agg/src/ctrl/agg_bezier_ctrl.cpp

371 lines
11 KiB
C++

//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// classes bezier_ctrl_impl, bezier_ctrl
//
//----------------------------------------------------------------------------
#include <string.h>
#include <stdio.h>
#include "ctrl/agg_bezier_ctrl.h"
namespace agg
{
//------------------------------------------------------------------------
bezier_ctrl_impl::bezier_ctrl_impl() :
ctrl(0,0,1,1,false),
m_stroke(m_curve),
m_poly(4, 5.0),
m_idx(0)
{
m_poly.in_polygon_check(false);
m_poly.xn(0) = 100.0;
m_poly.yn(0) = 0.0;
m_poly.xn(1) = 100.0;
m_poly.yn(1) = 50.0;
m_poly.xn(2) = 50.0;
m_poly.yn(2) = 100.0;
m_poly.xn(3) = 0.0;
m_poly.yn(3) = 100.0;
}
//------------------------------------------------------------------------
void bezier_ctrl_impl::curve(double x1, double y1,
double x2, double y2,
double x3, double y3,
double x4, double y4)
{
m_poly.xn(0) = x1;
m_poly.yn(0) = y1;
m_poly.xn(1) = x2;
m_poly.yn(1) = y2;
m_poly.xn(2) = x3;
m_poly.yn(2) = y3;
m_poly.xn(3) = x4;
m_poly.yn(3) = y4;
curve();
}
//------------------------------------------------------------------------
curve4& bezier_ctrl_impl::curve()
{
m_curve.init(m_poly.xn(0), m_poly.yn(0),
m_poly.xn(1), m_poly.yn(1),
m_poly.xn(2), m_poly.yn(2),
m_poly.xn(3), m_poly.yn(3));
return m_curve;
}
//------------------------------------------------------------------------
void bezier_ctrl_impl::rewind(unsigned idx)
{
m_idx = idx;
m_curve.approximation_scale(scale());
switch(idx)
{
default:
case 0: // Control line 1
m_curve.init(m_poly.xn(0), m_poly.yn(0),
(m_poly.xn(0) + m_poly.xn(1)) * 0.5,
(m_poly.yn(0) + m_poly.yn(1)) * 0.5,
(m_poly.xn(0) + m_poly.xn(1)) * 0.5,
(m_poly.yn(0) + m_poly.yn(1)) * 0.5,
m_poly.xn(1), m_poly.yn(1));
m_stroke.rewind(0);
break;
case 1: // Control line 2
m_curve.init(m_poly.xn(2), m_poly.yn(2),
(m_poly.xn(2) + m_poly.xn(3)) * 0.5,
(m_poly.yn(2) + m_poly.yn(3)) * 0.5,
(m_poly.xn(2) + m_poly.xn(3)) * 0.5,
(m_poly.yn(2) + m_poly.yn(3)) * 0.5,
m_poly.xn(3), m_poly.yn(3));
m_stroke.rewind(0);
break;
case 2: // Curve itself
m_curve.init(m_poly.xn(0), m_poly.yn(0),
m_poly.xn(1), m_poly.yn(1),
m_poly.xn(2), m_poly.yn(2),
m_poly.xn(3), m_poly.yn(3));
m_stroke.rewind(0);
break;
case 3: // Point 1
m_ellipse.init(m_poly.xn(0), m_poly.yn(0), point_radius(), point_radius(), 20);
m_ellipse.rewind(0);
break;
case 4: // Point 2
m_ellipse.init(m_poly.xn(1), m_poly.yn(1), point_radius(), point_radius(), 20);
m_ellipse.rewind(0);
break;
case 5: // Point 3
m_ellipse.init(m_poly.xn(2), m_poly.yn(2), point_radius(), point_radius(), 20);
m_ellipse.rewind(0);
break;
case 6: // Point 4
m_ellipse.init(m_poly.xn(3), m_poly.yn(3), point_radius(), point_radius(), 20);
m_ellipse.rewind(0);
break;
}
}
//------------------------------------------------------------------------
unsigned bezier_ctrl_impl::vertex(double* x, double* y)
{
unsigned cmd = path_cmd_stop;
switch(m_idx)
{
case 0:
case 1:
case 2:
cmd = m_stroke.vertex(x, y);
break;
case 3:
case 4:
case 5:
case 6:
case 7:
cmd = m_ellipse.vertex(x, y);
break;
}
if(!is_stop(cmd))
{
transform_xy(x, y);
}
return cmd;
}
//------------------------------------------------------------------------
bool bezier_ctrl_impl::in_rect(double, double) const
{
return false;
}
//------------------------------------------------------------------------
bool bezier_ctrl_impl::on_mouse_button_down(double x, double y)
{
inverse_transform_xy(&x, &y);
return m_poly.on_mouse_button_down(x, y);
}
//------------------------------------------------------------------------
bool bezier_ctrl_impl::on_mouse_move(double x, double y, bool button_flag)
{
inverse_transform_xy(&x, &y);
return m_poly.on_mouse_move(x, y, button_flag);
}
//------------------------------------------------------------------------
bool bezier_ctrl_impl::on_mouse_button_up(double x, double y)
{
return m_poly.on_mouse_button_up(x, y);
}
//------------------------------------------------------------------------
bool bezier_ctrl_impl::on_arrow_keys(bool left, bool right, bool down, bool up)
{
return m_poly.on_arrow_keys(left, right, down, up);
}
//------------------------------------------------------------------------
curve3_ctrl_impl::curve3_ctrl_impl() :
ctrl(0,0,1,1,false),
m_stroke(m_curve),
m_poly(3, 5.0),
m_idx(0)
{
m_poly.in_polygon_check(false);
m_poly.xn(0) = 100.0;
m_poly.yn(0) = 0.0;
m_poly.xn(1) = 100.0;
m_poly.yn(1) = 50.0;
m_poly.xn(2) = 50.0;
m_poly.yn(2) = 100.0;
}
//------------------------------------------------------------------------
void curve3_ctrl_impl::curve(double x1, double y1,
double x2, double y2,
double x3, double y3)
{
m_poly.xn(0) = x1;
m_poly.yn(0) = y1;
m_poly.xn(1) = x2;
m_poly.yn(1) = y2;
m_poly.xn(2) = x3;
m_poly.yn(2) = y3;
curve();
}
//------------------------------------------------------------------------
curve3& curve3_ctrl_impl::curve()
{
m_curve.init(m_poly.xn(0), m_poly.yn(0),
m_poly.xn(1), m_poly.yn(1),
m_poly.xn(2), m_poly.yn(2));
return m_curve;
}
//------------------------------------------------------------------------
void curve3_ctrl_impl::rewind(unsigned idx)
{
m_idx = idx;
switch(idx)
{
default:
case 0: // Control line
m_curve.init(m_poly.xn(0), m_poly.yn(0),
(m_poly.xn(0) + m_poly.xn(1)) * 0.5,
(m_poly.yn(0) + m_poly.yn(1)) * 0.5,
m_poly.xn(1), m_poly.yn(1));
m_stroke.rewind(0);
break;
case 1: // Control line 2
m_curve.init(m_poly.xn(1), m_poly.yn(1),
(m_poly.xn(1) + m_poly.xn(2)) * 0.5,
(m_poly.yn(1) + m_poly.yn(2)) * 0.5,
m_poly.xn(2), m_poly.yn(2));
m_stroke.rewind(0);
break;
case 2: // Curve itself
m_curve.init(m_poly.xn(0), m_poly.yn(0),
m_poly.xn(1), m_poly.yn(1),
m_poly.xn(2), m_poly.yn(2));
m_stroke.rewind(0);
break;
case 3: // Point 1
m_ellipse.init(m_poly.xn(0), m_poly.yn(0), point_radius(), point_radius(), 20);
m_ellipse.rewind(0);
break;
case 4: // Point 2
m_ellipse.init(m_poly.xn(1), m_poly.yn(1), point_radius(), point_radius(), 20);
m_ellipse.rewind(0);
break;
case 5: // Point 3
m_ellipse.init(m_poly.xn(2), m_poly.yn(2), point_radius(), point_radius(), 20);
m_ellipse.rewind(0);
break;
}
}
//------------------------------------------------------------------------
unsigned curve3_ctrl_impl::vertex(double* x, double* y)
{
unsigned cmd = path_cmd_stop;
switch(m_idx)
{
case 0:
case 1:
case 2:
cmd = m_stroke.vertex(x, y);
break;
case 3:
case 4:
case 5:
case 6:
cmd = m_ellipse.vertex(x, y);
break;
}
if(!is_stop(cmd))
{
transform_xy(x, y);
}
return cmd;
}
//------------------------------------------------------------------------
bool curve3_ctrl_impl::in_rect(double, double) const
{
return false;
}
//------------------------------------------------------------------------
bool curve3_ctrl_impl::on_mouse_button_down(double x, double y)
{
inverse_transform_xy(&x, &y);
return m_poly.on_mouse_button_down(x, y);
}
//------------------------------------------------------------------------
bool curve3_ctrl_impl::on_mouse_move(double x, double y, bool button_flag)
{
inverse_transform_xy(&x, &y);
return m_poly.on_mouse_move(x, y, button_flag);
}
//------------------------------------------------------------------------
bool curve3_ctrl_impl::on_mouse_button_up(double x, double y)
{
return m_poly.on_mouse_button_up(x, y);
}
//------------------------------------------------------------------------
bool curve3_ctrl_impl::on_arrow_keys(bool left, bool right, bool down, bool up)
{
return m_poly.on_arrow_keys(left, right, down, up);
}
}