mirror of https://github.com/KLayout/klayout.git
More consistent behavior of dots in context of booleans, added tests
dots vs. polygon booleans now work as well. This includes "&" and "-" and "inside_part", "outside_part" and the "split_..." versions.
This commit is contained in:
parent
d505767bf1
commit
156f0f4477
|
|
@ -944,6 +944,8 @@ AsIfFlatEdges::edge_region_op (const Region &other, db::EdgePolygonOp::mode_t mo
|
|||
|
||||
db::EdgeProcessor ep (report_progress (), progress_desc ());
|
||||
|
||||
bool has_dots = false;
|
||||
|
||||
for (db::Region::const_iterator p = other.begin (); ! p.at_end (); ++p) {
|
||||
if (p->box ().touches (bbox ())) {
|
||||
ep.insert (*p, 0);
|
||||
|
|
@ -951,7 +953,11 @@ AsIfFlatEdges::edge_region_op (const Region &other, db::EdgePolygonOp::mode_t mo
|
|||
}
|
||||
|
||||
for (EdgesIterator e (begin ()); ! e.at_end (); ++e) {
|
||||
ep.insert (*e, 1);
|
||||
if (e->is_degenerate ()) {
|
||||
has_dots = true;
|
||||
} else {
|
||||
ep.insert (*e, 1);
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<FlatEdges> output_second;
|
||||
|
|
@ -966,6 +972,36 @@ AsIfFlatEdges::edge_region_op (const Region &other, db::EdgePolygonOp::mode_t mo
|
|||
db::EdgePolygonOp op (mode, include_borders);
|
||||
ep.process (cc, op);
|
||||
|
||||
// process dots which are not captured by the booleans using the interaction function
|
||||
|
||||
if (has_dots) {
|
||||
|
||||
std::unique_ptr<FlatEdges> dots (new FlatEdges (false));
|
||||
for (EdgesIterator e (begin ()); ! e.at_end (); ++e) {
|
||||
if (e->is_degenerate ()) {
|
||||
dots->insert (*e);
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<EdgesDelegate *, EdgesDelegate *> res (0, 0);
|
||||
|
||||
if (mode == EdgePolygonOp::Both) {
|
||||
res = dots->selected_interacting_pair_generic (other, include_borders ? EdgesInteract : EdgesInside, size_t (1), std::numeric_limits<size_t>::max ());
|
||||
} else if (mode == EdgePolygonOp::Inside) {
|
||||
res.first = dots->selected_interacting_generic (other, include_borders ? EdgesInteract : EdgesInside, false, size_t (1), std::numeric_limits<size_t>::max ());
|
||||
} else if (mode == EdgePolygonOp::Outside) {
|
||||
res.first = dots->selected_interacting_generic (other, include_borders ? EdgesInteract : EdgesOutside, include_borders, size_t (1), std::numeric_limits<size_t>::max ());
|
||||
}
|
||||
|
||||
if (res.first) {
|
||||
output->add_in_place (db::Edges (res.first));
|
||||
}
|
||||
if (res.second) {
|
||||
output_second->add_in_place (db::Edges (res.second));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return std::make_pair (output.release (), output_second.release ());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -944,6 +944,26 @@ DeepEdges::and_or_not_with (const DeepEdges *other, EdgeBoolOp op) const
|
|||
std::pair<DeepLayer, DeepLayer>
|
||||
DeepEdges::edge_region_op (const DeepRegion *other, EdgePolygonOp::mode_t mode, bool include_borders) const
|
||||
{
|
||||
// first, extract dots
|
||||
|
||||
DeepLayer dots (deep_layer ().derived ());
|
||||
bool has_dots = false;
|
||||
|
||||
db::Layout &layout = const_cast<db::Layout &> (dots.layout ());
|
||||
|
||||
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
|
||||
const db::Shapes &s = c->shapes (deep_layer ().layer ());
|
||||
db::Shapes &st = c->shapes (dots.layer ());
|
||||
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::Edges); ! si.at_end (); ++si) {
|
||||
if (si->edge ().is_degenerate ()) {
|
||||
st.insert (*si);
|
||||
has_dots = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// normal processing (dots will vanish)
|
||||
|
||||
std::vector<unsigned int> output_layers;
|
||||
|
||||
DeepLayer dl_out (deep_layer ().derived ());
|
||||
|
|
@ -965,6 +985,29 @@ DeepEdges::edge_region_op (const DeepRegion *other, EdgePolygonOp::mode_t mode,
|
|||
|
||||
proc.run (&op, deep_layer ().layer (), other->deep_layer ().layer (), output_layers);
|
||||
|
||||
if (has_dots) {
|
||||
|
||||
// process dots
|
||||
|
||||
std::pair<EdgesDelegate *, EdgesDelegate *> res (0, 0);
|
||||
|
||||
if (mode == EdgePolygonOp::Both) {
|
||||
res = db::DeepEdges (dots).selected_interacting_pair_generic_impl (other, include_borders ? EdgesInteract : EdgesInside, size_t (1), std::numeric_limits<size_t>::max ());
|
||||
} else if (mode == EdgePolygonOp::Inside) {
|
||||
res.first = db::DeepEdges (dots).selected_interacting_generic_impl (other, include_borders ? EdgesInteract : EdgesInside, false, size_t (1), std::numeric_limits<size_t>::max ());
|
||||
} else if (mode == EdgePolygonOp::Outside) {
|
||||
res.first = db::DeepEdges (dots).selected_interacting_generic_impl (other, include_borders ? EdgesInteract : EdgesOutside, include_borders, size_t (1), std::numeric_limits<size_t>::max ());
|
||||
}
|
||||
|
||||
if (res.first) {
|
||||
db::DeepEdges (dl_out).add_in_place (db::Edges (res.first));
|
||||
}
|
||||
if (res.second) {
|
||||
db::DeepEdges (dl_out2).add_in_place (db::Edges (res.second));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return std::make_pair (dl_out, dl_out2);
|
||||
}
|
||||
|
||||
|
|
@ -1371,9 +1414,6 @@ RegionDelegate *DeepEdges::extended (coord_type ext_b, coord_type ext_e, coord_t
|
|||
EdgesDelegate *
|
||||
DeepEdges::selected_interacting_generic (const Region &other, EdgeInteractionMode mode, bool inverse, size_t min_count, size_t max_count) const
|
||||
{
|
||||
min_count = std::max (size_t (1), min_count);
|
||||
bool counting = !(min_count == 1 && max_count == std::numeric_limits<size_t>::max ());
|
||||
|
||||
std::unique_ptr<db::DeepRegion> dr_holder;
|
||||
const db::DeepRegion *other_deep = dynamic_cast<const db::DeepRegion *> (other.delegate ());
|
||||
if (! other_deep) {
|
||||
|
|
@ -1382,6 +1422,15 @@ DeepEdges::selected_interacting_generic (const Region &other, EdgeInteractionMod
|
|||
other_deep = dr_holder.get ();
|
||||
}
|
||||
|
||||
return selected_interacting_generic_impl (other_deep, mode, inverse, min_count, max_count);
|
||||
}
|
||||
|
||||
EdgesDelegate *
|
||||
DeepEdges::selected_interacting_generic_impl (const DeepRegion *other_deep, EdgeInteractionMode mode, bool inverse, size_t min_count, size_t max_count) const
|
||||
{
|
||||
min_count = std::max (size_t (1), min_count);
|
||||
bool counting = !(min_count == 1 && max_count == std::numeric_limits<size_t>::max ());
|
||||
|
||||
const db::DeepLayer &edges = merged_deep_layer ();
|
||||
|
||||
DeepLayer dl_out (edges.derived ());
|
||||
|
|
@ -1401,9 +1450,6 @@ DeepEdges::selected_interacting_generic (const Region &other, EdgeInteractionMod
|
|||
std::pair<EdgesDelegate *, EdgesDelegate *>
|
||||
DeepEdges::selected_interacting_pair_generic (const Region &other, EdgeInteractionMode mode, size_t min_count, size_t max_count) const
|
||||
{
|
||||
min_count = std::max (size_t (1), min_count);
|
||||
bool counting = !(min_count == 1 && max_count == std::numeric_limits<size_t>::max ());
|
||||
|
||||
std::unique_ptr<db::DeepRegion> dr_holder;
|
||||
const db::DeepRegion *other_deep = dynamic_cast<const db::DeepRegion *> (other.delegate ());
|
||||
if (! other_deep) {
|
||||
|
|
@ -1412,6 +1458,15 @@ DeepEdges::selected_interacting_pair_generic (const Region &other, EdgeInteracti
|
|||
other_deep = dr_holder.get ();
|
||||
}
|
||||
|
||||
return selected_interacting_pair_generic_impl (other_deep, mode, min_count, max_count);
|
||||
}
|
||||
|
||||
std::pair<EdgesDelegate *, EdgesDelegate *>
|
||||
DeepEdges::selected_interacting_pair_generic_impl (const db::DeepRegion *other_deep, EdgeInteractionMode mode, size_t min_count, size_t max_count) const
|
||||
{
|
||||
min_count = std::max (size_t (1), min_count);
|
||||
bool counting = !(min_count == 1 && max_count == std::numeric_limits<size_t>::max ());
|
||||
|
||||
const db::DeepLayer &edges = merged_deep_layer ();
|
||||
|
||||
DeepLayer dl_out (edges.derived ());
|
||||
|
|
|
|||
|
|
@ -197,6 +197,8 @@ private:
|
|||
virtual std::pair<EdgesDelegate *, EdgesDelegate *> selected_interacting_pair_generic (const Edges &edges, EdgeInteractionMode mode, size_t min_count, size_t max_count) const;
|
||||
virtual EdgesDelegate *selected_interacting_generic (const Region ®ion, EdgeInteractionMode mode, bool inverse, size_t min_count, size_t max_count) const;
|
||||
virtual std::pair<EdgesDelegate *, EdgesDelegate *> selected_interacting_pair_generic (const Region ®ion, EdgeInteractionMode mode, size_t min_count, size_t max_count) const;
|
||||
EdgesDelegate *selected_interacting_generic_impl (const DeepRegion *other_deep, EdgeInteractionMode mode, bool inverse, size_t min_count, size_t max_count) const;
|
||||
std::pair<EdgesDelegate *, EdgesDelegate *> selected_interacting_pair_generic_impl (const DeepRegion *other_deep, EdgeInteractionMode mode, size_t min_count, size_t max_count) const;
|
||||
DeepEdges *apply_filter (const EdgeFilterBase &filter) const;
|
||||
|
||||
template <class Result, class OutputContainer> OutputContainer *processed_impl (const edge_processor<Result> &filter) const;
|
||||
|
|
|
|||
|
|
@ -408,16 +408,24 @@ struct DetectTagEdgeSink
|
|||
static bool
|
||||
edge_is_inside_or_outside (bool outside, const db::Edge &a, const db::Polygon &b)
|
||||
{
|
||||
db::EdgeProcessor ep;
|
||||
ep.insert (b, 0);
|
||||
if (a.is_degenerate ()) {
|
||||
|
||||
ep.insert (a, 1);
|
||||
return ((db::inside_poly (b.begin_edge (), a.p1 ()) <= 0) == outside);
|
||||
|
||||
DetectTagEdgeSink es (outside ? 1 : 2); // 2 is the "outside" tag in "Both" mode -> this makes inside fail
|
||||
db::EdgePolygonOp op (db::EdgePolygonOp::Both, !outside /*include borders in inside*/);
|
||||
ep.process (es, op);
|
||||
} else {
|
||||
|
||||
return es.result;
|
||||
db::EdgeProcessor ep;
|
||||
ep.insert (b, 0);
|
||||
|
||||
ep.insert (a, 1);
|
||||
|
||||
DetectTagEdgeSink es (outside ? 1 : 2); // 2 is the "outside" tag in "Both" mode -> this makes inside fail
|
||||
db::EdgePolygonOp op (db::EdgePolygonOp::Both, !outside /*include borders in inside*/);
|
||||
ep.process (es, op);
|
||||
|
||||
return es.result;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
bool edge_is_inside (const db::Edge &a, const db::Polygon &b)
|
||||
|
|
|
|||
|
|
@ -133,9 +133,7 @@ FlatEdges::ensure_merged_edges_valid () const
|
|||
scanner.reserve (mp_edges->size ());
|
||||
|
||||
for (EdgesIterator e (begin ()); ! e.at_end (); ++e) {
|
||||
if (! e->is_degenerate ()) {
|
||||
scanner.insert (&*e, 0);
|
||||
}
|
||||
scanner.insert (&*e, 0);
|
||||
}
|
||||
|
||||
scanner.process (cluster_collector, 1, db::box_convert<db::Edge> ());
|
||||
|
|
@ -145,9 +143,7 @@ FlatEdges::ensure_merged_edges_valid () const
|
|||
std::map<db::properties_id_type, std::vector<const db::Edge *> > edges_by_props;
|
||||
|
||||
for (EdgesIterator e (begin ()); ! e.at_end (); ++e) {
|
||||
if (! e->is_degenerate ()) {
|
||||
edges_by_props [e.prop_id ()].push_back (e.operator-> ());
|
||||
}
|
||||
edges_by_props [e.prop_id ()].push_back (e.operator-> ());
|
||||
}
|
||||
|
||||
for (auto s2p = edges_by_props.begin (); s2p != edges_by_props.end (); ++s2p) {
|
||||
|
|
|
|||
|
|
@ -1626,3 +1626,13 @@ TEST(90d_edge_interaction_with_count)
|
|||
{
|
||||
run_test (_this, "90", true);
|
||||
}
|
||||
|
||||
TEST(91_edge_booleans_with_dots)
|
||||
{
|
||||
run_test (_this, "91", false);
|
||||
}
|
||||
|
||||
TEST(91d_edge_booleans_with_dots)
|
||||
{
|
||||
run_test (_this, "91", true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,3 +74,16 @@ e2.interacting(cm90, 2, 2).output(1101, 0)
|
|||
e2.interacting(c90, 1, 1).output(1102, 0)
|
||||
e2.interacting(cm90, 1, 1).output(1103, 0)
|
||||
|
||||
c90.interacting(e1).output(1200, 0)
|
||||
c90.not_interacting(e1).output(1201, 0)
|
||||
c90.interacting(e2).output(1202, 0)
|
||||
c90.not_interacting(e2).output(1203, 0)
|
||||
|
||||
c90.interacting(l1).output(1300, 0)
|
||||
c90.not_interacting(l1).output(1301, 0)
|
||||
c90.interacting(l2).output(1302, 0)
|
||||
c90.not_interacting(l2).output(1303, 0)
|
||||
|
||||
c90.split_interacting(l1)[0].output(1310, 0)
|
||||
c90.split_interacting(l1)[1].output(1311, 0)
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,52 @@
|
|||
|
||||
source $drc_test_source
|
||||
target $drc_test_target
|
||||
|
||||
if $drc_test_deep
|
||||
deep
|
||||
end
|
||||
|
||||
l1 = input(1, 0)
|
||||
l2 = input(2, 0)
|
||||
|
||||
l1.output(1, 0)
|
||||
l2.output(2, 0)
|
||||
|
||||
e1 = l1.edges
|
||||
e2 = l2.edges
|
||||
|
||||
e1.output(10, 0)
|
||||
e2.output(11, 0)
|
||||
|
||||
c1 = l1.corners(as_dots)
|
||||
c2 = l2.corners(as_dots)
|
||||
|
||||
c1.output(20, 0)
|
||||
c2.output(21, 0)
|
||||
|
||||
(c2 & l1).output(100, 0)
|
||||
(c2 - l1).output(101, 0)
|
||||
|
||||
c2.andnot(l1)[0].output(110, 0)
|
||||
c2.andnot(l1)[1].output(111, 0)
|
||||
|
||||
c2.inside_part(l1).output(200, 0)
|
||||
c2.outside_part(l1).output(201, 0)
|
||||
|
||||
c2.inside_outside_part(l1)[0].output(210, 0)
|
||||
c2.inside_outside_part(l1)[1].output(211, 0)
|
||||
|
||||
c2.interacting(l1).output(300, 0)
|
||||
c2.not_interacting(l1).output(301, 0)
|
||||
|
||||
c2.split_interacting(l1)[0].output(310, 0)
|
||||
c2.split_interacting(l1)[1].output(311, 0)
|
||||
|
||||
(c2 & e1).output(400, 0)
|
||||
(c2 - e1).output(401, 0)
|
||||
(c2 ^ e1).output(402, 0)
|
||||
(c2 | e1).output(403, 0)
|
||||
|
||||
c2.andnot(e1)[0].output(410, 0)
|
||||
c2.andnot(e1)[1].output(411, 0)
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue