mirror of https://github.com/KLayout/klayout.git
WIP: angle measurement ruler, radius measurement one. Needs improvement
This commit is contained in:
parent
d2d321c35b
commit
8415e075ad
|
|
@ -574,6 +574,16 @@
|
|||
<string>Ellipse</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Angle measurement</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Radius measurement</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
|
|
|
|||
|
|
@ -352,6 +352,16 @@
|
|||
<string>Ellipse</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Angle measurement</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Radius measurement</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="2" colspan="2">
|
||||
|
|
|
|||
|
|
@ -136,6 +136,10 @@ OutlineConverter::to_string (ant::Object::outline_type o)
|
|||
return "box";
|
||||
} else if (o == ant::Object::OL_ellipse) {
|
||||
return "ellipse";
|
||||
} else if (o == ant::Object::OL_radius) {
|
||||
return "radius";
|
||||
} else if (o == ant::Object::OL_angle) {
|
||||
return "angle";
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
|
|
@ -159,6 +163,10 @@ OutlineConverter::from_string (const std::string &s, ant::Object::outline_type &
|
|||
o = ant::Object::OL_box;
|
||||
} else if (t == "ellipse") {
|
||||
o = ant::Object::OL_ellipse;
|
||||
} else if (t == "radius") {
|
||||
o = ant::Object::OL_radius;
|
||||
} else if (t == "angle") {
|
||||
o = ant::Object::OL_angle;
|
||||
} else {
|
||||
o = ant::Object::OL_diag;
|
||||
}
|
||||
|
|
@ -241,7 +249,7 @@ RulerModeConverter::to_string (ant::Template::ruler_mode_type m)
|
|||
return "auto_metric";
|
||||
} else if (m == ant::Template::RulerMultiSegment) {
|
||||
return "multi_segment";
|
||||
} else if (m == ant::Template::RulerAngle) {
|
||||
} else if (m == ant::Template::RulerThreeClicks) {
|
||||
return "angle";
|
||||
} else {
|
||||
return "normal";
|
||||
|
|
@ -261,7 +269,7 @@ RulerModeConverter::from_string (const std::string &s, ant::Template::ruler_mode
|
|||
} else if (t == "multi_segment") {
|
||||
a = ant::Template::RulerMultiSegment;
|
||||
} else if (t == "angle") {
|
||||
a = ant::Template::RulerAngle;
|
||||
a = ant::Template::RulerThreeClicks;
|
||||
} else {
|
||||
a = ant::Template::RulerNormal;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,8 +77,10 @@ public:
|
|||
* OL_diag_yx: both OL_diag and OL_yx
|
||||
* OL_box: draw a box defined by start and end point
|
||||
* OL_ellipse: draws an ellipse with p1 and p2 defining the extension (style is ignored)
|
||||
* OL_angle: an angle measurement ruler (first vs. last segment)
|
||||
* OL_radius: a radius measurement ruler
|
||||
*/
|
||||
enum outline_type { OL_diag = 0, OL_xy = 1, OL_diag_xy = 2, OL_yx = 3, OL_diag_yx = 4, OL_box = 5, OL_ellipse = 6 };
|
||||
enum outline_type { OL_diag = 0, OL_xy = 1, OL_diag_xy = 2, OL_yx = 3, OL_diag_yx = 4, OL_box = 5, OL_ellipse = 6, OL_angle = 7, OL_radius = 8 };
|
||||
|
||||
/**
|
||||
* @brief The position type of the main label
|
||||
|
|
|
|||
|
|
@ -77,8 +77,11 @@ static std::vector<ant::Template> make_standard_templates ()
|
|||
templates.push_back (ant::Template (tl::to_string (tr ("Measure")), "$X", "$Y", "$D", ant::Object::STY_ruler, ant::Object::OL_diag, true, lay::AC_Global, "_measure"));
|
||||
templates.back ().set_mode (ant::Template::RulerAutoMetric);
|
||||
|
||||
templates.push_back (ant::Template (tl::to_string (tr ("Angle")), "$X", "$Y", "$D", ant::Object::STY_line, ant::Object::OL_diag, true, lay::AC_Global, "_angle"));
|
||||
templates.back ().set_mode (ant::Template::RulerAngle);
|
||||
templates.push_back (ant::Template (tl::to_string (tr ("Angle")), "$X", "$Y", "$D", ant::Object::STY_line, ant::Object::OL_angle, true, lay::AC_Global, "_angle"));
|
||||
templates.back ().set_mode (ant::Template::RulerThreeClicks);
|
||||
|
||||
templates.push_back (ant::Template (tl::to_string (tr ("Radius")), "$X", "$Y", "$D", ant::Object::STY_line, ant::Object::OL_radius, true, lay::AC_Global, "_radius"));
|
||||
templates.back ().set_mode (ant::Template::RulerThreeClicks);
|
||||
|
||||
templates.push_back (ant::Template (tl::to_string (tr ("Ellipse")), "W=$(abs(X))", "H=$(abs(Y))", "", ant::Object::STY_line, ant::Object::OL_ellipse, true, lay::AC_Global, std::string ()));
|
||||
|
||||
|
|
|
|||
|
|
@ -503,9 +503,12 @@ draw_text (const db::DPoint &q1,
|
|||
*
|
||||
* @param q1 The first point in pixel space
|
||||
* @param q2 The second point in pixel space
|
||||
* @param length_u The "typical dimension" - used to simplify for very small ellipses
|
||||
* @param sel True to draw ruler in "selected" mode
|
||||
* @param bitmap The bitmap to draw the ruler on
|
||||
* @param renderer The renderer object
|
||||
* @param start_angle The starting angle (in radians)
|
||||
* @param stop_angle The stop angle (in radians)
|
||||
*/
|
||||
void
|
||||
draw_ellipse (const db::DPoint &q1,
|
||||
|
|
@ -513,7 +516,9 @@ draw_ellipse (const db::DPoint &q1,
|
|||
double length_u,
|
||||
bool sel,
|
||||
lay::CanvasPlane *bitmap,
|
||||
lay::Renderer &renderer)
|
||||
lay::Renderer &renderer,
|
||||
double start_angle = 0.0,
|
||||
double stop_angle = 2.0 * M_PI)
|
||||
{
|
||||
double sel_width = 2 / renderer.resolution ();
|
||||
|
||||
|
|
@ -532,7 +537,7 @@ draw_ellipse (const db::DPoint &q1,
|
|||
|
||||
} else {
|
||||
|
||||
int npoints = 200;
|
||||
int npoints = int (floor (200 * abs (stop_angle - start_angle) / (2.0 * M_PI)));
|
||||
|
||||
// produce polygon stuff
|
||||
|
||||
|
|
@ -540,43 +545,29 @@ draw_ellipse (const db::DPoint &q1,
|
|||
double ry = fabs ((q2 - q1).y () * 0.5);
|
||||
db::DPoint c = q1 + (q2 - q1) * 0.5;
|
||||
|
||||
db::DPolygon p;
|
||||
|
||||
std::vector<db::DPoint> pts;
|
||||
pts.reserve (npoints);
|
||||
|
||||
if (sel) {
|
||||
rx += sel_width * 0.5;
|
||||
ry += sel_width * 0.5;
|
||||
}
|
||||
|
||||
double da = M_PI * 2.0 / double (npoints);
|
||||
for (int i = 0; i < npoints; ++i) {
|
||||
double a = da * i;
|
||||
std::vector<db::DPoint> pts;
|
||||
pts.reserve (npoints + 1);
|
||||
|
||||
double da = fabs (stop_angle - start_angle) / double (npoints);
|
||||
for (int i = 0; i < npoints + 1; ++i) {
|
||||
double a = da * i + start_angle;
|
||||
pts.push_back (c + db::DVector (rx * cos (a), ry * sin (a)));
|
||||
}
|
||||
|
||||
p.assign_hull (pts.begin (), pts.end ());
|
||||
|
||||
if (sel) {
|
||||
|
||||
pts.clear ();
|
||||
|
||||
rx -= sel_width;
|
||||
ry -= sel_width;
|
||||
for (int i = 0; i < npoints; ++i) {
|
||||
double a = da * i;
|
||||
pts.push_back (c + db::DVector (rx * cos (a), ry * sin (a)));
|
||||
}
|
||||
|
||||
p.insert_hole (pts.begin (), pts.end ());
|
||||
|
||||
db::DPath p (pts.begin (), pts.end (), sel_width);
|
||||
renderer.draw (p, bitmap, bitmap, 0, 0);
|
||||
|
||||
} else {
|
||||
|
||||
for (db::DPolygon::polygon_edge_iterator e = p.begin_edge (); ! e.at_end (); ++e) {
|
||||
renderer.draw (*e, 0, bitmap, 0, 0);
|
||||
for (size_t i = 0; i + 1 < pts.size (); ++i) {
|
||||
renderer.draw (db::DEdge (pts [i], pts [i + 1]), 0, bitmap, 0, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -639,52 +630,236 @@ draw_ruler_segment (const ant::Object &ruler, size_t index, const db::DCplxTrans
|
|||
draw_text (db::DPoint (q1.x (), q2.y ()), q2, lu, ruler.text_x (index, trans.fp_trans ()), r, ruler.style (), ant::Object::POS_center, ruler.xlabel_xalign (), ruler.xlabel_yalign (), bitmap, renderer);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (ruler.outline () == Object::OL_box) {
|
||||
void
|
||||
draw_ruler_box (const ant::Object &ruler, const db::DCplxTrans &trans, bool sel, lay::CanvasPlane *bitmap, lay::Renderer &renderer)
|
||||
{
|
||||
db::DPoint p1 = ruler.p1 (), p2 = ruler.p2 ();
|
||||
|
||||
bool r = (q2.x () > q1.x ()) ^ (q2.y () < q1.y ());
|
||||
// round the starting point, shift both, and round the end point
|
||||
std::pair <db::DPoint, db::DPoint> v = lay::snap (trans * p1, trans * p2);
|
||||
db::DPoint q1 = v.first;
|
||||
db::DPoint q2 = v.second;
|
||||
|
||||
draw_ruler (q1, db::DPoint (q2.x (), q1.y ()), lu, mu, sel, r, ruler.style (), bitmap, renderer, true, true);
|
||||
draw_text (q1, db::DPoint (q2.x (), q1.y ()), lu, ruler.text_x (index, trans.fp_trans ()), r, ruler.style (), ant::Object::POS_center, ruler.xlabel_xalign (), ruler.xlabel_yalign (), bitmap, renderer);
|
||||
draw_ruler (db::DPoint (q2.x (), q1.y ()), q2, lu, mu, sel, r, ruler.style (), bitmap, renderer, true, true);
|
||||
draw_text (db::DPoint (q2.x (), q1.y ()), q2, lu, ruler.text_y (index, trans.fp_trans ()), r, ruler.style (), ant::Object::POS_center, ruler.ylabel_xalign (), ruler.ylabel_yalign (), bitmap, renderer);
|
||||
draw_ruler (q1, db::DPoint (q1.x (), q2.y ()), lu, mu, sel, !r, ruler.style (), bitmap, renderer, true, true);
|
||||
draw_ruler (db::DPoint (q1.x (), q2.y ()), q2, lu, mu, sel, !r, ruler.style (), bitmap, renderer, true, true);
|
||||
draw_text (q1, q2, lu, ruler.text (index), !r, ant::Object::STY_none, ruler.main_position (), ruler.main_xalign (), ruler.main_yalign (), bitmap, renderer);
|
||||
double lu = p1.double_distance (p2);
|
||||
int min_tick_spc = int (0.5 + 20 / renderer.resolution ()); // min tick spacing in canvas units
|
||||
double mu = double (min_tick_spc) / trans.ctrans (1.0);
|
||||
|
||||
} else if (ruler.outline () == Object::OL_ellipse) {
|
||||
bool r = (q2.x () > q1.x ()) ^ (q2.y () < q1.y ());
|
||||
|
||||
bool r = (q2.x () > q1.x ()) ^ (q2.y () < q1.y ());
|
||||
size_t index = std::numeric_limits<size_t>::max ();
|
||||
draw_ruler (q1, db::DPoint (q2.x (), q1.y ()), lu, mu, sel, r, ruler.style (), bitmap, renderer, true, true);
|
||||
draw_text (q1, db::DPoint (q2.x (), q1.y ()), lu, ruler.text_x (index, trans.fp_trans ()), r, ruler.style (), ant::Object::POS_center, ruler.xlabel_xalign (), ruler.xlabel_yalign (), bitmap, renderer);
|
||||
draw_ruler (db::DPoint (q2.x (), q1.y ()), q2, lu, mu, sel, r, ruler.style (), bitmap, renderer, true, true);
|
||||
draw_text (db::DPoint (q2.x (), q1.y ()), q2, lu, ruler.text_y (index, trans.fp_trans ()), r, ruler.style (), ant::Object::POS_center, ruler.ylabel_xalign (), ruler.ylabel_yalign (), bitmap, renderer);
|
||||
draw_ruler (q1, db::DPoint (q1.x (), q2.y ()), lu, mu, sel, !r, ruler.style (), bitmap, renderer, true, true);
|
||||
draw_ruler (db::DPoint (q1.x (), q2.y ()), q2, lu, mu, sel, !r, ruler.style (), bitmap, renderer, true, true);
|
||||
draw_text (q1, q2, lu, ruler.text (index), !r, ant::Object::STY_none, ruler.main_position (), ruler.main_xalign (), ruler.main_yalign (), bitmap, renderer);
|
||||
}
|
||||
|
||||
draw_text (q1, db::DPoint (q2.x (), q1.y ()), lu, ruler.text_x (index, trans.fp_trans ()), r, ant::Object::STY_none, ant::Object::POS_center, ruler.xlabel_xalign (), ruler.xlabel_yalign (), bitmap, renderer);
|
||||
draw_text (db::DPoint (q2.x (), q1.y ()), q2, lu, ruler.text_y (index, trans.fp_trans ()), r, ant::Object::STY_none, ant::Object::POS_center, ruler.ylabel_xalign (), ruler.ylabel_yalign (), bitmap, renderer);
|
||||
draw_text (q1, q2, lu, ruler.text (index), !r, ant::Object::STY_none, ruler.main_position (), ruler.main_xalign (), ruler.main_yalign (), bitmap, renderer);
|
||||
void
|
||||
draw_ruler_ellipse (const ant::Object &ruler, const db::DCplxTrans &trans, bool sel, lay::CanvasPlane *bitmap, lay::Renderer &renderer)
|
||||
{
|
||||
db::DPoint p1 = ruler.p1 (), p2 = ruler.p2 ();
|
||||
|
||||
draw_ellipse (q1, q2, lu, sel, bitmap, renderer);
|
||||
// round the starting point, shift both, and round the end point
|
||||
std::pair <db::DPoint, db::DPoint> v = lay::snap (trans * p1, trans * p2);
|
||||
db::DPoint q1 = v.first;
|
||||
db::DPoint q2 = v.second;
|
||||
|
||||
double lu = p1.double_distance (p2);
|
||||
|
||||
bool r = (q2.x () > q1.x ()) ^ (q2.y () < q1.y ());
|
||||
|
||||
size_t index = std::numeric_limits<size_t>::max ();
|
||||
draw_text (q1, db::DPoint (q2.x (), q1.y ()), lu, ruler.text_x (index, trans.fp_trans ()), r, ant::Object::STY_none, ant::Object::POS_center, ruler.xlabel_xalign (), ruler.xlabel_yalign (), bitmap, renderer);
|
||||
draw_text (db::DPoint (q2.x (), q1.y ()), q2, lu, ruler.text_y (index, trans.fp_trans ()), r, ant::Object::STY_none, ant::Object::POS_center, ruler.ylabel_xalign (), ruler.ylabel_yalign (), bitmap, renderer);
|
||||
draw_text (q1, q2, lu, ruler.text (index), !r, ant::Object::STY_none, ruler.main_position (), ruler.main_xalign (), ruler.main_yalign (), bitmap, renderer);
|
||||
|
||||
draw_ellipse (q1, q2, lu, sel, bitmap, renderer);
|
||||
}
|
||||
|
||||
bool
|
||||
compute_interpolating_circle (const ant::Object::point_list &points, double &radius, db::DPoint ¢er, double &start_angle, double &stop_angle)
|
||||
{
|
||||
if (points.size () < 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
double d = points.back ().distance (points.front ()) * 0.5;
|
||||
if (d < db::epsilon) {
|
||||
return false;
|
||||
}
|
||||
|
||||
db::DVector n = points.back () - points.front ();
|
||||
db::DPoint m = points.front () + n * 0.5;
|
||||
n = db::DVector (n.y (), -n.x ()) * (1.0 / d);
|
||||
|
||||
double nom = 0.0;
|
||||
double div = 0.0;
|
||||
|
||||
for (size_t i = 1; i + 1 < points.size (); ++i) {
|
||||
db::DVector p = points [i] - m;
|
||||
double pn = db::sprod (p, n);
|
||||
div += pn * pn;
|
||||
nom += pn * (p.sq_double_length () - d * d);
|
||||
}
|
||||
|
||||
if (div < db::epsilon) {
|
||||
return false;
|
||||
}
|
||||
|
||||
double l = 0.5 * nom / div;
|
||||
radius = sqrt (l * l + d * d);
|
||||
center = m + n * l;
|
||||
|
||||
double a = atan2 (-n.y (), -n.x ());
|
||||
double da = atan2 (d, l);
|
||||
|
||||
if (fabs (l) < db::epsilon) {
|
||||
|
||||
start_angle = 0.0;
|
||||
stop_angle = M_PI * 2.0;
|
||||
|
||||
} else if (l < 0.0) {
|
||||
|
||||
start_angle = a + da;
|
||||
stop_angle = start_angle + 2.0 * (M_PI - da);
|
||||
|
||||
} else {
|
||||
|
||||
start_angle = a - da;
|
||||
stop_angle = a + da;
|
||||
|
||||
}
|
||||
|
||||
while (stop_angle < start_angle - db::epsilon) {
|
||||
stop_angle += M_PI * 2.0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
draw_ruler_radius (const ant::Object &ruler, const db::DCplxTrans &trans, bool sel, lay::CanvasPlane *bitmap, lay::Renderer &renderer)
|
||||
{
|
||||
// draw crosses for the support points
|
||||
for (auto p = ruler.points ().begin (); p != ruler.points ().end (); ++p) {
|
||||
ant::Object supp (*p, *p, 0, std::string (), std::string (), std::string (), ant::Object::STY_cross_start, ant::Object::OL_diag, false, lay::AC_Global);
|
||||
draw_ruler_segment (supp, 0, trans, sel, bitmap, renderer);
|
||||
}
|
||||
|
||||
double radius = 0.0;
|
||||
double start_angle = 0.0, stop_angle = 0.0;
|
||||
db::DPoint center;
|
||||
|
||||
// circle interpolation
|
||||
if (compute_interpolating_circle (ruler.points (), radius, center, start_angle, stop_angle)) {
|
||||
|
||||
// draw circle segment
|
||||
db::DVector rr (radius, radius);
|
||||
std::pair <db::DPoint, db::DPoint> v = lay::snap (trans * (center - rr), trans * (center + rr));
|
||||
draw_ellipse (v.first, v.second, radius * 2.0, sel, bitmap, renderer, start_angle, stop_angle);
|
||||
|
||||
double a = 0.5 * (start_angle + stop_angle);
|
||||
db::DPoint rc = center + db::DVector (cos (a), sin (a)) * radius;
|
||||
|
||||
// draw a center marker
|
||||
ant::Object center_loc (center, center, 0, std::string (), ruler.fmt_x (), ruler.fmt_y (), ant::Object::STY_cross_start, ant::Object::OL_diag, false, lay::AC_Global);
|
||||
draw_ruler_segment (center_loc, 0, trans, sel, bitmap, renderer);
|
||||
|
||||
// draw the radius ruler
|
||||
ant::Object radius (center, rc, 0, ruler.fmt (), std::string (), std::string (), ruler.style (), ruler.outline (), false, lay::AC_Global);
|
||||
draw_ruler_segment (radius, 0, trans, sel, bitmap, renderer);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
draw_ruler_angle (const ant::Object &ruler, const db::DCplxTrans &trans, bool sel, lay::CanvasPlane *bitmap, lay::Renderer &renderer)
|
||||
{
|
||||
// draw segments in diag mode
|
||||
ant::Object basic = ruler;
|
||||
basic.outline (ant::Object::OL_diag);
|
||||
draw_ruler_segment (basic, 0, trans, sel, bitmap, renderer);
|
||||
if (basic.segments () > 1) {
|
||||
draw_ruler_segment (basic, basic.segments () - 1, trans, sel, bitmap, renderer);
|
||||
}
|
||||
|
||||
if (ruler.points ().size () < 3) {
|
||||
return;
|
||||
}
|
||||
|
||||
db::DPoint p1 = ruler.p1 (), p2 = ruler.p2 ();
|
||||
|
||||
db::DVector pc;
|
||||
for (size_t i = 1; i + 1 < ruler.points ().size (); ++i) {
|
||||
pc += ruler.points ()[i] - db::DPoint ();
|
||||
}
|
||||
db::DPoint center = db::DPoint () + pc * (1.0 / double (ruler.points ().size () - 2));
|
||||
|
||||
db::DVector v1 (p1 - center);
|
||||
if (v1.double_length () < db::epsilon) {
|
||||
return;
|
||||
}
|
||||
|
||||
db::DVector v2 (p2 - center);
|
||||
if (v2.double_length () < db::epsilon) {
|
||||
return;
|
||||
}
|
||||
|
||||
double radius = std::min (v1.double_length (), v2.double_length ());
|
||||
|
||||
v1 *= 1.0 / v1.double_length ();
|
||||
v2 *= 1.0 / v2.double_length ();
|
||||
|
||||
if (db::vprod_sign (v1, v2) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
double start_angle = 0.0, stop_angle = 0.0;
|
||||
start_angle = atan2 (v1.y (), v1.x ());
|
||||
stop_angle = atan2 (v2.y (), v2.x ());
|
||||
|
||||
if (db::vprod_sign (v1, v2) < 0) {
|
||||
std::swap (start_angle, stop_angle);
|
||||
}
|
||||
|
||||
while (stop_angle < start_angle - db::epsilon) {
|
||||
stop_angle += M_PI * 2.0;
|
||||
}
|
||||
|
||||
db::DVector rr (radius * 0.9, radius * 0.9);
|
||||
std::pair <db::DPoint, db::DPoint> v = lay::snap (trans * (center - rr), trans * (center + rr));
|
||||
draw_ellipse (v.first, v.second, radius * 2.0, sel, bitmap, renderer, start_angle, stop_angle);
|
||||
|
||||
// @@@ TODO: draw text, apply styles to circle segments? ...
|
||||
}
|
||||
|
||||
void
|
||||
draw_ruler (const ant::Object &ruler, const db::DCplxTrans &trans, bool sel, lay::CanvasPlane *bitmap, lay::Renderer &renderer)
|
||||
{
|
||||
if (ruler.outline () == Object::OL_box || ruler.outline () == Object::OL_ellipse) {
|
||||
|
||||
draw_ruler_segment (ruler, std::numeric_limits<size_t>::max (), trans, sel, bitmap, renderer);
|
||||
|
||||
if (ruler.outline () == Object::OL_box) {
|
||||
draw_ruler_box (ruler, trans, sel, bitmap, renderer);
|
||||
} else if (ruler.outline () == Object::OL_ellipse) {
|
||||
draw_ruler_ellipse (ruler, trans, sel, bitmap, renderer);
|
||||
} else if (ruler.outline () == Object::OL_angle) {
|
||||
draw_ruler_angle (ruler, trans, sel, bitmap, renderer);
|
||||
} else if (ruler.outline () == Object::OL_radius) {
|
||||
draw_ruler_radius (ruler, trans, sel, bitmap, renderer);
|
||||
} else {
|
||||
|
||||
// other styles support segments, so paint them individually
|
||||
// other outline styles support segments, so paint them individually
|
||||
for (size_t index = 0; index < ruler.segments (); ++index) {
|
||||
draw_ruler_segment (ruler, index, trans, sel, bitmap, renderer);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
is_selected (const ant::Object &ruler, size_t index, const db::DPoint &pos, double enl, double &distance)
|
||||
{
|
||||
// @@@ angle, radius
|
||||
ant::Object::outline_type outline = ruler.outline ();
|
||||
|
||||
db::DPoint p1 = ruler.seg_p1 (index), p2 = ruler.seg_p2 (index);
|
||||
|
|
@ -759,7 +934,7 @@ is_selected (const ant::Object &ruler, size_t index, const db::DPoint &pos, doub
|
|||
static bool
|
||||
is_selected (const ant::Object &ruler, const db::DPoint &pos, double enl, double &distance)
|
||||
{
|
||||
if (ruler.outline () == ant::Object::OL_box || ruler.outline () == ant::Object::OL_ellipse) {
|
||||
if (ruler.outline () == ant::Object::OL_box || ruler.outline () == ant::Object::OL_ellipse || ruler.outline () == ant::Object::OL_angle || ruler.outline () == ant::Object::OL_radius) {
|
||||
return is_selected (ruler, std::numeric_limits<size_t>::max (), pos, enl, distance);
|
||||
}
|
||||
|
||||
|
|
@ -1078,6 +1253,7 @@ Service::insert_ruler (const ant::Object &ruler, bool limit_number)
|
|||
static bool
|
||||
dragging_what_seg (const ant::Object *robj, const db::DBox &search_dbox, ant::Service::MoveMode &mode, db::DPoint &p1, size_t index)
|
||||
{
|
||||
// @@@ radius, angle
|
||||
ant::Object::outline_type outline = robj->outline ();
|
||||
|
||||
db::DPoint p12, p21;
|
||||
|
|
@ -1159,7 +1335,7 @@ dragging_what (const ant::Object *robj, const db::DBox &search_dbox, ant::Servic
|
|||
{
|
||||
ant::Object::outline_type outline = robj->outline ();
|
||||
|
||||
if (outline == ant::Object::OL_box || outline == ant::Object::OL_ellipse) {
|
||||
if (outline == ant::Object::OL_box || outline == ant::Object::OL_ellipse || outline == ant::Object::OL_angle || outline == ant::Object::OL_radius) {
|
||||
index = std::numeric_limits<size_t>::max ();
|
||||
return dragging_what_seg (robj, search_dbox, mode, p1, index);
|
||||
}
|
||||
|
|
@ -1719,12 +1895,12 @@ Service::mouse_click_event (const db::DPoint &p, unsigned int buttons, bool prio
|
|||
|
||||
}
|
||||
|
||||
} else if (tpl.mode () == ant::Template::RulerMultiSegment || tpl.mode () == ant::Template::RulerAngle) {
|
||||
} else if (tpl.mode () == ant::Template::RulerMultiSegment || tpl.mode () == ant::Template::RulerThreeClicks) {
|
||||
|
||||
ant::Object::point_list pts = m_current.points ();
|
||||
tl_assert (! pts.empty ());
|
||||
|
||||
if (tpl.mode () == ant::Template::RulerAngle && pts.size () == 3) {
|
||||
if (tpl.mode () == ant::Template::RulerThreeClicks && pts.size () == 3) {
|
||||
|
||||
finish_drawing ();
|
||||
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ public:
|
|||
/**
|
||||
* @brief The ruler an angle type (two segments, three mouse clicks) for angle and circle radius measurements
|
||||
*/
|
||||
RulerAngle = 3,
|
||||
RulerThreeClicks = 3,
|
||||
|
||||
/**
|
||||
* @brief The ruler is a multi-segment type
|
||||
|
|
|
|||
|
|
@ -48,6 +48,8 @@ static int outline_yx () { return int (ant::Object::OL_yx); }
|
|||
static int outline_diag_yx () { return int (ant::Object::OL_diag_yx); }
|
||||
static int outline_box () { return int (ant::Object::OL_box); }
|
||||
static int outline_ellipse () { return int (ant::Object::OL_ellipse); }
|
||||
static int outline_angle () { return int (ant::Object::OL_angle); }
|
||||
static int outline_radius () { return int (ant::Object::OL_radius); }
|
||||
|
||||
static int angle_any () { return int (lay::AC_Any); }
|
||||
static int angle_diagonal () { return int (lay::AC_Diagonal); }
|
||||
|
|
@ -432,9 +434,9 @@ static int ruler_mode_auto_metric ()
|
|||
return ant::Template::RulerAutoMetric;
|
||||
}
|
||||
|
||||
static int ruler_mode_angle ()
|
||||
static int ruler_mode_three_clicks ()
|
||||
{
|
||||
return ant::Template::RulerAngle;
|
||||
return ant::Template::RulerThreeClicks;
|
||||
}
|
||||
|
||||
static int ruler_mode_multi_segment ()
|
||||
|
|
@ -523,9 +525,9 @@ gsi::Class<AnnotationRef> decl_Annotation (decl_BasicAnnotation, "lay", "Annotat
|
|||
"\n"
|
||||
"This constant has been introduced in version 0.25"
|
||||
) +
|
||||
gsi::method ("RulerAngle", &gsi::ruler_mode_angle,
|
||||
"@brief Specifies angle ruler mode for the \\register_template method\n"
|
||||
"In angle ruler mode, two segments are created for angle and circle radius measurements. Three mouse clicks are required.\n"
|
||||
gsi::method ("RulerThreeClicks", &gsi::ruler_mode_three_clicks,
|
||||
"@brief Specifies three-click ruler mode for the \\register_template method\n"
|
||||
"In this ruler mode, two segments are created for angle and circle radius measurements. Three mouse clicks are required.\n"
|
||||
"\n"
|
||||
"This constant has been introduced in version 0.28"
|
||||
) +
|
||||
|
|
@ -535,58 +537,58 @@ gsi::Class<AnnotationRef> decl_Annotation (decl_BasicAnnotation, "lay", "Annotat
|
|||
"\n"
|
||||
"This constant has been introduced in version 0.28"
|
||||
) +
|
||||
gsi::method ("StyleRuler|#style_ruler", &gsi::style_ruler,
|
||||
gsi::method ("StyleRuler", &gsi::style_ruler,
|
||||
"@brief Gets the ruler style code for use the \\style method\n"
|
||||
"When this style is specified, the annotation will show a ruler with "
|
||||
"some ticks at distances indicating a decade of units and a suitable "
|
||||
"subdivision into minor ticks at intervals of 1, 2 or 5 units."
|
||||
) +
|
||||
gsi::method ("StyleArrowEnd|#style_arrow_end", &gsi::style_arrow_end,
|
||||
gsi::method ("StyleArrowEnd", &gsi::style_arrow_end,
|
||||
"@brief Gets the end arrow style code for use the \\style method\n"
|
||||
"When this style is specified, an arrow is drawn pointing from the start to the end point."
|
||||
) +
|
||||
gsi::method ("StyleArrowStart|#style_arrow_start", &gsi::style_arrow_start,
|
||||
gsi::method ("StyleArrowStart", &gsi::style_arrow_start,
|
||||
"@brief Gets the start arrow style code for use the \\style method\n"
|
||||
"When this style is specified, an arrow is drawn pointing from the end to the start point."
|
||||
) +
|
||||
gsi::method ("StyleArrowBoth|#style_arrow_both", &gsi::style_arrow_both,
|
||||
gsi::method ("StyleArrowBoth", &gsi::style_arrow_both,
|
||||
"@brief Gets the both arrow ends style code for use the \\style method\n"
|
||||
"When this style is specified, a two-headed arrow is drawn."
|
||||
) +
|
||||
gsi::method ("StyleLine|#style_line", &gsi::style_line,
|
||||
gsi::method ("StyleLine", &gsi::style_line,
|
||||
"@brief Gets the line style code for use with the \\style method\n"
|
||||
"When this style is specified, a plain line is drawn."
|
||||
) +
|
||||
gsi::method ("StyleCrossStart|#style_cross_start", &gsi::style_cross_start,
|
||||
gsi::method ("StyleCrossStart", &gsi::style_cross_start,
|
||||
"@brief Gets the line style code for use with the \\style method\n"
|
||||
"When this style is specified, a cross is drawn at the start point.\n"
|
||||
"\n"
|
||||
"This constant has been added in version 0.26."
|
||||
) +
|
||||
gsi::method ("StyleCrossEnd|#style_cross_end", &gsi::style_cross_end,
|
||||
gsi::method ("StyleCrossEnd", &gsi::style_cross_end,
|
||||
"@brief Gets the line style code for use with the \\style method\n"
|
||||
"When this style is specified, a cross is drawn at the end point.\n"
|
||||
"\n"
|
||||
"This constant has been added in version 0.26."
|
||||
) +
|
||||
gsi::method ("StyleCrossBoth|#style_cross_both", &gsi::style_cross_both,
|
||||
gsi::method ("StyleCrossBoth", &gsi::style_cross_both,
|
||||
"@brief Gets the line style code for use with the \\style method\n"
|
||||
"When this style is specified, a cross is drawn at both points.\n"
|
||||
"\n"
|
||||
"This constant has been added in version 0.26."
|
||||
) +
|
||||
gsi::method ("OutlineDiag|#outline_diag", &gsi::outline_diag,
|
||||
gsi::method ("OutlineDiag", &gsi::outline_diag,
|
||||
"@brief Gets the diagonal output code for use with the \\outline method\n"
|
||||
"When this outline style is specified, a line connecting start and "
|
||||
"end points in the given style (ruler, arrow or plain line) is drawn."
|
||||
) +
|
||||
gsi::method ("OutlineXY|#outline_xy", &gsi::outline_xy,
|
||||
gsi::method ("OutlineXY", &gsi::outline_xy,
|
||||
"@brief Gets the xy outline code for use with the \\outline method\n"
|
||||
"When this outline style is specified, two lines are drawn: one horizontal from left "
|
||||
"to right and attached to the end of that a line from the bottom to the top. The lines "
|
||||
"are drawn in the specified style (see \\style method)."
|
||||
) +
|
||||
gsi::method ("OutlineDiagXY|#outline_diag_xy", &gsi::outline_diag_xy,
|
||||
gsi::method ("OutlineDiagXY", &gsi::outline_diag_xy,
|
||||
"@brief Gets the xy plus diagonal outline code for use with the \\outline method\n"
|
||||
"@brief outline_xy code used by the \\outline method\n"
|
||||
"When this outline style is specified, three lines are drawn: one horizontal from left "
|
||||
|
|
@ -594,53 +596,65 @@ gsi::Class<AnnotationRef> decl_Annotation (decl_BasicAnnotation, "lay", "Annotat
|
|||
"is drawn connecting the start and end points directly. The lines "
|
||||
"are drawn in the specified style (see \\style method)."
|
||||
) +
|
||||
gsi::method ("OutlineYX|#outline_yx", &gsi::outline_yx ,
|
||||
gsi::method ("OutlineYX", &gsi::outline_yx ,
|
||||
"@brief Gets the yx outline code for use with the \\outline method\n"
|
||||
"When this outline style is specified, two lines are drawn: one vertical from bottom "
|
||||
"to top and attached to the end of that a line from the left to the right. The lines "
|
||||
"are drawn in the specified style (see \\style method)."
|
||||
) +
|
||||
gsi::method ("OutlineDiagYX|#outline_diag_yx", &gsi::outline_diag_yx ,
|
||||
gsi::method ("OutlineDiagYX", &gsi::outline_diag_yx ,
|
||||
"@brief Gets the yx plus diagonal outline code for use with the \\outline method\n"
|
||||
"When this outline style is specified, three lines are drawn: one vertical from bottom "
|
||||
"to top and attached to the end of that a line from the left to the right. Another line "
|
||||
"is drawn connecting the start and end points directly. The lines "
|
||||
"are drawn in the specified style (see \\style method)."
|
||||
) +
|
||||
gsi::method ("OutlineBox|#outline_box", &gsi::outline_box,
|
||||
gsi::method ("OutlineBox", &gsi::outline_box,
|
||||
"@brief Gets the box outline code for use with the \\outline method\n"
|
||||
"When this outline style is specified, a box is drawn with the corners specified by the "
|
||||
"start and end point. All box edges are drawn in the style specified with the \\style "
|
||||
"attribute."
|
||||
) +
|
||||
gsi::method ("OutlineEllipse|#outline_ellipse", &gsi::outline_ellipse,
|
||||
gsi::method ("OutlineEllipse", &gsi::outline_ellipse,
|
||||
"@brief Gets the ellipse outline code for use with the \\outline method\n"
|
||||
"When this outline style is specified, an ellipse is drawn with the extensions specified by the "
|
||||
"start and end point. The contour drawn as a line.\n"
|
||||
"\n"
|
||||
"This constant has been introduced in version 0.26."
|
||||
) +
|
||||
gsi::method ("AngleAny|#angle_any", &gsi::angle_any,
|
||||
gsi::method ("OutlineAngle", &gsi::outline_angle,
|
||||
"@brief Gets the angle measurement ruler outline code for use with the \\outline method\n"
|
||||
"When this outline style is specified, the ruler is drawn to indicate the angle between the first and last segment.\n"
|
||||
"\n"
|
||||
"This constant has been introduced in version 0.28."
|
||||
) +
|
||||
gsi::method ("OutlineRadius", &gsi::outline_radius,
|
||||
"@brief Gets the radius measurement ruler outline code for use with the \\outline method\n"
|
||||
"When this outline style is specified, the ruler is drawn to indicate a radius defined by at least three points of the ruler.\n"
|
||||
"\n"
|
||||
"This constant has been introduced in version 0.28."
|
||||
) +
|
||||
gsi::method ("AngleAny", &gsi::angle_any,
|
||||
"@brief Gets the any angle code for use with the \\angle_constraint method\n"
|
||||
"If this value is specified for the angle constraint, all angles will be allowed."
|
||||
) +
|
||||
gsi::method ("AngleDiagonal|#angle_diagonal", &gsi::angle_diagonal,
|
||||
gsi::method ("AngleDiagonal", &gsi::angle_diagonal,
|
||||
"@brief Gets the diagonal angle code for use with the \\angle_constraint method\n"
|
||||
"If this value is specified for the angle constraint, only multiples of 45 degree are allowed."
|
||||
) +
|
||||
gsi::method ("AngleOrtho|#angle_ortho", &gsi::angle_ortho,
|
||||
gsi::method ("AngleOrtho", &gsi::angle_ortho,
|
||||
"@brief Gets the ortho angle code for use with the \\angle_constraint method\n"
|
||||
"If this value is specified for the angle constraint, only multiples of 90 degree are allowed."
|
||||
) +
|
||||
gsi::method ("AngleHorizontal|#angle_horizontal", &gsi::angle_horizontal,
|
||||
gsi::method ("AngleHorizontal", &gsi::angle_horizontal,
|
||||
"@brief Gets the horizontal angle code for use with the \\angle_constraint method\n"
|
||||
"If this value is specified for the angle constraint, only horizontal rulers are allowed."
|
||||
) +
|
||||
gsi::method ("AngleVertical|#angle_vertical", &gsi::angle_vertical,
|
||||
gsi::method ("AngleVertical", &gsi::angle_vertical,
|
||||
"@brief Gets the vertical angle code for use with the \\angle_constraint method\n"
|
||||
"If this value is specified for the angle constraint, only vertical rulers are allowed."
|
||||
) +
|
||||
gsi::method ("AngleGlobal|#angle_global", &gsi::angle_global,
|
||||
gsi::method ("AngleGlobal", &gsi::angle_global,
|
||||
"@brief Gets the global angle code for use with the \\angle_constraint method.\n"
|
||||
"This code will tell the ruler or marker to use the angle constraint defined globally."
|
||||
) +
|
||||
|
|
|
|||
Loading…
Reference in New Issue