diff --git a/src/ant/antService.cc b/src/ant/antService.cc index ee17d802f..884f18fda 100644 --- a/src/ant/antService.cc +++ b/src/ant/antService.cc @@ -1410,9 +1410,14 @@ Service::mouse_click_event (const db::DPoint &p, unsigned int buttons, bool prio } else if (tpl.mode () == ant::Template::RulerAutoMetric) { // for auto-metric we need some cutline constraint - any or global won't do. - lay::angle_constraint_type ac = tpl.angle_constraint (); - ac = (ac == lay::AC_Global ? m_snap_mode : ac); - if (ac == lay::AC_Any || ac == lay::AC_Global) { + lay::angle_constraint_type ac = ac_from_buttons (buttons); + if (ac == lay::AC_Global) { + ac = tpl.angle_constraint (); + } + if (ac == lay::AC_Global) { + ac = m_snap_mode; + } + if (ac == lay::AC_Global) { ac = lay::AC_Diagonal; } @@ -1424,7 +1429,7 @@ Service::mouse_click_event (const db::DPoint &p, unsigned int buttons, bool prio double snap_range = widget ()->mouse_event_trans ().inverted ().ctrans (m_snap_range); snap_range *= 0.5; - std::pair ee = lay::obj_snap2 (mp_view, p, p, g, ac, snap_range, snap_range * 1000.0); + std::pair ee = lay::obj_snap2 (mp_view, p, g, ac, snap_range, snap_range * 1000.0); if (ee.first) { // begin the transaction diff --git a/src/laybasic/laySnap.cc b/src/laybasic/laySnap.cc index b75aaa380..018366829 100644 --- a/src/laybasic/laySnap.cc +++ b/src/laybasic/laySnap.cc @@ -716,8 +716,8 @@ private: const std::set *mp_prop_sel; bool m_inv_prop_sel; bool m_projection_constraint; - bool m_directed; bool m_with_vertex; + bool m_directed; }; static std::pair @@ -776,33 +776,32 @@ do_obj_snap2 (lay::LayoutView *view, const db::DPoint &pt, const db::DVector &gr finder.find (view, sr); - if (finder.any ()) { + if ((cutlines.empty () && finder.any ()) || finder.any_exact ()) { db::DPoint p1 = finder.get_found (); std::vector cl; db::DVector n; - if (finder.is_vertex () || finder.has_found_edge ()) { + if (! cutlines.empty ()) { - if (finder.is_vertex ()) { + // select those cutlines that lead to the first intersection point + for (std::vector::const_iterator i = cutlines.begin (); i != cutlines.end (); ++i) { - std::pair ee = finder.get_found_vertex_edges (); - db::DVector d1 = ee.first.d (); - if (d1.double_length () > 1e-6) { - d1 *= (1.0 / d1.double_length ()); - } - db::DVector d2 = ee.second.d (); - if (d2.double_length () > 1e-6) { - d2 *= (1.0 / d1.double_length ()); + db::DVector n = i->d (); + db::DVector d = dp - p1; + if (fabs (db::vprod (n, d)) < 1e-6 * n.length () * d.length ()) { + if (db::sprod (n, d) < 0.0) { + n = -n; + } + cl.push_back (db::DEdge (p1, p1 + n)); } - n = ((d1 + d2) * 0.5).transformed (db::DTrans (db::DTrans::r90)); - - } else { - n = finder.get_found_edge ().d ().transformed (db::DTrans (db::DTrans::r90)); } + } else if (finder.has_found_edge ()) { + + n = finder.get_found_edge ().d ().transformed (db::DTrans (db::DTrans::r90)); if (db::sprod (n, dp - p1) < 0.0) { n = -n; } @@ -874,15 +873,17 @@ obj_snap (lay::LayoutView *view, const db::DPoint &p1, const db::DPoint &p2, con std::pair obj_snap2 (lay::LayoutView *view, const db::DPoint &pt, const db::DVector &grid, double min_search_range, double max_search_range) { - return do_obj_snap2 (view, pt, grid, min_search_range, max_search_range, std::vector ()); + return do_obj_snap2 (view, lay::snap_xy (pt, grid), db::DVector (), min_search_range, max_search_range, std::vector ()); } std::pair -obj_snap2 (lay::LayoutView *view, const db::DPoint &p1, const db::DPoint &p2, const db::DVector &grid, lay::angle_constraint_type snap_mode, double min_search_range, double max_search_range) +obj_snap2 (lay::LayoutView *view, const db::DPoint &pt, const db::DVector &grid, lay::angle_constraint_type snap_mode, double min_search_range, double max_search_range) { + db::DPoint dp = lay::snap_xy (pt, grid); + std::vector cutlines; - make_cutlines (snap_mode, p1, cutlines); - return do_obj_snap2 (view, p2, grid, min_search_range, max_search_range, cutlines); + make_cutlines (snap_mode, dp, cutlines); + return do_obj_snap2 (view, dp, db::DVector (), min_search_range, max_search_range, cutlines); } } diff --git a/src/laybasic/laySnap.h b/src/laybasic/laySnap.h index cf7449454..f0e31fcdc 100644 --- a/src/laybasic/laySnap.h +++ b/src/laybasic/laySnap.h @@ -127,14 +127,6 @@ namespace lay */ LAYBASIC_PUBLIC std::pair obj_snap (lay::LayoutView *view, const db::DPoint &pt, const db::DVector &grid, double snap_range); - /** - * @brief Same than obj_snap, but delivers two points on two opposite sides of the initial point - * - * This method basically implements "auto measure". The first value of the returned pair - * is true if such an edge could be found. Otherwise it's false. - */ - LAYBASIC_PUBLIC std::pair obj_snap2 (lay::LayoutView *view, const db::DPoint &pt, const db::DVector &grid, double min_search_range, double max_search_range); - /** * @brief combined grid-, projection- and object snapping provided to implementing "magnetic features" * @@ -149,7 +141,14 @@ namespace lay * This method basically implements "auto measure". The first value of the returned pair * is true if such an edge could be found. Otherwise it's false. */ - LAYBASIC_PUBLIC std::pair obj_snap2 (lay::LayoutView *view, const db::DPoint &pr, const db::DPoint &pt, const db::DVector &grid, lay::angle_constraint_type ac, double min_search_range, double max_search_range); + LAYBASIC_PUBLIC std::pair obj_snap2 (lay::LayoutView *view, const db::DPoint &pt, const db::DVector &grid, double min_search_range, double max_search_range); + + /** + * @brief Same than the previous obj_snap2, but allows specification of an angle constraint + * + * Measurements will be confined to the direction specified. + */ + LAYBASIC_PUBLIC std::pair obj_snap2 (lay::LayoutView *view, const db::DPoint &pt, const db::DVector &grid, lay::angle_constraint_type ac, double min_search_range, double max_search_range); /** * @brief Reduce a given vector according to the angle constraint diff --git a/src/unit_tests/laySnap.cc b/src/unit_tests/laySnap.cc index 67a8d60ff..ed3a45a3e 100644 --- a/src/unit_tests/laySnap.cc +++ b/src/unit_tests/laySnap.cc @@ -55,10 +55,23 @@ TEST(1) std::pair res; + // not hit + res = lay::obj_snap (&view, db::DPoint (1.505, 1.505), db::DVector (), 0.1); + EXPECT_EQ (res.first, false); + EXPECT_EQ (res.second.to_string (), "1.505,1.505"); + res = lay::obj_snap (&view, db::DPoint (0.505, 0.505), db::DVector (), 0.1); EXPECT_EQ (res.first, true); EXPECT_EQ (res.second.to_string (), "0.5,0.5"); + res = lay::obj_snap (&view, db::DPoint (0.485, 0.505), db::DVector (0.01, 0.01), 0.1); + EXPECT_EQ (res.first, true); + EXPECT_EQ (res.second.to_string (), "0.49,0.51"); + + res = lay::obj_snap (&view, db::DPoint (0.205, 0.215), db::DVector (0.01, 0.025), 0.1); + EXPECT_EQ (res.first, false); + EXPECT_EQ (res.second.to_string (), "0.21,0.225"); + res = lay::obj_snap (&view, db::DPoint (0.505, 1.005), db::DVector (), 0.1); EXPECT_EQ (res.first, false); EXPECT_EQ (res.second.to_string (), "0.505,1.005"); @@ -71,6 +84,65 @@ TEST(1) EXPECT_EQ (res.first, true); EXPECT_EQ (res.second.to_string (), "0.495,0.505"); + // projected snapping + res = lay::obj_snap (&view, db::DPoint (1.000, 0.505), db::DPoint (0.005, 1.005), db::DVector (), lay::AC_Horizontal, 0.1); + EXPECT_EQ (res.first, true); + EXPECT_EQ (res.second.to_string (), "0,0.505"); + + std::pair res2; + + res2 = lay::obj_snap2 (&view, db::DPoint (1.5, 1.5), db::DVector (), 0.005, 1.0); + EXPECT_EQ (res2.first, false); + EXPECT_EQ (res2.second.to_string (), "(0,0;0,0)"); + + res2 = lay::obj_snap2 (&view, db::DPoint (0.205, 0.5), db::DVector (), 0.005, 1.0); + EXPECT_EQ (res2.first, true); + EXPECT_EQ (res2.second.to_string (), "(0.3525,0.6475;0,0.295)"); + + res2 = lay::obj_snap2 (&view, db::DPoint (0.205, 0.5), db::DVector (), lay::AC_Horizontal, 0.005, 1.0); + EXPECT_EQ (res2.first, true); + EXPECT_EQ (res2.second.to_string (), "(0,0.5;0.5,0.5)"); + + res2 = lay::obj_snap2 (&view, db::DPoint (0.205, 0.5), db::DVector (0.03, 0.03), lay::AC_Horizontal, 0.005, 1.0); + EXPECT_EQ (res2.first, true); + EXPECT_EQ (res2.second.to_string (), "(0,0.51;0.49,0.51)"); + + res2 = lay::obj_snap2 (&view, db::DPoint (0.205, 0.5), db::DVector (), lay::AC_Vertical, 0.005, 1.0); + EXPECT_EQ (res2.first, true); + EXPECT_EQ (res2.second.to_string (), "(0.205,0.795;0.205,0)"); + + res2 = lay::obj_snap2 (&view, db::DPoint (0.205, 0.5), db::DVector (), lay::AC_Diagonal, 0.005, 1.0); + EXPECT_EQ (res2.first, true); + EXPECT_EQ (res2.second.to_string (), "(0.3525,0.6475;0,0.295)"); + + res2 = lay::obj_snap2 (&view, db::DPoint (0.205, 0.505), db::DVector (), lay::AC_Ortho, 0.005, 1.0); + EXPECT_EQ (res2.first, true); + EXPECT_EQ (res2.second.to_string (), "(0,0.505;0.495,0.505)"); + + res2 = lay::obj_snap2 (&view, db::DPoint (0.205, 0.5), db::DVector (), lay::AC_Any, 0.005, 1.0); + EXPECT_EQ (res2.first, true); + EXPECT_EQ (res2.second.to_string (), "(0.3525,0.6475;0,0.295)"); + + res2 = lay::obj_snap2 (&view, db::DPoint (0.205, 0.495), db::DVector (0.01, 0.01), 0.005, 1.0); + EXPECT_EQ (res2.first, true); + EXPECT_EQ (res2.second.to_string (), "(0.355,0.645;0,0.29)"); + + res2 = lay::obj_snap2 (&view, db::DPoint (0.5, 0.5), db::DVector (), 0.005, 1.0); + EXPECT_EQ (res2.first, false); + EXPECT_EQ (res2.second.to_string (), "(0,0;0,0)"); + + res2 = lay::obj_snap2 (&view, db::DPoint (0.005, 0.5), db::DVector (), 0.005, 1.0); + EXPECT_EQ (res2.first, true); + EXPECT_EQ (res2.second.to_string (), "(0,0.5;0.5,0.5)"); + + res2 = lay::obj_snap2 (&view, db::DPoint (0.0, 0.5), db::DVector (), 0.005, 1.0); + EXPECT_EQ (res2.first, false); + EXPECT_EQ (res2.second.to_string (), "(0,0;0,0)"); + + res2 = lay::obj_snap2 (&view, db::DPoint (-0.2, 0.5), db::DVector (), 0.005, 1.0); + EXPECT_EQ (res2.first, false); + EXPECT_EQ (res2.second.to_string (), "(0,0;0,0)"); + } // .. TODO: implement ..