Blame c++/vector/curvesarea.cpp

2fb9fd
2fb9fd
2fb9fd
#include "curvesarea.h"
2fb9fd
2fb9fd
2fb9fd
namespace {
2fb9fd
	struct DrawSegment {
2fb9fd
	private:
2fb9fd
		const Context &context;
2fb9fd
		const Segment &segment;
2fb9fd
		const Real width;
2fb9fd
		const Real precision_sqr;
2fb9fd
		const int max_level = 16;
2fb9fd
		int level;
2fb9fd
		Vector p0;
2fb9fd
		Real l0;
2fb9fd
2fb9fd
		Vector func(const Real &l)
2fb9fd
			{ return segment(l) + segment.t(l).perp().norm()*width; }
2fb9fd
2fb9fd
		void step(const Real &l1) {
2fb9fd
			Vector p1 = segment(l1) + segment.t(l1).perp().norm()*width;
2fb9fd
			if (++level < max_level)
2fb9fd
				while (greater((p1 - p0).lensqr(), precision_sqr))
2fb9fd
					step(l0 + 0.5*(l1 - l0));
2fb9fd
			--level;
2fb9fd
			context.line_to(p1);
2fb9fd
			p0 = p1; l0 = l1;
2fb9fd
		}
2fb9fd
2fb9fd
	public:
2fb9fd
		DrawSegment(const Context &context, const Segment &segment, const Real &width):
2fb9fd
			context(context), segment(segment), width(width), precision_sqr(context.pixelsize_sqr()), level(), l0()
2fb9fd
		{
2fb9fd
			context.line_to(p0 = func(0));
2fb9fd
			step(1);
2fb9fd
		}
2fb9fd
	};
2fb9fd
}
2fb9fd
2fb9fd
2fb9fd
CurvesArea::CurvesArea()
2fb9fd
{
2fb9fd
	set_size_request(500, 500);
2fb9fd
	
2fb9fd
	Vector center(250, 250);
2fb9fd
	const Real radius = 100;
2fb9fd
	const Real tangent_len = 50;
2fb9fd
	const int count = 5;
2fb9fd
	for(int i = 0; i < count; ++i) {
2fb9fd
		Real a = 2*pi*i/count;
2fb9fd
		Vector v = Vector::from_angle(a);
2fb9fd
		curve.push_back(CurvePoint(center + v*radius, v*tangent_len));
2fb9fd
		curve.back().add_to(*this);
2fb9fd
	}
2fb9fd
	curve.loop = true;
2fb9fd
}
2fb9fd
2fb9fd
void CurvesArea::put_segment(const Context &context, const Segment &segment, const Real width) {
2fb9fd
	if (equal(width, 0)) context.segment(segment);
2fb9fd
		            else DrawSegment(context, segment, width);
2fb9fd
}
2fb9fd
2fb9fd
void CurvesArea::put_curve(const Context &context, const Curve &curve, const Real width) {
2fb9fd
	for(Curve::const_iterator curr = curve.begin(); curr != curve.end(); ++curr) {
2fb9fd
		Curve::const_iterator next = curve.next(curr);
2fb9fd
		put_segment(context, Segment(curr->get_p(), next->get_p(), curr->get_t(), next->get_t()), width);
2fb9fd
	}
2fb9fd
}
2fb9fd
2fb9fd
void CurvesArea::draw_curve(const Context &context, const Curve &curve) {
2fb9fd
	context->save();
2fb9fd
	
2fb9fd
	Real width = 50;
2fb9fd
	context.set_line_width_px(1);
2fb9fd
2fb9fd
	// tangents
2fb9fd
	context.set_source_rgba(Color::gray());
2fb9fd
	for(Curve::const_iterator i = curve.begin(); i != curve.end(); ++i) {
2fb9fd
		context.move_to(i->p->position);
2fb9fd
		context.line_to(i->t->position);
2fb9fd
		context->stroke();
2fb9fd
	}
2fb9fd
2fb9fd
	// middle line
2fb9fd
	context.set_source_rgba(Color::black());
2fb9fd
	put_curve(context, curve);
2fb9fd
	context->stroke();
2fb9fd
	
2fb9fd
	// borders
2fb9fd
	context.set_source_rgba(Color::blue());
2fb9fd
	put_curve(context, curve, width);
2fb9fd
	context->stroke();
2fb9fd
	put_curve(context, curve, -width);
2fb9fd
	context->stroke();
2fb9fd
	
2fb9fd
	context->restore();
2fb9fd
}
2fb9fd
2fb9fd
2fb9fd
void CurvesArea::on_draw_content(const Context &context) {
2fb9fd
	draw_curve(context, curve);
2fb9fd
}