#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();
}