Blob Blame Raw


#include "random.h"

#include "curvearea.h"


CurveArea::CurveArea():
	hp0(new ActivePoint(Vector(100, 120), Color::white())),
	hp1(new ActivePoint(Vector(400, 420), Color::white())),
	ht0(new ActivePoint(Vector(400, 120), Color::yellow())),
	ht1(new ActivePoint(Vector(800, 420), Color::yellow())),
	bp0(new ActivePoint(Vector(600, 80), Color::white())),
	bp1(new ActivePoint(Vector(900, 380), Color::white())),
	bpp0(new ActivePoint(Vector(700, 80), Color::yellow())),
	bpp1(new ActivePoint(Vector(800, 380), Color::yellow())),
	cross(new ActivePoint(Vector(500, 250), Color::gray()))
{
	set_size_request(1000, 500);
	add_point(hp0);
	add_point(hp1);
	add_point(ht0);
	add_point(ht1);
	add_point(bp0);
	add_point(bp1);
	add_point(bpp0);
	add_point(bpp1);
	add_point(cross);
}

void CurveArea::on_point_move(const ActivePoint::Handle &point, const Vector &oldposition, const Vector &newposition) {
	if (point == hp0)
		ht0->position += newposition - oldposition;
	if (point == hp1)
		ht1->position += newposition - oldposition;
}

void CurveArea::put_rect(const Context &context, const Rect &rect) {
	context->move_to(rect.x0, rect.y0);
	context->line_to(rect.x1, rect.y0);
	context->line_to(rect.x1, rect.y1);
	context->line_to(rect.x0, rect.y1);
	context->close_path();
}

void CurveArea::put_hmark(const Context &context, const Vector &point) {
	context->move_to(point.x, point.y - 10);
	context->line_to(point.x, point.y + 10);
}

void CurveArea::put_vmark(const Context &context, const Vector &point) {
	context->move_to(point.x - 10, point.y);
	context->line_to(point.x + 10, point.y);
}

void CurveArea::put_hline(const Context &context, const Vector &point) {
	Real width = get_allocated_width();
	context->move_to(0, point.y);
	context->line_to(width, point.y);
	put_vmark(context, point);
}

void CurveArea::put_vline(const Context &context, const Vector &point) {
	Real height = get_allocated_height();
	context->move_to(point.x, 0);
	context->line_to(point.x, height);
	put_hmark(context, point);
}

void CurveArea::put_cross(const Context &context, const Vector &point) {
	put_hmark(context, point);
	put_vmark(context, point);
}

void CurveArea::on_draw_content(const Context &context) {
	Real roots[3];
	
	context->save();

	context.set_line_width_px(1);
	context.set_source_rgba(Color::gray().mulalpha(0.5));
	put_vline(context, cross->position);
	put_hline(context, cross->position);
	context->stroke();
	
	{
		context.set_line_width_px(1);
		Hermite h(
			hp0->position,
			hp1->position,
			ht0->position - hp0->position,
			ht1->position - hp1->position );
		
		context.set_source_rgba(Color::gray());
		context.move_to(hp0->position);
		context.line_to(ht0->position);
		context.move_to(hp1->position);
		context.line_to(ht1->position);
		context->stroke();

		context.set_source_rgba(Color::gray().mulalpha(0.25));
		put_rect(context, h.bounds_accurate());
		context->stroke();
		
		context.set_source_rgba(Color::gray().mulalpha(0.5));
		for(int i = h.bends_x(roots) - 1; i >= 0; --i)
			put_cross(context, h(roots[i]));
		for(int i = h.bends_y(roots) - 1; i >= 0; --i)
			put_cross(context, h(roots[i]));
		for(int i = h.intersections_x(roots, cross->position.x) - 1; i >= 0; --i)
			put_vmark(context, h(roots[i]));
		for(int i = h.intersections_y(roots, cross->position.y) - 1; i >= 0; --i)
			put_hmark(context, h(roots[i]));
		for(int i = h.inflection_x(roots) - 1; i >= 0; --i)
			put_cross(context, h(roots[i]));
		for(int i = h.inflection_y(roots) - 1; i >= 0; --i)
			put_cross(context, h(roots[i]));
		context->stroke();
		
		context.set_source_rgba(Color::blue().withalpha(0.5));
		context.hermite(h);
		context->stroke();

		context.set_line_width_px(3);
		Bezier bb = h.sub(rnd::real(), rnd::real()).get_bezier();
		context.set_source_rgba(Color::blue());
		context.bezier(bb);
		context->stroke();
	}
	
	{
		context.set_line_width_px(1);
		Bezier b(
			bp0->position,
			bp1->position,
			bpp0->position,
			bpp1->position );
		
		context.set_source_rgba(Color::gray());
		context.move_to(bp0->position);
		context.line_to(bpp0->position);
		context.line_to(bpp1->position);
		context.line_to(bp1->position);
		context->stroke();
		
		context.set_source_rgba(Color::gray().mulalpha(0.25));
		put_rect(context, b.bounds_accurate());
		context->stroke();
		
		context.set_source_rgba(Color::gray().mulalpha(0.5));
		for(int i = b.bends_x(roots) - 1; i >= 0; --i)
			put_cross(context, b(roots[i]));
		for(int i = b.bends_y(roots) - 1; i >= 0; --i)
			put_cross(context, b(roots[i]));
		for(int i = b.intersections_x(roots, cross->position.x) - 1; i >= 0; --i)
			put_vmark(context, b(roots[i]));
		for(int i = b.intersections_y(roots, cross->position.y) - 1; i >= 0; --i)
			put_hmark(context, b(roots[i]));
		for(int i = b.inflection_x(roots) - 1; i >= 0; --i)
			put_cross(context, b(roots[i]));
		for(int i = b.inflection_y(roots) - 1; i >= 0; --i)
			put_cross(context, b(roots[i]));
		context->stroke();
		
		context.set_source_rgba(Color::blue().mulalpha(0.5));
		context.bezier(b);
		context->stroke();

		context.set_line_width_px(3);
		Hermite hh = b.sub(rnd::real(), rnd::real()).get_hermite();
		context.set_source_rgba(Color::blue());
		context.hermite(hh);
		context->stroke();
	}
	
	context->restore();
}