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:
Matthias Koefferlein 2024-03-07 18:34:01 +01:00
parent d505767bf1
commit 156f0f4477
14 changed files with 192 additions and 20 deletions

View File

@ -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 ());
}

View File

@ -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 ());

View File

@ -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 &region, EdgeInteractionMode mode, bool inverse, size_t min_count, size_t max_count) const;
virtual std::pair<EdgesDelegate *, EdgesDelegate *> selected_interacting_pair_generic (const Region &region, 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;

View File

@ -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)

View File

@ -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) {

View File

@ -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);
}

View File

@ -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)

52
testdata/drc/drcSimpleTests_91.drc vendored Normal file
View File

@ -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)

BIN
testdata/drc/drcSimpleTests_91.gds vendored Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
testdata/drc/drcSimpleTests_au91.gds vendored Normal file

Binary file not shown.

BIN
testdata/drc/drcSimpleTests_au91d.gds vendored Normal file

Binary file not shown.

Binary file not shown.