diff --git a/src/edt/edt/edtPartialService.cc b/src/edt/edt/edtPartialService.cc index 072117153..565dbb24f 100644 --- a/src/edt/edt/edtPartialService.cc +++ b/src/edt/edt/edtPartialService.cc @@ -1655,7 +1655,7 @@ PartialService::mouse_move_event (const db::DPoint &p, unsigned int buttons, boo // thus, we can bring the point on grid or to an object's edge or vertex snap_details = snap2 (p); if (snap_details.object_snap == lay::PointSnapToObjectResult::NoObject) { - m_current = m_start + snap (p - m_start); + m_current = m_start + snap_move (p - m_start); } else { m_current = snap_details.snapped_point; mouse_cursor_from_snap_details (snap_details); @@ -1664,7 +1664,7 @@ PartialService::mouse_move_event (const db::DPoint &p, unsigned int buttons, boo } else { // snap movement to angle and grid without object - m_current = m_start + snap (p - m_start); + m_current = m_start + snap_move (p - m_start); clear_mouse_cursors (); } @@ -2202,6 +2202,79 @@ PartialService::begin_move (MoveMode mode, const db::DPoint &p, lay::angle_const } } +void +PartialService::update_vector_snapped_point (const db::DPoint &pt, db::DVector &vr, bool &result_set) const +{ + db::DVector v = snap (pt) - pt; + + if (! result_set || v.length () < vr.length ()) { + result_set = true; + vr = v; + } +} + +db::DVector +PartialService::snap_marker_to_grid (const db::DVector &v, bool &snapped) const +{ + if (! m_snap_objects_to_grid) { + return v; + } + + snapped = false; + db::DVector vr; + + // max. 10000 checks + size_t count = 10000; + + db::DVector snapped_to (1.0, 1.0); + db::DVector vv = lay::snap_angle (v, move_ac (), &snapped_to); + + TransformationVariants tv (view ()); + + for (auto r = m_selection.begin (); r != m_selection.end (); ++r) { + + if (! r->first.is_valid (view ()) || r->first.is_cell_inst ()) { + continue; + } + + const lay::CellView &cv = view ()->cellview (r->first.cv_index ()); + const std::vector *tv_list = tv.per_cv_and_layer (r->first.cv_index (), r->first.layer ()); + if (!tv_list || tv_list->empty ()) { + continue; + } + + db::CplxTrans tr = db::DCplxTrans (vv) * tv_list->front () * db::CplxTrans (cv->layout ().dbu ()) * cv.context_trans () * r->first.trans (); + + for (auto e = r->second.begin (); e != r->second.end () && count > 0; ++e) { + update_vector_snapped_point (tr * e->p1 (), vr, snapped); + --count; + if (count > 0) { + update_vector_snapped_point (tr * e->p2 (), vr, snapped); + --count; + } + } + + } + + if (snapped) { + vr += vv; + return db::DVector (vr.x () * snapped_to.x (), vr.y () * snapped_to.y ()); + } else { + return db::DVector (); + } +} + +db::DVector +PartialService::snap_move (const db::DVector &v) const +{ + bool snapped = false; + db::DVector vs = snap_marker_to_grid (v, snapped); + if (! snapped) { + vs = snap (v); + } + return vs; +} + void PartialService::move (const db::DPoint &p, lay::angle_constraint_type ac) { @@ -2222,7 +2295,7 @@ PartialService::move (const db::DPoint &p, lay::angle_constraint_type ac) // thus, we can bring the point on grid or to an object's edge or vertex snap_details = snap2 (p); if (snap_details.object_snap == lay::PointSnapToObjectResult::NoObject) { - m_current = m_start + snap (p - m_start); + m_current = m_start + snap_move (p - m_start); } else { m_current = snap_details.snapped_point; mouse_cursor_from_snap_details (snap_details); @@ -2231,7 +2304,7 @@ PartialService::move (const db::DPoint &p, lay::angle_constraint_type ac) } else { // snap movement to angle and grid without object - m_current = m_start + snap (p - m_start); + m_current = m_start + snap_move (p - m_start); clear_mouse_cursors (); } diff --git a/src/edt/edt/edtPartialService.h b/src/edt/edt/edtPartialService.h index cd98b953d..113cac0f5 100644 --- a/src/edt/edt/edtPartialService.h +++ b/src/edt/edt/edtPartialService.h @@ -374,6 +374,9 @@ private: db::DPoint snap (const db::DPoint &p) const; db::DVector snap (const db::DVector &p) const; lay::PointSnapToObjectResult snap2 (const db::DPoint &p) const; + void update_vector_snapped_point (const db::DPoint &pt, db::DVector &vr, bool &result_set) const; + db::DVector snap_marker_to_grid (const db::DVector &v, bool &snapped) const; + db::DVector snap_move(const db::DVector &p) const; void enter_edge (const EdgeWithIndex &e, size_t &nmarker, partial_objects::const_iterator sel, const std::map &new_points, const std::map &new_edges, const db::ICplxTrans >, const std::vector &tv, bool transient); void enter_vertices (size_t &nmarker, partial_objects::const_iterator sel, const std::map &new_points, const std::map &new_edges, const db::ICplxTrans >, const std::vector &tv, bool transient); diff --git a/src/edt/edt/edtService.cc b/src/edt/edt/edtService.cc index 83a0b8744..5d415b9b5 100644 --- a/src/edt/edt/edtService.cc +++ b/src/edt/edt/edtService.cc @@ -172,6 +172,20 @@ Service::update_vector_snapped_marker (const lay::ShapeMarker *sm, const db::DTr update_vector_snapped_point (tr * shape.bbox ().center (), vr, result_set); --count; + } else if (shape.is_point ()) { + + update_vector_snapped_point (tr * shape.point (), vr, result_set); + --count; + + } else if (shape.is_edge ()) { + + update_vector_snapped_point (tr * shape.edge ().p1 (), vr, result_set); + --count; + if (count > 0) { + update_vector_snapped_point (tr * shape.edge ().p2 (), vr, result_set); + --count; + } + } else if (shape.is_path ()) { for (auto pt = shape.begin_point (); pt != shape.end_point () && count > 0; ++pt) {