Enhance the selection behavior of partial edit mode: allow selection of edge ends if edges overlap, graphical indicator for selected partial

This commit is contained in:
Matthias Koefferlein
2023-07-15 00:22:17 +02:00
parent 67436d81a5
commit c831ed15f8
5 changed files with 220 additions and 132 deletions
@@ -210,6 +210,7 @@ EditorServiceBase::EditorServiceBase (LayoutViewBase *view)
: lay::ViewService (view->canvas ()),
lay::Editable (view),
lay::Plugin (view),
mp_view (view),
m_cursor_enabled (true),
m_has_tracking_position (false)
{
@@ -229,12 +230,30 @@ EditorServiceBase::add_mouse_cursor (const db::DPoint &pt, bool emphasize)
m_mouse_cursor_markers.push_back (new MouseCursorViewObject (this, ui (), pt, emphasize));
}
void
EditorServiceBase::add_mouse_cursor (const db::Point &pt, unsigned int cv_index, const db::ICplxTrans &gt, const std::vector<db::DCplxTrans> &tv, bool emphasize)
{
double dbu = mp_view->cellview (cv_index)->layout ().dbu ();
for (auto t = tv.begin (); t != tv.end (); ++t) {
add_mouse_cursor (*t * db::CplxTrans (dbu) * gt * pt, emphasize);
}
}
void
EditorServiceBase::add_edge_marker (const db::DEdge &e, bool emphasize)
{
m_mouse_cursor_markers.push_back (new EdgeMarkerViewObject (this, ui (), e, emphasize));
}
void
EditorServiceBase::add_edge_marker (const db::Edge &e, unsigned int cv_index, const db::ICplxTrans &gt, const std::vector<db::DCplxTrans> &tv, bool emphasize)
{
double dbu = mp_view->cellview (cv_index)->layout ().dbu ();
for (auto t = tv.begin (); t != tv.end (); ++t) {
add_edge_marker (*t * db::CplxTrans (dbu) * gt * e, emphasize);
}
}
void
EditorServiceBase::clear_mouse_cursors ()
{
+12 -1
View File
@@ -74,10 +74,20 @@ public:
*/
void add_mouse_cursor (const db::DPoint &pt, bool emphasize = false);
/**
* @brief Adds a mouse cursor to the given point in layout space
*/
void add_mouse_cursor (const db::Point &pt, unsigned int cv_index, const db::ICplxTrans &gt, const std::vector<db::DCplxTrans> &tv, bool emphasize = false);
/**
* @brief Adds an edge marker for the given edge
*/
void add_edge_marker (const db::DEdge &e, bool emphasize);
void add_edge_marker (const db::DEdge &e, bool emphasize = false);
/**
* @brief Adds an edge marker for the given edge in layout space
*/
void add_edge_marker (const db::Edge &e, unsigned int cv_index, const db::ICplxTrans &gt, const std::vector<db::DCplxTrans> &tv, bool emphasize = false);
/**
* @brief Resets the mouse cursor
@@ -132,6 +142,7 @@ protected:
private:
// The marker representing the mouse cursor
lay::LayoutViewBase *mp_view;
std::vector<lay::ViewObject *> m_mouse_cursor_markers;
tl::Color m_cursor_color;
bool m_cursor_enabled;
+48 -21
View File
@@ -123,47 +123,74 @@ Finder::start (lay::LayoutViewBase *view, unsigned int cv_index, const std::vect
}
}
void
Finder::test_edge (const db::ICplxTrans &trans, const db::Edge &edge, double &distance, bool &match)
{
if (test_edge (trans, edge, true, distance, match) == 0) {
test_edge (trans, edge, false, distance, match);
}
}
unsigned int
Finder::test_edge (const db::ICplxTrans &trans, const db::Edge &edg, double &distance, bool &match)
Finder::test_edge (const db::ICplxTrans &trans, const db::Edge &edg, bool points, double &distance, bool &match)
{
db::Point p1 = trans * edg.p1 ();
db::Point p2 = trans * edg.p2 ();
unsigned int ret = 0;
// we hit the region with the edge end points - take the closest vertex
if (m_region.contains (p1) || m_region.contains (p2)) {
if (points) {
double d1 = p1.double_distance (m_region.center ());
double d2 = p2.double_distance (m_region.center ());
// we hit the region with the edge end points - take the closest vertex
if (m_region.contains (p1) || m_region.contains (p2)) {
double d1 = p1.double_distance (m_region.center ());
double d2 = p2.double_distance (m_region.center ());
if (d1 < d2) {
ret = 1;
} else {
ret = 2;
}
double d = std::min (d1, d2);
// add a penalty of 1 DBU for being on the wrong
// side of the edge - this favors the right edge
// in case of butting corners
if (ret == 1) {
if (db::sprod_sign (m_region.center () - p1, p2 - p1) < 0) {
d += trans.ctrans (1);
}
} else {
if (db::sprod_sign (m_region.center () - p2, p1 - p2) < 0) {
d += trans.ctrans (1);
}
}
if (! match || d < distance) {
distance = d;
}
match = true;
double d = std::min (d1, d2);
if (! match || d < distance) {
distance = d;
}
if (d1 < d2) {
ret = 1;
} else {
ret = 2;
}
match = true;
}
} else {
// if the edge cuts through the active region: test the
// edge as a whole
if (ret == 0) {
// if the edge cuts through the active region: test the
// edge as a whole
db::Edge edg_trans (p1, p2);
if (edg_trans.clipped (m_region).first) {
double d = edg_trans.distance_abs (m_region.center ());
if (! match || d < distance) {
distance = d;
ret = 3;
}
ret = 3;
match = true;
}
}
return ret;
+8 -1
View File
@@ -176,11 +176,18 @@ protected:
*
* "trans" is the transformation to be applied to the edge before the test.
*
* If "points" is true, only points are tested, otherwise edges are tested.
*
* This method returns a mask indicating which point of the edge was matching.
* Bit 0 of this mask indicates the first point is matching, bit 1 indicates the
* second point is matching.
*/
unsigned int test_edge (const db::ICplxTrans &trans, const db::Edge &edge, double &distance, bool &match);
unsigned int test_edge (const db::ICplxTrans &trans, const db::Edge &edge, bool points, double &distance, bool &match);
/**
* @brief Tests an edge in point mode and edge mode (later)
*/
void test_edge (const db::ICplxTrans &trans, const db::Edge &edge, double &distance, bool &match);
private:
void do_find (const db::Cell &cell, int level, const db::DCplxTrans &vp, const db::ICplxTrans &t);