mirror of https://github.com/KLayout/klayout.git
WIP: debugging, test case for compound booleans
This commit is contained in:
parent
80509c64e5
commit
9c6e0129d9
|
|
@ -170,14 +170,14 @@ std::vector<db::Region *> CompoundRegionOperationPrimaryNode::inputs () const
|
|||
|
||||
void CompoundRegionOperationPrimaryNode::do_compute_local (db::Layout *, const shape_interactions<db::Polygon, db::Polygon> &interactions, std::vector<std::unordered_set<db::Polygon> > &results, size_t, double) const
|
||||
{
|
||||
for (shape_interactions<db::Polygon, db::Polygon>::subject_iterator i = interactions.begin_subjects (); i != interactions.begin_subjects (); ++i) {
|
||||
for (shape_interactions<db::Polygon, db::Polygon>::subject_iterator i = interactions.begin_subjects (); i != interactions.end_subjects (); ++i) {
|
||||
results.front ().insert (i->second);
|
||||
}
|
||||
}
|
||||
|
||||
void CompoundRegionOperationPrimaryNode::do_compute_local (db::Layout *, const shape_interactions<db::PolygonRef, db::PolygonRef> &interactions, std::vector<std::unordered_set<db::PolygonRef> > &results, size_t, double) const
|
||||
{
|
||||
for (shape_interactions<db::PolygonRef, db::PolygonRef>::subject_iterator i = interactions.begin_subjects (); i != interactions.begin_subjects (); ++i) {
|
||||
for (shape_interactions<db::PolygonRef, db::PolygonRef>::subject_iterator i = interactions.begin_subjects (); i != interactions.end_subjects (); ++i) {
|
||||
results.front ().insert (i->second);
|
||||
}
|
||||
}
|
||||
|
|
@ -320,11 +320,11 @@ CompoundRegionMultiInputOperationNode::init ()
|
|||
{
|
||||
std::map<db::Region *, unsigned int> input_index;
|
||||
|
||||
for (tl::shared_collection<CompoundRegionOperationNode>::iterator i = m_children.begin (); i != m_children.end (); ++i) {
|
||||
unsigned int child_index = 0;
|
||||
for (tl::shared_collection<CompoundRegionOperationNode>::iterator i = m_children.begin (); i != m_children.end (); ++i, ++child_index) {
|
||||
|
||||
std::vector<db::Region *> child_inputs = i->inputs ();
|
||||
unsigned int child_index = 0;
|
||||
for (std::vector<db::Region *>::const_iterator ii = child_inputs.begin (); ii != child_inputs.end (); ++ii, ++child_index) {
|
||||
for (std::vector<db::Region *>::const_iterator ii = child_inputs.begin (); ii != child_inputs.end (); ++ii) {
|
||||
|
||||
std::map<db::Region *, unsigned int>::const_iterator im = input_index.find (*ii);
|
||||
unsigned int li = (unsigned int) m_inputs.size ();
|
||||
|
|
@ -335,7 +335,7 @@ CompoundRegionMultiInputOperationNode::init ()
|
|||
input_index.insert (std::make_pair (*ii, li));
|
||||
}
|
||||
|
||||
m_map_layer_to_child [std::make_pair (child_index, (unsigned int) (ii - child_inputs.begin ()))] = li;
|
||||
m_map_layer_to_child [std::make_pair (child_index, li)] = (unsigned int) (ii - child_inputs.begin ());
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -726,17 +726,19 @@ public:
|
|||
|
||||
void add (const TS *ref1, unsigned int id1, const TI *ref2, unsigned int id2)
|
||||
{
|
||||
mp_result->add_subject_shape (id1, *ref1);
|
||||
if (!mp_result->has_subject_shape_id (id1)) {
|
||||
mp_result->add_subject_shape (id1, *ref1);
|
||||
}
|
||||
|
||||
if (mp_layout) {
|
||||
// In order to guarantee the refs come from the subject layout, we'd need to
|
||||
// rewrite them
|
||||
if (!mp_result->has_intruder_shape_id (id2)) {
|
||||
if (!mp_result->has_intruder_shape_id (id2)) {
|
||||
if (mp_layout) {
|
||||
// In order to guarantee the refs come from the subject layout, we'd need to
|
||||
// rewrite them
|
||||
db::shape_reference_translator<TI> rt (mp_layout);
|
||||
mp_result->add_intruder_shape (id2, m_intruder_layer, rt (*ref2));
|
||||
} else {
|
||||
mp_result->add_intruder_shape (id2, m_intruder_layer, *ref2);
|
||||
}
|
||||
} else {
|
||||
mp_result->add_intruder_shape (id2, m_intruder_layer, *ref2);
|
||||
}
|
||||
|
||||
mp_result->add_interaction (id1, id2);
|
||||
|
|
@ -761,8 +763,12 @@ public:
|
|||
|
||||
void add (const TS *ref1, unsigned int id1, const TI *ref2, unsigned int id2)
|
||||
{
|
||||
mp_result->add_subject_shape (id1, *ref1);
|
||||
mp_result->add_intruder_shape (id2, m_intruder_layer, *ref2);
|
||||
if (!mp_result->has_subject_shape_id (id1)) {
|
||||
mp_result->add_subject_shape (id1, *ref1);
|
||||
}
|
||||
if (!mp_result->has_intruder_shape_id (id2)) {
|
||||
mp_result->add_intruder_shape (id2, m_intruder_layer, *ref2);
|
||||
}
|
||||
mp_result->add_interaction (id1, id2);
|
||||
}
|
||||
|
||||
|
|
@ -784,8 +790,12 @@ public:
|
|||
|
||||
void add (const T *ref1, unsigned int id1, const T *ref2, unsigned int id2)
|
||||
{
|
||||
mp_result->add_subject_shape (id1, *ref1);
|
||||
mp_result->add_intruder_shape (id2, m_intruder_layer, *ref2);
|
||||
if (!mp_result->has_subject_shape_id (id1)) {
|
||||
mp_result->add_subject_shape (id1, *ref1);
|
||||
}
|
||||
if (!mp_result->has_intruder_shape_id (id2)) {
|
||||
mp_result->add_intruder_shape (id2, m_intruder_layer, *ref2);
|
||||
}
|
||||
mp_result->add_interaction (id1, id2);
|
||||
}
|
||||
|
||||
|
|
@ -1900,7 +1910,7 @@ template <class TS, class TI>
|
|||
struct scan_shape2shape_same_layer_flat
|
||||
{
|
||||
void
|
||||
operator () (const generic_shape_iterator<TS> &, bool, unsigned int, shape_interactions<TS, TI> &, db::Coord) const
|
||||
operator () (unsigned int, shape_interactions<TS, TI> &, db::Coord) const
|
||||
{
|
||||
// cannot have different types on the same layer
|
||||
tl_assert (false);
|
||||
|
|
@ -1911,106 +1921,30 @@ template <class T>
|
|||
struct scan_shape2shape_same_layer_flat<T, T>
|
||||
{
|
||||
void
|
||||
operator () (const generic_shape_iterator<T> &subjects, bool needs_isolated_subjects, unsigned int intruder_layer, shape_interactions<T, T> &interactions, db::Coord dist) const
|
||||
operator () (unsigned int intruder_layer, shape_interactions<T, T> &interactions, db::Coord dist) const
|
||||
{
|
||||
db::box_scanner<T, int> scanner;
|
||||
interaction_registration_shape1<T, T> rec (&interactions, intruder_layer);
|
||||
|
||||
addressable_shape_delivery<T> is (subjects);
|
||||
for ( ; !is.at_end (); ++is) {
|
||||
|
||||
unsigned int id = interactions.next_id ();
|
||||
|
||||
const T *shape = is.operator-> ();
|
||||
scanner.insert (shape, id);
|
||||
|
||||
// create subject for subject vs. nothing interactions
|
||||
if (needs_isolated_subjects) {
|
||||
interactions.add_subject (id, *shape);
|
||||
}
|
||||
|
||||
for (typename shape_interactions<T, T>::subject_iterator s = interactions.begin_subjects (); s != interactions.end_subjects (); ++s) {
|
||||
scanner.insert (&s->second, s->first);
|
||||
}
|
||||
|
||||
scanner.process (rec, dist, db::box_convert<T> ());
|
||||
}
|
||||
};
|
||||
|
||||
template <class TS, class TI>
|
||||
struct add_subjects_vs_nothing_flat
|
||||
{
|
||||
void
|
||||
operator () (const generic_shape_iterator<TS> &subjects, shape_interactions<TS, TI> &interactions) const
|
||||
{
|
||||
addressable_shape_delivery<TS> is (subjects);
|
||||
for ( ; !is.at_end (); ++is) {
|
||||
unsigned int id = interactions.next_id ();
|
||||
const TS *shape = is.operator-> ();
|
||||
interactions.add_subject (id, *shape);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <class TS, class TI>
|
||||
struct scan_shape2shape_different_layers_flat
|
||||
{
|
||||
void
|
||||
operator () (const generic_shape_iterator<TS> &subjects, const generic_shape_iterator<TI> &intruders, bool needs_isolated_subjects, unsigned int intruder_layer, shape_interactions<TS, TI> &interactions, db::Coord dist) const
|
||||
operator () (const generic_shape_iterator<TI> &intruders, const db::Box &common_box, unsigned int intruder_layer, shape_interactions<TS, TI> &interactions, db::Coord dist) const
|
||||
{
|
||||
db::box_scanner2<TS, int, TI, int> scanner;
|
||||
interaction_registration_shape2shape<TS, TI> rec (0 /*layout*/, &interactions, intruder_layer);
|
||||
|
||||
db::Box subjects_box = subjects.bbox ();
|
||||
if (subjects_box != db::Box::world ()) {
|
||||
subjects_box.enlarge (db::Vector (dist, dist));
|
||||
}
|
||||
|
||||
db::Box intruders_box = intruders.bbox ();
|
||||
if (intruders_box != db::Box::world ()) {
|
||||
intruders_box.enlarge (db::Vector (dist, dist));
|
||||
}
|
||||
|
||||
db::Box common_box = intruders_box & subjects_box;
|
||||
if (common_box.empty ()) {
|
||||
|
||||
if (needs_isolated_subjects) {
|
||||
for (generic_shape_iterator<TS> is = subjects; ! is.at_end (); ++is) {
|
||||
// create subject for subject vs. nothing interactions
|
||||
interactions.add_subject (interactions.next_id (), *is);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
addressable_shape_delivery<TS> is;
|
||||
|
||||
if (needs_isolated_subjects) {
|
||||
|
||||
box_convert<TS> bcs;
|
||||
|
||||
is = addressable_shape_delivery<TS> (subjects);
|
||||
for ( ; !is.at_end (); ++is) {
|
||||
|
||||
unsigned int id = interactions.next_id ();
|
||||
const TS *shape = is.operator-> ();
|
||||
|
||||
if (bcs (*shape).overlaps (common_box)) {
|
||||
scanner.insert1 (shape, id);
|
||||
}
|
||||
|
||||
// create subject for subject vs. nothing interactions
|
||||
interactions.add_subject (id, *shape);
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
is = addressable_shape_delivery<TS> (subjects.confined (common_box, true));
|
||||
for ( ; !is.at_end (); ++is) {
|
||||
scanner.insert1 (is.operator-> (), interactions.next_id ());
|
||||
}
|
||||
|
||||
for (typename shape_interactions<TS, TI>::subject_iterator s = interactions.begin_subjects (); s != interactions.end_subjects (); ++s) {
|
||||
scanner.insert1 (&s->second, s->first);
|
||||
}
|
||||
|
||||
addressable_shape_delivery<TI> ii (intruders.confined (common_box, true));
|
||||
|
|
@ -2039,16 +1973,55 @@ local_processor<TS, TI, TR>::run_flat (const generic_shape_iterator<TS> &subject
|
|||
shape_interactions<TS, TI> interactions;
|
||||
|
||||
bool needs_isolated_subjects = (op->on_empty_intruder_hint () != OnEmptyIntruderHint::Drop);
|
||||
if (intruders.empty () && needs_isolated_subjects) {
|
||||
add_subjects_vs_nothing_flat<TS, TI> () (subjects, interactions);
|
||||
|
||||
// build the subjects in the intruders list
|
||||
|
||||
db::Coord dist = op->dist ();
|
||||
|
||||
db::Box subjects_box = subjects.bbox ();
|
||||
if (subjects_box != db::Box::world ()) {
|
||||
subjects_box.enlarge (db::Vector (dist, dist));
|
||||
}
|
||||
|
||||
db::Box intruders_box;
|
||||
for (typename std::vector<generic_shape_iterator<TI> >::const_iterator il = intruders.begin (); il != intruders.end (); ++il) {
|
||||
if (*il == subjects) {
|
||||
scan_shape2shape_same_layer_flat<TS, TI> () (subjects, needs_isolated_subjects, (unsigned int) (il - intruders.begin ()), interactions, op->dist ());
|
||||
} else {
|
||||
scan_shape2shape_different_layers_flat<TS, TI> () (subjects, *il, needs_isolated_subjects, (unsigned int) (il - intruders.begin ()), interactions, op->dist ());
|
||||
intruders_box += il->bbox ();
|
||||
}
|
||||
if (intruders_box != db::Box::world ()) {
|
||||
intruders_box.enlarge (db::Vector (dist, dist));
|
||||
}
|
||||
|
||||
db::Box common_box = intruders_box & subjects_box;
|
||||
if (common_box.empty ()) {
|
||||
|
||||
if (needs_isolated_subjects) {
|
||||
for (generic_shape_iterator<TS> is = subjects; ! is.at_end (); ++is) {
|
||||
// create subject for subject vs. nothing interactions
|
||||
interactions.add_subject (interactions.next_id (), *is);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
box_convert<TS> bcs;
|
||||
|
||||
addressable_shape_delivery<TS> is (subjects);
|
||||
for ( ; !is.at_end (); ++is) {
|
||||
const TS *shape = is.operator-> ();
|
||||
if (needs_isolated_subjects || bcs (*shape).overlaps (common_box)) {
|
||||
unsigned int id = interactions.next_id ();
|
||||
interactions.add_subject (id, *shape);
|
||||
}
|
||||
}
|
||||
|
||||
for (typename std::vector<generic_shape_iterator<TI> >::const_iterator il = intruders.begin (); il != intruders.end (); ++il) {
|
||||
if (*il == subjects) {
|
||||
scan_shape2shape_same_layer_flat<TS, TI> () ((unsigned int) (il - intruders.begin ()), interactions, op->dist ());
|
||||
} else {
|
||||
scan_shape2shape_different_layers_flat<TS, TI> () (*il, common_box, (unsigned int) (il - intruders.begin ()), interactions, op->dist ());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (interactions.begin () != interactions.end ()) {
|
||||
|
|
|
|||
|
|
@ -138,6 +138,16 @@ bool RelativeExtentsAsEdges::result_must_not_be_merged () const
|
|||
return (fabs (m_fx1 - m_fx2) < db::epsilon && fabs (m_fy1 - m_fy2) < db::epsilon);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------
|
||||
// PolygonToEdgeProcessor implementation
|
||||
|
||||
void PolygonToEdgeProcessor::process (const db::Polygon &poly, std::vector<db::Edge> &result) const
|
||||
{
|
||||
for (db::Polygon::polygon_edge_iterator e = poly.begin_edge (); ! e.at_end (); ++e) {
|
||||
result.push_back (*e);
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------
|
||||
// ConvexDecomposition implementation
|
||||
|
||||
|
|
|
|||
|
|
@ -218,6 +218,21 @@ private:
|
|||
db::MagnificationAndOrientationReducer m_anisotropic_reducer;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A processor that delivers all edges for a polygon
|
||||
*/
|
||||
class DB_PUBLIC PolygonToEdgeProcessor
|
||||
: public db::PolygonToEdgeProcessorBase
|
||||
{
|
||||
public:
|
||||
PolygonToEdgeProcessor ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void process (const db::Polygon &poly, std::vector<db::Edge> &result) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A decomposition processor to deliver convex-only polygons
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include "dbCompoundOperation.h"
|
||||
#include "dbRegionUtils.h"
|
||||
#include "dbEdgesUtils.h"
|
||||
#include "dbRegionLocalOperations.h"
|
||||
|
||||
namespace gsi
|
||||
|
|
@ -187,6 +188,41 @@ static db::CompoundRegionOperationNode *new_minkowsky_sum_node4 (db::CompoundReg
|
|||
return new db::CompoundRegionProcessingOperationNode (new db::minkowsky_sum_computation<std::vector<db::Point> > (p), input, true /*processor is owned*/);
|
||||
}
|
||||
|
||||
static db::CompoundRegionOperationNode *new_edges_node (db::CompoundRegionOperationNode *input)
|
||||
{
|
||||
return new db::CompoundRegionToEdgeProcessingOperationNode (new db::PolygonToEdgeProcessor (), input, true /*processor is owned*/);
|
||||
}
|
||||
|
||||
static db::CompoundRegionOperationNode *new_edge_length_filter_node (db::CompoundRegionOperationNode *input, db::Edge::distance_type lmin, db::Edge::distance_type lmax, bool inverse)
|
||||
{
|
||||
return new db::CompoundRegionEdgeFilterOperationNode (new db::EdgeLengthFilter (lmin, lmax, inverse), input, true /*processor is owned*/);
|
||||
}
|
||||
|
||||
static db::CompoundRegionOperationNode *new_edge_orientation_filter_node (db::CompoundRegionOperationNode *input, double amin, double amax, bool inverse)
|
||||
{
|
||||
return new db::CompoundRegionEdgeFilterOperationNode (new db::EdgeOrientationFilter (amin, amax, inverse), input, true /*processor is owned*/);
|
||||
}
|
||||
|
||||
static db::CompoundRegionOperationNode *new_edge_pair_to_polygon_node (db::CompoundRegionOperationNode *input, db::Coord e)
|
||||
{
|
||||
return new db::CompoundRegionEdgePairToPolygonProcessingOperationNode (new db::EdgePairToPolygonProcessor (e), input, true /*processor is owned*/);
|
||||
}
|
||||
|
||||
static db::CompoundRegionOperationNode *new_edge_pair_to_edges_node (db::CompoundRegionOperationNode *input)
|
||||
{
|
||||
return new db::CompoundRegionEdgePairToEdgeProcessingOperationNode (new db::EdgePairToEdgesProcessor (), input, true /*processor is owned*/);
|
||||
}
|
||||
|
||||
static db::CompoundRegionOperationNode *new_edge_pair_to_first_edges_node (db::CompoundRegionOperationNode *input)
|
||||
{
|
||||
return new db::CompoundRegionEdgePairToEdgeProcessingOperationNode (new db::EdgePairToFirstEdgesProcessor (), input, true /*processor is owned*/);
|
||||
}
|
||||
|
||||
static db::CompoundRegionOperationNode *new_edge_pair_to_second_edges_node (db::CompoundRegionOperationNode *input)
|
||||
{
|
||||
return new db::CompoundRegionEdgePairToEdgeProcessingOperationNode (new db::EdgePairToSecondEdgesProcessor (), input, true /*processor is owned*/);
|
||||
}
|
||||
|
||||
static db::CompoundRegionOperationNode *new_check_node (db::edge_relation_type rel, bool different_polygons, db::Coord d, bool whole_edges, const tl::Variant &metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter)
|
||||
{
|
||||
return new db::CompoundRegionCheckOperationNode (rel, different_polygons, d,
|
||||
|
|
@ -386,6 +422,27 @@ Class<db::CompoundRegionOperationNode> decl_CompoundRegionOperationNode ("db", "
|
|||
gsi::constructor ("new_rectangle_filter", &new_rectangle_filter, gsi::arg ("input"), gsi::arg ("inverse", false),
|
||||
"@brief Creates a node filtering the input for rectangular shapes (or non-rectangular ones with 'inverse' set to 'true').\n"
|
||||
) +
|
||||
gsi::constructor ("new_edges", &new_edges_node, gsi::arg ("input"),
|
||||
"@brief Creates a node converting polygons into it's edges.\n"
|
||||
) +
|
||||
gsi::constructor ("new_edge_length_filter", &new_edge_length_filter_node, gsi::arg ("input"), gsi::arg ("lmin", 0), gsi::arg ("lmax", std::numeric_limits<db::Edge::distance_type>::max (), "max"), gsi::arg ("inverse", false),
|
||||
"@brief Creates a node filtering edges by their length.\n"
|
||||
) +
|
||||
gsi::constructor ("new_edge_orientation_filter", &new_edge_orientation_filter_node, gsi::arg ("input"), gsi::arg ("amin"), gsi::arg ("amax"), gsi::arg ("inverse", false),
|
||||
"@brief Creates a node filtering edges by their orientation.\n"
|
||||
) +
|
||||
gsi::constructor ("new_edge_pair_to_polygon", &new_edge_pair_to_polygon_node, gsi::arg ("input"), gsi::arg ("e", 0),
|
||||
"@brief Creates a node converting edge pairs to polygons.\n"
|
||||
) +
|
||||
gsi::constructor ("new_edge_pair_to_edges", &new_edge_pair_to_edges_node, gsi::arg ("input"),
|
||||
"@brief Creates a node converting edge pairs to two edges each.\n"
|
||||
) +
|
||||
gsi::constructor ("new_edge_pair_to_first_edges", &new_edge_pair_to_first_edges_node, gsi::arg ("input"),
|
||||
"@brief Creates a node delivering the first edge of each edges pair.\n"
|
||||
) +
|
||||
gsi::constructor ("new_edge_pair_to_second_edges", &new_edge_pair_to_second_edges_node, gsi::arg ("input"),
|
||||
"@brief Creates a node delivering the second edge of each edges pair.\n"
|
||||
) +
|
||||
method ("description=", &db::CompoundRegionOperationNode::set_description, gsi::arg ("d"),
|
||||
"@brief Sets the description for this node"
|
||||
) +
|
||||
|
|
|
|||
|
|
@ -126,3 +126,43 @@ TEST(2_ChainedOperations)
|
|||
db::compare_layouts (_this, ly, tl::testsrc () + "/testdata/drc/compound_au2.gds");
|
||||
}
|
||||
|
||||
TEST(3_BooleanOperations)
|
||||
{
|
||||
db::Layout ly;
|
||||
{
|
||||
std::string fn (tl::testsrc ());
|
||||
fn += "/testdata/drc/compound_3.gds";
|
||||
tl::InputStream stream (fn);
|
||||
db::Reader reader (stream);
|
||||
reader.read (ly);
|
||||
}
|
||||
|
||||
db::RegionCheckOptions check_options;
|
||||
check_options.metrics = db::Projection;
|
||||
|
||||
unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0));
|
||||
db::Region r (db::RecursiveShapeIterator (ly, ly.cell (*ly.begin_top_down ()), l1));
|
||||
|
||||
unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0));
|
||||
db::Region r2 (db::RecursiveShapeIterator (ly, ly.cell (*ly.begin_top_down ()), l2));
|
||||
|
||||
db::CompoundRegionOperationPrimaryNode *primary = new db::CompoundRegionOperationPrimaryNode ();
|
||||
db::CompoundRegionOperationSecondaryNode *secondary = new db::CompoundRegionOperationSecondaryNode (&r2);
|
||||
db::CompoundRegionGeometricalBoolOperationNode geo_bool (db::CompoundRegionGeometricalBoolOperationNode::And, primary, secondary);
|
||||
|
||||
db::Region res = r.cop_to_region (geo_bool);
|
||||
|
||||
unsigned int l1000 = ly.get_layer (db::LayerProperties (1000, 0));
|
||||
res.insert_into (&ly, *ly.begin_top_down (), l1000);
|
||||
|
||||
db::CompoundRegionGeometricalBoolOperationNode geo_bool2 (db::CompoundRegionGeometricalBoolOperationNode::Not, primary, secondary);
|
||||
|
||||
res = r.cop_to_region (geo_bool2);
|
||||
|
||||
unsigned int l1001 = ly.get_layer (db::LayerProperties (1001, 0));
|
||||
res.insert_into (&ly, *ly.begin_top_down (), l1001);
|
||||
|
||||
CHECKPOINT();
|
||||
db::compare_layouts (_this, ly, tl::testsrc () + "/testdata/drc/compound_au3.gds");
|
||||
}
|
||||
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue