Blame c++/vector/activecurve.h

145120
#ifndef ACTIVECURVE_H
145120
#define ACTIVECURVE_H
145120
145120
145120
#include <vector></vector>
145120
145120
#include "curve.h"
145120
#include "activearea.h"
145120
145120
class ActiveCurvePoint {
145120
public:
145120
	ActivePoint::Handle p, t0, t1;
145120
	
145120
	ActiveCurvePoint(const Vector &p, const Vector &t0, const Vector &t1):
145120
		p(new ActivePoint(p)),
145120
		t0(new ActivePoint(p + t0, Color::yellow())),
145120
		t1(new ActivePoint(p + t1, Color::yellow()))
145120
		{ }
145120
	explicit ActiveCurvePoint(const Vector &p = Vector(), const Vector &t = Vector()):
145120
		ActiveCurvePoint(p, t, t) { }
145120
145120
	const Vector& get_p() const { return p->position; }
145120
	Vector get_t0() const { return t0->position - get_p(); }
145120
	Vector get_t1() const { return t1->position - get_p(); }
145120
	Vector get_pp0() const { return get_t0()/3 + get_p(); }
145120
	Vector get_pp1() const { return get_t1()/3 + get_p(); }
145120
	
145120
	void add_to(ActiveArea &area) const {
145120
		area.add_point(p);
145120
		area.add_point(t0);
145120
		area.add_point(t1);
145120
	}
145120
	void remove_from(ActiveArea &area) const {
145120
		area.remove_point(p);
145120
		area.remove_point(t0);
145120
		area.remove_point(t1);
145120
	}
145120
};
145120
145120
class ActiveCurve: public std::vector<activecurvepoint> {</activecurvepoint>
145120
public:
145120
	template<typename t=""></typename>
145120
	class SegIterBase {
145120
	public:
145120
		typedef T Type;
145120
	private:
145120
		Type begin, end, last, i0, i1;
145120
		bool loop, valid;
145120
	protected:
145120
		SegIterBase():
145120
			begin(), end(), i0(), i1(), loop(), valid() { }
145120
		SegIterBase(const Type &begin, const Type &end, bool loop):
145120
			begin(begin), end(end), last(end), i0(begin), i1(begin), loop(loop), valid(true)
145120
		{
145120
			--last; ++i1;
145120
			if (i0 == end) i1 = end;
145120
			if (loop && i1 == end) i1 = begin;
145120
		}
145120
	public:
145120
		operator bool () const
145120
			{ return valid && i0 != end && i1 != end; }
145120
		bool is_first() const
145120
			{ assert(*this); return i0 == begin; }
145120
		bool is_last() const
145120
			{ assert(*this); return i1 == (loop ? begin : last); }
145120
	
145120
		bool next() {
145120
			assert(*this);
145120
			++i0; ++i1;
145120
			if (loop && i1 == end) i1 = begin;
145120
			return *this;
145120
		}
145120
		
145120
		const ActiveCurvePoint& point0() const { assert(*this); return *i0; }
145120
		const ActiveCurvePoint& point1() const { assert(*this); return *i1; }
145120
		const Vector& p0() const { return point0().get_p(); }
145120
		const Vector& p1() const { return point1().get_p(); }
145120
	};
145120
145120
	class SegIter: public SegIterBase<const_iterator> {</const_iterator>
145120
	public:
145120
		SegIter() { }
145120
		explicit SegIter(const ActiveCurve &curve):
145120
			SegIterBase(curve.begin(), curve.end(), curve.loop) { }
145120
		Vector t0()  const { return point0().get_t1(); }
145120
		Vector t1()  const { return point1().get_t0(); }
145120
		Vector pp0() const { return point0().get_pp1(); }
145120
		Vector pp1() const { return point1().get_pp0(); }
145120
		Hermite hermite() const { return Hermite(p0(), p1(), t0(), -t1()); }
145120
		Bezier  bezier()  const { return Bezier (p0(), p1(), pp0(), pp1()); }
145120
	};
145120
145120
	class SegRIter: public SegIterBase<const_reverse_iterator> {</const_reverse_iterator>
145120
	public:
145120
		SegRIter() { }
145120
		explicit SegRIter(const ActiveCurve &curve):
145120
			SegIterBase(curve.rbegin(), curve.rend(), curve.loop) { }
145120
		Vector t0()  const { return point0().get_t0(); }
145120
		Vector t1()  const { return point1().get_t1(); }
145120
		Vector pp0() const { return point0().get_pp0(); }
145120
		Vector pp1() const { return point1().get_pp1(); }
145120
		Hermite hermite() const { return Hermite(p0(), p1(), t0(), -t1()); }
145120
		Bezier  bezier()  const { return Bezier (p0(), p1(), pp0(), pp1()); }
145120
	};
145120
145120
	bool loop;
145120
	Color color;
145120
	Color tangent_color;
145120
	
145120
	ActiveCurve(): loop(), color(Color::black()), tangent_color(Color::gray()) { }
145120
	
145120
	void set_tail_tangents_visible(bool x)
145120
		{ if (!empty()) front().t0->visible = back().t1->visible = x; }
145120
	void set_tail_tangents_visible()
145120
		{ set_tail_tangents_visible(loop); }
145120
	
145120
	void put(const Context &context, bool jump = false) const {
145120
		for(SegIter i(*this); i; i.next())
145120
			context.hermite( i.hermite(), jump && i.is_first() );
145120
		if (loop && jump) context->close_path();
145120
	}
145120
145120
	void put_tangents(const Context &context) const {
145120
		for(SegIter i(*this); i; i.next()) {
145120
			context.move_to(i.p0());
145120
			context.line_to(i.p0() + i.t0());
145120
			context.move_to(i.p1());
145120
			context.line_to(i.p1() + i.t1());
145120
		}
145120
	}
145120
	
145120
	void on_point_move(const ActivePoint::Handle &point, const Vector &oldposition, const Vector &/*newposition*/) {
145120
		for(const_iterator i = begin(); i != end(); ++i) {
145120
			if (i->p == point) {
145120
				Vector d = i->p->position - oldposition;
145120
				i->t0->position += d;
145120
				i->t1->position += d;
145120
				break;
145120
			}
145120
		}
145120
	}
145120
145120
	void draw(const Context &context) const {
145120
		context->save();
145120
		
145120
		context.set_line_width_px(1);
145120
		
145120
		context.set_source_rgba(color);
145120
		put_tangents(context);
145120
		context->stroke();
145120
145120
		context.set_source_rgba(tangent_color);
145120
		put(context, true);
145120
		context->stroke();
145120
		
145120
		context->restore();
145120
	}
145120
};
145120
145120
145120
#endif