mirror of https://github.com/KLayout/klayout.git
WIP: enabling booleans with property constraints
This commit is contained in:
parent
f3e610b6e8
commit
b7c515bf91
|
|
@ -288,6 +288,7 @@ HEADERS = \
|
|||
dbPolygonTools.h \
|
||||
dbPolygonGenerators.h \
|
||||
dbPropertiesRepository.h \
|
||||
dbPropertyConstraint.h \
|
||||
dbReader.h \
|
||||
dbRecursiveInstanceIterator.h \
|
||||
dbRecursiveShapeIterator.h \
|
||||
|
|
|
|||
|
|
@ -1428,7 +1428,7 @@ AsIfFlatRegion::sized (coord_type dx, coord_type dy, unsigned int mode) const
|
|||
}
|
||||
|
||||
RegionDelegate *
|
||||
AsIfFlatRegion::and_with (const Region &other) const
|
||||
AsIfFlatRegion::and_with (const Region &other, PropertyConstraint property_constraint) const
|
||||
{
|
||||
if (empty () || other.empty ()) {
|
||||
|
||||
|
|
@ -1479,6 +1479,8 @@ AsIfFlatRegion::and_with (const Region &other) const
|
|||
|
||||
} else {
|
||||
|
||||
// @@@ TODO: implement property constraint
|
||||
|
||||
// Generic case
|
||||
db::EdgeProcessor ep (report_progress (), progress_desc ());
|
||||
ep.set_base_verbosity (base_verbosity ());
|
||||
|
|
@ -1515,7 +1517,7 @@ AsIfFlatRegion::and_with (const Region &other) const
|
|||
}
|
||||
|
||||
RegionDelegate *
|
||||
AsIfFlatRegion::not_with (const Region &other) const
|
||||
AsIfFlatRegion::not_with (const Region &other, PropertyConstraint property_constraint) const
|
||||
{
|
||||
if (empty ()) {
|
||||
|
||||
|
|
@ -1534,6 +1536,8 @@ AsIfFlatRegion::not_with (const Region &other) const
|
|||
|
||||
} else {
|
||||
|
||||
// @@@ TODO: implement property constraint
|
||||
|
||||
// Generic case
|
||||
db::EdgeProcessor ep (report_progress (), progress_desc ());
|
||||
ep.set_base_verbosity (base_verbosity ());
|
||||
|
|
@ -1571,7 +1575,7 @@ AsIfFlatRegion::not_with (const Region &other) const
|
|||
|
||||
|
||||
std::pair<RegionDelegate *, RegionDelegate *>
|
||||
AsIfFlatRegion::andnot_with (const Region &other) const
|
||||
AsIfFlatRegion::andnot_with (const Region &other, PropertyConstraint property_constraint) const
|
||||
{
|
||||
if (empty ()) {
|
||||
|
||||
|
|
@ -1590,6 +1594,8 @@ AsIfFlatRegion::andnot_with (const Region &other) const
|
|||
|
||||
} else {
|
||||
|
||||
// @@@ TODO: implement property constraint
|
||||
|
||||
// Generic case
|
||||
db::EdgeProcessor ep (report_progress (), progress_desc ());
|
||||
ep.set_base_verbosity (base_verbosity ());
|
||||
|
|
|
|||
|
|
@ -122,11 +122,11 @@ public:
|
|||
virtual RegionDelegate *sized (coord_type d, unsigned int mode) const;
|
||||
virtual RegionDelegate *sized (coord_type dx, coord_type dy, unsigned int mode) const;
|
||||
|
||||
virtual RegionDelegate *and_with (const Region &other) const;
|
||||
virtual RegionDelegate *not_with (const Region &other) const;
|
||||
virtual RegionDelegate *and_with (const Region &other, PropertyConstraint property_constraint) const;
|
||||
virtual RegionDelegate *not_with (const Region &other, PropertyConstraint property_constraint) const;
|
||||
virtual RegionDelegate *xor_with (const Region &other) const;
|
||||
virtual RegionDelegate *or_with (const Region &other) const;
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> andnot_with (const Region &) const;
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> andnot_with (const Region &other, PropertyConstraint property_constraint) const;
|
||||
|
||||
virtual RegionDelegate *add_in_place (const Region &other)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -699,7 +699,7 @@ DeepRegion::insert_into (db::Layout *layout, db::cell_index_type into_cell, unsi
|
|||
}
|
||||
|
||||
RegionDelegate *
|
||||
DeepRegion::and_with (const Region &other) const
|
||||
DeepRegion::and_with (const Region &other, PropertyConstraint property_constraint) const
|
||||
{
|
||||
const DeepRegion *other_deep = dynamic_cast <const DeepRegion *> (other.delegate ());
|
||||
|
||||
|
|
@ -713,17 +713,17 @@ DeepRegion::and_with (const Region &other) const
|
|||
|
||||
} else if (! other_deep) {
|
||||
|
||||
return AsIfFlatRegion::and_with (other);
|
||||
return AsIfFlatRegion::and_with (other, property_constraint);
|
||||
|
||||
} else {
|
||||
|
||||
return new DeepRegion (and_or_not_with (other_deep, true));
|
||||
return new DeepRegion (and_or_not_with (other_deep, true, property_constraint));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
DeepRegion::not_with (const Region &other) const
|
||||
DeepRegion::not_with (const Region &other, PropertyConstraint property_constraint) const
|
||||
{
|
||||
const DeepRegion *other_deep = dynamic_cast <const DeepRegion *> (other.delegate ());
|
||||
|
||||
|
|
@ -733,11 +733,11 @@ DeepRegion::not_with (const Region &other) const
|
|||
|
||||
} else if (! other_deep) {
|
||||
|
||||
return AsIfFlatRegion::not_with (other);
|
||||
return AsIfFlatRegion::not_with (other, property_constraint);
|
||||
|
||||
} else {
|
||||
|
||||
return new DeepRegion (and_or_not_with (other_deep, false));
|
||||
return new DeepRegion (and_or_not_with (other_deep, false, property_constraint));
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -750,7 +750,7 @@ DeepRegion::or_with (const Region &other) const
|
|||
}
|
||||
|
||||
std::pair<RegionDelegate *, RegionDelegate *>
|
||||
DeepRegion::andnot_with (const Region &other) const
|
||||
DeepRegion::andnot_with (const Region &other, PropertyConstraint property_constraint) const
|
||||
{
|
||||
const DeepRegion *other_deep = dynamic_cast <const DeepRegion *> (other.delegate ());
|
||||
|
||||
|
|
@ -764,39 +764,59 @@ DeepRegion::andnot_with (const Region &other) const
|
|||
|
||||
} else if (! other_deep) {
|
||||
|
||||
return AsIfFlatRegion::andnot_with (other);
|
||||
return AsIfFlatRegion::andnot_with (other, property_constraint);
|
||||
|
||||
} else {
|
||||
|
||||
std::pair<DeepLayer, DeepLayer> res = and_and_not_with (other_deep);
|
||||
std::pair<DeepLayer, DeepLayer> res = and_and_not_with (other_deep, property_constraint);
|
||||
return std::make_pair (new DeepRegion (res.first), new DeepRegion (res.second));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
DeepLayer
|
||||
DeepRegion::and_or_not_with (const DeepRegion *other, bool and_op) const
|
||||
DeepRegion::and_or_not_with (const DeepRegion *other, bool and_op, db::PropertyConstraint property_constraint) const
|
||||
{
|
||||
DeepLayer dl_out (deep_layer ().derived ());
|
||||
|
||||
db::BoolAndOrNotLocalOperation op (and_op);
|
||||
if (property_constraint == db::NoPropertyConstraint) {
|
||||
|
||||
db::local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef> proc (const_cast<db::Layout *> (&deep_layer ().layout ()), const_cast<db::Cell *> (&deep_layer ().initial_cell ()), &other->deep_layer ().layout (), &other->deep_layer ().initial_cell (), deep_layer ().breakout_cells (), other->deep_layer ().breakout_cells ());
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
proc.set_description (progress_desc ());
|
||||
proc.set_report_progress (report_progress ());
|
||||
proc.set_threads (deep_layer ().store ()->threads ());
|
||||
proc.set_area_ratio (deep_layer ().store ()->max_area_ratio ());
|
||||
proc.set_max_vertex_count (deep_layer ().store ()->max_vertex_count ());
|
||||
db::BoolAndOrNotLocalOperation op (and_op);
|
||||
|
||||
proc.run (&op, deep_layer ().layer (), other->deep_layer ().layer (), dl_out.layer ());
|
||||
db::local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef> proc (const_cast<db::Layout *> (&deep_layer ().layout ()), const_cast<db::Cell *> (&deep_layer ().initial_cell ()), &other->deep_layer ().layout (), &other->deep_layer ().initial_cell (), deep_layer ().breakout_cells (), other->deep_layer ().breakout_cells ());
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
proc.set_description (progress_desc ());
|
||||
proc.set_report_progress (report_progress ());
|
||||
proc.set_threads (deep_layer ().store ()->threads ());
|
||||
proc.set_area_ratio (deep_layer ().store ()->max_area_ratio ());
|
||||
proc.set_max_vertex_count (deep_layer ().store ()->max_vertex_count ());
|
||||
|
||||
proc.run (&op, deep_layer ().layer (), other->deep_layer ().layer (), dl_out.layer ());
|
||||
|
||||
} else {
|
||||
|
||||
db::BoolAndOrNotLocalOperationWithProperties op (and_op, &deep_layer ().layout (), &other->deep_layer ().layout (), property_constraint);
|
||||
|
||||
db::local_processor<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::PolygonRefWithProperties> proc (const_cast<db::Layout *> (&deep_layer ().layout ()), const_cast<db::Cell *> (&deep_layer ().initial_cell ()), &other->deep_layer ().layout (), &other->deep_layer ().initial_cell (), deep_layer ().breakout_cells (), other->deep_layer ().breakout_cells ());
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
proc.set_description (progress_desc ());
|
||||
proc.set_report_progress (report_progress ());
|
||||
proc.set_threads (deep_layer ().store ()->threads ());
|
||||
proc.set_area_ratio (deep_layer ().store ()->max_area_ratio ());
|
||||
proc.set_max_vertex_count (deep_layer ().store ()->max_vertex_count ());
|
||||
|
||||
proc.run (&op, deep_layer ().layer (), other->deep_layer ().layer (), dl_out.layer ());
|
||||
|
||||
}
|
||||
|
||||
return dl_out;
|
||||
}
|
||||
|
||||
std::pair<DeepLayer, DeepLayer>
|
||||
DeepRegion::and_and_not_with (const DeepRegion *other) const
|
||||
DeepRegion::and_and_not_with (const DeepRegion *other, PropertyConstraint property_constraint) const
|
||||
{
|
||||
// @@@ TODO: implement property_constraint
|
||||
|
||||
DeepLayer dl_out1 (deep_layer ().derived ());
|
||||
DeepLayer dl_out2 (deep_layer ().derived ());
|
||||
|
||||
|
|
@ -845,8 +865,8 @@ DeepRegion::xor_with (const Region &other) const
|
|||
|
||||
// Implement XOR as (A-B)+(B-A) - only this implementation
|
||||
// is compatible with the local processor scheme
|
||||
DeepLayer n1 (and_or_not_with (other_deep, false));
|
||||
DeepLayer n2 (other_deep->and_or_not_with (this, false));
|
||||
DeepLayer n1 (and_or_not_with (other_deep, false, db::NoPropertyConstraint));
|
||||
DeepLayer n2 (other_deep->and_or_not_with (this, false, db::NoPropertyConstraint));
|
||||
|
||||
n1.add_from (n2);
|
||||
return new DeepRegion (n1);
|
||||
|
|
|
|||
|
|
@ -99,11 +99,11 @@ public:
|
|||
virtual RegionDelegate *cop_to_region (db::CompoundRegionOperationNode &node);
|
||||
virtual EdgesDelegate *cop_to_edges (db::CompoundRegionOperationNode &node);
|
||||
|
||||
virtual RegionDelegate *and_with (const Region &other) const;
|
||||
virtual RegionDelegate *not_with (const Region &other) const;
|
||||
virtual RegionDelegate *and_with (const Region &other, db::PropertyConstraint property_constraint) const;
|
||||
virtual RegionDelegate *not_with (const Region &other, db::PropertyConstraint property_constraint) const;
|
||||
virtual RegionDelegate *xor_with (const Region &other) const;
|
||||
virtual RegionDelegate *or_with (const Region &other) const;
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> andnot_with (const Region &) const;
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> andnot_with (const Region &, db::PropertyConstraint property_constraint) const;
|
||||
|
||||
virtual RegionDelegate *add_in_place (const Region &other);
|
||||
virtual RegionDelegate *add (const Region &other) const;
|
||||
|
|
@ -174,8 +174,8 @@ private:
|
|||
|
||||
void init ();
|
||||
void ensure_merged_polygons_valid () const;
|
||||
DeepLayer and_or_not_with(const DeepRegion *other, bool and_op) const;
|
||||
std::pair<DeepLayer, DeepLayer> and_and_not_with (const DeepRegion *other) const;
|
||||
DeepLayer and_or_not_with(const DeepRegion *other, bool and_op, PropertyConstraint property_constraint) const;
|
||||
std::pair<DeepLayer, DeepLayer> and_and_not_with (const DeepRegion *other, PropertyConstraint property_constraint) const;
|
||||
DeepRegion *apply_filter (const PolygonFilterBase &filter) const;
|
||||
|
||||
template <class Result, class OutputContainer> OutputContainer *processed_impl (const polygon_processor<Result> &filter) const;
|
||||
|
|
|
|||
|
|
@ -98,9 +98,9 @@ public:
|
|||
virtual RegionDelegate *sized (coord_type, unsigned int) const { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *sized (coord_type, coord_type, unsigned int) const { return new EmptyRegion (); }
|
||||
|
||||
virtual RegionDelegate *and_with (const Region &) const { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *not_with (const Region &) const { return new EmptyRegion (); }
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> andnot_with (const Region &) const { return std::make_pair (new EmptyRegion (), new EmptyRegion ()); }
|
||||
virtual RegionDelegate *and_with (const Region &, db::PropertyConstraint) const { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *not_with (const Region &, db::PropertyConstraint) const { return new EmptyRegion (); }
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> andnot_with (const Region &, db::PropertyConstraint) const { return std::make_pair (new EmptyRegion (), new EmptyRegion ()); }
|
||||
virtual RegionDelegate *xor_with (const Region &other) const;
|
||||
virtual RegionDelegate *or_with (const Region &other) const;
|
||||
virtual RegionDelegate *add_in_place (const Region &other);
|
||||
|
|
|
|||
|
|
@ -1042,36 +1042,6 @@ private:
|
|||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct addressable_object_from_shape
|
||||
{
|
||||
const T *operator () (const db::Shape &shape)
|
||||
{
|
||||
typename T::tag object_tag;
|
||||
return shape.basic_ptr (object_tag);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct addressable_object_from_shape<db::NetShape>
|
||||
{
|
||||
const NetShape *operator () (const db::Shape &shape)
|
||||
{
|
||||
if (shape.type () == db::Shape::TextRef) {
|
||||
m_heap.push_back (db::NetShape (shape.text_ref ()));
|
||||
return &m_heap.back ();
|
||||
} else if (shape.type () == db::Shape::PolygonRef) {
|
||||
m_heap.push_back (db::NetShape (shape.polygon_ref ()));
|
||||
return &m_heap.back ();
|
||||
} else {
|
||||
tl_assert (false);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::list<NetShape> m_heap;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct attr_accessor
|
||||
{
|
||||
|
|
|
|||
|
|
@ -197,14 +197,12 @@ public:
|
|||
|
||||
shape_type operator() (const shape_type &s) const
|
||||
{
|
||||
// CAUTION: no property ID translation happens here (reasoning: the main use case is fake ID for net tagging)
|
||||
return shape_type (shape_reference_translator<Basic>::operator () (s), s.properties_id ());
|
||||
}
|
||||
|
||||
template <class Trans>
|
||||
shape_type operator() (const shape_type &s, const Trans &tr) const
|
||||
{
|
||||
// CAUTION: no property ID translation happens here (reasoning: the main use case is fake ID for net tagging)
|
||||
return shape_type (shape_reference_translator<Basic>::operator () (s, tr), s.properties_id ());
|
||||
}
|
||||
};
|
||||
|
|
@ -445,7 +443,7 @@ template class DB_PUBLIC local_processor_cell_context<db::Polygon, db::Text, db:
|
|||
template class DB_PUBLIC local_processor_cell_context<db::Polygon, db::Edge, db::Polygon>;
|
||||
template class DB_PUBLIC local_processor_cell_context<db::Polygon, db::Text, db::Text>;
|
||||
template class DB_PUBLIC local_processor_cell_context<db::Polygon, db::Edge, db::Edge>;
|
||||
template class DB_PUBLIC local_processor_cell_context<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::PolygonRef>;
|
||||
template class DB_PUBLIC local_processor_cell_context<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::PolygonRefWithProperties>;
|
||||
template class DB_PUBLIC local_processor_cell_context<db::PolygonRef, db::PolygonRef, db::PolygonRef>;
|
||||
template class DB_PUBLIC local_processor_cell_context<db::PolygonRef, db::Edge, db::PolygonRef>;
|
||||
template class DB_PUBLIC local_processor_cell_context<db::PolygonRef, db::PolygonRef, db::EdgePair>;
|
||||
|
|
@ -759,7 +757,7 @@ template class DB_PUBLIC local_processor_cell_contexts<db::Polygon, db::Edge, db
|
|||
template class DB_PUBLIC local_processor_cell_contexts<db::Polygon, db::Edge, db::Edge>;
|
||||
template class DB_PUBLIC local_processor_cell_contexts<db::Polygon, db::Text, db::Polygon>;
|
||||
template class DB_PUBLIC local_processor_cell_contexts<db::Polygon, db::Text, db::Text>;
|
||||
template class DB_PUBLIC local_processor_cell_contexts<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::PolygonRef>;
|
||||
template class DB_PUBLIC local_processor_cell_contexts<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::PolygonRefWithProperties>;
|
||||
template class DB_PUBLIC local_processor_cell_contexts<db::PolygonRef, db::PolygonRef, db::PolygonRef>;
|
||||
template class DB_PUBLIC local_processor_cell_contexts<db::PolygonRef, db::Edge, db::PolygonRef>;
|
||||
template class DB_PUBLIC local_processor_cell_contexts<db::PolygonRef, db::PolygonRef, db::EdgePair>;
|
||||
|
|
@ -1064,6 +1062,7 @@ private:
|
|||
void add_shapes_from_intruder_inst (unsigned int id1, const db::Cell &intruder_cell, const db::ICplxTrans &tn, unsigned int /*inst_id*/, const db::Box ®ion)
|
||||
{
|
||||
db::shape_reference_translator<TI> rt (mp_subject_layout);
|
||||
db::shape_to_object<TI> s2o;
|
||||
|
||||
// Look up all shapes from the intruder instance which interact with the subject shape
|
||||
// (given through region)
|
||||
|
|
@ -1074,7 +1073,7 @@ private:
|
|||
|
||||
// NOTE: we intentionally rewrite to the *subject* layout - this way polygon refs in the context come from the
|
||||
// subject, not from the intruder.
|
||||
TI ref2 = rt (*si.shape ().basic_ptr (typename TI::tag ()), tn * si.trans ());
|
||||
TI ref2 = rt (s2o (si.shape ()), tn * si.trans ());
|
||||
|
||||
// reuse the same id for shapes from the same instance -> this avoid duplicates with different IDs on
|
||||
// the intruder side.
|
||||
|
|
@ -1335,7 +1334,7 @@ template class DB_PUBLIC local_processor_context_computation_task<db::Polygon, d
|
|||
template class DB_PUBLIC local_processor_context_computation_task<db::Polygon, db::Text, db::Text>;
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::Polygon, db::Edge, db::Polygon>;
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::Polygon, db::Edge, db::Edge>;
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::PolygonRef>;
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::PolygonRefWithProperties>;
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRef, db::PolygonRef, db::PolygonRef>;
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRef, db::TextRef, db::TextRef>;
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRef, db::TextRef, db::PolygonRef>;
|
||||
|
|
@ -1398,7 +1397,7 @@ template class DB_PUBLIC local_processor_result_computation_task<db::Polygon, db
|
|||
template class DB_PUBLIC local_processor_result_computation_task<db::Polygon, db::Text, db::Text>;
|
||||
template class DB_PUBLIC local_processor_result_computation_task<db::Polygon, db::Edge, db::Polygon>;
|
||||
template class DB_PUBLIC local_processor_result_computation_task<db::Polygon, db::Edge, db::Edge>;
|
||||
template class DB_PUBLIC local_processor_result_computation_task<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::PolygonRef>;
|
||||
template class DB_PUBLIC local_processor_result_computation_task<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::PolygonRefWithProperties>;
|
||||
template class DB_PUBLIC local_processor_result_computation_task<db::PolygonRef, db::PolygonRef, db::PolygonRef>;
|
||||
template class DB_PUBLIC local_processor_result_computation_task<db::PolygonRef, db::Edge, db::PolygonRef>;
|
||||
template class DB_PUBLIC local_processor_result_computation_task<db::PolygonRef, db::PolygonRef, db::EdgePair>;
|
||||
|
|
@ -1712,6 +1711,7 @@ void local_processor<TS, TI, TR>::compute_contexts (local_processor_contexts<TS,
|
|||
// TODO: can we shortcut this if interactions is empty?
|
||||
{
|
||||
db::box_scanner2<db::CellInstArray, int, TI, int> scanner;
|
||||
db::addressable_object_from_shape<TI> heap;
|
||||
interaction_registration_inst2shape<TS, TI, TR> rec (mp_subject_layout, contexts.subject_layer (), dist, &interactions);
|
||||
|
||||
for (db::Cell::const_iterator i = subject_cell->begin (); !i.at_end (); ++i) {
|
||||
|
|
@ -1728,7 +1728,7 @@ void local_processor<TS, TI, TR>::compute_contexts (local_processor_contexts<TS,
|
|||
|
||||
for (std::map<unsigned int, const db::Shapes *>::const_iterator im = intruder_shapes.begin (); im != intruder_shapes.end (); ++im) {
|
||||
for (db::Shapes::shape_iterator i = im->second->begin (shape_flags<TI> ()); !i.at_end (); ++i) {
|
||||
scanner.insert2 (i->basic_ptr (typename TI::tag ()), im->first);
|
||||
scanner.insert2 (heap (*i), im->first);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1880,11 +1880,12 @@ struct scan_shape2shape_same_layer
|
|||
operator () (const db::Shapes *subject_shapes, unsigned int subject_id0, const std::set<TI> &intruders, unsigned int intruder_layer_index, shape_interactions<TS, TI> &interactions, db::Coord dist) const
|
||||
{
|
||||
db::box_scanner2<TS, int, TI, int> scanner;
|
||||
db::addressable_object_from_shape<TS> heap;
|
||||
interaction_registration_shape1<TS, TI> rec (&interactions, intruder_layer_index);
|
||||
|
||||
unsigned int id = subject_id0;
|
||||
for (db::Shapes::shape_iterator i = subject_shapes->begin (shape_flags<TS> ()); !i.at_end (); ++i) {
|
||||
const TS *ref = i->basic_ptr (typename TS::tag ());
|
||||
const TS *ref = heap (*i);
|
||||
scanner.insert1 (ref, id++);
|
||||
}
|
||||
|
||||
|
|
@ -1904,12 +1905,12 @@ struct scan_shape2shape_same_layer<T, T>
|
|||
operator () (const db::Shapes *subject_shapes, unsigned int subject_id0, const std::set<T> &intruders, unsigned int intruder_layer, shape_interactions<T, T> &interactions, db::Coord dist) const
|
||||
{
|
||||
db::box_scanner<T, int> scanner;
|
||||
db::addressable_object_from_shape<T> heap;
|
||||
interaction_registration_shape1<T, T> rec (&interactions, intruder_layer);
|
||||
|
||||
unsigned int id = subject_id0;
|
||||
for (db::Shapes::shape_iterator i = subject_shapes->begin (shape_flags<T> ()); !i.at_end (); ++i) {
|
||||
const T *ref = i->basic_ptr (typename T::tag ());
|
||||
scanner.insert (ref, id++);
|
||||
scanner.insert (heap (*i), id++);
|
||||
}
|
||||
|
||||
// TODO: can we confine this search to the subject's (sized) bounding box?
|
||||
|
|
@ -1928,12 +1929,13 @@ struct scan_shape2shape_different_layers
|
|||
operator () (db::Layout *layout, const db::Shapes *subject_shapes, const db::Shapes *intruder_shapes, unsigned int subject_id0, const std::set<TI> *intruders, unsigned int intruder_layer_index, shape_interactions<TS, TI> &interactions, db::Coord dist) const
|
||||
{
|
||||
db::box_scanner2<TS, int, TI, int> scanner;
|
||||
db::addressable_object_from_shape<TS> sheap;
|
||||
db::addressable_object_from_shape<TI> iheap;
|
||||
interaction_registration_shape2shape<TS, TI> rec (layout, &interactions, intruder_layer_index);
|
||||
|
||||
unsigned int id = subject_id0;
|
||||
for (db::Shapes::shape_iterator i = subject_shapes->begin (shape_flags<TS> ()); !i.at_end (); ++i, ++id) {
|
||||
const TS *ref = i->basic_ptr (typename TS::tag ());
|
||||
scanner.insert1 (ref, id);
|
||||
scanner.insert1 (sheap (*i), id);
|
||||
}
|
||||
|
||||
// TODO: can we confine this search to the subject's (sized) bounding box?
|
||||
|
|
@ -1952,7 +1954,7 @@ struct scan_shape2shape_different_layers
|
|||
unsigned int id = subject_id0;
|
||||
for (db::Shapes::shape_iterator i = intruder_shapes->begin (shape_flags<TI> ()); !i.at_end (); ++i, ++id) {
|
||||
unsigned int iid = interactions.next_id ();
|
||||
scanner.insert2 (i->basic_ptr (typename TI::tag ()), iid);
|
||||
scanner.insert2 (iheap (*i), iid);
|
||||
rec.same (id, iid);
|
||||
}
|
||||
|
||||
|
|
@ -1960,7 +1962,7 @@ struct scan_shape2shape_different_layers
|
|||
|
||||
// TODO: can we confine this search to the subject's (sized) bounding box?
|
||||
for (db::Shapes::shape_iterator i = intruder_shapes->begin (shape_flags<TI> ()); !i.at_end (); ++i) {
|
||||
scanner.insert2 (i->basic_ptr (typename TI::tag ()), interactions.next_id ());
|
||||
scanner.insert2 (iheap (*i), interactions.next_id ());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1976,6 +1978,7 @@ void
|
|||
local_processor<TS, TI, TR>::compute_local_cell (const db::local_processor_contexts<TS, TI, TR> &contexts, db::Cell *subject_cell, const db::Cell *intruder_cell, const local_operation<TS, TI, TR> *op, const typename local_processor_cell_contexts<TS, TI, TR>::context_key_type &intruders, std::vector<std::unordered_set<TR> > &result) const
|
||||
{
|
||||
const db::Shapes *subject_shapes = &subject_cell->shapes (contexts.subject_layer ());
|
||||
db::shape_to_object<TS> s2o;
|
||||
|
||||
shape_interactions<TS, TI> interactions;
|
||||
|
||||
|
|
@ -1990,8 +1993,7 @@ local_processor<TS, TI, TR>::compute_local_cell (const db::local_processor_conte
|
|||
}
|
||||
|
||||
if (op->on_empty_intruder_hint () != OnEmptyIntruderHint::Drop) {
|
||||
const TS *ref = i->basic_ptr (typename TS::tag ());
|
||||
interactions.add_subject (id, *ref);
|
||||
interactions.add_subject (id, s2o (*i));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -2035,11 +2037,12 @@ local_processor<TS, TI, TR>::compute_local_cell (const db::local_processor_conte
|
|||
if (! subject_shapes->empty () && ! ((! intruder_cell || intruder_cell->begin ().at_end ()) && intruders.first.empty ())) {
|
||||
|
||||
db::box_scanner2<TS, int, db::CellInstArray, int> scanner;
|
||||
db::addressable_object_from_shape<TS> heap;
|
||||
interaction_registration_shape2inst<TS, TI> rec (mp_subject_layout, mp_intruder_layout, ail, il_index, op->dist (), &interactions);
|
||||
|
||||
unsigned int id = subject_id0;
|
||||
for (db::Shapes::shape_iterator i = subject_shapes->begin (shape_flags<TS> ()); !i.at_end (); ++i) {
|
||||
scanner.insert1 (i->basic_ptr (typename TS::tag ()), id++);
|
||||
scanner.insert1 (heap (*i), id++);
|
||||
}
|
||||
|
||||
unsigned int inst_id = 0;
|
||||
|
|
@ -2414,7 +2417,7 @@ template class DB_PUBLIC local_processor<db::Polygon, db::Text, db::Polygon>;
|
|||
template class DB_PUBLIC local_processor<db::Polygon, db::Text, db::Text>;
|
||||
template class DB_PUBLIC local_processor<db::Polygon, db::Edge, db::Polygon>;
|
||||
template class DB_PUBLIC local_processor<db::Polygon, db::Edge, db::Edge>;
|
||||
template class DB_PUBLIC local_processor<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::PolygonRef>;
|
||||
template class DB_PUBLIC local_processor<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::PolygonRefWithProperties>;
|
||||
template class DB_PUBLIC local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef>;
|
||||
template class DB_PUBLIC local_processor<db::PolygonRef, db::Edge, db::PolygonRef>;
|
||||
template class DB_PUBLIC local_processor<db::PolygonRef, db::Edge, db::Edge>;
|
||||
|
|
|
|||
|
|
@ -29,10 +29,12 @@
|
|||
#include "dbPolygonTools.h"
|
||||
#include "dbLocalOperationUtils.h"
|
||||
#include "dbEdgeBoolean.h"
|
||||
#include "dbLayoutUtils.h"
|
||||
#include "tlLog.h"
|
||||
#include "tlTimer.h"
|
||||
#include "tlInternational.h"
|
||||
#include "tlProgress.h"
|
||||
#include "tlSList.h"
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
|
@ -92,7 +94,7 @@ template class DB_PUBLIC local_operation<db::Polygon, db::Text, db::Polygon>;
|
|||
template class DB_PUBLIC local_operation<db::Polygon, db::Text, db::Text>;
|
||||
template class DB_PUBLIC local_operation<db::Polygon, db::Edge, db::Polygon>;
|
||||
template class DB_PUBLIC local_operation<db::Polygon, db::Edge, db::Edge>;
|
||||
template class DB_PUBLIC local_operation<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::PolygonRef>;
|
||||
template class DB_PUBLIC local_operation<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::PolygonRefWithProperties>;
|
||||
template class DB_PUBLIC local_operation<db::PolygonRef, db::PolygonRef, db::PolygonRef>;
|
||||
template class DB_PUBLIC local_operation<db::PolygonRef, db::Text, db::PolygonRef>;
|
||||
template class DB_PUBLIC local_operation<db::PolygonRef, db::TextRef, db::PolygonRef>;
|
||||
|
|
@ -188,6 +190,127 @@ BoolAndOrNotLocalOperation::do_compute_local (db::Layout *layout, const shape_in
|
|||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
// BoolAndOrNotLocalOperationWithProperties implementation
|
||||
|
||||
BoolAndOrNotLocalOperationWithProperties::BoolAndOrNotLocalOperationWithProperties (bool is_and, const db::Layout *subject_layout, const db::Layout *intruder_layout, db::PropertyConstraint property_constraint)
|
||||
: m_is_and (is_and), m_property_constraint (property_constraint), mp_subject_layout (subject_layout), mp_intruder_layout (intruder_layout)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
OnEmptyIntruderHint
|
||||
BoolAndOrNotLocalOperationWithProperties::on_empty_intruder_hint () const
|
||||
{
|
||||
return m_is_and ? Drop : Copy;
|
||||
}
|
||||
|
||||
std::string
|
||||
BoolAndOrNotLocalOperationWithProperties::description () const
|
||||
{
|
||||
return m_is_and ? tl::to_string (tr ("AND operation")) : tl::to_string (tr ("NOT operation"));
|
||||
}
|
||||
|
||||
void
|
||||
BoolAndOrNotLocalOperationWithProperties::do_compute_local (db::Layout *layout, const shape_interactions<db::PolygonRefWithProperties, db::PolygonRefWithProperties> &interactions, std::vector<std::unordered_set<db::PolygonRefWithProperties> > &results, size_t max_vertex_count, double area_ratio) const
|
||||
{
|
||||
db::PropertyMapper pms (*layout, *mp_subject_layout);
|
||||
db::PropertyMapper pmi (*layout, *mp_intruder_layout);
|
||||
|
||||
// @@@ TODO: implement different property constraint etc.
|
||||
|
||||
tl_assert (results.size () == 1);
|
||||
std::unordered_set<db::PolygonRefWithProperties> &result = results.front ();
|
||||
|
||||
db::EdgeProcessor ep;
|
||||
|
||||
std::map<db::properties_id_type, std::pair<tl::slist<db::PolygonRef>, std::set<db::PolygonRef> > > by_prop_id;
|
||||
|
||||
for (shape_interactions<db::PolygonRefWithProperties, db::PolygonRefWithProperties>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
|
||||
const db::PolygonRefWithProperties &subject = interactions.subject_shape (i->first);
|
||||
|
||||
if (i->second.empty ()) {
|
||||
|
||||
if (! m_is_and) {
|
||||
result.insert (db::PolygonRefWithProperties (subject, pms (subject.properties_id ())));
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
db::properties_id_type prop_id_s = (m_property_constraint != db::NoPropertyConstraint ? pms (subject.properties_id ()) : 0);
|
||||
|
||||
std::pair<tl::slist<db::PolygonRef>, std::set<db::PolygonRef> > &shapes_by_prop = by_prop_id [prop_id_s];
|
||||
shapes_by_prop.first.push_front (subject);
|
||||
|
||||
for (shape_interactions<db::PolygonRefWithProperties, db::PolygonRefWithProperties>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
const db::PolygonRefWithProperties &intruder = interactions.intruder_shape (*j).second;
|
||||
db::properties_id_type prop_id_i = (m_property_constraint != db::NoPropertyConstraint ? pmi (intruder.properties_id ()) : 0);
|
||||
if ((prop_id_i != prop_id_s) == (m_property_constraint == db::DifferentPropertiesConstraint)) {
|
||||
shapes_by_prop.second.insert (intruder);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (auto p2s = by_prop_id.begin (); p2s != by_prop_id.end (); ++p2s) {
|
||||
|
||||
ep.clear ();
|
||||
size_t p1 = 0, p2 = 1;
|
||||
|
||||
const std::set<db::PolygonRef> &others = p2s->second.second;
|
||||
db::properties_id_type prop_id = p2s->first;
|
||||
|
||||
for (auto s = p2s->second.first.begin (); s != p2s->second.first.end (); ++s) {
|
||||
|
||||
const db::PolygonRef &subject = *s;
|
||||
if (others.find (subject) != others.end ()) {
|
||||
if (m_is_and) {
|
||||
result.insert (db::PolygonRefWithProperties (subject, prop_id));
|
||||
}
|
||||
} else if (others.empty ()) {
|
||||
// shortcut (not: keep, and: drop)
|
||||
if (! m_is_and) {
|
||||
result.insert (db::PolygonRefWithProperties (subject, prop_id));
|
||||
}
|
||||
} else {
|
||||
for (db::PolygonRef::polygon_edge_iterator e = subject.begin_edge (); ! e.at_end(); ++e) {
|
||||
ep.insert (*e, p1);
|
||||
}
|
||||
p1 += 2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (! others.empty () && p1 > 0) {
|
||||
|
||||
for (std::set<db::PolygonRef>::const_iterator o = others.begin (); o != others.end (); ++o) {
|
||||
for (db::PolygonRef::polygon_edge_iterator e = o->begin_edge (); ! e.at_end(); ++e) {
|
||||
ep.insert (*e, p2);
|
||||
}
|
||||
p2 += 2;
|
||||
}
|
||||
|
||||
std::unordered_set<db::PolygonRef> result_wo_props;
|
||||
|
||||
db::BooleanOp op (m_is_and ? db::BooleanOp::And : db::BooleanOp::ANotB);
|
||||
db::PolygonRefGenerator pr (layout, result_wo_props);
|
||||
db::PolygonSplitter splitter (pr, area_ratio, max_vertex_count);
|
||||
db::PolygonGenerator pg (splitter, true, true);
|
||||
ep.set_base_verbosity (50);
|
||||
ep.process (pg, op);
|
||||
|
||||
for (auto r = result_wo_props.begin (); r != result_wo_props.end (); ++r) {
|
||||
result.insert (db::PolygonRefWithProperties (*r, prop_id));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
// TwoBoolAndNotLocalOperation implementation
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "dbLayout.h"
|
||||
#include "dbEdgeBoolean.h"
|
||||
#include "dbEdgeProcessor.h"
|
||||
#include "dbPropertyConstraint.h"
|
||||
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
|
@ -146,6 +147,25 @@ private:
|
|||
bool m_is_and;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Implements a boolean AND or NOT operation
|
||||
*/
|
||||
class DB_PUBLIC BoolAndOrNotLocalOperationWithProperties
|
||||
: public local_operation<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::PolygonRefWithProperties>
|
||||
{
|
||||
public:
|
||||
BoolAndOrNotLocalOperationWithProperties (bool is_and, const db::Layout *subject_layout, const db::Layout *intruder_layout, db::PropertyConstraint property_constraint);
|
||||
|
||||
virtual void do_compute_local (db::Layout *layout, const shape_interactions<db::PolygonRefWithProperties, db::PolygonRefWithProperties> &interactions, std::vector<std::unordered_set<db::PolygonRefWithProperties> > &result, size_t max_vertex_count, double area_ratio) const;
|
||||
virtual OnEmptyIntruderHint on_empty_intruder_hint () const;
|
||||
virtual std::string description () const;
|
||||
|
||||
private:
|
||||
bool m_is_and;
|
||||
db::PropertyConstraint m_property_constraint;
|
||||
const db::Layout *mp_subject_layout, *mp_intruder_layout;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Implements a boolean AND plus NOT operation
|
||||
*
|
||||
|
|
|
|||
|
|
@ -27,6 +27,9 @@
|
|||
#include "dbText.h"
|
||||
#include "dbShapeRepository.h"
|
||||
#include "dbBoxConvert.h"
|
||||
#include "dbShape.h"
|
||||
#include "dbShapeFlags.h" // for addressable_object_from_shape
|
||||
#include "tlSList.h"
|
||||
|
||||
namespace db {
|
||||
|
||||
|
|
@ -172,6 +175,28 @@ struct box_convert<db::NetShape>
|
|||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct addressable_object_from_shape<db::NetShape>
|
||||
{
|
||||
typedef db::NetShape value_type;
|
||||
|
||||
const value_type *operator () (const db::Shape &shape)
|
||||
{
|
||||
if (shape.type () == db::Shape::TextRef) {
|
||||
m_heap.push_back (db::NetShape (shape.text_ref ()));
|
||||
return &m_heap.back ();
|
||||
} else if (shape.type () == db::Shape::PolygonRef) {
|
||||
m_heap.push_back (db::NetShape (shape.polygon_ref ()));
|
||||
return &m_heap.back ();
|
||||
} else {
|
||||
tl_assert (false);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
tl::slist<NetShape> m_heap;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -0,0 +1,57 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2023 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef HDR_dbPropertyConstraint
|
||||
#define HDR_dbPropertyConstraint
|
||||
|
||||
#include "dbCommon.h"
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Specifies a property constraint for some operations
|
||||
*/
|
||||
enum PropertyConstraint
|
||||
{
|
||||
/**
|
||||
* @brief No constraint, shapes are processed regardless of their properties
|
||||
*/
|
||||
NoPropertyConstraint = 0,
|
||||
|
||||
/**
|
||||
* @brief Shapes are processed if their properties are the same
|
||||
*/
|
||||
SamePropertiesConstraint = 1,
|
||||
|
||||
/**
|
||||
* @brief Shapes are processed if their properties are different
|
||||
*/
|
||||
DifferentPropertiesConstraint = 2
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1036,7 +1036,15 @@ public:
|
|||
*/
|
||||
Region operator& (const Region &other) const
|
||||
{
|
||||
return Region (mp_delegate->and_with (other));
|
||||
return Region (mp_delegate->and_with (other, db::NoPropertyConstraint));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Boolean AND operator with options
|
||||
*/
|
||||
Region bool_and (const Region &other, PropertyConstraint prop_constraint = db::NoPropertyConstraint) const
|
||||
{
|
||||
return Region (mp_delegate->and_with (other, prop_constraint));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1047,7 +1055,19 @@ public:
|
|||
*/
|
||||
Region &operator&= (const Region &other)
|
||||
{
|
||||
set_delegate (mp_delegate->and_with (other));
|
||||
set_delegate (mp_delegate->and_with (other, db::NoPropertyConstraint));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief In-place boolean AND operator with options
|
||||
*
|
||||
* This method does not necessarily merge the region. To ensure the region
|
||||
* is merged, call merge afterwards.
|
||||
*/
|
||||
Region &bool_and_with (const Region &other, PropertyConstraint prop_constraint = db::NoPropertyConstraint)
|
||||
{
|
||||
set_delegate (mp_delegate->and_with (other, prop_constraint));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -1056,7 +1076,15 @@ public:
|
|||
*/
|
||||
Region operator- (const Region &other) const
|
||||
{
|
||||
return Region (mp_delegate->not_with (other));
|
||||
return Region (mp_delegate->not_with (other, db::NoPropertyConstraint));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Boolean NOT operator with options
|
||||
*/
|
||||
Region bool_not (const Region &other, PropertyConstraint prop_constraint = db::NoPropertyConstraint) const
|
||||
{
|
||||
return Region (mp_delegate->not_with (other, prop_constraint));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1067,7 +1095,19 @@ public:
|
|||
*/
|
||||
Region &operator-= (const Region &other)
|
||||
{
|
||||
set_delegate (mp_delegate->not_with (other));
|
||||
set_delegate (mp_delegate->not_with (other, db::NoPropertyConstraint));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief In-place boolean NOT operator with options
|
||||
*
|
||||
* This method does not necessarily merge the region. To ensure the region
|
||||
* is merged, call merge afterwards.
|
||||
*/
|
||||
Region bool_not_with (const Region &other, PropertyConstraint prop_constraint = db::NoPropertyConstraint)
|
||||
{
|
||||
set_delegate (mp_delegate->not_with (other, prop_constraint));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -1134,9 +1174,9 @@ public:
|
|||
*
|
||||
* The first region delivered will be the AND result, the second one the NOT result.
|
||||
*/
|
||||
std::pair<Region, Region> andnot (const Region &other) const
|
||||
std::pair<Region, Region> andnot (const Region &other, PropertyConstraint prop_constraint = db::NoPropertyConstraint) const
|
||||
{
|
||||
std::pair<RegionDelegate *, RegionDelegate *> res = mp_delegate->andnot_with (other);
|
||||
std::pair<RegionDelegate *, RegionDelegate *> res = mp_delegate->andnot_with (other, prop_constraint);
|
||||
return std::make_pair (Region (res.first), Region (res.second));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -273,13 +273,13 @@ public:
|
|||
virtual RegionDelegate *sized (coord_type d, unsigned int mode) const = 0;
|
||||
virtual RegionDelegate *sized (coord_type dx, coord_type dy, unsigned int mode) const = 0;
|
||||
|
||||
virtual RegionDelegate *and_with (const Region &other) const = 0;
|
||||
virtual RegionDelegate *not_with (const Region &other) const = 0;
|
||||
virtual RegionDelegate *and_with (const Region &other, PropertyConstraint prop_constraint) const = 0;
|
||||
virtual RegionDelegate *not_with (const Region &other, PropertyConstraint prop_constraint) const = 0;
|
||||
virtual RegionDelegate *xor_with (const Region &other) const = 0;
|
||||
virtual RegionDelegate *or_with (const Region &other) const = 0;
|
||||
virtual RegionDelegate *add_in_place (const Region &other) = 0;
|
||||
virtual RegionDelegate *add (const Region &other) const = 0;
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> andnot_with (const Region &other) const = 0;
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> andnot_with (const Region &other, PropertyConstraint prop_constraint) const = 0;
|
||||
|
||||
virtual RegionDelegate *selected_outside (const Region &other) const = 0;
|
||||
virtual RegionDelegate *selected_not_outside (const Region &other) const = 0;
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include "dbLocalOperation.h"
|
||||
#include "dbEdgeProcessor.h"
|
||||
#include "dbRegionCheckUtils.h"
|
||||
#include "dbPropertyConstraint.h"
|
||||
|
||||
#include <vector>
|
||||
#include <unordered_set>
|
||||
|
|
|
|||
|
|
@ -26,71 +26,134 @@
|
|||
|
||||
#include "dbCommon.h"
|
||||
#include "dbShapes.h"
|
||||
#include "tlSList.h"
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
||||
template <class T> unsigned int shape_flags ();
|
||||
template <class T> unsigned int shape_flags_pure ();
|
||||
|
||||
template <> inline unsigned int shape_flags<db::PolygonRef> () { return 1 << db::ShapeIterator::PolygonRef; }
|
||||
template <> inline unsigned int shape_flags_pure<db::PolygonRef> () { return 1 << db::ShapeIterator::PolygonRef; }
|
||||
|
||||
template <> inline unsigned int shape_flags<db::TextRef> () { return 1 << db::ShapeIterator::TextRef; }
|
||||
template <> inline unsigned int shape_flags_pure<db::TextRef> () { return 1 << db::ShapeIterator::TextRef; }
|
||||
|
||||
template <> inline unsigned int shape_flags<db::Box> () { return db::ShapeIterator::Boxes; }
|
||||
template <> inline unsigned int shape_flags_pure<db::Box> () { return 1 << db::ShapeIterator::Box; }
|
||||
|
||||
template <> inline unsigned int shape_flags<db::Path> () { return db::ShapeIterator::Paths; }
|
||||
template <> inline unsigned int shape_flags_pure<db::Path> () { return 1 << db::ShapeIterator::Path; }
|
||||
|
||||
template <> inline unsigned int shape_flags<db::Polygon> () { return db::ShapeIterator::Polygons; }
|
||||
template <> inline unsigned int shape_flags_pure<db::Polygon> () { return 1 << db::ShapeIterator::Polygon; }
|
||||
|
||||
template <> inline unsigned int shape_flags<db::Edge> () { return db::ShapeIterator::Edges; }
|
||||
template <> inline unsigned int shape_flags_pure<db::Edge> () { return 1 << db::ShapeIterator::Edge; }
|
||||
|
||||
template <> inline unsigned int shape_flags<db::EdgePair> () { return db::ShapeIterator::EdgePairs; }
|
||||
template <> inline unsigned int shape_flags_pure<db::EdgePair> () { return 1 << db::ShapeIterator::EdgePair; }
|
||||
|
||||
template <> inline unsigned int shape_flags<db::Text> () { return db::ShapeIterator::Texts; }
|
||||
template <> inline unsigned int shape_flags_pure<db::Text> () { return 1 << db::ShapeIterator::Text; }
|
||||
|
||||
template <> inline unsigned int shape_flags<db::PolygonRefWithProperties> () { return db::ShapeIterator::Properties | shape_flags_pure<db::PolygonRef> (); }
|
||||
template <> inline unsigned int shape_flags_pure<db::PolygonRefWithProperties> () { return db::ShapeIterator::Properties | shape_flags_pure<db::PolygonRef> (); }
|
||||
|
||||
template <> inline unsigned int shape_flags<db::TextRefWithProperties> () { return db::ShapeIterator::Properties | shape_flags_pure<db::TextRef> (); }
|
||||
template <> inline unsigned int shape_flags_pure<db::TextRefWithProperties> () { return db::ShapeIterator::Properties | shape_flags_pure<db::TextRef> (); }
|
||||
|
||||
template <> inline unsigned int shape_flags<db::BoxWithProperties> () { return db::ShapeIterator::Properties | shape_flags_pure<db::Box> (); }
|
||||
template <> inline unsigned int shape_flags_pure<db::BoxWithProperties> () { return db::ShapeIterator::Properties | shape_flags_pure<db::Box> (); }
|
||||
|
||||
template <> inline unsigned int shape_flags<db::PathWithProperties> () { return db::ShapeIterator::Properties | shape_flags_pure<db::Path> (); }
|
||||
template <> inline unsigned int shape_flags_pure<db::PathWithProperties> () { return db::ShapeIterator::Properties | shape_flags_pure<db::Path> (); }
|
||||
|
||||
template <> inline unsigned int shape_flags<db::PolygonWithProperties> () { return db::ShapeIterator::Properties | shape_flags_pure<db::Polygon> (); }
|
||||
template <> inline unsigned int shape_flags_pure<db::PolygonWithProperties> () { return db::ShapeIterator::Properties | shape_flags_pure<db::Polygon> (); }
|
||||
|
||||
template <> inline unsigned int shape_flags<db::EdgeWithProperties> () { return db::ShapeIterator::Properties | shape_flags_pure<db::Edge> (); }
|
||||
template <> inline unsigned int shape_flags_pure<db::EdgeWithProperties> () { return db::ShapeIterator::Properties | shape_flags_pure<db::Edge> (); }
|
||||
|
||||
template <> inline unsigned int shape_flags<db::EdgePairWithProperties> () { return db::ShapeIterator::Properties | shape_flags_pure<db::EdgePair> (); }
|
||||
template <> inline unsigned int shape_flags_pure<db::EdgePairWithProperties> () { return db::ShapeIterator::Properties | shape_flags_pure<db::EdgePair> (); }
|
||||
|
||||
template <> inline unsigned int shape_flags<db::TextWithProperties> () { return db::ShapeIterator::Properties | shape_flags_pure<db::Text> (); }
|
||||
template <> inline unsigned int shape_flags_pure<db::TextWithProperties> () { return db::ShapeIterator::Properties | shape_flags_pure<db::Text> (); }
|
||||
|
||||
template <class T>
|
||||
struct DB_PUBLIC shape_to_object
|
||||
struct shape_flags_traits
|
||||
{
|
||||
void set (const db::Shape &) { }
|
||||
const T *get (const db::Shape &s) const { return s.basic_ptr (typename T::tag ()); }
|
||||
static unsigned int generic () { return 0; }
|
||||
static unsigned int pure () { return 0; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct shape_flags_traits<db::PolygonRef>
|
||||
{
|
||||
static unsigned int generic () { return 1 << db::ShapeIterator::PolygonRef; }
|
||||
static unsigned int pure () { return 1 << db::ShapeIterator::PolygonRef; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct DB_PUBLIC shape_to_object<db::Polygon>
|
||||
struct shape_flags_traits<db::TextRef>
|
||||
{
|
||||
static unsigned int generic () { return 1 << db::ShapeIterator::TextRef; }
|
||||
static unsigned int pure () { return 1 << db::ShapeIterator::TextRef; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct shape_flags_traits<db::Box>
|
||||
{
|
||||
static unsigned int generic () { return db::ShapeIterator::Boxes; }
|
||||
static unsigned int pure () { return 1 << db::ShapeIterator::Box; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct shape_flags_traits<db::Path>
|
||||
{
|
||||
static unsigned int generic () { return db::ShapeIterator::Paths; }
|
||||
static unsigned int pure () { return 1 << db::ShapeIterator::Path; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct shape_flags_traits<db::Polygon>
|
||||
{
|
||||
static unsigned int generic () { return db::ShapeIterator::Polygons; }
|
||||
static unsigned int pure () { return 1 << db::ShapeIterator::Polygon; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct shape_flags_traits<db::SimplePolygon>
|
||||
{
|
||||
static unsigned int generic () { return db::ShapeIterator::Polygons; }
|
||||
static unsigned int pure () { return 1 << db::ShapeIterator::SimplePolygon; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct shape_flags_traits<db::Edge>
|
||||
{
|
||||
static unsigned int generic () { return db::ShapeIterator::Edges; }
|
||||
static unsigned int pure () { return 1 << db::ShapeIterator::Edge; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct shape_flags_traits<db::EdgePair>
|
||||
{
|
||||
static unsigned int generic () { return db::ShapeIterator::EdgePairs; }
|
||||
static unsigned int pure () { return 1 << db::ShapeIterator::EdgePair; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct shape_flags_traits<db::Text>
|
||||
{
|
||||
static unsigned int generic () { return db::ShapeIterator::Texts; }
|
||||
static unsigned int pure () { return 1 << db::ShapeIterator::Text; }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct shape_flags_traits<db::object_with_properties<T> >
|
||||
{
|
||||
static unsigned int generic () { return shape_flags_traits<T>::generic (); }
|
||||
static unsigned int pure () { return shape_flags_traits<T>::pure (); }
|
||||
};
|
||||
|
||||
template <class T> unsigned int shape_flags () { return shape_flags_traits<T>::generic (); }
|
||||
template <class T> unsigned int shape_flags_pure () { return shape_flags_traits<T>::pure (); }
|
||||
|
||||
/**
|
||||
* @brief Converter helpers for changing a shape to an object of a specific type
|
||||
*
|
||||
* These converters a volatile. The pointer delivered is not valid after the next object has
|
||||
* been retrieved.
|
||||
*/
|
||||
|
||||
template <class T>
|
||||
struct DB_PUBLIC shape_to_object_impl
|
||||
{
|
||||
typedef T value_type;
|
||||
|
||||
void set (const db::Shape &) { }
|
||||
const value_type *get (const db::Shape &s) const { return s.basic_ptr (typename T::tag ()); }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct DB_PUBLIC shape_to_object_impl<db::object_with_properties<T> >
|
||||
{
|
||||
typedef db::object_with_properties<T> value_type;
|
||||
|
||||
void set (const db::Shape &s)
|
||||
{
|
||||
if (! s.has_prop_id ()) {
|
||||
m_shape = value_type (*s.basic_ptr (typename T::tag ()), 0);
|
||||
}
|
||||
}
|
||||
|
||||
const value_type *get (const db::Shape &s) const
|
||||
{
|
||||
if (! s.has_prop_id ()) {
|
||||
return &m_shape;
|
||||
} else {
|
||||
return s.basic_ptr (typename value_type::tag ());
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
value_type m_shape;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct DB_PUBLIC shape_to_object_impl<db::Polygon>
|
||||
{
|
||||
typedef db::Polygon value_type;
|
||||
|
||||
|
|
@ -102,7 +165,27 @@ private:
|
|||
};
|
||||
|
||||
template <>
|
||||
struct DB_PUBLIC shape_to_object<db::SimplePolygon>
|
||||
struct DB_PUBLIC shape_to_object_impl<db::PolygonWithProperties>
|
||||
{
|
||||
typedef db::PolygonWithProperties value_type;
|
||||
|
||||
void set (const db::Shape &s)
|
||||
{
|
||||
s.polygon (m_shape);
|
||||
m_shape.properties_id (s.prop_id ());
|
||||
}
|
||||
|
||||
const value_type *get (const db::Shape &) const
|
||||
{
|
||||
return &m_shape;
|
||||
}
|
||||
|
||||
private:
|
||||
value_type m_shape;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct DB_PUBLIC shape_to_object_impl<db::SimplePolygon>
|
||||
{
|
||||
typedef db::SimplePolygon value_type;
|
||||
|
||||
|
|
@ -114,7 +197,27 @@ private:
|
|||
};
|
||||
|
||||
template <>
|
||||
struct DB_PUBLIC shape_to_object<db::Path>
|
||||
struct DB_PUBLIC shape_to_object_impl<db::SimplePolygonWithProperties>
|
||||
{
|
||||
typedef db::SimplePolygonWithProperties value_type;
|
||||
|
||||
void set (const db::Shape &s)
|
||||
{
|
||||
s.simple_polygon (m_shape);
|
||||
m_shape.properties_id (s.prop_id ());
|
||||
}
|
||||
|
||||
const value_type *get (const db::Shape &) const
|
||||
{
|
||||
return &m_shape;
|
||||
}
|
||||
|
||||
private:
|
||||
value_type m_shape;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct DB_PUBLIC shape_to_object_impl<db::Path>
|
||||
{
|
||||
typedef db::Path value_type;
|
||||
|
||||
|
|
@ -126,7 +229,27 @@ private:
|
|||
};
|
||||
|
||||
template <>
|
||||
struct DB_PUBLIC shape_to_object<db::Text>
|
||||
struct DB_PUBLIC shape_to_object_impl<db::PathWithProperties>
|
||||
{
|
||||
typedef db::PathWithProperties value_type;
|
||||
|
||||
void set (const db::Shape &s)
|
||||
{
|
||||
s.path (m_shape);
|
||||
m_shape.properties_id (s.prop_id ());
|
||||
}
|
||||
|
||||
const value_type *get (const db::Shape &) const
|
||||
{
|
||||
return &m_shape;
|
||||
}
|
||||
|
||||
private:
|
||||
value_type m_shape;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct DB_PUBLIC shape_to_object_impl<db::Text>
|
||||
{
|
||||
typedef db::Text value_type;
|
||||
|
||||
|
|
@ -138,17 +261,395 @@ private:
|
|||
};
|
||||
|
||||
template <>
|
||||
struct DB_PUBLIC shape_to_object<db::Box>
|
||||
struct DB_PUBLIC shape_to_object_impl<db::TextWithProperties>
|
||||
{
|
||||
typedef db::TextWithProperties value_type;
|
||||
|
||||
void set (const db::Shape &s)
|
||||
{
|
||||
s.text (m_shape);
|
||||
m_shape.properties_id (s.prop_id ());
|
||||
}
|
||||
|
||||
const value_type *get (const db::Shape &) const
|
||||
{
|
||||
return &m_shape;
|
||||
}
|
||||
|
||||
private:
|
||||
value_type m_shape;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct DB_PUBLIC shape_to_object_impl<db::Box>
|
||||
{
|
||||
typedef db::Box value_type;
|
||||
|
||||
void set (const db::Shape *s) { s->box (m_shape); }
|
||||
void set (const db::Shape &s) { s.box (m_shape); }
|
||||
const value_type *get (const db::Shape *) const { return &m_shape; }
|
||||
|
||||
private:
|
||||
value_type m_shape;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct DB_PUBLIC shape_to_object_impl<db::BoxWithProperties>
|
||||
{
|
||||
typedef db::BoxWithProperties value_type;
|
||||
|
||||
void set (const db::Shape &s)
|
||||
{
|
||||
s.box (m_shape);
|
||||
m_shape.properties_id (s.prop_id ());
|
||||
}
|
||||
|
||||
const value_type *get (const db::Shape &) const
|
||||
{
|
||||
return &m_shape;
|
||||
}
|
||||
|
||||
private:
|
||||
value_type m_shape;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct DB_PUBLIC shape_to_object
|
||||
: public shape_to_object_impl<T>
|
||||
{
|
||||
const typename shape_to_object_impl<T>::value_type &operator() (const db::Shape &s)
|
||||
{
|
||||
shape_to_object_impl<T>::set (s);
|
||||
return *shape_to_object_impl<T>::get (s);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Implements an addressable object heap
|
||||
*
|
||||
* This object can deliver addressable objects from shapes. It will keep temporary objects
|
||||
* internally if required.
|
||||
*/
|
||||
|
||||
template <class T>
|
||||
struct addressable_object_from_shape
|
||||
{
|
||||
typedef T value_type;
|
||||
|
||||
const T *operator () (const db::Shape &shape)
|
||||
{
|
||||
typename T::tag object_tag;
|
||||
return shape.basic_ptr (object_tag);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct addressable_object_from_shape<db::object_with_properties<T> >
|
||||
{
|
||||
typedef db::object_with_properties<T> value_type;
|
||||
|
||||
const db::object_with_properties<T> *operator () (const db::Shape &shape)
|
||||
{
|
||||
if (shape.has_prop_id ()) {
|
||||
typename db::object_with_properties<T>::tag object_tag;
|
||||
return shape.basic_ptr (object_tag);
|
||||
} else {
|
||||
typename T::tag object_tag;
|
||||
m_heap.push_back (db::object_with_properties<T> (*shape.basic_ptr (object_tag), 0));
|
||||
return &m_heap.back ();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
tl::slist<db::object_with_properties<T> > m_heap;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct addressable_object_from_shape<db::Box>
|
||||
{
|
||||
typedef db::Box value_type;
|
||||
|
||||
const value_type *operator () (const db::Shape &shape)
|
||||
{
|
||||
if (shape.type () == db::Shape::Box) {
|
||||
return shape.basic_ptr (value_type::tag ());
|
||||
} else {
|
||||
m_heap.push_front (value_type ());
|
||||
shape.box (m_heap.front ());
|
||||
return &m_heap.front ();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
tl::slist<value_type> m_heap;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct addressable_object_from_shape<db::BoxWithProperties>
|
||||
{
|
||||
typedef db::BoxWithProperties value_type;
|
||||
|
||||
const value_type *operator () (const db::Shape &shape)
|
||||
{
|
||||
if (shape.has_prop_id () && shape.type () == db::Shape::Box) {
|
||||
return shape.basic_ptr (value_type::tag ());
|
||||
} else {
|
||||
m_heap.push_front (value_type ());
|
||||
shape.box (m_heap.front ());
|
||||
m_heap.front ().properties_id (shape.prop_id ());
|
||||
return &m_heap.front ();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
tl::slist<value_type> m_heap;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct addressable_object_from_shape<db::Polygon>
|
||||
{
|
||||
typedef db::Polygon value_type;
|
||||
|
||||
const value_type *operator () (const db::Shape &shape)
|
||||
{
|
||||
if (shape.type () == db::Shape::Polygon) {
|
||||
return shape.basic_ptr (value_type::tag ());
|
||||
} else {
|
||||
m_heap.push_front (value_type ());
|
||||
shape.polygon (m_heap.front ());
|
||||
return &m_heap.front ();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
tl::slist<value_type> m_heap;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct addressable_object_from_shape<db::PolygonWithProperties>
|
||||
{
|
||||
typedef db::PolygonWithProperties value_type;
|
||||
|
||||
const value_type *operator () (const db::Shape &shape)
|
||||
{
|
||||
if (shape.has_prop_id () && shape.type () == db::Shape::Polygon) {
|
||||
return shape.basic_ptr (value_type::tag ());
|
||||
} else {
|
||||
m_heap.push_front (value_type ());
|
||||
shape.polygon (m_heap.front ());
|
||||
m_heap.front ().properties_id (shape.prop_id ());
|
||||
return &m_heap.front ();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
tl::slist<value_type> m_heap;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct addressable_object_from_shape<db::SimplePolygon>
|
||||
{
|
||||
typedef db::SimplePolygon value_type;
|
||||
|
||||
const value_type *operator () (const db::Shape &shape)
|
||||
{
|
||||
if (shape.type () == db::Shape::SimplePolygon) {
|
||||
return shape.basic_ptr (value_type::tag ());
|
||||
} else {
|
||||
m_heap.push_front (value_type ());
|
||||
shape.simple_polygon (m_heap.front ());
|
||||
return &m_heap.front ();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
tl::slist<value_type> m_heap;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct addressable_object_from_shape<db::SimplePolygonWithProperties>
|
||||
{
|
||||
typedef db::SimplePolygonWithProperties value_type;
|
||||
|
||||
const value_type *operator () (const db::Shape &shape)
|
||||
{
|
||||
if (shape.has_prop_id () && shape.type () == db::Shape::SimplePolygon) {
|
||||
return shape.basic_ptr (value_type::tag ());
|
||||
} else {
|
||||
m_heap.push_front (value_type ());
|
||||
shape.simple_polygon (m_heap.front ());
|
||||
m_heap.front ().properties_id (shape.prop_id ());
|
||||
return &m_heap.front ();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
tl::slist<value_type> m_heap;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct addressable_object_from_shape<db::Path>
|
||||
{
|
||||
typedef db::Path value_type;
|
||||
|
||||
const value_type *operator () (const db::Shape &shape)
|
||||
{
|
||||
if (shape.type () == db::Shape::Path) {
|
||||
return shape.basic_ptr (value_type::tag ());
|
||||
} else {
|
||||
m_heap.push_front (value_type ());
|
||||
shape.path (m_heap.front ());
|
||||
return &m_heap.front ();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
tl::slist<value_type> m_heap;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct addressable_object_from_shape<db::PathWithProperties>
|
||||
{
|
||||
typedef db::PathWithProperties value_type;
|
||||
|
||||
const value_type *operator () (const db::Shape &shape)
|
||||
{
|
||||
if (shape.has_prop_id () && shape.type () == db::Shape::Path) {
|
||||
return shape.basic_ptr (value_type::tag ());
|
||||
} else {
|
||||
m_heap.push_front (value_type ());
|
||||
shape.path (m_heap.front ());
|
||||
m_heap.front ().properties_id (shape.prop_id ());
|
||||
return &m_heap.front ();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
tl::slist<value_type> m_heap;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct addressable_object_from_shape<db::Edge>
|
||||
{
|
||||
typedef db::Edge value_type;
|
||||
|
||||
const value_type *operator () (const db::Shape &shape)
|
||||
{
|
||||
if (shape.type () == db::Shape::Edge) {
|
||||
return shape.basic_ptr (value_type::tag ());
|
||||
} else {
|
||||
m_heap.push_front (value_type ());
|
||||
shape.edge (m_heap.front ());
|
||||
return &m_heap.front ();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
tl::slist<value_type> m_heap;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct addressable_object_from_shape<db::EdgeWithProperties>
|
||||
{
|
||||
typedef db::EdgeWithProperties value_type;
|
||||
|
||||
const value_type *operator () (const db::Shape &shape)
|
||||
{
|
||||
if (shape.has_prop_id () && shape.type () == db::Shape::Edge) {
|
||||
return shape.basic_ptr (value_type::tag ());
|
||||
} else {
|
||||
m_heap.push_front (value_type ());
|
||||
shape.edge (m_heap.front ());
|
||||
m_heap.front ().properties_id (shape.prop_id ());
|
||||
return &m_heap.front ();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
tl::slist<value_type> m_heap;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct addressable_object_from_shape<db::EdgePair>
|
||||
{
|
||||
typedef db::EdgePair value_type;
|
||||
|
||||
const value_type *operator () (const db::Shape &shape)
|
||||
{
|
||||
if (shape.type () == db::Shape::EdgePair) {
|
||||
return shape.basic_ptr (value_type::tag ());
|
||||
} else {
|
||||
m_heap.push_front (value_type ());
|
||||
shape.edge_pair (m_heap.front ());
|
||||
return &m_heap.front ();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
tl::slist<value_type> m_heap;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct addressable_object_from_shape<db::EdgePairWithProperties>
|
||||
{
|
||||
typedef db::EdgePairWithProperties value_type;
|
||||
|
||||
const value_type *operator () (const db::Shape &shape)
|
||||
{
|
||||
if (shape.has_prop_id () && shape.type () == db::Shape::EdgePair) {
|
||||
return shape.basic_ptr (value_type::tag ());
|
||||
} else {
|
||||
m_heap.push_front (value_type ());
|
||||
shape.edge_pair (m_heap.front ());
|
||||
m_heap.front ().properties_id (shape.prop_id ());
|
||||
return &m_heap.front ();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
tl::slist<value_type> m_heap;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct addressable_object_from_shape<db::Text>
|
||||
{
|
||||
typedef db::Text value_type;
|
||||
|
||||
const value_type *operator () (const db::Shape &shape)
|
||||
{
|
||||
if (shape.type () == db::Shape::Text) {
|
||||
return shape.basic_ptr (value_type::tag ());
|
||||
} else {
|
||||
m_heap.push_front (value_type ());
|
||||
shape.text (m_heap.front ());
|
||||
return &m_heap.front ();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
tl::slist<value_type> m_heap;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct addressable_object_from_shape<db::TextWithProperties>
|
||||
{
|
||||
typedef db::TextWithProperties value_type;
|
||||
|
||||
const value_type *operator () (const db::Shape &shape)
|
||||
{
|
||||
if (shape.has_prop_id () && shape.type () == db::Shape::Text) {
|
||||
return shape.basic_ptr (value_type::tag ());
|
||||
} else {
|
||||
m_heap.push_front (value_type ());
|
||||
shape.text (m_heap.front ());
|
||||
m_heap.front ().properties_id (shape.prop_id ());
|
||||
return &m_heap.front ();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
tl::slist<value_type> m_heap;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -619,9 +619,9 @@ static db::EdgePairs separation2 (const db::Region *r, const db::Region &other,
|
|||
);
|
||||
}
|
||||
|
||||
static std::vector<db::Region> andnot (const db::Region *r, const db::Region &other)
|
||||
static std::vector<db::Region> andnot (const db::Region *r, const db::Region &other, db::PropertyConstraint prop_constraint)
|
||||
{
|
||||
return as_2region_vector (r->andnot (other));
|
||||
return as_2region_vector (r->andnot (other, prop_constraint));
|
||||
}
|
||||
|
||||
static std::vector<db::Region> split_inside (const db::Region *r, const db::Region &other)
|
||||
|
|
@ -1595,7 +1595,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
) +
|
||||
method_ext ("andnot", &andnot, gsi::arg ("other"),
|
||||
method_ext ("andnot", &andnot, gsi::arg ("other"), gsi::arg ("property_constraint", db::NoPropertyConstraint),
|
||||
"@brief Returns the boolean AND and NOT between self and the other region\n"
|
||||
"\n"
|
||||
"@return A two-element array of regions with the first one being the AND result and the second one being the NOT result\n"
|
||||
|
|
@ -1613,6 +1613,18 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"This method will compute the boolean AND (intersection) between two regions. "
|
||||
"The result is often but not necessarily always merged.\n"
|
||||
) +
|
||||
method ("and", &db::Region::bool_and, gsi::arg ("other"), gsi::arg ("property_constraint", db::NoPropertyConstraint),
|
||||
"@brief Returns the boolean AND between self and the other region\n"
|
||||
"\n"
|
||||
"@return The result of the boolean AND operation\n"
|
||||
"\n"
|
||||
"This method will compute the boolean AND (intersection) between two regions. "
|
||||
"The result is often but not necessarily always merged.\n"
|
||||
"It allows specification of a property constaint - e.g. only performing the boolean operation between "
|
||||
"shapes with the same user properties.\n"
|
||||
"\n"
|
||||
"This variant has been introduced in version 0.28.4."
|
||||
) +
|
||||
method ("&=", &db::Region::operator&=, gsi::arg ("other"),
|
||||
"@brief Performs the boolean AND between self and the other region\n"
|
||||
"\n"
|
||||
|
|
@ -1621,6 +1633,18 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"This method will compute the boolean AND (intersection) between two regions. "
|
||||
"The result is often but not necessarily always merged.\n"
|
||||
) +
|
||||
method ("and_with", &db::Region::bool_and_with, gsi::arg ("other"), gsi::arg ("property_constraint", db::NoPropertyConstraint),
|
||||
"@brief Performs the boolean AND between self and the other region\n"
|
||||
"\n"
|
||||
"@return The region after modification (self)\n"
|
||||
"\n"
|
||||
"This method will compute the boolean AND (intersection) between two regions. "
|
||||
"The result is often but not necessarily always merged.\n"
|
||||
"It allows specification of a property constaint - e.g. only performing the boolean operation between "
|
||||
"shapes with the same user properties.\n"
|
||||
"\n"
|
||||
"This variant has been introduced in version 0.28.4."
|
||||
) +
|
||||
method ("-", &db::Region::operator-, gsi::arg ("other"),
|
||||
"@brief Returns the boolean NOT between self and the other region\n"
|
||||
"\n"
|
||||
|
|
@ -1629,6 +1653,14 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"This method will compute the boolean NOT (intersection) between two regions. "
|
||||
"The result is often but not necessarily always merged.\n"
|
||||
) +
|
||||
method ("not", &db::Region::bool_not, gsi::arg ("other"), gsi::arg ("property_constraint", db::NoPropertyConstraint),
|
||||
"@brief Returns the boolean NOT between self and the other region\n"
|
||||
"\n"
|
||||
"@return The result of the boolean NOT operation\n"
|
||||
"\n"
|
||||
"This method will compute the boolean NOT (intersection) between two regions. "
|
||||
"The result is often but not necessarily always merged.\n"
|
||||
) +
|
||||
method ("-=", &db::Region::operator-=, gsi::arg ("other"),
|
||||
"@brief Performs the boolean NOT between self and the other region\n"
|
||||
"\n"
|
||||
|
|
@ -1637,6 +1669,14 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"This method will compute the boolean NOT (intersection) between two regions. "
|
||||
"The result is often but not necessarily always merged.\n"
|
||||
) +
|
||||
method ("not_with", &db::Region::bool_not_with, gsi::arg ("other"), gsi::arg ("property_constraint", db::NoPropertyConstraint),
|
||||
"@brief Performs the boolean NOT between self and the other region\n"
|
||||
"\n"
|
||||
"@return The region after modification (self)\n"
|
||||
"\n"
|
||||
"This method will compute the boolean NOT (intersection) between two regions. "
|
||||
"The result is often but not necessarily always merged.\n"
|
||||
) +
|
||||
method ("^", &db::Region::operator^, gsi::arg ("other"),
|
||||
"@brief Returns the boolean XOR between self and the other region\n"
|
||||
"\n"
|
||||
|
|
@ -3055,6 +3095,32 @@ gsi::EnumIn<db::Region, db::metrics_type> decl_Region_Metrics ("db", "Metrics",
|
|||
gsi::ClassExt<db::Region> inject_Metrics_in_parent (decl_Region_Metrics.defs ());
|
||||
gsi::ClassExt<db::Edges> inject_Metrics_in_Edges (decl_Region_Metrics.defs ());
|
||||
|
||||
gsi::EnumIn<db::Region, db::PropertyConstraint> decl_Region_PropertyConstraint ("db", "PropertyConstraint",
|
||||
gsi::enum_const ("NoPropertyConstraint", db::NoPropertyConstraint,
|
||||
"@brief Specifies not to apply any property constraint\n"
|
||||
"When using this constraint - for example on a boolean operation - shapes are considered "
|
||||
"regardless of their user properties."
|
||||
) +
|
||||
gsi::enum_const ("SamePropertiesConstraint", db::SamePropertiesConstraint,
|
||||
"@brief Specifies to consider shapes only if their user properties are the same\n"
|
||||
"When using this constraint - for example on a boolean operation - shapes are considered "
|
||||
"only if their user properties are the same."
|
||||
) +
|
||||
gsi::enum_const ("DifferentPropertiesConstraint", db::DifferentPropertiesConstraint,
|
||||
"@brief Specifies to consider shapes only if their user properties are different\n"
|
||||
"When using this constraint - for example on a boolean operation - shapes are considered "
|
||||
"only if their user properties are different."
|
||||
),
|
||||
"@brief This class represents the property constraint for boolean and check functions.\n"
|
||||
"\n"
|
||||
"This enum has been introduced in version 0.28.4."
|
||||
);
|
||||
|
||||
// Inject the Region::PropertyConstraint declarations into Region and Edges:
|
||||
// (Edges injection has to be done here because only here defs() is available)
|
||||
gsi::ClassExt<db::Region> inject_PropertyConstraint_in_parent (decl_Region_PropertyConstraint.defs ());
|
||||
gsi::ClassExt<db::Edges> inject_PropertyConstraint_in_Edges (decl_Region_PropertyConstraint.defs ());
|
||||
|
||||
gsi::EnumIn<db::Region, db::RectFilter> decl_Region_RectFilter ("db", "RectFilter",
|
||||
gsi::enum_const ("NoRectFilter", db::RectFilter::NoRectFilter,
|
||||
"@brief Specifies no filtering"
|
||||
|
|
|
|||
|
|
@ -40,92 +40,6 @@ static unsigned int define_layer (db::Layout &ly, db::LayerMap &lmap, int gds_la
|
|||
return lid;
|
||||
}
|
||||
|
||||
class BoolBetweenNets
|
||||
: public db::local_operation<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::PolygonRef>
|
||||
{
|
||||
public:
|
||||
BoolBetweenNets (bool is_and, bool connected)
|
||||
: m_is_and (is_and), m_connected (connected)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
db::OnEmptyIntruderHint
|
||||
on_empty_intruder_hint () const
|
||||
{
|
||||
return m_is_and ? db::Drop : db::Copy;
|
||||
}
|
||||
|
||||
std::string
|
||||
description () const
|
||||
{
|
||||
return m_is_and ? tl::to_string (tr ("AND operation")) : tl::to_string (tr ("NOT operation"));
|
||||
}
|
||||
|
||||
void
|
||||
do_compute_local (db::Layout *layout, const db::shape_interactions<db::PolygonRefWithProperties, db::PolygonRefWithProperties> &interactions, std::vector<std::unordered_set<db::PolygonRef> > &results, size_t max_vertex_count, double area_ratio) const
|
||||
{
|
||||
tl_assert (results.size () == 1);
|
||||
std::unordered_set<db::PolygonRef> &result = results.front ();
|
||||
|
||||
db::EdgeProcessor ep;
|
||||
|
||||
// NOTE: is guess we do not need to handle subject/subject interactions ...
|
||||
for (auto i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
|
||||
const db::PolygonRefWithProperties &subject = interactions.subject_shape (i->first);
|
||||
|
||||
bool any_intruder = false;
|
||||
for (auto j = i->second.begin (); j != i->second.end () && ! any_intruder; ++j) {
|
||||
const db::PolygonRefWithProperties &other = interactions.intruder_shape (*j).second;
|
||||
any_intruder = ((other.properties_id () == subject.properties_id ()) == m_connected);
|
||||
}
|
||||
|
||||
if (! any_intruder) {
|
||||
|
||||
// shortcut (not: keep, and: drop)
|
||||
if (! m_is_and) {
|
||||
result.insert (subject);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
ep.clear ();
|
||||
|
||||
for (db::PolygonRef::polygon_edge_iterator e = subject.begin_edge (); ! e.at_end(); ++e) {
|
||||
ep.insert (*e, 0);
|
||||
}
|
||||
|
||||
for (auto j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
|
||||
const db::PolygonRefWithProperties &other = interactions.intruder_shape (*j).second;
|
||||
if ((other.properties_id () == subject.properties_id ()) == m_connected) {
|
||||
for (db::PolygonRef::polygon_edge_iterator e = other.begin_edge (); ! e.at_end(); ++e) {
|
||||
ep.insert (*e, 1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
db::BooleanOp op (m_is_and ? db::BooleanOp::And : db::BooleanOp::ANotB);
|
||||
db::PolygonRefGenerator pr (layout, result);
|
||||
db::PolygonSplitter splitter (pr, area_ratio, max_vertex_count);
|
||||
db::PolygonGenerator pg (splitter, true, true);
|
||||
ep.set_base_verbosity (50);
|
||||
ep.process (pg, op);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_is_and;
|
||||
bool m_connected;
|
||||
};
|
||||
|
||||
|
||||
TEST(0_Develop)
|
||||
{
|
||||
db::Layout ly;
|
||||
|
|
@ -210,15 +124,26 @@ TEST(0_Develop)
|
|||
lmap_write [wvia1 = ly2.insert_layer (db::LayerProperties (16, 0))] = l2n.layer_by_name ("via1");
|
||||
lmap_write [wmetal2 = ly2.insert_layer (db::LayerProperties (17, 0))] = l2n.layer_by_name ("metal2");
|
||||
|
||||
l2n.build_all_nets (cm, ly2, lmap_write, "NET_", db::LayoutToNetlist::NetIDOnly, tl::Variant (), db::LayoutToNetlist::BNH_SubcircuitCells, "SC_", 0 /*don't produce devices*/);
|
||||
l2n.build_all_nets (cm, ly2, lmap_write, "NET_", db::LayoutToNetlist::NetNameAndIDOnly, tl::Variant (1), db::LayoutToNetlist::BNH_SubcircuitCells, "SC_", 0 /*don't produce devices*/);
|
||||
|
||||
unsigned int out = ly2.insert_layer (db::LayerProperties (1000, 0));
|
||||
unsigned int out1 = ly2.insert_layer (db::LayerProperties (1000, 0));
|
||||
unsigned int out2 = ly2.insert_layer (db::LayerProperties (1001, 0));
|
||||
unsigned int out3 = ly2.insert_layer (db::LayerProperties (1002, 0));
|
||||
|
||||
db::local_processor<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::PolygonRef> proc (&ly2, &top2);
|
||||
BoolBetweenNets n2n (true, true);
|
||||
proc.run (&n2n, wmetal1, wmetal2, out);
|
||||
db::local_processor<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::PolygonRefWithProperties> proc (&ly2, &top2);
|
||||
{
|
||||
db::BoolAndOrNotLocalOperationWithProperties n2n (true, &ly2, &ly2, db::SamePropertiesConstraint);
|
||||
proc.run (&n2n, wmetal1, wmetal2, out1);
|
||||
}
|
||||
{
|
||||
db::BoolAndOrNotLocalOperationWithProperties n2n (true, &ly2, &ly2, db::DifferentPropertiesConstraint);
|
||||
proc.run (&n2n, wmetal1, wmetal2, out2);
|
||||
}
|
||||
{
|
||||
db::BoolAndOrNotLocalOperationWithProperties n2n (true, &ly2, &ly2, db::NoPropertyConstraint);
|
||||
proc.run (&n2n, wmetal1, wmetal2, out3);
|
||||
}
|
||||
|
||||
// @@@ may no work correctly as we have used fake prop ids
|
||||
{
|
||||
db::SaveLayoutOptions options;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue