Fixed issue #1294 (grid snap not working in partial mode)

This commit is contained in:
Matthias Koefferlein 2023-02-16 21:23:59 +01:00
parent 334e9985f3
commit 7903b9d70d
2 changed files with 52 additions and 5 deletions

View File

@ -1552,15 +1552,19 @@ PartialService::mouse_move_event (const db::DPoint &p, unsigned int buttons, boo
m_alt_ac = ac_from_buttons (buttons);
// drag the vertex or edge/segment
if (m_selection.size () == 1 && ! m_selection.begin ()->first.is_cell_inst () && (m_selection.begin ()->second.size () == 1 /*p*/ || m_selection.begin ()->second.size () == 3 /*p1,p2,edge*/)) {
if (is_single_point_selection () || is_single_edge_selection ()) {
lay::PointSnapToObjectResult snap_details;
// for a single selected point or edge, m_start is the original position and we snap the target -
// thus, we can bring the point on grid or to an object's edge or vertex
snap_details = snap2 (p);
m_current = snap_details.snapped_point;
mouse_cursor_from_snap_details (snap_details);
if (snap_details.object_snap == lay::PointSnapToObjectResult::NoObject) {
m_current = m_start + snap (p - m_start);
} else {
m_current = snap_details.snapped_point;
mouse_cursor_from_snap_details (snap_details);
}
} else {
@ -1601,6 +1605,17 @@ PartialService::mouse_move_event (const db::DPoint &p, unsigned int buttons, boo
return false;
}
static db::DPoint
projected_to_edge (const db::DEdge &edge, const db::DPoint &p)
{
if (edge.is_degenerate ()) {
return edge.p1 ();
} else {
db::DVector v = edge.d () * (1.0 / edge.length ());
return edge.p1 () + v * db::sprod (p - edge.p1 (), v);
}
}
bool
PartialService::mouse_press_event (const db::DPoint &p, unsigned int buttons, bool prio)
{
@ -1674,8 +1689,12 @@ PartialService::mouse_press_event (const db::DPoint &p, unsigned int buttons, bo
if (is_single_point_selection ()) {
// for a single selected point we use the original point as the start location which
// allows bringing a to grid
// allows bringing it to grid
m_current = m_start = single_selected_point ();
} else if (is_single_edge_selection ()) {
// for an edge selection use the point projected to edge as the start location which
// allows bringing it to grid
m_current = m_start = projected_to_edge (single_selected_edge (), p);
} else {
m_current = m_start = p;
}
@ -1863,8 +1882,12 @@ PartialService::mouse_click_event (const db::DPoint &p, unsigned int buttons, bo
if (is_single_point_selection ()) {
// for a single selected point we use the original point as the start location which
// allows bringing a to grid
// allows bringing it to grid
m_current = m_start = single_selected_point ();
} else if (is_single_edge_selection ()) {
// for an edge selection use the point projected to edge as the start location which
// allows bringing it to grid
m_current = m_start = projected_to_edge (single_selected_edge (), p);
} else {
m_current = m_start = p;
}
@ -2390,6 +2413,28 @@ PartialService::is_single_point_selection () const
return (m_selection.size () == 1 && ! m_selection.begin ()->first.is_cell_inst () && m_selection.begin ()->second.size () == 1 /*p*/);
}
db::DEdge
PartialService::single_selected_edge () const
{
// build the transformation variants cache and
// use only the first one of the explicit transformations
// TODO: clarify how this can be implemented in a more generic form or leave it thus.
TransformationVariants tv (view ());
const std::vector<db::DCplxTrans> *tv_list = tv.per_cv_and_layer (m_selection.begin ()->first.cv_index (), m_selection.begin ()->first.layer ());
const lay::CellView &cv = view ()->cellview (m_selection.begin ()->first.cv_index ());
db::ICplxTrans gt (cv.context_trans () * m_selection.begin ()->first.trans ());
db::CplxTrans tt = (*tv_list)[0] * db::CplxTrans (cv->layout ().dbu ()) * gt;
return tt * *m_selection.begin ()->second.begin ();
}
bool
PartialService::is_single_edge_selection () const
{
return (m_selection.size () == 1 && ! m_selection.begin ()->first.is_cell_inst () && m_selection.begin ()->second.size () == 3 /*p1,p2,edge*/);
}
bool
PartialService::select (const db::DBox &box, SelectionMode mode)
{

View File

@ -363,7 +363,9 @@ private:
void resize_markers (size_t n, bool transient);
void resize_inst_markers (size_t n, bool transient);
bool is_single_point_selection () const;
bool is_single_edge_selection () const;
db::DPoint single_selected_point () const;
db::DEdge single_selected_edge () const;
bool handle_guiding_shape_changes ();
void transform_selection (const db::DTrans &move_trans);
};