From d2d321c35bb6d21db8f4471d7b4a537128cb16ea Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Wed, 28 Sep 2022 21:16:47 +0200 Subject: [PATCH] WIP: point editing of multi-segment rulers --- src/ant/ant/antObject.cc | 84 ++++++++++++++++++++++++++++++++------- src/ant/ant/antObject.h | 25 ++++++++++-- src/ant/ant/antService.cc | 82 ++++++++++++++++++++++---------------- src/ant/ant/antService.h | 2 + 4 files changed, 140 insertions(+), 53 deletions(-) diff --git a/src/ant/ant/antObject.cc b/src/ant/ant/antObject.cc index 1dedd9281..510ce87a3 100644 --- a/src/ant/ant/antObject.cc +++ b/src/ant/ant/antObject.cc @@ -32,6 +32,24 @@ namespace ant { +static void +clean_points_impl (ant::Object::point_list &points) +{ + auto wp = points.begin (); + auto p = points.begin (); + while (p != points.end ()) { + auto pp = p + 1; + while (pp != points.end () && *pp == *p) { + ++pp; + } + *wp++ = *p; + p = pp; + } + + points.erase (wp, points.end ()); +} + + Object::Object () : m_id (-1), m_fmt_x ("$X"), m_fmt_y ("$Y"), m_fmt ("$D"), @@ -88,7 +106,7 @@ Object::Object (const db::DPoint &_p1, const db::DPoint &_p2, int id, const ant: } Object::Object (const Object::point_list &pts, int id, const ant::Template &t) - : m_id (id), + : m_points (pts), m_id (id), m_fmt_x (t.fmt_x ()), m_fmt_y (t.fmt_y ()), m_fmt (t.fmt ()), m_style (t.style ()), m_outline (t.outline ()), m_snap (t.snap ()), m_angle_constraint (t.angle_constraint ()), @@ -98,7 +116,7 @@ Object::Object (const Object::point_list &pts, int id, const ant::Template &t) m_xlabel_xalign (t.xlabel_xalign ()), m_xlabel_yalign (t.xlabel_yalign ()), m_ylabel_xalign (t.ylabel_xalign ()), m_ylabel_yalign (t.ylabel_yalign ()) { - set_points (pts); + clean_points_impl (m_points); } Object::Object (const ant::Object &d) @@ -224,22 +242,36 @@ Object::operator== (const ant::Object &d) const ; } +void +Object::clean_points () +{ + auto new_points = m_points; + clean_points_impl (new_points); + set_points_exact (std::move (new_points)); +} + void Object::set_points (const point_list &points) { - point_list new_points; - auto p = points.begin (); - while (p != points.end ()) { - auto pp = p + 1; - while (pp != points.end () && *pp == *p) { - ++pp; - } - new_points.push_back (*p); - p = pp; - } + auto new_points = points; + clean_points_impl (new_points); + set_points_exact (std::move (new_points)); +} - if (m_points != new_points) { - m_points = new_points; +void +Object::set_points_exact (const point_list &points) +{ + if (m_points != points) { + m_points = points; + property_changed (); + } +} + +void +Object::set_points_exact (point_list &&points) +{ + if (m_points != points) { + m_points.swap (points); property_changed (); } } @@ -272,6 +304,30 @@ Object::seg_p2 (size_t seg_index) const } } +void +Object::seg_p1 (size_t seg_index, const db::DPoint &p) +{ + if (seg_index == std::numeric_limits::max ()) { + p1 (p); + } else if (seg_index < m_points.size ()) { + m_points[seg_index] = p; + } else if (! m_points.empty ()) { + m_points.back () = p; + } +} + +void +Object::seg_p2 (size_t seg_index, const db::DPoint &p) +{ + if (seg_index == std::numeric_limits::max ()) { + p2 (p); + } else if (seg_index + 1 < m_points.size ()) { + m_points[seg_index + 1] = p; + } else if (! m_points.empty ()) { + m_points.back () = p; + } +} + void Object::p1 (const db::DPoint &p) { diff --git a/src/ant/ant/antObject.h b/src/ant/ant/antObject.h index 60752449d..6fd478c7a 100644 --- a/src/ant/ant/antObject.h +++ b/src/ant/ant/antObject.h @@ -295,10 +295,17 @@ public: /** * @brief Sets the ruler's definition points without cleaning */ - void set_points_exact (const point_list &points) - { - m_points = points; - } + void set_points_exact (const point_list &points); + + /** + * @brief Sets the ruler's definition points without cleaning (move semantics) + */ + void set_points_exact (point_list &&points); + + /** + * @brief Cleans the point list + */ + void clean_points (); /** * @brief Gets the first point of the indicated segment @@ -310,6 +317,16 @@ public: */ db::DPoint seg_p2 (size_t seg_index) const; + /** + * @brief Sets the first point of the indicated segment + */ + void seg_p1 (size_t seg_index, const db::DPoint &p); + + /** + * @brief Sets the second point of the indicated segment + */ + void seg_p2 (size_t seg_index, const db::DPoint &p); + /** * @brief Gets the number of segments * diff --git a/src/ant/ant/antService.cc b/src/ant/ant/antService.cc index fb76bc076..ffcf88a06 100644 --- a/src/ant/ant/antService.cc +++ b/src/ant/ant/antService.cc @@ -858,6 +858,7 @@ Service::Service (db::Manager *manager, lay::LayoutViewBase *view) mp_transient_ruler (0), m_drawing (false), m_current (), m_move_mode (MoveNone), + m_seg_index (0), m_current_template (0) { mp_view->annotations_changed_event.add (this, &Service::annotations_changed); @@ -1074,29 +1075,28 @@ Service::insert_ruler (const ant::Object &ruler, bool limit_number) return new_id; } -/** - * @brief Helper function to determine which move mode to choose given a certain search box and ant::Object - */ static bool -dragging_what (const ant::Object *robj, const db::DBox &search_dbox, ant::Service::MoveMode &mode, db::DPoint &p1) +dragging_what_seg (const ant::Object *robj, const db::DBox &search_dbox, ant::Service::MoveMode &mode, db::DPoint &p1, size_t index) { + ant::Object::outline_type outline = robj->outline (); + db::DPoint p12, p21; bool has_p12 = false, has_p21 = false; - db::DPoint p11 = robj->p1 (), p22 = robj->p2 (); + db::DPoint p11 = robj->seg_p1 (index), p22 = robj->seg_p2 (index); db::DPoint c = p11 + (p22 - p11) * 0.5; - - if (robj->outline () == ant::Object::OL_xy || robj->outline () == ant::Object::OL_diag_xy || robj->outline () == ant::Object::OL_box) { - p12 = db::DPoint (robj->p2 ().x (), robj->p1 ().y ()); + + if (outline == ant::Object::OL_xy || outline== ant::Object::OL_diag_xy || outline == ant::Object::OL_box) { + p12 = db::DPoint (p22.x (), p11.y ()); has_p12 = true; } - if (robj->outline () == ant::Object::OL_yx || robj->outline () == ant::Object::OL_diag_yx || robj->outline () == ant::Object::OL_box) { - p21 = db::DPoint (robj->p1 ().x (), robj->p2 ().y ()); + if (outline == ant::Object::OL_yx || outline == ant::Object::OL_diag_yx || outline == ant::Object::OL_box) { + p21 = db::DPoint (p11.x (), p22.y ()); has_p21 = true; } - - if (robj->outline () == ant::Object::OL_ellipse) { + + if (outline == ant::Object::OL_ellipse) { db::DVector d = (p22 - p11) * 0.5; p12 = c + db::DVector (d.x (), -d.y ()); p21 = c + db::DVector (-d.x (), d.y ()); @@ -1106,7 +1106,7 @@ dragging_what (const ant::Object *robj, const db::DBox &search_dbox, ant::Servic // HINT: this was implemented returning a std::pair, but // I was not able to get it to work in gcc 4.1.2 in -O3 mode ... - + if (search_dbox.contains (p11)) { p1 = p11; mode = ant::Service::MoveP1; @@ -1147,18 +1147,28 @@ dragging_what (const ant::Object *robj, const db::DBox &search_dbox, ant::Servic mode = ant::Service::MoveP2Y; return true; } - if ((robj->outline () == ant::Object::OL_diag || robj->outline () == ant::Object::OL_diag_xy || robj->outline () == ant::Object::OL_diag_yx) - && db::DEdge (p11, p22).distance_abs (search_dbox.center ()) <= search_dbox.width () * 0.5) { - p1 = search_dbox.center (); - mode = ant::Service::MoveRuler; - return true; + + return false; +} + +/** + * @brief Helper function to determine which move mode to choose given a certain search box and ant::Object + */ +static bool +dragging_what (const ant::Object *robj, const db::DBox &search_dbox, ant::Service::MoveMode &mode, db::DPoint &p1, size_t &index) +{ + ant::Object::outline_type outline = robj->outline (); + + if (outline == ant::Object::OL_box || outline == ant::Object::OL_ellipse) { + index = std::numeric_limits::max (); + return dragging_what_seg (robj, search_dbox, mode, p1, index); } - if ((robj->outline () == ant::Object::OL_box || robj->outline () == ant::Object::OL_ellipse) && search_dbox.inside (db::DBox (p11, p22))) { - p1 = search_dbox.center (); - mode = ant::Service::MoveRuler; - return true; + + for (index = 0; index < robj->segments (); ++index) { + if (dragging_what_seg (robj, search_dbox, mode, p1, index)) { + return true; + } } - return false; } @@ -1185,6 +1195,7 @@ Service::begin_move (lay::Editable::MoveMode mode, const db::DPoint &p, lay::ang } else if (mode == lay::Editable::Partial) { m_move_mode = MoveNone; + m_seg_index = 0; // compute search box double l = catch_distance (); @@ -1216,7 +1227,7 @@ Service::begin_move (lay::Editable::MoveMode mode, const db::DPoint &p, lay::ang const ant::Object *robj = dynamic_cast ((*ri).ptr ()); if (robj && (! robj_min || robj == robj_min)) { - if (dragging_what (robj, search_dbox, m_move_mode, m_p1) && m_move_mode != MoveRuler) { + if (dragging_what (robj, search_dbox, m_move_mode, m_p1, m_seg_index) && m_move_mode != MoveRuler) { // found anything: make the moved ruler the selection clear_selection (); @@ -1273,7 +1284,7 @@ Service::begin_move (lay::Editable::MoveMode mode, const db::DPoint &p, lay::ang const ant::Object *robj = dynamic_cast ((*r).ptr ()); if (robj && (! robj_min || robj == robj_min)) { - if (dragging_what (robj, search_dbox, m_move_mode, m_p1)) { + if (dragging_what (robj, search_dbox, m_move_mode, m_p1, m_seg_index)) { // found anything: make the moved ruler the selection clear_selection (); @@ -1340,50 +1351,50 @@ Service::move (const db::DPoint &p, lay::angle_constraint_type ac) if (m_move_mode == MoveP1) { - m_current.p1 (snap2 (m_p1, p, &m_current, ac).second); + m_current.seg_p1 (m_seg_index, snap2 (m_p1, p, &m_current, ac).second); m_rulers [0]->redraw (); } else if (m_move_mode == MoveP2) { - m_current.p2 (snap2 (m_p1, p, &m_current, ac).second); + m_current.seg_p2 (m_seg_index, snap2 (m_p1, p, &m_current, ac).second); m_rulers [0]->redraw (); } else if (m_move_mode == MoveP12) { db::DPoint p12 = snap2 (m_p1, p, &m_current, ac).second; - m_current.p1 (db::DPoint (m_current.p1 ().x(), p12.y ())); - m_current.p2 (db::DPoint (p12.x (), m_current.p2 ().y ())); + m_current.seg_p1 (m_seg_index, db::DPoint (m_current.seg_p1 (m_seg_index).x(), p12.y ())); + m_current.seg_p2 (m_seg_index, db::DPoint (p12.x (), m_current.seg_p2 (m_seg_index).y ())); m_rulers [0]->redraw (); } else if (m_move_mode == MoveP21) { db::DPoint p21 = snap2 (m_p1, p, &m_current, ac).second; - m_current.p1 (db::DPoint (p21.x (), m_current.p1 ().y ())); - m_current.p2 (db::DPoint (m_current.p2 ().x(), p21.y ())); + m_current.seg_p1 (m_seg_index, db::DPoint (p21.x (), m_current.seg_p1 (m_seg_index).y ())); + m_current.seg_p2 (m_seg_index, db::DPoint (m_current.seg_p2 (m_seg_index).x(), p21.y ())); m_rulers [0]->redraw (); } else if (m_move_mode == MoveP1X) { db::DPoint pc = snap2 (m_p1, p, &m_current, ac).second; - m_current.p1 (db::DPoint (pc.x (), m_current.p1 ().y ())); + m_current.seg_p1 (m_seg_index, db::DPoint (pc.x (), m_current.seg_p1 (m_seg_index).y ())); m_rulers [0]->redraw (); } else if (m_move_mode == MoveP2X) { db::DPoint pc = snap2 (m_p1, p, &m_current, ac).second; - m_current.p2 (db::DPoint (pc.x (), m_current.p2 ().y ())); + m_current.seg_p2 (m_seg_index, db::DPoint (pc.x (), m_current.seg_p2 (m_seg_index).y ())); m_rulers [0]->redraw (); } else if (m_move_mode == MoveP1Y) { db::DPoint pc = snap2 (m_p1, p, &m_current, ac).second; - m_current.p1 (db::DPoint (m_current.p1 ().x (), pc.y ())); + m_current.seg_p1 (m_seg_index, db::DPoint (m_current.seg_p1 (m_seg_index).x (), pc.y ())); m_rulers [0]->redraw (); } else if (m_move_mode == MoveP2Y) { db::DPoint pc = snap2 (m_p1, p, &m_current, ac).second; - m_current.p2 (db::DPoint (m_current.p2 ().x (), pc.y ())); + m_current.seg_p2 (m_seg_index, db::DPoint (m_current.seg_p2 (m_seg_index).x (), pc.y ())); m_rulers [0]->redraw (); } else if (m_move_mode == MoveRuler) { @@ -1474,6 +1485,7 @@ Service::end_move (const db::DPoint &, lay::angle_constraint_type) } else if (m_move_mode != MoveNone) { // replace the ruler that was moved + m_current.clean_points (); mp_view->annotation_shapes ().replace (m_selected.begin ()->first, db::DUserObject (new ant::Object (m_current))); annotation_changed_event (m_current.id ()); diff --git a/src/ant/ant/antService.h b/src/ant/ant/antService.h index 5d55af179..a36bf6884 100644 --- a/src/ant/ant/antService.h +++ b/src/ant/ant/antService.h @@ -545,6 +545,8 @@ private: ant::Object m_original; // The current move mode MoveMode m_move_mode; + // The currently moving segment + size_t m_seg_index; // The ruler template std::vector m_ruler_templates; unsigned int m_current_template;