mirror of https://github.com/KLayout/klayout.git
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:
parent
67436d81a5
commit
c831ed15f8
|
|
@ -774,7 +774,6 @@ PartialShapeFinder::visit_cell (const db::Cell &cell, const db::Box &hit_box, co
|
||||||
|
|
||||||
checkpoint ();
|
checkpoint ();
|
||||||
|
|
||||||
// in point mode just store that found that has the least "distance"
|
|
||||||
m_founds.push_back (founds_vector_type::value_type ());
|
m_founds.push_back (founds_vector_type::value_type ());
|
||||||
|
|
||||||
lay::ObjectInstPath &inst_path = m_founds.back ().first;
|
lay::ObjectInstPath &inst_path = m_founds.back ().first;
|
||||||
|
|
@ -786,7 +785,8 @@ PartialShapeFinder::visit_cell (const db::Cell &cell, const db::Box &hit_box, co
|
||||||
inst_path.set_layer (*l);
|
inst_path.set_layer (*l);
|
||||||
inst_path.set_shape (*shape);
|
inst_path.set_shape (*shape);
|
||||||
|
|
||||||
// in point mode, test the edges and use a "closest" criterion
|
// in box mode, select the edges depending on whether an endpoint is inside the
|
||||||
|
// box or not
|
||||||
if (shape->is_polygon ()) {
|
if (shape->is_polygon ()) {
|
||||||
|
|
||||||
for (unsigned int c = 0; c < shape->holes () + 1; ++c) {
|
for (unsigned int c = 0; c < shape->holes () + 1; ++c) {
|
||||||
|
|
@ -897,155 +897,164 @@ PartialShapeFinder::visit_cell (const db::Cell &cell, const db::Box &hit_box, co
|
||||||
const db::Shapes &shapes = cell.shapes (*l);
|
const db::Shapes &shapes = cell.shapes (*l);
|
||||||
std::vector <EdgeWithIndex> edge_sel;
|
std::vector <EdgeWithIndex> edge_sel;
|
||||||
|
|
||||||
db::ShapeIterator shape = shapes.begin_touching (scan_box, flags (), prop_sel (), inv_prop_sel ());
|
// two passes - one with points, second with edges
|
||||||
while (! shape.at_end ()) {
|
|
||||||
|
|
||||||
bool match = false;
|
bool any = false;
|
||||||
double d = std::numeric_limits<double>::max ();
|
for (int pass = 0; pass < 2 && ! any; ++pass) {
|
||||||
|
|
||||||
edge_sel.clear ();
|
db::ShapeIterator shape = shapes.begin_touching (scan_box, flags (), prop_sel (), inv_prop_sel ());
|
||||||
|
while (! shape.at_end ()) {
|
||||||
|
|
||||||
checkpoint ();
|
bool match = false;
|
||||||
|
double d = std::numeric_limits<double>::max ();
|
||||||
|
|
||||||
// in point mode, test the edges and use a "closest" criterion
|
edge_sel.clear ();
|
||||||
if (shape->is_polygon ()) {
|
|
||||||
|
|
||||||
for (unsigned int c = 0; c < shape->holes () + 1; ++c) {
|
checkpoint ();
|
||||||
|
|
||||||
|
// in point mode, test the edges and use a "closest" criterion
|
||||||
|
if (shape->is_polygon ()) {
|
||||||
|
|
||||||
|
for (unsigned int c = 0; c < shape->holes () + 1; ++c) {
|
||||||
|
|
||||||
|
unsigned int n = 0;
|
||||||
|
db::Shape::polygon_edge_iterator ee;
|
||||||
|
for (db::Shape::polygon_edge_iterator e = shape->begin_edge (c); ! e.at_end (); e = ee, ++n) {
|
||||||
|
|
||||||
|
ee = e;
|
||||||
|
++ee;
|
||||||
|
unsigned int nn = ee.at_end () ? 0 : n + 1;
|
||||||
|
|
||||||
|
unsigned int r = test_edge (t, *e, pass == 0, d, match);
|
||||||
|
if (r) {
|
||||||
|
edge_sel.clear ();
|
||||||
|
if ((r & 1) != 0) {
|
||||||
|
edge_sel.push_back (EdgeWithIndex (db::Edge ((*e).p1 (), (*e).p1 ()), n, n, c));
|
||||||
|
}
|
||||||
|
if ((r & 2) != 0) {
|
||||||
|
edge_sel.push_back (EdgeWithIndex (db::Edge ((*e).p2 (), (*e).p2 ()), nn, nn, c));
|
||||||
|
}
|
||||||
|
if (r == 3) {
|
||||||
|
edge_sel.push_back (EdgeWithIndex (*e, n, nn, c));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (shape->is_path ()) {
|
||||||
|
|
||||||
|
// test the "spine"
|
||||||
|
db::Shape::point_iterator pt = shape->begin_point ();
|
||||||
|
if (pt != shape->end_point ()) {
|
||||||
|
db::Point p (*pt);
|
||||||
|
++pt;
|
||||||
|
unsigned int n = 0;
|
||||||
|
for (; pt != shape->end_point (); ++pt, ++n) {
|
||||||
|
unsigned int r = test_edge (t, db::Edge (p, *pt), pass == 0, d, match);
|
||||||
|
if (r) {
|
||||||
|
edge_sel.clear ();
|
||||||
|
if ((r & 1) != 0) {
|
||||||
|
edge_sel.push_back (EdgeWithIndex (db::Edge (p, p), n, n, 0));
|
||||||
|
}
|
||||||
|
if ((r & 2) != 0) {
|
||||||
|
edge_sel.push_back (EdgeWithIndex (db::Edge (*pt, *pt), n + 1, n + 1, 0));
|
||||||
|
}
|
||||||
|
if (r == 3) {
|
||||||
|
edge_sel.push_back (EdgeWithIndex (db::Edge (p, *pt), n, n + 1, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p = *pt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (shape->is_box ()) {
|
||||||
|
|
||||||
|
const db::Box &box = shape->box ();
|
||||||
|
|
||||||
|
// convert to polygon and test those edges
|
||||||
|
db::Polygon poly (box);
|
||||||
|
|
||||||
unsigned int n = 0;
|
unsigned int n = 0;
|
||||||
db::Shape::polygon_edge_iterator ee;
|
db::Shape::polygon_edge_iterator ee;
|
||||||
for (db::Shape::polygon_edge_iterator e = shape->begin_edge (c); ! e.at_end (); e = ee, ++n) {
|
for (db::Shape::polygon_edge_iterator e = poly.begin_edge (); ! e.at_end (); e = ee, ++n) {
|
||||||
|
|
||||||
ee = e;
|
ee = e;
|
||||||
++ee;
|
++ee;
|
||||||
unsigned int nn = ee.at_end () ? 0 : n + 1;
|
unsigned int nn = ee.at_end () ? 0 : n + 1;
|
||||||
|
|
||||||
unsigned int r = test_edge (t, *e, d, match);
|
unsigned int r = test_edge (t, *e, pass == 0, d, match);
|
||||||
if (r) {
|
if (r) {
|
||||||
edge_sel.clear ();
|
edge_sel.clear ();
|
||||||
if ((r & 1) == 1) {
|
if ((r & 1) != 0) {
|
||||||
edge_sel.push_back (EdgeWithIndex (db::Edge ((*e).p1 (), (*e).p1 ()), n, n, c));
|
edge_sel.push_back (EdgeWithIndex (db::Edge ((*e).p1 (), (*e).p1 ()), n, n, 0));
|
||||||
}
|
}
|
||||||
if ((r & 2) == 2) {
|
if ((r & 2) != 0) {
|
||||||
edge_sel.push_back (EdgeWithIndex (db::Edge ((*e).p2 (), (*e).p2 ()), nn, nn, c));
|
edge_sel.push_back (EdgeWithIndex (db::Edge ((*e).p2 (), (*e).p2 ()), nn, nn, 0));
|
||||||
}
|
}
|
||||||
if (r == 3) {
|
if (r == 3) {
|
||||||
edge_sel.push_back (EdgeWithIndex (*e, n, nn, c));
|
edge_sel.push_back (EdgeWithIndex (*e, n, nn, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} else if (shape->is_text ()) {
|
||||||
|
|
||||||
} else if (shape->is_path ()) {
|
db::Point tp (shape->text_trans () * db::Point ());
|
||||||
|
|
||||||
// test the "spine"
|
if (text_info ()) {
|
||||||
db::Shape::point_iterator pt = shape->begin_point ();
|
|
||||||
if (pt != shape->end_point ()) {
|
db::CplxTrans t_dbu = db::CplxTrans (layout ().dbu ()) * t;
|
||||||
db::Point p (*pt);
|
db::Text text;
|
||||||
++pt;
|
shape->text (text);
|
||||||
unsigned int n = 0;
|
db::Box tb (t_dbu.inverted () * text_info ()->bbox (t_dbu * text, vp));
|
||||||
for (; pt != shape->end_point (); ++pt, ++n) {
|
if (tb.contains (hit_box.center ())) {
|
||||||
unsigned int r = test_edge (t, db::Edge (p, *pt), d, match);
|
d = tp.distance (hit_box.center ());
|
||||||
if (r) {
|
|
||||||
edge_sel.clear ();
|
edge_sel.clear ();
|
||||||
if ((r & 1) == 1) {
|
edge_sel.push_back (EdgeWithIndex (db::Edge (tp, tp), 0, 0, 0));
|
||||||
edge_sel.push_back (EdgeWithIndex (db::Edge (p, p), n, n, 0));
|
match = true;
|
||||||
}
|
|
||||||
if ((r & 2) == 2) {
|
|
||||||
edge_sel.push_back (EdgeWithIndex (db::Edge (*pt, *pt), n + 1, n + 1, 0));
|
|
||||||
}
|
|
||||||
if (r == 3) {
|
|
||||||
edge_sel.push_back (EdgeWithIndex (db::Edge (p, *pt), n, n + 1, 0));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
p = *pt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (shape->is_box ()) {
|
} else {
|
||||||
|
|
||||||
const db::Box &box = shape->box ();
|
if (hit_box.contains (tp)) {
|
||||||
|
d = tp.distance (hit_box.center ());
|
||||||
// convert to polygon and test those edges
|
edge_sel.clear ();
|
||||||
db::Polygon poly (box);
|
edge_sel.push_back (EdgeWithIndex (db::Edge (tp, tp), 0, 0, 0));
|
||||||
|
match = true;
|
||||||
unsigned int n = 0;
|
|
||||||
db::Shape::polygon_edge_iterator ee;
|
|
||||||
for (db::Shape::polygon_edge_iterator e = poly.begin_edge (); ! e.at_end (); e = ee, ++n) {
|
|
||||||
|
|
||||||
ee = e;
|
|
||||||
++ee;
|
|
||||||
unsigned int nn = ee.at_end () ? 0 : n + 1;
|
|
||||||
|
|
||||||
unsigned int r = test_edge (t, *e, d, match);
|
|
||||||
if (r) {
|
|
||||||
edge_sel.clear ();
|
|
||||||
if ((r & 1) == 1) {
|
|
||||||
edge_sel.push_back (EdgeWithIndex (db::Edge ((*e).p1 (), (*e).p1 ()), n, n, 0));
|
|
||||||
}
|
|
||||||
if ((r & 2) == 2) {
|
|
||||||
edge_sel.push_back (EdgeWithIndex (db::Edge ((*e).p2 (), (*e).p2 ()), nn, nn, 0));
|
|
||||||
}
|
|
||||||
if (r == 3) {
|
|
||||||
edge_sel.push_back (EdgeWithIndex (*e, n, nn, 0));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (shape->is_text ()) {
|
if (match && closer (d)) {
|
||||||
|
|
||||||
db::Point tp (shape->text_trans () * db::Point ());
|
// in point mode just store that found that has the least "distance"
|
||||||
|
if (m_founds.empty ()) {
|
||||||
if (text_info ()) {
|
m_founds.push_back (founds_vector_type::value_type ());
|
||||||
|
|
||||||
db::CplxTrans t_dbu = db::CplxTrans (layout ().dbu ()) * t;
|
|
||||||
db::Text text;
|
|
||||||
shape->text (text);
|
|
||||||
db::Box tb (t_dbu.inverted () * text_info ()->bbox (t_dbu * text, vp));
|
|
||||||
if (tb.contains (hit_box.center ())) {
|
|
||||||
d = tp.distance (hit_box.center ());
|
|
||||||
edge_sel.clear ();
|
|
||||||
edge_sel.push_back (EdgeWithIndex (db::Edge (tp, tp), 0, 0, 0));
|
|
||||||
match = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
lay::ObjectInstPath &inst_path = m_founds.back ().first;
|
||||||
|
|
||||||
if (hit_box.contains (tp)) {
|
inst_path.set_cv_index (cv_index ());
|
||||||
d = tp.distance (hit_box.center ());
|
inst_path.set_topcell (topcell ());
|
||||||
edge_sel.clear ();
|
inst_path.assign_path (path ().begin (), path ().end ());
|
||||||
edge_sel.push_back (EdgeWithIndex (db::Edge (tp, tp), 0, 0, 0));
|
inst_path.set_layer (*l);
|
||||||
match = true;
|
inst_path.set_shape (*shape);
|
||||||
}
|
|
||||||
|
m_founds.back ().second = edge_sel;
|
||||||
|
|
||||||
|
any = true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
++shape;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (match && closer (d)) {
|
|
||||||
|
|
||||||
// in point mode just store that found that has the least "distance"
|
|
||||||
if (m_founds.empty ()) {
|
|
||||||
m_founds.push_back (founds_vector_type::value_type ());
|
|
||||||
}
|
|
||||||
|
|
||||||
lay::ObjectInstPath &inst_path = m_founds.back ().first;
|
|
||||||
|
|
||||||
inst_path.set_cv_index (cv_index ());
|
|
||||||
inst_path.set_topcell (topcell ());
|
|
||||||
inst_path.assign_path (path ().begin (), path ().end ());
|
|
||||||
inst_path.set_layer (*l);
|
|
||||||
inst_path.set_shape (*shape);
|
|
||||||
|
|
||||||
m_founds.back ().second = edge_sel;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
++shape;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -1153,6 +1162,7 @@ PartialService::timeout ()
|
||||||
m_hover = true;
|
m_hover = true;
|
||||||
|
|
||||||
mp_view->clear_transient_selection ();
|
mp_view->clear_transient_selection ();
|
||||||
|
clear_mouse_cursors ();
|
||||||
|
|
||||||
// compute search box
|
// compute search box
|
||||||
double l = catch_distance ();
|
double l = catch_distance ();
|
||||||
|
|
@ -2413,6 +2423,10 @@ PartialService::enter_edge (const EdgeWithIndex &e, size_t &nmarker, partial_obj
|
||||||
db::DEdge ee = db::DEdge (db::DPoint (ep2) + ((db::DPoint (ep1) - db::DPoint (ep2)) * 0.25), db::DPoint (ep2));
|
db::DEdge ee = db::DEdge (db::DPoint (ep2) + ((db::DPoint (ep1) - db::DPoint (ep2)) * 0.25), db::DPoint (ep2));
|
||||||
marker->set (ee, db::DCplxTrans (gt), tv);
|
marker->set (ee, db::DCplxTrans (gt), tv);
|
||||||
|
|
||||||
|
if (transient && sel->second.size () == 1) {
|
||||||
|
add_mouse_cursor (ep2, sel->first.cv_index (), gt, tv, true);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p1_sel && !p12_sel) {
|
if (p1_sel && !p12_sel) {
|
||||||
|
|
@ -2423,12 +2437,22 @@ PartialService::enter_edge (const EdgeWithIndex &e, size_t &nmarker, partial_obj
|
||||||
db::DEdge ee = db::DEdge (db::DPoint (ep1), db::DPoint (ep1) + ((db::DPoint (ep2) - db::DPoint (ep1)) * 0.25));
|
db::DEdge ee = db::DEdge (db::DPoint (ep1), db::DPoint (ep1) + ((db::DPoint (ep2) - db::DPoint (ep1)) * 0.25));
|
||||||
marker->set (ee, db::DCplxTrans (gt), tv);
|
marker->set (ee, db::DCplxTrans (gt), tv);
|
||||||
|
|
||||||
}
|
if (transient && sel->second.size () == 1) {
|
||||||
|
add_mouse_cursor (ep1, sel->first.cv_index (), gt, tv, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (p12_sel) {
|
if (p12_sel) {
|
||||||
|
|
||||||
lay::Marker *marker = new_marker (nmarker, sel->first.cv_index (), transient);
|
lay::Marker *marker = new_marker (nmarker, sel->first.cv_index (), transient);
|
||||||
marker->set_vertex_size (0);
|
marker->set_vertex_size (0);
|
||||||
marker->set (enew, gt, tv);
|
marker->set (enew, gt, tv);
|
||||||
|
|
||||||
|
if (transient) {
|
||||||
|
add_edge_marker (enew, sel->first.cv_index (), gt, tv, true);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -210,6 +210,7 @@ EditorServiceBase::EditorServiceBase (LayoutViewBase *view)
|
||||||
: lay::ViewService (view->canvas ()),
|
: lay::ViewService (view->canvas ()),
|
||||||
lay::Editable (view),
|
lay::Editable (view),
|
||||||
lay::Plugin (view),
|
lay::Plugin (view),
|
||||||
|
mp_view (view),
|
||||||
m_cursor_enabled (true),
|
m_cursor_enabled (true),
|
||||||
m_has_tracking_position (false)
|
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));
|
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 >, 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
|
void
|
||||||
EditorServiceBase::add_edge_marker (const db::DEdge &e, bool emphasize)
|
EditorServiceBase::add_edge_marker (const db::DEdge &e, bool emphasize)
|
||||||
{
|
{
|
||||||
m_mouse_cursor_markers.push_back (new EdgeMarkerViewObject (this, ui (), e, 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 >, 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
|
void
|
||||||
EditorServiceBase::clear_mouse_cursors ()
|
EditorServiceBase::clear_mouse_cursors ()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -74,10 +74,20 @@ public:
|
||||||
*/
|
*/
|
||||||
void add_mouse_cursor (const db::DPoint &pt, bool emphasize = false);
|
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 >, const std::vector<db::DCplxTrans> &tv, bool emphasize = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Adds an edge marker for the given edge
|
* @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 >, const std::vector<db::DCplxTrans> &tv, bool emphasize = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Resets the mouse cursor
|
* @brief Resets the mouse cursor
|
||||||
|
|
@ -132,6 +142,7 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// The marker representing the mouse cursor
|
// The marker representing the mouse cursor
|
||||||
|
lay::LayoutViewBase *mp_view;
|
||||||
std::vector<lay::ViewObject *> m_mouse_cursor_markers;
|
std::vector<lay::ViewObject *> m_mouse_cursor_markers;
|
||||||
tl::Color m_cursor_color;
|
tl::Color m_cursor_color;
|
||||||
bool m_cursor_enabled;
|
bool m_cursor_enabled;
|
||||||
|
|
|
||||||
|
|
@ -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
|
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 p1 = trans * edg.p1 ();
|
||||||
db::Point p2 = trans * edg.p2 ();
|
db::Point p2 = trans * edg.p2 ();
|
||||||
|
|
||||||
unsigned int ret = 0;
|
unsigned int ret = 0;
|
||||||
|
|
||||||
// we hit the region with the edge end points - take the closest vertex
|
if (points) {
|
||||||
if (m_region.contains (p1) || m_region.contains (p2)) {
|
|
||||||
|
|
||||||
double d1 = p1.double_distance (m_region.center ());
|
// we hit the region with the edge end points - take the closest vertex
|
||||||
double d2 = p2.double_distance (m_region.center ());
|
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) {
|
} else {
|
||||||
ret = 1;
|
|
||||||
} else {
|
|
||||||
ret = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
match = true;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the edge cuts through the active region: test the
|
// if the edge cuts through the active region: test the
|
||||||
// edge as a whole
|
// edge as a whole
|
||||||
if (ret == 0) {
|
|
||||||
db::Edge edg_trans (p1, p2);
|
db::Edge edg_trans (p1, p2);
|
||||||
if (edg_trans.clipped (m_region).first) {
|
if (edg_trans.clipped (m_region).first) {
|
||||||
|
|
||||||
double d = edg_trans.distance_abs (m_region.center ());
|
double d = edg_trans.distance_abs (m_region.center ());
|
||||||
if (! match || d < distance) {
|
if (! match || d < distance) {
|
||||||
distance = d;
|
distance = d;
|
||||||
ret = 3;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = 3;
|
||||||
match = true;
|
match = true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
||||||
|
|
@ -176,11 +176,18 @@ protected:
|
||||||
*
|
*
|
||||||
* "trans" is the transformation to be applied to the edge before the test.
|
* "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.
|
* 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
|
* Bit 0 of this mask indicates the first point is matching, bit 1 indicates the
|
||||||
* second point is matching.
|
* 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:
|
private:
|
||||||
void do_find (const db::Cell &cell, int level, const db::DCplxTrans &vp, const db::ICplxTrans &t);
|
void do_find (const db::Cell &cell, int level, const db::DCplxTrans &vp, const db::ICplxTrans &t);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue