mirror of https://github.com/KLayout/klayout.git
commit
ab8cfee1ea
|
|
@ -37,6 +37,7 @@ build-*
|
|||
bin-*
|
||||
mkqtdecl.tmp
|
||||
mkqtdecl5.tmp
|
||||
mkqtdecl6.tmp
|
||||
testtmp
|
||||
*build.macos*
|
||||
*bin.macos*
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ SOURCES = \
|
|||
dbEdgePairs.cc \
|
||||
dbEdgeProcessor.cc \
|
||||
dbEdges.cc \
|
||||
dbEdgesLocalOperations.cc \
|
||||
dbFillTool.cc \
|
||||
dbFuzzyCellMapping.cc \
|
||||
dbGenericShapeIterator.cc \
|
||||
|
|
@ -243,6 +244,7 @@ HEADERS = \
|
|||
dbEdgePairs.h \
|
||||
dbEdgeProcessor.h \
|
||||
dbEdges.h \
|
||||
dbEdgesLocalOperations.h \
|
||||
dbEdgesToContours.h \
|
||||
dbFillTool.h \
|
||||
dbFuzzyCellMapping.h \
|
||||
|
|
@ -260,6 +262,7 @@ HEADERS = \
|
|||
dbLayoutLayers.h \
|
||||
dbLayoutQuery.h \
|
||||
dbLayoutStateModel.h \
|
||||
dbLayoutToNetlistEnums.h \
|
||||
dbLayoutUtils.h \
|
||||
dbLibrary.h \
|
||||
dbLibraryManager.h \
|
||||
|
|
@ -288,6 +291,7 @@ HEADERS = \
|
|||
dbPolygonTools.h \
|
||||
dbPolygonGenerators.h \
|
||||
dbPropertiesRepository.h \
|
||||
dbPropertyConstraint.h \
|
||||
dbReader.h \
|
||||
dbRecursiveInstanceIterator.h \
|
||||
dbRecursiveShapeIterator.h \
|
||||
|
|
@ -372,6 +376,7 @@ HEADERS = \
|
|||
dbRegionUtils.h \
|
||||
dbEdgesUtils.h \
|
||||
dbRegionProcessors.h \
|
||||
gsiDeclDbContainerHelpers.h \
|
||||
gsiDeclDbHelpers.h \
|
||||
dbNetlistCompare.h \
|
||||
dbNetlistReader.h \
|
||||
|
|
|
|||
|
|
@ -151,6 +151,7 @@ RegionDelegate *
|
|||
AsIfFlatEdgePairs::processed_to_polygons (const EdgePairToPolygonProcessorBase &filter) const
|
||||
{
|
||||
std::unique_ptr<FlatRegion> region (new FlatRegion ());
|
||||
db::PropertyMapper pm (region->properties_repository (), properties_repository ());
|
||||
|
||||
if (filter.result_must_not_be_merged ()) {
|
||||
region->set_merged_semantics (false);
|
||||
|
|
@ -162,7 +163,12 @@ AsIfFlatEdgePairs::processed_to_polygons (const EdgePairToPolygonProcessorBase &
|
|||
res_polygons.clear ();
|
||||
filter.process (*e, res_polygons);
|
||||
for (std::vector<db::Polygon>::const_iterator pr = res_polygons.begin (); pr != res_polygons.end (); ++pr) {
|
||||
region->insert (*pr);
|
||||
db::properties_id_type prop_id = pm (e.prop_id ());
|
||||
if (prop_id != 0) {
|
||||
region->insert (db::PolygonWithProperties (*pr, prop_id));
|
||||
} else {
|
||||
region->insert (*pr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -173,6 +179,7 @@ EdgesDelegate *
|
|||
AsIfFlatEdgePairs::processed_to_edges (const EdgePairToEdgeProcessorBase &filter) const
|
||||
{
|
||||
std::unique_ptr<FlatEdges> edges (new FlatEdges ());
|
||||
db::PropertyMapper pm (edges->properties_repository (), properties_repository ());
|
||||
|
||||
if (filter.result_must_not_be_merged ()) {
|
||||
edges->set_merged_semantics (false);
|
||||
|
|
@ -184,7 +191,12 @@ AsIfFlatEdgePairs::processed_to_edges (const EdgePairToEdgeProcessorBase &filter
|
|||
res_edges.clear ();
|
||||
filter.process (*e, res_edges);
|
||||
for (std::vector<db::Edge>::const_iterator pr = res_edges.begin (); pr != res_edges.end (); ++pr) {
|
||||
edges->insert (*pr);
|
||||
db::properties_id_type prop_id = pm (e.prop_id ());
|
||||
if (prop_id != 0) {
|
||||
edges->insert (db::EdgeWithProperties (*pr, prop_id));
|
||||
} else {
|
||||
edges->insert (*pr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -195,10 +207,16 @@ EdgePairsDelegate *
|
|||
AsIfFlatEdgePairs::filtered (const EdgePairFilterBase &filter) const
|
||||
{
|
||||
std::unique_ptr<FlatEdgePairs> new_edge_pairs (new FlatEdgePairs ());
|
||||
db::PropertyMapper pm (new_edge_pairs->properties_repository (), properties_repository ());
|
||||
|
||||
for (EdgePairsIterator p (begin ()); ! p.at_end (); ++p) {
|
||||
if (filter.selected (*p)) {
|
||||
new_edge_pairs->insert (*p);
|
||||
db::properties_id_type prop_id = pm (p.prop_id ());
|
||||
if (prop_id != 0) {
|
||||
new_edge_pairs->insert (db::EdgePairWithProperties (*p, prop_id));
|
||||
} else {
|
||||
new_edge_pairs->insert (*p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -209,11 +227,17 @@ RegionDelegate *
|
|||
AsIfFlatEdgePairs::polygons (db::Coord e) const
|
||||
{
|
||||
std::unique_ptr<FlatRegion> output (new FlatRegion ());
|
||||
db::PropertyMapper pm (output->properties_repository (), properties_repository ());
|
||||
|
||||
for (EdgePairsIterator ep (begin ()); ! ep.at_end (); ++ep) {
|
||||
db::Polygon poly = ep->normalized ().to_polygon (e);
|
||||
if (poly.vertices () >= 3) {
|
||||
output->insert (poly);
|
||||
db::properties_id_type prop_id = pm (ep.prop_id ());
|
||||
if (prop_id != 0) {
|
||||
output->insert (db::PolygonWithProperties (poly, prop_id));
|
||||
} else {
|
||||
output->insert (poly);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -224,10 +248,17 @@ EdgesDelegate *
|
|||
AsIfFlatEdgePairs::edges () const
|
||||
{
|
||||
std::unique_ptr<FlatEdges> output (new FlatEdges ());
|
||||
db::PropertyMapper pm (output->properties_repository (), properties_repository ());
|
||||
|
||||
for (EdgePairsIterator ep (begin ()); ! ep.at_end (); ++ep) {
|
||||
output->insert (ep->first ());
|
||||
output->insert (ep->second ());
|
||||
db::properties_id_type prop_id = pm (ep.prop_id ());
|
||||
if (prop_id != 0) {
|
||||
output->insert (db::EdgeWithProperties (ep->first (), prop_id));
|
||||
output->insert (db::EdgeWithProperties (ep->second (), prop_id));
|
||||
} else {
|
||||
output->insert (ep->first ());
|
||||
output->insert (ep->second ());
|
||||
}
|
||||
}
|
||||
|
||||
return output.release ();
|
||||
|
|
@ -237,9 +268,15 @@ EdgesDelegate *
|
|||
AsIfFlatEdgePairs::first_edges () const
|
||||
{
|
||||
std::unique_ptr<FlatEdges> output (new FlatEdges ());
|
||||
db::PropertyMapper pm (output->properties_repository (), properties_repository ());
|
||||
|
||||
for (EdgePairsIterator ep (begin ()); ! ep.at_end (); ++ep) {
|
||||
output->insert (ep->first ());
|
||||
db::properties_id_type prop_id = pm (ep.prop_id ());
|
||||
if (prop_id != 0) {
|
||||
output->insert (db::EdgeWithProperties (ep->first (), prop_id));
|
||||
} else {
|
||||
output->insert (ep->first ());
|
||||
}
|
||||
}
|
||||
|
||||
return output.release ();
|
||||
|
|
@ -249,9 +286,15 @@ EdgesDelegate *
|
|||
AsIfFlatEdgePairs::second_edges () const
|
||||
{
|
||||
std::unique_ptr<FlatEdges> output (new FlatEdges ());
|
||||
db::PropertyMapper pm (output->properties_repository (), properties_repository ());
|
||||
|
||||
for (EdgePairsIterator ep (begin ()); ! ep.at_end (); ++ep) {
|
||||
output->insert (ep->second ());
|
||||
db::properties_id_type prop_id = pm (ep.prop_id ());
|
||||
if (prop_id != 0) {
|
||||
output->insert (db::EdgeWithProperties (ep->second (), prop_id));
|
||||
} else {
|
||||
output->insert (ep->second ());
|
||||
}
|
||||
}
|
||||
|
||||
return output.release ();
|
||||
|
|
@ -260,18 +303,25 @@ AsIfFlatEdgePairs::second_edges () const
|
|||
EdgePairsDelegate *
|
||||
AsIfFlatEdgePairs::add (const EdgePairs &other) const
|
||||
{
|
||||
FlatEdgePairs *other_flat = dynamic_cast<FlatEdgePairs *> (other.delegate ());
|
||||
const FlatEdgePairs *other_flat = dynamic_cast<const FlatEdgePairs *> (other.delegate ());
|
||||
if (other_flat) {
|
||||
|
||||
std::unique_ptr<FlatEdgePairs> new_edge_pairs (new FlatEdgePairs (*other_flat));
|
||||
new_edge_pairs->invalidate_cache ();
|
||||
|
||||
db::PropertyMapper pm (new_edge_pairs->properties_repository (), properties_repository ());
|
||||
|
||||
size_t n = new_edge_pairs->raw_edge_pairs ().size () + count ();
|
||||
|
||||
new_edge_pairs->reserve (n);
|
||||
|
||||
for (EdgePairsIterator p (begin ()); ! p.at_end (); ++p) {
|
||||
new_edge_pairs->raw_edge_pairs ().insert (*p);
|
||||
db::properties_id_type prop_id = pm (p.prop_id ());
|
||||
if (prop_id) {
|
||||
new_edge_pairs->raw_edge_pairs ().insert (db::EdgePairWithProperties (*p, prop_id));
|
||||
} else {
|
||||
new_edge_pairs->raw_edge_pairs ().insert (*p);
|
||||
}
|
||||
}
|
||||
|
||||
return new_edge_pairs.release ();
|
||||
|
|
@ -280,15 +330,28 @@ AsIfFlatEdgePairs::add (const EdgePairs &other) const
|
|||
|
||||
std::unique_ptr<FlatEdgePairs> new_edge_pairs (new FlatEdgePairs ());
|
||||
|
||||
db::PropertyMapper pm (new_edge_pairs->properties_repository (), properties_repository ());
|
||||
db::PropertyMapper pm_other (new_edge_pairs->properties_repository (), &other.properties_repository ());
|
||||
|
||||
size_t n = count () + other.count ();
|
||||
|
||||
new_edge_pairs->reserve (n);
|
||||
|
||||
for (EdgePairsIterator p (begin ()); ! p.at_end (); ++p) {
|
||||
new_edge_pairs->raw_edge_pairs ().insert (*p);
|
||||
db::properties_id_type prop_id = pm (p.prop_id ());
|
||||
if (prop_id) {
|
||||
new_edge_pairs->raw_edge_pairs ().insert (db::EdgePairWithProperties (*p, prop_id));
|
||||
} else {
|
||||
new_edge_pairs->raw_edge_pairs ().insert (*p);
|
||||
}
|
||||
}
|
||||
for (EdgePairsIterator p (other.begin ()); ! p.at_end (); ++p) {
|
||||
new_edge_pairs->raw_edge_pairs ().insert (*p);
|
||||
db::properties_id_type prop_id = pm_other (p.prop_id ());
|
||||
if (prop_id) {
|
||||
new_edge_pairs->raw_edge_pairs ().insert (db::EdgePairWithProperties (*p, prop_id));
|
||||
} else {
|
||||
new_edge_pairs->raw_edge_pairs ().insert (*p);
|
||||
}
|
||||
}
|
||||
|
||||
return new_edge_pairs.release ();
|
||||
|
|
@ -344,9 +407,16 @@ AsIfFlatEdgePairs::insert_into (Layout *layout, db::cell_index_type into_cell, u
|
|||
// improves performance when inserting an original layout into the same layout
|
||||
db::LayoutLocker locker (layout);
|
||||
|
||||
db::PropertyMapper pm (&layout->properties_repository (), properties_repository ());
|
||||
|
||||
db::Shapes &shapes = layout->cell (into_cell).shapes (into_layer);
|
||||
for (EdgePairsIterator e (begin ()); ! e.at_end (); ++e) {
|
||||
shapes.insert (*e);
|
||||
db::properties_id_type prop_id = pm (e.prop_id ());
|
||||
if (prop_id) {
|
||||
shapes.insert (db::EdgePairWithProperties (*e, prop_id));
|
||||
} else {
|
||||
shapes.insert (*e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -356,9 +426,16 @@ AsIfFlatEdgePairs::insert_into_as_polygons (Layout *layout, db::cell_index_type
|
|||
// improves performance when inserting an original layout into the same layout
|
||||
db::LayoutLocker locker (layout);
|
||||
|
||||
db::PropertyMapper pm (&layout->properties_repository (), properties_repository ());
|
||||
|
||||
db::Shapes &shapes = layout->cell (into_cell).shapes (into_layer);
|
||||
for (EdgePairsIterator e (begin ()); ! e.at_end (); ++e) {
|
||||
shapes.insert (e->normalized ().to_simple_polygon (enl));
|
||||
db::properties_id_type prop_id = pm (e.prop_id ());
|
||||
if (prop_id) {
|
||||
shapes.insert (db::SimplePolygonWithProperties (e->normalized ().to_simple_polygon (enl), prop_id));
|
||||
} else {
|
||||
shapes.insert (e->normalized ().to_simple_polygon (enl));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ AsIfFlatEdges::selected_interacting_generic (const Region &other, EdgeInteractio
|
|||
|
||||
db::box_scanner2<db::Edge, size_t, db::Polygon, size_t> scanner (report_progress (), progress_desc ());
|
||||
|
||||
AddressableEdgeDelivery e (begin_merged (), has_valid_merged_edges ());
|
||||
AddressableEdgeDelivery e (begin_merged ());
|
||||
|
||||
for ( ; ! e.at_end (); ++e) {
|
||||
scanner.insert1 (e.operator-> (), 0);
|
||||
|
|
@ -150,7 +150,7 @@ AsIfFlatEdges::selected_interacting_generic (const Edges &edges, EdgeInteraction
|
|||
|
||||
db::box_scanner<db::Edge, size_t> scanner (report_progress (), progress_desc ());
|
||||
|
||||
AddressableEdgeDelivery e (begin_merged (), has_valid_merged_edges ());
|
||||
AddressableEdgeDelivery e (begin_merged ());
|
||||
|
||||
for ( ; ! e.at_end (); ++e) {
|
||||
scanner.insert (e.operator-> (), 0);
|
||||
|
|
@ -201,7 +201,7 @@ AsIfFlatEdges::selected_interacting_pair_generic (const Region ®ion, EdgeInte
|
|||
|
||||
db::box_scanner2<db::Edge, size_t, db::Polygon, size_t> scanner (report_progress (), progress_desc ());
|
||||
|
||||
AddressableEdgeDelivery e (begin_merged (), has_valid_merged_edges ());
|
||||
AddressableEdgeDelivery e (begin_merged ());
|
||||
|
||||
for ( ; ! e.at_end (); ++e) {
|
||||
scanner.insert1 (e.operator-> (), 0);
|
||||
|
|
@ -245,7 +245,7 @@ AsIfFlatEdges::selected_interacting_pair_generic (const Edges &other, EdgeIntera
|
|||
|
||||
db::box_scanner<db::Edge, size_t> scanner (report_progress (), progress_desc ());
|
||||
|
||||
AddressableEdgeDelivery e (begin_merged (), has_valid_merged_edges ());
|
||||
AddressableEdgeDelivery e (begin_merged ());
|
||||
|
||||
for ( ; ! e.at_end (); ++e) {
|
||||
scanner.insert (e.operator-> (), 0);
|
||||
|
|
@ -281,7 +281,7 @@ AsIfFlatEdges::pull_generic (const Edges &edges) const
|
|||
{
|
||||
db::box_scanner<db::Edge, size_t> scanner (report_progress (), progress_desc ());
|
||||
|
||||
AddressableEdgeDelivery e (begin (), has_valid_edges ());
|
||||
AddressableEdgeDelivery e (begin ());
|
||||
|
||||
for ( ; ! e.at_end (); ++e) {
|
||||
scanner.insert (e.operator-> (), 1);
|
||||
|
|
@ -310,7 +310,7 @@ AsIfFlatEdges::pull_generic (const Region &other) const
|
|||
|
||||
db::box_scanner2<db::Edge, size_t, db::Polygon, size_t> scanner (report_progress (), progress_desc ());
|
||||
|
||||
AddressableEdgeDelivery e (begin (), true);
|
||||
AddressableEdgeDelivery e (begin ());
|
||||
|
||||
for ( ; ! e.at_end (); ++e) {
|
||||
scanner.insert1 (e.operator-> (), 0);
|
||||
|
|
@ -480,6 +480,8 @@ AsIfFlatEdges::extended (coord_type ext_b, coord_type ext_e, coord_type ext_o, c
|
|||
{
|
||||
if (join) {
|
||||
|
||||
// TODO: property support?
|
||||
|
||||
std::unique_ptr<FlatRegion> output (new FlatRegion ());
|
||||
db::ShapeGenerator sg (output->raw_polygons (), false);
|
||||
JoinEdgesClusterCollector cluster_collector (&sg, ext_b, ext_e, ext_o, ext_i);
|
||||
|
|
@ -487,7 +489,7 @@ AsIfFlatEdges::extended (coord_type ext_b, coord_type ext_e, coord_type ext_o, c
|
|||
db::box_scanner<db::Edge, size_t> scanner (report_progress (), progress_desc ());
|
||||
scanner.reserve (count ());
|
||||
|
||||
AddressableEdgeDelivery e (begin (), has_valid_edges ());
|
||||
AddressableEdgeDelivery e (begin ());
|
||||
|
||||
size_t n = 0;
|
||||
for ( ; ! e.at_end (); ++e) {
|
||||
|
|
@ -502,8 +504,15 @@ AsIfFlatEdges::extended (coord_type ext_b, coord_type ext_e, coord_type ext_o, c
|
|||
} else {
|
||||
|
||||
std::unique_ptr<FlatRegion> output (new FlatRegion ());
|
||||
db::PropertyMapper pm (output->properties_repository (), properties_repository ());
|
||||
|
||||
for (EdgesIterator e (begin_merged ()); ! e.at_end (); ++e) {
|
||||
output->insert (extended_edge (*e, ext_b, ext_e, ext_o, ext_i));
|
||||
db::properties_id_type prop_id = pm (e.prop_id ());
|
||||
if (prop_id != 0) {
|
||||
output->insert (db::PolygonWithProperties (extended_edge (*e, ext_b, ext_e, ext_o, ext_i), prop_id));
|
||||
} else {
|
||||
output->insert (extended_edge (*e, ext_b, ext_e, ext_o, ext_i));
|
||||
}
|
||||
}
|
||||
|
||||
return output.release ();
|
||||
|
|
@ -733,7 +742,7 @@ AsIfFlatEdges::run_check (db::edge_relation_type rel, const Edges *other, db::Co
|
|||
db::box_scanner<db::Edge, size_t> scanner (report_progress (), progress_desc ());
|
||||
scanner.reserve (count () + (other ? other->count () : 0));
|
||||
|
||||
AddressableEdgeDelivery e (begin_merged (), has_valid_merged_edges ());
|
||||
AddressableEdgeDelivery e (begin_merged ());
|
||||
|
||||
size_t n = 0;
|
||||
for ( ; ! e.at_end (); ++e) {
|
||||
|
|
@ -774,7 +783,7 @@ AsIfFlatEdges::boolean (const Edges *other, EdgeBoolOp op) const
|
|||
db::box_scanner<db::Edge, size_t> scanner (report_progress (), progress_desc ());
|
||||
scanner.reserve (count () + (other ? other->count () : 0));
|
||||
|
||||
AddressableEdgeDelivery e (begin (), has_valid_edges ());
|
||||
AddressableEdgeDelivery e (begin ());
|
||||
|
||||
for ( ; ! e.at_end (); ++e) {
|
||||
if (! e->is_degenerate ()) {
|
||||
|
|
@ -808,7 +817,7 @@ AsIfFlatEdges::boolean_andnot (const Edges *other) const
|
|||
db::box_scanner<db::Edge, size_t> scanner (report_progress (), progress_desc ());
|
||||
scanner.reserve (count () + (other ? other->count () : 0));
|
||||
|
||||
AddressableEdgeDelivery e (begin (), has_valid_edges ());
|
||||
AddressableEdgeDelivery e (begin ());
|
||||
|
||||
for ( ; ! e.at_end (); ++e) {
|
||||
if (! e->is_degenerate ()) {
|
||||
|
|
@ -876,7 +885,7 @@ AsIfFlatEdges::edge_region_op (const Region &other, db::EdgePolygonOp::mode_t mo
|
|||
EdgesDelegate *
|
||||
AsIfFlatEdges::add (const Edges &other) const
|
||||
{
|
||||
FlatEdges *other_flat = dynamic_cast<FlatEdges *> (other.delegate ());
|
||||
const FlatEdges *other_flat = dynamic_cast<const FlatEdges *> (other.delegate ());
|
||||
if (other_flat) {
|
||||
|
||||
std::unique_ptr<FlatEdges> new_edges (new FlatEdges (*other_flat));
|
||||
|
|
@ -960,10 +969,15 @@ AsIfFlatEdges::insert_into (Layout *layout, db::cell_index_type into_cell, unsig
|
|||
{
|
||||
// improves performance when inserting an original layout into the same layout
|
||||
db::LayoutLocker locker (layout);
|
||||
db::PropertyMapper pm (&layout->properties_repository (), properties_repository ());
|
||||
|
||||
db::Shapes &shapes = layout->cell (into_cell).shapes (into_layer);
|
||||
for (EdgesIterator e (begin ()); ! e.at_end (); ++e) {
|
||||
shapes.insert (*e);
|
||||
if (e.prop_id () != 0) {
|
||||
shapes.insert (db::EdgeWithProperties (*e, pm (e.prop_id ())));
|
||||
} else {
|
||||
shapes.insert (*e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -54,9 +54,9 @@ public:
|
|||
|
||||
virtual std::string to_string (size_t nmax) const;
|
||||
|
||||
virtual EdgePairsDelegate *cop_to_edge_pairs (db::CompoundRegionOperationNode &node);
|
||||
virtual RegionDelegate *cop_to_region (db::CompoundRegionOperationNode &node);
|
||||
virtual EdgesDelegate *cop_to_edges (db::CompoundRegionOperationNode &node);
|
||||
virtual EdgePairsDelegate *cop_to_edge_pairs (db::CompoundRegionOperationNode &node, PropertyConstraint prop_constraint);
|
||||
virtual RegionDelegate *cop_to_region (db::CompoundRegionOperationNode &node, db::PropertyConstraint prop_constraint);
|
||||
virtual EdgesDelegate *cop_to_edges (db::CompoundRegionOperationNode &node, db::PropertyConstraint prop_constraint);
|
||||
|
||||
EdgePairsDelegate *width_check (db::Coord d, const RegionCheckOptions &options) const;
|
||||
EdgePairsDelegate *space_check (db::Coord d, const RegionCheckOptions &options) const;
|
||||
|
|
@ -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 *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 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, PropertyConstraint prop_constraint) const;
|
||||
virtual RegionDelegate *or_with (const Region &other, PropertyConstraint prop_constraint) const;
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> andnot_with (const Region &other, PropertyConstraint property_constraint) const;
|
||||
|
||||
virtual RegionDelegate *add_in_place (const Region &other)
|
||||
{
|
||||
|
|
@ -278,11 +278,15 @@ public:
|
|||
virtual bool equals (const Region &other) const;
|
||||
virtual bool less (const Region &other) const;
|
||||
|
||||
virtual RegionDelegate *nets (LayoutToNetlist *l2n, NetPropertyMode prop_mode, const tl::Variant &net_prop_name, const std::vector<const db::Net *> *net_filter) const;
|
||||
|
||||
virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const;
|
||||
|
||||
protected:
|
||||
void update_bbox (const db::Box &box);
|
||||
void invalidate_bbox ();
|
||||
void merge_polygons_to (db::Shapes &output, bool min_coherence, unsigned int min_wc, PropertiesRepository *target_rp = 0) const;
|
||||
RegionDelegate *and_or_not_with (bool is_and, const Region &other, PropertyConstraint property_constraint) const;
|
||||
|
||||
virtual EdgePairsDelegate *run_check (db::edge_relation_type rel, bool different_polygons, const Region *other, db::Coord d, const RegionCheckOptions &options) const;
|
||||
virtual EdgePairsDelegate *run_single_polygon_check (db::edge_relation_type rel, db::Coord d, const RegionCheckOptions &options) const;
|
||||
|
|
@ -308,7 +312,6 @@ private:
|
|||
mutable db::Box m_bbox;
|
||||
|
||||
virtual db::Box compute_bbox () const;
|
||||
static RegionDelegate *region_from_box (const db::Box &b);
|
||||
EdgePairsDelegate *space_or_isolated_check (db::Coord d, const RegionCheckOptions &options, bool isolated) const;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -179,7 +179,11 @@ AsIfFlatTexts::processed_to_polygons (const TextToPolygonProcessorBase &filter)
|
|||
res_polygons.clear ();
|
||||
filter.process (*e, res_polygons);
|
||||
for (std::vector<db::Polygon>::const_iterator pr = res_polygons.begin (); pr != res_polygons.end (); ++pr) {
|
||||
region->insert (*pr);
|
||||
if (e.prop_id () != 0) {
|
||||
region->insert (db::PolygonWithProperties (*pr, e.prop_id ()));
|
||||
} else {
|
||||
region->insert (*pr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -216,7 +220,7 @@ AsIfFlatTexts::edges () const
|
|||
TextsDelegate *
|
||||
AsIfFlatTexts::add (const Texts &other) const
|
||||
{
|
||||
FlatTexts *other_flat = dynamic_cast<FlatTexts *> (other.delegate ());
|
||||
const FlatTexts *other_flat = dynamic_cast<const FlatTexts *> (other.delegate ());
|
||||
if (other_flat) {
|
||||
|
||||
std::unique_ptr<FlatTexts> new_texts (new FlatTexts (*other_flat));
|
||||
|
|
@ -330,7 +334,7 @@ AsIfFlatTexts::selected_interacting_generic (const Region &other, bool inverse)
|
|||
|
||||
db::box_scanner2<db::Text, size_t, db::Polygon, size_t> scanner (report_progress (), progress_desc ());
|
||||
|
||||
AddressableTextDelivery e (begin (), has_valid_texts ());
|
||||
AddressableTextDelivery e (begin ());
|
||||
|
||||
for ( ; ! e.at_end (); ++e) {
|
||||
scanner.insert1 (e.operator-> (), 0);
|
||||
|
|
@ -376,7 +380,7 @@ AsIfFlatTexts::pull_generic (const Region &other) const
|
|||
|
||||
db::box_scanner2<db::Text, size_t, db::Polygon, size_t> scanner (report_progress (), progress_desc ());
|
||||
|
||||
AddressableTextDelivery e (begin (), has_valid_texts ());
|
||||
AddressableTextDelivery e (begin ());
|
||||
|
||||
for ( ; ! e.at_end (); ++e) {
|
||||
scanner.insert1 (e.operator-> (), 0);
|
||||
|
|
|
|||
|
|
@ -766,7 +766,7 @@ Cell::copy_shapes (const db::Cell &source_cell, const db::LayerMapping &layer_ma
|
|||
}
|
||||
|
||||
if (target_layout != source_layout) {
|
||||
db::PropertyMapper pm (*target_layout, *source_layout);
|
||||
db::PropertyMapper pm (target_layout, source_layout);
|
||||
db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ());
|
||||
for (std::map<unsigned int, unsigned int>::const_iterator lm = layer_mapping.begin (); lm != layer_mapping.end (); ++lm) {
|
||||
shapes (lm->second).insert_transformed (source_cell.shapes (lm->first), trans, pm);
|
||||
|
|
@ -915,7 +915,7 @@ Cell::move_shapes (db::Cell &source_cell, const db::LayerMapping &layer_mapping)
|
|||
}
|
||||
|
||||
if (target_layout != source_layout) {
|
||||
db::PropertyMapper pm (*target_layout, *source_layout);
|
||||
db::PropertyMapper pm (target_layout, source_layout);
|
||||
db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ());
|
||||
for (std::map<unsigned int, unsigned int>::const_iterator lm = layer_mapping.begin (); lm != layer_mapping.end (); ++lm) {
|
||||
shapes (lm->second).insert_transformed (source_cell.shapes (lm->first), trans, pm);
|
||||
|
|
@ -988,7 +988,7 @@ Cell::move_tree (db::Cell &source_cell)
|
|||
throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout")));
|
||||
}
|
||||
|
||||
db::PropertyMapper pm (*target_layout, *source_layout);
|
||||
db::PropertyMapper pm (target_layout, source_layout);
|
||||
db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ());
|
||||
|
||||
db::CellMapping cm;
|
||||
|
|
@ -1022,7 +1022,7 @@ Cell::move_tree_shapes (db::Cell &source_cell, const db::CellMapping &cm)
|
|||
throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout")));
|
||||
}
|
||||
|
||||
db::PropertyMapper pm (*target_layout, *source_layout);
|
||||
db::PropertyMapper pm (target_layout, source_layout);
|
||||
db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ());
|
||||
|
||||
db::LayerMapping lm;
|
||||
|
|
@ -1049,7 +1049,7 @@ Cell::move_tree_shapes (db::Cell &source_cell, const db::CellMapping &cm, const
|
|||
throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout")));
|
||||
}
|
||||
|
||||
db::PropertyMapper pm (*target_layout, *source_layout);
|
||||
db::PropertyMapper pm (target_layout, source_layout);
|
||||
db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ());
|
||||
|
||||
std::vector <db::cell_index_type> source_cells;
|
||||
|
|
|
|||
|
|
@ -371,7 +371,7 @@ CellMapping::do_create_missing_mapping (db::Layout &layout_a, const db::Layout &
|
|||
|
||||
if (! new_cells.empty ()) {
|
||||
|
||||
db::PropertyMapper pm (layout_a, layout_b);
|
||||
db::PropertyMapper pm (&layout_a, &layout_b);
|
||||
|
||||
// Note: this avoids frequent cell index table rebuilds if source and target layout are identical
|
||||
layout_a.start_changes ();
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ namespace db
|
|||
ClipboardData::ClipboardData ()
|
||||
: m_layout (), m_incomplete_cells ()
|
||||
{
|
||||
m_prop_id_map.set_target (m_layout);
|
||||
m_prop_id_map.set_target (&m_layout);
|
||||
m_container_cell_index = m_layout.add_cell ("");
|
||||
}
|
||||
|
||||
|
|
@ -47,7 +47,7 @@ ClipboardData::add (const db::Layout &layout, unsigned int layer, const db::Shap
|
|||
m_layout.insert_layer (layer, layout.get_properties (layer));
|
||||
}
|
||||
|
||||
m_prop_id_map.set_source (layout);
|
||||
m_prop_id_map.set_source (&layout);
|
||||
m_layout.cell (m_container_cell_index).shapes (layer).insert (shape, m_prop_id_map);
|
||||
}
|
||||
|
||||
|
|
@ -60,7 +60,7 @@ ClipboardData::add (const db::Layout &layout, unsigned int layer, const db::Shap
|
|||
m_layout.insert_layer (layer, layout.get_properties (layer));
|
||||
}
|
||||
|
||||
m_prop_id_map.set_source (layout);
|
||||
m_prop_id_map.set_source (&layout);
|
||||
db::Shape new_shape = m_layout.cell (m_container_cell_index).shapes (layer).insert (shape, m_prop_id_map);
|
||||
m_layout.cell (m_container_cell_index).shapes (layer).transform (new_shape, trans);
|
||||
}
|
||||
|
|
@ -80,7 +80,7 @@ ClipboardData::add (const db::Layout &layout, const db::Instance &inst, unsigned
|
|||
}
|
||||
|
||||
// Insert the instance mapping the cell to the target cell_index and the property ID using the map
|
||||
m_prop_id_map.set_source (layout);
|
||||
m_prop_id_map.set_source (&layout);
|
||||
tl::const_map<db::cell_index_type> im (target_cell_index);
|
||||
m_layout.cell (m_container_cell_index).insert (inst, im, m_prop_id_map);
|
||||
}
|
||||
|
|
@ -102,7 +102,7 @@ ClipboardData::add (const db::Layout &layout, const db::Instance &inst, unsigned
|
|||
}
|
||||
|
||||
// Insert the instance mapping the cell to the target cell_index and the property ID using the map
|
||||
m_prop_id_map.set_source (layout);
|
||||
m_prop_id_map.set_source (&layout);
|
||||
tl::const_map<db::cell_index_type> im (target_cell_index);
|
||||
db::Instance new_inst = m_layout.cell (m_container_cell_index).insert (inst, im, m_prop_id_map);
|
||||
m_layout.cell (m_container_cell_index).transform (new_inst, trans);
|
||||
|
|
@ -123,7 +123,7 @@ ClipboardData::add (const db::Layout &layout, const db::Cell &cell, unsigned int
|
|||
m_context_info.erase (target_cell_index);
|
||||
}
|
||||
|
||||
m_prop_id_map.set_source (layout);
|
||||
m_prop_id_map.set_source (&layout);
|
||||
|
||||
// copy the shapes
|
||||
for (unsigned int l = 0; l < layout.layers (); ++l) {
|
||||
|
|
@ -157,7 +157,7 @@ std::vector<unsigned int>
|
|||
ClipboardData::do_insert (db::Layout &layout, const db::ICplxTrans *trans, db::Cell *cell, std::vector<db::cell_index_type> *new_tops, ClipboardDataInsertReceiver *insert_receiver) const
|
||||
{
|
||||
std::vector <unsigned int> new_layers;
|
||||
PropertyMapper prop_id_map (layout, m_layout);
|
||||
PropertyMapper prop_id_map (&layout, &m_layout);
|
||||
|
||||
std::map <db::LayerProperties, unsigned int, db::LPLogicalLessFunc> layer_map;
|
||||
for (unsigned int l = 0; l < layout.layers (); ++l) {
|
||||
|
|
|
|||
|
|
@ -1548,6 +1548,11 @@ CompoundRegionCheckOperationNode::CompoundRegionCheckOperationNode (CompoundRegi
|
|||
{
|
||||
set_description ("check");
|
||||
|
||||
// force different polygons in the different properties case to skip intra-polygon checks
|
||||
if (pc_always_different (m_options.prop_constraint)) {
|
||||
m_different_polygons = true;
|
||||
}
|
||||
|
||||
m_check.set_include_zero (false);
|
||||
m_check.set_whole_edges (options.whole_edges);
|
||||
m_check.set_ignore_angle (options.ignore_angle);
|
||||
|
|
|
|||
|
|
@ -1618,6 +1618,69 @@ private:
|
|||
tl::weak_ptr<CompoundRegionOperationNode> mp_node;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The generic local operation with property support
|
||||
*
|
||||
* This local operation executes the operation tree within a local processor.
|
||||
* When put into a local processor, the operation tree will be executed on each interaction.
|
||||
*/
|
||||
template <class TS, class TI, class TR>
|
||||
class DB_PUBLIC compound_local_operation_with_properties
|
||||
: public local_operation<db::object_with_properties<TS>, db::object_with_properties<TI>, db::object_with_properties<TR> >
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
*
|
||||
* Creates a local operation which utilizes the operation tree. "node" is the root of the operation tree.
|
||||
* Ownership of the node is *not* transferred to the local operation.
|
||||
*/
|
||||
compound_local_operation_with_properties<TS, TI, TR> (CompoundRegionOperationNode *node, db::PropertyConstraint prop_constraint, db::PropertiesRepository *target_pr, const db::PropertiesRepository *subject_pr, const std::vector<const db::PropertiesRepository *> &intruder_prs)
|
||||
: mp_node (node), m_prop_constraint (prop_constraint), m_pms (target_pr, subject_pr)
|
||||
{
|
||||
m_pmis.reserve (intruder_prs.size ());
|
||||
for (auto i = intruder_prs.begin (); i != intruder_prs.end (); ++i) {
|
||||
m_pmis.push_back (db::PropertyMapper (target_pr, *i));
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void do_compute_local (db::Layout *layout, const shape_interactions<db::object_with_properties<TS>, db::object_with_properties<TI> > &interactions, std::vector<std::unordered_set<db::object_with_properties<TR> > > &results, size_t max_vertex_count, double area_ratio) const
|
||||
{
|
||||
auto interactions_by_prop_id = separate_interactions_to_interactions_by_properties (interactions, m_prop_constraint, m_pms, m_pmis);
|
||||
for (auto s2p = interactions_by_prop_id.begin (); s2p != interactions_by_prop_id.end (); ++s2p) {
|
||||
|
||||
std::vector<std::unordered_set<TR> > results_wo_props;
|
||||
results_wo_props.resize (results.size ());
|
||||
|
||||
CompoundRegionOperationCache cache;
|
||||
mp_node->compute_local (&cache, layout, s2p->second, results_wo_props, max_vertex_count, area_ratio);
|
||||
|
||||
for (size_t n = 0; n < results.size (); ++n) {
|
||||
for (auto i = results_wo_props [n].begin (); i != results_wo_props [n].end (); ++i) {
|
||||
results [n].insert (db::object_with_properties<TR> (*i, pc_norm (m_prop_constraint, s2p->first)));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
virtual db::Coord dist () const { return mp_node->dist (); }
|
||||
virtual OnEmptyIntruderHint on_empty_intruder_hint () const { return mp_node->on_empty_intruder_hint (); }
|
||||
virtual bool requests_single_subjects () const { return true; }
|
||||
virtual std::string description () const { return mp_node->description (); }
|
||||
|
||||
const TransformationReducer *vars () const { return mp_node->vars (); }
|
||||
bool wants_variants () const { return mp_node->wants_variants (); }
|
||||
std::vector<db::Region *> inputs () const { return mp_node->inputs (); }
|
||||
|
||||
private:
|
||||
tl::weak_ptr<CompoundRegionOperationNode> mp_node;
|
||||
db::PropertyConstraint m_prop_constraint;
|
||||
mutable db::PropertyMapper m_pms;
|
||||
mutable std::vector<db::PropertyMapper> m_pmis;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ public:
|
|||
typedef db::EdgePair value_type;
|
||||
|
||||
DeepEdgePairsIterator (const db::RecursiveShapeIterator &iter)
|
||||
: m_iter (iter)
|
||||
: m_iter (iter), m_prop_id (0)
|
||||
{
|
||||
set ();
|
||||
}
|
||||
|
|
@ -72,6 +72,11 @@ public:
|
|||
return &m_edge_pair;
|
||||
}
|
||||
|
||||
virtual db::properties_id_type prop_id () const
|
||||
{
|
||||
return m_prop_id;
|
||||
}
|
||||
|
||||
virtual bool equals (const generic_shape_iterator_delegate_base<value_type> *other) const
|
||||
{
|
||||
const DeepEdgePairsIterator *o = dynamic_cast<const DeepEdgePairsIterator *> (other);
|
||||
|
|
@ -100,12 +105,14 @@ private:
|
|||
|
||||
db::RecursiveShapeIterator m_iter;
|
||||
mutable value_type m_edge_pair;
|
||||
mutable db::properties_id_type m_prop_id;
|
||||
|
||||
void set () const
|
||||
{
|
||||
if (! m_iter.at_end ()) {
|
||||
m_iter.shape ().edge_pair (m_edge_pair);
|
||||
m_iter->edge_pair (m_edge_pair);
|
||||
m_edge_pair.transform (m_iter.trans ());
|
||||
m_prop_id = m_iter->prop_id ();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -307,6 +314,21 @@ const db::RecursiveShapeIterator *DeepEdgePairs::iter () const
|
|||
return 0;
|
||||
}
|
||||
|
||||
void DeepEdgePairs::apply_property_translator (const db::PropertiesTranslator &pt)
|
||||
{
|
||||
DeepShapeCollectionDelegateBase::apply_property_translator (pt);
|
||||
}
|
||||
|
||||
db::PropertiesRepository *DeepEdgePairs::properties_repository ()
|
||||
{
|
||||
return &deep_layer ().layout ().properties_repository ();
|
||||
}
|
||||
|
||||
const db::PropertiesRepository *DeepEdgePairs::properties_repository () const
|
||||
{
|
||||
return &deep_layer ().layout ().properties_repository ();
|
||||
}
|
||||
|
||||
EdgePairsDelegate *
|
||||
DeepEdgePairs::add_in_place (const EdgePairs &other)
|
||||
{
|
||||
|
|
@ -451,7 +473,11 @@ RegionDelegate *DeepEdgePairs::polygons (db::Coord e) const
|
|||
for (db::Shapes::shape_iterator s = c->shapes (deep_layer ().layer ()).begin (db::ShapeIterator::EdgePairs); ! s.at_end (); ++s) {
|
||||
db::Polygon poly = s->edge_pair ().normalized ().to_polygon (e);
|
||||
if (poly.vertices () >= 3) {
|
||||
output.insert (db::PolygonRef (poly, layout.shape_repository ()));
|
||||
if (s->prop_id () != 0) {
|
||||
output.insert (db::PolygonRefWithProperties (db::PolygonRef (poly, layout.shape_repository ()), s->prop_id ()));
|
||||
} else {
|
||||
output.insert (db::PolygonRef (poly, layout.shape_repository ()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -469,10 +495,18 @@ EdgesDelegate *DeepEdgePairs::generic_edges (bool first, bool second) const
|
|||
for (db::Shapes::shape_iterator s = c->shapes (deep_layer ().layer ()).begin (db::ShapeIterator::EdgePairs); ! s.at_end (); ++s) {
|
||||
db::EdgePair ep = s->edge_pair ();
|
||||
if (first) {
|
||||
output.insert (ep.first ());
|
||||
if (s->prop_id () != 0) {
|
||||
output.insert (db::EdgeWithProperties (ep.first (), s->prop_id ()));
|
||||
} else {
|
||||
output.insert (ep.first ());
|
||||
}
|
||||
}
|
||||
if (second) {
|
||||
output.insert (ep.second ());
|
||||
if (s->prop_id () != 0) {
|
||||
output.insert (db::EdgeWithProperties (ep.second (), s->prop_id ()));
|
||||
} else {
|
||||
output.insert (ep.second ());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,6 +72,9 @@ public:
|
|||
virtual const db::EdgePair *nth (size_t n) const;
|
||||
virtual bool has_valid_edge_pairs () const;
|
||||
virtual const db::RecursiveShapeIterator *iter () const;
|
||||
virtual void apply_property_translator (const db::PropertiesTranslator &pt);
|
||||
virtual db::PropertiesRepository *properties_repository ();
|
||||
virtual const db::PropertiesRepository *properties_repository () const;
|
||||
|
||||
virtual EdgePairsDelegate *filter_in_place (const EdgePairFilterBase &filter);
|
||||
virtual EdgePairsDelegate *filtered (const EdgePairFilterBase &) const;
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#include "dbLocalOperation.h"
|
||||
#include "dbLocalOperationUtils.h"
|
||||
#include "dbRegionLocalOperations.h" // for db::ContainedEdgesLocalOperation
|
||||
#include "dbEdgesLocalOperations.h"
|
||||
#include "dbHierProcessor.h"
|
||||
#include "dbEmptyEdges.h"
|
||||
|
||||
|
|
@ -54,7 +55,7 @@ public:
|
|||
typedef db::Edge value_type;
|
||||
|
||||
DeepEdgesIterator (const db::RecursiveShapeIterator &iter)
|
||||
: m_iter (iter)
|
||||
: m_iter (iter), m_prop_id (0)
|
||||
{
|
||||
set ();
|
||||
}
|
||||
|
|
@ -82,6 +83,11 @@ public:
|
|||
return &m_edge;
|
||||
}
|
||||
|
||||
virtual db::properties_id_type prop_id () const
|
||||
{
|
||||
return m_prop_id;
|
||||
}
|
||||
|
||||
virtual bool equals (const generic_shape_iterator_delegate_base<value_type> *other) const
|
||||
{
|
||||
const DeepEdgesIterator *o = dynamic_cast<const DeepEdgesIterator *> (other);
|
||||
|
|
@ -110,12 +116,14 @@ private:
|
|||
|
||||
db::RecursiveShapeIterator m_iter;
|
||||
mutable value_type m_edge;
|
||||
mutable db::properties_id_type m_prop_id;
|
||||
|
||||
void set () const
|
||||
{
|
||||
if (! m_iter.at_end ()) {
|
||||
m_iter.shape ().edge (m_edge);
|
||||
m_iter->edge (m_edge);
|
||||
m_edge.transform (m_iter.trans ());
|
||||
m_prop_id = m_iter->prop_id ();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -212,12 +220,17 @@ void DeepEdges::merged_semantics_changed ()
|
|||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void DeepEdges::do_insert (const db::Edge &edge)
|
||||
void DeepEdges::do_insert (const db::Edge &edge, db::properties_id_type prop_id)
|
||||
{
|
||||
db::Layout &layout = deep_layer ().layout ();
|
||||
if (layout.begin_top_down () != layout.end_top_down ()) {
|
||||
db::Cell &top_cell = layout.cell (*layout.begin_top_down ());
|
||||
top_cell.shapes (deep_layer ().layer ()).insert (edge);
|
||||
db::Shapes &shapes = top_cell.shapes (deep_layer ().layer ());
|
||||
if (prop_id == 0) {
|
||||
shapes.insert (edge);
|
||||
} else {
|
||||
shapes.insert (db::EdgeWithProperties (edge, prop_id));
|
||||
}
|
||||
}
|
||||
|
||||
invalidate_bbox ();
|
||||
|
|
@ -441,6 +454,24 @@ DeepEdges::iter () const
|
|||
return 0;
|
||||
}
|
||||
|
||||
void DeepEdges::apply_property_translator (const db::PropertiesTranslator &pt)
|
||||
{
|
||||
DeepShapeCollectionDelegateBase::apply_property_translator (pt);
|
||||
|
||||
m_merged_edges_valid = false;
|
||||
m_merged_edges = db::DeepLayer ();
|
||||
}
|
||||
|
||||
db::PropertiesRepository *DeepEdges::properties_repository ()
|
||||
{
|
||||
return &deep_layer ().layout ().properties_repository ();
|
||||
}
|
||||
|
||||
const db::PropertiesRepository *DeepEdges::properties_repository () const
|
||||
{
|
||||
return &deep_layer ().layout ().properties_repository ();
|
||||
}
|
||||
|
||||
bool DeepEdges::equals (const Edges &other) const
|
||||
{
|
||||
const DeepEdges *other_delegate = dynamic_cast<const DeepEdges *> (other.delegate ());
|
||||
|
|
@ -481,6 +512,60 @@ public:
|
|||
}
|
||||
|
||||
db::Shapes &merged (size_t cid, db::cell_index_type ci, bool initial = true)
|
||||
{
|
||||
return compute_merged (cid, ci, initial);
|
||||
}
|
||||
|
||||
void erase (size_t cid, db::cell_index_type ci)
|
||||
{
|
||||
m_merged_cluster.erase (std::make_pair (cid, ci));
|
||||
m_property_id_per_cluster.erase (std::make_pair (cid, ci));
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<std::pair<size_t, db::cell_index_type>, db::Shapes> m_merged_cluster;
|
||||
std::map<std::pair<size_t, db::cell_index_type>, db::properties_id_type> m_property_id_per_cluster;
|
||||
std::set<std::pair<size_t, db::cell_index_type> > m_done;
|
||||
unsigned int m_layer;
|
||||
const db::hier_clusters<db::Edge> *mp_hc;
|
||||
db::box_scanner<db::Edge, size_t> m_scanner;
|
||||
|
||||
db::properties_id_type property_id (size_t cid, db::cell_index_type ci, bool initial)
|
||||
{
|
||||
std::map<std::pair<size_t, db::cell_index_type>, db::properties_id_type>::iterator s = m_property_id_per_cluster.find (std::make_pair (cid, ci));
|
||||
|
||||
// some sanity checks: initial clusters are single-use, are never generated twice and cannot be retrieved again
|
||||
if (initial) {
|
||||
tl_assert (s == m_property_id_per_cluster.end ());
|
||||
}
|
||||
|
||||
if (s != m_property_id_per_cluster.end ()) {
|
||||
return s->second;
|
||||
}
|
||||
|
||||
s = m_property_id_per_cluster.insert (std::make_pair (std::make_pair (cid, ci), db::properties_id_type (0))).first;
|
||||
|
||||
const db::connected_clusters<db::Edge> &cc = mp_hc->clusters_per_cell (ci);
|
||||
const db::local_cluster<db::Edge> &c = cc.cluster_by_id (cid);
|
||||
|
||||
if (c.begin_attr () != c.end_attr ()) {
|
||||
|
||||
s->second = *c.begin_attr ();
|
||||
|
||||
} else {
|
||||
|
||||
const db::connected_clusters<db::Edge>::connections_type &conn = cc.connections_for_cluster (cid);
|
||||
for (db::connected_clusters<db::Edge>::connections_type::const_iterator i = conn.begin (); i != conn.end () && s->second == db::properties_id_type (0); ++i) {
|
||||
s->second = property_id (i->id (), i->inst_cell_index (), false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return s->second;
|
||||
|
||||
}
|
||||
|
||||
db::Shapes &compute_merged (size_t cid, db::cell_index_type ci, bool initial)
|
||||
{
|
||||
std::map<std::pair<size_t, db::cell_index_type>, db::Shapes>::iterator s = m_merged_cluster.find (std::make_pair (cid, ci));
|
||||
|
||||
|
|
@ -498,6 +583,8 @@ public:
|
|||
|
||||
s = m_merged_cluster.insert (std::make_pair (std::make_pair (cid, ci), db::Shapes (false))).first;
|
||||
|
||||
db::properties_id_type prop_id = property_id (cid, ci, initial);
|
||||
|
||||
const db::connected_clusters<db::Edge> &cc = mp_hc->clusters_per_cell (ci);
|
||||
const db::local_cluster<db::Edge> &c = cc.cluster_by_id (cid);
|
||||
|
||||
|
|
@ -505,7 +592,7 @@ public:
|
|||
|
||||
const db::connected_clusters<db::Edge>::connections_type &conn = cc.connections_for_cluster (cid);
|
||||
for (db::connected_clusters<db::Edge>::connections_type::const_iterator i = conn.begin (); i != conn.end (); ++i) {
|
||||
const db::Shapes &cc_shapes = merged (i->id (), i->inst_cell_index (), false);
|
||||
const db::Shapes &cc_shapes = compute_merged (i->id (), i->inst_cell_index (), false);
|
||||
merged_child_clusters.push_back (std::make_pair (&cc_shapes, i->inst_trans ()));
|
||||
}
|
||||
|
||||
|
|
@ -531,18 +618,11 @@ public:
|
|||
// .. and run the merge operation
|
||||
|
||||
s->second.clear ();
|
||||
EdgeBooleanClusterCollectorToShapes cluster_collector (&s->second, EdgeOr);
|
||||
EdgeBooleanClusterCollectorToShapes cluster_collector (&s->second, EdgeOr, prop_id);
|
||||
m_scanner.process (cluster_collector, 1, db::box_convert<db::Edge> ());
|
||||
|
||||
return s->second;
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<std::pair<size_t, db::cell_index_type>, db::Shapes> m_merged_cluster;
|
||||
std::set<std::pair<size_t, db::cell_index_type> > m_done;
|
||||
unsigned int m_layer;
|
||||
const db::hier_clusters<db::Edge> *mp_hc;
|
||||
db::box_scanner<db::Edge, size_t> m_scanner;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -582,7 +662,7 @@ DeepEdges::ensure_merged_edges_valid () const
|
|||
hc.set_base_verbosity (base_verbosity() + 10);
|
||||
hc.build (layout, deep_layer ().initial_cell (), conn);
|
||||
|
||||
// collect the clusters and merge them into big polygons
|
||||
// collect the clusters and merge them into larger edges
|
||||
// NOTE: using the ClusterMerger we merge bottom-up forming bigger and bigger polygons. This is
|
||||
// hopefully more efficient that collecting everything and will lead to reuse of parts.
|
||||
|
||||
|
|
@ -596,7 +676,7 @@ DeepEdges::ensure_merged_edges_valid () const
|
|||
if (cc.is_root (*cl)) {
|
||||
db::Shapes &s = cm.merged (*cl, c->cell_index ());
|
||||
c->shapes (m_merged_edges.layer ()).insert (s);
|
||||
s.clear (); // not needed anymore
|
||||
cm.erase (*cl, c->cell_index ()); // not needed anymore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -613,6 +693,7 @@ DeepEdges::set_is_merged (bool f)
|
|||
{
|
||||
m_is_merged = f;
|
||||
m_merged_edges_valid = false;
|
||||
m_merged_edges = db::DeepLayer ();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -1187,6 +1268,8 @@ RegionDelegate *DeepEdges::extended (coord_type ext_b, coord_type ext_e, coord_t
|
|||
|
||||
if (join) {
|
||||
|
||||
// TODO: property support
|
||||
|
||||
db::hier_clusters<db::Edge> hc;
|
||||
db::Connectivity conn (db::Connectivity::EdgesConnectByPoints);
|
||||
conn.connect (edges);
|
||||
|
|
@ -1247,6 +1330,7 @@ RegionDelegate *DeepEdges::extended (coord_type ext_b, coord_type ext_e, coord_t
|
|||
|
||||
PolygonRefToShapesGenerator prgen (&layout, out);
|
||||
for (db::Shapes::shape_iterator si = c->shapes (edges.layer ()).begin (db::ShapeIterator::Edges); ! si.at_end (); ++si) {
|
||||
prgen.set_prop_id (si->prop_id ());
|
||||
prgen.put (extended_edge (si->edge ().transformed (v->first), ext_b, ext_e, ext_o, ext_i).transformed (v->first.inverted ()));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ public:
|
|||
|
||||
virtual void reserve (size_t n);
|
||||
|
||||
virtual void do_insert (const db::Edge &edge);
|
||||
virtual void do_insert (const db::Edge &edge, properties_id_type prop_id);
|
||||
|
||||
EdgesDelegate *clone () const;
|
||||
|
||||
|
|
@ -80,6 +80,9 @@ public:
|
|||
virtual bool has_valid_merged_edges () const;
|
||||
|
||||
virtual const db::RecursiveShapeIterator *iter () const;
|
||||
virtual void apply_property_translator (const db::PropertiesTranslator &pt);
|
||||
virtual db::PropertiesRepository *properties_repository ();
|
||||
virtual const db::PropertiesRepository *properties_repository () const;
|
||||
|
||||
virtual bool equals (const Edges &other) const;
|
||||
virtual bool less (const Edges &other) const;
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
#include "dbRegionLocalOperations.h"
|
||||
#include "dbLocalOperationUtils.h"
|
||||
#include "dbCompoundOperation.h"
|
||||
#include "dbLayoutToNetlist.h"
|
||||
#include "tlTimer.h"
|
||||
|
||||
namespace db
|
||||
|
|
@ -57,7 +58,7 @@ public:
|
|||
typedef db::Polygon value_type;
|
||||
|
||||
DeepRegionIterator (const db::RecursiveShapeIterator &iter)
|
||||
: m_iter (iter)
|
||||
: m_iter (iter), m_prop_id (0)
|
||||
{
|
||||
set ();
|
||||
}
|
||||
|
|
@ -85,6 +86,11 @@ public:
|
|||
return &m_polygon;
|
||||
}
|
||||
|
||||
virtual db::properties_id_type prop_id () const
|
||||
{
|
||||
return m_prop_id;
|
||||
}
|
||||
|
||||
virtual bool equals (const generic_shape_iterator_delegate_base<value_type> *other) const
|
||||
{
|
||||
const DeepRegionIterator *o = dynamic_cast<const DeepRegionIterator *> (other);
|
||||
|
|
@ -113,12 +119,14 @@ private:
|
|||
|
||||
db::RecursiveShapeIterator m_iter;
|
||||
mutable value_type m_polygon;
|
||||
mutable db::properties_id_type m_prop_id;
|
||||
|
||||
void set () const
|
||||
{
|
||||
if (! m_iter.at_end ()) {
|
||||
m_iter.shape ().polygon (m_polygon);
|
||||
m_iter->polygon (m_polygon);
|
||||
m_polygon.transform (m_iter.trans (), false);
|
||||
m_prop_id = m_iter->prop_id ();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -220,12 +228,17 @@ void DeepRegion::min_coherence_changed ()
|
|||
set_is_merged (false);
|
||||
}
|
||||
|
||||
void DeepRegion::do_insert (const db::Polygon &polygon)
|
||||
void DeepRegion::do_insert (const db::Polygon &polygon, db::properties_id_type prop_id)
|
||||
{
|
||||
db::Layout &layout = deep_layer ().layout ();
|
||||
if (layout.begin_top_down () != layout.end_top_down ()) {
|
||||
db::Cell &top_cell = layout.cell (*layout.begin_top_down ());
|
||||
top_cell.shapes (deep_layer ().layer ()).insert (db::PolygonRef (polygon, layout.shape_repository ()));
|
||||
db::Shapes &shapes = top_cell.shapes (deep_layer ().layer ());
|
||||
if (prop_id == 0) {
|
||||
shapes.insert (db::PolygonRef (polygon, layout.shape_repository ()));
|
||||
} else {
|
||||
shapes.insert (db::PolygonRefWithProperties (db::PolygonRef (polygon, layout.shape_repository ()), prop_id));
|
||||
}
|
||||
}
|
||||
|
||||
invalidate_bbox ();
|
||||
|
|
@ -339,11 +352,16 @@ flatten_layer (db::DeepLayer &deep_layer)
|
|||
db::Cell &top_cell = layout.cell (*layout.begin_top_down ());
|
||||
|
||||
db::Shapes flat_shapes (layout.is_editable ());
|
||||
|
||||
for (db::RecursiveShapeIterator iter (layout, top_cell, deep_layer.layer ()); !iter.at_end (); ++iter) {
|
||||
if (iter->is_polygon ()) {
|
||||
db::Polygon poly;
|
||||
iter->polygon (poly);
|
||||
flat_shapes.insert (db::PolygonRef (poly.transformed (iter.trans ()), layout.shape_repository ()));
|
||||
if (! iter->prop_id ()) {
|
||||
flat_shapes.insert (db::PolygonRef (poly.transformed (iter.trans ()), layout.shape_repository ()));
|
||||
} else {
|
||||
flat_shapes.insert (db::PolygonRefWithProperties (db::PolygonRef (poly.transformed (iter.trans ()), layout.shape_repository ()), iter->prop_id ()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -439,6 +457,12 @@ DeepRegion::nth (size_t) const
|
|||
throw tl::Exception (tl::to_string (tr ("Random access to polygons is available only for flat regions")));
|
||||
}
|
||||
|
||||
db::properties_id_type
|
||||
DeepRegion::nth_prop_id (size_t) const
|
||||
{
|
||||
throw tl::Exception (tl::to_string (tr ("Random access to polygons is available only for flat regions")));
|
||||
}
|
||||
|
||||
bool
|
||||
DeepRegion::has_valid_polygons () const
|
||||
{
|
||||
|
|
@ -457,6 +481,24 @@ DeepRegion::iter () const
|
|||
return 0;
|
||||
}
|
||||
|
||||
void DeepRegion::apply_property_translator (const db::PropertiesTranslator &pt)
|
||||
{
|
||||
DeepShapeCollectionDelegateBase::apply_property_translator (pt);
|
||||
|
||||
m_merged_polygons_valid = false;
|
||||
m_merged_polygons = db::DeepLayer ();
|
||||
}
|
||||
|
||||
db::PropertiesRepository *DeepRegion::properties_repository ()
|
||||
{
|
||||
return &deep_layer ().layout ().properties_repository ();
|
||||
}
|
||||
|
||||
const db::PropertiesRepository *DeepRegion::properties_repository () const
|
||||
{
|
||||
return &deep_layer ().layout ().properties_repository ();
|
||||
}
|
||||
|
||||
bool
|
||||
DeepRegion::equals (const Region &other) const
|
||||
{
|
||||
|
|
@ -504,16 +546,53 @@ public:
|
|||
void erase (size_t cid, db::cell_index_type ci)
|
||||
{
|
||||
m_merged_cluster.erase (std::make_pair (cid, ci));
|
||||
m_property_id_per_cluster.erase (std::make_pair (cid, ci));
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<std::pair<size_t, db::cell_index_type>, db::Shapes> m_merged_cluster;
|
||||
std::map<std::pair<size_t, db::cell_index_type>, db::properties_id_type> m_property_id_per_cluster;
|
||||
unsigned int m_layer;
|
||||
db::Layout *mp_layout;
|
||||
const db::hier_clusters<db::PolygonRef> *mp_hc;
|
||||
bool m_min_coherence;
|
||||
db::EdgeProcessor m_ep;
|
||||
|
||||
db::properties_id_type property_id (size_t cid, db::cell_index_type ci, bool initial)
|
||||
{
|
||||
std::map<std::pair<size_t, db::cell_index_type>, db::properties_id_type>::iterator s = m_property_id_per_cluster.find (std::make_pair (cid, ci));
|
||||
|
||||
// some sanity checks: initial clusters are single-use, are never generated twice and cannot be retrieved again
|
||||
if (initial) {
|
||||
tl_assert (s == m_property_id_per_cluster.end ());
|
||||
}
|
||||
|
||||
if (s != m_property_id_per_cluster.end ()) {
|
||||
return s->second;
|
||||
}
|
||||
|
||||
s = m_property_id_per_cluster.insert (std::make_pair (std::make_pair (cid, ci), db::properties_id_type (0))).first;
|
||||
|
||||
const db::connected_clusters<db::PolygonRef> &cc = mp_hc->clusters_per_cell (ci);
|
||||
const db::local_cluster<db::PolygonRef> &c = cc.cluster_by_id (cid);
|
||||
|
||||
if (c.begin_attr () != c.end_attr ()) {
|
||||
|
||||
s->second = *c.begin_attr ();
|
||||
|
||||
} else {
|
||||
|
||||
const db::connected_clusters<db::PolygonRef>::connections_type &conn = cc.connections_for_cluster (cid);
|
||||
for (db::connected_clusters<db::PolygonRef>::connections_type::const_iterator i = conn.begin (); i != conn.end () && s->second == db::properties_id_type (0); ++i) {
|
||||
s->second = property_id (i->id (), i->inst_cell_index (), false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return s->second;
|
||||
|
||||
}
|
||||
|
||||
db::Shapes &compute_merged (size_t cid, db::cell_index_type ci, bool initial, unsigned int min_wc)
|
||||
{
|
||||
std::map<std::pair<size_t, db::cell_index_type>, db::Shapes>::iterator s = m_merged_cluster.find (std::make_pair (cid, ci));
|
||||
|
|
@ -529,6 +608,8 @@ private:
|
|||
|
||||
s = m_merged_cluster.insert (std::make_pair (std::make_pair (cid, ci), db::Shapes (false))).first;
|
||||
|
||||
db::properties_id_type prop_id = property_id (cid, ci, initial);
|
||||
|
||||
const db::connected_clusters<db::PolygonRef> &cc = mp_hc->clusters_per_cell (ci);
|
||||
const db::local_cluster<db::PolygonRef> &c = cc.cluster_by_id (cid);
|
||||
|
||||
|
|
@ -580,7 +661,7 @@ private:
|
|||
|
||||
// and run the merge step
|
||||
db::MergeOp op (min_wc);
|
||||
db::PolygonRefToShapesGenerator pr (mp_layout, &s->second);
|
||||
db::PolygonRefToShapesGenerator pr (mp_layout, &s->second, prop_id);
|
||||
db::PolygonGenerator pg (pr, false /*don't resolve holes*/, m_min_coherence);
|
||||
m_ep.process (pg, op);
|
||||
|
||||
|
|
@ -629,7 +710,7 @@ DeepRegion::ensure_merged_polygons_valid () const
|
|||
db::Connectivity conn;
|
||||
conn.connect (deep_layer ());
|
||||
hc.set_base_verbosity (base_verbosity () + 10);
|
||||
hc.build (layout, deep_layer ().initial_cell (), conn);
|
||||
hc.build (layout, deep_layer ().initial_cell (), conn, 0, 0, true /*separate_attributes*/);
|
||||
|
||||
// collect the clusters and merge them into big polygons
|
||||
// NOTE: using the ClusterMerger we merge bottom-up forming bigger and bigger polygons. This is
|
||||
|
|
@ -662,6 +743,7 @@ DeepRegion::set_is_merged (bool f)
|
|||
{
|
||||
m_is_merged = f;
|
||||
m_merged_polygons_valid = false;
|
||||
m_merged_polygons = db::DeepLayer ();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -671,131 +753,194 @@ DeepRegion::insert_into (db::Layout *layout, db::cell_index_type into_cell, unsi
|
|||
}
|
||||
|
||||
RegionDelegate *
|
||||
DeepRegion::and_with (const Region &other) const
|
||||
DeepRegion::nets (LayoutToNetlist *l2n, NetPropertyMode prop_mode, const tl::Variant &net_prop_name, const std::vector<const db::Net *> *nets) const
|
||||
{
|
||||
db::NetBuilder &net_builder = deep_layer ().store_non_const ()->net_builder_for (l2n);
|
||||
|
||||
if (&l2n->dss () != deep_layer ().store ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("Extracted netlist is from different scope as this layer - cannot pull net shapes")));
|
||||
}
|
||||
|
||||
DeepLayer result = deep_layer ().derived ();
|
||||
|
||||
std::unique_ptr<db::Region> region_for_layer (l2n->layer_by_original (this));
|
||||
if (! region_for_layer) {
|
||||
throw tl::Exception (tl::to_string (tr ("The given layer is not an original layer used in netlist extraction")));
|
||||
}
|
||||
|
||||
std::map<unsigned int, const db::Region *> lmap;
|
||||
lmap.insert (std::make_pair (result.layer (), region_for_layer.get ()));
|
||||
|
||||
net_builder.build_nets (nets, lmap, prop_mode, net_prop_name);
|
||||
|
||||
return new db::DeepRegion (result);
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
DeepRegion::and_with (const Region &other, PropertyConstraint property_constraint) const
|
||||
{
|
||||
const DeepRegion *other_deep = dynamic_cast <const DeepRegion *> (other.delegate ());
|
||||
|
||||
if (empty ()) {
|
||||
|
||||
return clone ();
|
||||
return clone ()->remove_properties (pc_remove (property_constraint));
|
||||
|
||||
} else if (other.empty ()) {
|
||||
|
||||
return other.delegate ()->clone ();
|
||||
return other.delegate ()->clone ()->remove_properties (pc_remove (property_constraint));
|
||||
|
||||
} 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 ());
|
||||
|
||||
if (empty () || other.empty ()) {
|
||||
|
||||
return clone ();
|
||||
return clone ()->remove_properties (pc_remove (property_constraint));
|
||||
|
||||
} 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));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
DeepRegion::or_with (const Region &other) const
|
||||
DeepRegion::or_with (const Region &other, db::PropertyConstraint /*property_constraint*/) const
|
||||
{
|
||||
// TODO: implement property_constraint
|
||||
RegionDelegate *res = add (other);
|
||||
return res->merged_in_place ();
|
||||
}
|
||||
|
||||
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 ());
|
||||
|
||||
if (empty ()) {
|
||||
|
||||
return std::make_pair (clone (), clone ());
|
||||
return std::make_pair (clone ()->remove_properties (pc_remove (property_constraint)), clone ()->remove_properties (pc_remove (property_constraint)));
|
||||
|
||||
} else if (other.empty ()) {
|
||||
|
||||
return std::make_pair (other.delegate ()->clone (), clone ());
|
||||
return std::make_pair (other.delegate ()->clone ()->remove_properties (pc_remove (property_constraint)), clone ()->remove_properties (pc_remove (property_constraint)));
|
||||
|
||||
} 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 (pc_skip (property_constraint)) {
|
||||
|
||||
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 ());
|
||||
configure_proc (proc);
|
||||
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, &dl_out.layout ().properties_repository (), &deep_layer ().layout ().properties_repository (), &other->deep_layer ().layout ().properties_repository (), 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 ());
|
||||
configure_proc (proc);
|
||||
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
|
||||
{
|
||||
DeepLayer dl_out1 (deep_layer ().derived ());
|
||||
DeepLayer dl_out2 (deep_layer ().derived ());
|
||||
|
||||
db::TwoBoolAndNotLocalOperation op;
|
||||
if (pc_skip (property_constraint)) {
|
||||
|
||||
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::TwoBoolAndNotLocalOperation op;
|
||||
|
||||
std::vector<unsigned int> il;
|
||||
il.push_back (other->deep_layer ().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 ());
|
||||
configure_proc (proc);
|
||||
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 ());
|
||||
|
||||
std::vector<unsigned int> ol;
|
||||
ol.push_back (dl_out1.layer ());
|
||||
ol.push_back (dl_out2.layer ());
|
||||
std::vector<unsigned int> il;
|
||||
il.push_back (other->deep_layer ().layer ());
|
||||
|
||||
proc.run (&op, deep_layer ().layer (), il, ol);
|
||||
std::vector<unsigned int> ol;
|
||||
ol.push_back (dl_out1.layer ());
|
||||
ol.push_back (dl_out2.layer ());
|
||||
|
||||
proc.run (&op, deep_layer ().layer (), il, ol);
|
||||
|
||||
} else {
|
||||
|
||||
db::PropertiesRepository *pr_out1 = &dl_out1.layout ().properties_repository ();
|
||||
db::PropertiesRepository *pr_out2 = &dl_out2.layout ().properties_repository ();
|
||||
const db::PropertiesRepository *pr = &deep_layer ().layout ().properties_repository ();
|
||||
db::TwoBoolAndNotLocalOperationWithProperties op (pr_out1, pr_out2, pr, pr, 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 ());
|
||||
configure_proc (proc);
|
||||
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 ());
|
||||
|
||||
std::vector<unsigned int> il;
|
||||
il.push_back (other->deep_layer ().layer ());
|
||||
|
||||
std::vector<unsigned int> ol;
|
||||
ol.push_back (dl_out1.layer ());
|
||||
ol.push_back (dl_out2.layer ());
|
||||
|
||||
proc.run (&op, deep_layer ().layer (), il, ol);
|
||||
|
||||
}
|
||||
|
||||
return std::make_pair (dl_out1, dl_out2);
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
DeepRegion::xor_with (const Region &other) const
|
||||
DeepRegion::xor_with (const Region &other, db::PropertyConstraint property_constraint) const
|
||||
{
|
||||
const DeepRegion *other_deep = dynamic_cast <const DeepRegion *> (other.delegate ());
|
||||
|
||||
|
|
@ -811,14 +956,14 @@ DeepRegion::xor_with (const Region &other) const
|
|||
|
||||
} else if (! other_deep) {
|
||||
|
||||
return AsIfFlatRegion::xor_with (other);
|
||||
return AsIfFlatRegion::xor_with (other, property_constraint);
|
||||
|
||||
} else {
|
||||
|
||||
// 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, property_constraint));
|
||||
DeepLayer n2 (other_deep->and_or_not_with (this, false, property_constraint));
|
||||
|
||||
n1.add_from (n2);
|
||||
return new DeepRegion (n1);
|
||||
|
|
@ -1168,89 +1313,13 @@ DeepRegion::snapped (db::Coord gx, db::Coord gy)
|
|||
return res.release ();
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
class PolygonToEdgeLocalOperation
|
||||
: public local_operation<db::PolygonRef, db::PolygonRef, db::Edge>
|
||||
{
|
||||
public:
|
||||
PolygonToEdgeLocalOperation ()
|
||||
: local_operation<db::PolygonRef, db::PolygonRef, db::Edge> ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
virtual db::Coord dist () const { return 1; }
|
||||
virtual bool requests_single_subjects () const { return true; }
|
||||
virtual std::string description () const { return std::string ("polygon to edges"); }
|
||||
|
||||
virtual void do_compute_local (db::Layout * /*layout*/, const shape_interactions<db::PolygonRef, db::PolygonRef> &interactions, std::vector<std::unordered_set<db::Edge> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const
|
||||
{
|
||||
db::EdgeProcessor ep;
|
||||
ep.set_base_verbosity (50);
|
||||
|
||||
for (shape_interactions<db::PolygonRef, db::PolygonRef>::subject_iterator s = interactions.begin_subjects (); s != interactions.end_subjects (); ++s) {
|
||||
ep.insert (s->second);
|
||||
}
|
||||
|
||||
if (interactions.num_intruders () == 0) {
|
||||
|
||||
db::EdgeToEdgeSetGenerator eg (results.front ());
|
||||
db::MergeOp op (0);
|
||||
ep.process (eg, op);
|
||||
|
||||
} else {
|
||||
|
||||
// With intruders: to compute our local contribution we take the edges without and with intruders
|
||||
// and deliver what is in both sets
|
||||
|
||||
db::MergeOp op (0);
|
||||
|
||||
std::vector<Edge> edges1;
|
||||
db::EdgeContainer ec1 (edges1);
|
||||
ep.process (ec1, op);
|
||||
|
||||
ep.clear ();
|
||||
|
||||
for (shape_interactions<db::PolygonRef, db::PolygonRef>::subject_iterator s = interactions.begin_subjects (); s != interactions.end_subjects (); ++s) {
|
||||
ep.insert (s->second);
|
||||
}
|
||||
for (shape_interactions<db::PolygonRef, db::PolygonRef>::intruder_iterator i = interactions.begin_intruders (); i != interactions.end_intruders (); ++i) {
|
||||
ep.insert (i->second.second);
|
||||
}
|
||||
|
||||
std::vector<Edge> edges2;
|
||||
db::EdgeContainer ec2 (edges2);
|
||||
ep.process (ec2, op);
|
||||
|
||||
// Runs the boolean AND between the result with and without intruders
|
||||
|
||||
db::box_scanner<db::Edge, size_t> scanner;
|
||||
scanner.reserve (edges1.size () + edges2.size ());
|
||||
|
||||
for (std::vector<Edge>::const_iterator i = edges1.begin (); i != edges1.end (); ++i) {
|
||||
scanner.insert (i.operator-> (), 0);
|
||||
}
|
||||
for (std::vector<Edge>::const_iterator i = edges2.begin (); i != edges2.end (); ++i) {
|
||||
scanner.insert (i.operator-> (), 1);
|
||||
}
|
||||
|
||||
EdgeBooleanClusterCollector<std::unordered_set<db::Edge> > cluster_collector (&results.front (), EdgeAnd);
|
||||
scanner.process (cluster_collector, 1, db::box_convert<db::Edge> ());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
EdgesDelegate *
|
||||
DeepRegion::edges (const EdgeFilterBase *filter) const
|
||||
{
|
||||
std::unique_ptr<db::DeepEdges> res (new db::DeepEdges (deep_layer ().derived ()));
|
||||
|
||||
if (empty ()) {
|
||||
return new db::DeepEdges (deep_layer ().derived ());
|
||||
return res.release ();
|
||||
}
|
||||
|
||||
if (! filter && merged_semantics () && ! merged_polygons_available ()) {
|
||||
|
|
@ -1259,29 +1328,22 @@ DeepRegion::edges (const EdgeFilterBase *filter) const
|
|||
|
||||
const db::DeepLayer &polygons = deep_layer ();
|
||||
|
||||
db::PolygonToEdgeLocalOperation op;
|
||||
db::PolygonToEdgeLocalOperation op (res->properties_repository (), &polygons.layout ().properties_repository ());
|
||||
|
||||
db::local_processor<db::PolygonRef, db::PolygonRef, db::Edge> proc (const_cast<db::Layout *> (&polygons.layout ()),
|
||||
const_cast<db::Cell *> (&polygons.initial_cell ()),
|
||||
polygons.breakout_cells ());
|
||||
db::local_processor<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::EdgeWithProperties> proc (&res->deep_layer ().layout (), &res->deep_layer ().initial_cell (), polygons.breakout_cells ());
|
||||
|
||||
proc.set_description (progress_desc ());
|
||||
proc.set_report_progress (report_progress ());
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
configure_proc (proc);
|
||||
proc.set_threads (polygons.store ()->threads ());
|
||||
|
||||
// a boolean core makes somewhat better hierarchy
|
||||
proc.set_boolean_core (true);
|
||||
|
||||
std::unique_ptr<db::DeepEdges> res (new db::DeepEdges (polygons.derived ()));
|
||||
|
||||
proc.run (&op, polygons.layer (), foreign_idlayer (), res->deep_layer ().layer ());
|
||||
|
||||
return res.release ();
|
||||
|
||||
} else {
|
||||
|
||||
const db::DeepLayer &polygons = merged_deep_layer ();
|
||||
db::PropertyMapper pm (res->properties_repository (), &polygons.layout ().properties_repository ());
|
||||
|
||||
std::unique_ptr<VariantsCollectorBase> vars;
|
||||
|
||||
|
|
@ -1298,7 +1360,6 @@ DeepRegion::edges (const EdgeFilterBase *filter) const
|
|||
|
||||
db::Layout &layout = const_cast<db::Layout &> (polygons.layout ());
|
||||
|
||||
std::unique_ptr<db::DeepEdges> res (new db::DeepEdges (polygons.derived ()));
|
||||
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
|
||||
|
||||
db::ICplxTrans tr;
|
||||
|
|
@ -1318,7 +1379,7 @@ DeepRegion::edges (const EdgeFilterBase *filter) const
|
|||
|
||||
for (db::Polygon::polygon_edge_iterator e = poly.begin_edge (); ! e.at_end (); ++e) {
|
||||
if (! filter || filter->selected ((*e).transformed (tr))) {
|
||||
st.insert (*e);
|
||||
st.insert (db::EdgeWithProperties (*e, pm (si->prop_id ())));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1327,9 +1388,10 @@ DeepRegion::edges (const EdgeFilterBase *filter) const
|
|||
}
|
||||
|
||||
res->set_is_merged (merged_semantics () || is_merged ());
|
||||
return res.release ();
|
||||
|
||||
}
|
||||
|
||||
return res.release ();
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
|
|
@ -1593,6 +1655,7 @@ DeepRegion::sized (coord_type d, unsigned int mode) const
|
|||
db::SizingPolygonFilter siz (pg2, d_with_mag, d_with_mag, mode);
|
||||
|
||||
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) {
|
||||
pr.set_prop_id (si->prop_id ());
|
||||
db::Polygon poly;
|
||||
si->polygon (poly);
|
||||
siz.put (poly);
|
||||
|
|
@ -1655,6 +1718,7 @@ DeepRegion::sized (coord_type dx, coord_type dy, unsigned int mode) const
|
|||
db::SizingPolygonFilter siz (pg2, dx_with_mag, dy_with_mag, mode);
|
||||
|
||||
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) {
|
||||
pr.set_prop_id (si->prop_id ());
|
||||
db::Polygon poly;
|
||||
si->polygon (poly);
|
||||
siz.put (poly);
|
||||
|
|
@ -1683,17 +1747,16 @@ Output *region_cop_impl (DeepRegion *region, db::CompoundRegionOperationNode &no
|
|||
}
|
||||
}
|
||||
|
||||
db::local_processor<db::PolygonRef, db::PolygonRef, TR> proc (const_cast<db::Layout *> (®ion->deep_layer ().layout ()),
|
||||
const_cast<db::Cell *> (®ion->deep_layer ().initial_cell ()),
|
||||
region->deep_layer ().breakout_cells ());
|
||||
const db::DeepLayer &polygons (region->merged_deep_layer ());
|
||||
std::unique_ptr<Output> res (new Output (polygons.derived ()));
|
||||
|
||||
db::local_processor<db::PolygonRef, db::PolygonRef, TR> proc (&res->deep_layer ().layout (), &res->deep_layer ().initial_cell (), region->deep_layer ().breakout_cells ());
|
||||
|
||||
proc.set_description (region->progress_desc ());
|
||||
proc.set_report_progress (region->report_progress ());
|
||||
proc.set_base_verbosity (region->base_verbosity ());
|
||||
proc.set_threads (region->deep_layer ().store ()->threads ());
|
||||
|
||||
const db::DeepLayer &polygons (region->merged_deep_layer ());
|
||||
|
||||
std::vector<unsigned int> other_layers;
|
||||
for (std::vector<db::Region *>::const_iterator i = inputs.begin (); i != inputs.end (); ++i) {
|
||||
|
||||
|
|
@ -1714,41 +1777,108 @@ Output *region_cop_impl (DeepRegion *region, db::CompoundRegionOperationNode &no
|
|||
|
||||
}
|
||||
|
||||
std::unique_ptr<Output> res (new Output (polygons.derived ()));
|
||||
compound_local_operation<db::PolygonRef, db::PolygonRef, TR> op (&node);
|
||||
proc.run (&op, polygons.layer (), other_layers, res->deep_layer ().layer ());
|
||||
|
||||
return res.release ();
|
||||
}
|
||||
|
||||
EdgePairsDelegate *
|
||||
DeepRegion::cop_to_edge_pairs (db::CompoundRegionOperationNode &node)
|
||||
template <class TR, class Output>
|
||||
static
|
||||
Output *region_cop_with_properties_impl (DeepRegion *region, db::CompoundRegionOperationNode &node, db::PropertyConstraint prop_constraint)
|
||||
{
|
||||
DeepEdgePairs *output = region_cop_impl<db::EdgePair, DeepEdgePairs> (this, node);
|
||||
// Fall back to flat mode if one of the inputs is flat
|
||||
std::vector<db::Region *> inputs = node.inputs ();
|
||||
for (std::vector<db::Region *>::const_iterator i = inputs.begin (); i != inputs.end (); ++i) {
|
||||
if (! is_subject_regionptr (*i) && ! dynamic_cast<const db::DeepRegion *> ((*i)->delegate ())) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
const db::DeepLayer &polygons (region->merged_deep_layer ());
|
||||
std::unique_ptr<Output> res (new Output (polygons.derived ()));
|
||||
|
||||
db::local_processor<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::object_with_properties<TR> > proc (&res->deep_layer ().layout (), &res->deep_layer ().initial_cell (), region->deep_layer ().breakout_cells ());
|
||||
|
||||
proc.set_description (region->progress_desc ());
|
||||
proc.set_report_progress (region->report_progress ());
|
||||
proc.set_base_verbosity (region->base_verbosity ());
|
||||
proc.set_threads (region->deep_layer ().store ()->threads ());
|
||||
|
||||
std::vector<unsigned int> other_layers;
|
||||
std::vector<const db::PropertiesRepository *> intruder_prs;
|
||||
const db::PropertiesRepository *subject_pr = &polygons.layout ().properties_repository ();
|
||||
|
||||
for (std::vector<db::Region *>::const_iterator i = inputs.begin (); i != inputs.end (); ++i) {
|
||||
|
||||
if (is_subject_regionptr (*i)) {
|
||||
if (*i == subject_regionptr ()) {
|
||||
other_layers.push_back (subject_idlayer ());
|
||||
} else {
|
||||
other_layers.push_back (foreign_idlayer ());
|
||||
}
|
||||
intruder_prs.push_back (subject_pr);
|
||||
} else {
|
||||
const db::DeepRegion *other_deep = dynamic_cast<const db::DeepRegion *> ((*i)->delegate ());
|
||||
tl_assert (other_deep != 0);
|
||||
if (&other_deep->deep_layer ().layout () != ®ion->deep_layer ().layout () || &other_deep->deep_layer ().initial_cell () != ®ion->deep_layer ().initial_cell ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("Complex DeepRegion operations need to use the same layout and top cell for all inputs")));
|
||||
}
|
||||
other_layers.push_back (other_deep->deep_layer ().layer ());
|
||||
intruder_prs.push_back (other_deep->properties_repository ());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
compound_local_operation_with_properties<db::PolygonRef, db::PolygonRef, TR> op (&node, prop_constraint, res->properties_repository (), subject_pr, intruder_prs);
|
||||
proc.run (&op, polygons.layer (), other_layers, res->deep_layer ().layer ());
|
||||
|
||||
return res.release ();
|
||||
}
|
||||
|
||||
EdgePairsDelegate *
|
||||
DeepRegion::cop_to_edge_pairs (db::CompoundRegionOperationNode &node, db::PropertyConstraint prop_constraint)
|
||||
{
|
||||
DeepEdgePairs *output = 0;
|
||||
if (pc_skip (prop_constraint)) {
|
||||
output = region_cop_impl<db::EdgePair, DeepEdgePairs> (this, node);
|
||||
} else {
|
||||
output = region_cop_with_properties_impl<db::EdgePair, DeepEdgePairs> (this, node, prop_constraint);
|
||||
}
|
||||
if (! output) {
|
||||
return AsIfFlatRegion::cop_to_edge_pairs (node);
|
||||
return AsIfFlatRegion::cop_to_edge_pairs (node, prop_constraint);
|
||||
} else {
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
DeepRegion::cop_to_region (db::CompoundRegionOperationNode &node)
|
||||
DeepRegion::cop_to_region (db::CompoundRegionOperationNode &node, db::PropertyConstraint prop_constraint)
|
||||
{
|
||||
DeepRegion *output = region_cop_impl<db::PolygonRef, db::DeepRegion> (this, node);
|
||||
DeepRegion *output = 0;
|
||||
if (pc_skip (prop_constraint)) {
|
||||
output = region_cop_impl<db::PolygonRef, db::DeepRegion> (this, node);
|
||||
} else {
|
||||
output = region_cop_with_properties_impl<db::PolygonRef, DeepRegion> (this, node, prop_constraint);
|
||||
}
|
||||
if (! output) {
|
||||
return AsIfFlatRegion::cop_to_region (node);
|
||||
return AsIfFlatRegion::cop_to_region (node, prop_constraint);
|
||||
} else {
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
||||
EdgesDelegate *
|
||||
DeepRegion::cop_to_edges (db::CompoundRegionOperationNode &node)
|
||||
DeepRegion::cop_to_edges (db::CompoundRegionOperationNode &node, db::PropertyConstraint prop_constraint)
|
||||
{
|
||||
DeepEdges *output = region_cop_impl<db::Edge, db::DeepEdges> (this, node);
|
||||
DeepEdges *output = 0;
|
||||
if (pc_skip (prop_constraint)) {
|
||||
output = region_cop_impl<db::Edge, DeepEdges> (this, node);
|
||||
} else {
|
||||
output = region_cop_with_properties_impl<db::Edge, DeepEdges> (this, node, prop_constraint);
|
||||
}
|
||||
if (! output) {
|
||||
return AsIfFlatRegion::cop_to_edges (node);
|
||||
return AsIfFlatRegion::cop_to_edges (node, prop_constraint);
|
||||
} else {
|
||||
return output;
|
||||
}
|
||||
|
|
@ -1763,6 +1893,11 @@ DeepRegion::run_check (db::edge_relation_type rel, bool different_polygons, cons
|
|||
return new db::DeepEdgePairs (deep_layer ().derived ());
|
||||
}
|
||||
|
||||
// force different polygons in the different properties case to skip intra-polygon checks
|
||||
if (pc_always_different (options.prop_constraint)) {
|
||||
different_polygons = true;
|
||||
}
|
||||
|
||||
const db::DeepRegion *other_deep = 0;
|
||||
unsigned int other_layer = 0;
|
||||
bool other_is_merged = true;
|
||||
|
|
@ -1782,6 +1917,7 @@ DeepRegion::run_check (db::edge_relation_type rel, bool different_polygons, cons
|
|||
return db::AsIfFlatRegion::run_check (rel, different_polygons, other, d, options);
|
||||
}
|
||||
if (! other->merged_semantics ()) {
|
||||
other_layer = other_deep->deep_layer ().layer ();
|
||||
other_is_merged = true;
|
||||
} else if (options.whole_edges) {
|
||||
// NOTE: whole edges needs both inputs merged
|
||||
|
|
@ -1804,21 +1940,40 @@ DeepRegion::run_check (db::edge_relation_type rel, bool different_polygons, cons
|
|||
|
||||
std::unique_ptr<db::DeepEdgePairs> res (new db::DeepEdgePairs (polygons.derived ()));
|
||||
|
||||
db::CheckLocalOperation op (check, different_polygons, primary_is_merged, other_deep != 0, other_is_merged, options);
|
||||
db::Layout *subject_layout = &res->deep_layer ().layout ();
|
||||
db::Cell *subject_top = &res->deep_layer ().initial_cell ();
|
||||
const db::Layout *intruder_layout = other_deep ? &other_deep->deep_layer ().layout () : &polygons.layout ();
|
||||
const db::Cell *intruder_top = other_deep ? &other_deep->deep_layer ().initial_cell () : &polygons.initial_cell ();
|
||||
const std::set<db::cell_index_type> *subject_breakout_cells = deep_layer ().breakout_cells ();
|
||||
const std::set<db::cell_index_type> *intruder_breakout_cells = other_deep ? other_deep->deep_layer ().breakout_cells () : 0;
|
||||
|
||||
db::local_processor<db::PolygonRef, db::PolygonRef, db::EdgePair> proc (const_cast<db::Layout *> (&polygons.layout ()),
|
||||
const_cast<db::Cell *> (&polygons.initial_cell ()),
|
||||
other_deep ? &other_deep->deep_layer ().layout () : const_cast<db::Layout *> (&polygons.layout ()),
|
||||
other_deep ? &other_deep->deep_layer ().initial_cell () : const_cast<db::Cell *> (&polygons.initial_cell ()),
|
||||
deep_layer ().breakout_cells (),
|
||||
other_deep ? other_deep->deep_layer ().breakout_cells () : 0);
|
||||
if (options.prop_constraint == db::IgnoreProperties) {
|
||||
|
||||
proc.set_description (progress_desc ());
|
||||
proc.set_report_progress (report_progress ());
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
proc.set_threads (polygons.store ()->threads ());
|
||||
db::CheckLocalOperation op (check, different_polygons, primary_is_merged, other_deep != 0, other_is_merged, options);
|
||||
|
||||
proc.run (&op, polygons.layer (), other_layer, res->deep_layer ().layer ());
|
||||
db::local_processor<db::PolygonRef, db::PolygonRef, db::EdgePair> proc (subject_layout, subject_top,
|
||||
intruder_layout, intruder_top,
|
||||
subject_breakout_cells, intruder_breakout_cells);
|
||||
|
||||
configure_proc (proc);
|
||||
proc.set_threads (polygons.store ()->threads ());
|
||||
|
||||
proc.run (&op, polygons.layer (), other_layer, res->deep_layer ().layer ());
|
||||
|
||||
} else {
|
||||
|
||||
db::check_local_operation_with_properties<db::PolygonRef, db::PolygonRef> op (check, different_polygons, primary_is_merged, other_deep != 0, other_is_merged, options, res->properties_repository (), properties_repository (), other_deep ? other_deep->properties_repository () : &polygons.layout ().properties_repository ());
|
||||
|
||||
db::local_processor<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::EdgePairWithProperties> proc (subject_layout, subject_top,
|
||||
intruder_layout, intruder_top,
|
||||
subject_breakout_cells, intruder_breakout_cells);
|
||||
|
||||
configure_proc (proc);
|
||||
proc.set_threads (polygons.store ()->threads ());
|
||||
|
||||
proc.run (&op, polygons.layer (), other_layer, res->deep_layer ().layer ());
|
||||
|
||||
}
|
||||
|
||||
return res.release ();
|
||||
}
|
||||
|
|
@ -1849,7 +2004,7 @@ DeepRegion::run_single_polygon_check (db::edge_relation_type rel, db::Coord d, c
|
|||
|
||||
for (db::Shapes::shape_iterator s = shapes.begin (db::ShapeIterator::Polygons); ! s.at_end (); ++s) {
|
||||
|
||||
edge2edge_check_negative_or_positive<db::Shapes> edge_check (check, result, options.negative, false /*does not require different polygons*/, false /*does not require different layers*/, options.shielded, true /*symmetric edge pairs*/);
|
||||
edge2edge_check_negative_or_positive<db::Shapes> edge_check (check, result, options.negative, false /*does not require different polygons*/, false /*does not require different layers*/, options.shielded, true /*symmetric edge pairs*/, pc_remove (options.prop_constraint) ? 0 : s->prop_id ());
|
||||
poly2poly_check<db::Polygon> poly_check (edge_check);
|
||||
|
||||
db::Polygon poly;
|
||||
|
|
@ -1955,9 +2110,7 @@ DeepRegion::in_and_out_generic (const Region &other, InteractingOutputMode outpu
|
|||
db::ContainedLocalOperation op (output_mode);
|
||||
|
||||
db::local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_polygons.layout (), &other_polygons.initial_cell (), polygons.breakout_cells (), other_polygons.breakout_cells ());
|
||||
proc.set_description (progress_desc ());
|
||||
proc.set_report_progress (report_progress ());
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
configure_proc (proc);
|
||||
proc.set_threads (polygons.store ()->threads ());
|
||||
|
||||
InteractingResultHolder orh (output_mode, merged_semantics (), polygons);
|
||||
|
|
@ -2019,9 +2172,7 @@ DeepRegion::selected_interacting_generic (const Region &other, int mode, bool to
|
|||
db::InteractingLocalOperation op (mode, touching, output_mode, min_count, max_count, true);
|
||||
|
||||
db::local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_polygons.layout (), &other_polygons.initial_cell (), polygons.breakout_cells (), other_polygons.breakout_cells ());
|
||||
proc.set_description (progress_desc ());
|
||||
proc.set_report_progress (report_progress ());
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
configure_proc (proc);
|
||||
proc.set_threads (polygons.store ()->threads ());
|
||||
if (split_after) {
|
||||
proc.set_area_ratio (polygons.store ()->max_area_ratio ());
|
||||
|
|
@ -2076,9 +2227,7 @@ DeepRegion::selected_interacting_generic (const Edges &other, InteractingOutputM
|
|||
db::InteractingWithEdgeLocalOperation op (output_mode, min_count, max_count, true);
|
||||
|
||||
db::local_processor<db::PolygonRef, db::Edge, db::PolygonRef> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell (), polygons.breakout_cells (), other_deep->deep_layer ().breakout_cells ());
|
||||
proc.set_description (progress_desc ());
|
||||
proc.set_report_progress (report_progress ());
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
configure_proc (proc);
|
||||
proc.set_threads (polygons.store ()->threads ());
|
||||
if (split_after) {
|
||||
proc.set_area_ratio (polygons.store ()->max_area_ratio ());
|
||||
|
|
@ -2122,9 +2271,7 @@ DeepRegion::pull_generic (const Region &other, int mode, bool touching) const
|
|||
db::PullLocalOperation op (mode, touching);
|
||||
|
||||
db::local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_polygons.layout (), &other_polygons.initial_cell (), polygons.breakout_cells (), other_polygons.breakout_cells ());
|
||||
proc.set_description (progress_desc ());
|
||||
proc.set_report_progress (report_progress ());
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
configure_proc (proc);
|
||||
proc.set_threads (polygons.store ()->threads ());
|
||||
if (split_after) {
|
||||
proc.set_area_ratio (polygons.store ()->max_area_ratio ());
|
||||
|
|
@ -2162,9 +2309,7 @@ DeepRegion::pull_generic (const Edges &other) const
|
|||
db::PullWithEdgeLocalOperation op;
|
||||
|
||||
db::local_processor<db::PolygonRef, db::Edge, db::Edge> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_edges.layout (), &other_edges.initial_cell (), polygons.breakout_cells (), other_edges.breakout_cells ());
|
||||
proc.set_description (progress_desc ());
|
||||
proc.set_report_progress (report_progress ());
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
configure_proc (proc);
|
||||
proc.set_threads (polygons.store ()->threads ());
|
||||
proc.run (&op, polygons.layer (), other_edges.layer (), dl_out.layer ());
|
||||
|
||||
|
|
@ -2197,9 +2342,7 @@ DeepRegion::pull_generic (const Texts &other) const
|
|||
db::PullWithTextLocalOperation op;
|
||||
|
||||
db::local_processor<db::PolygonRef, db::TextRef, db::TextRef> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_texts.layout (), &other_texts.initial_cell (), polygons.breakout_cells (), other_texts.breakout_cells ());
|
||||
proc.set_description (progress_desc ());
|
||||
proc.set_report_progress (report_progress ());
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
configure_proc (proc);
|
||||
proc.set_threads (polygons.store ()->threads ());
|
||||
proc.run (&op, polygons.layer (), other_texts.layer (), dl_out.layer ());
|
||||
|
||||
|
|
@ -2246,9 +2389,7 @@ DeepRegion::selected_interacting_generic (const Texts &other, InteractingOutputM
|
|||
db::InteractingWithTextLocalOperation op (output_mode, min_count, max_count);
|
||||
|
||||
db::local_processor<db::PolygonRef, db::TextRef, db::PolygonRef> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell (), polygons.breakout_cells (), other_deep->deep_layer ().breakout_cells ());
|
||||
proc.set_description (progress_desc ());
|
||||
proc.set_report_progress (report_progress ());
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
configure_proc (proc);
|
||||
proc.set_threads (polygons.store ()->threads ());
|
||||
if (split_after) {
|
||||
proc.set_area_ratio (polygons.store ()->max_area_ratio ());
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ public:
|
|||
|
||||
RegionDelegate *clone () const;
|
||||
|
||||
virtual void do_insert (const db::Polygon &polygon);
|
||||
virtual void do_insert (const db::Polygon &polygon, db::properties_id_type prop_id);
|
||||
|
||||
virtual void do_transform (const db::Trans &t);
|
||||
virtual void do_transform (const db::ICplxTrans &t);
|
||||
|
|
@ -74,10 +74,14 @@ public:
|
|||
virtual bool is_merged () const;
|
||||
|
||||
virtual const db::Polygon *nth (size_t n) const;
|
||||
virtual db::properties_id_type nth_prop_id (size_t n) const;
|
||||
virtual bool has_valid_polygons () const;
|
||||
virtual bool has_valid_merged_polygons () const;
|
||||
|
||||
virtual const db::RecursiveShapeIterator *iter () const;
|
||||
virtual void apply_property_translator (const db::PropertiesTranslator &pt);
|
||||
virtual db::PropertiesRepository *properties_repository ();
|
||||
virtual const db::PropertiesRepository *properties_repository () const;
|
||||
|
||||
virtual bool equals (const Region &other) const;
|
||||
virtual bool less (const Region &other) const;
|
||||
|
|
@ -92,15 +96,15 @@ public:
|
|||
|
||||
virtual std::string to_string (size_t nmax) const;
|
||||
|
||||
virtual EdgePairsDelegate *cop_to_edge_pairs (db::CompoundRegionOperationNode &node);
|
||||
virtual RegionDelegate *cop_to_region (db::CompoundRegionOperationNode &node);
|
||||
virtual EdgesDelegate *cop_to_edges (db::CompoundRegionOperationNode &node);
|
||||
virtual EdgePairsDelegate *cop_to_edge_pairs (db::CompoundRegionOperationNode &node, db::PropertyConstraint prop_constraint);
|
||||
virtual RegionDelegate *cop_to_region (db::CompoundRegionOperationNode &node, db::PropertyConstraint prop_constraint);
|
||||
virtual EdgesDelegate *cop_to_edges (db::CompoundRegionOperationNode &node, db::PropertyConstraint prop_constraint);
|
||||
|
||||
virtual RegionDelegate *and_with (const Region &other) const;
|
||||
virtual RegionDelegate *not_with (const Region &other) 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 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, db::PropertyConstraint property_constraint) const;
|
||||
virtual RegionDelegate *or_with (const Region &other, db::PropertyConstraint property_constraint) 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;
|
||||
|
|
@ -135,6 +139,8 @@ public:
|
|||
|
||||
virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const;
|
||||
|
||||
virtual RegionDelegate *nets (LayoutToNetlist *l2n, NetPropertyMode prop_mode, const tl::Variant &net_prop_name, const std::vector<const Net *> *nets) const;
|
||||
|
||||
virtual DeepShapeCollectionDelegateBase *deep ()
|
||||
{
|
||||
return this;
|
||||
|
|
@ -171,11 +177,19 @@ 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;
|
||||
|
||||
template <class Proc>
|
||||
void configure_proc (Proc &proc) const
|
||||
{
|
||||
proc.set_description (progress_desc ());
|
||||
proc.set_report_progress (report_progress ());
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
#include "dbDeepEdgePairs.h"
|
||||
#include "dbDeepTexts.h"
|
||||
#include "dbShapeCollection.h"
|
||||
#include "dbLayoutToNetlist.h"
|
||||
|
||||
#include "tlTimer.h"
|
||||
|
||||
|
|
@ -50,7 +51,7 @@ DeepLayer::DeepLayer ()
|
|||
DeepLayer::DeepLayer (const Region ®ion)
|
||||
: mp_store (), m_layout (0), m_layer (0)
|
||||
{
|
||||
const db::DeepRegion *dr = dynamic_cast<db::DeepRegion *> (region.delegate ());
|
||||
const db::DeepRegion *dr = dynamic_cast<const db::DeepRegion *> (region.delegate ());
|
||||
tl_assert (dr != 0);
|
||||
*this = dr->deep_layer ();
|
||||
}
|
||||
|
|
@ -58,7 +59,7 @@ DeepLayer::DeepLayer (const Region ®ion)
|
|||
DeepLayer::DeepLayer (const Texts &texts)
|
||||
: mp_store (), m_layout (0), m_layer (0)
|
||||
{
|
||||
const db::DeepTexts *dr = dynamic_cast<db::DeepTexts *> (texts.delegate ());
|
||||
const db::DeepTexts *dr = dynamic_cast<const db::DeepTexts *> (texts.delegate ());
|
||||
tl_assert (dr != 0);
|
||||
*this = dr->deep_layer ();
|
||||
}
|
||||
|
|
@ -66,7 +67,7 @@ DeepLayer::DeepLayer (const Texts &texts)
|
|||
DeepLayer::DeepLayer (const Edges &edges)
|
||||
: mp_store (), m_layout (0), m_layer (0)
|
||||
{
|
||||
const db::DeepEdges *dr = dynamic_cast<db::DeepEdges *> (edges.delegate ());
|
||||
const db::DeepEdges *dr = dynamic_cast<const db::DeepEdges *> (edges.delegate ());
|
||||
tl_assert (dr != 0);
|
||||
*this = dr->deep_layer ();
|
||||
}
|
||||
|
|
@ -74,7 +75,7 @@ DeepLayer::DeepLayer (const Edges &edges)
|
|||
DeepLayer::DeepLayer (const EdgePairs &edge_pairs)
|
||||
: mp_store (), m_layout (0), m_layer (0)
|
||||
{
|
||||
const db::DeepEdgePairs *dr = dynamic_cast<db::DeepEdgePairs *> (edge_pairs.delegate ());
|
||||
const db::DeepEdgePairs *dr = dynamic_cast<const db::DeepEdgePairs *> (edge_pairs.delegate ());
|
||||
tl_assert (dr != 0);
|
||||
*this = dr->deep_layer ();
|
||||
}
|
||||
|
|
@ -261,10 +262,31 @@ DeepLayer::check_dss () const
|
|||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
struct DeepShapeStore::LayoutHolder
|
||||
{
|
||||
class L2NStatusChangedListener
|
||||
: public tl::Object
|
||||
{
|
||||
public:
|
||||
L2NStatusChangedListener (DeepShapeStore::LayoutHolder *lh, db::LayoutToNetlist *l2n)
|
||||
: mp_lh (lh), mp_l2n (l2n)
|
||||
{
|
||||
mp_l2n->status_changed_event ().add (this, &L2NStatusChangedListener::l2n_destroyed);
|
||||
}
|
||||
|
||||
private:
|
||||
void l2n_destroyed (gsi::ObjectBase::StatusEventType ev)
|
||||
{
|
||||
if (ev == gsi::ObjectBase::ObjectDestroyed) {
|
||||
// CAUTION: this will eventually delete *this!
|
||||
mp_lh->remove_l2n (mp_l2n);
|
||||
}
|
||||
}
|
||||
|
||||
DeepShapeStore::LayoutHolder *mp_lh;
|
||||
db::LayoutToNetlist *mp_l2n;
|
||||
};
|
||||
|
||||
LayoutHolder (const db::ICplxTrans &trans)
|
||||
: refs (0), layout (false), builder (&layout, trans)
|
||||
{
|
||||
|
|
@ -287,16 +309,42 @@ struct DeepShapeStore::LayoutHolder
|
|||
}
|
||||
}
|
||||
|
||||
bool has_net_builder_for (db::LayoutToNetlist *l2n) const
|
||||
{
|
||||
auto l = net_builders.find (l2n);
|
||||
return (l != net_builders.end ());
|
||||
}
|
||||
|
||||
db::NetBuilder &net_builder_for (db::Cell &top, db::LayoutToNetlist *l2n)
|
||||
{
|
||||
auto l = net_builders.find (l2n);
|
||||
if (l == net_builders.end ()) {
|
||||
l = net_builders.insert (std::make_pair (l2n, std::make_pair (L2NStatusChangedListener (this, l2n), db::NetBuilder (&layout, l2n->cell_mapping_into (layout, top, false), l2n)))).first;
|
||||
return l->second.second;
|
||||
} else {
|
||||
return l->second.second;
|
||||
}
|
||||
}
|
||||
|
||||
void remove_l2n (db::LayoutToNetlist *l2n)
|
||||
{
|
||||
auto l = net_builders.find (l2n);
|
||||
if (l != net_builders.end ()) {
|
||||
net_builders.erase (l);
|
||||
}
|
||||
}
|
||||
|
||||
int refs;
|
||||
db::Layout layout;
|
||||
db::HierarchyBuilder builder;
|
||||
std::map<db::LayoutToNetlist *, std::pair<L2NStatusChangedListener, db::NetBuilder> > net_builders;
|
||||
std::map<unsigned int, int> layer_refs;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
DeepShapeStoreState::DeepShapeStoreState ()
|
||||
: m_threads (1), m_max_area_ratio (3.0), m_max_vertex_count (16), m_reject_odd_polygons (false), m_text_property_name (), m_text_enlargement (-1)
|
||||
: m_threads (1), m_max_area_ratio (3.0), m_max_vertex_count (16), m_reject_odd_polygons (false), m_text_property_name (), m_text_enlargement (-1), m_subcircuit_hierarchy_for_nets (false)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
|
@ -403,6 +451,19 @@ DeepShapeStoreState::max_vertex_count () const
|
|||
return m_max_vertex_count;
|
||||
}
|
||||
|
||||
void
|
||||
DeepShapeStoreState::set_subcircuit_hierarchy_for_nets (bool f)
|
||||
{
|
||||
m_subcircuit_hierarchy_for_nets = f;
|
||||
}
|
||||
|
||||
bool
|
||||
DeepShapeStoreState::subcircuit_hierarchy_for_nets () const
|
||||
{
|
||||
return m_subcircuit_hierarchy_for_nets;
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
static size_t s_instance_count = 0;
|
||||
|
|
@ -475,19 +536,20 @@ DeepLayer DeepShapeStore::create_from_flat (const db::Region ®ion, bool for_n
|
|||
db::Shapes *shapes = &initial_cell ().shapes (layer);
|
||||
db::Box world = db::Box::world ();
|
||||
|
||||
// The chain of operators for producing clipped and reduced polygon references
|
||||
db::PolygonReferenceHierarchyBuilderShapeReceiver refs (&layout (), text_enlargement (), text_property_name ());
|
||||
db::ReducingHierarchyBuilderShapeReceiver red (&refs, max_area_ratio, max_vertex_count, m_state.reject_odd_polygons ());
|
||||
|
||||
// try to maintain the texts on top level - go through shape iterator
|
||||
std::pair<db::RecursiveShapeIterator, db::ICplxTrans> ii = region.begin_iter ();
|
||||
db::ICplxTrans ttop = trans * ii.second;
|
||||
|
||||
// The chain of operators for producing clipped and reduced polygon references
|
||||
db::PolygonReferenceHierarchyBuilderShapeReceiver refs (&layout (), ii.first.layout (), text_enlargement (), text_property_name ());
|
||||
db::ReducingHierarchyBuilderShapeReceiver red (&refs, max_area_ratio, max_vertex_count, m_state.reject_odd_polygons ());
|
||||
|
||||
while (! ii.first.at_end ()) {
|
||||
|
||||
if (for_netlist && ii.first->is_text () && ii.first.layout () && ii.first.cell () != ii.first.top_cell ()) {
|
||||
// Skip texts on levels below top cell. For the reasoning see the description of this method.
|
||||
} else {
|
||||
red.push (*ii.first, ttop * ii.first.trans (), world, 0, shapes);
|
||||
red.push (*ii.first, ii.first.prop_id (), ttop * ii.first.trans (), world, 0, shapes);
|
||||
}
|
||||
|
||||
++ii.first;
|
||||
|
|
@ -515,12 +577,12 @@ DeepLayer DeepShapeStore::create_from_flat (const db::Edges &edges, const db::IC
|
|||
db::Shapes *shapes = &initial_cell ().shapes (layer);
|
||||
db::Box world = db::Box::world ();
|
||||
|
||||
db::EdgeBuildingHierarchyBuilderShapeReceiver eb (false);
|
||||
|
||||
std::pair<db::RecursiveShapeIterator, db::ICplxTrans> ii = edges.begin_iter ();
|
||||
db::ICplxTrans ttop = trans * ii.second;
|
||||
|
||||
db::EdgeBuildingHierarchyBuilderShapeReceiver eb (&layout (), ii.first.layout (), false);
|
||||
while (! ii.first.at_end ()) {
|
||||
eb.push (*ii.first, ttop * ii.first.trans (), world, 0, shapes);
|
||||
eb.push (*ii.first, ii.first.prop_id (), ttop * ii.first.trans (), world, 0, shapes);
|
||||
++ii.first;
|
||||
}
|
||||
|
||||
|
|
@ -545,12 +607,13 @@ DeepLayer DeepShapeStore::create_from_flat (const db::Texts &texts, const db::IC
|
|||
db::Shapes *shapes = &initial_cell ().shapes (layer);
|
||||
db::Box world = db::Box::world ();
|
||||
|
||||
db::TextBuildingHierarchyBuilderShapeReceiver tb (&layout ());
|
||||
|
||||
std::pair<db::RecursiveShapeIterator, db::ICplxTrans> ii = texts.begin_iter ();
|
||||
db::ICplxTrans ttop = trans * ii.second;
|
||||
|
||||
db::TextBuildingHierarchyBuilderShapeReceiver tb (&layout (), ii.first.layout ());
|
||||
|
||||
while (! ii.first.at_end ()) {
|
||||
tb.push (*ii.first, ttop * ii.first.trans (), world, 0, shapes);
|
||||
tb.push (*ii.first, ii.first.prop_id (), ttop * ii.first.trans (), world, 0, shapes);
|
||||
++ii.first;
|
||||
}
|
||||
|
||||
|
|
@ -621,6 +684,16 @@ const tl::Variant &DeepShapeStore::text_property_name () const
|
|||
return m_state.text_property_name ();
|
||||
}
|
||||
|
||||
void DeepShapeStore::set_subcircuit_hierarchy_for_nets (bool f)
|
||||
{
|
||||
m_state.set_subcircuit_hierarchy_for_nets (f);
|
||||
}
|
||||
|
||||
bool DeepShapeStore::subcircuit_hierarchy_for_nets () const
|
||||
{
|
||||
return m_state.subcircuit_hierarchy_for_nets ();
|
||||
}
|
||||
|
||||
const std::set<db::cell_index_type> *
|
||||
DeepShapeStore::breakout_cells (unsigned int layout_index) const
|
||||
{
|
||||
|
|
@ -651,6 +724,27 @@ DeepShapeStore::add_breakout_cells (unsigned int layout_index, const std::set<db
|
|||
m_state.add_breakout_cells (layout_index, cc);
|
||||
}
|
||||
|
||||
bool
|
||||
DeepShapeStore::has_net_builder_for (unsigned int layout_index, db::LayoutToNetlist *l2n)
|
||||
{
|
||||
return m_layouts [layout_index]->has_net_builder_for (l2n);
|
||||
}
|
||||
|
||||
db::NetBuilder &
|
||||
DeepShapeStore::net_builder_for (unsigned int layout_index, db::LayoutToNetlist *l2n)
|
||||
{
|
||||
db::NetBuilder &nb = m_layouts [layout_index]->net_builder_for (initial_cell (layout_index), l2n);
|
||||
|
||||
if (subcircuit_hierarchy_for_nets ()) {
|
||||
nb.set_hier_mode (db::BNH_SubcircuitCells);
|
||||
nb.set_cell_name_prefix ("X$$"); // TODO: needs to be a configuration option?
|
||||
} else {
|
||||
nb.set_hier_mode (db::BNH_Flatten);
|
||||
}
|
||||
|
||||
return nb;
|
||||
}
|
||||
|
||||
void DeepShapeStore::set_threads (int n)
|
||||
{
|
||||
m_state.set_threads (n);
|
||||
|
|
@ -836,7 +930,7 @@ DeepLayer DeepShapeStore::create_polygon_layer (const db::RecursiveShapeIterator
|
|||
builder.set_target_layer (layer_index);
|
||||
|
||||
// The chain of operators for producing clipped and reduced polygon references
|
||||
db::PolygonReferenceHierarchyBuilderShapeReceiver refs (& layout, text_enlargement (), text_property_name ());
|
||||
db::PolygonReferenceHierarchyBuilderShapeReceiver refs (&layout, si.layout (), text_enlargement (), text_property_name ());
|
||||
db::ReducingHierarchyBuilderShapeReceiver red (&refs, max_area_ratio, max_vertex_count, m_state.reject_odd_polygons ());
|
||||
db::ClippingHierarchyBuilderShapeReceiver clip (&red);
|
||||
|
||||
|
|
@ -905,7 +999,7 @@ DeepLayer DeepShapeStore::create_copy (const DeepLayer &source, HierarchyBuilder
|
|||
db::Shapes &into = c->shapes (layer_index);
|
||||
const db::Shapes &from = c->shapes (from_layer_index);
|
||||
for (db::Shapes::shape_iterator s = from.begin (db::ShapeIterator::All); ! s.at_end (); ++s) {
|
||||
pipe->push (*s, trans, region, 0, &into);
|
||||
pipe->push (*s, s->prop_id (), trans, region, 0, &into);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -914,13 +1008,19 @@ DeepLayer DeepShapeStore::create_copy (const DeepLayer &source, HierarchyBuilder
|
|||
|
||||
DeepLayer DeepShapeStore::create_edge_layer (const db::RecursiveShapeIterator &si, bool as_edges, const db::ICplxTrans &trans)
|
||||
{
|
||||
db::EdgeBuildingHierarchyBuilderShapeReceiver refs (as_edges);
|
||||
unsigned int layout_index = layout_for_iter (si, trans);
|
||||
db::Layout &layout = m_layouts[layout_index]->layout;
|
||||
|
||||
db::EdgeBuildingHierarchyBuilderShapeReceiver refs (&layout, si.layout (), as_edges);
|
||||
return create_custom_layer (si, &refs, trans);
|
||||
}
|
||||
|
||||
DeepLayer DeepShapeStore::create_edge_pair_layer (const db::RecursiveShapeIterator &si, const db::ICplxTrans &trans)
|
||||
{
|
||||
db::EdgePairBuildingHierarchyBuilderShapeReceiver refs;
|
||||
unsigned int layout_index = layout_for_iter (si, trans);
|
||||
db::Layout &layout = m_layouts[layout_index]->layout;
|
||||
|
||||
db::EdgePairBuildingHierarchyBuilderShapeReceiver refs (&layout, si.layout ());
|
||||
return create_custom_layer (si, &refs, trans);
|
||||
}
|
||||
|
||||
|
|
@ -929,7 +1029,7 @@ DeepLayer DeepShapeStore::create_text_layer (const db::RecursiveShapeIterator &s
|
|||
unsigned int layout_index = layout_for_iter (si, trans);
|
||||
db::Layout &layout = m_layouts[layout_index]->layout;
|
||||
|
||||
db::TextBuildingHierarchyBuilderShapeReceiver refs (&layout);
|
||||
db::TextBuildingHierarchyBuilderShapeReceiver refs (&layout, si.layout ());
|
||||
return create_custom_layer (si, &refs, trans);
|
||||
}
|
||||
|
||||
|
|
@ -1200,19 +1300,32 @@ DeepShapeStore::insert_as_polygons (const DeepLayer &deep_layer, db::Layout *int
|
|||
|
||||
if (s->is_edge_pair ()) {
|
||||
|
||||
out.insert (s->edge_pair ().normalized ().to_simple_polygon (enl));
|
||||
if (s->prop_id () != 0) {
|
||||
out.insert (db::SimplePolygonWithProperties (s->edge_pair ().normalized ().to_simple_polygon (enl), s->prop_id ()));
|
||||
} else {
|
||||
out.insert (s->edge_pair ().normalized ().to_simple_polygon (enl));
|
||||
}
|
||||
|
||||
} else if (s->is_path () || s->is_polygon () || s->is_box ()) {
|
||||
|
||||
db::Polygon poly;
|
||||
s->polygon (poly);
|
||||
out.insert (poly);
|
||||
if (s->prop_id () != 0) {
|
||||
out.insert (db::PolygonWithProperties (poly, s->prop_id ()));
|
||||
} else {
|
||||
out.insert (poly);
|
||||
}
|
||||
|
||||
} else if (s->is_text ()) {
|
||||
|
||||
db::Text t;
|
||||
s->text (t);
|
||||
out.insert (db::SimplePolygon (t.box ().enlarged (db::Vector (enl, enl))));
|
||||
db::SimplePolygon sp (t.box ().enlarged (db::Vector (enl, enl)));
|
||||
if (s->prop_id () != 0) {
|
||||
out.insert (db::SimplePolygonWithProperties (sp, s->prop_id ()));
|
||||
} else {
|
||||
out.insert (sp);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -47,6 +47,8 @@ class Edges;
|
|||
class EdgePairs;
|
||||
class Texts;
|
||||
class ShapeCollection;
|
||||
class NetBuilder;
|
||||
class LayoutToNetlist;
|
||||
|
||||
/**
|
||||
* @brief Represents a shape collection from the deep shape store
|
||||
|
|
@ -220,6 +222,16 @@ public:
|
|||
return mp_store.get ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the non-const shape store object
|
||||
* This feature is intended for internal purposes.
|
||||
*/
|
||||
DeepShapeStore *store_non_const () const
|
||||
{
|
||||
check_dss ();
|
||||
return const_cast<DeepShapeStore *> (mp_store.get ());
|
||||
}
|
||||
|
||||
private:
|
||||
friend class DeepShapeStore;
|
||||
|
||||
|
|
@ -262,6 +274,9 @@ public:
|
|||
void add_breakout_cell (unsigned int layout_index, db::cell_index_type ci);
|
||||
void add_breakout_cells (unsigned int layout_index, const std::set<db::cell_index_type> &cc);
|
||||
|
||||
void set_subcircuit_hierarchy_for_nets (bool f);
|
||||
bool subcircuit_hierarchy_for_nets () const;
|
||||
|
||||
private:
|
||||
int m_threads;
|
||||
double m_max_area_ratio;
|
||||
|
|
@ -270,6 +285,7 @@ private:
|
|||
tl::Variant m_text_property_name;
|
||||
std::vector<std::set<db::cell_index_type> > m_breakout_cells;
|
||||
int m_text_enlargement;
|
||||
bool m_subcircuit_hierarchy_for_nets;
|
||||
|
||||
std::set<db::cell_index_type> &ensure_breakout_cells (unsigned int layout_index)
|
||||
{
|
||||
|
|
@ -668,6 +684,37 @@ public:
|
|||
*/
|
||||
bool is_valid_layout_index (unsigned int n) const;
|
||||
|
||||
/**
|
||||
* @brief Gets the net builder object for a given layout index and LayoutToNetlist database
|
||||
*
|
||||
* If no net builder is available, one will be created. Use \\has_net_builder to check whether one is
|
||||
* already created.
|
||||
*/
|
||||
db::NetBuilder &net_builder_for (unsigned int layout_index, db::LayoutToNetlist *l2n);
|
||||
|
||||
/**
|
||||
* @brief Gets the net builder object for a given LayoutToNetlist database (requires the DSS to be singular)
|
||||
*/
|
||||
db::NetBuilder &net_builder_for (db::LayoutToNetlist *l2n)
|
||||
{
|
||||
require_singular ();
|
||||
return net_builder_for (0, l2n);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets a value indicating whether a net building is available
|
||||
*/
|
||||
bool has_net_builder_for(unsigned int layout_index, db::LayoutToNetlist *l2n);
|
||||
|
||||
/**
|
||||
* @brief Gets the net builder object for a given LayoutToNetlist database (requires the DSS to be singular)
|
||||
*/
|
||||
bool has_net_builder_for (db::LayoutToNetlist *l2n)
|
||||
{
|
||||
require_singular ();
|
||||
return has_net_builder_for (0, l2n);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The deep shape store also keeps the number of threads to allocate for the hierarchical processor
|
||||
*
|
||||
|
|
@ -752,6 +799,20 @@ public:
|
|||
*/
|
||||
int text_enlargement () const;
|
||||
|
||||
/**
|
||||
* @brief Sets a value indicating whether to build a subcircuit hierarchy per net
|
||||
*
|
||||
* This flag is used to determine the way, net subcircuit hierarchies are built:
|
||||
* when true, subcells are created for subcircuits on a net. Otherwise the net
|
||||
* shapes are produced flat inside the cell they appear on.
|
||||
*/
|
||||
void set_subcircuit_hierarchy_for_nets (bool f);
|
||||
|
||||
/**
|
||||
* @brief Gets a value indicating whether to build a subcircuit hierarchy per net
|
||||
*/
|
||||
bool subcircuit_hierarchy_for_nets () const;
|
||||
|
||||
/**
|
||||
* @brief Gets the breakout cells for a given layout
|
||||
* Returns 0 if there are no breakout cells for this layout.
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ public:
|
|||
typedef db::Text value_type;
|
||||
|
||||
DeepTextsIterator (const db::RecursiveShapeIterator &iter)
|
||||
: m_iter (iter)
|
||||
: m_iter (iter), m_prop_id (0)
|
||||
{
|
||||
set ();
|
||||
}
|
||||
|
|
@ -77,6 +77,11 @@ public:
|
|||
return &m_text;
|
||||
}
|
||||
|
||||
virtual db::properties_id_type prop_id () const
|
||||
{
|
||||
return m_prop_id;
|
||||
}
|
||||
|
||||
virtual bool equals (const generic_shape_iterator_delegate_base<value_type> *other) const
|
||||
{
|
||||
const DeepTextsIterator *o = dynamic_cast<const DeepTextsIterator *> (other);
|
||||
|
|
@ -105,12 +110,14 @@ private:
|
|||
|
||||
db::RecursiveShapeIterator m_iter;
|
||||
mutable value_type m_text;
|
||||
mutable db::properties_id_type m_prop_id;
|
||||
|
||||
void set () const
|
||||
{
|
||||
if (! m_iter.at_end ()) {
|
||||
m_iter.shape ().text (m_text);
|
||||
m_iter->text (m_text);
|
||||
m_text.transform (m_iter.trans ());
|
||||
m_prop_id = m_iter->prop_id ();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -331,6 +338,21 @@ const db::RecursiveShapeIterator *DeepTexts::iter () const
|
|||
return 0;
|
||||
}
|
||||
|
||||
void DeepTexts::apply_property_translator (const db::PropertiesTranslator &pt)
|
||||
{
|
||||
DeepShapeCollectionDelegateBase::apply_property_translator (pt);
|
||||
}
|
||||
|
||||
db::PropertiesRepository *DeepTexts::properties_repository ()
|
||||
{
|
||||
return &deep_layer ().layout ().properties_repository ();
|
||||
}
|
||||
|
||||
const db::PropertiesRepository *DeepTexts::properties_repository () const
|
||||
{
|
||||
return &deep_layer ().layout ().properties_repository ();
|
||||
}
|
||||
|
||||
TextsDelegate *
|
||||
DeepTexts::add_in_place (const Texts &other)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -73,6 +73,9 @@ public:
|
|||
virtual const db::Text *nth (size_t n) const;
|
||||
virtual bool has_valid_texts () const;
|
||||
virtual const db::RecursiveShapeIterator *iter () const;
|
||||
virtual void apply_property_translator (const db::PropertiesTranslator &pt);
|
||||
virtual db::PropertiesRepository *properties_repository ();
|
||||
virtual const db::PropertiesRepository *properties_repository () const;
|
||||
|
||||
virtual TextsDelegate *filter_in_place (const TextFilterBase &filter);
|
||||
virtual TextsDelegate *filtered (const TextFilterBase &) const;
|
||||
|
|
|
|||
|
|
@ -409,13 +409,13 @@ public:
|
|||
typedef Iterator const_iterator;
|
||||
|
||||
ShapesToOutputContainerAdaptor ()
|
||||
: mp_shapes (0)
|
||||
: mp_shapes (0), m_prop_id (0)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
ShapesToOutputContainerAdaptor (db::Shapes &shapes)
|
||||
: mp_shapes (&shapes)
|
||||
ShapesToOutputContainerAdaptor (db::Shapes &shapes, db::properties_id_type prop_id = 0)
|
||||
: mp_shapes (&shapes), m_prop_id (prop_id)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
|
@ -432,11 +432,16 @@ public:
|
|||
|
||||
void insert (const db::Edge &edge)
|
||||
{
|
||||
mp_shapes->insert (edge);
|
||||
if (m_prop_id != 0) {
|
||||
mp_shapes->insert (db::EdgeWithProperties (edge, m_prop_id));
|
||||
} else {
|
||||
mp_shapes->insert (edge);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
db::Shapes *mp_shapes;
|
||||
db::properties_id_type m_prop_id;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -445,13 +450,13 @@ private:
|
|||
struct DB_PUBLIC EdgeBooleanClusterCollectorToShapes
|
||||
: EdgeBooleanClusterCollector<ShapesToOutputContainerAdaptor>
|
||||
{
|
||||
EdgeBooleanClusterCollectorToShapes (db::Shapes *output, EdgeBoolOp op)
|
||||
: EdgeBooleanClusterCollector<ShapesToOutputContainerAdaptor> (&m_adaptor, op), m_adaptor (*output)
|
||||
EdgeBooleanClusterCollectorToShapes (db::Shapes *output, EdgeBoolOp op, db::properties_id_type prop_id = 0)
|
||||
: EdgeBooleanClusterCollector<ShapesToOutputContainerAdaptor> (&m_adaptor, op), m_adaptor (*output, prop_id)
|
||||
{
|
||||
}
|
||||
|
||||
EdgeBooleanClusterCollectorToShapes (db::Shapes *output, EdgeBoolOp op, db::Shapes *output2)
|
||||
: EdgeBooleanClusterCollector<ShapesToOutputContainerAdaptor> (&m_adaptor, op, &m_adaptor2), m_adaptor (*output), m_adaptor2 (*output2)
|
||||
EdgeBooleanClusterCollectorToShapes (db::Shapes *output, EdgeBoolOp op, db::Shapes *output2, db::properties_id_type prop_id = 0)
|
||||
: EdgeBooleanClusterCollector<ShapesToOutputContainerAdaptor> (&m_adaptor, op, &m_adaptor2), m_adaptor (*output, prop_id), m_adaptor2 (*output2, prop_id)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -149,10 +149,26 @@ const db::RecursiveShapeIterator &
|
|||
EdgePairs::iter () const
|
||||
{
|
||||
static db::RecursiveShapeIterator def_iter;
|
||||
const db::RecursiveShapeIterator *i = mp_delegate->iter ();
|
||||
const db::RecursiveShapeIterator *i = mp_delegate ? mp_delegate->iter () : 0;
|
||||
return *(i ? i : &def_iter);
|
||||
}
|
||||
|
||||
const db::PropertiesRepository &
|
||||
EdgePairs::properties_repository () const
|
||||
{
|
||||
static db::PropertiesRepository empty_prop_repo;
|
||||
const db::PropertiesRepository *r = delegate () ? delegate ()->properties_repository () : 0;
|
||||
return *(r ? r : &empty_prop_repo);
|
||||
}
|
||||
|
||||
db::PropertiesRepository &
|
||||
EdgePairs::properties_repository ()
|
||||
{
|
||||
db::PropertiesRepository *r = delegate () ? delegate ()->properties_repository () : 0;
|
||||
tl_assert (r != 0);
|
||||
return *r;
|
||||
}
|
||||
|
||||
void EdgePairs::processed (Region &output, const EdgePairToPolygonProcessorBase &filter) const
|
||||
{
|
||||
output = Region (mp_delegate->processed_to_polygons (filter));
|
||||
|
|
|
|||
|
|
@ -44,63 +44,8 @@ class DeepShapeStore;
|
|||
class TransformationReducer;
|
||||
class EdgeFilterBase;
|
||||
|
||||
/**
|
||||
* @brief An edge pair set iterator
|
||||
*
|
||||
* The iterator delivers the edge pairs of the edge pair set
|
||||
*/
|
||||
class DB_PUBLIC EdgePairsIterator
|
||||
: public generic_shape_iterator<db::EdgePair>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor
|
||||
*/
|
||||
EdgePairsIterator ()
|
||||
: generic_shape_iterator<db::EdgePair> ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Constructor from a delegate
|
||||
* The iterator will take ownership over the delegate
|
||||
*/
|
||||
EdgePairsIterator (EdgePairsIteratorDelegate *delegate)
|
||||
: generic_shape_iterator<db::EdgePair> (delegate)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Copy constructor and assignment
|
||||
*/
|
||||
EdgePairsIterator (const EdgePairsIterator &other)
|
||||
: generic_shape_iterator<db::EdgePair> (static_cast<const generic_shape_iterator<db::EdgePair> &> (other))
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assignment
|
||||
*/
|
||||
EdgePairsIterator &operator= (const EdgePairsIterator &other)
|
||||
{
|
||||
generic_shape_iterator<db::EdgePair>::operator= (other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Increment
|
||||
*/
|
||||
EdgePairsIterator &operator++ ()
|
||||
{
|
||||
generic_shape_iterator<db::EdgePair>::operator++ ();
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
typedef addressable_shape_delivery_gen<EdgePairsIterator> AddressableEdgePairDelivery;
|
||||
typedef generic_shape_iterator<EdgePair> EdgePairsIterator;
|
||||
typedef addressable_shape_delivery<EdgePair> AddressableEdgePairDelivery;
|
||||
|
||||
class EdgePairs;
|
||||
|
||||
|
|
@ -251,7 +196,15 @@ public:
|
|||
/**
|
||||
* @brief Gets the underlying delegate object
|
||||
*/
|
||||
EdgePairsDelegate *delegate () const
|
||||
const EdgePairsDelegate *delegate () const
|
||||
{
|
||||
return mp_delegate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the underlying delegate object
|
||||
*/
|
||||
EdgePairsDelegate *delegate ()
|
||||
{
|
||||
return mp_delegate;
|
||||
}
|
||||
|
|
@ -488,7 +441,7 @@ public:
|
|||
*/
|
||||
AddressableEdgePairDelivery addressable_edge_pairs () const
|
||||
{
|
||||
return AddressableEdgePairDelivery (begin (), has_valid_edge_pairs ());
|
||||
return AddressableEdgePairDelivery (begin ());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -498,6 +451,20 @@ public:
|
|||
*/
|
||||
const db::RecursiveShapeIterator &iter () const;
|
||||
|
||||
/**
|
||||
* @brief Gets the property repository
|
||||
*
|
||||
* Use this object to decode property IDs.
|
||||
*/
|
||||
const db::PropertiesRepository &properties_repository () const;
|
||||
|
||||
/**
|
||||
* @brief Gets the property repository
|
||||
*
|
||||
* Use this object to decode and encode property IDs.
|
||||
*/
|
||||
db::PropertiesRepository &properties_repository ();
|
||||
|
||||
/**
|
||||
* @brief Equality
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -166,6 +166,12 @@ public:
|
|||
|
||||
virtual EdgePairsDelegate *clone () const = 0;
|
||||
|
||||
EdgePairsDelegate *remove_properties (bool remove = true)
|
||||
{
|
||||
ShapeCollectionDelegateBase::remove_properties (remove);
|
||||
return this;
|
||||
}
|
||||
|
||||
void enable_progress (const std::string &progress_desc);
|
||||
void disable_progress ();
|
||||
|
||||
|
|
@ -205,6 +211,9 @@ public:
|
|||
virtual bool has_valid_edge_pairs () const = 0;
|
||||
|
||||
virtual const db::RecursiveShapeIterator *iter () const = 0;
|
||||
virtual void apply_property_translator (const db::PropertiesTranslator &pt) = 0;
|
||||
virtual db::PropertiesRepository *properties_repository () = 0;
|
||||
virtual const db::PropertiesRepository *properties_repository () const = 0;
|
||||
|
||||
virtual bool equals (const EdgePairs &other) const = 0;
|
||||
virtual bool less (const EdgePairs &other) const = 0;
|
||||
|
|
|
|||
|
|
@ -108,10 +108,26 @@ const db::RecursiveShapeIterator &
|
|||
Edges::iter () const
|
||||
{
|
||||
static db::RecursiveShapeIterator def_iter;
|
||||
const db::RecursiveShapeIterator *i = mp_delegate->iter ();
|
||||
const db::RecursiveShapeIterator *i = mp_delegate ? mp_delegate->iter () : 0;
|
||||
return *(i ? i : &def_iter);
|
||||
}
|
||||
|
||||
const db::PropertiesRepository &
|
||||
Edges::properties_repository () const
|
||||
{
|
||||
static db::PropertiesRepository empty_prop_repo;
|
||||
const db::PropertiesRepository *r = delegate () ? delegate ()->properties_repository () : 0;
|
||||
return *(r ? r : &empty_prop_repo);
|
||||
}
|
||||
|
||||
db::PropertiesRepository &
|
||||
Edges::properties_repository ()
|
||||
{
|
||||
db::PropertiesRepository *r = delegate () ? delegate ()->properties_repository () : 0;
|
||||
tl_assert (r != 0);
|
||||
return *r;
|
||||
}
|
||||
|
||||
void
|
||||
Edges::set_delegate (EdgesDelegate *delegate, bool keep_attributes)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -39,63 +39,8 @@ class MutableEdges;
|
|||
class EmptyEdges;
|
||||
class DeepShapeStore;
|
||||
|
||||
/**
|
||||
* @brief An edge set iterator
|
||||
*
|
||||
* The iterator delivers the edges of the edge set
|
||||
*/
|
||||
class DB_PUBLIC EdgesIterator
|
||||
: public generic_shape_iterator<db::Edge>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor
|
||||
*/
|
||||
EdgesIterator ()
|
||||
: generic_shape_iterator<db::Edge> ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Constructor from a delegate
|
||||
* The iterator will take ownership over the delegate
|
||||
*/
|
||||
EdgesIterator (EdgesIteratorDelegate *delegate)
|
||||
: generic_shape_iterator<db::Edge> (delegate)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Copy constructor and assignment
|
||||
*/
|
||||
EdgesIterator (const EdgesIterator &other)
|
||||
: generic_shape_iterator<db::Edge> (static_cast<const generic_shape_iterator<db::Edge> &> (other))
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assignment
|
||||
*/
|
||||
EdgesIterator &operator= (const EdgesIterator &other)
|
||||
{
|
||||
generic_shape_iterator<db::Edge>::operator= (other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Increment
|
||||
*/
|
||||
EdgesIterator &operator++ ()
|
||||
{
|
||||
generic_shape_iterator<db::Edge>::operator++ ();
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
typedef addressable_shape_delivery_gen<EdgesIterator> AddressableEdgeDelivery;
|
||||
typedef generic_shape_iterator<db::Edge> EdgesIterator;
|
||||
typedef addressable_shape_delivery<Edge> AddressableEdgeDelivery;
|
||||
|
||||
class Edges;
|
||||
|
||||
|
|
@ -269,7 +214,15 @@ public:
|
|||
/**
|
||||
* @brief Gets the underlying delegate object
|
||||
*/
|
||||
EdgesDelegate *delegate () const
|
||||
const EdgesDelegate *delegate () const
|
||||
{
|
||||
return mp_delegate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the underlying delegate object
|
||||
*/
|
||||
EdgesDelegate *delegate ()
|
||||
{
|
||||
return mp_delegate;
|
||||
}
|
||||
|
|
@ -1441,7 +1394,7 @@ public:
|
|||
*/
|
||||
AddressableEdgeDelivery addressable_edges () const
|
||||
{
|
||||
return AddressableEdgeDelivery (begin (), has_valid_edges ());
|
||||
return AddressableEdgeDelivery (begin ());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1460,7 +1413,7 @@ public:
|
|||
*/
|
||||
AddressableEdgeDelivery addressable_merged_edges () const
|
||||
{
|
||||
return AddressableEdgeDelivery (begin_merged (), has_valid_merged_edges ());
|
||||
return AddressableEdgeDelivery (begin_merged ());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1470,6 +1423,20 @@ public:
|
|||
*/
|
||||
const db::RecursiveShapeIterator &iter () const;
|
||||
|
||||
/**
|
||||
* @brief Gets the property repository
|
||||
*
|
||||
* Use this object to decode property IDs.
|
||||
*/
|
||||
const db::PropertiesRepository &properties_repository () const;
|
||||
|
||||
/**
|
||||
* @brief Gets the property repository
|
||||
*
|
||||
* Use this object to decode and encode property IDs.
|
||||
*/
|
||||
db::PropertiesRepository &properties_repository ();
|
||||
|
||||
/**
|
||||
* @brief Equality
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -239,6 +239,12 @@ public:
|
|||
|
||||
virtual EdgesDelegate *clone () const = 0;
|
||||
|
||||
EdgesDelegate *remove_properties (bool remove = true)
|
||||
{
|
||||
ShapeCollectionDelegateBase::remove_properties (remove);
|
||||
return this;
|
||||
}
|
||||
|
||||
void set_base_verbosity (int vb);
|
||||
int base_verbosity () const
|
||||
{
|
||||
|
|
@ -340,6 +346,9 @@ public:
|
|||
virtual bool has_valid_merged_edges () const = 0;
|
||||
|
||||
virtual const db::RecursiveShapeIterator *iter () const = 0;
|
||||
virtual void apply_property_translator (const db::PropertiesTranslator &pt) = 0;
|
||||
virtual db::PropertiesRepository *properties_repository () = 0;
|
||||
virtual const db::PropertiesRepository *properties_repository () const = 0;
|
||||
|
||||
virtual bool equals (const Edges &other) const = 0;
|
||||
virtual bool less (const Edges &other) const = 0;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,203 @@
|
|||
|
||||
/*
|
||||
|
||||
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
|
||||
|
||||
*/
|
||||
|
||||
#include "dbEdgesLocalOperations.h"
|
||||
#include "dbHierProcessor.h"
|
||||
#include "dbLocalOperationUtils.h"
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
// EdgeBoolAndOrNotLocalOperation implementation
|
||||
|
||||
EdgeBoolAndOrNotLocalOperation::EdgeBoolAndOrNotLocalOperation (EdgeBoolOp op)
|
||||
: m_op (op)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
OnEmptyIntruderHint
|
||||
EdgeBoolAndOrNotLocalOperation::on_empty_intruder_hint () const
|
||||
{
|
||||
return (m_op == EdgeAnd || m_op == EdgeIntersections) ? Drop : Copy;
|
||||
}
|
||||
|
||||
std::string
|
||||
EdgeBoolAndOrNotLocalOperation::description () const
|
||||
{
|
||||
if (m_op == EdgeIntersections) {
|
||||
return tl::to_string (tr ("Edge INTERSECTION operation"));
|
||||
} else if (m_op == EdgeAnd) {
|
||||
return tl::to_string (tr ("Edge AND operation"));
|
||||
} else if (m_op == EdgeNot) {
|
||||
return tl::to_string (tr ("Edge NOT operation"));
|
||||
} else {
|
||||
return std::string ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
EdgeBoolAndOrNotLocalOperation::do_compute_local (db::Layout * /*layout*/, const shape_interactions<db::Edge, db::Edge> &interactions, std::vector<std::unordered_set<db::Edge> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const
|
||||
{
|
||||
tl_assert (results.size () == size_t (m_op == EdgeAndNot ? 2 : 1));
|
||||
|
||||
std::unordered_set<db::Edge> &result = results.front ();
|
||||
|
||||
std::unordered_set<db::Edge> *result2 = 0;
|
||||
if (results.size () > 1) {
|
||||
result2 = &results[1];
|
||||
}
|
||||
|
||||
EdgeBooleanClusterCollector<std::unordered_set<db::Edge> > cluster_collector (&result, m_op, result2);
|
||||
|
||||
db::box_scanner<db::Edge, size_t> scanner;
|
||||
|
||||
std::set<db::Edge> others;
|
||||
for (shape_interactions<db::Edge, db::Edge>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
for (shape_interactions<db::Edge, db::Edge>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
others.insert (interactions.intruder_shape (*j).second);
|
||||
}
|
||||
}
|
||||
|
||||
bool any_subject = false;
|
||||
bool is_and = (m_op == EdgeAnd || m_op == EdgeAndNot || m_op == EdgeIntersections);
|
||||
|
||||
for (shape_interactions<db::Edge, db::Edge>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
|
||||
const db::Edge &subject = interactions.subject_shape (i->first);
|
||||
if (others.find (subject) != others.end ()) {
|
||||
if (is_and) {
|
||||
result.insert (subject);
|
||||
}
|
||||
} else if (i->second.empty ()) {
|
||||
// shortcut (not: keep, and: drop)
|
||||
if (! is_and) {
|
||||
result.insert (subject);
|
||||
}
|
||||
} else {
|
||||
scanner.insert (&subject, 0);
|
||||
any_subject = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (! others.empty () || any_subject) {
|
||||
|
||||
for (std::set<db::Edge>::const_iterator o = others.begin (); o != others.end (); ++o) {
|
||||
scanner.insert (o.operator-> (), 1);
|
||||
}
|
||||
|
||||
scanner.process (cluster_collector, 1, db::box_convert<db::Edge> ());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
// EdgeToPolygonLocalOperation implementation
|
||||
|
||||
EdgeToPolygonLocalOperation::EdgeToPolygonLocalOperation (EdgePolygonOp::mode_t op, bool include_borders)
|
||||
: m_op (op), m_include_borders (include_borders)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
OnEmptyIntruderHint
|
||||
EdgeToPolygonLocalOperation::on_empty_intruder_hint () const
|
||||
{
|
||||
return m_op == EdgePolygonOp::Inside ? Drop : (m_op == EdgePolygonOp::Outside ? Copy : CopyToSecond);
|
||||
}
|
||||
|
||||
std::string
|
||||
EdgeToPolygonLocalOperation::description () const
|
||||
{
|
||||
if (m_op == EdgePolygonOp::Inside) {
|
||||
return tl::to_string (tr ("Edge to polygon AND/INSIDE"));
|
||||
} else if (m_op == EdgePolygonOp::Outside) {
|
||||
return tl::to_string (tr ("Edge to polygon NOT/OUTSIDE"));
|
||||
} else {
|
||||
return tl::to_string (tr ("Edge to polygon ANDNOT/INOUTSIDE"));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
EdgeToPolygonLocalOperation::do_compute_local (db::Layout * /*layout*/, const shape_interactions<db::Edge, db::PolygonRef> &interactions, std::vector<std::unordered_set<db::Edge> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const
|
||||
{
|
||||
tl_assert (results.size () == size_t (m_op == EdgePolygonOp::Both ? 2 : 1));
|
||||
|
||||
std::unordered_set<db::Edge> &result = results.front ();
|
||||
|
||||
std::unordered_set<db::Edge> *result2 = 0;
|
||||
if (results.size () > 1) {
|
||||
result2 = &results[1];
|
||||
}
|
||||
|
||||
db::EdgeProcessor ep;
|
||||
|
||||
std::set<db::PolygonRef> others;
|
||||
for (shape_interactions<db::Edge, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
for (shape_interactions<db::Edge, db::PolygonRef>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
others.insert (interactions.intruder_shape (*j).second);
|
||||
}
|
||||
}
|
||||
|
||||
bool any_subject = false;
|
||||
|
||||
for (shape_interactions<db::Edge, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
|
||||
const db::Edge &subject = interactions.subject_shape (i->first);
|
||||
if (i->second.empty ()) {
|
||||
// shortcut (outside: keep, otherwise: drop)
|
||||
if (m_op == db::EdgePolygonOp::Outside) {
|
||||
result.insert (subject);
|
||||
} else if (m_op == db::EdgePolygonOp::Both) {
|
||||
result2->insert (subject);
|
||||
}
|
||||
} else {
|
||||
ep.insert (subject, 1);
|
||||
any_subject = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (! others.empty () || any_subject) {
|
||||
|
||||
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, 0);
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<db::EdgeToEdgeSetGenerator> cc_second;
|
||||
if (result2) {
|
||||
cc_second.reset (new db::EdgeToEdgeSetGenerator (*result2, 2 /*second tag*/));
|
||||
}
|
||||
|
||||
db::EdgeToEdgeSetGenerator cc (result, 1 /*first tag*/, cc_second.get ());
|
||||
db::EdgePolygonOp op (m_op, m_include_borders);
|
||||
ep.process (cc, op);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
|
||||
/*
|
||||
|
||||
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_dbEdgesLocalOperation
|
||||
#define HDR_dbEdgesLocalOperation
|
||||
|
||||
#include "dbCommon.h"
|
||||
|
||||
#include "dbLayout.h"
|
||||
#include "dbEdgeBoolean.h"
|
||||
#include "dbEdgeProcessor.h"
|
||||
#include "dbLocalOperation.h"
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Implements a boolean AND or NOT operation between edges
|
||||
*/
|
||||
class DB_PUBLIC EdgeBoolAndOrNotLocalOperation
|
||||
: public local_operation<db::Edge, db::Edge, db::Edge>
|
||||
{
|
||||
public:
|
||||
EdgeBoolAndOrNotLocalOperation (db::EdgeBoolOp op);
|
||||
|
||||
virtual void do_compute_local (db::Layout *layout, const shape_interactions<db::Edge, db::Edge> &interactions, std::vector<std::unordered_set<db::Edge> > &result, size_t max_vertex_count, double area_ratio) const;
|
||||
virtual OnEmptyIntruderHint on_empty_intruder_hint () const;
|
||||
virtual std::string description () const;
|
||||
|
||||
// edge interaction distance is 1 to force overlap between edges and edge/boxes
|
||||
virtual db::Coord dist () const { return 1; }
|
||||
|
||||
private:
|
||||
db::EdgeBoolOp m_op;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Implements a boolean AND or NOT operation between edges and polygons (polygons as intruders)
|
||||
*
|
||||
* "AND" is implemented by "outside == false", "NOT" by "outside == true" with "include_borders == true".
|
||||
* With "include_borders == false" the operations are "INSIDE" and "OUTSIDE".
|
||||
*/
|
||||
class DB_PUBLIC EdgeToPolygonLocalOperation
|
||||
: public local_operation<db::Edge, db::PolygonRef, db::Edge>
|
||||
{
|
||||
public:
|
||||
EdgeToPolygonLocalOperation (EdgePolygonOp::mode_t op, bool include_borders);
|
||||
|
||||
virtual void do_compute_local (db::Layout *layout, const shape_interactions<db::Edge, db::PolygonRef> &interactions, std::vector<std::unordered_set<db::Edge> > &result, size_t max_vertex_count, double area_ratio) const;
|
||||
virtual OnEmptyIntruderHint on_empty_intruder_hint () const;
|
||||
virtual std::string description () const;
|
||||
|
||||
// edge interaction distance is 1 to force overlap between edges and edge/boxes
|
||||
virtual db::Coord dist () const { return m_include_borders ? 1 : 0; }
|
||||
|
||||
private:
|
||||
db::EdgePolygonOp::mode_t m_op;
|
||||
bool m_include_borders;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -73,6 +73,9 @@ public:
|
|||
virtual bool has_valid_edge_pairs () const { return true; }
|
||||
|
||||
virtual const db::RecursiveShapeIterator *iter () const { return 0; }
|
||||
virtual void apply_property_translator (const db::PropertiesTranslator &) { }
|
||||
virtual db::PropertiesRepository *properties_repository () { return 0; }
|
||||
virtual const db::PropertiesRepository *properties_repository () const { return 0; }
|
||||
|
||||
virtual bool equals (const EdgePairs &other) const;
|
||||
virtual bool less (const EdgePairs &other) const;
|
||||
|
|
|
|||
|
|
@ -122,6 +122,9 @@ public:
|
|||
virtual bool has_valid_merged_edges () const { return true; }
|
||||
|
||||
virtual const db::RecursiveShapeIterator *iter () const { return 0; }
|
||||
virtual void apply_property_translator (const db::PropertiesTranslator &) { }
|
||||
virtual db::PropertiesRepository *properties_repository () { return 0; }
|
||||
virtual const db::PropertiesRepository *properties_repository () const { return 0; }
|
||||
|
||||
virtual bool equals (const Edges &other) const;
|
||||
virtual bool less (const Edges &other) const;
|
||||
|
|
|
|||
|
|
@ -67,19 +67,20 @@ EmptyRegion::add (const Region &other) const
|
|||
}
|
||||
|
||||
RegionDelegate *
|
||||
EmptyRegion::xor_with (const Region &other) const
|
||||
EmptyRegion::xor_with (const Region &other, db::PropertyConstraint prop_constraint) const
|
||||
{
|
||||
return or_with (other);
|
||||
return or_with (other, prop_constraint);
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
EmptyRegion::or_with (const Region &other) const
|
||||
EmptyRegion::or_with (const Region &other, db::PropertyConstraint /*prop_constraint*/) const
|
||||
{
|
||||
if (other.empty ()) {
|
||||
return new EmptyRegion ();
|
||||
} else if (! other.strict_handling ()) {
|
||||
return other.delegate ()->clone ();
|
||||
} else {
|
||||
// TODO: implement prop_constraint
|
||||
return other.delegate ()->merged ();
|
||||
}
|
||||
}
|
||||
|
|
@ -97,19 +98,19 @@ EmptyRegion::processed_to_edge_pairs (const PolygonToEdgePairProcessorBase &) co
|
|||
}
|
||||
|
||||
EdgePairsDelegate *
|
||||
EmptyRegion::cop_to_edge_pairs (db::CompoundRegionOperationNode &)
|
||||
EmptyRegion::cop_to_edge_pairs (db::CompoundRegionOperationNode &, db::PropertyConstraint)
|
||||
{
|
||||
return new EmptyEdgePairs ();
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
EmptyRegion::cop_to_region (db::CompoundRegionOperationNode &)
|
||||
EmptyRegion::cop_to_region (db::CompoundRegionOperationNode &, db::PropertyConstraint)
|
||||
{
|
||||
return new EmptyRegion ();
|
||||
}
|
||||
|
||||
EdgesDelegate *
|
||||
EmptyRegion::cop_to_edges (db::CompoundRegionOperationNode &)
|
||||
EmptyRegion::cop_to_edges (db::CompoundRegionOperationNode &, db::PropertyConstraint)
|
||||
{
|
||||
return new EmptyEdges ();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,9 +62,9 @@ public:
|
|||
|
||||
virtual Box bbox () const { return Box (); }
|
||||
|
||||
virtual EdgePairsDelegate *cop_to_edge_pairs (db::CompoundRegionOperationNode &node);
|
||||
virtual RegionDelegate *cop_to_region (db::CompoundRegionOperationNode &node);
|
||||
virtual EdgesDelegate *cop_to_edges (db::CompoundRegionOperationNode &node);
|
||||
virtual EdgePairsDelegate *cop_to_edge_pairs (db::CompoundRegionOperationNode &node, PropertyConstraint);
|
||||
virtual RegionDelegate *cop_to_region (db::CompoundRegionOperationNode &node, PropertyConstraint);
|
||||
virtual EdgesDelegate *cop_to_edges (db::CompoundRegionOperationNode &node, PropertyConstraint);
|
||||
|
||||
virtual EdgePairsDelegate *width_check (db::Coord, const RegionCheckOptions &) const;
|
||||
virtual EdgePairsDelegate *space_check (db::Coord, const RegionCheckOptions &) const;
|
||||
|
|
@ -98,11 +98,11 @@ 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 *xor_with (const Region &other) const;
|
||||
virtual RegionDelegate *or_with (const Region &other) const;
|
||||
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, db::PropertyConstraint prop_constraint) const;
|
||||
virtual RegionDelegate *or_with (const Region &other, db::PropertyConstraint prop_constraint) const;
|
||||
virtual RegionDelegate *add_in_place (const Region &other);
|
||||
virtual RegionDelegate *add (const Region &other) const;
|
||||
|
||||
|
|
@ -138,14 +138,20 @@ public:
|
|||
virtual bool has_valid_polygons () const { return true; }
|
||||
virtual bool has_valid_merged_polygons () const { return true; }
|
||||
virtual const db::Polygon *nth (size_t) const { tl_assert (false); }
|
||||
virtual db::properties_id_type nth_prop_id (size_t) const { tl_assert (false); }
|
||||
|
||||
virtual const db::RecursiveShapeIterator *iter () const { return 0; }
|
||||
virtual void apply_property_translator (const db::PropertiesTranslator &) { }
|
||||
virtual db::PropertiesRepository *properties_repository () { return 0; }
|
||||
virtual const db::PropertiesRepository *properties_repository () const { return 0; }
|
||||
|
||||
virtual bool equals (const Region &other) const;
|
||||
virtual bool less (const Region &other) const;
|
||||
|
||||
virtual void insert_into (Layout *, db::cell_index_type, unsigned int) const { }
|
||||
|
||||
virtual RegionDelegate *nets (LayoutToNetlist *, NetPropertyMode, const tl::Variant &, const std::vector<const db::Net *> *) const { return new EmptyRegion (); }
|
||||
|
||||
private:
|
||||
EmptyRegion &operator= (const EmptyRegion &other);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -71,6 +71,9 @@ public:
|
|||
virtual bool has_valid_texts () const { return true; }
|
||||
|
||||
virtual const db::RecursiveShapeIterator *iter () const { return 0; }
|
||||
virtual void apply_property_translator (const db::PropertiesTranslator &) { }
|
||||
virtual db::PropertiesRepository *properties_repository () { return 0; }
|
||||
virtual const db::PropertiesRepository *properties_repository () const { return 0; }
|
||||
|
||||
virtual bool equals (const Texts &other) const;
|
||||
virtual bool less (const Texts &other) const;
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ namespace db
|
|||
// FlatEdgePairs implementation
|
||||
|
||||
FlatEdgePairs::FlatEdgePairs ()
|
||||
: MutableEdgePairs (), mp_edge_pairs (new db::Shapes (false))
|
||||
: MutableEdgePairs (), mp_edge_pairs (new db::Shapes (false)), mp_properties_repository (new db::PropertiesRepository ())
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
|
@ -43,13 +43,13 @@ FlatEdgePairs::~FlatEdgePairs ()
|
|||
}
|
||||
|
||||
FlatEdgePairs::FlatEdgePairs (const FlatEdgePairs &other)
|
||||
: MutableEdgePairs (other), mp_edge_pairs (other.mp_edge_pairs)
|
||||
: MutableEdgePairs (other), mp_edge_pairs (other.mp_edge_pairs), mp_properties_repository (other.mp_properties_repository)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
FlatEdgePairs::FlatEdgePairs (const db::Shapes &edge_pairs)
|
||||
: MutableEdgePairs (), mp_edge_pairs (new db::Shapes (edge_pairs))
|
||||
: MutableEdgePairs (), mp_edge_pairs (new db::Shapes (edge_pairs)), mp_properties_repository (new db::PropertiesRepository ())
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
|
@ -97,6 +97,8 @@ Box FlatEdgePairs::compute_bbox () const
|
|||
EdgePairsDelegate *
|
||||
FlatEdgePairs::filter_in_place (const EdgePairFilterBase &filter)
|
||||
{
|
||||
// TODO: implement property support
|
||||
|
||||
db::Shapes &ep = *mp_edge_pairs;
|
||||
|
||||
edge_pair_iterator_type pw = ep.get_layer<db::EdgePair, db::unstable_layer_tag> ().begin ();
|
||||
|
|
@ -121,22 +123,22 @@ EdgePairsDelegate *FlatEdgePairs::add (const EdgePairs &other) const
|
|||
std::unique_ptr<FlatEdgePairs> new_edge_pairs (new FlatEdgePairs (*this));
|
||||
new_edge_pairs->invalidate_cache ();
|
||||
|
||||
FlatEdgePairs *other_flat = dynamic_cast<FlatEdgePairs *> (other.delegate ());
|
||||
db::PropertyMapper pm (new_edge_pairs->properties_repository (), &other.properties_repository ());
|
||||
|
||||
const FlatEdgePairs *other_flat = dynamic_cast<const FlatEdgePairs *> (other.delegate ());
|
||||
if (other_flat) {
|
||||
|
||||
new_edge_pairs->raw_edge_pairs ().insert (other_flat->raw_edge_pairs ().get_layer<db::EdgePair, db::unstable_layer_tag> ().begin (), other_flat->raw_edge_pairs ().get_layer<db::EdgePair, db::unstable_layer_tag> ().end ());
|
||||
new_edge_pairs->raw_edge_pairs ().insert (other_flat->raw_edge_pairs (), pm);
|
||||
|
||||
} else {
|
||||
|
||||
size_t n = new_edge_pairs->raw_edge_pairs ().size ();
|
||||
for (EdgePairsIterator p (other.begin ()); ! p.at_end (); ++p) {
|
||||
++n;
|
||||
}
|
||||
|
||||
new_edge_pairs->raw_edge_pairs ().reserve (db::EdgePair::tag (), n);
|
||||
|
||||
for (EdgePairsIterator p (other.begin ()); ! p.at_end (); ++p) {
|
||||
new_edge_pairs->raw_edge_pairs ().insert (*p);
|
||||
db::properties_id_type prop_id = pm (p.prop_id ());
|
||||
if (prop_id != 0) {
|
||||
new_edge_pairs->raw_edge_pairs ().insert (db::EdgePairWithProperties (*p, prop_id));
|
||||
} else {
|
||||
new_edge_pairs->raw_edge_pairs ().insert (*p);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -150,22 +152,22 @@ EdgePairsDelegate *FlatEdgePairs::add_in_place (const EdgePairs &other)
|
|||
|
||||
db::Shapes &ep = *mp_edge_pairs;
|
||||
|
||||
FlatEdgePairs *other_flat = dynamic_cast<FlatEdgePairs *> (other.delegate ());
|
||||
db::PropertyMapper pm (properties_repository (), &other.properties_repository ());
|
||||
|
||||
const FlatEdgePairs *other_flat = dynamic_cast<const FlatEdgePairs *> (other.delegate ());
|
||||
if (other_flat) {
|
||||
|
||||
ep.insert (other_flat->raw_edge_pairs ().get_layer<db::EdgePair, db::unstable_layer_tag> ().begin (), other_flat->raw_edge_pairs ().get_layer<db::EdgePair, db::unstable_layer_tag> ().end ());
|
||||
ep.insert (other_flat->raw_edge_pairs (), pm);
|
||||
|
||||
} else {
|
||||
|
||||
size_t n = ep.size ();
|
||||
for (EdgePairsIterator p (other.begin ()); ! p.at_end (); ++p) {
|
||||
++n;
|
||||
}
|
||||
|
||||
ep.reserve (db::EdgePair::tag (), n);
|
||||
|
||||
for (EdgePairsIterator p (other.begin ()); ! p.at_end (); ++p) {
|
||||
ep.insert (*p);
|
||||
db::properties_id_type prop_id = pm (p.prop_id ());
|
||||
if (prop_id != 0) {
|
||||
ep.insert (db::EdgePairWithProperties (*p, prop_id));
|
||||
} else {
|
||||
ep.insert (*p);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -188,19 +190,50 @@ const db::RecursiveShapeIterator *FlatEdgePairs::iter () const
|
|||
return 0;
|
||||
}
|
||||
|
||||
void FlatEdgePairs::apply_property_translator (const db::PropertiesTranslator &pt)
|
||||
{
|
||||
if ((mp_edge_pairs->type_mask () & db::ShapeIterator::Properties) != 0) {
|
||||
|
||||
db::Shapes new_edge_pairs (mp_edge_pairs->is_editable ());
|
||||
new_edge_pairs.assign (*mp_edge_pairs, pt);
|
||||
mp_edge_pairs->swap (new_edge_pairs);
|
||||
|
||||
invalidate_cache ();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
db::PropertiesRepository *FlatEdgePairs::properties_repository ()
|
||||
{
|
||||
return mp_properties_repository.get_non_const ();
|
||||
}
|
||||
|
||||
const db::PropertiesRepository *FlatEdgePairs::properties_repository () const
|
||||
{
|
||||
return mp_properties_repository.get_const ();
|
||||
}
|
||||
|
||||
void
|
||||
FlatEdgePairs::insert_into_as_polygons (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer, db::Coord enl) const
|
||||
{
|
||||
db::Shapes &out = layout->cell (into_cell).shapes (into_layer);
|
||||
db::PropertyMapper pm (&layout->properties_repository (), properties_repository ());
|
||||
|
||||
for (EdgePairsIterator p (begin ()); ! p.at_end (); ++p) {
|
||||
out.insert (p->normalized ().to_simple_polygon (enl));
|
||||
db::properties_id_type prop_id = pm (p.prop_id ());
|
||||
if (prop_id != 0) {
|
||||
out.insert (db::SimplePolygonWithProperties (p->normalized ().to_simple_polygon (enl), prop_id));
|
||||
} else {
|
||||
out.insert (p->normalized ().to_simple_polygon (enl));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FlatEdgePairs::insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const
|
||||
{
|
||||
layout->cell (into_cell).shapes (into_layer).insert (*mp_edge_pairs);
|
||||
db::PropertyMapper pm (&layout->properties_repository (), properties_repository ());
|
||||
layout->cell (into_cell).shapes (into_layer).insert (*mp_edge_pairs, pm);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -78,6 +78,9 @@ public:
|
|||
virtual bool has_valid_edge_pairs () const;
|
||||
|
||||
virtual const db::RecursiveShapeIterator *iter () const;
|
||||
virtual void apply_property_translator (const db::PropertiesTranslator &pt);
|
||||
virtual db::PropertiesRepository *properties_repository ();
|
||||
virtual const db::PropertiesRepository *properties_repository () const;
|
||||
|
||||
virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const;
|
||||
virtual void insert_into_as_polygons (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer, db::Coord enl) const;
|
||||
|
|
@ -119,6 +122,7 @@ private:
|
|||
FlatEdgePairs &operator= (const FlatEdgePairs &other);
|
||||
|
||||
mutable tl::copy_on_write_ptr<db::Shapes> mp_edge_pairs;
|
||||
mutable tl::copy_on_write_ptr<db::PropertiesRepository> mp_properties_repository;
|
||||
|
||||
template <class Trans>
|
||||
void transform_generic (const Trans &trans)
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ namespace db
|
|||
// FlatEdges implementation
|
||||
|
||||
FlatEdges::FlatEdges ()
|
||||
: MutableEdges (), mp_edges (new db::Shapes (false)), mp_merged_edges (new db::Shapes (false))
|
||||
: MutableEdges (), mp_edges (new db::Shapes (false)), mp_merged_edges (new db::Shapes (false)), mp_properties_repository (new db::PropertiesRepository ())
|
||||
{
|
||||
init ();
|
||||
}
|
||||
|
|
@ -44,7 +44,7 @@ FlatEdges::~FlatEdges ()
|
|||
}
|
||||
|
||||
FlatEdges::FlatEdges (const FlatEdges &other)
|
||||
: MutableEdges (other), mp_edges (other.mp_edges), mp_merged_edges (other.mp_merged_edges)
|
||||
: MutableEdges (other), mp_edges (other.mp_edges), mp_merged_edges (other.mp_merged_edges), mp_properties_repository (other.mp_properties_repository)
|
||||
{
|
||||
init ();
|
||||
|
||||
|
|
@ -53,7 +53,7 @@ FlatEdges::FlatEdges (const FlatEdges &other)
|
|||
}
|
||||
|
||||
FlatEdges::FlatEdges (const db::Shapes &edges, bool is_merged)
|
||||
: MutableEdges (), mp_edges (new db::Shapes (edges)), mp_merged_edges (new db::Shapes (false))
|
||||
: MutableEdges (), mp_edges (new db::Shapes (edges)), mp_merged_edges (new db::Shapes (false)), mp_properties_repository (new db::PropertiesRepository ())
|
||||
{
|
||||
init ();
|
||||
|
||||
|
|
@ -61,7 +61,7 @@ FlatEdges::FlatEdges (const db::Shapes &edges, bool is_merged)
|
|||
}
|
||||
|
||||
FlatEdges::FlatEdges (bool is_merged)
|
||||
: MutableEdges (), mp_edges (new db::Shapes (false)), mp_merged_edges (new db::Shapes (false))
|
||||
: MutableEdges (), mp_edges (new db::Shapes (false)), mp_merged_edges (new db::Shapes (false)), mp_properties_repository (new db::PropertiesRepository ())
|
||||
{
|
||||
init ();
|
||||
|
||||
|
|
@ -88,7 +88,8 @@ void FlatEdges::init ()
|
|||
|
||||
void FlatEdges::insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const
|
||||
{
|
||||
layout->cell (into_cell).shapes (into_layer).insert (*mp_edges);
|
||||
db::PropertyMapper pm (&layout->properties_repository (), mp_properties_repository.get_const ());
|
||||
layout->cell (into_cell).shapes (into_layer).insert (*mp_edges, pm);
|
||||
}
|
||||
|
||||
void FlatEdges::merged_semantics_changed ()
|
||||
|
|
@ -109,19 +110,62 @@ FlatEdges::ensure_merged_edges_valid () const
|
|||
|
||||
mp_merged_edges->clear ();
|
||||
|
||||
db::Shapes tmp (false);
|
||||
EdgeBooleanClusterCollectorToShapes cluster_collector (&tmp, EdgeOr);
|
||||
|
||||
db::box_scanner<db::Edge, size_t> scanner (report_progress (), progress_desc ());
|
||||
scanner.reserve (mp_edges->size ());
|
||||
|
||||
for (EdgesIterator e (begin ()); ! e.at_end (); ++e) {
|
||||
if (! e->is_degenerate ()) {
|
||||
scanner.insert (&*e, 0);
|
||||
// count edges and reserve memory
|
||||
size_t n = 0;
|
||||
db::properties_id_type prop_id = 0;
|
||||
bool need_split_props = false;
|
||||
for (EdgesIterator s (begin ()); ! s.at_end (); ++s, ++n) {
|
||||
if (n == 0) {
|
||||
prop_id = s.prop_id ();
|
||||
} else if (! need_split_props && prop_id != s.prop_id ()) {
|
||||
need_split_props = true;
|
||||
}
|
||||
}
|
||||
|
||||
scanner.process (cluster_collector, 1, db::box_convert<db::Edge> ());
|
||||
db::Shapes tmp (false);
|
||||
|
||||
if (! need_split_props) {
|
||||
|
||||
EdgeBooleanClusterCollectorToShapes cluster_collector (&tmp, EdgeOr);
|
||||
|
||||
scanner.reserve (mp_edges->size ());
|
||||
|
||||
for (EdgesIterator e (begin ()); ! e.at_end (); ++e) {
|
||||
if (! e->is_degenerate ()) {
|
||||
scanner.insert (&*e, 0);
|
||||
}
|
||||
}
|
||||
|
||||
scanner.process (cluster_collector, 1, db::box_convert<db::Edge> ());
|
||||
|
||||
} else {
|
||||
|
||||
std::map<db::properties_id_type, std::vector<const db::Edge *> > edges_by_props;
|
||||
|
||||
for (EdgesIterator e (begin ()); ! e.at_end (); ++e) {
|
||||
if (! e->is_degenerate ()) {
|
||||
edges_by_props [e.prop_id ()].push_back (e.operator-> ());
|
||||
}
|
||||
}
|
||||
|
||||
for (auto s2p = edges_by_props.begin (); s2p != edges_by_props.end (); ++s2p) {
|
||||
|
||||
EdgeBooleanClusterCollectorToShapes cluster_collector (&tmp, EdgeOr, s2p->first);
|
||||
|
||||
scanner.clear ();
|
||||
scanner.reserve (s2p->second.size ());
|
||||
|
||||
for (auto s = s2p->second.begin (); s != s2p->second.end (); ++s) {
|
||||
scanner.insert (*s, 0);
|
||||
}
|
||||
|
||||
scanner.process (cluster_collector, 1, db::box_convert<db::Edge> ());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
mp_merged_edges->swap (tmp);
|
||||
m_merged_edges_valid = true;
|
||||
|
|
@ -192,23 +236,36 @@ FlatEdges::processed_in_place (const EdgeProcessorBase &filter)
|
|||
db::Shapes &e = *mp_edges;
|
||||
|
||||
edge_iterator_type pw = e.get_layer<db::Edge, db::unstable_layer_tag> ().begin ();
|
||||
edge_iterator_wp_type pw_wp = e.get_layer<db::EdgeWithProperties, db::unstable_layer_tag> ().begin ();
|
||||
|
||||
for (EdgesIterator p (filter.requires_raw_input () ? begin () : begin_merged ()); ! p.at_end (); ++p) {
|
||||
|
||||
edge_res.clear ();
|
||||
filter.process (*p, edge_res);
|
||||
|
||||
for (std::vector<db::Edge>::const_iterator pr = edge_res.begin (); pr != edge_res.end (); ++pr) {
|
||||
if (pw == e.get_layer<db::Edge, db::unstable_layer_tag> ().end ()) {
|
||||
e.get_layer<db::Edge, db::unstable_layer_tag> ().insert (*pr);
|
||||
pw = e.get_layer<db::Edge, db::unstable_layer_tag> ().end ();
|
||||
if (p.prop_id () != 0) {
|
||||
if (pw_wp == e.get_layer<db::EdgeWithProperties, db::unstable_layer_tag> ().end ()) {
|
||||
e.get_layer<db::EdgeWithProperties, db::unstable_layer_tag> ().insert (db::EdgeWithProperties (*pr, p.prop_id ()));
|
||||
pw_wp = e.get_layer<db::EdgeWithProperties, db::unstable_layer_tag> ().end ();
|
||||
} else {
|
||||
e.get_layer<db::EdgeWithProperties, db::unstable_layer_tag> ().replace (pw_wp++, db::EdgeWithProperties (*pr, p.prop_id ()));
|
||||
}
|
||||
} else {
|
||||
e.get_layer<db::Edge, db::unstable_layer_tag> ().replace (pw++, *pr);
|
||||
if (pw == e.get_layer<db::Edge, db::unstable_layer_tag> ().end ()) {
|
||||
e.get_layer<db::Edge, db::unstable_layer_tag> ().insert (*pr);
|
||||
pw = e.get_layer<db::Edge, db::unstable_layer_tag> ().end ();
|
||||
} else {
|
||||
e.get_layer<db::Edge, db::unstable_layer_tag> ().replace (pw++, *pr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
e.get_layer<db::Edge, db::unstable_layer_tag> ().erase (pw, e.get_layer<db::Edge, db::unstable_layer_tag> ().end ());
|
||||
e.get_layer<db::EdgeWithProperties, db::unstable_layer_tag> ().erase (pw_wp, e.get_layer<db::EdgeWithProperties, db::unstable_layer_tag> ().end ());
|
||||
|
||||
mp_merged_edges->clear ();
|
||||
m_is_merged = filter.result_is_merged () && merged_semantics ();
|
||||
|
||||
|
|
@ -221,18 +278,31 @@ FlatEdges::filter_in_place (const EdgeFilterBase &filter)
|
|||
db::Shapes &e = *mp_edges;
|
||||
|
||||
edge_iterator_type pw = e.get_layer<db::Edge, db::unstable_layer_tag> ().begin ();
|
||||
edge_iterator_wp_type pw_wp = e.get_layer<db::EdgeWithProperties, db::unstable_layer_tag> ().begin ();
|
||||
|
||||
for (EdgesIterator p (begin_merged ()); ! p.at_end (); ++p) {
|
||||
if (filter.selected (*p)) {
|
||||
if (pw == e.get_layer<db::Edge, db::unstable_layer_tag> ().end ()) {
|
||||
e.get_layer<db::Edge, db::unstable_layer_tag> ().insert (*p);
|
||||
pw = e.get_layer<db::Edge, db::unstable_layer_tag> ().end ();
|
||||
if (p.prop_id () != 0) {
|
||||
if (pw_wp == e.get_layer<db::EdgeWithProperties, db::unstable_layer_tag> ().end ()) {
|
||||
e.get_layer<db::EdgeWithProperties, db::unstable_layer_tag> ().insert (db::EdgeWithProperties (*p, p.prop_id ()));
|
||||
pw_wp = e.get_layer<db::EdgeWithProperties, db::unstable_layer_tag> ().end ();
|
||||
} else {
|
||||
e.get_layer<db::EdgeWithProperties, db::unstable_layer_tag> ().replace (pw_wp++, db::EdgeWithProperties (*p, p.prop_id ()));
|
||||
}
|
||||
} else {
|
||||
e.get_layer<db::Edge, db::unstable_layer_tag> ().replace (pw++, *p);
|
||||
if (pw == e.get_layer<db::Edge, db::unstable_layer_tag> ().end ()) {
|
||||
e.get_layer<db::Edge, db::unstable_layer_tag> ().insert (*p);
|
||||
pw = e.get_layer<db::Edge, db::unstable_layer_tag> ().end ();
|
||||
} else {
|
||||
e.get_layer<db::Edge, db::unstable_layer_tag> ().replace (pw++, *p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
e.get_layer<db::Edge, db::unstable_layer_tag> ().erase (pw, e.get_layer<db::Edge, db::unstable_layer_tag> ().end ());
|
||||
e.get_layer<db::EdgeWithProperties, db::unstable_layer_tag> ().erase (pw_wp, e.get_layer<db::EdgeWithProperties, db::unstable_layer_tag> ().end ());
|
||||
|
||||
mp_merged_edges->clear ();
|
||||
m_is_merged = merged_semantics ();
|
||||
|
||||
|
|
@ -245,7 +315,7 @@ EdgesDelegate *FlatEdges::add (const Edges &other) const
|
|||
new_region->invalidate_cache ();
|
||||
new_region->set_is_merged (false);
|
||||
|
||||
FlatEdges *other_flat = dynamic_cast<FlatEdges *> (other.delegate ());
|
||||
const FlatEdges *other_flat = dynamic_cast<const FlatEdges *> (other.delegate ());
|
||||
if (other_flat) {
|
||||
|
||||
new_region->raw_edges ().insert (other_flat->raw_edges ().get_layer<db::Edge, db::unstable_layer_tag> ().begin (), other_flat->raw_edges ().get_layer<db::Edge, db::unstable_layer_tag> ().end ());
|
||||
|
|
@ -275,7 +345,7 @@ EdgesDelegate *FlatEdges::add_in_place (const Edges &other)
|
|||
|
||||
db::Shapes &e = *mp_edges;
|
||||
|
||||
FlatEdges *other_flat = dynamic_cast<FlatEdges *> (other.delegate ());
|
||||
const FlatEdges *other_flat = dynamic_cast<const FlatEdges *> (other.delegate ());
|
||||
if (other_flat) {
|
||||
|
||||
e.insert (other_flat->raw_edges ().get_layer<db::Edge, db::unstable_layer_tag> ().begin (), other_flat->raw_edges ().get_layer<db::Edge, db::unstable_layer_tag> ().end ());
|
||||
|
|
@ -318,12 +388,40 @@ const db::RecursiveShapeIterator *FlatEdges::iter () const
|
|||
return 0;
|
||||
}
|
||||
|
||||
void FlatEdges::apply_property_translator (const db::PropertiesTranslator &pt)
|
||||
{
|
||||
if ((mp_edges->type_mask () & db::ShapeIterator::Properties) != 0) {
|
||||
|
||||
db::Shapes new_edges (mp_edges->is_editable ());
|
||||
new_edges.assign (*mp_edges, pt);
|
||||
mp_edges->swap (new_edges);
|
||||
|
||||
invalidate_cache ();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
db::PropertiesRepository *FlatEdges::properties_repository ()
|
||||
{
|
||||
return mp_properties_repository.get_non_const ();
|
||||
}
|
||||
|
||||
const db::PropertiesRepository *FlatEdges::properties_repository () const
|
||||
{
|
||||
return mp_properties_repository.get_const ();
|
||||
}
|
||||
|
||||
void
|
||||
FlatEdges::do_insert (const db::Edge &edge)
|
||||
FlatEdges::do_insert (const db::Edge &edge, db::properties_id_type prop_id)
|
||||
{
|
||||
m_is_merged = empty ();
|
||||
|
||||
mp_edges->insert (edge);
|
||||
if (prop_id == 0) {
|
||||
mp_edges->insert (edge);
|
||||
} else {
|
||||
mp_edges->insert (db::EdgeWithProperties (edge, prop_id));
|
||||
}
|
||||
|
||||
invalidate_cache ();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -50,6 +50,8 @@ public:
|
|||
|
||||
typedef db::layer<db::Edge, db::unstable_layer_tag> edge_layer_type;
|
||||
typedef edge_layer_type::iterator edge_iterator_type;
|
||||
typedef db::layer<db::EdgeWithProperties, db::unstable_layer_tag> edge_layer_wp_type;
|
||||
typedef edge_layer_wp_type::iterator edge_iterator_wp_type;
|
||||
|
||||
FlatEdges ();
|
||||
FlatEdges (const db::Shapes &edges, bool is_merged);
|
||||
|
|
@ -91,8 +93,11 @@ public:
|
|||
virtual bool has_valid_merged_edges () const;
|
||||
|
||||
virtual const db::RecursiveShapeIterator *iter () const;
|
||||
virtual void apply_property_translator (const db::PropertiesTranslator &pt);
|
||||
virtual db::PropertiesRepository *properties_repository ();
|
||||
virtual const db::PropertiesRepository *properties_repository () const;
|
||||
|
||||
void do_insert (const db::Edge &edge);
|
||||
void do_insert (const db::Edge &edge, properties_id_type prop_id);
|
||||
|
||||
void do_transform (const db::Trans &t)
|
||||
{
|
||||
|
|
@ -132,6 +137,7 @@ private:
|
|||
mutable tl::copy_on_write_ptr<db::Shapes> mp_edges;
|
||||
mutable tl::copy_on_write_ptr<db::Shapes> mp_merged_edges;
|
||||
mutable bool m_merged_edges_valid;
|
||||
mutable tl::copy_on_write_ptr<db::PropertiesRepository> mp_properties_repository;
|
||||
|
||||
void init ();
|
||||
void ensure_merged_edges_valid () const;
|
||||
|
|
@ -144,6 +150,9 @@ private:
|
|||
for (edge_iterator_type p = e.template get_layer<db::Edge, db::unstable_layer_tag> ().begin (); p != e.get_layer<db::Edge, db::unstable_layer_tag> ().end (); ++p) {
|
||||
e.get_layer<db::Edge, db::unstable_layer_tag> ().replace (p, p->transformed (trans));
|
||||
}
|
||||
for (edge_iterator_wp_type p = e.template get_layer<db::EdgeWithProperties, db::unstable_layer_tag> ().begin (); p != e.get_layer<db::EdgeWithProperties, db::unstable_layer_tag> ().end (); ++p) {
|
||||
e.get_layer<db::EdgeWithProperties, db::unstable_layer_tag> ().replace (p, p->transformed (trans));
|
||||
}
|
||||
invalidate_cache ();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include "dbEmptyRegion.h"
|
||||
#include "dbRegion.h"
|
||||
#include "dbShapeProcessor.h"
|
||||
#include "tlSList.h"
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
|
@ -33,18 +34,13 @@ namespace db
|
|||
// FlatRegion implementation
|
||||
|
||||
FlatRegion::FlatRegion ()
|
||||
: MutableRegion (), mp_polygons (new db::Shapes (false)), mp_merged_polygons (new db::Shapes (false))
|
||||
: MutableRegion (), mp_polygons (new db::Shapes (false)), mp_merged_polygons (new db::Shapes (false)), mp_properties_repository (new db::PropertiesRepository ())
|
||||
{
|
||||
init ();
|
||||
}
|
||||
|
||||
FlatRegion::~FlatRegion ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
FlatRegion::FlatRegion (const FlatRegion &other)
|
||||
: MutableRegion (other), mp_polygons (other.mp_polygons), mp_merged_polygons (other.mp_merged_polygons)
|
||||
: MutableRegion (other), mp_polygons (other.mp_polygons), mp_merged_polygons (other.mp_merged_polygons), mp_properties_repository (other.mp_properties_repository)
|
||||
{
|
||||
init ();
|
||||
|
||||
|
|
@ -53,7 +49,7 @@ FlatRegion::FlatRegion (const FlatRegion &other)
|
|||
}
|
||||
|
||||
FlatRegion::FlatRegion (const db::Shapes &polygons, bool is_merged)
|
||||
: MutableRegion (), mp_polygons (new db::Shapes (polygons)), mp_merged_polygons (new db::Shapes (false))
|
||||
: MutableRegion (), mp_polygons (new db::Shapes (polygons)), mp_merged_polygons (new db::Shapes (false)), mp_properties_repository (new db::PropertiesRepository ())
|
||||
{
|
||||
init ();
|
||||
|
||||
|
|
@ -61,13 +57,18 @@ FlatRegion::FlatRegion (const db::Shapes &polygons, bool is_merged)
|
|||
}
|
||||
|
||||
FlatRegion::FlatRegion (bool is_merged)
|
||||
: MutableRegion (), mp_polygons (new db::Shapes (false)), mp_merged_polygons (new db::Shapes (false))
|
||||
: MutableRegion (), mp_polygons (new db::Shapes (false)), mp_merged_polygons (new db::Shapes (false)), mp_properties_repository (new db::PropertiesRepository ())
|
||||
{
|
||||
init ();
|
||||
|
||||
m_is_merged = is_merged;
|
||||
}
|
||||
|
||||
FlatRegion::~FlatRegion ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void FlatRegion::set_is_merged (bool m)
|
||||
{
|
||||
m_is_merged = m;
|
||||
|
|
@ -108,33 +109,8 @@ void
|
|||
FlatRegion::ensure_merged_polygons_valid () const
|
||||
{
|
||||
if (! m_merged_polygons_valid) {
|
||||
|
||||
mp_merged_polygons->clear ();
|
||||
|
||||
db::EdgeProcessor ep (report_progress (), progress_desc ());
|
||||
ep.set_base_verbosity (base_verbosity ());
|
||||
|
||||
// count edges and reserve memory
|
||||
size_t n = 0;
|
||||
for (RegionIterator p (begin ()); ! p.at_end (); ++p) {
|
||||
n += p->vertices ();
|
||||
}
|
||||
ep.reserve (n);
|
||||
|
||||
// insert the polygons into the processor
|
||||
n = 0;
|
||||
for (RegionIterator p (begin ()); ! p.at_end (); ++p, ++n) {
|
||||
ep.insert (*p, n);
|
||||
}
|
||||
|
||||
// and run the merge step
|
||||
db::MergeOp op (0);
|
||||
db::ShapeGenerator pc (*mp_merged_polygons);
|
||||
db::PolygonGenerator pg (pc, false /*don't resolve holes*/, min_coherence ());
|
||||
ep.process (pg, op);
|
||||
|
||||
merge_polygons_to (*mp_merged_polygons, min_coherence (), 0);
|
||||
m_merged_polygons_valid = true;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -196,20 +172,33 @@ Box FlatRegion::compute_bbox () const
|
|||
RegionDelegate *FlatRegion::filter_in_place (const PolygonFilterBase &filter)
|
||||
{
|
||||
db::layer<db::Polygon, db::unstable_layer_tag> &poly_layer = mp_polygons->get_layer<db::Polygon, db::unstable_layer_tag> ();
|
||||
db::layer<db::PolygonWithProperties, db::unstable_layer_tag> &poly_layer_wp = mp_polygons->get_layer<db::PolygonWithProperties, db::unstable_layer_tag> ();
|
||||
|
||||
polygon_iterator_type pw = poly_layer.begin ();
|
||||
polygon_iterator_wp_type pw_wp = poly_layer_wp.begin ();
|
||||
|
||||
for (RegionIterator p (filter.requires_raw_input () ? begin () : begin_merged ()); ! p.at_end (); ++p) {
|
||||
if (filter.selected (*p)) {
|
||||
if (pw == poly_layer.end ()) {
|
||||
poly_layer.insert (*p);
|
||||
poly_layer.end ();
|
||||
if (p.prop_id () != 0) {
|
||||
if (pw_wp == poly_layer_wp.end ()) {
|
||||
poly_layer_wp.insert (db::PolygonWithProperties (*p, p.prop_id ()));
|
||||
pw_wp = poly_layer_wp.end ();
|
||||
} else {
|
||||
poly_layer_wp.replace (pw_wp++, db::PolygonWithProperties (*p, p.prop_id ()));
|
||||
}
|
||||
} else {
|
||||
poly_layer.replace (pw++, *p);
|
||||
if (pw == poly_layer.end ()) {
|
||||
poly_layer.insert (*p);
|
||||
pw = poly_layer.end ();
|
||||
} else {
|
||||
poly_layer.replace (pw++, *p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
poly_layer.erase (pw, poly_layer.end ());
|
||||
poly_layer_wp.erase (pw_wp, poly_layer_wp.end ());
|
||||
|
||||
mp_merged_polygons->clear ();
|
||||
m_is_merged = filter.requires_raw_input () ? false : merged_semantics ();
|
||||
|
|
@ -221,15 +210,24 @@ RegionDelegate *FlatRegion::process_in_place (const PolygonProcessorBase &filter
|
|||
{
|
||||
db::layer<db::Polygon, db::unstable_layer_tag> &poly_layer = mp_polygons->get_layer<db::Polygon, db::unstable_layer_tag> ();
|
||||
db::layer<db::Polygon, db::unstable_layer_tag> out;
|
||||
db::layer<db::PolygonWithProperties, db::unstable_layer_tag> &poly_layer_wp = mp_polygons->get_layer<db::PolygonWithProperties, db::unstable_layer_tag> ();
|
||||
db::layer<db::PolygonWithProperties, db::unstable_layer_tag> out_wp;
|
||||
|
||||
std::vector<db::Polygon> poly_res;
|
||||
for (RegionIterator p (filter.requires_raw_input () ? begin () : begin_merged ()); ! p.at_end (); ++p) {
|
||||
poly_res.clear ();
|
||||
filter.process (*p, poly_res);
|
||||
out.insert (poly_res.begin (), poly_res.end ());
|
||||
if (p.prop_id () != 0) {
|
||||
for (auto r = poly_res.begin (); r != poly_res.end (); ++r) {
|
||||
out_wp.insert (db::PolygonWithProperties (*r, p.prop_id ()));
|
||||
}
|
||||
} else {
|
||||
out.insert (poly_res.begin (), poly_res.end ());
|
||||
}
|
||||
}
|
||||
|
||||
poly_layer.swap (out);
|
||||
poly_layer_wp.swap (out_wp);
|
||||
|
||||
mp_merged_polygons->clear ();
|
||||
m_is_merged = filter.result_is_merged () && merged_semantics ();
|
||||
|
|
@ -279,28 +277,7 @@ RegionDelegate *FlatRegion::merged_in_place (bool min_coherence, unsigned int mi
|
|||
} else {
|
||||
|
||||
invalidate_cache ();
|
||||
|
||||
db::EdgeProcessor ep (report_progress (), progress_desc ());
|
||||
ep.set_base_verbosity (base_verbosity ());
|
||||
|
||||
// count edges and reserve memory
|
||||
size_t n = 0;
|
||||
for (RegionIterator p (begin ()); ! p.at_end (); ++p) {
|
||||
n += p->vertices ();
|
||||
}
|
||||
ep.reserve (n);
|
||||
|
||||
// insert the polygons into the processor
|
||||
n = 0;
|
||||
for (RegionIterator p (begin ()); ! p.at_end (); ++p, ++n) {
|
||||
ep.insert (*p, n);
|
||||
}
|
||||
|
||||
// and run the merge step
|
||||
db::MergeOp op (min_wc);
|
||||
db::ShapeGenerator pc (*mp_polygons, true /*clear*/);
|
||||
db::PolygonGenerator pg (pc, false /*don't resolve holes*/, min_coherence);
|
||||
ep.process (pg, op);
|
||||
merge_polygons_to (*mp_polygons, min_coherence, min_wc);
|
||||
|
||||
m_is_merged = true;
|
||||
|
||||
|
|
@ -330,7 +307,7 @@ RegionDelegate *FlatRegion::add (const Region &other) const
|
|||
new_region->invalidate_cache ();
|
||||
new_region->set_is_merged (false);
|
||||
|
||||
FlatRegion *other_flat = dynamic_cast<FlatRegion *> (other.delegate ());
|
||||
const FlatRegion *other_flat = dynamic_cast<const FlatRegion *> (other.delegate ());
|
||||
if (other_flat) {
|
||||
|
||||
new_region->raw_polygons ().insert (other_flat->raw_polygons ().get_layer<db::Polygon, db::unstable_layer_tag> ().begin (), other_flat->raw_polygons ().get_layer<db::Polygon, db::unstable_layer_tag> ().end ());
|
||||
|
|
@ -360,7 +337,7 @@ RegionDelegate *FlatRegion::add_in_place (const Region &other)
|
|||
|
||||
db::Shapes &polygons = *mp_polygons;
|
||||
|
||||
FlatRegion *other_flat = dynamic_cast<FlatRegion *> (other.delegate ());
|
||||
const FlatRegion *other_flat = dynamic_cast<const FlatRegion *> (other.delegate ());
|
||||
if (other_flat) {
|
||||
|
||||
polygons.insert (other_flat->raw_polygons ().get_layer<db::Polygon, db::unstable_layer_tag> ().begin (), other_flat->raw_polygons ().get_layer<db::Polygon, db::unstable_layer_tag> ().end ());
|
||||
|
|
@ -385,7 +362,46 @@ RegionDelegate *FlatRegion::add_in_place (const Region &other)
|
|||
|
||||
const db::Polygon *FlatRegion::nth (size_t n) const
|
||||
{
|
||||
return n < mp_polygons->size () ? &mp_polygons->get_layer<db::Polygon, db::unstable_layer_tag> ().begin () [n] : 0;
|
||||
// NOTE: this assumes that we iterate over non-property polygons first and then over polygons with properties
|
||||
|
||||
if (n >= mp_polygons->size ()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const db::layer<db::Polygon, db::unstable_layer_tag> &l = mp_polygons->get_layer<db::Polygon, db::unstable_layer_tag> ();
|
||||
if (n < l.size ()) {
|
||||
return &l.begin () [n];
|
||||
}
|
||||
n -= l.size ();
|
||||
|
||||
const db::layer<db::PolygonWithProperties, db::unstable_layer_tag> &lp = mp_polygons->get_layer<db::PolygonWithProperties, db::unstable_layer_tag> ();
|
||||
if (n < lp.size ()) {
|
||||
return &lp.begin () [n];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
db::properties_id_type FlatRegion::nth_prop_id (size_t n) const
|
||||
{
|
||||
// NOTE: this assumes that we iterate over non-property polygons first and then over polygons with properties
|
||||
|
||||
if (n >= mp_polygons->size ()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const db::layer<db::Polygon, db::unstable_layer_tag> &l = mp_polygons->get_layer<db::Polygon, db::unstable_layer_tag> ();
|
||||
if (n < l.size ()) {
|
||||
return 0;
|
||||
}
|
||||
n -= l.size ();
|
||||
|
||||
const db::layer<db::PolygonWithProperties, db::unstable_layer_tag> &lp = mp_polygons->get_layer<db::PolygonWithProperties, db::unstable_layer_tag> ();
|
||||
if (n < lp.size ()) {
|
||||
return lp.begin () [n].properties_id ();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool FlatRegion::has_valid_polygons () const
|
||||
|
|
@ -403,19 +419,47 @@ const db::RecursiveShapeIterator *FlatRegion::iter () const
|
|||
return 0;
|
||||
}
|
||||
|
||||
void FlatRegion::apply_property_translator (const db::PropertiesTranslator &pt)
|
||||
{
|
||||
if ((mp_polygons->type_mask () & db::ShapeIterator::Properties) != 0) {
|
||||
|
||||
db::Shapes new_polygons (mp_polygons->is_editable ());
|
||||
new_polygons.assign (*mp_polygons, pt);
|
||||
mp_polygons->swap (new_polygons);
|
||||
|
||||
invalidate_cache ();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
db::PropertiesRepository *FlatRegion::properties_repository ()
|
||||
{
|
||||
return mp_properties_repository.get_non_const ();
|
||||
}
|
||||
|
||||
const db::PropertiesRepository *FlatRegion::properties_repository () const
|
||||
{
|
||||
return mp_properties_repository.get_const ();
|
||||
}
|
||||
|
||||
void FlatRegion::insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const
|
||||
{
|
||||
layout->cell (into_cell).shapes (into_layer).insert (*mp_polygons);
|
||||
db::PropertyMapper pm (&layout->properties_repository (), mp_properties_repository.get_const ());
|
||||
layout->cell (into_cell).shapes (into_layer).insert (*mp_polygons, pm);
|
||||
}
|
||||
|
||||
void
|
||||
FlatRegion::do_insert (const db::Polygon &polygon)
|
||||
FlatRegion::do_insert (const db::Polygon &polygon, properties_id_type prop_id)
|
||||
{
|
||||
if (polygon.holes () > 0 || polygon.vertices () > 0) {
|
||||
|
||||
bool is_box = (empty () && polygon.is_box ());
|
||||
|
||||
mp_polygons->insert (polygon);
|
||||
if (prop_id != 0) {
|
||||
mp_polygons->insert (db::PolygonWithProperties (polygon, prop_id));
|
||||
} else {
|
||||
mp_polygons->insert (polygon);
|
||||
}
|
||||
set_is_merged (is_box);
|
||||
|
||||
invalidate_cache ();
|
||||
|
|
|
|||
|
|
@ -48,6 +48,8 @@ public:
|
|||
typedef db::Polygon value_type;
|
||||
typedef db::layer<db::Polygon, db::unstable_layer_tag> polygon_layer_type;
|
||||
typedef polygon_layer_type::iterator polygon_iterator_type;
|
||||
typedef db::layer<db::PolygonWithProperties, db::unstable_layer_tag> polygon_layer_wp_type;
|
||||
typedef polygon_layer_wp_type::iterator polygon_iterator_wp_type;
|
||||
|
||||
FlatRegion ();
|
||||
FlatRegion (const db::Shapes &polygons, bool is_merged);
|
||||
|
|
@ -92,12 +94,16 @@ public:
|
|||
virtual RegionDelegate *add (const Region &other) const;
|
||||
|
||||
virtual const db::Polygon *nth (size_t n) const;
|
||||
virtual db::properties_id_type nth_prop_id (size_t) const;
|
||||
virtual bool has_valid_polygons () const;
|
||||
virtual bool has_valid_merged_polygons () const;
|
||||
|
||||
virtual const db::RecursiveShapeIterator *iter () const;
|
||||
virtual void apply_property_translator (const db::PropertiesTranslator &pt);
|
||||
virtual db::PropertiesRepository *properties_repository ();
|
||||
virtual const db::PropertiesRepository *properties_repository () const;
|
||||
|
||||
void do_insert (const db::Polygon &polygon);
|
||||
void do_insert (const db::Polygon &polygon, db::properties_id_type prop_id);
|
||||
|
||||
void do_transform (const db::Trans &t)
|
||||
{
|
||||
|
|
@ -141,6 +147,7 @@ private:
|
|||
mutable tl::copy_on_write_ptr<db::Shapes> mp_polygons;
|
||||
mutable tl::copy_on_write_ptr<db::Shapes> mp_merged_polygons;
|
||||
mutable bool m_merged_polygons_valid;
|
||||
mutable tl::copy_on_write_ptr<db::PropertiesRepository> mp_properties_repository;
|
||||
|
||||
void init ();
|
||||
void ensure_merged_polygons_valid () const;
|
||||
|
|
@ -153,6 +160,9 @@ private:
|
|||
for (polygon_iterator_type p = polygons.get_layer<db::Polygon, db::unstable_layer_tag> ().begin (); p != polygons.get_layer<db::Polygon, db::unstable_layer_tag> ().end (); ++p) {
|
||||
polygons.get_layer<db::Polygon, db::unstable_layer_tag> ().replace (p, p->transformed (trans));
|
||||
}
|
||||
for (polygon_iterator_wp_type p = polygons.get_layer<db::PolygonWithProperties, db::unstable_layer_tag> ().begin (); p != polygons.get_layer<db::PolygonWithProperties, db::unstable_layer_tag> ().end (); ++p) {
|
||||
polygons.get_layer<db::PolygonWithProperties, db::unstable_layer_tag> ().replace (p, p->transformed (trans));
|
||||
}
|
||||
invalidate_cache ();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ namespace db
|
|||
// FlatTexts implementation
|
||||
|
||||
FlatTexts::FlatTexts ()
|
||||
: MutableTexts (), mp_texts (new db::Shapes (false))
|
||||
: MutableTexts (), mp_texts (new db::Shapes (false)), mp_properties_repository (new db::PropertiesRepository ())
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
|
@ -43,13 +43,13 @@ FlatTexts::~FlatTexts ()
|
|||
}
|
||||
|
||||
FlatTexts::FlatTexts (const FlatTexts &other)
|
||||
: MutableTexts (other), mp_texts (other.mp_texts)
|
||||
: MutableTexts (other), mp_texts (other.mp_texts), mp_properties_repository (other.mp_properties_repository)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
FlatTexts::FlatTexts (const db::Shapes &texts)
|
||||
: MutableTexts (), mp_texts (new db::Shapes (texts))
|
||||
: MutableTexts (), mp_texts (new db::Shapes (texts)), mp_properties_repository (new db::PropertiesRepository ())
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
|
@ -121,7 +121,7 @@ TextsDelegate *FlatTexts::add (const Texts &other) const
|
|||
std::unique_ptr<FlatTexts> new_texts (new FlatTexts (*this));
|
||||
new_texts->invalidate_cache ();
|
||||
|
||||
FlatTexts *other_flat = dynamic_cast<FlatTexts *> (other.delegate ());
|
||||
const FlatTexts *other_flat = dynamic_cast<const FlatTexts *> (other.delegate ());
|
||||
if (other_flat) {
|
||||
|
||||
new_texts->raw_texts ().insert (other_flat->raw_texts ().get_layer<db::Text, db::unstable_layer_tag> ().begin (), other_flat->raw_texts ().get_layer<db::Text, db::unstable_layer_tag> ().end ());
|
||||
|
|
@ -150,7 +150,7 @@ TextsDelegate *FlatTexts::add_in_place (const Texts &other)
|
|||
|
||||
db::Shapes &texts = *mp_texts;
|
||||
|
||||
FlatTexts *other_flat = dynamic_cast<FlatTexts *> (other.delegate ());
|
||||
const FlatTexts *other_flat = dynamic_cast<const FlatTexts *> (other.delegate ());
|
||||
if (other_flat) {
|
||||
|
||||
texts.insert (other_flat->raw_texts ().get_layer<db::Text, db::unstable_layer_tag> ().begin (), other_flat->raw_texts ().get_layer<db::Text, db::unstable_layer_tag> ().end ());
|
||||
|
|
@ -188,6 +188,29 @@ const db::RecursiveShapeIterator *FlatTexts::iter () const
|
|||
return 0;
|
||||
}
|
||||
|
||||
void FlatTexts::apply_property_translator (const db::PropertiesTranslator &pt)
|
||||
{
|
||||
if ((mp_texts->type_mask () & db::ShapeIterator::Properties) != 0) {
|
||||
|
||||
db::Shapes new_texts (mp_texts->is_editable ());
|
||||
new_texts.assign (*mp_texts, pt);
|
||||
mp_texts->swap (new_texts);
|
||||
|
||||
invalidate_cache ();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
db::PropertiesRepository *FlatTexts::properties_repository ()
|
||||
{
|
||||
return mp_properties_repository.get_non_const ();
|
||||
}
|
||||
|
||||
const db::PropertiesRepository *FlatTexts::properties_repository () const
|
||||
{
|
||||
return mp_properties_repository.get_const ();
|
||||
}
|
||||
|
||||
void
|
||||
FlatTexts::insert_into_as_polygons (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer, db::Coord enl) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -79,6 +79,9 @@ public:
|
|||
virtual bool has_valid_texts () const;
|
||||
|
||||
virtual const db::RecursiveShapeIterator *iter () const;
|
||||
virtual void apply_property_translator (const db::PropertiesTranslator &pt);
|
||||
virtual db::PropertiesRepository *properties_repository ();
|
||||
virtual const db::PropertiesRepository *properties_repository () const;
|
||||
|
||||
virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const;
|
||||
virtual void insert_into_as_polygons (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer, db::Coord enl) const;
|
||||
|
|
@ -120,6 +123,7 @@ private:
|
|||
FlatTexts &operator= (const FlatTexts &other);
|
||||
|
||||
mutable tl::copy_on_write_ptr<db::Shapes> mp_texts;
|
||||
mutable tl::copy_on_write_ptr<db::PropertiesRepository> mp_properties_repository;
|
||||
|
||||
template <class Trans>
|
||||
void transform_generic (const Trans &trans)
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ public:
|
|||
virtual bool at_end () const = 0;
|
||||
virtual void increment () = 0;
|
||||
virtual const T *get () const = 0;
|
||||
virtual db::properties_id_type prop_id () const = 0;
|
||||
virtual generic_shape_iterator_delegate_base<T> *clone () const = 0;
|
||||
virtual bool equals (const generic_shape_iterator_delegate_base<T> *other) const = 0;
|
||||
};
|
||||
|
|
@ -86,6 +87,11 @@ public:
|
|||
return m_iter.operator-> ();
|
||||
}
|
||||
|
||||
virtual db::properties_id_type prop_id () const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
generic_shape_iterator_delegate_base<value_type> *clone () const
|
||||
{
|
||||
return new generic_shape_iterator_delegate2<Iter> (*this);
|
||||
|
|
@ -141,6 +147,11 @@ public:
|
|||
return m_iter.operator-> ();
|
||||
}
|
||||
|
||||
virtual db::properties_id_type prop_id () const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
generic_shape_iterator_delegate_base<value_type> *clone () const
|
||||
{
|
||||
return new generic_shape_iterator_delegate1<Iter> (*this);
|
||||
|
|
@ -170,7 +181,7 @@ public:
|
|||
const_cast<db::Shapes *> (mp_shapes)->update ();
|
||||
}
|
||||
m_iter = mp_shapes->begin (shape_flags<T> ());
|
||||
m_is_addressable = shape_flags<T> () == shape_flags_pure<T> () || mp_shapes->begin (shape_flags<T> () - shape_flags_pure<T> ()).at_end ();
|
||||
m_is_addressable = ! shape_flags_with_props<T> () && (shape_flags<T> () == shape_flags_pure<T> () || mp_shapes->begin (shape_flags<T> () - shape_flags_pure<T> ()).at_end ());
|
||||
set ();
|
||||
}
|
||||
|
||||
|
|
@ -217,6 +228,11 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
virtual db::properties_id_type prop_id () const
|
||||
{
|
||||
return m_iter->prop_id ();
|
||||
}
|
||||
|
||||
generic_shape_iterator_delegate_base<T> *clone () const
|
||||
{
|
||||
return new generic_shapes_iterator_delegate<T> (*this);
|
||||
|
|
@ -289,9 +305,23 @@ public:
|
|||
: mp_delegate (other.mp_delegate ? other.mp_delegate->clone () : 0)
|
||||
{ }
|
||||
|
||||
generic_shape_iterator (generic_shape_iterator &&other)
|
||||
: mp_delegate (0)
|
||||
{
|
||||
std::swap (mp_delegate, other.mp_delegate);
|
||||
}
|
||||
|
||||
~generic_shape_iterator ()
|
||||
{
|
||||
delete mp_delegate;
|
||||
mp_delegate = 0;
|
||||
}
|
||||
|
||||
generic_shape_iterator &set_delegate (generic_shape_iterator_delegate_base<T> *delegate)
|
||||
{
|
||||
delete mp_delegate;
|
||||
mp_delegate = delegate;
|
||||
return *this;
|
||||
}
|
||||
|
||||
generic_shape_iterator &operator= (const generic_shape_iterator &other)
|
||||
|
|
@ -319,6 +349,11 @@ public:
|
|||
return ! mp_delegate || mp_delegate->is_addressable ();
|
||||
}
|
||||
|
||||
db::properties_id_type prop_id () const
|
||||
{
|
||||
return mp_delegate ? mp_delegate->prop_id () : 0;
|
||||
}
|
||||
|
||||
reference operator* () const
|
||||
{
|
||||
return *mp_delegate->get ();
|
||||
|
|
@ -372,12 +407,108 @@ public:
|
|||
};
|
||||
|
||||
/**
|
||||
* @brief A helper class allowing delivery of addressable edges
|
||||
* @brief Wraps a generic shape iterator to provide a property-enabled one
|
||||
*/
|
||||
|
||||
template <class T>
|
||||
class DB_PUBLIC generic_shape_iterator_with_properties_delegate
|
||||
: public generic_shape_iterator_delegate_base<db::object_with_properties<T> >
|
||||
{
|
||||
public:
|
||||
generic_shape_iterator_with_properties_delegate (generic_shape_iterator<T> &&basic)
|
||||
: m_basic (basic)
|
||||
{
|
||||
set ();
|
||||
}
|
||||
|
||||
generic_shape_iterator_with_properties_delegate (generic_shape_iterator_delegate_base<T> *delegate)
|
||||
: m_basic (delegate)
|
||||
{
|
||||
set ();
|
||||
}
|
||||
|
||||
generic_shape_iterator_with_properties_delegate (const generic_shape_iterator<T> &basic)
|
||||
: m_basic (basic)
|
||||
{
|
||||
set ();
|
||||
}
|
||||
|
||||
generic_shape_iterator_with_properties_delegate *clone () const
|
||||
{
|
||||
return new generic_shape_iterator_with_properties_delegate (m_basic);
|
||||
}
|
||||
|
||||
virtual void do_reset (const db::Box ®ion, bool overlapping)
|
||||
{
|
||||
m_basic.reset (region, overlapping);
|
||||
}
|
||||
|
||||
virtual db::Box bbox () const
|
||||
{
|
||||
return m_basic.bbox ();
|
||||
}
|
||||
|
||||
virtual bool is_addressable () const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool at_end () const
|
||||
{
|
||||
return m_basic.at_end ();
|
||||
}
|
||||
|
||||
virtual void increment ()
|
||||
{
|
||||
++m_basic;
|
||||
set ();
|
||||
}
|
||||
|
||||
virtual const db::object_with_properties<T> *get () const
|
||||
{
|
||||
return &m_object;
|
||||
}
|
||||
|
||||
virtual db::properties_id_type prop_id () const
|
||||
{
|
||||
return m_object.properties_id ();
|
||||
}
|
||||
|
||||
virtual bool equals (const generic_shape_iterator_delegate_base<db::object_with_properties<T> > *other) const
|
||||
{
|
||||
const generic_shape_iterator_with_properties_delegate<T> *other_cast = dynamic_cast<const generic_shape_iterator_with_properties_delegate<T> *> (other);
|
||||
return other_cast && m_basic == other_cast->m_basic;
|
||||
}
|
||||
|
||||
private:
|
||||
db::generic_shape_iterator<T> m_basic;
|
||||
db::object_with_properties<T> m_object;
|
||||
|
||||
void set ()
|
||||
{
|
||||
m_object = db::object_with_properties<T> (*m_basic, m_basic.prop_id ());
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
generic_shape_iterator<db::object_with_properties<T> > make_wp_iter (generic_shape_iterator<T> &&basic)
|
||||
{
|
||||
return generic_shape_iterator<db::object_with_properties<T> > ().set_delegate (new generic_shape_iterator_with_properties_delegate<T> (basic));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
generic_shape_iterator<db::object_with_properties<T> > make_wp_iter (db::generic_shape_iterator_delegate_base<T> *delegate)
|
||||
{
|
||||
return generic_shape_iterator<db::object_with_properties<T> > ().set_delegate (new generic_shape_iterator_with_properties_delegate<T> (delegate));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief A helper class allowing delivery of addressable objects
|
||||
*
|
||||
* In some applications (i.e. box scanner), shapes need to be taken
|
||||
* by address. An iterator cannot always deliver addressable objects.
|
||||
* This class help providing this ability by keeping a temporary copy
|
||||
* if required.
|
||||
* The addressable_shape_delivery class help providing this ability by keeping temporary copies
|
||||
* if required on a heap.
|
||||
*/
|
||||
|
||||
template <class Iter>
|
||||
|
|
@ -422,32 +553,22 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
const value_type &operator* () const
|
||||
{
|
||||
return *operator-> ();
|
||||
}
|
||||
|
||||
db::properties_id_type prop_id () const
|
||||
{
|
||||
return m_iter.prop_id ();
|
||||
}
|
||||
|
||||
private:
|
||||
Iter m_iter;
|
||||
bool m_iterator_is_addressable;
|
||||
std::list<value_type> m_heap;
|
||||
};
|
||||
|
||||
template <class Iter>
|
||||
class DB_PUBLIC addressable_shape_delivery_gen
|
||||
: public addressable_shape_delivery_impl<Iter>
|
||||
{
|
||||
public:
|
||||
addressable_shape_delivery_gen ()
|
||||
: addressable_shape_delivery_impl<Iter> ()
|
||||
{ }
|
||||
|
||||
explicit addressable_shape_delivery_gen (const Iter &iter, bool iterator_is_addressable)
|
||||
: addressable_shape_delivery_impl<Iter> (iter, iterator_is_addressable)
|
||||
{ }
|
||||
|
||||
addressable_shape_delivery_gen &operator++ ()
|
||||
{
|
||||
addressable_shape_delivery_impl<Iter>::inc ();
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class DB_PUBLIC addressable_shape_delivery
|
||||
: public addressable_shape_delivery_impl<db::generic_shape_iterator<T> >
|
||||
|
|
@ -470,6 +591,29 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class DB_PUBLIC unaddressable_shape_delivery
|
||||
: public addressable_shape_delivery_impl<db::generic_shape_iterator<T> >
|
||||
{
|
||||
public:
|
||||
typedef db::generic_shape_iterator<T> iter_type;
|
||||
|
||||
unaddressable_shape_delivery ()
|
||||
: addressable_shape_delivery_impl<iter_type> ()
|
||||
{ }
|
||||
|
||||
explicit unaddressable_shape_delivery (const iter_type &iter)
|
||||
: addressable_shape_delivery_impl<iter_type> (iter, true)
|
||||
{ }
|
||||
|
||||
unaddressable_shape_delivery &operator++ ()
|
||||
{
|
||||
addressable_shape_delivery_impl<iter_type>::inc ();
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -872,8 +872,8 @@ struct cluster_building_receiver
|
|||
typedef std::set<size_t> global_nets;
|
||||
typedef std::pair<shape_vector, global_nets> cluster_value;
|
||||
|
||||
cluster_building_receiver (const db::Connectivity &conn, const tl::equivalence_clusters<size_t> *attr_equivalence)
|
||||
: mp_conn (&conn), mp_attr_equivalence (attr_equivalence)
|
||||
cluster_building_receiver (const db::Connectivity &conn, const tl::equivalence_clusters<size_t> *attr_equivalence, bool separate_attributes)
|
||||
: mp_conn (&conn), mp_attr_equivalence (attr_equivalence), m_separate_attributes (separate_attributes)
|
||||
{
|
||||
if (mp_attr_equivalence) {
|
||||
// cache the global nets per attribute equivalence cluster
|
||||
|
|
@ -930,6 +930,9 @@ struct cluster_building_receiver
|
|||
|
||||
void add (const T *s1, std::pair<unsigned int, size_t> p1, const T *s2, std::pair<unsigned int, size_t> p2)
|
||||
{
|
||||
if (m_separate_attributes && p1.second != p2.second) {
|
||||
return;
|
||||
}
|
||||
if (! mp_conn->interacts (*s1, p1.first, *s2, p2.first)) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -1021,6 +1024,7 @@ private:
|
|||
std::list<cluster_value> m_clusters;
|
||||
std::map<size_t, std::set<size_t> > m_global_nets_by_attribute_cluster;
|
||||
const tl::equivalence_clusters<size_t> *mp_attr_equivalence;
|
||||
bool m_separate_attributes;
|
||||
|
||||
void join (typename std::list<cluster_value>::iterator ic1, typename std::list<cluster_value>::iterator ic2)
|
||||
{
|
||||
|
|
@ -1038,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
|
||||
{
|
||||
|
|
@ -1126,7 +1100,7 @@ struct get_shape_flags<db::NetShape>
|
|||
|
||||
template <class T>
|
||||
void
|
||||
local_clusters<T>::build_clusters (const db::Cell &cell, const db::Connectivity &conn, const tl::equivalence_clusters<size_t> *attr_equivalence, bool report_progress)
|
||||
local_clusters<T>::build_clusters (const db::Cell &cell, const db::Connectivity &conn, const tl::equivalence_clusters<size_t> *attr_equivalence, bool report_progress, bool separate_attributes)
|
||||
{
|
||||
static std::string desc = tl::to_string (tr ("Building local clusters"));
|
||||
|
||||
|
|
@ -1143,7 +1117,7 @@ local_clusters<T>::build_clusters (const db::Cell &cell, const db::Connectivity
|
|||
}
|
||||
}
|
||||
|
||||
cluster_building_receiver<T, box_type> rec (conn, attr_equivalence);
|
||||
cluster_building_receiver<T, box_type> rec (conn, attr_equivalence, separate_attributes);
|
||||
bs.process (rec, 1 /*==touching*/, bc);
|
||||
rec.generate_clusters (*this);
|
||||
|
||||
|
|
@ -1391,11 +1365,11 @@ hier_clusters<T>::mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpos
|
|||
|
||||
template <class T>
|
||||
void
|
||||
hier_clusters<T>::build (const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn, const std::map<db::cell_index_type, tl::equivalence_clusters<size_t> > *attr_equivalence, const std::set<db::cell_index_type> *breakout_cells)
|
||||
hier_clusters<T>::build (const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn, const std::map<db::cell_index_type, tl::equivalence_clusters<size_t> > *attr_equivalence, const std::set<db::cell_index_type> *breakout_cells, bool separate_attributes)
|
||||
{
|
||||
clear ();
|
||||
cell_clusters_box_converter<T> cbc (layout, *this);
|
||||
do_build (cbc, layout, cell, conn, attr_equivalence, breakout_cells);
|
||||
do_build (cbc, layout, cell, conn, attr_equivalence, breakout_cells, separate_attributes);
|
||||
}
|
||||
|
||||
namespace
|
||||
|
|
@ -1437,9 +1411,18 @@ public:
|
|||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
hc_receiver (const db::Layout &layout, const db::Cell &cell, db::connected_clusters<T> &cell_clusters, hier_clusters<T> &tree, const cell_clusters_box_converter<T> &cbc, const db::Connectivity &conn, const std::set<db::cell_index_type> *breakout_cells, typename hier_clusters<T>::instance_interaction_cache_type *instance_interaction_cache)
|
||||
: mp_layout (&layout), mp_cell (&cell), mp_tree (&tree), mp_cbc (&cbc), mp_conn (&conn), mp_breakout_cells (breakout_cells), m_cluster_cache_misses (0), m_cluster_cache_hits (0), mp_instance_interaction_cache (instance_interaction_cache)
|
||||
hc_receiver (const db::Layout &layout, const db::Cell &cell, db::connected_clusters<T> &cell_clusters, hier_clusters<T> &tree, const cell_clusters_box_converter<T> &cbc, const db::Connectivity &conn, const std::set<db::cell_index_type> *breakout_cells, typename hier_clusters<T>::instance_interaction_cache_type *instance_interaction_cache, bool separate_attributes)
|
||||
{
|
||||
mp_layout = &layout;
|
||||
mp_cell = &cell;
|
||||
mp_tree = &tree;
|
||||
mp_cbc = &cbc;
|
||||
mp_conn = &conn;
|
||||
mp_breakout_cells = breakout_cells;
|
||||
m_cluster_cache_misses = 0;
|
||||
m_cluster_cache_hits = 0;
|
||||
mp_instance_interaction_cache = instance_interaction_cache;
|
||||
m_separate_attributes = separate_attributes;
|
||||
mp_cell_clusters = &cell_clusters;
|
||||
}
|
||||
|
||||
|
|
@ -1568,6 +1551,7 @@ private:
|
|||
instance_interaction_cache<interaction_key_for_clusters<box_type>, std::list<std::pair<size_t, size_t> > > m_interaction_cache_for_clusters;
|
||||
size_t m_cluster_cache_misses, m_cluster_cache_hits;
|
||||
typename hier_clusters<T>::instance_interaction_cache_type *mp_instance_interaction_cache;
|
||||
bool m_separate_attributes;
|
||||
|
||||
/**
|
||||
* @brief Investigate a pair of instances
|
||||
|
|
@ -1838,7 +1822,7 @@ private:
|
|||
box_type bc2 = (common2 & i->bbox ().transformed (t12));
|
||||
for (typename db::local_clusters<T>::touching_iterator j = cl2.begin_touching (bc2); ! j.at_end (); ++j) {
|
||||
|
||||
if (i->interacts (*j, t21, *mp_conn)) {
|
||||
if ((! m_separate_attributes || i->same_attrs (*j)) && i->interacts (*j, t21, *mp_conn)) {
|
||||
new_interactions.push_back (std::make_pair (i->id (), j->id ()));
|
||||
}
|
||||
|
||||
|
|
@ -2010,7 +1994,7 @@ private:
|
|||
|
||||
for (typename db::local_clusters<T>::touching_iterator j = cl2.begin_touching (c1.bbox ().transformed (t2.inverted ())); ! j.at_end (); ++j) {
|
||||
|
||||
if (c1.interacts (*j, t2, *mp_conn)) {
|
||||
if ((! m_separate_attributes || c1.same_attrs (*j)) && c1.interacts (*j, t2, *mp_conn)) {
|
||||
interactions.push_back (std::make_pair (c1.id (), j->id ()));
|
||||
}
|
||||
|
||||
|
|
@ -2249,7 +2233,7 @@ hier_clusters<T>::propagate_cluster_inst (const db::Layout &layout, const db::Ce
|
|||
|
||||
template <class T>
|
||||
void
|
||||
hier_clusters<T>::do_build (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn, const std::map<db::cell_index_type, tl::equivalence_clusters<size_t> > *attr_equivalence, const std::set<db::cell_index_type> *breakout_cells)
|
||||
hier_clusters<T>::do_build (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn, const std::map<db::cell_index_type, tl::equivalence_clusters<size_t> > *attr_equivalence, const std::set<db::cell_index_type> *breakout_cells, bool separate_attributes)
|
||||
{
|
||||
tl::SelfTimer timer (tl::verbosity () > m_base_verbosity, tl::to_string (tr ("Computing shape clusters")));
|
||||
|
||||
|
|
@ -2284,7 +2268,7 @@ hier_clusters<T>::do_build (cell_clusters_box_converter<T> &cbc, const db::Layou
|
|||
}
|
||||
}
|
||||
|
||||
build_local_cluster (layout, layout.cell (*c), conn, ec);
|
||||
build_local_cluster (layout, layout.cell (*c), conn, ec, separate_attributes);
|
||||
|
||||
++progress;
|
||||
|
||||
|
|
@ -2315,7 +2299,7 @@ hier_clusters<T>::do_build (cell_clusters_box_converter<T> &cbc, const db::Layou
|
|||
todo.push_back (*c);
|
||||
} else {
|
||||
tl_assert (! todo.empty ());
|
||||
build_hier_connections_for_cells (cbc, layout, todo, conn, breakout_cells, progress, instance_interaction_cache);
|
||||
build_hier_connections_for_cells (cbc, layout, todo, conn, breakout_cells, progress, instance_interaction_cache, separate_attributes);
|
||||
done.insert (todo.begin (), todo.end ());
|
||||
todo.clear ();
|
||||
todo.push_back (*c);
|
||||
|
|
@ -2325,7 +2309,7 @@ hier_clusters<T>::do_build (cell_clusters_box_converter<T> &cbc, const db::Layou
|
|||
|
||||
}
|
||||
|
||||
build_hier_connections_for_cells (cbc, layout, todo, conn, breakout_cells, progress, instance_interaction_cache);
|
||||
build_hier_connections_for_cells (cbc, layout, todo, conn, breakout_cells, progress, instance_interaction_cache, separate_attributes);
|
||||
}
|
||||
|
||||
if (tl::verbosity () >= m_base_verbosity + 20) {
|
||||
|
|
@ -2335,7 +2319,7 @@ hier_clusters<T>::do_build (cell_clusters_box_converter<T> &cbc, const db::Layou
|
|||
|
||||
template <class T>
|
||||
void
|
||||
hier_clusters<T>::build_local_cluster (const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn, const tl::equivalence_clusters<size_t> *attr_equivalence)
|
||||
hier_clusters<T>::build_local_cluster (const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn, const tl::equivalence_clusters<size_t> *attr_equivalence, bool separate_attributes)
|
||||
{
|
||||
std::string msg = tl::to_string (tr ("Computing local clusters for cell: ")) + std::string (layout.cell_name (cell.cell_index ()));
|
||||
if (tl::verbosity () >= m_base_verbosity + 20) {
|
||||
|
|
@ -2344,15 +2328,15 @@ hier_clusters<T>::build_local_cluster (const db::Layout &layout, const db::Cell
|
|||
tl::SelfTimer timer (tl::verbosity () > m_base_verbosity + 20, msg);
|
||||
|
||||
connected_clusters<T> &local = m_per_cell_clusters [cell.cell_index ()];
|
||||
local.build_clusters (cell, conn, attr_equivalence, true);
|
||||
local.build_clusters (cell, conn, attr_equivalence, true, separate_attributes);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void
|
||||
hier_clusters<T>::build_hier_connections_for_cells (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const std::vector<db::cell_index_type> &cells, const db::Connectivity &conn, const std::set<db::cell_index_type> *breakout_cells, tl::RelativeProgress &progress, instance_interaction_cache_type &instance_interaction_cache)
|
||||
hier_clusters<T>::build_hier_connections_for_cells (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const std::vector<db::cell_index_type> &cells, const db::Connectivity &conn, const std::set<db::cell_index_type> *breakout_cells, tl::RelativeProgress &progress, instance_interaction_cache_type &instance_interaction_cache, bool separate_attributes)
|
||||
{
|
||||
for (std::vector<db::cell_index_type>::const_iterator c = cells.begin (); c != cells.end (); ++c) {
|
||||
build_hier_connections (cbc, layout, layout.cell (*c), conn, breakout_cells, instance_interaction_cache);
|
||||
build_hier_connections (cbc, layout, layout.cell (*c), conn, breakout_cells, instance_interaction_cache, separate_attributes);
|
||||
++progress;
|
||||
}
|
||||
}
|
||||
|
|
@ -2436,7 +2420,7 @@ private:
|
|||
|
||||
template <class T>
|
||||
void
|
||||
hier_clusters<T>::build_hier_connections (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn, const std::set<db::cell_index_type> *breakout_cells, instance_interaction_cache_type &instance_interaction_cache)
|
||||
hier_clusters<T>::build_hier_connections (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn, const std::set<db::cell_index_type> *breakout_cells, instance_interaction_cache_type &instance_interaction_cache, bool separate_attributes)
|
||||
{
|
||||
std::string msg = tl::to_string (tr ("Computing hierarchical clusters for cell: ")) + std::string (layout.cell_name (cell.cell_index ()));
|
||||
if (tl::verbosity () >= m_base_verbosity + 20) {
|
||||
|
|
@ -2448,7 +2432,7 @@ hier_clusters<T>::build_hier_connections (cell_clusters_box_converter<T> &cbc, c
|
|||
|
||||
// NOTE: this is a receiver for both the child-to-child and
|
||||
// local to child interactions.
|
||||
std::unique_ptr<hc_receiver<T> > rec (new hc_receiver<T> (layout, cell, local, *this, cbc, conn, breakout_cells, &instance_interaction_cache));
|
||||
std::unique_ptr<hc_receiver<T> > rec (new hc_receiver<T> (layout, cell, local, *this, cbc, conn, breakout_cells, &instance_interaction_cache, separate_attributes));
|
||||
cell_inst_clusters_box_converter<T> cibc (cbc);
|
||||
|
||||
// The box scanner needs pointers so we have to first store the instances
|
||||
|
|
|
|||
|
|
@ -337,6 +337,14 @@ public:
|
|||
*/
|
||||
void add_attr (attr_id a);
|
||||
|
||||
/**
|
||||
* @brief Gets a value indicating whether the attributes of the clusters are identical
|
||||
*/
|
||||
bool same_attrs (const local_cluster<T> &other) const
|
||||
{
|
||||
return m_attrs == other.m_attrs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the attribute iterator (begin)
|
||||
*/
|
||||
|
|
@ -537,7 +545,7 @@ public:
|
|||
* cluster joining may happen in this case, because multi-attribute
|
||||
* assignment might create connections too.
|
||||
*/
|
||||
void build_clusters (const db::Cell &cell, const db::Connectivity &conn, const tl::equivalence_clusters<size_t> *attr_equivalence = 0, bool report_progress = false);
|
||||
void build_clusters (const db::Cell &cell, const db::Connectivity &conn, const tl::equivalence_clusters<size_t> *attr_equivalence = 0, bool report_progress = false, bool separate_attributes = false);
|
||||
|
||||
/**
|
||||
* @brief Creates and inserts a new clusters
|
||||
|
|
@ -1212,7 +1220,7 @@ public:
|
|||
/**
|
||||
* @brief Builds a hierarchy of clusters from a cell hierarchy and given connectivity
|
||||
*/
|
||||
void build (const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn, const std::map<db::cell_index_type, tl::equivalence_clusters<size_t> > *attr_equivalence = 0, const std::set<cell_index_type> *breakout_cells = 0);
|
||||
void build (const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn, const std::map<db::cell_index_type, tl::equivalence_clusters<size_t> > *attr_equivalence = 0, const std::set<cell_index_type> *breakout_cells = 0, bool separate_attributes = false);
|
||||
|
||||
/**
|
||||
* @brief Gets the connected clusters for a given cell
|
||||
|
|
@ -1255,10 +1263,10 @@ public:
|
|||
void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, bool no_self, void *parent) const;
|
||||
|
||||
private:
|
||||
void build_local_cluster (const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn, const tl::equivalence_clusters<size_t> *attr_equivalence);
|
||||
void build_hier_connections (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn, const std::set<cell_index_type> *breakout_cells, instance_interaction_cache_type &instance_interaction_cache);
|
||||
void build_hier_connections_for_cells (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const std::vector<db::cell_index_type> &cells, const db::Connectivity &conn, const std::set<cell_index_type> *breakout_cells, tl::RelativeProgress &progress, instance_interaction_cache_type &instance_interaction_cache);
|
||||
void do_build (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn, const std::map<cell_index_type, tl::equivalence_clusters<size_t> > *attr_equivalence, const std::set<cell_index_type> *breakout_cells);
|
||||
void build_local_cluster (const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn, const tl::equivalence_clusters<size_t> *attr_equivalence, bool separate_attributes);
|
||||
void build_hier_connections (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn, const std::set<cell_index_type> *breakout_cells, instance_interaction_cache_type &instance_interaction_cache, bool separate_attributes);
|
||||
void build_hier_connections_for_cells (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const std::vector<db::cell_index_type> &cells, const db::Connectivity &conn, const std::set<cell_index_type> *breakout_cells, tl::RelativeProgress &progress, instance_interaction_cache_type &instance_interaction_cache, bool separate_attributes);
|
||||
void do_build (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn, const std::map<cell_index_type, tl::equivalence_clusters<size_t> > *attr_equivalence, const std::set<cell_index_type> *breakout_cells, bool separate_attributes);
|
||||
|
||||
std::map<db::cell_index_type, connected_clusters<T> > m_per_cell_clusters;
|
||||
int m_base_verbosity;
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include "dbRecursiveShapeIterator.h"
|
||||
#include "dbBoxConvert.h"
|
||||
#include "dbEdgeProcessor.h"
|
||||
#include "dbEdgeBoolean.h"
|
||||
#include "dbPolygonGenerators.h"
|
||||
#include "dbLocalOperationUtils.h"
|
||||
#include "dbShapeFlags.h"
|
||||
|
|
@ -182,6 +183,31 @@ public:
|
|||
shape_reference_translator (db::Layout * /*target_layout*/) { }
|
||||
};
|
||||
|
||||
template<class Basic>
|
||||
class shape_reference_translator<db::object_with_properties<Basic> >
|
||||
: public shape_reference_translator<Basic>
|
||||
{
|
||||
public:
|
||||
typedef db::object_with_properties<Basic> shape_type;
|
||||
|
||||
shape_reference_translator (db::Layout *target_layout)
|
||||
: shape_reference_translator<Basic> (target_layout)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
shape_type operator() (const shape_type &s) const
|
||||
{
|
||||
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
|
||||
{
|
||||
return shape_type (shape_reference_translator<Basic>::operator () (s, tr), s.properties_id ());
|
||||
}
|
||||
};
|
||||
|
||||
template <class Ref, class Trans>
|
||||
class shape_reference_translator_with_trans_from_shape_ref
|
||||
{
|
||||
|
|
@ -273,6 +299,26 @@ private:
|
|||
Trans m_trans;
|
||||
};
|
||||
|
||||
template <class Basic, class Trans>
|
||||
class shape_reference_translator_with_trans<db::object_with_properties<Basic>, Trans>
|
||||
: public shape_reference_translator_with_trans<Basic, Trans>
|
||||
{
|
||||
public:
|
||||
typedef db::object_with_properties<Basic> shape_type;
|
||||
|
||||
shape_reference_translator_with_trans (db::Layout *target_layout)
|
||||
: shape_reference_translator_with_trans<Basic, Trans> (target_layout)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
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_with_trans<Basic, Trans>::operator () (s), s.properties_id ());
|
||||
}
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
|
|
@ -309,6 +355,8 @@ db::Box safe_box_enlarged (const db::Box &box, db::Coord dx, db::Coord dy)
|
|||
{
|
||||
if (box.empty ()) {
|
||||
return box;
|
||||
} else if (box == db::Box::world ()) {
|
||||
return box;
|
||||
} else {
|
||||
db::Coord w2 = db::Coord (box.width () / 2);
|
||||
db::Coord h2 = db::Coord (box.height () / 2);
|
||||
|
|
@ -392,20 +440,6 @@ local_processor_cell_context<TS, TI, TR>::propagate (unsigned int output_layer,
|
|||
}
|
||||
}
|
||||
|
||||
// explicit instantiations
|
||||
template class DB_PUBLIC local_processor_cell_context<db::Polygon, db::Polygon, db::Polygon>;
|
||||
template class DB_PUBLIC local_processor_cell_context<db::Polygon, db::Text, db::Polygon>;
|
||||
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::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>;
|
||||
template class DB_PUBLIC local_processor_cell_context<db::Polygon, db::Polygon, db::EdgePair>;
|
||||
template class DB_PUBLIC local_processor_cell_context<db::Edge, db::Edge, db::Edge>;
|
||||
template class DB_PUBLIC local_processor_cell_context<db::Edge, db::Polygon, db::Edge>;
|
||||
template class DB_PUBLIC local_processor_cell_context<db::Edge, db::Edge, db::EdgePair>;
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
// LocalProcessorCellContexts implementation
|
||||
|
||||
|
|
@ -493,6 +527,62 @@ subtract (std::unordered_set<db::PolygonRef> &res, const std::unordered_set<db::
|
|||
ep.process (pg, op);
|
||||
}
|
||||
|
||||
template <class TS, class TI>
|
||||
static void
|
||||
subtract (std::unordered_set<db::PolygonRefWithProperties> &res, const std::unordered_set<db::PolygonRefWithProperties> &other, db::Layout *layout, const db::local_processor<TS, TI, db::PolygonRefWithProperties> *proc)
|
||||
{
|
||||
if (other.empty ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (! proc->boolean_core ()) {
|
||||
subtract_set (res, other);
|
||||
return;
|
||||
}
|
||||
|
||||
size_t max_vertex_count = proc->max_vertex_count ();
|
||||
double area_ratio = proc->area_ratio ();
|
||||
|
||||
std::unordered_set<db::PolygonRefWithProperties> first;
|
||||
first.swap (res);
|
||||
|
||||
std::map<db::properties_id_type, std::pair<std::vector<const db::PolygonRefWithProperties *>, std::vector<const db::PolygonRefWithProperties *> > > by_prop_id;
|
||||
for (auto i = first.begin (); i != first.end (); ++i) {
|
||||
by_prop_id [i->properties_id ()].first.push_back (i.operator-> ());
|
||||
}
|
||||
for (auto i = other.begin (); i != other.end (); ++i) {
|
||||
by_prop_id [i->properties_id ()].second.push_back (i.operator-> ());
|
||||
}
|
||||
|
||||
db::EdgeProcessor ep;
|
||||
ep.set_base_verbosity (proc->base_verbosity () + 30);
|
||||
|
||||
for (auto s2p = by_prop_id.begin (); s2p != by_prop_id.end (); ++s2p) {
|
||||
|
||||
db::properties_id_type prop_id = s2p->first;
|
||||
size_t p1 = 0, p2 = 1;
|
||||
|
||||
ep.clear ();
|
||||
|
||||
for (auto i = s2p->second.first.begin (); i != s2p->second.first.end (); ++i) {
|
||||
ep.insert (**i, p1);
|
||||
p1 += 2;
|
||||
}
|
||||
|
||||
for (auto i = s2p->second.second.begin (); i != s2p->second.second.end (); ++i) {
|
||||
ep.insert (**i, p2);
|
||||
p2 += 2;
|
||||
}
|
||||
|
||||
db::BooleanOp op (db::BooleanOp::ANotB);
|
||||
db::polygon_ref_generator_with_properties<db::PolygonRefWithProperties> pr (layout, res, prop_id);
|
||||
db::PolygonSplitter splitter (pr, area_ratio, max_vertex_count);
|
||||
db::PolygonGenerator pg (splitter, true, true);
|
||||
ep.process (pg, op);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
template <class TS, class TI>
|
||||
static void
|
||||
subtract (std::unordered_set<db::Edge> &res, const std::unordered_set<db::Edge> &other, db::Layout * /*layout*/, const db::local_processor<TS, TI, db::Edge> *proc)
|
||||
|
|
@ -523,6 +613,59 @@ subtract (std::unordered_set<db::Edge> &res, const std::unordered_set<db::Edge>
|
|||
res.swap (result);
|
||||
}
|
||||
|
||||
template <class TS, class TI>
|
||||
static void
|
||||
subtract (std::unordered_set<db::EdgeWithProperties> &res, const std::unordered_set<db::EdgeWithProperties> &other, db::Layout * /*layout*/, const db::local_processor<TS, TI, db::EdgeWithProperties> *proc)
|
||||
{
|
||||
if (other.empty ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (! proc->boolean_core ()) {
|
||||
subtract_set (res, other);
|
||||
return;
|
||||
}
|
||||
|
||||
std::unordered_set<db::EdgeWithProperties> first;
|
||||
first.swap (res);
|
||||
|
||||
std::map<db::properties_id_type, std::pair<std::vector<const db::EdgeWithProperties *>, std::vector<const db::EdgeWithProperties *> > > by_prop_id;
|
||||
for (auto i = first.begin (); i != first.end (); ++i) {
|
||||
by_prop_id [i->properties_id ()].first.push_back (i.operator-> ());
|
||||
}
|
||||
for (auto i = other.begin (); i != other.end (); ++i) {
|
||||
by_prop_id [i->properties_id ()].second.push_back (i.operator-> ());
|
||||
}
|
||||
|
||||
for (auto s2p = by_prop_id.begin (); s2p != by_prop_id.end (); ++s2p) {
|
||||
|
||||
if (s2p->second.second.empty ()) {
|
||||
|
||||
for (auto i = s2p->second.first.begin (); i != s2p->second.first.end (); ++i) {
|
||||
res.insert (**i);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
db::box_scanner<db::Edge, size_t> scanner;
|
||||
scanner.reserve (s2p->second.first.size () + s2p->second.second.size ());
|
||||
|
||||
for (auto i = s2p->second.first.begin (); i != s2p->second.first.end (); ++i) {
|
||||
scanner.insert (*i, 0);
|
||||
}
|
||||
for (auto i = s2p->second.second.begin (); i != s2p->second.second.end (); ++i) {
|
||||
scanner.insert (*i, 1);
|
||||
}
|
||||
|
||||
db::property_injector<db::Edge, std::unordered_set<db::EdgeWithProperties> > prop_inject (&res, s2p->first);
|
||||
EdgeBooleanClusterCollector<db::property_injector<db::Edge, std::unordered_set<db::EdgeWithProperties> > > cluster_collector (&prop_inject, EdgeNot);
|
||||
scanner.process (cluster_collector, 1, db::box_convert<db::Edge> ());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
template <class TS, class TI, class TR>
|
||||
static void
|
||||
subtract (std::unordered_set<TR> &res, const std::unordered_set<TR> &other, db::Layout * /*layout*/, const db::local_processor<TS, TI, TR> * /*proc*/)
|
||||
|
|
@ -705,20 +848,6 @@ local_processor_cell_contexts<TS, TI, TR>::compute_results (const local_processo
|
|||
}
|
||||
}
|
||||
|
||||
// explicit instantiations
|
||||
template class DB_PUBLIC local_processor_cell_contexts<db::Polygon, db::Polygon, db::Polygon>;
|
||||
template class DB_PUBLIC local_processor_cell_contexts<db::Polygon, db::Edge, db::Polygon>;
|
||||
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::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>;
|
||||
template class DB_PUBLIC local_processor_cell_contexts<db::Polygon, db::Polygon, db::EdgePair>;
|
||||
template class DB_PUBLIC local_processor_cell_contexts<db::Edge, db::PolygonRef, db::Edge>;
|
||||
template class DB_PUBLIC local_processor_cell_contexts<db::Edge, db::Edge, db::Edge>;
|
||||
template class DB_PUBLIC local_processor_cell_contexts<db::Edge, db::Edge, db::EdgePair>;
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
|
||||
template <class TS, class TI>
|
||||
|
|
@ -810,20 +939,6 @@ shape_interactions<TS, TI>::intruder_shape (unsigned int id) const
|
|||
}
|
||||
}
|
||||
|
||||
// explicit instantiations
|
||||
template class DB_PUBLIC shape_interactions<db::Polygon, db::Polygon>;
|
||||
template class DB_PUBLIC shape_interactions<db::Polygon, db::Text>;
|
||||
template class DB_PUBLIC shape_interactions<db::Polygon, db::TextRef>;
|
||||
template class DB_PUBLIC shape_interactions<db::Polygon, db::Edge>;
|
||||
template class DB_PUBLIC shape_interactions<db::PolygonRef, db::PolygonRef>;
|
||||
template class DB_PUBLIC shape_interactions<db::PolygonRef, db::TextRef>;
|
||||
template class DB_PUBLIC shape_interactions<db::PolygonRef, db::Text>;
|
||||
template class DB_PUBLIC shape_interactions<db::PolygonRef, db::Edge>;
|
||||
template class DB_PUBLIC shape_interactions<db::Edge, db::Edge>;
|
||||
template class DB_PUBLIC shape_interactions<db::Edge, db::PolygonRef>;
|
||||
template class DB_PUBLIC shape_interactions<db::TextRef, db::TextRef>;
|
||||
template class DB_PUBLIC shape_interactions<db::TextRef, db::PolygonRef>;
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
// Helper classes for the LocalProcessor
|
||||
|
||||
|
|
@ -1014,6 +1129,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)
|
||||
|
|
@ -1024,7 +1140,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.
|
||||
|
|
@ -1279,28 +1395,6 @@ local_processor_context_computation_task<TS, TI, TR>::perform ()
|
|||
mp_proc->compute_contexts (*mp_contexts, mp_parent_context, mp_subject_parent, mp_subject_cell, m_subject_cell_inst, mp_intruder_cell, m_intruders, m_dist);
|
||||
}
|
||||
|
||||
// explicit instantiations
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::Polygon, db::Polygon, db::Polygon>;
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::Polygon, db::Text, db::Polygon>;
|
||||
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::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>;
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::TextRef, db::PolygonRef, db::PolygonRef>;
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::TextRef, db::PolygonRef, db::TextRef>;
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRef, db::Edge, db::PolygonRef>;
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRef, db::Edge, db::Edge>;
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRef, db::PolygonRef, db::Edge>;
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRef, db::PolygonRef, db::EdgePair>;
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::Polygon, db::Polygon, db::EdgePair>;
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::Polygon, db::Polygon, db::Edge>;
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::Edge, db::Edge, db::Edge>;
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::Edge, db::PolygonRef, db::Edge>;
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::Edge, db::Edge, db::EdgePair>;
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::Edge, db::PolygonRef, db::PolygonRef>;
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
// LocalProcessorResultComputationTask implementation
|
||||
|
||||
|
|
@ -1341,20 +1435,6 @@ local_processor_result_computation_task<TS, TI, TR>::perform ()
|
|||
}
|
||||
}
|
||||
|
||||
// explicit instantiations
|
||||
template class DB_PUBLIC local_processor_result_computation_task<db::Polygon, db::Polygon, db::Polygon>;
|
||||
template class DB_PUBLIC local_processor_result_computation_task<db::Polygon, db::Text, db::Polygon>;
|
||||
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::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>;
|
||||
template class DB_PUBLIC local_processor_result_computation_task<db::Polygon, db::Polygon, db::EdgePair>;
|
||||
template class DB_PUBLIC local_processor_result_computation_task<db::Edge, db::Edge, db::Edge>;
|
||||
template class DB_PUBLIC local_processor_result_computation_task<db::Edge, db::PolygonRef, db::Edge>;
|
||||
template class DB_PUBLIC local_processor_result_computation_task<db::Edge, db::Edge, db::EdgePair>;
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
// LocalProcessor implementation
|
||||
|
||||
|
|
@ -1660,6 +1740,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) {
|
||||
|
|
@ -1676,7 +1757,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1828,11 +1909,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++);
|
||||
}
|
||||
|
||||
|
|
@ -1852,12 +1934,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?
|
||||
|
|
@ -1876,12 +1958,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?
|
||||
|
|
@ -1900,7 +1983,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);
|
||||
}
|
||||
|
||||
|
|
@ -1908,7 +1991,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 ());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1924,6 +2007,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;
|
||||
|
||||
|
|
@ -1938,8 +2022,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));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1983,11 +2066,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;
|
||||
|
|
@ -2167,21 +2251,16 @@ local_processor<TS, TI, TR>::run_flat (const generic_shape_iterator<TS> &subject
|
|||
|
||||
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 subjects_box = safe_box_enlarged (subjects.bbox (), dist, dist);
|
||||
|
||||
db::Box intruders_box;
|
||||
for (typename std::vector<generic_shape_iterator<TI> >::const_iterator il = intruders.begin (); il != intruders.end (); ++il) {
|
||||
intruders_box += il->bbox ();
|
||||
}
|
||||
if (intruders_box != db::Box::world ()) {
|
||||
intruders_box.enlarge (db::Vector (dist, dist));
|
||||
}
|
||||
intruders_box = safe_box_enlarged (intruders_box, dist, dist);
|
||||
|
||||
db::Box common_box = intruders_box & subjects_box;
|
||||
if (common_box.empty ()) {
|
||||
if (common_box.empty () || common_box.width () == 0 || common_box.height () == 0) {
|
||||
|
||||
if (needs_isolated_subjects) {
|
||||
for (generic_shape_iterator<TS> is = subjects; ! is.at_end (); ++is) {
|
||||
|
|
@ -2192,13 +2271,14 @@ local_processor<TS, TI, TR>::run_flat (const generic_shape_iterator<TS> &subject
|
|||
|
||||
} else {
|
||||
|
||||
common_box = safe_box_enlarged (common_box, -1, -1);
|
||||
|
||||
if (needs_isolated_subjects) {
|
||||
|
||||
addressable_shape_delivery<TS> is (subjects);
|
||||
unaddressable_shape_delivery<TS> is (subjects);
|
||||
for ( ; !is.at_end (); ++is) {
|
||||
const TS *shape = is.operator-> ();
|
||||
unsigned int id = interactions.next_id ();
|
||||
interactions.add_subject (id, *shape);
|
||||
interactions.add_subject (id, *is);
|
||||
}
|
||||
|
||||
unsigned int il_index = 0;
|
||||
|
|
@ -2240,7 +2320,7 @@ local_processor<TS, TI, TR>::run_flat (const generic_shape_iterator<TS> &subject
|
|||
|
||||
} else {
|
||||
|
||||
addressable_shape_delivery<TI> ii ((*il).confined (common_box, true));
|
||||
addressable_shape_delivery<TI> ii ((*il).confined (common_box, false));
|
||||
for (; !ii.at_end (); ++ii) {
|
||||
scanner.insert2 (ii.operator-> (), interactions.next_id ());
|
||||
}
|
||||
|
|
@ -2276,7 +2356,7 @@ local_processor<TS, TI, TR>::run_flat (const generic_shape_iterator<TS> &subject
|
|||
|
||||
interaction_registration_shape1_scanner_combo<TS, TI> scanner (&interactions, il_index, m_report_progress, scan_description);
|
||||
|
||||
addressable_shape_delivery<TS> is (subjects.confined (common_box, true));
|
||||
addressable_shape_delivery<TS> is (subjects.confined (common_box, false));
|
||||
unsigned int id = id_first;
|
||||
|
||||
for ( ; ! is.at_end (); ++is, ++id) {
|
||||
|
|
@ -2295,7 +2375,7 @@ local_processor<TS, TI, TR>::run_flat (const generic_shape_iterator<TS> &subject
|
|||
// this is the case of intra-layer interactions ("foreign"): we pretend we have two layers and
|
||||
// reject shape self-interactions by registering them as "same"
|
||||
|
||||
addressable_shape_delivery<TS> is (subjects.confined (common_box, true));
|
||||
addressable_shape_delivery<TS> is (subjects.confined (common_box, false));
|
||||
|
||||
unsigned int id = id_first;
|
||||
for ( ; ! is.at_end (); ++is, ++id) {
|
||||
|
|
@ -2309,8 +2389,8 @@ local_processor<TS, TI, TR>::run_flat (const generic_shape_iterator<TS> &subject
|
|||
|
||||
} else {
|
||||
|
||||
addressable_shape_delivery<TS> is (subjects.confined (common_box, true));
|
||||
addressable_shape_delivery<TI> ii ((*il).confined (common_box, true));
|
||||
addressable_shape_delivery<TS> is (subjects.confined (common_box, false));
|
||||
addressable_shape_delivery<TI> ii ((*il).confined (common_box, false));
|
||||
|
||||
unsigned int id = id_first;
|
||||
for ( ; ! is.at_end (); ++is, ++id) {
|
||||
|
|
@ -2356,12 +2436,136 @@ local_processor<TS, TI, TR>::run_flat (const generic_shape_iterator<TS> &subject
|
|||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
|
||||
// NOTE: don't forget to update the explicit instantiations in dbLocalOperation.cc
|
||||
|
||||
// explicit instantiations
|
||||
template class DB_PUBLIC local_processor_cell_context<db::Polygon, db::Polygon, db::Polygon>;
|
||||
template class DB_PUBLIC local_processor_cell_context<db::Polygon, db::Text, db::Polygon>;
|
||||
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::PolygonRefWithProperties>;
|
||||
template class DB_PUBLIC local_processor_cell_context<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::EdgeWithProperties>;
|
||||
template class DB_PUBLIC local_processor_cell_context<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::EdgePairWithProperties>;
|
||||
template class DB_PUBLIC local_processor_cell_context<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::EdgePair>;
|
||||
template class DB_PUBLIC local_processor_cell_context<db::PolygonWithProperties, db::PolygonWithProperties, db::PolygonWithProperties>;
|
||||
template class DB_PUBLIC local_processor_cell_context<db::PolygonWithProperties, db::PolygonWithProperties, db::EdgeWithProperties>;
|
||||
template class DB_PUBLIC local_processor_cell_context<db::PolygonWithProperties, db::PolygonWithProperties, db::EdgePairWithProperties>;
|
||||
template class DB_PUBLIC local_processor_cell_context<db::PolygonWithProperties, db::PolygonWithProperties, db::EdgePair>;
|
||||
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>;
|
||||
template class DB_PUBLIC local_processor_cell_context<db::Polygon, db::Polygon, db::EdgePair>;
|
||||
template class DB_PUBLIC local_processor_cell_context<db::Edge, db::Edge, db::Edge>;
|
||||
template class DB_PUBLIC local_processor_cell_context<db::Edge, db::Polygon, db::Edge>;
|
||||
template class DB_PUBLIC local_processor_cell_context<db::Edge, db::Edge, db::EdgePair>;
|
||||
|
||||
// explicit instantiations
|
||||
template class DB_PUBLIC local_processor_cell_contexts<db::Polygon, db::Polygon, db::Polygon>;
|
||||
template class DB_PUBLIC local_processor_cell_contexts<db::Polygon, db::Edge, db::Polygon>;
|
||||
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::PolygonRefWithProperties>;
|
||||
template class DB_PUBLIC local_processor_cell_contexts<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::EdgeWithProperties>;
|
||||
template class DB_PUBLIC local_processor_cell_contexts<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::EdgePairWithProperties>;
|
||||
template class DB_PUBLIC local_processor_cell_contexts<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::EdgePair>;
|
||||
template class DB_PUBLIC local_processor_cell_contexts<db::PolygonWithProperties, db::PolygonWithProperties, db::PolygonWithProperties>;
|
||||
template class DB_PUBLIC local_processor_cell_contexts<db::PolygonWithProperties, db::PolygonWithProperties, db::EdgeWithProperties>;
|
||||
template class DB_PUBLIC local_processor_cell_contexts<db::PolygonWithProperties, db::PolygonWithProperties, db::EdgePairWithProperties>;
|
||||
template class DB_PUBLIC local_processor_cell_contexts<db::PolygonWithProperties, db::PolygonWithProperties, db::EdgePair>;
|
||||
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>;
|
||||
template class DB_PUBLIC local_processor_cell_contexts<db::Polygon, db::Polygon, db::EdgePair>;
|
||||
template class DB_PUBLIC local_processor_cell_contexts<db::Edge, db::PolygonRef, db::Edge>;
|
||||
template class DB_PUBLIC local_processor_cell_contexts<db::Edge, db::Edge, db::Edge>;
|
||||
template class DB_PUBLIC local_processor_cell_contexts<db::Edge, db::Edge, db::EdgePair>;
|
||||
|
||||
// explicit instantiations
|
||||
template class DB_PUBLIC shape_interactions<db::Polygon, db::Polygon>;
|
||||
template class DB_PUBLIC shape_interactions<db::Polygon, db::Text>;
|
||||
template class DB_PUBLIC shape_interactions<db::Polygon, db::TextRef>;
|
||||
template class DB_PUBLIC shape_interactions<db::Polygon, db::Edge>;
|
||||
template class DB_PUBLIC shape_interactions<db::PolygonRefWithProperties, db::PolygonRefWithProperties>;
|
||||
template class DB_PUBLIC shape_interactions<db::PolygonWithProperties, db::PolygonWithProperties>;
|
||||
template class DB_PUBLIC shape_interactions<db::PolygonRef, db::PolygonRef>;
|
||||
template class DB_PUBLIC shape_interactions<db::PolygonRef, db::TextRef>;
|
||||
template class DB_PUBLIC shape_interactions<db::PolygonRef, db::Text>;
|
||||
template class DB_PUBLIC shape_interactions<db::PolygonRef, db::Edge>;
|
||||
template class DB_PUBLIC shape_interactions<db::Edge, db::Edge>;
|
||||
template class DB_PUBLIC shape_interactions<db::Edge, db::PolygonRef>;
|
||||
template class DB_PUBLIC shape_interactions<db::TextRef, db::TextRef>;
|
||||
template class DB_PUBLIC shape_interactions<db::TextRef, db::PolygonRef>;
|
||||
|
||||
// explicit instantiations
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::Polygon, db::Polygon, db::Polygon>;
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::Polygon, db::Text, db::Polygon>;
|
||||
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::PolygonRefWithProperties>;
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::EdgeWithProperties>;
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::EdgePairWithProperties>;
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::EdgePair>;
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonWithProperties, db::PolygonWithProperties, db::PolygonWithProperties>;
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonWithProperties, db::PolygonWithProperties, db::EdgeWithProperties>;
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonWithProperties, db::PolygonWithProperties, db::EdgePairWithProperties>;
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonWithProperties, db::PolygonWithProperties, db::EdgePair>;
|
||||
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>;
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::TextRef, db::PolygonRef, db::PolygonRef>;
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::TextRef, db::PolygonRef, db::TextRef>;
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRef, db::Edge, db::PolygonRef>;
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRef, db::Edge, db::Edge>;
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRef, db::PolygonRef, db::Edge>;
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::PolygonRef, db::PolygonRef, db::EdgePair>;
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::Polygon, db::Polygon, db::EdgePair>;
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::Polygon, db::Polygon, db::Edge>;
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::Edge, db::Edge, db::Edge>;
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::Edge, db::PolygonRef, db::Edge>;
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::Edge, db::Edge, db::EdgePair>;
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::Edge, db::PolygonRef, db::PolygonRef>;
|
||||
|
||||
// explicit instantiations
|
||||
template class DB_PUBLIC local_processor_result_computation_task<db::Polygon, db::Polygon, db::Polygon>;
|
||||
template class DB_PUBLIC local_processor_result_computation_task<db::Polygon, db::Text, db::Polygon>;
|
||||
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::EdgeWithProperties>;
|
||||
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::PolygonRefWithProperties, db::PolygonRefWithProperties, db::EdgePairWithProperties>;
|
||||
template class DB_PUBLIC local_processor_result_computation_task<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::EdgePair>;
|
||||
template class DB_PUBLIC local_processor_result_computation_task<db::PolygonWithProperties, db::PolygonWithProperties, db::PolygonWithProperties>;
|
||||
template class DB_PUBLIC local_processor_result_computation_task<db::PolygonWithProperties, db::PolygonWithProperties, db::EdgeWithProperties>;
|
||||
template class DB_PUBLIC local_processor_result_computation_task<db::PolygonWithProperties, db::PolygonWithProperties, db::EdgePairWithProperties>;
|
||||
template class DB_PUBLIC local_processor_result_computation_task<db::PolygonWithProperties, db::PolygonWithProperties, db::EdgePair>;
|
||||
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>;
|
||||
template class DB_PUBLIC local_processor_result_computation_task<db::Polygon, db::Polygon, db::EdgePair>;
|
||||
template class DB_PUBLIC local_processor_result_computation_task<db::Edge, db::Edge, db::Edge>;
|
||||
template class DB_PUBLIC local_processor_result_computation_task<db::Edge, db::PolygonRef, db::Edge>;
|
||||
template class DB_PUBLIC local_processor_result_computation_task<db::Edge, db::Edge, db::EdgePair>;
|
||||
|
||||
// explicit instantiations
|
||||
template class DB_PUBLIC local_processor<db::Polygon, db::Polygon, db::Polygon>;
|
||||
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::PolygonRefWithProperties>;
|
||||
template class DB_PUBLIC local_processor<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::EdgeWithProperties>;
|
||||
template class DB_PUBLIC local_processor<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::EdgePair>;
|
||||
template class DB_PUBLIC local_processor<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::EdgePairWithProperties>;
|
||||
template class DB_PUBLIC local_processor<db::PolygonWithProperties, db::PolygonWithProperties, db::PolygonWithProperties>;
|
||||
template class DB_PUBLIC local_processor<db::PolygonWithProperties, db::PolygonWithProperties, db::EdgeWithProperties>;
|
||||
template class DB_PUBLIC local_processor<db::PolygonWithProperties, db::PolygonWithProperties, db::EdgePair>;
|
||||
template class DB_PUBLIC local_processor<db::PolygonWithProperties, db::PolygonWithProperties, db::EdgePairWithProperties>;
|
||||
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>;
|
||||
|
|
|
|||
|
|
@ -407,11 +407,11 @@ HierarchyBuilder::new_inst_member (const RecursiveShapeIterator *iter, const db:
|
|||
}
|
||||
|
||||
void
|
||||
HierarchyBuilder::shape (const RecursiveShapeIterator * /*iter*/, const db::Shape &shape, const db::ICplxTrans &apply_always, const db::ICplxTrans & /*trans*/, const db::Box ®ion, const box_tree_type *complex_region)
|
||||
HierarchyBuilder::shape (const RecursiveShapeIterator *iter, const db::Shape &shape, const db::ICplxTrans &apply_always, const db::ICplxTrans & /*trans*/, const db::Box ®ion, const box_tree_type *complex_region)
|
||||
{
|
||||
for (std::vector<db::Cell *>::const_iterator c = m_cell_stack.back ().second.begin (); c != m_cell_stack.back ().second.end (); ++c) {
|
||||
db::Shapes &shapes = (*c)->shapes (m_target_layer);
|
||||
mp_pipe->push (shape, m_trans * apply_always, region, complex_region, &shapes);
|
||||
mp_pipe->push (shape, iter->prop_id (), m_trans * apply_always, region, complex_region, &shapes);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -424,54 +424,54 @@ ClippingHierarchyBuilderShapeReceiver::ClippingHierarchyBuilderShapeReceiver (Hi
|
|||
}
|
||||
|
||||
void
|
||||
ClippingHierarchyBuilderShapeReceiver::push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box ®ion, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
|
||||
ClippingHierarchyBuilderShapeReceiver::push (const db::Shape &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box ®ion, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
|
||||
{
|
||||
static db::Box world = db::Box::world ();
|
||||
|
||||
if (region == world || is_inside (shape.bbox (), region, complex_region)) {
|
||||
|
||||
mp_pipe->push (shape, trans, world, 0, target);
|
||||
mp_pipe->push (shape, prop_id, trans, world, 0, target);
|
||||
|
||||
} else if (! is_outside (shape.bbox (), region, complex_region)) {
|
||||
|
||||
// clip the shape if required
|
||||
if (shape.is_text () || shape.is_edge () || shape.is_edge_pair ()) {
|
||||
mp_pipe->push (shape, trans, world, 0, target);
|
||||
mp_pipe->push (shape, prop_id, trans, world, 0, target);
|
||||
} else if (shape.is_box ()) {
|
||||
insert_clipped (shape.box (), trans, region, complex_region, target);
|
||||
insert_clipped (shape.box (), prop_id, trans, region, complex_region, target);
|
||||
} else if (shape.is_polygon () || shape.is_simple_polygon () || shape.is_path ()) {
|
||||
db::Polygon poly;
|
||||
shape.polygon (poly);
|
||||
insert_clipped (poly, trans, region, complex_region, target);
|
||||
insert_clipped (poly, prop_id, trans, region, complex_region, target);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ClippingHierarchyBuilderShapeReceiver::push (const db::Box &shape, const db::ICplxTrans &trans, const db::Box ®ion, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
|
||||
ClippingHierarchyBuilderShapeReceiver::push (const db::Box &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box ®ion, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
|
||||
{
|
||||
static db::Box world = db::Box::world ();
|
||||
|
||||
if (! complex_region) {
|
||||
db::Box r = shape & region;
|
||||
if (! r.empty()) {
|
||||
mp_pipe->push (r, trans, world, 0, target);
|
||||
mp_pipe->push (r, prop_id, trans, world, 0, target);
|
||||
}
|
||||
} else {
|
||||
insert_clipped (shape, trans, region, complex_region, target);
|
||||
insert_clipped (shape, prop_id, trans, region, complex_region, target);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ClippingHierarchyBuilderShapeReceiver::push (const db::Polygon &shape, const db::ICplxTrans &trans, const db::Box ®ion, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
|
||||
ClippingHierarchyBuilderShapeReceiver::push (const db::Polygon &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box ®ion, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
|
||||
{
|
||||
static db::Box world = db::Box::world ();
|
||||
|
||||
if (region == world || (shape.box ().inside (region) && ! complex_region)) {
|
||||
mp_pipe->push (shape, trans, world, 0, target);
|
||||
mp_pipe->push (shape, prop_id, trans, world, 0, target);
|
||||
} else {
|
||||
insert_clipped (shape, trans, region, complex_region, target);
|
||||
insert_clipped (shape, prop_id, trans, region, complex_region, target);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -529,7 +529,7 @@ ClippingHierarchyBuilderShapeReceiver::is_outside (const db::Box &box, const db:
|
|||
}
|
||||
|
||||
void
|
||||
ClippingHierarchyBuilderShapeReceiver::insert_clipped (const db::Box &box, const db::ICplxTrans &trans, const db::Box ®ion, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
|
||||
ClippingHierarchyBuilderShapeReceiver::insert_clipped (const db::Box &box, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box ®ion, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
|
||||
{
|
||||
db::Box bb = box & region;
|
||||
static db::Box world = db::Box::world ();
|
||||
|
|
@ -538,16 +538,16 @@ ClippingHierarchyBuilderShapeReceiver::insert_clipped (const db::Box &box, const
|
|||
for (db::RecursiveShapeReceiver::box_tree_type::overlapping_iterator cr = complex_region->begin_overlapping (bb, db::box_convert<db::Box> ()); ! cr.at_end (); ++cr) {
|
||||
db::Box bc = *cr & bb;
|
||||
if (! bc.empty ()) {
|
||||
mp_pipe->push (bc, trans, world, 0, target);
|
||||
mp_pipe->push (bc, prop_id, trans, world, 0, target);
|
||||
}
|
||||
}
|
||||
} else if (! bb.empty ()) {
|
||||
mp_pipe->push (bb, trans, world, 0, target);
|
||||
mp_pipe->push (bb, prop_id, trans, world, 0, target);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ClippingHierarchyBuilderShapeReceiver::insert_clipped (const db::Polygon &poly, const db::ICplxTrans &trans, const db::Box ®ion, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
|
||||
ClippingHierarchyBuilderShapeReceiver::insert_clipped (const db::Polygon &poly, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box ®ion, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
|
||||
{
|
||||
std::vector<db::Polygon> clipped_poly;
|
||||
static db::Box world = db::Box::world ();
|
||||
|
|
@ -562,7 +562,7 @@ ClippingHierarchyBuilderShapeReceiver::insert_clipped (const db::Polygon &poly,
|
|||
}
|
||||
|
||||
for (std::vector<db::Polygon>::const_iterator p = clipped_poly.begin (); p != clipped_poly.end (); ++p) {
|
||||
mp_pipe->push (*p, trans, world, 0, target);
|
||||
mp_pipe->push (*p, prop_id, trans, world, 0, target);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -575,33 +575,33 @@ ReducingHierarchyBuilderShapeReceiver::ReducingHierarchyBuilderShapeReceiver (Hi
|
|||
}
|
||||
|
||||
void
|
||||
ReducingHierarchyBuilderShapeReceiver::push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box ®ion, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
|
||||
ReducingHierarchyBuilderShapeReceiver::push (const db::Shape &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box ®ion, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
|
||||
{
|
||||
if (shape.is_text () || shape.is_edge () || shape.is_edge_pair ()) {
|
||||
mp_pipe->push (shape, trans, region, complex_region, target);
|
||||
mp_pipe->push (shape, prop_id, trans, region, complex_region, target);
|
||||
} else if (shape.is_box ()) {
|
||||
mp_pipe->push (shape.box (), trans, region, complex_region, target);
|
||||
mp_pipe->push (shape.box (), prop_id, trans, region, complex_region, target);
|
||||
} else if (shape.is_polygon () || shape.is_simple_polygon () || shape.is_path ()) {
|
||||
db::Polygon poly;
|
||||
shape.polygon (poly);
|
||||
reduce (poly, trans, region, complex_region, target);
|
||||
reduce (poly, prop_id, trans, region, complex_region, target);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ReducingHierarchyBuilderShapeReceiver::push (const db::Box &shape, const db::ICplxTrans &trans, const db::Box ®ion, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
|
||||
ReducingHierarchyBuilderShapeReceiver::push (const db::Box &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box ®ion, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
|
||||
{
|
||||
mp_pipe->push (shape, trans, region, complex_region, target);
|
||||
mp_pipe->push (shape, prop_id, trans, region, complex_region, target);
|
||||
}
|
||||
|
||||
void
|
||||
ReducingHierarchyBuilderShapeReceiver::push (const db::Polygon &shape, const db::ICplxTrans &trans, const db::Box ®ion, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
|
||||
ReducingHierarchyBuilderShapeReceiver::push (const db::Polygon &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box ®ion, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
|
||||
{
|
||||
reduce (shape, trans, region, complex_region, target);
|
||||
reduce (shape, prop_id, trans, region, complex_region, target);
|
||||
}
|
||||
|
||||
void
|
||||
ReducingHierarchyBuilderShapeReceiver::reduce (const db::Polygon &poly, const db::ICplxTrans &trans, const db::Box ®ion, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target, bool check)
|
||||
ReducingHierarchyBuilderShapeReceiver::reduce (const db::Polygon &poly, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box ®ion, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target, bool check)
|
||||
{
|
||||
if (check && m_reject_odd_polygons && is_non_orientable_polygon (poly)) {
|
||||
// non-orientable polygons generate an error
|
||||
|
|
@ -620,26 +620,41 @@ ReducingHierarchyBuilderShapeReceiver::reduce (const db::Polygon &poly, const db
|
|||
db::split_polygon (poly, split_polygons);
|
||||
|
||||
for (std::vector <db::Polygon>::const_iterator sp = split_polygons.begin (); sp != split_polygons.end (); ++sp) {
|
||||
reduce (*sp, trans, region, complex_region, target, false);
|
||||
reduce (*sp, prop_id, trans, region, complex_region, target, false);
|
||||
}
|
||||
|
||||
} else {
|
||||
mp_pipe->push (poly, trans, region, complex_region, target);
|
||||
mp_pipe->push (poly, prop_id, trans, region, complex_region, target);
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
|
||||
PolygonReferenceHierarchyBuilderShapeReceiver::PolygonReferenceHierarchyBuilderShapeReceiver (db::Layout *layout, int text_enlargement, const tl::Variant &text_prop_name)
|
||||
PolygonReferenceHierarchyBuilderShapeReceiver::PolygonReferenceHierarchyBuilderShapeReceiver (db::Layout *layout, const db::Layout *source_layout, int text_enlargement, const tl::Variant &text_prop_name)
|
||||
: mp_layout (layout), m_text_enlargement (text_enlargement), m_make_text_prop (false), m_text_prop_id (0)
|
||||
{
|
||||
if (! text_prop_name.is_nil ()) {
|
||||
m_text_prop_id = layout->properties_repository ().prop_name_id (text_prop_name);
|
||||
m_make_text_prop = true;
|
||||
}
|
||||
|
||||
if (source_layout && source_layout != layout) {
|
||||
m_pm.set_source (source_layout);
|
||||
m_pm.set_target (layout);
|
||||
}
|
||||
}
|
||||
|
||||
void PolygonReferenceHierarchyBuilderShapeReceiver::push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target)
|
||||
void PolygonReferenceHierarchyBuilderShapeReceiver::make_pref (db::Shapes *target, const db::Polygon &poly, db::properties_id_type prop_id)
|
||||
{
|
||||
prop_id = m_pm (prop_id);
|
||||
if (prop_id != 0) {
|
||||
target->insert (db::PolygonRefWithProperties (db::PolygonRef (poly, mp_layout->shape_repository ()), prop_id));
|
||||
} else {
|
||||
target->insert (db::PolygonRef (poly, mp_layout->shape_repository ()));
|
||||
}
|
||||
}
|
||||
|
||||
void PolygonReferenceHierarchyBuilderShapeReceiver::push (const db::Shape &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target)
|
||||
{
|
||||
if (shape.is_box () || shape.is_polygon () || shape.is_simple_polygon () || shape.is_path ()) {
|
||||
|
||||
|
|
@ -652,25 +667,35 @@ void PolygonReferenceHierarchyBuilderShapeReceiver::push (const db::Shape &shape
|
|||
// NOTE: as this is a specialized receiver for the purpose of building region
|
||||
// representations we don't need empty polygons here
|
||||
if (poly.area2 () > 0) {
|
||||
target->insert (db::PolygonRef (poly, mp_layout->shape_repository ()));
|
||||
make_pref (target, poly, prop_id);
|
||||
}
|
||||
|
||||
} else if (shape.is_text () && m_text_enlargement >= 0) {
|
||||
|
||||
// Texts generate small marker shapes with text_enlargement defining the box
|
||||
|
||||
db::Polygon poly (shape.text_trans () * db::Box (-m_text_enlargement, -m_text_enlargement, m_text_enlargement, m_text_enlargement));
|
||||
if (! trans.is_unity ()) {
|
||||
poly.transform (trans);
|
||||
}
|
||||
db::PolygonRef pref (poly, mp_layout->shape_repository ());
|
||||
|
||||
db::properties_id_type pid;
|
||||
|
||||
if (m_make_text_prop) {
|
||||
|
||||
// NOTE: text properties override the prop_id passed down from the hierarchy builder when generating the
|
||||
// text marker shape
|
||||
db::PropertiesRepository::properties_set ps;
|
||||
ps.insert (std::make_pair (m_text_prop_id, tl::Variant (shape.text_string ())));
|
||||
db::properties_id_type pid = mp_layout->properties_repository ().properties_id (ps);
|
||||
pid = mp_layout->properties_repository ().properties_id (ps);
|
||||
|
||||
} else {
|
||||
pid = m_pm (prop_id);
|
||||
}
|
||||
|
||||
if (pid != 0) {
|
||||
target->insert (db::PolygonRefWithProperties (pref, pid));
|
||||
|
||||
} else {
|
||||
target->insert (pref);
|
||||
}
|
||||
|
|
@ -678,89 +703,126 @@ void PolygonReferenceHierarchyBuilderShapeReceiver::push (const db::Shape &shape
|
|||
}
|
||||
}
|
||||
|
||||
void PolygonReferenceHierarchyBuilderShapeReceiver::push (const db::Box &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target)
|
||||
void PolygonReferenceHierarchyBuilderShapeReceiver::push (const db::Box &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target)
|
||||
{
|
||||
if (shape.area () > 0) {
|
||||
target->insert (db::PolygonRef (db::Polygon (shape.transformed (trans)), mp_layout->shape_repository ()));
|
||||
make_pref (target, db::Polygon (shape).transformed (trans), prop_id);
|
||||
}
|
||||
}
|
||||
|
||||
void PolygonReferenceHierarchyBuilderShapeReceiver::push (const db::Polygon &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target)
|
||||
void PolygonReferenceHierarchyBuilderShapeReceiver::push (const db::Polygon &shape, properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target)
|
||||
{
|
||||
if (shape.area2 () > 0) {
|
||||
target->insert (db::PolygonRef (shape.transformed (trans), mp_layout->shape_repository ()));
|
||||
make_pref (target, shape.transformed (trans), prop_id);
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
|
||||
EdgeBuildingHierarchyBuilderShapeReceiver::EdgeBuildingHierarchyBuilderShapeReceiver (bool as_edges)
|
||||
EdgeBuildingHierarchyBuilderShapeReceiver::EdgeBuildingHierarchyBuilderShapeReceiver (db::Layout *layout, const db::Layout *source_layout, bool as_edges)
|
||||
: m_as_edges (as_edges)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
if (source_layout && source_layout != layout) {
|
||||
m_pm.set_source (source_layout);
|
||||
m_pm.set_target (layout);
|
||||
}
|
||||
}
|
||||
|
||||
void EdgeBuildingHierarchyBuilderShapeReceiver::push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box ®ion, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
|
||||
void EdgeBuildingHierarchyBuilderShapeReceiver::push (const db::Shape &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box ®ion, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
|
||||
{
|
||||
if (m_as_edges && (shape.is_polygon () || shape.is_simple_polygon () || shape.is_path ())) {
|
||||
db::Polygon poly;
|
||||
shape.polygon (poly);
|
||||
push (poly, trans, region, complex_region, target);
|
||||
push (poly, prop_id, trans, region, complex_region, target);
|
||||
} else if (m_as_edges && shape.is_box ()) {
|
||||
push (shape.box (), trans, region, complex_region, target);
|
||||
push (shape.box (), prop_id, trans, region, complex_region, target);
|
||||
} else if (shape.is_edge ()) {
|
||||
target->insert (shape.edge ());
|
||||
prop_id = m_pm (prop_id);
|
||||
if (prop_id != 0) {
|
||||
target->insert (db::EdgeWithProperties (shape.edge (), shape.prop_id ()));
|
||||
} else {
|
||||
target->insert (shape.edge ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EdgeBuildingHierarchyBuilderShapeReceiver::push (const db::Box &box, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target)
|
||||
void EdgeBuildingHierarchyBuilderShapeReceiver::push (const db::Box &box, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target)
|
||||
{
|
||||
if (m_as_edges && ! box.empty ()) {
|
||||
target->insert (db::Edge (box.p1 (), box.upper_left ()).transformed (trans));
|
||||
target->insert (db::Edge (box.upper_left (), box.p2 ()).transformed (trans));
|
||||
target->insert (db::Edge (box.p2 (), box.lower_right ()).transformed (trans));
|
||||
target->insert (db::Edge (box.lower_right (), box.p1 ()).transformed (trans));
|
||||
prop_id = m_pm (prop_id);
|
||||
if (prop_id != 0) {
|
||||
target->insert (db::EdgeWithProperties (db::Edge (box.p1 (), box.upper_left ()).transformed (trans), prop_id));
|
||||
target->insert (db::EdgeWithProperties (db::Edge (box.upper_left (), box.p2 ()).transformed (trans), prop_id));
|
||||
target->insert (db::EdgeWithProperties (db::Edge (box.p2 (), box.lower_right ()).transformed (trans), prop_id));
|
||||
target->insert (db::EdgeWithProperties (db::Edge (box.lower_right (), box.p1 ()).transformed (trans), prop_id));
|
||||
} else {
|
||||
target->insert (db::Edge (box.p1 (), box.upper_left ()).transformed (trans));
|
||||
target->insert (db::Edge (box.upper_left (), box.p2 ()).transformed (trans));
|
||||
target->insert (db::Edge (box.p2 (), box.lower_right ()).transformed (trans));
|
||||
target->insert (db::Edge (box.lower_right (), box.p1 ()).transformed (trans));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EdgeBuildingHierarchyBuilderShapeReceiver::push (const db::Polygon &poly, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target)
|
||||
void EdgeBuildingHierarchyBuilderShapeReceiver::push (const db::Polygon &poly, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target)
|
||||
{
|
||||
if (m_as_edges) {
|
||||
prop_id = m_pm (prop_id);
|
||||
for (db::Polygon::polygon_edge_iterator e = poly.begin_edge (); ! e.at_end (); ++e) {
|
||||
target->insert ((*e).transformed (trans));
|
||||
if (prop_id != 0) {
|
||||
target->insert (db::EdgeWithProperties ((*e).transformed (trans), prop_id));
|
||||
} else {
|
||||
target->insert ((*e).transformed (trans));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
|
||||
EdgePairBuildingHierarchyBuilderShapeReceiver::EdgePairBuildingHierarchyBuilderShapeReceiver ()
|
||||
EdgePairBuildingHierarchyBuilderShapeReceiver::EdgePairBuildingHierarchyBuilderShapeReceiver (db::Layout *layout, const db::Layout *source_layout)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
if (source_layout && source_layout != layout) {
|
||||
m_pm.set_source (source_layout);
|
||||
m_pm.set_target (layout);
|
||||
}
|
||||
}
|
||||
|
||||
void EdgePairBuildingHierarchyBuilderShapeReceiver::push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box & /*region*/, const db::RecursiveShapeReceiver::box_tree_type * /*complex_region*/, db::Shapes *target)
|
||||
void EdgePairBuildingHierarchyBuilderShapeReceiver::push (const db::Shape &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box & /*region*/, const db::RecursiveShapeReceiver::box_tree_type * /*complex_region*/, db::Shapes *target)
|
||||
{
|
||||
if (shape.is_edge_pair ()) {
|
||||
target->insert (shape.edge_pair ().transformed (trans));
|
||||
prop_id = m_pm (prop_id);
|
||||
if (prop_id != 0) {
|
||||
target->insert (db::EdgePairWithProperties (shape.edge_pair ().transformed (trans), prop_id));
|
||||
} else {
|
||||
target->insert (shape.edge_pair ().transformed (trans));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
|
||||
TextBuildingHierarchyBuilderShapeReceiver::TextBuildingHierarchyBuilderShapeReceiver (db::Layout *layout)
|
||||
TextBuildingHierarchyBuilderShapeReceiver::TextBuildingHierarchyBuilderShapeReceiver (db::Layout *layout, const db::Layout *source_layout)
|
||||
: mp_layout (layout)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
if (source_layout && source_layout != layout) {
|
||||
m_pm.set_source (source_layout);
|
||||
m_pm.set_target (layout);
|
||||
}
|
||||
}
|
||||
|
||||
void TextBuildingHierarchyBuilderShapeReceiver::push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box & /*region*/, const db::RecursiveShapeReceiver::box_tree_type * /*complex_region*/, db::Shapes *target)
|
||||
void TextBuildingHierarchyBuilderShapeReceiver::push (const db::Shape &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box & /*region*/, const db::RecursiveShapeReceiver::box_tree_type * /*complex_region*/, db::Shapes *target)
|
||||
{
|
||||
if (shape.is_text ()) {
|
||||
// NOTE: we intentionally skip all the text attributes (font etc.) here because in the context
|
||||
// of a text collections we're only interested in the locations.
|
||||
db::Text t (shape.text_string (), shape.text_trans ());
|
||||
target->insert (db::TextRef (t.transformed (trans), mp_layout->shape_repository ()));
|
||||
prop_id = m_pm (prop_id);
|
||||
if (prop_id != 0) {
|
||||
target->insert (db::TextRefWithProperties (db::TextRef (t.transformed (trans), mp_layout->shape_repository ()), prop_id));
|
||||
} else {
|
||||
target->insert (db::TextRef (t.transformed (trans), mp_layout->shape_repository ()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include "dbRecursiveShapeIterator.h"
|
||||
#include "dbLayout.h"
|
||||
#include "dbLayoutUtils.h"
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
|
@ -55,9 +56,9 @@ public:
|
|||
HierarchyBuilderShapeReceiver () { }
|
||||
virtual ~HierarchyBuilderShapeReceiver () { }
|
||||
|
||||
virtual void push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box ®ion, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target) = 0;
|
||||
virtual void push (const db::Box &shape, const db::ICplxTrans &trans, const db::Box ®ion, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target) = 0;
|
||||
virtual void push (const db::Polygon &shape, const db::ICplxTrans &trans, const db::Box ®ion, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target) = 0;
|
||||
virtual void push (const db::Shape &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box ®ion, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target) = 0;
|
||||
virtual void push (const db::Box &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box ®ion, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target) = 0;
|
||||
virtual void push (const db::Polygon &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box ®ion, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -69,28 +70,45 @@ class DB_PUBLIC HierarchyBuilderShapeInserter
|
|||
public:
|
||||
HierarchyBuilderShapeInserter () { }
|
||||
|
||||
virtual void push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target)
|
||||
virtual void push (const db::Shape &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target)
|
||||
{
|
||||
tl::ident_map<db::Layout::properties_id_type> pm;
|
||||
tl::const_map<db::Layout::properties_id_type> pm (prop_id);
|
||||
target->insert (shape, trans, pm);
|
||||
}
|
||||
|
||||
virtual void push (const db::Box &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target)
|
||||
virtual void push (const db::Box &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target)
|
||||
{
|
||||
if (trans.is_ortho ()) {
|
||||
target->insert (shape.transformed (trans));
|
||||
if (prop_id != 0) {
|
||||
target->insert (db::BoxWithProperties (shape.transformed (trans), prop_id));
|
||||
} else {
|
||||
target->insert (shape.transformed (trans));
|
||||
}
|
||||
} else {
|
||||
db::Polygon poly (shape);
|
||||
target->insert (poly.transformed (trans));
|
||||
if (prop_id != 0) {
|
||||
db::PolygonWithProperties poly (db::Polygon (shape), prop_id);
|
||||
target->insert (poly.transformed (trans));
|
||||
} else {
|
||||
db::Polygon poly (shape);
|
||||
target->insert (poly.transformed (trans));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void push (const db::Polygon &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target)
|
||||
virtual void push (const db::Polygon &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target)
|
||||
{
|
||||
if (trans.is_unity ()) {
|
||||
target->insert (shape);
|
||||
if (prop_id != 0) {
|
||||
target->insert (db::PolygonWithProperties (shape, prop_id));
|
||||
} else {
|
||||
target->insert (shape);
|
||||
}
|
||||
} else {
|
||||
target->insert (shape.transformed (trans));
|
||||
if (prop_id != 0) {
|
||||
target->insert (db::PolygonWithProperties (shape.transformed (trans), prop_id));
|
||||
} else {
|
||||
target->insert (shape.transformed (trans));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -104,13 +122,13 @@ class DB_PUBLIC ClippingHierarchyBuilderShapeReceiver
|
|||
public:
|
||||
ClippingHierarchyBuilderShapeReceiver (HierarchyBuilderShapeReceiver *pipe = 0);
|
||||
|
||||
virtual void push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
|
||||
virtual void push (const db::Box &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
|
||||
virtual void push (const db::Polygon &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
|
||||
virtual void push (const db::Shape &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
|
||||
virtual void push (const db::Box &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
|
||||
virtual void push (const db::Polygon &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
|
||||
|
||||
private:
|
||||
void insert_clipped (const db::Box &box, const db::ICplxTrans &trans, const db::Box ®ion, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target);
|
||||
void insert_clipped (const db::Polygon &poly, const db::ICplxTrans &trans, const db::Box ®ion, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target);
|
||||
void insert_clipped (const db::Box &box, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box ®ion, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target);
|
||||
void insert_clipped (const db::Polygon &poly, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box ®ion, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target);
|
||||
static bool is_inside (const db::Box &box, const db::Box ®ion, const db::RecursiveShapeReceiver::box_tree_type *complex_region);
|
||||
static bool is_outside (const db::Box &box, const db::Box ®ion, const db::RecursiveShapeReceiver::box_tree_type *complex_region);
|
||||
|
||||
|
|
@ -126,12 +144,12 @@ class DB_PUBLIC ReducingHierarchyBuilderShapeReceiver
|
|||
public:
|
||||
ReducingHierarchyBuilderShapeReceiver (HierarchyBuilderShapeReceiver *pipe = 0, double area_ratio = 3.0, size_t max_vertex_count = 16, bool reject_odd_polygons = false);
|
||||
|
||||
virtual void push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
|
||||
virtual void push (const db::Box &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
|
||||
virtual void push (const db::Polygon &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
|
||||
virtual void push (const db::Shape &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
|
||||
virtual void push (const db::Box &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
|
||||
virtual void push (const db::Polygon &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
|
||||
|
||||
private:
|
||||
void reduce (const db::Polygon &poly, const db::ICplxTrans &trans, const db::Box ®ion, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target, bool check = true);
|
||||
void reduce (const db::Polygon &poly, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box ®ion, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target, bool check = true);
|
||||
|
||||
HierarchyBuilderShapeReceiver *mp_pipe;
|
||||
double m_area_ratio;
|
||||
|
|
@ -146,17 +164,20 @@ class DB_PUBLIC PolygonReferenceHierarchyBuilderShapeReceiver
|
|||
: public HierarchyBuilderShapeReceiver
|
||||
{
|
||||
public:
|
||||
PolygonReferenceHierarchyBuilderShapeReceiver (db::Layout *layout, int text_enlargement = -1, const tl::Variant &text_prop_name = tl::Variant ());
|
||||
PolygonReferenceHierarchyBuilderShapeReceiver (db::Layout *layout, const Layout *source_layout, int text_enlargement = -1, const tl::Variant &text_prop_name = tl::Variant ());
|
||||
|
||||
virtual void push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
|
||||
virtual void push (const db::Box &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
|
||||
virtual void push (const db::Polygon &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
|
||||
virtual void push (const db::Shape &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
|
||||
virtual void push (const db::Box &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
|
||||
virtual void push (const db::Polygon &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
|
||||
|
||||
private:
|
||||
void make_pref (db::Shapes *target, const db::Polygon &polygon, db::properties_id_type prop_id);
|
||||
|
||||
db::Layout *mp_layout;
|
||||
int m_text_enlargement;
|
||||
bool m_make_text_prop;
|
||||
db::property_names_id_type m_text_prop_id;
|
||||
db::PropertyMapper m_pm;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -166,14 +187,15 @@ class DB_PUBLIC EdgeBuildingHierarchyBuilderShapeReceiver
|
|||
: public HierarchyBuilderShapeReceiver
|
||||
{
|
||||
public:
|
||||
EdgeBuildingHierarchyBuilderShapeReceiver (bool as_edges);
|
||||
EdgeBuildingHierarchyBuilderShapeReceiver (db::Layout *layout, const Layout *source_layout, bool as_edges);
|
||||
|
||||
virtual void push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
|
||||
virtual void push (const db::Box &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
|
||||
virtual void push (const db::Polygon &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
|
||||
virtual void push (const db::Shape &shape, properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
|
||||
virtual void push (const db::Box &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
|
||||
virtual void push (const db::Polygon &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
|
||||
|
||||
private:
|
||||
bool m_as_edges;
|
||||
db::PropertyMapper m_pm;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -183,11 +205,14 @@ class DB_PUBLIC EdgePairBuildingHierarchyBuilderShapeReceiver
|
|||
: public HierarchyBuilderShapeReceiver
|
||||
{
|
||||
public:
|
||||
EdgePairBuildingHierarchyBuilderShapeReceiver ();
|
||||
EdgePairBuildingHierarchyBuilderShapeReceiver (db::Layout *layout, const Layout *source_layout);
|
||||
|
||||
virtual void push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
|
||||
virtual void push (const db::Box &, const db::ICplxTrans &, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *) { }
|
||||
virtual void push (const db::Polygon &, const db::ICplxTrans &, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *) { }
|
||||
virtual void push (const db::Shape &shape, properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
|
||||
virtual void push (const db::Box &, db::properties_id_type, const db::ICplxTrans &, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *) { }
|
||||
virtual void push (const db::Polygon &, db::properties_id_type, const db::ICplxTrans &, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *) { }
|
||||
|
||||
private:
|
||||
db::PropertyMapper m_pm;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -197,14 +222,15 @@ class DB_PUBLIC TextBuildingHierarchyBuilderShapeReceiver
|
|||
: public HierarchyBuilderShapeReceiver
|
||||
{
|
||||
public:
|
||||
TextBuildingHierarchyBuilderShapeReceiver (db::Layout *layout);
|
||||
TextBuildingHierarchyBuilderShapeReceiver (db::Layout *layout, const Layout *source_layout);
|
||||
|
||||
virtual void push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
|
||||
virtual void push (const db::Box &, const db::ICplxTrans &, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *) { }
|
||||
virtual void push (const db::Polygon &, const db::ICplxTrans &, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *) { }
|
||||
virtual void push (const db::Shape &shape, properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
|
||||
virtual void push (const db::Box &, db::properties_id_type, const db::ICplxTrans &, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *) { }
|
||||
virtual void push (const db::Polygon &, db::properties_id_type, const db::ICplxTrans &, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *) { }
|
||||
|
||||
private:
|
||||
db::Layout *mp_layout;
|
||||
db::PropertyMapper m_pm;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -670,11 +670,11 @@ do_compare_layouts (const db::Layout &a, const db::Cell *top_a, const db::Layout
|
|||
na.properties_repository () = a.properties_repository ();
|
||||
nb.properties_repository () = b.properties_repository ();
|
||||
|
||||
db::PropertyMapper prop_normalize_a (n, a);
|
||||
db::PropertyMapper prop_normalize_b (n, b);
|
||||
db::PropertyMapper prop_normalize_a (&n, &a);
|
||||
db::PropertyMapper prop_normalize_b (&n, &b);
|
||||
|
||||
db::PropertyMapper prop_remap_to_a (na, n);
|
||||
db::PropertyMapper prop_remap_to_b (nb, n);
|
||||
db::PropertyMapper prop_remap_to_a (&na, &n);
|
||||
db::PropertyMapper prop_remap_to_b (&nb, &n);
|
||||
|
||||
// compare layers
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,10 @@
|
|||
namespace db
|
||||
{
|
||||
|
||||
// the iterator provides the hierarchical selection (enabling/disabling cells etc.)
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
// LayoutToNetlist implementation
|
||||
|
||||
// Note: the iterator provides the hierarchical selection (enabling/disabling cells etc.)
|
||||
|
||||
LayoutToNetlist::LayoutToNetlist (const db::RecursiveShapeIterator &iter)
|
||||
: m_iter (iter), m_layout_index (0), m_netlist_extracted (false), m_is_flat (false), m_device_scaling (1.0), m_include_floating_subcircuits (false)
|
||||
|
|
@ -155,9 +158,7 @@ db::Region *LayoutToNetlist::make_layer (const std::string &n)
|
|||
si.shape_flags (db::ShapeIterator::Nothing);
|
||||
|
||||
std::unique_ptr <db::Region> region (new db::Region (si, dss ()));
|
||||
if (! n.empty ()) {
|
||||
register_layer (*region, n);
|
||||
}
|
||||
register_layer (*region, n);
|
||||
return region.release ();
|
||||
}
|
||||
|
||||
|
|
@ -168,9 +169,7 @@ db::Region *LayoutToNetlist::make_layer (unsigned int layer_index, const std::st
|
|||
si.shape_flags (db::ShapeIterator::All);
|
||||
|
||||
std::unique_ptr <db::Region> region (new db::Region (si, dss ()));
|
||||
if (! n.empty ()) {
|
||||
register_layer (*region, n);
|
||||
}
|
||||
register_layer (*region, n);
|
||||
return region.release ();
|
||||
}
|
||||
|
||||
|
|
@ -181,9 +180,7 @@ db::Texts *LayoutToNetlist::make_text_layer (unsigned int layer_index, const std
|
|||
si.shape_flags (db::ShapeIterator::Texts);
|
||||
|
||||
std::unique_ptr <db::Texts> texts (new db::Texts (si, dss ()));
|
||||
if (! n.empty ()) {
|
||||
register_layer (*texts, n);
|
||||
}
|
||||
register_layer (*texts, n);
|
||||
return texts.release ();
|
||||
}
|
||||
|
||||
|
|
@ -194,9 +191,7 @@ db::Region *LayoutToNetlist::make_polygon_layer (unsigned int layer_index, const
|
|||
si.shape_flags (db::ShapeIterator::Paths | db::ShapeIterator::Polygons | db::ShapeIterator::Boxes);
|
||||
|
||||
std::unique_ptr <db::Region> region (new db::Region (si, dss ()));
|
||||
if (! n.empty ()) {
|
||||
register_layer (*region, n);
|
||||
}
|
||||
register_layer (*region, n);
|
||||
return region.release ();
|
||||
}
|
||||
|
||||
|
|
@ -264,7 +259,7 @@ void LayoutToNetlist::connect (const db::Region &l)
|
|||
reset_extracted ();
|
||||
|
||||
if (! is_persisted (l)) {
|
||||
register_layer (l, make_new_name ());
|
||||
register_layer (l);
|
||||
}
|
||||
|
||||
// we need to keep a reference, so we can safely delete the region
|
||||
|
|
@ -279,10 +274,10 @@ void LayoutToNetlist::connect_impl (const db::ShapeCollection &a, const db::Shap
|
|||
reset_extracted ();
|
||||
|
||||
if (! is_persisted (a)) {
|
||||
register_layer (a, make_new_name ());
|
||||
register_layer (a);
|
||||
}
|
||||
if (! is_persisted (b)) {
|
||||
register_layer (b, make_new_name ());
|
||||
register_layer (b);
|
||||
}
|
||||
|
||||
// we need to keep a reference, so we can safely delete the region
|
||||
|
|
@ -299,7 +294,7 @@ size_t LayoutToNetlist::connect_global_impl (const db::ShapeCollection &l, const
|
|||
reset_extracted ();
|
||||
|
||||
if (! is_persisted (l)) {
|
||||
register_layer (l, make_new_name ());
|
||||
register_layer (l);
|
||||
}
|
||||
|
||||
// we need to keep a reference, so we can safely delete the region
|
||||
|
|
@ -430,6 +425,8 @@ void LayoutToNetlist::mem_stat (MemStatistics *stat, MemStatistics::purpose_t pu
|
|||
db::mem_stat (stat, purpose, cat, m_dlrefs, true, (void *) this);
|
||||
db::mem_stat (stat, purpose, cat, m_named_regions, true, (void *) this);
|
||||
db::mem_stat (stat, purpose, cat, m_name_of_layer, true, (void *) this);
|
||||
db::mem_stat (stat, purpose, cat, m_region_by_original, true, (void *) this);
|
||||
db::mem_stat (stat, purpose, cat, m_region_of_layer, true, (void *) this);
|
||||
db::mem_stat (stat, purpose, cat, m_joined_net_names, true, (void *) this);
|
||||
db::mem_stat (stat, purpose, cat, m_joined_net_names_per_cell, true, (void *) this);
|
||||
db::mem_stat (stat, purpose, cat, m_joined_nets, true, (void *) this);
|
||||
|
|
@ -534,11 +531,29 @@ db::Region *LayoutToNetlist::layer_by_name (const std::string &name)
|
|||
|
||||
db::Region *LayoutToNetlist::layer_by_index (unsigned int index)
|
||||
{
|
||||
std::map<unsigned int, std::string>::const_iterator n = m_name_of_layer.find (index);
|
||||
if (n == m_name_of_layer.end ()) {
|
||||
auto n = m_region_of_layer.find (index);
|
||||
if (n == m_region_of_layer.end ()) {
|
||||
return 0;
|
||||
} else {
|
||||
return layer_by_name (n->second);
|
||||
return new db::Region (new db::DeepRegion (n->second));
|
||||
}
|
||||
}
|
||||
|
||||
db::Region *LayoutToNetlist::layer_by_original (const ShapeCollectionDelegateBase *original_delegate)
|
||||
{
|
||||
auto n = m_region_by_original.find (tl::id_of (original_delegate));
|
||||
if (n == m_region_by_original.end ()) {
|
||||
|
||||
DeepShapeCollectionDelegateBase *dl = const_cast<ShapeCollectionDelegateBase *> (original_delegate)->deep ();
|
||||
if (dl && dl->deep_layer ().store () == mp_dss.get ()) {
|
||||
// implicitly original because the collection is inside our DSS
|
||||
return new db::Region (new db::DeepRegion (dl->deep_layer ()));
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
} else {
|
||||
return new db::Region (new db::DeepRegion (n->second));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -565,12 +580,19 @@ std::string LayoutToNetlist::name (const ShapeCollection &coll) const
|
|||
}
|
||||
}
|
||||
|
||||
void LayoutToNetlist::register_layer (const ShapeCollection &collection, const std::string &n)
|
||||
void LayoutToNetlist::register_layer (const ShapeCollection &collection, const std::string &n_in)
|
||||
{
|
||||
if (m_named_regions.find (n) != m_named_regions.end ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("Layer name is already used: ")) + n);
|
||||
if (m_region_by_original.find (tl::id_of (collection.get_delegate ())) != m_region_by_original.end ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("The layer is already registered")));
|
||||
}
|
||||
|
||||
if (! n_in.empty () && m_named_regions.find (n_in) != m_named_regions.end ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("Layer name is already used: ")) + n_in);
|
||||
}
|
||||
|
||||
// Caution: this make create names which clash with future explicit names. Hopefully, the generated names are unique enough.
|
||||
std::string n = n_in.empty () ? make_new_name () : n_in;
|
||||
|
||||
db::DeepLayer dl;
|
||||
|
||||
if (m_is_flat) {
|
||||
|
|
@ -586,17 +608,14 @@ void LayoutToNetlist::register_layer (const ShapeCollection &collection, const s
|
|||
|
||||
} else {
|
||||
|
||||
if (is_persisted (collection)) {
|
||||
std::string prev_name = name (collection);
|
||||
m_named_regions.erase (prev_name);
|
||||
}
|
||||
|
||||
dl = delegate->deep_layer ();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
m_region_by_original [tl::id_of (collection.get_delegate ())] = dl;
|
||||
m_region_of_layer [dl.layer ()] = dl;
|
||||
m_named_regions [n] = dl;
|
||||
m_name_of_layer [dl.layer ()] = n;
|
||||
}
|
||||
|
|
@ -618,6 +637,17 @@ db::DeepLayer LayoutToNetlist::deep_layer_of (const db::ShapeCollection &coll) c
|
|||
}
|
||||
}
|
||||
|
||||
bool LayoutToNetlist::is_persisted_impl (const db::ShapeCollection &coll) const
|
||||
{
|
||||
if (coll.get_delegate ()->deep () && coll.get_delegate ()->deep ()->deep_layer ().store () == mp_dss.get ()) {
|
||||
// implicitly persisted because the collection is inside our DSS
|
||||
return true;
|
||||
} else {
|
||||
// explicitly persisted through "register"
|
||||
return m_region_by_original.find (tl::id_of (coll.get_delegate ())) != m_region_by_original.end ();
|
||||
}
|
||||
}
|
||||
|
||||
db::CellMapping LayoutToNetlist::make_cell_mapping_into (db::Layout &layout, db::Cell &cell, const std::vector<const db::Net *> *nets, bool with_device_cells)
|
||||
{
|
||||
std::set<db::cell_index_type> device_cells;
|
||||
|
|
@ -742,28 +772,28 @@ static bool deliver_shape (const db::NetShape &s, db::Shapes &shapes, const Tr &
|
|||
|
||||
db::PolygonRef pr = s.polygon_ref ();
|
||||
|
||||
if (pr.obj ().is_box ()) {
|
||||
db::Layout *layout = shapes.layout ();
|
||||
if (layout) {
|
||||
// NOTE: by maintaining the PolygonRefs we can directly use the output of "build_nets" as input
|
||||
// for a hierarchical processor.
|
||||
db::PolygonRef polygon_ref (pr.obj ().transformed (pr.trans ()).transformed (tr), layout->shape_repository ());
|
||||
if (propid) {
|
||||
shapes.insert (db::PolygonRefWithProperties (polygon_ref, propid));
|
||||
} else {
|
||||
shapes.insert (polygon_ref);
|
||||
}
|
||||
} else if (pr.obj ().is_box ()) {
|
||||
if (propid) {
|
||||
shapes.insert (db::BoxWithProperties (pr.obj ().box ().transformed (pr.trans ()).transformed (tr), propid));
|
||||
} else {
|
||||
shapes.insert (pr.obj ().box ().transformed (pr.trans ()).transformed (tr));
|
||||
}
|
||||
} else {
|
||||
db::Layout *layout = shapes.layout ();
|
||||
if (layout) {
|
||||
db::PolygonRef polygon_ref (pr.obj ().transformed (pr.trans ()).transformed (tr), layout->shape_repository ());
|
||||
if (propid) {
|
||||
shapes.insert (db::PolygonRefWithProperties (polygon_ref, propid));
|
||||
} else {
|
||||
shapes.insert (polygon_ref);
|
||||
}
|
||||
db::Polygon polygon (pr.obj ().transformed (pr.trans ()).transformed (tr));
|
||||
if (propid) {
|
||||
shapes.insert (db::PolygonWithProperties (polygon, propid));
|
||||
} else {
|
||||
db::Polygon polygon (pr.obj ().transformed (pr.trans ()).transformed (tr));
|
||||
if (propid) {
|
||||
shapes.insert (db::PolygonWithProperties (polygon, propid));
|
||||
} else {
|
||||
shapes.insert (polygon);
|
||||
}
|
||||
shapes.insert (polygon);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -850,7 +880,7 @@ static bool deliver_shapes_of_net (bool recursive, const db::Netlist *nl, const
|
|||
return true;
|
||||
}
|
||||
|
||||
void LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive, db::Shapes &to, db::properties_id_type propid) const
|
||||
void LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive, db::Shapes &to, db::properties_id_type propid, const ICplxTrans &trans) const
|
||||
{
|
||||
unsigned int lid = layer_of (of_layer);
|
||||
const db::Circuit *circuit = net.circuit ();
|
||||
|
|
@ -859,10 +889,10 @@ void LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region &of_la
|
|||
std::map<unsigned int, db::Shapes *> lmap;
|
||||
lmap [lid] = &to;
|
||||
|
||||
deliver_shapes_of_net (recursive, mp_netlist.get (), m_net_clusters, circuit->cell_index (), net.cluster_id (), lmap, db::ICplxTrans (), propid);
|
||||
deliver_shapes_of_net (recursive, mp_netlist.get (), m_net_clusters, circuit->cell_index (), net.cluster_id (), lmap, trans, propid);
|
||||
}
|
||||
|
||||
db::Region *LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive) const
|
||||
db::Region *LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive, const db::ICplxTrans &trans) const
|
||||
{
|
||||
unsigned int lid = layer_of (of_layer);
|
||||
const db::Circuit *circuit = net.circuit ();
|
||||
|
|
@ -872,268 +902,44 @@ db::Region *LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region
|
|||
std::map<unsigned int, db::Region *> lmap;
|
||||
lmap [lid] = res.get ();
|
||||
|
||||
deliver_shapes_of_net (recursive, mp_netlist.get (), m_net_clusters, circuit->cell_index (), net.cluster_id (), lmap, db::ICplxTrans (), 0);
|
||||
deliver_shapes_of_net (recursive, mp_netlist.get (), m_net_clusters, circuit->cell_index (), net.cluster_id (), lmap, trans, 0);
|
||||
|
||||
return res.release ();
|
||||
}
|
||||
|
||||
void
|
||||
LayoutToNetlist::build_net_rec (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, const char *net_cell_name_prefix, db::properties_id_type netname_propid, BuildNetHierarchyMode hier_mode, const char *cell_name_prefix, const char *device_cell_name_prefix, cell_reuse_table_type &reuse_table, const db::ICplxTrans &tr) const
|
||||
LayoutToNetlist::build_net (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, NetPropertyMode net_prop_mode, const tl::Variant &netname_prop, BuildNetHierarchyMode hier_mode, const char *cell_name_prefix, const char *device_cell_name_prefix) const
|
||||
{
|
||||
const db::Circuit *circuit = net.circuit ();
|
||||
tl_assert (circuit != 0);
|
||||
NetBuilder builder (&target, this);
|
||||
builder.set_hier_mode (hier_mode);
|
||||
builder.set_cell_name_prefix (cell_name_prefix);
|
||||
builder.set_device_cell_name_prefix (device_cell_name_prefix);
|
||||
|
||||
build_net_rec (circuit->cell_index (), net.cluster_id (), target, target_cell, lmap, &net, net_cell_name_prefix, netname_propid, hier_mode, cell_name_prefix, device_cell_name_prefix, reuse_table, tr);
|
||||
builder.build_net (target_cell, net, lmap, net_prop_mode, netname_prop);
|
||||
}
|
||||
|
||||
void
|
||||
LayoutToNetlist::build_net_rec (db::cell_index_type ci, size_t cid, db::Layout &target, db::Cell &tc, const std::map<unsigned int, const db::Region *> &lmap, const db::Net *net, const char *net_cell_name_prefix, db::properties_id_type netname_propid, BuildNetHierarchyMode hier_mode, const char *circuit_cell_name_prefix, const char *device_cell_name_prefix, cell_reuse_table_type &reuse_table, const db::ICplxTrans &tr) const
|
||||
LayoutToNetlist::build_all_nets (const db::CellMapping &cmap, db::Layout &target, const std::map<unsigned int, const db::Region *> &lmap, const char *net_cell_name_prefix, NetPropertyMode net_prop_mode, const tl::Variant &netname_prop, BuildNetHierarchyMode hier_mode, const char *circuit_cell_name_prefix, const char *device_cell_name_prefix) const
|
||||
{
|
||||
db::Cell *target_cell = &tc;
|
||||
NetBuilder builder (&target, cmap, this);
|
||||
builder.set_hier_mode (hier_mode);
|
||||
builder.set_net_cell_name_prefix (net_cell_name_prefix);
|
||||
builder.set_cell_name_prefix (circuit_cell_name_prefix);
|
||||
builder.set_device_cell_name_prefix (device_cell_name_prefix);
|
||||
|
||||
if (net_cell_name_prefix) {
|
||||
|
||||
const db::connected_clusters<db::NetShape> &ccl = m_net_clusters.clusters_per_cell (ci);
|
||||
|
||||
bool any_connections = circuit_cell_name_prefix && ! ccl.connections_for_cluster (cid).empty ();
|
||||
if (! any_connections) {
|
||||
|
||||
StopOnFirst sof;
|
||||
std::map<unsigned int, StopOnFirst *> sof_lmap;
|
||||
for (std::map<unsigned int, const db::Region *>::const_iterator l = lmap.begin (); l != lmap.end (); ++l) {
|
||||
if (l->second) {
|
||||
sof_lmap.insert (std::make_pair (layer_of (*l->second), &sof));
|
||||
}
|
||||
}
|
||||
|
||||
bool consider_cell = ! deliver_shapes_of_net (hier_mode == BNH_Flatten, mp_netlist.get (), m_net_clusters, ci, cid, sof_lmap, tr, 0);
|
||||
if (! consider_cell) {
|
||||
// shortcut if cell is empty -> no net cell will be produced
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// make a specific cell for the net if requested
|
||||
|
||||
target_cell = &target.cell (target.add_cell ((std::string (net_cell_name_prefix) + net->expanded_name ()).c_str ()));
|
||||
tc.insert (db::CellInstArray (db::CellInst (target_cell->cell_index ()), db::Trans ()));
|
||||
|
||||
}
|
||||
|
||||
std::map<unsigned int, db::Shapes *> target_lmap;
|
||||
for (std::map<unsigned int, const db::Region *>::const_iterator l = lmap.begin (); l != lmap.end (); ++l) {
|
||||
if (l->second) {
|
||||
target_lmap.insert (std::make_pair (layer_of (*l->second), &target_cell->shapes (l->first)));
|
||||
}
|
||||
}
|
||||
|
||||
deliver_shapes_of_net (hier_mode == BNH_Flatten, mp_netlist.get (), m_net_clusters, ci, cid, target_lmap, tr, netname_propid);
|
||||
|
||||
if (hier_mode != BNH_SubcircuitCells && ! device_cell_name_prefix) {
|
||||
return;
|
||||
}
|
||||
|
||||
// NOTE: we propagate the magnification part of tr down, but keep the rotation/translation part in the instance
|
||||
// (we want to avoid magnified instances)
|
||||
db::ICplxTrans tr_wo_mag = tr * db::ICplxTrans (1.0 / tr.mag ());
|
||||
db::ICplxTrans tr_mag (tr.mag ());
|
||||
|
||||
const db::connected_clusters<db::NetShape> &clusters = m_net_clusters.clusters_per_cell (ci);
|
||||
typedef db::connected_clusters<db::NetShape>::connections_type connections_type;
|
||||
const connections_type &connections = clusters.connections_for_cluster (cid);
|
||||
for (connections_type::const_iterator c = connections.begin (); c != connections.end (); ++c) {
|
||||
|
||||
db::cell_index_type subci = c->inst_cell_index ();
|
||||
size_t subcid = c->id ();
|
||||
|
||||
CellReuseTableKey cmap_key (subci, netname_propid, subcid);
|
||||
|
||||
cell_reuse_table_type::const_iterator cm = reuse_table.find (cmap_key);
|
||||
if (cm == reuse_table.end ()) {
|
||||
|
||||
const char *name_prefix = 0;
|
||||
if (mp_netlist->device_abstract_by_cell_index (subci)) {
|
||||
name_prefix = device_cell_name_prefix;
|
||||
} else {
|
||||
name_prefix = circuit_cell_name_prefix;
|
||||
}
|
||||
|
||||
if (name_prefix) {
|
||||
|
||||
std::string cell_name = internal_layout ()->cell_name (subci);
|
||||
|
||||
db::cell_index_type target_ci = target.add_cell ((std::string (name_prefix) + cell_name).c_str ());
|
||||
cm = reuse_table.insert (std::make_pair (cmap_key, target_ci)).first;
|
||||
|
||||
build_net_rec (subci, subcid, target, target.cell (target_ci), lmap, 0, 0, netname_propid, hier_mode, circuit_cell_name_prefix, device_cell_name_prefix, reuse_table, tr_mag);
|
||||
|
||||
} else {
|
||||
cm = reuse_table.insert (std::make_pair (cmap_key, std::numeric_limits<db::cell_index_type>::max ())).first;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (cm->second != std::numeric_limits<db::cell_index_type>::max ()) {
|
||||
db::CellInstArray ci (db::CellInst (cm->second), tr_wo_mag * c->inst_trans ());
|
||||
ci.transform_into (tr_mag);
|
||||
target_cell->insert (ci);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
db::properties_id_type
|
||||
LayoutToNetlist::make_netname_propid (db::Layout &ly, const tl::Variant &netname_prop, const db::Net &net) const
|
||||
{
|
||||
if (! netname_prop.is_nil () || net.begin_properties () != net.end_properties ()) {
|
||||
|
||||
db::PropertiesRepository::properties_set propset;
|
||||
|
||||
// add the user properties too (TODO: make this configurable?)
|
||||
for (db::Net::property_iterator p = net.begin_properties (); p != net.end_properties (); ++p) {
|
||||
db::property_names_id_type key_propnameid = ly.properties_repository ().prop_name_id (p->first);
|
||||
propset.insert (std::make_pair (key_propnameid, p->second));
|
||||
}
|
||||
|
||||
if (! netname_prop.is_nil ()) {
|
||||
db::property_names_id_type name_propnameid = ly.properties_repository ().prop_name_id (netname_prop);
|
||||
propset.insert (std::make_pair (name_propnameid, tl::Variant (net.expanded_name ())));
|
||||
}
|
||||
|
||||
return ly.properties_repository ().properties_id (propset);
|
||||
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
builder.build_nets (0, lmap, net_prop_mode, netname_prop);
|
||||
}
|
||||
|
||||
void
|
||||
LayoutToNetlist::build_net (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, const tl::Variant &netname_prop, BuildNetHierarchyMode hier_mode, const char *cell_name_prefix, const char *device_cell_name_prefix) const
|
||||
LayoutToNetlist::build_nets (const std::vector<const db::Net *> *nets, const db::CellMapping &cmap, db::Layout &target, const std::map<unsigned int, const db::Region *> &lmap, const char *net_cell_name_prefix, NetPropertyMode net_prop_mode, const tl::Variant &netname_prop, BuildNetHierarchyMode hier_mode, const char *circuit_cell_name_prefix, const char *device_cell_name_prefix) const
|
||||
{
|
||||
if (! m_netlist_extracted) {
|
||||
throw tl::Exception (tl::to_string (tr ("The netlist has not been extracted yet")));
|
||||
}
|
||||
NetBuilder builder (&target, cmap, this);
|
||||
builder.set_hier_mode (hier_mode);
|
||||
builder.set_net_cell_name_prefix (net_cell_name_prefix);
|
||||
builder.set_cell_name_prefix (circuit_cell_name_prefix);
|
||||
builder.set_device_cell_name_prefix (device_cell_name_prefix);
|
||||
|
||||
cell_reuse_table_type cell_reuse_table;
|
||||
|
||||
double mag = internal_layout ()->dbu () / target.dbu ();
|
||||
|
||||
db::properties_id_type netname_propid = make_netname_propid (target, netname_prop, net);
|
||||
build_net_rec (net, target, target_cell, lmap, 0, netname_propid, hier_mode, cell_name_prefix, device_cell_name_prefix, cell_reuse_table, db::ICplxTrans (mag));
|
||||
}
|
||||
|
||||
void
|
||||
LayoutToNetlist::build_all_nets (const db::CellMapping &cmap, db::Layout &target, const std::map<unsigned int, const db::Region *> &lmap, const char *net_cell_name_prefix, const tl::Variant &netname_prop, BuildNetHierarchyMode hier_mode, const char *circuit_cell_name_prefix, const char *device_cell_name_prefix) const
|
||||
{
|
||||
build_nets (0, cmap, target, lmap, net_cell_name_prefix, netname_prop, hier_mode, circuit_cell_name_prefix, device_cell_name_prefix);
|
||||
}
|
||||
|
||||
void
|
||||
LayoutToNetlist::build_net_rec (const db::Net &net, db::Layout &target, db::cell_index_type circuit_cell, const db::CellMapping &cmap, const std::map<unsigned int, const db::Region *> &lmap, const char *net_cell_name_prefix, db::properties_id_type netname_propid, BuildNetHierarchyMode hier_mode, const char *cell_name_prefix, const char *device_cell_name_prefix, cell_reuse_table_type &reuse_table, const ICplxTrans &tr) const
|
||||
{
|
||||
if (! cmap.has_mapping (circuit_cell)) {
|
||||
|
||||
const db::Cell &cc = internal_layout ()->cell (circuit_cell);
|
||||
|
||||
for (db::Cell::parent_inst_iterator p = cc.begin_parent_insts (); ! p.at_end (); ++p) {
|
||||
|
||||
db::CellInstArray ci = p->child_inst ().cell_inst ();
|
||||
for (db::CellInstArray::iterator ia = ci.begin (); ! ia.at_end(); ++ia) {
|
||||
|
||||
db::ICplxTrans tr_parent = ci.complex_trans (*ia) * tr;
|
||||
build_net_rec (net, target, p->parent_cell_index (), cmap, lmap, net_cell_name_prefix, netname_propid, hier_mode, cell_name_prefix, device_cell_name_prefix, reuse_table, tr_parent);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
double mag = internal_layout ()->dbu () / target.dbu ();
|
||||
|
||||
db::cell_index_type target_ci = cmap.cell_mapping (circuit_cell);
|
||||
build_net_rec (net, target, target.cell (target_ci), lmap, net_cell_name_prefix, netname_propid, hier_mode, cell_name_prefix, device_cell_name_prefix, reuse_table, db::ICplxTrans (mag) * tr);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LayoutToNetlist::build_nets (const std::vector<const db::Net *> *nets, const db::CellMapping &cmap, db::Layout &target, const std::map<unsigned int, const db::Region *> &lmap, const char *net_cell_name_prefix, const tl::Variant &netname_prop, BuildNetHierarchyMode hier_mode, const char *circuit_cell_name_prefix, const char *device_cell_name_prefix) const
|
||||
{
|
||||
if (! m_netlist_extracted) {
|
||||
throw tl::Exception (tl::to_string (tr ("The netlist has not been extracted yet")));
|
||||
}
|
||||
|
||||
std::set<const db::Net *> net_set;
|
||||
if (nets) {
|
||||
net_set.insert (nets->begin (), nets->end ());
|
||||
}
|
||||
|
||||
cell_reuse_table_type cell_reuse_table;
|
||||
|
||||
const db::Netlist *netlist = mp_netlist.get ();
|
||||
for (db::Netlist::const_circuit_iterator c = netlist->begin_circuits (); c != netlist->end_circuits (); ++c) {
|
||||
|
||||
bool is_top_circuit = c->begin_parents () == c->end_parents ();
|
||||
|
||||
for (db::Circuit::const_net_iterator n = c->begin_nets (); n != c->end_nets (); ++n) {
|
||||
|
||||
// exclude local nets in recursive mode except if they are explicitly selected
|
||||
if (! nets && hier_mode != BNH_Disconnected && ! is_top_circuit && n->pin_count () > 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! nets || net_set.find (n.operator-> ()) != net_set.end ()) {
|
||||
db::properties_id_type netname_propid = make_netname_propid (target, netname_prop, *n);
|
||||
build_net_rec (*n, target, c->cell_index (), cmap, lmap, net_cell_name_prefix, netname_propid, hier_mode, circuit_cell_name_prefix, device_cell_name_prefix, cell_reuse_table, db::ICplxTrans ());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (hier_mode != BNH_Disconnected && ! nets) {
|
||||
|
||||
// With recursive nets we skip nets in subcircuits which are connected upwards. This means, nets will
|
||||
// get lost if there is no connection to this pin from the outside. Hence we need to deliver nets from
|
||||
// subcircuits as part of the circuit which calls the subcircuit - but NOT in a subcircuit cell, because
|
||||
// this will just apply to nets from certain instances. But the net cell name will be formed as "subcircuit:net"
|
||||
//
|
||||
// In explicit selection mode we don't care about this as nets are explicitly taken or not.
|
||||
|
||||
const db::Circuit &circuit = *c;
|
||||
for (db::Circuit::const_subcircuit_iterator sc = circuit.begin_subcircuits (); sc != circuit.end_subcircuits (); ++sc) {
|
||||
|
||||
const db::SubCircuit &subcircuit = *sc;
|
||||
for (db::Circuit::const_pin_iterator p = subcircuit.circuit_ref ()->begin_pins (); p != subcircuit.circuit_ref ()->end_pins (); ++p) {
|
||||
|
||||
if (! subcircuit.net_for_pin (p->id ())) {
|
||||
|
||||
const db::Net *n = subcircuit.circuit_ref ()->net_for_pin (p->id ());
|
||||
if (n) {
|
||||
|
||||
double dbu = target.dbu ();
|
||||
db::ICplxTrans tr = db::CplxTrans (dbu).inverted () * subcircuit.trans () * db::CplxTrans (dbu);
|
||||
|
||||
db::properties_id_type netname_propid = make_netname_propid (target, netname_prop, *n);
|
||||
|
||||
if (net_cell_name_prefix) {
|
||||
std::string ncn = std::string (net_cell_name_prefix) + subcircuit.expanded_name () + ":";
|
||||
build_net_rec (*n, target, c->cell_index (), cmap, lmap, ncn.c_str (), netname_propid, hier_mode, circuit_cell_name_prefix, device_cell_name_prefix, cell_reuse_table, tr);
|
||||
} else {
|
||||
build_net_rec (*n, target, c->cell_index (), cmap, lmap, net_cell_name_prefix, netname_propid, hier_mode, circuit_cell_name_prefix, device_cell_name_prefix, cell_reuse_table, tr);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
builder.build_nets (nets, lmap, net_prop_mode, netname_prop);
|
||||
}
|
||||
|
||||
db::Net *LayoutToNetlist::probe_net (const db::Region &of_region, const db::DPoint &point, std::vector<db::SubCircuit *> *sc_path_out, db::Circuit *initial_circuit)
|
||||
|
|
@ -1692,4 +1498,400 @@ void LayoutToNetlist::set_generator (const std::string &g)
|
|||
m_generator = g;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
// NetBuilder implementation
|
||||
|
||||
NetBuilder::NetBuilder ()
|
||||
: m_hier_mode (BNH_Flatten), m_has_net_cell_name_prefix (false), m_has_cell_name_prefix (false), m_has_device_cell_name_prefix (false)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
NetBuilder::NetBuilder (db::Layout *target, const db::CellMapping &cmap, const db::LayoutToNetlist *source)
|
||||
: mp_target (target), m_cmap (cmap), mp_source (const_cast <db::LayoutToNetlist *> (source)),
|
||||
m_hier_mode (BNH_Flatten), m_has_net_cell_name_prefix (false), m_has_cell_name_prefix (false), m_has_device_cell_name_prefix (false)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
NetBuilder::NetBuilder (db::Layout *target, const db::LayoutToNetlist *source)
|
||||
: mp_target (target), mp_source (const_cast <db::LayoutToNetlist *> (source)),
|
||||
m_hier_mode (BNH_Flatten), m_has_net_cell_name_prefix (false), m_has_cell_name_prefix (false), m_has_device_cell_name_prefix (false)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
NetBuilder::NetBuilder (const db::NetBuilder &other)
|
||||
{
|
||||
operator=(other);
|
||||
}
|
||||
|
||||
NetBuilder::NetBuilder (db::NetBuilder &&other)
|
||||
{
|
||||
operator=(other);
|
||||
}
|
||||
|
||||
NetBuilder &
|
||||
NetBuilder::operator= (const db::NetBuilder &other)
|
||||
{
|
||||
if (this != &other) {
|
||||
mp_target = other.mp_target;
|
||||
mp_source = other.mp_source;
|
||||
m_cmap = other.m_cmap;
|
||||
m_reuse_table = other.m_reuse_table;
|
||||
m_hier_mode = other.m_hier_mode;
|
||||
m_has_net_cell_name_prefix = other.m_has_net_cell_name_prefix;
|
||||
m_net_cell_name_prefix = other.m_net_cell_name_prefix;
|
||||
m_has_cell_name_prefix = other.m_has_cell_name_prefix;
|
||||
m_cell_name_prefix = other.m_cell_name_prefix;
|
||||
m_has_device_cell_name_prefix = other.m_has_device_cell_name_prefix;
|
||||
m_device_cell_name_prefix = other.m_device_cell_name_prefix;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
NetBuilder &
|
||||
NetBuilder::operator= (db::NetBuilder &&other)
|
||||
{
|
||||
if (this != &other) {
|
||||
mp_target = other.mp_target;
|
||||
other.mp_target.reset (0);
|
||||
mp_source = other.mp_source;
|
||||
other.mp_source.reset (0);
|
||||
m_cmap.swap (other.m_cmap);
|
||||
m_reuse_table.swap (other.m_reuse_table);
|
||||
std::swap (m_hier_mode, other.m_hier_mode);
|
||||
std::swap (m_has_net_cell_name_prefix, other.m_has_net_cell_name_prefix);
|
||||
m_net_cell_name_prefix.swap (other.m_net_cell_name_prefix);
|
||||
std::swap (m_has_cell_name_prefix, other.m_has_cell_name_prefix);
|
||||
m_cell_name_prefix.swap (other.m_cell_name_prefix);
|
||||
std::swap (m_has_device_cell_name_prefix, other.m_has_device_cell_name_prefix);
|
||||
m_device_cell_name_prefix.swap (other.m_device_cell_name_prefix);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void
|
||||
NetBuilder::set_net_cell_name_prefix (const char *s)
|
||||
{
|
||||
m_has_net_cell_name_prefix = (s != 0);
|
||||
m_net_cell_name_prefix = std::string (s ? s : "");
|
||||
}
|
||||
|
||||
void
|
||||
NetBuilder::set_cell_name_prefix (const char *s)
|
||||
{
|
||||
bool has_cell_name_prefix = (s != 0);
|
||||
std::string cell_name_prefix (s ? s : "");
|
||||
|
||||
if (has_cell_name_prefix != m_has_cell_name_prefix || cell_name_prefix != m_cell_name_prefix) {
|
||||
m_reuse_table.clear ();
|
||||
m_has_cell_name_prefix = has_cell_name_prefix;
|
||||
m_cell_name_prefix = cell_name_prefix;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NetBuilder::set_device_cell_name_prefix (const char *s)
|
||||
{
|
||||
bool has_device_cell_name_prefix = (s != 0);
|
||||
std::string device_cell_name_prefix (s ? s : "");
|
||||
|
||||
if (has_device_cell_name_prefix != m_has_device_cell_name_prefix || device_cell_name_prefix != m_device_cell_name_prefix) {
|
||||
m_reuse_table.clear ();
|
||||
m_has_device_cell_name_prefix = has_device_cell_name_prefix;
|
||||
m_device_cell_name_prefix = device_cell_name_prefix;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NetBuilder::prepare_build_nets () const
|
||||
{
|
||||
tl_assert (mp_target.get ());
|
||||
tl_assert (mp_source.get ());
|
||||
|
||||
if (! mp_source->is_netlist_extracted ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("The netlist has not been extracted yet")));
|
||||
}
|
||||
|
||||
// Resets the "initialized" flag so existing cells are reused but freshly filled
|
||||
for (auto i = m_reuse_table.begin (); i != m_reuse_table.end (); ++i) {
|
||||
i->second.second = false;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NetBuilder::build_net (db::Cell &target_cell, const db::Net &net, const std::map<unsigned int, const db::Region *> &lmap, NetPropertyMode net_prop_mode, const tl::Variant &netname_prop) const
|
||||
{
|
||||
prepare_build_nets ();
|
||||
|
||||
double mag = mp_source->internal_layout ()->dbu () / mp_target->dbu ();
|
||||
|
||||
db::properties_id_type netname_propid = make_netname_propid (target ().properties_repository (), net_prop_mode, netname_prop, net);
|
||||
build_net_rec (net, target_cell, lmap, std::string (), netname_propid, db::ICplxTrans (mag));
|
||||
}
|
||||
|
||||
void
|
||||
NetBuilder::build_all_nets (const std::map<unsigned int, const db::Region *> &lmap, NetPropertyMode net_prop_mode, const tl::Variant &netname_prop) const
|
||||
{
|
||||
build_nets (0, lmap, net_prop_mode, netname_prop);
|
||||
}
|
||||
|
||||
void
|
||||
NetBuilder::build_nets (const std::vector<const Net *> *nets, const std::map<unsigned int, const db::Region *> &lmap, NetPropertyMode prop_mode, const tl::Variant &netname_prop) const
|
||||
{
|
||||
prepare_build_nets ();
|
||||
|
||||
std::set<const db::Net *> net_set;
|
||||
if (nets) {
|
||||
net_set.insert (nets->begin (), nets->end ());
|
||||
}
|
||||
|
||||
const db::Netlist *netlist = mp_source->netlist ();
|
||||
for (db::Netlist::const_circuit_iterator c = netlist->begin_circuits (); c != netlist->end_circuits (); ++c) {
|
||||
|
||||
bool is_top_circuit = c->begin_parents () == c->end_parents ();
|
||||
|
||||
for (db::Circuit::const_net_iterator n = c->begin_nets (); n != c->end_nets (); ++n) {
|
||||
|
||||
// exclude local nets in recursive mode except if they are explicitly selected
|
||||
if (! nets && m_hier_mode != BNH_Disconnected && ! is_top_circuit && n->pin_count () > 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! nets || net_set.find (n.operator-> ()) != net_set.end ()) {
|
||||
db::properties_id_type netname_propid = make_netname_propid (target ().properties_repository (), prop_mode, netname_prop, *n);
|
||||
build_net_rec (*n, c->cell_index (), lmap, std::string (), netname_propid, db::ICplxTrans ());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (m_hier_mode != BNH_Disconnected && ! nets) {
|
||||
|
||||
// With recursive nets we skip nets in subcircuits which are connected upwards. This means, nets will
|
||||
// get lost if there is no connection to this pin from the outside. Hence we need to deliver nets from
|
||||
// subcircuits as part of the circuit which calls the subcircuit - but NOT in a subcircuit cell, because
|
||||
// this will just apply to nets from certain instances. But the net cell name will be formed as "subcircuit:net"
|
||||
//
|
||||
// In explicit selection mode we don't care about this as nets are explicitly taken or not.
|
||||
|
||||
const db::Circuit &circuit = *c;
|
||||
for (db::Circuit::const_subcircuit_iterator sc = circuit.begin_subcircuits (); sc != circuit.end_subcircuits (); ++sc) {
|
||||
|
||||
const db::SubCircuit &subcircuit = *sc;
|
||||
for (db::Circuit::const_pin_iterator p = subcircuit.circuit_ref ()->begin_pins (); p != subcircuit.circuit_ref ()->end_pins (); ++p) {
|
||||
|
||||
if (! subcircuit.net_for_pin (p->id ())) {
|
||||
|
||||
const db::Net *n = subcircuit.circuit_ref ()->net_for_pin (p->id ());
|
||||
if (n) {
|
||||
|
||||
double dbu = mp_target->dbu ();
|
||||
db::ICplxTrans tr = db::CplxTrans (dbu).inverted () * subcircuit.trans () * db::CplxTrans (dbu);
|
||||
|
||||
std::string net_name_prefix = subcircuit.expanded_name () + ":";
|
||||
db::properties_id_type netname_propid = make_netname_propid (target ().properties_repository (), prop_mode, netname_prop, *n, net_name_prefix);
|
||||
|
||||
build_net_rec (*n, c->cell_index (), lmap, net_name_prefix, netname_propid, tr);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NetBuilder::build_net_rec (const db::Net &net, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, const std::string &add_net_cell_name_prefix, db::properties_id_type netname_propid, const db::ICplxTrans &tr) const
|
||||
{
|
||||
const db::Circuit *circuit = net.circuit ();
|
||||
tl_assert (circuit != 0);
|
||||
|
||||
build_net_rec (circuit->cell_index (), net.cluster_id (), target_cell, lmap, &net, add_net_cell_name_prefix, netname_propid, tr);
|
||||
}
|
||||
|
||||
void
|
||||
NetBuilder::build_net_rec (db::cell_index_type ci, size_t cid, db::Cell &tc, const std::map<unsigned int, const db::Region *> &lmap, const db::Net *net, const std::string &add_net_cell_name_prefix, db::properties_id_type netname_propid, const db::ICplxTrans &tr) const
|
||||
{
|
||||
db::Cell *target_cell = &tc;
|
||||
|
||||
if (net && m_has_net_cell_name_prefix) {
|
||||
|
||||
const db::connected_clusters<db::NetShape> &ccl = mp_source->net_clusters ().clusters_per_cell (ci);
|
||||
|
||||
bool any_connections = m_has_cell_name_prefix && ! ccl.connections_for_cluster (cid).empty ();
|
||||
if (! any_connections) {
|
||||
|
||||
StopOnFirst sof;
|
||||
std::map<unsigned int, StopOnFirst *> sof_lmap;
|
||||
for (std::map<unsigned int, const db::Region *>::const_iterator l = lmap.begin (); l != lmap.end (); ++l) {
|
||||
if (l->second) {
|
||||
sof_lmap.insert (std::make_pair (mp_source->layer_of (*l->second), &sof));
|
||||
}
|
||||
}
|
||||
|
||||
bool consider_cell = ! deliver_shapes_of_net (m_hier_mode == BNH_Flatten, mp_source->netlist (), mp_source->net_clusters (), ci, cid, sof_lmap, tr, 0);
|
||||
if (! consider_cell) {
|
||||
// shortcut if cell is empty -> no net cell will be produced
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// make a specific cell for the net if requested
|
||||
|
||||
target_cell = &target ().cell (target ().add_cell ((m_net_cell_name_prefix + add_net_cell_name_prefix + net->expanded_name ()).c_str ()));
|
||||
tc.insert (db::CellInstArray (db::CellInst (target_cell->cell_index ()), db::Trans ()));
|
||||
|
||||
}
|
||||
|
||||
std::map<unsigned int, db::Shapes *> target_lmap;
|
||||
for (std::map<unsigned int, const db::Region *>::const_iterator l = lmap.begin (); l != lmap.end (); ++l) {
|
||||
if (l->second) {
|
||||
target_lmap.insert (std::make_pair (mp_source->layer_of (*l->second), &target_cell->shapes (l->first)));
|
||||
}
|
||||
}
|
||||
|
||||
deliver_shapes_of_net (m_hier_mode == BNH_Flatten, mp_source->netlist (), mp_source->net_clusters (), ci, cid, target_lmap, tr, netname_propid);
|
||||
|
||||
if (m_hier_mode != BNH_SubcircuitCells && ! m_has_device_cell_name_prefix) {
|
||||
return;
|
||||
}
|
||||
|
||||
// NOTE: we propagate the magnification part of tr down, but keep the rotation/translation part in the instance
|
||||
// (we want to avoid magnified instances)
|
||||
db::ICplxTrans tr_wo_mag = tr * db::ICplxTrans (1.0 / tr.mag ());
|
||||
db::ICplxTrans tr_mag (tr.mag ());
|
||||
|
||||
const db::connected_clusters<db::NetShape> &clusters = mp_source->net_clusters ().clusters_per_cell (ci);
|
||||
typedef db::connected_clusters<db::NetShape>::connections_type connections_type;
|
||||
const connections_type &connections = clusters.connections_for_cluster (cid);
|
||||
for (connections_type::const_iterator c = connections.begin (); c != connections.end (); ++c) {
|
||||
|
||||
db::cell_index_type subci = c->inst_cell_index ();
|
||||
size_t subcid = c->id ();
|
||||
|
||||
CellReuseTableKey cmap_key (subci, netname_propid, subcid);
|
||||
|
||||
cell_reuse_table_type::iterator cm = m_reuse_table.find (cmap_key);
|
||||
if (cm == m_reuse_table.end ()) {
|
||||
|
||||
bool has_name_prefix = false;
|
||||
std::string name_prefix;
|
||||
if (mp_source->netlist ()->device_abstract_by_cell_index (subci)) {
|
||||
name_prefix = m_device_cell_name_prefix;
|
||||
has_name_prefix = m_has_device_cell_name_prefix;
|
||||
} else {
|
||||
name_prefix = m_cell_name_prefix;
|
||||
has_name_prefix = m_has_cell_name_prefix;
|
||||
}
|
||||
|
||||
if (has_name_prefix) {
|
||||
|
||||
std::string cell_name = mp_source->internal_layout ()->cell_name (subci);
|
||||
|
||||
db::cell_index_type target_ci = target ().add_cell ((name_prefix + cell_name).c_str ());
|
||||
cm = m_reuse_table.insert (std::make_pair (cmap_key, std::make_pair (target_ci, true))).first;
|
||||
|
||||
build_net_rec (subci, subcid, target ().cell (target_ci), lmap, 0, std::string (), netname_propid, tr_mag);
|
||||
|
||||
} else {
|
||||
cm = m_reuse_table.insert (std::make_pair (cmap_key, std::make_pair (std::numeric_limits<db::cell_index_type>::max (), false))).first;
|
||||
}
|
||||
|
||||
} else if (!cm->second.second && cm->second.first != std::numeric_limits<db::cell_index_type>::max ()) {
|
||||
|
||||
// initialize cell (after reuse of the net builder)
|
||||
build_net_rec (subci, subcid, target ().cell (cm->second.first), lmap, 0, std::string (), netname_propid, tr_mag);
|
||||
cm->second.second = true;
|
||||
|
||||
}
|
||||
|
||||
if (cm->second.first != std::numeric_limits<db::cell_index_type>::max ()) {
|
||||
db::CellInstArray ci (db::CellInst (cm->second.first), tr_wo_mag * c->inst_trans ());
|
||||
ci.transform_into (tr_mag);
|
||||
target_cell->insert (ci);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NetBuilder::build_net_rec (const db::Net &net, db::cell_index_type circuit_cell, const std::map<unsigned int, const db::Region *> &lmap, const std::string &add_net_cell_name_prefix, db::properties_id_type netname_propid, const ICplxTrans &tr) const
|
||||
{
|
||||
if (! m_cmap.has_mapping (circuit_cell)) {
|
||||
|
||||
const db::Cell &cc = mp_source->internal_layout ()->cell (circuit_cell);
|
||||
|
||||
for (db::Cell::parent_inst_iterator p = cc.begin_parent_insts (); ! p.at_end (); ++p) {
|
||||
|
||||
db::CellInstArray ci = p->child_inst ().cell_inst ();
|
||||
for (db::CellInstArray::iterator ia = ci.begin (); ! ia.at_end(); ++ia) {
|
||||
|
||||
db::ICplxTrans tr_parent = ci.complex_trans (*ia) * tr;
|
||||
build_net_rec (net, p->parent_cell_index (), lmap, add_net_cell_name_prefix, netname_propid, tr_parent);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
double mag = mp_source->internal_layout ()->dbu () / mp_target->dbu ();
|
||||
|
||||
db::cell_index_type target_ci = m_cmap.cell_mapping (circuit_cell);
|
||||
build_net_rec (net, target ().cell (target_ci), lmap, add_net_cell_name_prefix, netname_propid, db::ICplxTrans (mag) * tr);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
db::properties_id_type
|
||||
NetBuilder::make_netname_propid (db::PropertiesRepository &pr, NetPropertyMode net_prop_mode, const tl::Variant &netname_prop, const db::Net &net, const std::string &net_name_prefix)
|
||||
{
|
||||
if (net_prop_mode == NPM_NoProperties) {
|
||||
|
||||
return 0;
|
||||
|
||||
} else if (! netname_prop.is_nil () || (net_prop_mode == NPM_AllProperties && net.begin_properties () != net.end_properties ())) {
|
||||
|
||||
db::PropertiesRepository::properties_set propset;
|
||||
|
||||
// add the user properties too (TODO: make this configurable?)
|
||||
for (db::Net::property_iterator p = net.begin_properties (); p != net.end_properties (); ++p) {
|
||||
db::property_names_id_type key_propnameid = pr.prop_name_id (p->first);
|
||||
propset.insert (std::make_pair (key_propnameid, p->second));
|
||||
}
|
||||
|
||||
if (! netname_prop.is_nil ()) {
|
||||
db::property_names_id_type name_propnameid = pr.prop_name_id (netname_prop);
|
||||
if (net_prop_mode == NPM_NetQualifiedNameOnly) {
|
||||
std::vector<tl::Variant> l;
|
||||
l.reserve (2);
|
||||
l.push_back (tl::Variant (net_name_prefix + net.expanded_name ()));
|
||||
l.push_back (tl::Variant (net.circuit ()->name ()));
|
||||
propset.insert (std::make_pair (name_propnameid, tl::Variant (l)));
|
||||
} else if (net_prop_mode == NPM_NetIDOnly) {
|
||||
propset.insert (std::make_pair (name_propnameid, tl::Variant (reinterpret_cast <size_t> (&net))));
|
||||
} else {
|
||||
propset.insert (std::make_pair (name_propnameid, tl::Variant (net_name_prefix + net.expanded_name ())));
|
||||
}
|
||||
}
|
||||
|
||||
return pr.properties_id (propset);
|
||||
|
||||
} else {
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,11 +27,14 @@
|
|||
#include "dbCellMapping.h"
|
||||
#include "dbNetlistExtractor.h"
|
||||
#include "dbNetlistDeviceExtractor.h"
|
||||
#include "dbLayoutToNetlistEnums.h"
|
||||
#include "tlGlobPattern.h"
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
||||
class NetlistBuilder;
|
||||
|
||||
/**
|
||||
* @brief A generic framework for extracting netlists from layouts
|
||||
*
|
||||
|
|
@ -234,14 +237,22 @@ public:
|
|||
double device_scaling () const;
|
||||
|
||||
/**
|
||||
* @brief Register a layer under the given name
|
||||
* This is a formal name for the layer. Using a name or layer properties
|
||||
* (see below) enhances readability of backannotated information
|
||||
* @brief Register a layer, optionally under the given name
|
||||
* Using a name or layer properties (see below) enhances readability of backannotated information
|
||||
* if layers are involved. Use this method to attach a name to a region
|
||||
* derived by boolean operations for example.
|
||||
* Named regions are persisted inside the LayoutToNetlist object.
|
||||
*
|
||||
* Registered regions are persisted inside the LayoutToNetlist object
|
||||
* if they are flat or original layer regions.
|
||||
* This allows passing flat or original layer collections.
|
||||
*
|
||||
* If no name is given, the region will not be registered under a name.
|
||||
* Still the collection will be persisted if required.
|
||||
*
|
||||
* In addition to regions, text collections can be registered too.
|
||||
* Including texts in "connect" makes net names begin assigned from the text strings.
|
||||
*/
|
||||
void register_layer (const ShapeCollection &collection, const std::string &name);
|
||||
void register_layer (const ShapeCollection &collection, const std::string &name = std::string ());
|
||||
|
||||
/**
|
||||
* @brief Gets the name of the given collection
|
||||
|
|
@ -276,7 +287,7 @@ public:
|
|||
template <class Collection>
|
||||
bool is_persisted (const Collection &coll) const
|
||||
{
|
||||
return m_name_of_layer.find (layer_of (coll)) != m_name_of_layer.end ();
|
||||
return is_persisted_impl (coll);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -297,6 +308,20 @@ public:
|
|||
*/
|
||||
db::Region *layer_by_index (unsigned int index);
|
||||
|
||||
/**
|
||||
* @brief Gets the internal layer from the original layer
|
||||
*/
|
||||
db::Region *layer_by_original (const ShapeCollection &original_layer)
|
||||
{
|
||||
return layer_by_original (original_layer.get_delegate ());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the layer from the original layer's delegate
|
||||
* Returns 0 if the original layer was not registered as an input_layer.
|
||||
*/
|
||||
db::Region *layer_by_original (const ShapeCollectionDelegateBase *original_delegate);
|
||||
|
||||
/**
|
||||
* @brief Iterates over the layer indexes and names managed by this object (begin)
|
||||
*/
|
||||
|
|
@ -688,7 +713,7 @@ public:
|
|||
* This methods returns a new'd Region. It's the responsibility of the caller
|
||||
* to delete this object.
|
||||
*/
|
||||
db::Region *shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive) const;
|
||||
db::Region *shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive, const db::ICplxTrans &trans = db::ICplxTrans ()) const;
|
||||
|
||||
/**
|
||||
* @brief Delivers all shapes of a specific net and layer to the given Shapes container.
|
||||
|
|
@ -701,30 +726,7 @@ public:
|
|||
*
|
||||
* propid is an optional properties ID which is attached to the shapes if not 0.
|
||||
*/
|
||||
void shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive, db::Shapes &to, properties_id_type propid = 0) const;
|
||||
|
||||
/**
|
||||
* @brief An enum describing the way the net hierarchy is mapped
|
||||
*/
|
||||
enum BuildNetHierarchyMode
|
||||
{
|
||||
/**
|
||||
* @brief Flatten the net
|
||||
* Collects all shapes of a net and puts that into the net cell or circuit cell
|
||||
*/
|
||||
BNH_Flatten = 0,
|
||||
/**
|
||||
* @brief Build a net hierarchy adding cells for each subcircuit on the net
|
||||
* Uses the circuit_cell_prefix to build the subcircuit cell names
|
||||
*/
|
||||
BNH_SubcircuitCells = 1,
|
||||
/**
|
||||
* @brief No hierarchy
|
||||
* Just output the shapes of the net belonging to the circuit cell.
|
||||
* Connections are not indicated!
|
||||
*/
|
||||
BNH_Disconnected = 2
|
||||
};
|
||||
void shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive, db::Shapes &to, properties_id_type propid = 0, const db::ICplxTrans &trans = db::ICplxTrans ()) const;
|
||||
|
||||
/**
|
||||
* @brief Builds a net representation in the given layout and cell
|
||||
|
|
@ -747,15 +749,17 @@ public:
|
|||
* using a name like device_cell_name_prefix + device name. Otherwise the device shapes are
|
||||
* treated as part of the net.
|
||||
*
|
||||
* @param net The net to build
|
||||
* @param target The target layout
|
||||
* @param target_cell The target cell
|
||||
* @param lmap Target layer indexes (keys) and net regions (values)
|
||||
* @param hier_mode See description of this method
|
||||
* @param net_prop_mode How to attach properties to shapes
|
||||
* @param netname_prop An (optional) property name to which to attach the net name
|
||||
* @param cell_name_prefix Chooses recursive mode if non-null
|
||||
* @param device_cell_name_prefix See above
|
||||
*/
|
||||
void build_net (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, const tl::Variant &netname_prop, BuildNetHierarchyMode hier_mode, const char *cell_name_prefix, const char *device_cell_name_prefix) const;
|
||||
void build_net (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, NetPropertyMode prop_mode, const tl::Variant &netname_prop, BuildNetHierarchyMode hier_mode, const char *cell_name_prefix, const char *device_cell_name_prefix) const;
|
||||
|
||||
/**
|
||||
* @brief Builds a full hierarchical representation of the nets
|
||||
|
|
@ -788,18 +792,19 @@ public:
|
|||
* @param cmap The mapping of internal layout to target layout for the circuit mapping
|
||||
* @param target The target layout
|
||||
* @param lmap Target layer indexes (keys) and net regions (values)
|
||||
* @param hier_mode See description of this method
|
||||
* @param netname_prop An (optional) property name to which to attach the net name
|
||||
* @param circuit_cell_name_prefix See method description
|
||||
* @param net_cell_name_prefix See method description
|
||||
* @param net_prop_mode How to attach properties to shapes
|
||||
* @param netname_prop The property key to use for the net name or "nil" for no netname properties
|
||||
* @param hier_mode See description of this method
|
||||
* @param circuit_cell_name_prefix See method description
|
||||
* @param device_cell_name_prefix See above
|
||||
*/
|
||||
void build_all_nets (const db::CellMapping &cmap, db::Layout &target, const std::map<unsigned int, const db::Region *> &lmap, const char *net_cell_name_prefix, const tl::Variant &netname_prop, BuildNetHierarchyMode hier_mode, const char *circuit_cell_name_prefix, const char *device_cell_name_prefix) const;
|
||||
void build_all_nets (const db::CellMapping &cmap, db::Layout &target, const std::map<unsigned int, const db::Region *> &lmap, const char *net_cell_name_prefix, NetPropertyMode prop_mode, const tl::Variant &netname_prop, BuildNetHierarchyMode hier_mode, const char *circuit_cell_name_prefix, const char *device_cell_name_prefix) const;
|
||||
|
||||
/**
|
||||
* @brief Like build_all_nets, but with the ability to select some nets
|
||||
*/
|
||||
void build_nets (const std::vector<const Net *> *nets, const db::CellMapping &cmap, db::Layout &target, const std::map<unsigned int, const db::Region *> &lmap, const char *net_cell_name_prefix, const tl::Variant &netname_prop, BuildNetHierarchyMode hier_mode, const char *circuit_cell_name_prefix, const char *device_cell_name_prefix) const;
|
||||
void build_nets (const std::vector<const Net *> *nets, const db::CellMapping &cmap, db::Layout &target, const std::map<unsigned int, const db::Region *> &lmap, const char *net_cell_name_prefix, NetPropertyMode prop_mode, const tl::Variant &netname_prop, BuildNetHierarchyMode hier_mode, const char *circuit_cell_name_prefix, const char *device_cell_name_prefix) const;
|
||||
|
||||
/**
|
||||
* @brief Finds the net by probing a specific location on the given layer
|
||||
|
|
@ -935,6 +940,8 @@ private:
|
|||
std::set<db::DeepLayer> m_dlrefs;
|
||||
std::map<std::string, db::DeepLayer> m_named_regions;
|
||||
std::map<unsigned int, std::string> m_name_of_layer;
|
||||
std::map<tl::id_type, db::DeepLayer> m_region_by_original;
|
||||
std::map<unsigned int, db::DeepLayer> m_region_of_layer;
|
||||
bool m_netlist_extracted;
|
||||
bool m_is_flat;
|
||||
double m_device_scaling;
|
||||
|
|
@ -946,6 +953,127 @@ private:
|
|||
std::list<std::set<std::string> > m_joined_nets;
|
||||
std::list<std::pair<tl::GlobPattern, std::set<std::string> > > m_joined_nets_per_cell;
|
||||
|
||||
void init ();
|
||||
void ensure_netlist ();
|
||||
size_t search_net (const db::ICplxTrans &trans, const db::Cell *cell, const db::local_cluster<NetShape> &test_cluster, std::vector<db::InstElement> &rev_inst_path);
|
||||
db::DeepLayer deep_layer_of (const ShapeCollection &coll) const;
|
||||
void ensure_layout () const;
|
||||
std::string make_new_name (const std::string &stem = std::string ());
|
||||
db::CellMapping make_cell_mapping_into (db::Layout &layout, db::Cell &cell, const std::vector<const db::Net *> *nets, bool with_device_cells);
|
||||
void connect_impl (const db::ShapeCollection &a, const db::ShapeCollection &b);
|
||||
size_t connect_global_impl (const db::ShapeCollection &l, const std::string &gn);
|
||||
bool is_persisted_impl (const db::ShapeCollection &coll) const;
|
||||
|
||||
// implementation of NetlistManipulationCallbacks
|
||||
virtual size_t link_net_to_parent_circuit (const Net *subcircuit_net, Circuit *parent_circuit, const DCplxTrans &trans);
|
||||
virtual void link_nets (const db::Net *net, const db::Net *with);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief An object building nets (net-to-layout)
|
||||
*
|
||||
* This object can be used to persist netlist builder information - e.g. reusing net cells when building individual
|
||||
* layers from nets. In this case, build nets with a layer selection and call the build_net function many times.
|
||||
*/
|
||||
|
||||
class DB_PUBLIC NetBuilder
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor
|
||||
*/
|
||||
NetBuilder ();
|
||||
|
||||
/**
|
||||
* @brief Constructs a net builder with a target layout, a cell mapping table and a LayoutToNetlist source
|
||||
*
|
||||
* @param target The target layout
|
||||
* @param cmap The cell mapping from the internal layout (inside LayoutToNetlist) to the target - use LayoutInfo::cell_mapping_into to generate this map
|
||||
* @param source The LayoutToNetlist source.
|
||||
*
|
||||
* A cell map needs to be supplied only if intending to build many nets in hierarchical mode from multiple circuits.
|
||||
*/
|
||||
NetBuilder (db::Layout *target, const db::CellMapping &cmap, const db::LayoutToNetlist *source);
|
||||
|
||||
/**
|
||||
* @brief Constructs a net builder with a source only
|
||||
*
|
||||
* @param source The LayoutToNetlist source.
|
||||
*
|
||||
* This net builder can be used to build single nets into dedicated target cells.
|
||||
*/
|
||||
NetBuilder (db::Layout *target, const db::LayoutToNetlist *source);
|
||||
|
||||
/**
|
||||
* @brief Copy constructor
|
||||
*/
|
||||
NetBuilder (const db::NetBuilder &other);
|
||||
|
||||
/**
|
||||
* @brief Move constructor
|
||||
*/
|
||||
NetBuilder (db::NetBuilder &&other);
|
||||
|
||||
/**
|
||||
* @brief Assignment
|
||||
*/
|
||||
NetBuilder &operator= (const db::NetBuilder &other);
|
||||
|
||||
/**
|
||||
* @brief Move
|
||||
*/
|
||||
NetBuilder &operator= (db::NetBuilder &&other);
|
||||
|
||||
/**
|
||||
* @brief Sets the net-to-hierarchy generation mode
|
||||
*/
|
||||
void set_hier_mode (BuildNetHierarchyMode hm)
|
||||
{
|
||||
m_hier_mode = hm;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets or resets the net cell name prefix
|
||||
*
|
||||
* Pass 0 to this string value to reset it.
|
||||
*/
|
||||
void set_net_cell_name_prefix (const char *s);
|
||||
|
||||
/**
|
||||
* @brief Sets or resets the circuit cell name prefix
|
||||
*
|
||||
* Pass 0 to this string value to reset it.
|
||||
*/
|
||||
void set_cell_name_prefix (const char *s);
|
||||
|
||||
/**
|
||||
* @brief Sets or resets the device cell name prefix
|
||||
*
|
||||
* Pass 0 to this string value to reset it.
|
||||
*/
|
||||
void set_device_cell_name_prefix (const char *s);
|
||||
|
||||
/**
|
||||
* @brief See \LayoutToNetlist for details of this function
|
||||
*/
|
||||
void build_net (db::Cell &target_cell, const db::Net &net, const std::map<unsigned int, const db::Region *> &lmap, NetPropertyMode prop_mode, const tl::Variant &netname_prop) const;
|
||||
|
||||
/**
|
||||
* @brief See \LayoutToNetlist for details of this function
|
||||
*/
|
||||
void build_all_nets (const std::map<unsigned int, const db::Region *> &lmap, NetPropertyMode prop_mode, const tl::Variant &netname_prop) const;
|
||||
|
||||
/**
|
||||
* @brief See \LayoutToNetlist for details of this function
|
||||
*/
|
||||
void build_nets (const std::vector<const Net *> *nets, const std::map<unsigned int, const db::Region *> &lmap, NetPropertyMode prop_mode, const tl::Variant &netname_prop) const;
|
||||
|
||||
/**
|
||||
* @brief A helper function to create a property ID for a given net, net property name and net property mode
|
||||
*/
|
||||
static db::properties_id_type make_netname_propid (db::PropertiesRepository &pr, NetPropertyMode net_prop_mode, const tl::Variant &netname_prop, const db::Net &net, const std::string &net_name_prefix = std::string ());
|
||||
|
||||
private:
|
||||
struct CellReuseTableKey
|
||||
{
|
||||
CellReuseTableKey (db::cell_index_type _cell_index, db::properties_id_type _netname_propid, size_t _cluster_id)
|
||||
|
|
@ -973,25 +1101,29 @@ private:
|
|||
size_t cluster_id;
|
||||
};
|
||||
|
||||
typedef std::map<CellReuseTableKey, db::cell_index_type> cell_reuse_table_type;
|
||||
typedef std::map<CellReuseTableKey, std::pair<db::cell_index_type, bool> > cell_reuse_table_type;
|
||||
|
||||
void init ();
|
||||
void ensure_netlist ();
|
||||
size_t search_net (const db::ICplxTrans &trans, const db::Cell *cell, const db::local_cluster<NetShape> &test_cluster, std::vector<db::InstElement> &rev_inst_path);
|
||||
void build_net_rec (const db::Net &net, db::Layout &target, cell_index_type circuit_cell, const db::CellMapping &cmap, const std::map<unsigned int, const db::Region *> &lmap, const char *net_cell_name_prefix, db::properties_id_type netname_propid, BuildNetHierarchyMode hier_mode, const char *cell_name_prefix, const char *device_cell_name_prefix, cell_reuse_table_type &reuse_table, const ICplxTrans &tr) const;
|
||||
void build_net_rec (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, const char *net_cell_name_prefix, db::properties_id_type netname_propid, BuildNetHierarchyMode hier_mode, const char *cell_name_prefix, const char *device_cell_name_prefix, cell_reuse_table_type &reuse_table, const ICplxTrans &tr) const;
|
||||
void build_net_rec (db::cell_index_type ci, size_t cid, db::Layout &target, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, const Net *net, const char *net_cell_name_prefix, db::properties_id_type netname_propid, BuildNetHierarchyMode hier_mode, const char *cell_name_prefix, const char *device_cell_name_prefix, cell_reuse_table_type &reuse_table, const ICplxTrans &tr) const;
|
||||
db::DeepLayer deep_layer_of (const ShapeCollection &coll) const;
|
||||
void ensure_layout () const;
|
||||
std::string make_new_name (const std::string &stem = std::string ());
|
||||
db::properties_id_type make_netname_propid (db::Layout &ly, const tl::Variant &netname_prop, const db::Net &net) const;
|
||||
db::CellMapping make_cell_mapping_into (db::Layout &layout, db::Cell &cell, const std::vector<const db::Net *> *nets, bool with_device_cells);
|
||||
void connect_impl (const db::ShapeCollection &a, const db::ShapeCollection &b);
|
||||
size_t connect_global_impl (const db::ShapeCollection &l, const std::string &gn);
|
||||
tl::weak_ptr<db::Layout> mp_target;
|
||||
db::CellMapping m_cmap;
|
||||
tl::weak_ptr<db::LayoutToNetlist> mp_source;
|
||||
mutable cell_reuse_table_type m_reuse_table;
|
||||
BuildNetHierarchyMode m_hier_mode;
|
||||
bool m_has_net_cell_name_prefix;
|
||||
std::string m_net_cell_name_prefix;
|
||||
bool m_has_cell_name_prefix;
|
||||
std::string m_cell_name_prefix;
|
||||
bool m_has_device_cell_name_prefix;
|
||||
std::string m_device_cell_name_prefix;
|
||||
|
||||
// implementation of NetlistManipulationCallbacks
|
||||
virtual size_t link_net_to_parent_circuit (const Net *subcircuit_net, Circuit *parent_circuit, const DCplxTrans &trans);
|
||||
virtual void link_nets (const db::Net *net, const db::Net *with);
|
||||
void build_net_rec (const db::Net &net, cell_index_type circuit_cell, const std::map<unsigned int, const db::Region *> &lmap, const std::string &add_net_cell_name_prefix, db::properties_id_type netname_propid, const ICplxTrans &tr) const;
|
||||
void build_net_rec (const db::Net &net, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, const std::string &add_net_cell_name_prefix, db::properties_id_type netname_propid, const ICplxTrans &tr) const;
|
||||
void build_net_rec (db::cell_index_type ci, size_t cid, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, const Net *net, const std::string &add_net_cell_name_prefix, db::properties_id_type netname_propid, const ICplxTrans &tr) const;
|
||||
void prepare_build_nets () const;
|
||||
|
||||
db::Layout &target () const
|
||||
{
|
||||
return const_cast<db::Layout &> (*mp_target);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -0,0 +1,85 @@
|
|||
|
||||
/*
|
||||
|
||||
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_dbLayoutToNetlistEnums
|
||||
#define _HDR_dbLayoutToNetlistEnums
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief An enum describing the way how net information is attached to shapes as properties in "build_nets"
|
||||
*/
|
||||
enum NetPropertyMode
|
||||
{
|
||||
/**
|
||||
* @brief Do no generate properties
|
||||
*/
|
||||
NPM_NoProperties,
|
||||
|
||||
/**
|
||||
* @brief Attach all net properties plus the net name (if a "netname_prop" is specified to "build_nets")
|
||||
*/
|
||||
NPM_AllProperties,
|
||||
|
||||
/**
|
||||
* @brief Attach net name only (if a "netname_prop" is specified to "build_nets")
|
||||
*/
|
||||
NPM_NetNameOnly,
|
||||
|
||||
/**
|
||||
* @brief Like NetNameOnly, but use a unique net ID (db::Net address actually) instead of name
|
||||
*/
|
||||
NPM_NetIDOnly,
|
||||
|
||||
/**
|
||||
* @brief Like NetNameOnly, but use a tuple of net and circuit name
|
||||
*/
|
||||
NPM_NetQualifiedNameOnly,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief An enum describing the way the net hierarchy is mapped
|
||||
*/
|
||||
enum BuildNetHierarchyMode
|
||||
{
|
||||
/**
|
||||
* @brief Flatten the net
|
||||
* Collects all shapes of a net and puts that into the net cell or circuit cell
|
||||
*/
|
||||
BNH_Flatten = 0,
|
||||
/**
|
||||
* @brief Build a net hierarchy adding cells for each subcircuit on the net
|
||||
* Uses the circuit_cell_prefix to build the subcircuit cell names
|
||||
*/
|
||||
BNH_SubcircuitCells = 1,
|
||||
/**
|
||||
* @brief No hierarchy
|
||||
* Just output the shapes of the net belonging to the circuit cell.
|
||||
* Connections are not indicated!
|
||||
*/
|
||||
BNH_Disconnected = 2
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -26,6 +26,7 @@
|
|||
#include "dbPolygonTools.h"
|
||||
#include "tlProgress.h"
|
||||
#include "tlTimer.h"
|
||||
#include "tlThreads.h"
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
|
@ -60,8 +61,14 @@ DirectLayerMapping::map_layer (const LayerProperties &lprops)
|
|||
// ------------------------------------------------------------------------------------
|
||||
// PropertyMapper implementation
|
||||
|
||||
PropertyMapper::PropertyMapper (db::Layout &target, const db::Layout &source)
|
||||
: mp_target (&target), mp_source (&source)
|
||||
PropertyMapper::PropertyMapper (db::Layout *target, const db::Layout *source)
|
||||
: mp_target (target ? &target->properties_repository () : 0), mp_source (source ? &source->properties_repository () : 0)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
PropertyMapper::PropertyMapper (db::PropertiesRepository *target, const db::PropertiesRepository *source)
|
||||
: mp_target (target), mp_source (source)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
|
@ -82,11 +89,24 @@ PropertyMapper::PropertyMapper ()
|
|||
* @brief Specify the source layout
|
||||
*/
|
||||
void
|
||||
PropertyMapper::set_source (const db::Layout &source)
|
||||
PropertyMapper::set_source (const db::Layout *source)
|
||||
{
|
||||
if (&source != mp_source) {
|
||||
const db::PropertiesRepository *pr = source ? &source->properties_repository () : 0;
|
||||
if (pr != mp_source) {
|
||||
m_prop_id_map.clear ();
|
||||
mp_source = &source;
|
||||
mp_source = pr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Specify the source property repository
|
||||
*/
|
||||
void
|
||||
PropertyMapper::set_source (const db::PropertiesRepository *source)
|
||||
{
|
||||
if (source != mp_source) {
|
||||
m_prop_id_map.clear ();
|
||||
mp_source = source;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -94,11 +114,24 @@ PropertyMapper::set_source (const db::Layout &source)
|
|||
* @brief Specify the target layout
|
||||
*/
|
||||
void
|
||||
PropertyMapper::set_target (db::Layout &target)
|
||||
PropertyMapper::set_target (db::Layout *target)
|
||||
{
|
||||
if (&target != mp_target) {
|
||||
db::PropertiesRepository *pr = target ? &target->properties_repository () : 0;
|
||||
if (pr != mp_target) {
|
||||
m_prop_id_map.clear ();
|
||||
mp_target = ⌖
|
||||
mp_target = pr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Specify the target property repository
|
||||
*/
|
||||
void
|
||||
PropertyMapper::set_target (db::PropertiesRepository *target)
|
||||
{
|
||||
if (target != mp_target) {
|
||||
m_prop_id_map.clear ();
|
||||
mp_target = target;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -108,17 +141,20 @@ PropertyMapper::set_target (db::Layout &target)
|
|||
db::Layout::properties_id_type
|
||||
PropertyMapper::operator() (db::Layout::properties_id_type source_id)
|
||||
{
|
||||
if (source_id == 0 || mp_source == mp_target) {
|
||||
if (source_id == 0 || mp_source == mp_target || ! mp_source || ! mp_target) {
|
||||
return source_id;
|
||||
}
|
||||
|
||||
tl_assert (mp_source != 0);
|
||||
tl_assert (mp_target != 0);
|
||||
|
||||
static tl::Mutex s_mutex;
|
||||
tl::MutexLocker locker (&s_mutex);
|
||||
|
||||
std::map <db::Layout::properties_id_type, db::Layout::properties_id_type>::const_iterator p = m_prop_id_map.find (source_id);
|
||||
|
||||
if (p == m_prop_id_map.end ()) {
|
||||
db::Layout::properties_id_type new_id = mp_target->properties_repository ().translate (mp_source->properties_repository (), source_id);
|
||||
db::Layout::properties_id_type new_id = mp_target->translate (*mp_source, source_id);
|
||||
m_prop_id_map.insert (std::make_pair (source_id, new_id));
|
||||
return new_id;
|
||||
} else {
|
||||
|
|
@ -196,7 +232,7 @@ merge_layouts (db::Layout &target,
|
|||
}
|
||||
|
||||
// provide the property mapper
|
||||
db::PropertyMapper pm (target, source);
|
||||
db::PropertyMapper pm (&target, &source);
|
||||
|
||||
tl::RelativeProgress progress (tl::to_string (tr ("Merge cells")), all_cells_to_copy.size (), 1);
|
||||
|
||||
|
|
@ -308,7 +344,7 @@ copy_or_move_shapes (db::Layout &target,
|
|||
collect_cells_to_copy (source, source_cells, cell_mapping, all_top_level_cells, all_cells_to_copy);
|
||||
|
||||
// provide the property mapper
|
||||
db::PropertyMapper pm (target, source);
|
||||
db::PropertyMapper pm (&target, &source);
|
||||
|
||||
tl::RelativeProgress progress (tl::to_string (tr ("Merge cells")), all_cells_to_copy.size () * layer_mapping.size (), 1);
|
||||
|
||||
|
|
|
|||
|
|
@ -80,8 +80,16 @@ public:
|
|||
* @param source The source layout
|
||||
* @param target The target layout
|
||||
*/
|
||||
PropertyMapper (db::Layout &target, const db::Layout &source);
|
||||
PropertyMapper (db::Layout *target, const db::Layout *source);
|
||||
|
||||
/**
|
||||
* @brief Instantiate a property mapper for mapping of property ids from the source to the target property repository
|
||||
*
|
||||
* @param source The source property repository
|
||||
* @param target The target property repository
|
||||
*/
|
||||
PropertyMapper (db::PropertiesRepository *target, const db::PropertiesRepository *source);
|
||||
|
||||
/**
|
||||
* @brief Instantiate a property mapper for mapping of property ids from the source to the target layout
|
||||
*
|
||||
|
|
@ -93,21 +101,31 @@ public:
|
|||
/**
|
||||
* @brief Specify the source layout
|
||||
*/
|
||||
void set_source (const db::Layout &source);
|
||||
void set_source (const db::Layout *source);
|
||||
|
||||
/**
|
||||
* @brief Specify the source property repository
|
||||
*/
|
||||
void set_source (const db::PropertiesRepository *source);
|
||||
|
||||
/**
|
||||
* @brief Specify the target layout
|
||||
*/
|
||||
void set_target (db::Layout &target);
|
||||
void set_target (db::Layout *target);
|
||||
|
||||
/**
|
||||
* @brief Specify the target property repository
|
||||
*/
|
||||
void set_target (db::PropertiesRepository *target);
|
||||
|
||||
/**
|
||||
* @brief The actual mapping function
|
||||
*/
|
||||
db::Layout::properties_id_type operator() (db::Layout::properties_id_type source_id);
|
||||
|
||||
private:
|
||||
db::Layout *mp_target;
|
||||
const db::Layout *mp_source;
|
||||
db::PropertiesRepository *mp_target;
|
||||
const db::PropertiesRepository *mp_source;
|
||||
std::map <db::Layout::properties_id_type, db::Layout::properties_id_type> m_prop_id_map;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -224,7 +224,7 @@ LibraryProxy::update (db::ImportLayerMapping *layer_mapping)
|
|||
clear_shapes ();
|
||||
clear_insts ();
|
||||
|
||||
PropertyMapper prop_id_map (*layout (), lib->layout ());
|
||||
PropertyMapper prop_id_map (layout (), &lib->layout ());
|
||||
|
||||
for (unsigned int l = 0; l < lib->layout ().layers (); ++l) {
|
||||
if (layer_indices [l] >= 0) {
|
||||
|
|
|
|||
|
|
@ -22,17 +22,6 @@
|
|||
|
||||
#include "dbLocalOperation.h"
|
||||
#include "dbHierProcessor.h"
|
||||
#include "dbBoxScanner.h"
|
||||
#include "dbRecursiveShapeIterator.h"
|
||||
#include "dbBoxConvert.h"
|
||||
#include "dbPolygonGenerators.h"
|
||||
#include "dbPolygonTools.h"
|
||||
#include "dbLocalOperationUtils.h"
|
||||
#include "dbEdgeBoolean.h"
|
||||
#include "tlLog.h"
|
||||
#include "tlTimer.h"
|
||||
#include "tlInternational.h"
|
||||
#include "tlProgress.h"
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
|
@ -92,6 +81,14 @@ 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::PolygonRefWithProperties>;
|
||||
template class DB_PUBLIC local_operation<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::EdgeWithProperties>;
|
||||
template class DB_PUBLIC local_operation<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::EdgePairWithProperties>;
|
||||
template class DB_PUBLIC local_operation<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::EdgePair>;
|
||||
template class DB_PUBLIC local_operation<db::PolygonWithProperties, db::PolygonWithProperties, db::PolygonWithProperties>;
|
||||
template class DB_PUBLIC local_operation<db::PolygonWithProperties, db::PolygonWithProperties, db::EdgeWithProperties>;
|
||||
template class DB_PUBLIC local_operation<db::PolygonWithProperties, db::PolygonWithProperties, db::EdgePairWithProperties>;
|
||||
template class DB_PUBLIC local_operation<db::PolygonWithProperties, db::PolygonWithProperties, db::EdgePair>;
|
||||
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>;
|
||||
|
|
@ -109,401 +106,5 @@ template class DB_PUBLIC local_operation<db::Edge, db::Edge, db::EdgePair>;
|
|||
template class DB_PUBLIC local_operation<db::TextRef, db::PolygonRef, db::PolygonRef>;
|
||||
template class DB_PUBLIC local_operation<db::TextRef, db::PolygonRef, db::TextRef>;
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
// BoolAndOrNotLocalOperation implementation
|
||||
|
||||
BoolAndOrNotLocalOperation::BoolAndOrNotLocalOperation (bool is_and)
|
||||
: m_is_and (is_and)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
OnEmptyIntruderHint
|
||||
BoolAndOrNotLocalOperation::on_empty_intruder_hint () const
|
||||
{
|
||||
return m_is_and ? Drop : Copy;
|
||||
}
|
||||
|
||||
std::string
|
||||
BoolAndOrNotLocalOperation::description () const
|
||||
{
|
||||
return m_is_and ? tl::to_string (tr ("AND operation")) : tl::to_string (tr ("NOT operation"));
|
||||
}
|
||||
|
||||
void
|
||||
BoolAndOrNotLocalOperation::do_compute_local (db::Layout *layout, const shape_interactions<db::PolygonRef, db::PolygonRef> &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;
|
||||
|
||||
size_t p1 = 0, p2 = 1;
|
||||
|
||||
std::set<db::PolygonRef> others;
|
||||
for (shape_interactions<db::PolygonRef, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
for (shape_interactions<db::PolygonRef, db::PolygonRef>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
others.insert (interactions.intruder_shape (*j).second);
|
||||
}
|
||||
}
|
||||
|
||||
for (shape_interactions<db::PolygonRef, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
|
||||
const db::PolygonRef &subject = interactions.subject_shape (i->first);
|
||||
if (others.find (subject) != others.end ()) {
|
||||
if (m_is_and) {
|
||||
result.insert (subject);
|
||||
}
|
||||
} else if (i->second.empty ()) {
|
||||
// shortcut (not: keep, and: drop)
|
||||
if (! m_is_and) {
|
||||
result.insert (subject);
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
// TwoBoolAndNotLocalOperation implementation
|
||||
|
||||
TwoBoolAndNotLocalOperation::TwoBoolAndNotLocalOperation ()
|
||||
: db::local_operation<db::PolygonRef, db::PolygonRef, db::PolygonRef> ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void
|
||||
TwoBoolAndNotLocalOperation::do_compute_local (db::Layout *layout, const shape_interactions<db::PolygonRef, db::PolygonRef> &interactions, std::vector<std::unordered_set<db::PolygonRef> > &results, size_t max_vertex_count, double area_ratio) const
|
||||
{
|
||||
tl_assert (results.size () == 2);
|
||||
|
||||
db::EdgeProcessor ep;
|
||||
|
||||
std::unordered_set<db::PolygonRef> &result0 = results [0];
|
||||
std::unordered_set<db::PolygonRef> &result1 = results [1];
|
||||
|
||||
size_t p1 = 0, p2 = 1;
|
||||
|
||||
std::set<db::PolygonRef> others;
|
||||
for (db::shape_interactions<db::PolygonRef, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
for (db::shape_interactions<db::PolygonRef, db::PolygonRef>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
others.insert (interactions.intruder_shape (*j).second);
|
||||
}
|
||||
}
|
||||
|
||||
for (db::shape_interactions<db::PolygonRef, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
|
||||
const db::PolygonRef &subject = interactions.subject_shape (i->first);
|
||||
if (others.find (subject) != others.end ()) {
|
||||
result0.insert (subject);
|
||||
} else if (i->second.empty ()) {
|
||||
// shortcut (not: keep, and: drop)
|
||||
result1.insert (subject);
|
||||
} 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;
|
||||
}
|
||||
|
||||
db::BooleanOp op0 (db::BooleanOp::And);
|
||||
db::PolygonRefGenerator pr0 (layout, result0);
|
||||
db::PolygonSplitter splitter0 (pr0, area_ratio, max_vertex_count);
|
||||
db::PolygonGenerator pg0 (splitter0, true, true);
|
||||
|
||||
db::BooleanOp op1 (db::BooleanOp::ANotB);
|
||||
db::PolygonRefGenerator pr1 (layout, result1);
|
||||
db::PolygonSplitter splitter1 (pr1, area_ratio, max_vertex_count);
|
||||
db::PolygonGenerator pg1 (splitter1, true, true);
|
||||
|
||||
ep.set_base_verbosity (50);
|
||||
|
||||
std::vector<std::pair<db::EdgeSink *, db::EdgeEvaluatorBase *> > procs;
|
||||
procs.push_back (std::make_pair (&pg0, &op0));
|
||||
procs.push_back (std::make_pair (&pg1, &op1));
|
||||
ep.process (procs);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::string TwoBoolAndNotLocalOperation::description () const
|
||||
{
|
||||
return tl::to_string (tr ("ANDNOT operation"));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
|
||||
SelfOverlapMergeLocalOperation::SelfOverlapMergeLocalOperation (unsigned int wrap_count)
|
||||
: m_wrap_count (wrap_count)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void
|
||||
SelfOverlapMergeLocalOperation::do_compute_local (db::Layout *layout, const shape_interactions<db::PolygonRef, db::PolygonRef> &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 ();
|
||||
|
||||
if (m_wrap_count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
db::EdgeProcessor ep;
|
||||
|
||||
size_t p1 = 0, p2 = 1;
|
||||
std::set<unsigned int> seen;
|
||||
|
||||
for (shape_interactions<db::PolygonRef, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
|
||||
if (seen.find (i->first) == seen.end ()) {
|
||||
seen.insert (i->first);
|
||||
const db::PolygonRef &subject = interactions.subject_shape (i->first);
|
||||
for (db::PolygonRef::polygon_edge_iterator e = subject.begin_edge (); ! e.at_end(); ++e) {
|
||||
ep.insert (*e, p1);
|
||||
}
|
||||
p1 += 2;
|
||||
}
|
||||
|
||||
for (db::shape_interactions<db::PolygonRef, db::PolygonRef>::iterator2 o = i->second.begin (); o != i->second.end (); ++o) {
|
||||
// don't take the same (really the same, not an identical one) shape twice - the interaction
|
||||
// set does not take care to list just one copy of the same item on the intruder side.
|
||||
if (seen.find (*o) == seen.end ()) {
|
||||
seen.insert (*o);
|
||||
const db::PolygonRef &intruder = interactions.intruder_shape (*o).second;
|
||||
for (db::PolygonRef::polygon_edge_iterator e = intruder.begin_edge (); ! e.at_end(); ++e) {
|
||||
ep.insert (*e, p2);
|
||||
}
|
||||
p2 += 2;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
db::MergeOp op (m_wrap_count - 1);
|
||||
db::PolygonRefGenerator pr (layout, result);
|
||||
db::PolygonGenerator pg (pr, true, true);
|
||||
ep.set_base_verbosity (50);
|
||||
ep.process (pg, op);
|
||||
}
|
||||
|
||||
OnEmptyIntruderHint SelfOverlapMergeLocalOperation::on_empty_intruder_hint () const
|
||||
{
|
||||
return m_wrap_count > 1 ? Drop : Copy;
|
||||
}
|
||||
|
||||
std::string SelfOverlapMergeLocalOperation::description () const
|
||||
{
|
||||
return tl::sprintf (tl::to_string (tr ("Self-overlap (wrap count %d)")), int (m_wrap_count));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
// EdgeBoolAndOrNotLocalOperation implementation
|
||||
|
||||
EdgeBoolAndOrNotLocalOperation::EdgeBoolAndOrNotLocalOperation (EdgeBoolOp op)
|
||||
: m_op (op)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
OnEmptyIntruderHint
|
||||
EdgeBoolAndOrNotLocalOperation::on_empty_intruder_hint () const
|
||||
{
|
||||
return (m_op == EdgeAnd || m_op == EdgeIntersections) ? Drop : Copy;
|
||||
}
|
||||
|
||||
std::string
|
||||
EdgeBoolAndOrNotLocalOperation::description () const
|
||||
{
|
||||
if (m_op == EdgeIntersections) {
|
||||
return tl::to_string (tr ("Edge INTERSECTION operation"));
|
||||
} else if (m_op == EdgeAnd) {
|
||||
return tl::to_string (tr ("Edge AND operation"));
|
||||
} else if (m_op == EdgeNot) {
|
||||
return tl::to_string (tr ("Edge NOT operation"));
|
||||
} else {
|
||||
return std::string ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
EdgeBoolAndOrNotLocalOperation::do_compute_local (db::Layout * /*layout*/, const shape_interactions<db::Edge, db::Edge> &interactions, std::vector<std::unordered_set<db::Edge> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const
|
||||
{
|
||||
tl_assert (results.size () == size_t (m_op == EdgeAndNot ? 2 : 1));
|
||||
|
||||
std::unordered_set<db::Edge> &result = results.front ();
|
||||
|
||||
std::unordered_set<db::Edge> *result2 = 0;
|
||||
if (results.size () > 1) {
|
||||
result2 = &results[1];
|
||||
}
|
||||
|
||||
EdgeBooleanClusterCollector<std::unordered_set<db::Edge> > cluster_collector (&result, m_op, result2);
|
||||
|
||||
db::box_scanner<db::Edge, size_t> scanner;
|
||||
|
||||
std::set<db::Edge> others;
|
||||
for (shape_interactions<db::Edge, db::Edge>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
for (shape_interactions<db::Edge, db::Edge>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
others.insert (interactions.intruder_shape (*j).second);
|
||||
}
|
||||
}
|
||||
|
||||
bool any_subject = false;
|
||||
bool is_and = (m_op == EdgeAnd || m_op == EdgeAndNot || m_op == EdgeIntersections);
|
||||
|
||||
for (shape_interactions<db::Edge, db::Edge>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
|
||||
const db::Edge &subject = interactions.subject_shape (i->first);
|
||||
if (others.find (subject) != others.end ()) {
|
||||
if (is_and) {
|
||||
result.insert (subject);
|
||||
}
|
||||
} else if (i->second.empty ()) {
|
||||
// shortcut (not: keep, and: drop)
|
||||
if (! is_and) {
|
||||
result.insert (subject);
|
||||
}
|
||||
} else {
|
||||
scanner.insert (&subject, 0);
|
||||
any_subject = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (! others.empty () || any_subject) {
|
||||
|
||||
for (std::set<db::Edge>::const_iterator o = others.begin (); o != others.end (); ++o) {
|
||||
scanner.insert (o.operator-> (), 1);
|
||||
}
|
||||
|
||||
scanner.process (cluster_collector, 1, db::box_convert<db::Edge> ());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
// EdgeToPolygonLocalOperation implementation
|
||||
|
||||
EdgeToPolygonLocalOperation::EdgeToPolygonLocalOperation (EdgePolygonOp::mode_t op, bool include_borders)
|
||||
: m_op (op), m_include_borders (include_borders)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
OnEmptyIntruderHint
|
||||
EdgeToPolygonLocalOperation::on_empty_intruder_hint () const
|
||||
{
|
||||
return m_op == EdgePolygonOp::Inside ? Drop : (m_op == EdgePolygonOp::Outside ? Copy : CopyToSecond);
|
||||
}
|
||||
|
||||
std::string
|
||||
EdgeToPolygonLocalOperation::description () const
|
||||
{
|
||||
if (m_op == EdgePolygonOp::Inside) {
|
||||
return tl::to_string (tr ("Edge to polygon AND/INSIDE"));
|
||||
} else if (m_op == EdgePolygonOp::Outside) {
|
||||
return tl::to_string (tr ("Edge to polygon NOT/OUTSIDE"));
|
||||
} else {
|
||||
return tl::to_string (tr ("Edge to polygon ANDNOT/INOUTSIDE"));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
EdgeToPolygonLocalOperation::do_compute_local (db::Layout * /*layout*/, const shape_interactions<db::Edge, db::PolygonRef> &interactions, std::vector<std::unordered_set<db::Edge> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const
|
||||
{
|
||||
tl_assert (results.size () == size_t (m_op == EdgePolygonOp::Both ? 2 : 1));
|
||||
|
||||
std::unordered_set<db::Edge> &result = results.front ();
|
||||
|
||||
std::unordered_set<db::Edge> *result2 = 0;
|
||||
if (results.size () > 1) {
|
||||
result2 = &results[1];
|
||||
}
|
||||
|
||||
db::EdgeProcessor ep;
|
||||
|
||||
std::set<db::PolygonRef> others;
|
||||
for (shape_interactions<db::Edge, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
for (shape_interactions<db::Edge, db::PolygonRef>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
others.insert (interactions.intruder_shape (*j).second);
|
||||
}
|
||||
}
|
||||
|
||||
bool any_subject = false;
|
||||
|
||||
for (shape_interactions<db::Edge, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
|
||||
const db::Edge &subject = interactions.subject_shape (i->first);
|
||||
if (i->second.empty ()) {
|
||||
// shortcut (outside: keep, otherwise: drop)
|
||||
if (m_op == db::EdgePolygonOp::Outside) {
|
||||
result.insert (subject);
|
||||
} else if (m_op == db::EdgePolygonOp::Both) {
|
||||
result2->insert (subject);
|
||||
}
|
||||
} else {
|
||||
ep.insert (subject, 1);
|
||||
any_subject = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (! others.empty () || any_subject) {
|
||||
|
||||
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, 0);
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<db::EdgeToEdgeSetGenerator> cc_second;
|
||||
if (result2) {
|
||||
cc_second.reset (new db::EdgeToEdgeSetGenerator (*result2, 2 /*second tag*/));
|
||||
}
|
||||
|
||||
db::EdgeToEdgeSetGenerator cc (result, 1 /*first tag*/, cc_second.get ());
|
||||
db::EdgePolygonOp op (m_op, m_include_borders);
|
||||
ep.process (cc, op);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,10 +26,7 @@
|
|||
#define HDR_dbLocalOperation
|
||||
|
||||
#include "dbCommon.h"
|
||||
|
||||
#include "dbLayout.h"
|
||||
#include "dbEdgeBoolean.h"
|
||||
#include "dbEdgeProcessor.h"
|
||||
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
|
@ -129,102 +126,6 @@ protected:
|
|||
virtual void do_compute_local (db::Layout *layout, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<TR> > &result, size_t max_vertex_count, double area_ratio) const = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Implements a boolean AND or NOT operation
|
||||
*/
|
||||
class DB_PUBLIC BoolAndOrNotLocalOperation
|
||||
: public local_operation<db::PolygonRef, db::PolygonRef, db::PolygonRef>
|
||||
{
|
||||
public:
|
||||
BoolAndOrNotLocalOperation (bool is_and);
|
||||
|
||||
virtual void do_compute_local (db::Layout *layout, const shape_interactions<db::PolygonRef, db::PolygonRef> &interactions, std::vector<std::unordered_set<db::PolygonRef> > &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;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Implements a boolean AND plus NOT operation
|
||||
*
|
||||
* This processor delivers two outputs: the first one having the AND result, the second
|
||||
* one having the NOT result.
|
||||
*/
|
||||
class DB_PUBLIC TwoBoolAndNotLocalOperation
|
||||
: public local_operation<db::PolygonRef, db::PolygonRef, db::PolygonRef>
|
||||
{
|
||||
public:
|
||||
TwoBoolAndNotLocalOperation ();
|
||||
|
||||
virtual void do_compute_local (db::Layout *layout, const shape_interactions<db::PolygonRef, db::PolygonRef> &interactions, std::vector<std::unordered_set<db::PolygonRef> > &result, size_t max_vertex_count, double area_ratio) const;
|
||||
virtual std::string description () const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Implements a merge operation with an overlap count
|
||||
* With a given wrap_count, the result will only contains shapes where
|
||||
* the original shapes overlap at least "wrap_count" times.
|
||||
*/
|
||||
class DB_PUBLIC SelfOverlapMergeLocalOperation
|
||||
: public local_operation<db::PolygonRef, db::PolygonRef, db::PolygonRef>
|
||||
{
|
||||
public:
|
||||
SelfOverlapMergeLocalOperation (unsigned int wrap_count);
|
||||
|
||||
virtual void do_compute_local (db::Layout *layout, const shape_interactions<db::PolygonRef, db::PolygonRef> &interactions, std::vector<std::unordered_set<db::PolygonRef> > &result, size_t max_vertex_count, double area_ratio) const;
|
||||
virtual OnEmptyIntruderHint on_empty_intruder_hint () const;
|
||||
virtual std::string description () const;
|
||||
|
||||
private:
|
||||
unsigned int m_wrap_count;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Implements a boolean AND or NOT operation between edges
|
||||
*/
|
||||
class DB_PUBLIC EdgeBoolAndOrNotLocalOperation
|
||||
: public local_operation<db::Edge, db::Edge, db::Edge>
|
||||
{
|
||||
public:
|
||||
EdgeBoolAndOrNotLocalOperation (db::EdgeBoolOp op);
|
||||
|
||||
virtual void do_compute_local (db::Layout *layout, const shape_interactions<db::Edge, db::Edge> &interactions, std::vector<std::unordered_set<db::Edge> > &result, size_t max_vertex_count, double area_ratio) const;
|
||||
virtual OnEmptyIntruderHint on_empty_intruder_hint () const;
|
||||
virtual std::string description () const;
|
||||
|
||||
// edge interaction distance is 1 to force overlap between edges and edge/boxes
|
||||
virtual db::Coord dist () const { return 1; }
|
||||
|
||||
private:
|
||||
db::EdgeBoolOp m_op;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Implements a boolean AND or NOT operation between edges and polygons (polygons as intruders)
|
||||
*
|
||||
* "AND" is implemented by "outside == false", "NOT" by "outside == true" with "include_borders == true".
|
||||
* With "include_borders == false" the operations are "INSIDE" and "OUTSIDE".
|
||||
*/
|
||||
class DB_PUBLIC EdgeToPolygonLocalOperation
|
||||
: public local_operation<db::Edge, db::PolygonRef, db::Edge>
|
||||
{
|
||||
public:
|
||||
EdgeToPolygonLocalOperation (EdgePolygonOp::mode_t op, bool include_borders);
|
||||
|
||||
virtual void do_compute_local (db::Layout *layout, const shape_interactions<db::Edge, db::PolygonRef> &interactions, std::vector<std::unordered_set<db::Edge> > &result, size_t max_vertex_count, double area_ratio) const;
|
||||
virtual OnEmptyIntruderHint on_empty_intruder_hint () const;
|
||||
virtual std::string description () const;
|
||||
|
||||
// edge interaction distance is 1 to force overlap between edges and edge/boxes
|
||||
virtual db::Coord dist () const { return m_include_borders ? 1 : 0; }
|
||||
|
||||
private:
|
||||
db::EdgePolygonOp::mode_t m_op;
|
||||
bool m_include_borders;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -27,38 +27,11 @@
|
|||
namespace db
|
||||
{
|
||||
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
// class EdgeToEdgeSetGenerator
|
||||
|
||||
EdgeToEdgeSetGenerator::EdgeToEdgeSetGenerator (std::unordered_set<db::Edge> &edges, int tag, EdgeToEdgeSetGenerator *chained)
|
||||
: mp_edges (&edges), m_tag (tag), mp_chained (chained)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void EdgeToEdgeSetGenerator::put (const db::Edge &edge)
|
||||
{
|
||||
mp_edges->insert (edge);
|
||||
if (mp_chained) {
|
||||
mp_chained->put (edge);
|
||||
}
|
||||
}
|
||||
|
||||
void EdgeToEdgeSetGenerator::put (const db::Edge &edge, int tag)
|
||||
{
|
||||
if (m_tag == 0 || m_tag == tag) {
|
||||
mp_edges->insert (edge);
|
||||
}
|
||||
if (mp_chained) {
|
||||
mp_chained->put (edge, tag);
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
// class PolygonRefGenerator
|
||||
|
||||
PolygonRefToShapesGenerator::PolygonRefToShapesGenerator (db::Layout *layout, db::Shapes *shapes)
|
||||
: PolygonSink (), mp_layout (layout), mp_shapes (shapes)
|
||||
PolygonRefToShapesGenerator::PolygonRefToShapesGenerator (db::Layout *layout, db::Shapes *shapes, db::properties_id_type prop_id)
|
||||
: PolygonSink (), mp_layout (layout), mp_shapes (shapes), m_prop_id (prop_id)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
|
@ -66,7 +39,11 @@ PolygonRefToShapesGenerator::PolygonRefToShapesGenerator (db::Layout *layout, db
|
|||
void PolygonRefToShapesGenerator::put (const db::Polygon &polygon)
|
||||
{
|
||||
tl::MutexLocker locker (&mp_layout->lock ());
|
||||
mp_shapes->insert (db::PolygonRef (polygon, mp_layout->shape_repository ()));
|
||||
if (m_prop_id != 0) {
|
||||
mp_shapes->insert (db::PolygonRefWithProperties (db::PolygonRef (polygon, mp_layout->shape_repository ()), m_prop_id));
|
||||
} else {
|
||||
mp_shapes->insert (db::PolygonRef (polygon, mp_layout->shape_repository ()));
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -28,7 +28,9 @@
|
|||
#include "dbCommon.h"
|
||||
|
||||
#include "dbLayout.h"
|
||||
#include "dbPropertyConstraint.h"
|
||||
#include "dbPolygonGenerators.h"
|
||||
#include "dbLocalOperation.h"
|
||||
#include "dbHash.h"
|
||||
#include "tlThreads.h"
|
||||
|
||||
|
|
@ -37,6 +39,8 @@
|
|||
namespace db
|
||||
{
|
||||
|
||||
class PropertyMapper;
|
||||
|
||||
template <class Trans>
|
||||
class polygon_transformation_filter
|
||||
: public PolygonSink
|
||||
|
|
@ -123,31 +127,117 @@ private:
|
|||
|
||||
typedef polygon_ref_generator<db::PolygonRef> PolygonRefGenerator;
|
||||
|
||||
class DB_PUBLIC EdgeToEdgeSetGenerator
|
||||
template <class T>
|
||||
class DB_PUBLIC polygon_ref_generator_with_properties;
|
||||
|
||||
template <>
|
||||
class DB_PUBLIC polygon_ref_generator_with_properties<db::PolygonRefWithProperties>
|
||||
: public PolygonSink
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
polygon_ref_generator_with_properties (db::Layout *layout, std::unordered_set<db::PolygonRefWithProperties> &polyrefs, db::properties_id_type prop_id)
|
||||
: PolygonSink (), mp_layout (layout), mp_polyrefs (&polyrefs), m_prop_id (prop_id)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Implementation of the PolygonSink interface
|
||||
*/
|
||||
void put (const db::Polygon &polygon)
|
||||
{
|
||||
tl::MutexLocker locker (&mp_layout->lock ());
|
||||
mp_polyrefs->insert (db::PolygonRefWithProperties (db::PolygonRef (polygon, mp_layout->shape_repository ()), m_prop_id));
|
||||
}
|
||||
|
||||
private:
|
||||
db::Layout *mp_layout;
|
||||
std::unordered_set<db::PolygonRefWithProperties> *mp_polyrefs;
|
||||
db::properties_id_type m_prop_id;
|
||||
};
|
||||
|
||||
template <>
|
||||
class DB_PUBLIC polygon_ref_generator_with_properties<db::PolygonWithProperties>
|
||||
: public PolygonSink
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
polygon_ref_generator_with_properties (db::Layout *, std::unordered_set<db::PolygonWithProperties> &polygons, db::properties_id_type prop_id)
|
||||
: mp_polygons (&polygons), m_prop_id (prop_id)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Implementation of the PolygonSink interface
|
||||
*/
|
||||
virtual void put (const db::Polygon &polygon)
|
||||
{
|
||||
mp_polygons->insert (db::PolygonWithProperties (polygon, m_prop_id));
|
||||
}
|
||||
|
||||
private:
|
||||
std::unordered_set<db::PolygonWithProperties> *mp_polygons;
|
||||
db::properties_id_type m_prop_id;
|
||||
};
|
||||
|
||||
typedef polygon_ref_generator<db::PolygonRef> PolygonRefGenerator;
|
||||
|
||||
template <class Container>
|
||||
class DB_PUBLIC edge_to_edge_set_generator
|
||||
: public EdgeSink
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
EdgeToEdgeSetGenerator (std::unordered_set<db::Edge> &edges, int tag = 0, EdgeToEdgeSetGenerator *chained = 0);
|
||||
edge_to_edge_set_generator (Container &edges, int tag = 0, EdgeSink *chained = 0)
|
||||
: mp_edges (&edges), m_tag (tag), mp_chained (chained)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Implementation of the PolygonSink interface
|
||||
*/
|
||||
virtual void put (const db::Edge &edge);
|
||||
virtual void put (const db::Edge &edge)
|
||||
{
|
||||
if (mp_edges) {
|
||||
mp_edges->insert (edge);
|
||||
}
|
||||
if (mp_chained) {
|
||||
mp_chained->put (edge);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Implementation of the PolygonSink interface
|
||||
*/
|
||||
virtual void put (const db::Edge &edge, int tag);
|
||||
virtual void put (const db::Edge &edge, int tag)
|
||||
{
|
||||
if (m_tag == 0 || m_tag == tag) {
|
||||
if (mp_edges) {
|
||||
mp_edges->insert (edge);
|
||||
}
|
||||
}
|
||||
if (mp_chained) {
|
||||
mp_chained->put (edge, tag);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::unordered_set<db::Edge> *mp_edges;
|
||||
Container *mp_edges;
|
||||
int m_tag;
|
||||
EdgeToEdgeSetGenerator *mp_chained;
|
||||
EdgeSink *mp_chained;
|
||||
};
|
||||
|
||||
typedef edge_to_edge_set_generator<std::unordered_set<db::Edge> > EdgeToEdgeSetGenerator;
|
||||
|
||||
class DB_PUBLIC PolygonRefToShapesGenerator
|
||||
: public PolygonSink
|
||||
{
|
||||
|
|
@ -155,7 +245,15 @@ public:
|
|||
/**
|
||||
* @brief Constructor specifying an external vector for storing the polygons
|
||||
*/
|
||||
PolygonRefToShapesGenerator (db::Layout *layout, db::Shapes *shapes);
|
||||
PolygonRefToShapesGenerator (db::Layout *layout, db::Shapes *shapes, db::properties_id_type prop_id = 0);
|
||||
|
||||
/**
|
||||
* @brief Sets the property ID to be used for the next polygon
|
||||
*/
|
||||
void set_prop_id (db::properties_id_type prop_id)
|
||||
{
|
||||
m_prop_id = prop_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Implementation of the PolygonSink interface
|
||||
|
|
@ -165,6 +263,7 @@ public:
|
|||
private:
|
||||
db::Layout *mp_layout;
|
||||
db::Shapes *mp_shapes;
|
||||
db::properties_id_type m_prop_id;
|
||||
};
|
||||
|
||||
class DB_PUBLIC PolygonSplitter
|
||||
|
|
@ -184,6 +283,129 @@ private:
|
|||
size_t m_max_vertex_count;
|
||||
};
|
||||
|
||||
template <class T, class Container>
|
||||
class DB_PUBLIC property_injector
|
||||
{
|
||||
public:
|
||||
typedef typename Container::const_iterator const_iterator;
|
||||
|
||||
property_injector (Container *container, db::properties_id_type prop_id)
|
||||
: mp_container (container), m_prop_id (prop_id)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
const_iterator begin () const
|
||||
{
|
||||
return mp_container->begin ();
|
||||
}
|
||||
|
||||
const_iterator end () const
|
||||
{
|
||||
return mp_container->end ();
|
||||
}
|
||||
|
||||
void insert (const T &t)
|
||||
{
|
||||
mp_container->insert (db::object_with_properties<T> (t, m_prop_id));
|
||||
}
|
||||
|
||||
private:
|
||||
Container *mp_container;
|
||||
db::properties_id_type m_prop_id;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Separates the interacting shapes by property relation
|
||||
*
|
||||
* Returns a map of property ID, subject shapes and intruder shapes belonging to the subject shapes.
|
||||
* Depending on the property constraint the intruders will either be ones with and properties (NoPropertyConstraint),
|
||||
* the same properties than the subject (SamePropertiesConstraint) or different properties (DifferentPropertiesConstraint).
|
||||
*/
|
||||
template <class TS, class TI>
|
||||
DB_PUBLIC_TEMPLATE
|
||||
std::map<db::properties_id_type, std::pair<std::vector<const TS *>, std::set<const TI *> > >
|
||||
separate_interactions_by_properties (const shape_interactions<db::object_with_properties<TS>, db::object_with_properties<TI> > &interactions, db::PropertyConstraint property_constraint, db::PropertyMapper &pms, db::PropertyMapper &pmi)
|
||||
{
|
||||
std::map<db::properties_id_type, std::pair<std::vector<const TS *>, std::set<const TI *> > > by_prop_id;
|
||||
|
||||
for (auto i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
|
||||
const db::object_with_properties<TS> &subject = interactions.subject_shape (i->first);
|
||||
|
||||
db::properties_id_type prop_id = pms (subject.properties_id ());
|
||||
|
||||
std::pair<std::vector<const TS *>, std::set<const TI *> > &s2p = by_prop_id [prop_id];
|
||||
s2p.first.push_back (&subject);
|
||||
|
||||
for (auto ii = i->second.begin (); ii != i->second.end (); ++ii) {
|
||||
|
||||
const std::pair<unsigned int, db::object_with_properties<TI> > &intruder = interactions.intruder_shape (*ii);
|
||||
|
||||
if (pc_match (property_constraint, prop_id, pmi (intruder.second.properties_id ()))) {
|
||||
s2p.second.insert (&intruder.second);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return by_prop_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Separates the interacting shapes by property relation
|
||||
*
|
||||
* Returns a map of property ID, subject shapes and intruder shapes belonging to the subject shapes.
|
||||
* Depending on the property constraint the intruders will either be ones with and properties (NoPropertyConstraint),
|
||||
* the same properties than the subject (SamePropertiesConstraint) or different properties (DifferentPropertiesConstraint).
|
||||
*/
|
||||
template <class TS, class TI>
|
||||
DB_PUBLIC_TEMPLATE
|
||||
std::map<db::properties_id_type, db::shape_interactions<TS, TI> >
|
||||
separate_interactions_to_interactions_by_properties (const shape_interactions<db::object_with_properties<TS>, db::object_with_properties<TI> > &interactions, db::PropertyConstraint property_constraint, db::PropertyMapper &pms, std::vector<db::PropertyMapper> &pmis)
|
||||
{
|
||||
std::map<db::properties_id_type, db::shape_interactions<TS, TI> > by_prop_id;
|
||||
std::map<db::properties_id_type, std::set<unsigned int> > intruder_ids_by_prop_id;
|
||||
|
||||
for (auto i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
|
||||
const db::object_with_properties<TS> &subject = interactions.subject_shape (i->first);
|
||||
db::properties_id_type prop_id = pms (subject.properties_id ());
|
||||
|
||||
db::shape_interactions<TS, TI> &s2p = by_prop_id [prop_id];
|
||||
std::set<unsigned int> &intruder_ids = intruder_ids_by_prop_id [prop_id];
|
||||
s2p.add_subject (i->first, subject);
|
||||
|
||||
for (auto ii = i->second.begin (); ii != i->second.end (); ++ii) {
|
||||
|
||||
const std::pair<unsigned int, db::object_with_properties<TI> > &intruder = interactions.intruder_shape (*ii);
|
||||
tl_assert (intruder.first < (unsigned int) pmis.size ());
|
||||
|
||||
if (pc_match (property_constraint, prop_id, pmis[intruder.first] (intruder.second.properties_id ()))) {
|
||||
s2p.add_interaction (i->first, *ii);
|
||||
intruder_ids.insert (*ii);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (auto i = intruder_ids_by_prop_id.begin (); i != intruder_ids_by_prop_id.end (); ++i) {
|
||||
|
||||
db::shape_interactions<TS, TI> &s2p = by_prop_id [i->first];
|
||||
const std::set<unsigned int> &intruder_ids = intruder_ids_by_prop_id [i->first];
|
||||
|
||||
for (auto ii = intruder_ids.begin (); ii != intruder_ids.end (); ++ii) {
|
||||
auto is = interactions.intruder_shape (*ii);
|
||||
s2p.add_intruder_shape (*ii, is.first, is.second);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return by_prop_id;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -50,10 +50,21 @@ void
|
|||
MutableEdges::insert (const db::Box &box)
|
||||
{
|
||||
if (! box.empty () && box.width () > 0 && box.height () > 0) {
|
||||
do_insert (db::Edge (box.lower_left (), box.upper_left ()));
|
||||
do_insert (db::Edge (box.upper_left (), box.upper_right ()));
|
||||
do_insert (db::Edge (box.upper_right (), box.lower_right ()));
|
||||
do_insert (db::Edge (box.lower_right (), box.lower_left ()));
|
||||
do_insert (db::Edge (box.lower_left (), box.upper_left ()), 0);
|
||||
do_insert (db::Edge (box.upper_left (), box.upper_right ()), 0);
|
||||
do_insert (db::Edge (box.upper_right (), box.lower_right ()), 0);
|
||||
do_insert (db::Edge (box.lower_right (), box.lower_left ()), 0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MutableEdges::insert (const db::BoxWithProperties &box)
|
||||
{
|
||||
if (! box.empty () && box.width () > 0 && box.height () > 0) {
|
||||
do_insert (db::Edge (box.lower_left (), box.upper_left ()), box.properties_id ());
|
||||
do_insert (db::Edge (box.upper_left (), box.upper_right ()), box.properties_id ());
|
||||
do_insert (db::Edge (box.upper_right (), box.lower_right ()), box.properties_id ());
|
||||
do_insert (db::Edge (box.lower_right (), box.lower_left ()), box.properties_id ());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -65,12 +76,30 @@ MutableEdges::insert (const db::Path &path)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
MutableEdges::insert (const db::PathWithProperties &path)
|
||||
{
|
||||
if (path.points () > 0) {
|
||||
insert (db::PolygonWithProperties (path.polygon (), path.properties_id ()));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MutableEdges::insert (const db::Polygon &polygon)
|
||||
{
|
||||
if (polygon.holes () > 0 || polygon.vertices () > 0) {
|
||||
for (db::Polygon::polygon_edge_iterator e = polygon.begin_edge (); ! e.at_end (); ++e) {
|
||||
do_insert (*e);
|
||||
do_insert (*e, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MutableEdges::insert (const db::PolygonWithProperties &polygon)
|
||||
{
|
||||
if (polygon.holes () > 0 || polygon.vertices () > 0) {
|
||||
for (db::Polygon::polygon_edge_iterator e = polygon.begin_edge (); ! e.at_end (); ++e) {
|
||||
do_insert (*e, polygon.properties_id ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -80,7 +109,17 @@ MutableEdges::insert (const db::SimplePolygon &polygon)
|
|||
{
|
||||
if (polygon.vertices () > 0) {
|
||||
for (db::SimplePolygon::polygon_edge_iterator e = polygon.begin_edge (); ! e.at_end (); ++e) {
|
||||
do_insert (*e);
|
||||
do_insert (*e, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MutableEdges::insert (const db::SimplePolygonWithProperties &polygon)
|
||||
{
|
||||
if (polygon.vertices () > 0) {
|
||||
for (db::SimplePolygon::polygon_edge_iterator e = polygon.begin_edge (); ! e.at_end (); ++e) {
|
||||
do_insert (*e, polygon.properties_id ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -88,17 +127,21 @@ MutableEdges::insert (const db::SimplePolygon &polygon)
|
|||
void
|
||||
MutableEdges::insert (const db::Shape &shape)
|
||||
{
|
||||
db::properties_id_type prop_id = shape.prop_id ();
|
||||
|
||||
if (shape.is_polygon () || shape.is_path () || shape.is_box ()) {
|
||||
|
||||
db::Polygon poly;
|
||||
shape.polygon (poly);
|
||||
insert (poly);
|
||||
for (auto e = poly.begin_edge (); ! e.at_end (); ++e) {
|
||||
do_insert (*e, prop_id);
|
||||
}
|
||||
|
||||
} else if (shape.is_edge ()) {
|
||||
|
||||
db::Edge edge;
|
||||
shape.edge (edge);
|
||||
do_insert (edge);
|
||||
do_insert (edge, prop_id);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ public:
|
|||
|
||||
virtual void reserve (size_t n) = 0;
|
||||
|
||||
virtual void do_insert (const db::Edge &edge) = 0;
|
||||
virtual void do_insert (const db::Edge &edge, db::properties_id_type prop_id) = 0;
|
||||
|
||||
void transform (const db::UnitTrans &) { }
|
||||
void transform (const db::Disp &t) { do_transform (db::Trans (t)); }
|
||||
|
|
@ -63,29 +63,37 @@ public:
|
|||
void transform (const db::IMatrix2d &t) { do_transform (t); }
|
||||
void transform (const db::IMatrix3d &t) { do_transform (t); }
|
||||
|
||||
void insert (const db::Edge &edge) { do_insert (edge); }
|
||||
void insert (const db::Edge &edge) { do_insert (edge, 0); }
|
||||
void insert (const db::EdgeWithProperties &edge) { do_insert (edge, edge.properties_id ()); }
|
||||
void insert (const db::Box &box);
|
||||
void insert (const db::BoxWithProperties &box);
|
||||
void insert (const db::Path &path);
|
||||
void insert (const db::PathWithProperties &path);
|
||||
void insert (const db::SimplePolygon &polygon);
|
||||
void insert (const db::SimplePolygonWithProperties &polygon);
|
||||
void insert (const db::Polygon &polygon);
|
||||
void insert (const db::PolygonWithProperties &polygon);
|
||||
void insert (const db::Shape &shape);
|
||||
|
||||
template <class T>
|
||||
void insert (const db::Shape &shape, const T &trans)
|
||||
{
|
||||
db::properties_id_type prop_id = shape.prop_id ();
|
||||
|
||||
if (shape.is_polygon () || shape.is_path () || shape.is_box ()) {
|
||||
|
||||
db::Polygon poly;
|
||||
shape.polygon (poly);
|
||||
poly.transform (trans);
|
||||
insert (poly);
|
||||
for (auto e = poly.begin_edge (); ! e.at_end (); ++e) {
|
||||
do_insert ((*e).transformed (trans), prop_id);
|
||||
}
|
||||
|
||||
} else if (shape.is_edge ()) {
|
||||
|
||||
db::Edge edge;
|
||||
shape.edge (edge);
|
||||
edge.transform (trans);
|
||||
insert (edge);
|
||||
do_insert (edge, prop_id);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,7 +50,15 @@ void
|
|||
MutableRegion::insert (const db::Box &box)
|
||||
{
|
||||
if (! box.empty () && box.width () > 0 && box.height () > 0) {
|
||||
do_insert (db::Polygon (box));
|
||||
do_insert (db::Polygon (box), 0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MutableRegion::insert (const db::BoxWithProperties &box)
|
||||
{
|
||||
if (! box.empty () && box.width () > 0 && box.height () > 0) {
|
||||
do_insert (db::Polygon (box), box.properties_id ());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -58,7 +66,15 @@ void
|
|||
MutableRegion::insert (const db::Path &path)
|
||||
{
|
||||
if (path.points () > 0) {
|
||||
do_insert (path.polygon ());
|
||||
do_insert (path.polygon (), 0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MutableRegion::insert (const db::PathWithProperties &path)
|
||||
{
|
||||
if (path.points () > 0) {
|
||||
do_insert (path.polygon (), path.properties_id ());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -68,7 +84,17 @@ MutableRegion::insert (const db::SimplePolygon &polygon)
|
|||
if (polygon.vertices () > 0) {
|
||||
db::Polygon poly;
|
||||
poly.assign_hull (polygon.begin_hull (), polygon.end_hull ());
|
||||
do_insert (poly);
|
||||
do_insert (poly, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MutableRegion::insert (const db::SimplePolygonWithProperties &polygon)
|
||||
{
|
||||
if (polygon.vertices () > 0) {
|
||||
db::Polygon poly;
|
||||
poly.assign_hull (polygon.begin_hull (), polygon.end_hull ());
|
||||
do_insert (poly, polygon.properties_id ());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -78,13 +104,8 @@ MutableRegion::insert (const db::Shape &shape)
|
|||
if (shape.is_polygon () || shape.is_path () || shape.is_box ()) {
|
||||
db::Polygon poly;
|
||||
shape.polygon (poly);
|
||||
insert (poly);
|
||||
} else if (shape.is_path ()) {
|
||||
insert (shape.path ());
|
||||
} else if (shape.is_box ()) {
|
||||
insert (shape.box ());
|
||||
do_insert (poly, shape.prop_id ());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ public:
|
|||
MutableRegion (const MutableRegion &other);
|
||||
virtual ~MutableRegion ();
|
||||
|
||||
virtual void do_insert (const db::Polygon &polygon) = 0;
|
||||
virtual void do_insert (const db::Polygon &polygon, db::properties_id_type prop_id) = 0;
|
||||
|
||||
void transform (const db::UnitTrans &) { }
|
||||
void transform (const db::Disp &t) { do_transform (db::Trans (t)); }
|
||||
|
|
@ -63,10 +63,14 @@ public:
|
|||
|
||||
virtual void reserve (size_t n) = 0;
|
||||
|
||||
void insert (const db::Polygon &polygon) { do_insert (polygon); }
|
||||
void insert (const db::Polygon &polygon) { do_insert (polygon, 0); }
|
||||
void insert (const db::PolygonWithProperties &polygon) { do_insert (polygon, polygon.properties_id ()); }
|
||||
void insert (const db::Box &box);
|
||||
void insert (const db::BoxWithProperties &box);
|
||||
void insert (const db::Path &path);
|
||||
void insert (const db::PathWithProperties &path);
|
||||
void insert (const db::SimplePolygon &polygon);
|
||||
void insert (const db::SimplePolygonWithProperties &polygon);
|
||||
|
||||
void insert (const db::Shape &shape);
|
||||
|
||||
|
|
@ -77,7 +81,7 @@ public:
|
|||
db::Polygon poly;
|
||||
shape.polygon (poly);
|
||||
poly.transform (trans);
|
||||
insert (poly);
|
||||
do_insert (poly, shape.prop_id ());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -285,7 +285,8 @@ NetlistExtractor::extract_nets (const db::DeepShapeStore &dss, unsigned int layo
|
|||
for (connected_clusters_type::all_iterator c = clusters.begin_all (); ! c.at_end (); ++c) {
|
||||
|
||||
const db::local_cluster<db::NetShape> &lc = clusters.cluster_by_id (*c);
|
||||
if (clusters.connections_for_cluster (*c).empty () && lc.empty ()) {
|
||||
const connected_clusters_type::connections_type &cc = clusters.connections_for_cluster (*c);
|
||||
if (cc.empty () && lc.empty ()) {
|
||||
// this is an entirely empty cluster so we skip it.
|
||||
// Such clusters are left over when joining clusters.
|
||||
continue;
|
||||
|
|
@ -313,6 +314,23 @@ NetlistExtractor::extract_nets (const db::DeepShapeStore &dss, unsigned int layo
|
|||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
// This code will pull net names from subcircuits into their parents if those nets are dummy connections
|
||||
// made to satisfy the subcircuit's pin, but not to make a physical connection.
|
||||
// Don't know whether this is a good idea, so this code is disabled for now.
|
||||
|
||||
if (net_names.empty () && clusters.is_dummy (*c) && net->subcircuit_pin_count () == 1) {
|
||||
// in the case of a dummy connection (partially connected subcircuits) create a
|
||||
// new name indicating the subcircuit and the subcircuit net name - this makes subcircuit
|
||||
// net names available (the net is pseudo-root inside in the subcircuit)
|
||||
const db::NetSubcircuitPinRef &sc_pin = *net->begin_subcircuit_pins ();
|
||||
const db::Net *sc_net = sc_pin.subcircuit ()->circuit_ref ()->net_for_pin (sc_pin.pin_id ());
|
||||
if (sc_net && ! sc_net->name ().empty ()) {
|
||||
net_names.insert (sc_pin.subcircuit ()->expanded_name () + ":" + sc_net->name ());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
assign_net_names (net, net_names);
|
||||
|
||||
if (! clusters.is_root (*c)) {
|
||||
|
|
|
|||
|
|
@ -176,6 +176,15 @@ public:
|
|||
m_id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the transformed object
|
||||
*/
|
||||
template <class Trans>
|
||||
object_with_properties<Obj> transformed (const Trans &tr) const
|
||||
{
|
||||
return object_with_properties<Obj> (Obj::transformed (tr), m_id);
|
||||
}
|
||||
|
||||
private:
|
||||
properties_id_type m_id;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ namespace
|
|||
typedef db::EdgePair value_type;
|
||||
|
||||
OriginalLayerEdgePairsIterator (const db::RecursiveShapeIterator &iter, const db::ICplxTrans &trans)
|
||||
: m_rec_iter (iter), m_iter_trans (trans)
|
||||
: m_rec_iter (iter), m_iter_trans (trans), m_prop_id (0)
|
||||
{
|
||||
set ();
|
||||
}
|
||||
|
|
@ -67,6 +67,11 @@ namespace
|
|||
return &m_shape;
|
||||
}
|
||||
|
||||
virtual db::properties_id_type prop_id () const
|
||||
{
|
||||
return m_prop_id;
|
||||
}
|
||||
|
||||
virtual EdgePairsIteratorDelegate *clone () const
|
||||
{
|
||||
return new OriginalLayerEdgePairsIterator (*this);
|
||||
|
|
@ -100,15 +105,17 @@ namespace
|
|||
db::RecursiveShapeIterator m_rec_iter;
|
||||
db::ICplxTrans m_iter_trans;
|
||||
value_type m_shape;
|
||||
db::properties_id_type m_prop_id;
|
||||
|
||||
void set ()
|
||||
{
|
||||
while (! m_rec_iter.at_end () && !m_rec_iter.shape ().is_edge_pair ()) {
|
||||
while (! m_rec_iter.at_end () && !m_rec_iter->is_edge_pair ()) {
|
||||
++m_rec_iter;
|
||||
}
|
||||
if (! m_rec_iter.at_end ()) {
|
||||
m_rec_iter.shape ().edge_pair (m_shape);
|
||||
m_rec_iter->edge_pair (m_shape);
|
||||
m_shape.transform (m_iter_trans * m_rec_iter.trans ());
|
||||
m_prop_id = m_rec_iter.prop_id ();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -195,6 +202,24 @@ OriginalLayerEdgePairs::iter () const
|
|||
return &m_iter;
|
||||
}
|
||||
|
||||
void
|
||||
OriginalLayerEdgePairs::apply_property_translator (const db::PropertiesTranslator &pt)
|
||||
{
|
||||
m_iter.apply_property_translator (pt);
|
||||
}
|
||||
|
||||
db::PropertiesRepository *
|
||||
OriginalLayerEdgePairs::properties_repository ()
|
||||
{
|
||||
return m_iter.layout () ? &const_cast<db::Layout * >(m_iter.layout ())->properties_repository () : 0;
|
||||
}
|
||||
|
||||
const db::PropertiesRepository *
|
||||
OriginalLayerEdgePairs::properties_repository () const
|
||||
{
|
||||
return m_iter.layout () ? &m_iter.layout ()->properties_repository () : 0;
|
||||
}
|
||||
|
||||
bool
|
||||
OriginalLayerEdgePairs::equals (const EdgePairs &other) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -56,6 +56,9 @@ public:
|
|||
virtual bool has_valid_edge_pairs () const;
|
||||
|
||||
virtual const db::RecursiveShapeIterator *iter () const;
|
||||
virtual void apply_property_translator (const db::PropertiesTranslator &pt);
|
||||
virtual db::PropertiesRepository *properties_repository ();
|
||||
virtual const db::PropertiesRepository *properties_repository () const;
|
||||
|
||||
virtual bool equals (const EdgePairs &other) const;
|
||||
virtual bool less (const EdgePairs &other) const;
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ namespace
|
|||
typedef db::Edge value_type;
|
||||
|
||||
OriginalLayerEdgesIterator (const db::RecursiveShapeIterator &iter, const db::ICplxTrans &trans)
|
||||
: m_rec_iter (iter), m_iter_trans (trans)
|
||||
: m_rec_iter (iter), m_iter_trans (trans), m_prop_id (0)
|
||||
{
|
||||
set ();
|
||||
}
|
||||
|
|
@ -68,6 +68,11 @@ namespace
|
|||
return &m_shape;
|
||||
}
|
||||
|
||||
virtual db::properties_id_type prop_id () const
|
||||
{
|
||||
return m_prop_id;
|
||||
}
|
||||
|
||||
virtual EdgesIteratorDelegate *clone () const
|
||||
{
|
||||
return new OriginalLayerEdgesIterator (*this);
|
||||
|
|
@ -101,15 +106,17 @@ namespace
|
|||
db::RecursiveShapeIterator m_rec_iter;
|
||||
db::ICplxTrans m_iter_trans;
|
||||
value_type m_shape;
|
||||
db::properties_id_type m_prop_id;
|
||||
|
||||
void set ()
|
||||
{
|
||||
while (! m_rec_iter.at_end () && !m_rec_iter.shape ().is_edge ()) {
|
||||
while (! m_rec_iter.at_end () && !m_rec_iter->is_edge ()) {
|
||||
++m_rec_iter;
|
||||
}
|
||||
if (! m_rec_iter.at_end ()) {
|
||||
m_rec_iter.shape ().edge (m_shape);
|
||||
m_rec_iter->edge (m_shape);
|
||||
m_shape.transform (m_iter_trans * m_rec_iter.trans ());
|
||||
m_prop_id = m_rec_iter.prop_id ();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -120,7 +127,6 @@ namespace
|
|||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
OriginalLayerEdges::OriginalLayerEdges ()
|
||||
|
|
@ -245,6 +251,27 @@ OriginalLayerEdges::iter () const
|
|||
return &m_iter;
|
||||
}
|
||||
|
||||
void
|
||||
OriginalLayerEdges::apply_property_translator (const db::PropertiesTranslator &pt)
|
||||
{
|
||||
m_iter.apply_property_translator (pt);
|
||||
|
||||
m_merged_edges_valid = false;
|
||||
m_merged_edges.clear ();
|
||||
}
|
||||
|
||||
db::PropertiesRepository *
|
||||
OriginalLayerEdges::properties_repository ()
|
||||
{
|
||||
return m_iter.layout () ? &const_cast<db::Layout * >(m_iter.layout ())->properties_repository () : 0;
|
||||
}
|
||||
|
||||
const db::PropertiesRepository *
|
||||
OriginalLayerEdges::properties_repository () const
|
||||
{
|
||||
return m_iter.layout () ? &m_iter.layout ()->properties_repository () : 0;
|
||||
}
|
||||
|
||||
bool
|
||||
OriginalLayerEdges::equals (const Edges &other) const
|
||||
{
|
||||
|
|
@ -287,7 +314,7 @@ OriginalLayerEdges::ensure_merged_edges_valid () const
|
|||
db::box_scanner<db::Edge, size_t> scanner (report_progress (), progress_desc ());
|
||||
scanner.reserve (count ());
|
||||
|
||||
AddressableEdgeDelivery e (begin (), has_valid_edges ());
|
||||
AddressableEdgeDelivery e (begin ());
|
||||
|
||||
for ( ; ! e.at_end (); ++e) {
|
||||
if (! e->is_degenerate ()) {
|
||||
|
|
|
|||
|
|
@ -62,6 +62,9 @@ public:
|
|||
virtual bool has_valid_merged_edges () const;
|
||||
|
||||
virtual const db::RecursiveShapeIterator *iter () const;
|
||||
virtual void apply_property_translator (const db::PropertiesTranslator &pt);
|
||||
virtual db::PropertiesRepository *properties_repository ();
|
||||
virtual const db::PropertiesRepository *properties_repository () const;
|
||||
|
||||
virtual bool equals (const Edges &other) const;
|
||||
virtual bool less (const Edges &other) const;
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@
|
|||
#include "dbFlatRegion.h"
|
||||
#include "dbFlatEdges.h"
|
||||
#include "dbRegion.h"
|
||||
#include "dbShapeProcessor.h"
|
||||
#include "dbDeepEdges.h"
|
||||
#include "dbDeepRegion.h"
|
||||
#include "dbDeepShapeStore.h"
|
||||
|
|
@ -46,7 +45,7 @@ namespace
|
|||
{
|
||||
public:
|
||||
OriginalLayerRegionIterator (const db::RecursiveShapeIterator &iter, const db::ICplxTrans &trans)
|
||||
: m_rec_iter (iter), m_iter_trans (trans)
|
||||
: m_rec_iter (iter), m_iter_trans (trans), m_prop_id (0)
|
||||
{
|
||||
set ();
|
||||
}
|
||||
|
|
@ -72,6 +71,11 @@ namespace
|
|||
return &m_polygon;
|
||||
}
|
||||
|
||||
virtual db::properties_id_type prop_id () const
|
||||
{
|
||||
return m_prop_id;
|
||||
}
|
||||
|
||||
virtual RegionIteratorDelegate *clone () const
|
||||
{
|
||||
return new OriginalLayerRegionIterator (*this);
|
||||
|
|
@ -105,15 +109,17 @@ namespace
|
|||
db::RecursiveShapeIterator m_rec_iter;
|
||||
db::ICplxTrans m_iter_trans;
|
||||
db::Polygon m_polygon;
|
||||
db::properties_id_type m_prop_id;
|
||||
|
||||
void set ()
|
||||
{
|
||||
while (! m_rec_iter.at_end () && ! (m_rec_iter.shape ().is_polygon () || m_rec_iter.shape ().is_path () || m_rec_iter.shape ().is_box ())) {
|
||||
while (! m_rec_iter.at_end () && ! (m_rec_iter->is_polygon () || m_rec_iter->is_path () || m_rec_iter->is_box ())) {
|
||||
++m_rec_iter;
|
||||
}
|
||||
if (! m_rec_iter.at_end ()) {
|
||||
m_rec_iter.shape ().polygon (m_polygon);
|
||||
m_rec_iter->polygon (m_polygon);
|
||||
m_polygon.transform (m_iter_trans * m_rec_iter.trans (), false);
|
||||
m_prop_id = m_rec_iter.prop_id ();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -234,10 +240,10 @@ OriginalLayerRegion::count () const
|
|||
size_t nn = 0;
|
||||
if (iter.multiple_layers ()) {
|
||||
for (std::vector<unsigned int>::const_iterator l = iter.layers ().begin (); l != iter.layers ().end (); ++l) {
|
||||
nn += layout.cell (*c).shapes (*l).size (iter.shape_flags () & db::ShapeIterator::Regions);
|
||||
nn += layout.cell (*c).shapes (*l).size (iter.shape_flags () & (db::ShapeIterator::Regions | db::ShapeIterator::Properties));
|
||||
}
|
||||
} else if (iter.layer () < layout.layers ()) {
|
||||
nn += layout.cell (*c).shapes (iter.layer ()).size (iter.shape_flags () & db::ShapeIterator::Regions);
|
||||
nn += layout.cell (*c).shapes (iter.layer ()).size (iter.shape_flags () & (db::ShapeIterator::Regions | db::ShapeIterator::Properties));
|
||||
}
|
||||
n += cc.weight (*c) * nn;
|
||||
}
|
||||
|
|
@ -339,6 +345,12 @@ OriginalLayerRegion::nth (size_t) const
|
|||
throw tl::Exception (tl::to_string (tr ("Random access to polygons is available only for flat regions")));
|
||||
}
|
||||
|
||||
db::properties_id_type
|
||||
OriginalLayerRegion::nth_prop_id (size_t) const
|
||||
{
|
||||
throw tl::Exception (tl::to_string (tr ("Random access to polygons is available only for flat regions")));
|
||||
}
|
||||
|
||||
bool
|
||||
OriginalLayerRegion::has_valid_polygons () const
|
||||
{
|
||||
|
|
@ -357,6 +369,27 @@ OriginalLayerRegion::iter () const
|
|||
return &m_iter;
|
||||
}
|
||||
|
||||
void
|
||||
OriginalLayerRegion::apply_property_translator (const db::PropertiesTranslator &pt)
|
||||
{
|
||||
m_iter.apply_property_translator (pt);
|
||||
|
||||
m_merged_polygons_valid = false;
|
||||
m_merged_polygons.clear ();
|
||||
}
|
||||
|
||||
db::PropertiesRepository *
|
||||
OriginalLayerRegion::properties_repository ()
|
||||
{
|
||||
return m_iter.layout () ? &const_cast<db::Layout * >(m_iter.layout ())->properties_repository () : 0;
|
||||
}
|
||||
|
||||
const db::PropertiesRepository *
|
||||
OriginalLayerRegion::properties_repository () const
|
||||
{
|
||||
return m_iter.layout () ? &m_iter.layout ()->properties_repository () : 0;
|
||||
}
|
||||
|
||||
bool
|
||||
OriginalLayerRegion::equals (const Region &other) const
|
||||
{
|
||||
|
|
@ -386,6 +419,17 @@ OriginalLayerRegion::init ()
|
|||
m_merged_polygons_valid = false;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
struct AssignProp
|
||||
{
|
||||
AssignProp () : prop_id (0) { }
|
||||
db::properties_id_type operator() (db::properties_id_type) { return prop_id; }
|
||||
db::properties_id_type prop_id;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
OriginalLayerRegion::insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const
|
||||
{
|
||||
|
|
@ -397,12 +441,19 @@ OriginalLayerRegion::insert_into (Layout *layout, db::cell_index_type into_cell,
|
|||
|
||||
db::Shapes &sh = layout->cell (into_cell).shapes (into_layer);
|
||||
|
||||
db::PropertyMapper pm;
|
||||
if (m_iter.layout ()) {
|
||||
pm = db::PropertyMapper (layout, m_iter.layout ());
|
||||
}
|
||||
|
||||
// NOTE: if the source (r) is from the same layout than the shapes live in, we better
|
||||
// lock the layout against updates while inserting
|
||||
db::LayoutLocker locker (layout);
|
||||
AssignProp ap;
|
||||
for (db::RecursiveShapeIterator i = m_iter; !i.at_end (); ++i) {
|
||||
tl::ident_map<db::properties_id_type> pm;
|
||||
sh.insert (*i, i.trans (), pm);
|
||||
db::properties_id_type prop_id = i.prop_id ();
|
||||
ap.prop_id = (prop_id != 0 ? pm (prop_id) : 0);
|
||||
sh.insert (*i, i.trans (), ap);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -412,28 +463,7 @@ OriginalLayerRegion::ensure_merged_polygons_valid () const
|
|||
if (! m_merged_polygons_valid) {
|
||||
|
||||
m_merged_polygons.clear ();
|
||||
|
||||
db::EdgeProcessor ep (report_progress (), progress_desc ());
|
||||
ep.set_base_verbosity (base_verbosity ());
|
||||
|
||||
// count edges and reserve memory
|
||||
size_t n = 0;
|
||||
for (RegionIterator p (begin ()); ! p.at_end (); ++p) {
|
||||
n += p->vertices ();
|
||||
}
|
||||
ep.reserve (n);
|
||||
|
||||
// insert the polygons into the processor
|
||||
n = 0;
|
||||
for (RegionIterator p (begin ()); ! p.at_end (); ++p, ++n) {
|
||||
ep.insert (*p, n);
|
||||
}
|
||||
|
||||
// and run the merge step
|
||||
db::MergeOp op (0);
|
||||
db::ShapeGenerator pc (m_merged_polygons);
|
||||
db::PolygonGenerator pg (pc, false /*don't resolve holes*/, min_coherence ());
|
||||
ep.process (pg, op);
|
||||
merge_polygons_to (m_merged_polygons, min_coherence (), 0);
|
||||
|
||||
m_merged_polygons_valid = true;
|
||||
|
||||
|
|
|
|||
|
|
@ -62,10 +62,14 @@ public:
|
|||
virtual size_t hier_count () const;
|
||||
|
||||
virtual const db::Polygon *nth (size_t n) const;
|
||||
virtual db::properties_id_type nth_prop_id (size_t) const;
|
||||
virtual bool has_valid_polygons () const;
|
||||
virtual bool has_valid_merged_polygons () const;
|
||||
|
||||
virtual const db::RecursiveShapeIterator *iter () const;
|
||||
virtual void apply_property_translator (const db::PropertiesTranslator &pt);
|
||||
virtual db::PropertiesRepository *properties_repository ();
|
||||
virtual const db::PropertiesRepository *properties_repository () const;
|
||||
|
||||
virtual bool equals (const Region &other) const;
|
||||
virtual bool less (const Region &other) const;
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ namespace
|
|||
typedef db::Text value_type;
|
||||
|
||||
OriginalLayerTextsIterator (const db::RecursiveShapeIterator &iter, const db::ICplxTrans &trans)
|
||||
: m_rec_iter (iter), m_iter_trans (trans)
|
||||
: m_rec_iter (iter), m_iter_trans (trans), m_prop_id (0)
|
||||
{
|
||||
set ();
|
||||
}
|
||||
|
|
@ -67,6 +67,11 @@ namespace
|
|||
return &m_shape;
|
||||
}
|
||||
|
||||
virtual db::properties_id_type prop_id () const
|
||||
{
|
||||
return m_prop_id;
|
||||
}
|
||||
|
||||
virtual OriginalLayerTextsIterator *clone () const
|
||||
{
|
||||
return new OriginalLayerTextsIterator (*this);
|
||||
|
|
@ -100,6 +105,7 @@ namespace
|
|||
db::RecursiveShapeIterator m_rec_iter;
|
||||
db::ICplxTrans m_iter_trans;
|
||||
value_type m_shape;
|
||||
db::properties_id_type m_prop_id;
|
||||
|
||||
void set ()
|
||||
{
|
||||
|
|
@ -107,8 +113,9 @@ namespace
|
|||
++m_rec_iter;
|
||||
}
|
||||
if (! m_rec_iter.at_end ()) {
|
||||
m_rec_iter.shape ().text (m_shape);
|
||||
m_rec_iter->text (m_shape);
|
||||
m_shape.transform (m_iter_trans * m_rec_iter.trans ());
|
||||
m_prop_id = m_rec_iter.prop_id ();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -195,6 +202,24 @@ OriginalLayerTexts::iter () const
|
|||
return &m_iter;
|
||||
}
|
||||
|
||||
void
|
||||
OriginalLayerTexts::apply_property_translator (const db::PropertiesTranslator &pt)
|
||||
{
|
||||
m_iter.apply_property_translator (pt);
|
||||
}
|
||||
|
||||
db::PropertiesRepository *
|
||||
OriginalLayerTexts::properties_repository ()
|
||||
{
|
||||
return m_iter.layout () ? &const_cast<db::Layout * >(m_iter.layout ())->properties_repository () : 0;
|
||||
}
|
||||
|
||||
const db::PropertiesRepository *
|
||||
OriginalLayerTexts::properties_repository () const
|
||||
{
|
||||
return m_iter.layout () ? &m_iter.layout ()->properties_repository () : 0;
|
||||
}
|
||||
|
||||
bool
|
||||
OriginalLayerTexts::equals (const Texts &other) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -56,6 +56,9 @@ public:
|
|||
virtual bool has_valid_texts () const;
|
||||
|
||||
virtual const db::RecursiveShapeIterator *iter () const;
|
||||
virtual void apply_property_translator (const db::PropertiesTranslator &pt);
|
||||
virtual db::PropertiesRepository *properties_repository ();
|
||||
virtual const db::PropertiesRepository *properties_repository () const;
|
||||
|
||||
virtual bool equals (const Texts &other) const;
|
||||
virtual bool less (const Texts &other) const;
|
||||
|
|
|
|||
|
|
@ -42,6 +42,12 @@ PropertiesRepository::PropertiesRepository (db::LayoutStateModel *state_model)
|
|||
tl_assert (id == 0);
|
||||
}
|
||||
|
||||
PropertiesRepository::PropertiesRepository (const PropertiesRepository &d)
|
||||
: mp_state_model (0)
|
||||
{
|
||||
operator= (d);
|
||||
}
|
||||
|
||||
PropertiesRepository &
|
||||
PropertiesRepository::operator= (const PropertiesRepository &d)
|
||||
{
|
||||
|
|
@ -207,5 +213,135 @@ PropertiesRepository::translate (const PropertiesRepository &rep, properties_id_
|
|||
return properties_id (new_pset);
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// PropertiesRepository implementation
|
||||
|
||||
PropertiesTranslator::PropertiesTranslator ()
|
||||
: m_pass (true), m_null (true)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
PropertiesTranslator::PropertiesTranslator (bool pass)
|
||||
: m_pass (pass), m_null (false)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
PropertiesTranslator::PropertiesTranslator (const std::map<db::properties_id_type, db::properties_id_type> &map)
|
||||
: m_map (map), m_pass (false), m_null (false)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
PropertiesTranslator
|
||||
PropertiesTranslator::operator* (const PropertiesTranslator &other) const
|
||||
{
|
||||
if (other.m_pass) {
|
||||
|
||||
// NOTE: by handling this first, "pass_all * null" will give "pass_all" which is desired
|
||||
// for RecursiveShapeIterator::apply_property_translator.
|
||||
return *this;
|
||||
|
||||
} else if (m_pass) {
|
||||
|
||||
return other;
|
||||
|
||||
} else {
|
||||
|
||||
std::map<db::properties_id_type, db::properties_id_type> new_map;
|
||||
|
||||
for (auto i = other.m_map.begin (); i != other.m_map.end (); ++i) {
|
||||
auto ii = m_map.find (i->second);
|
||||
if (ii != m_map.end ()) {
|
||||
new_map.insert (std::make_pair (i->first, ii->second));
|
||||
}
|
||||
}
|
||||
|
||||
return PropertiesTranslator (new_map);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
db::properties_id_type
|
||||
PropertiesTranslator::operator() (db::properties_id_type id) const
|
||||
{
|
||||
if (m_pass || id == 0) {
|
||||
return id;
|
||||
} else {
|
||||
auto i = m_map.find (id);
|
||||
return i != m_map.end () ? i->second : 0;
|
||||
}
|
||||
}
|
||||
|
||||
PropertiesTranslator
|
||||
PropertiesTranslator::make_remove_all ()
|
||||
{
|
||||
return PropertiesTranslator (false);
|
||||
}
|
||||
|
||||
PropertiesTranslator
|
||||
PropertiesTranslator::make_pass_all ()
|
||||
{
|
||||
return PropertiesTranslator (true);
|
||||
}
|
||||
|
||||
PropertiesTranslator
|
||||
PropertiesTranslator::make_filter (db::PropertiesRepository &repo, const std::set<tl::Variant> &keys)
|
||||
{
|
||||
std::map<db::properties_id_type, db::properties_id_type> map;
|
||||
std::set<db::property_names_id_type> names_selected;
|
||||
|
||||
for (auto k = keys.begin (); k != keys.end (); ++k) {
|
||||
names_selected.insert (repo.prop_name_id (*k));
|
||||
}
|
||||
|
||||
db::PropertiesRepository org_repo = repo;
|
||||
|
||||
for (auto p = org_repo.begin (); p != org_repo.end (); ++p) {
|
||||
db::PropertiesRepository::properties_set new_set;
|
||||
for (auto i = p->second.begin (); i != p->second.end (); ++i) {
|
||||
if (names_selected.find (i->first) != names_selected.end ()) {
|
||||
new_set.insert (*i);
|
||||
}
|
||||
}
|
||||
if (! new_set.empty ()) {
|
||||
map.insert (std::make_pair (p->first, repo.properties_id (new_set)));
|
||||
}
|
||||
}
|
||||
|
||||
return PropertiesTranslator (map);
|
||||
}
|
||||
|
||||
PropertiesTranslator
|
||||
PropertiesTranslator::make_key_mapper (db::PropertiesRepository &repo, const std::map<tl::Variant, tl::Variant> &keys)
|
||||
{
|
||||
std::map<db::properties_id_type, db::properties_id_type> map;
|
||||
std::map<db::property_names_id_type, db::property_names_id_type> name_map;
|
||||
|
||||
for (auto k = keys.begin (); k != keys.end (); ++k) {
|
||||
name_map.insert (std::make_pair (repo.prop_name_id (k->first), repo.prop_name_id (k->second)));
|
||||
}
|
||||
|
||||
db::PropertiesRepository org_repo = repo;
|
||||
|
||||
for (auto p = org_repo.begin (); p != org_repo.end (); ++p) {
|
||||
db::PropertiesRepository::properties_set new_set;
|
||||
for (auto i = p->second.begin (); i != p->second.end (); ++i) {
|
||||
auto nm = name_map.find (i->first);
|
||||
if (nm != name_map.end ()) {
|
||||
new_set.insert (std::make_pair (nm->second, i->second));
|
||||
}
|
||||
}
|
||||
if (! new_set.empty ()) {
|
||||
map.insert (std::make_pair (p->first, repo.properties_id (new_set)));
|
||||
}
|
||||
}
|
||||
|
||||
return PropertiesTranslator (map);
|
||||
}
|
||||
|
||||
|
||||
} // namespace db
|
||||
|
||||
|
|
|
|||
|
|
@ -63,6 +63,11 @@ public:
|
|||
*/
|
||||
PropertiesRepository (db::LayoutStateModel *state_model = 0);
|
||||
|
||||
/**
|
||||
* @brief Copy constructor
|
||||
*/
|
||||
PropertiesRepository (const PropertiesRepository &d);
|
||||
|
||||
/**
|
||||
* @brief Assignment
|
||||
*/
|
||||
|
|
@ -232,8 +237,117 @@ private:
|
|||
std::map <name_value_pair, properties_id_vector> m_properties_component_table;
|
||||
|
||||
db::LayoutStateModel *mp_state_model;
|
||||
};
|
||||
|
||||
PropertiesRepository (const PropertiesRepository &d);
|
||||
/**
|
||||
* @brief A map for selecting/translating properties
|
||||
*
|
||||
* The following rules apply:
|
||||
* - All non-mapped properties are mapped to 0 (removed)
|
||||
* - 0 is always mapped to 0
|
||||
* - Do not include key or value 0 in the map passed to the constructor
|
||||
*
|
||||
* A "pass translator" will pass all IDs unchanged.
|
||||
*
|
||||
* Note that a property translator - specifically the filters and
|
||||
* mappers created by "make_filter" and "make_key_mapper" - are snapshots.
|
||||
* As creating new filters will generate new property IDs for the mapping
|
||||
* targets, property translators generated previously may become invalid.
|
||||
* In general it is safe to concatenate new translators after old ones.
|
||||
* The old ones will not map the property IDs understood by the new ones,
|
||||
* but as such IDs cannot become input to the old translator, this should
|
||||
* not matter.
|
||||
*/
|
||||
|
||||
class DB_PUBLIC PropertiesTranslator
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor - this creates a null translator
|
||||
*/
|
||||
PropertiesTranslator ();
|
||||
|
||||
/**
|
||||
* @brief Creates a "pass all" (pass = true) or "remove all" (pass = false) translator
|
||||
*/
|
||||
PropertiesTranslator (bool pass);
|
||||
|
||||
/**
|
||||
* @brief Creates a property ID mapper from a table
|
||||
*/
|
||||
PropertiesTranslator (const std::map<db::properties_id_type, db::properties_id_type> &map);
|
||||
|
||||
/**
|
||||
* @brief Gets a value indicating whether the translator is "pass"
|
||||
*/
|
||||
bool is_pass () const
|
||||
{
|
||||
return m_pass;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets a value indicating whether the translator is "empty" (remove all)
|
||||
*/
|
||||
bool is_empty () const
|
||||
{
|
||||
return ! m_pass && m_map.empty ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets a value indicating whether the translator is "null" (default-constructed)
|
||||
*/
|
||||
bool is_null () const
|
||||
{
|
||||
return m_null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Concatenates two translators (the right one first)
|
||||
*/
|
||||
PropertiesTranslator operator* (const PropertiesTranslator &other) const;
|
||||
|
||||
/**
|
||||
* @brief Concatenates two translators (the right one first) - in place version
|
||||
*/
|
||||
PropertiesTranslator &operator*= (const PropertiesTranslator &other)
|
||||
{
|
||||
*this = this->operator* (other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Translation of the property ID
|
||||
*/
|
||||
db::properties_id_type operator() (db::properties_id_type id) const;
|
||||
|
||||
/**
|
||||
* @brief Factory: create a "remove all" translator
|
||||
*/
|
||||
static PropertiesTranslator make_remove_all ();
|
||||
|
||||
/**
|
||||
* @brief Factory: create a "pass all" translator
|
||||
*/
|
||||
static PropertiesTranslator make_pass_all ();
|
||||
|
||||
/**
|
||||
* @brief Factory: create a filter translator
|
||||
*
|
||||
* The translator delivered by this function will leave only the given keys in the properties.
|
||||
*/
|
||||
static PropertiesTranslator make_filter (db::PropertiesRepository &repo, const std::set<tl::Variant> &keys);
|
||||
|
||||
/**
|
||||
* @brief Factory: create a key mapper translator
|
||||
*
|
||||
* The translator delivered by this function will translate the given keys to new ones
|
||||
* and remove non-listed keys.
|
||||
*/
|
||||
static PropertiesTranslator make_key_mapper (db::PropertiesRepository &repo, const std::map<tl::Variant, tl::Variant> &keys);
|
||||
|
||||
private:
|
||||
std::map<db::properties_id_type, db::properties_id_type> m_map;
|
||||
bool m_pass, m_null;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -0,0 +1,131 @@
|
|||
|
||||
/*
|
||||
|
||||
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"
|
||||
#include "dbTypes.h"
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Specifies a property constraint for some operations
|
||||
*/
|
||||
enum PropertyConstraint
|
||||
{
|
||||
/**
|
||||
* @brief Ignore properties
|
||||
*
|
||||
* In this mode, properties are not considered and erased.
|
||||
*/
|
||||
IgnoreProperties = 0,
|
||||
|
||||
/**
|
||||
* @brief No constraint, shapes are processed regardless of their properties
|
||||
*
|
||||
* Properties are attached to the outputs where applicable.
|
||||
*/
|
||||
NoPropertyConstraint = 1,
|
||||
|
||||
/**
|
||||
* @brief Shapes are processed if their properties are the same
|
||||
*
|
||||
* Properties are attached to the outputs where applicable.
|
||||
*/
|
||||
SamePropertiesConstraint = 2,
|
||||
|
||||
/**
|
||||
* @brief Shapes are processed if their properties are the same
|
||||
*
|
||||
* No properties are attached to the output.
|
||||
*/
|
||||
SamePropertiesConstraintDrop = 3,
|
||||
|
||||
/**
|
||||
* @brief Shapes are processed if their properties are different
|
||||
*
|
||||
* Properties are attached to the outputs where applicable.
|
||||
*/
|
||||
DifferentPropertiesConstraint = 4,
|
||||
|
||||
/**
|
||||
* @brief Shapes are processed if their properties are different
|
||||
*
|
||||
* No properties are attached to the output.
|
||||
*/
|
||||
DifferentPropertiesConstraintDrop = 5
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Returns a predicate indicating whether properties need to be considered
|
||||
*/
|
||||
bool inline pc_skip (PropertyConstraint pc)
|
||||
{
|
||||
return pc == IgnoreProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns a predicate indicating whether properties are always different
|
||||
*/
|
||||
bool inline pc_always_different (PropertyConstraint pc)
|
||||
{
|
||||
return pc == DifferentPropertiesConstraint || pc == DifferentPropertiesConstraintDrop;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns a value indicating whether two properties satisfy the condition
|
||||
*/
|
||||
bool inline pc_match (PropertyConstraint pc, db::properties_id_type a, db::properties_id_type b)
|
||||
{
|
||||
if (pc == SamePropertiesConstraint || pc == SamePropertiesConstraintDrop) {
|
||||
return a == b;
|
||||
} else if (pc == DifferentPropertiesConstraint || pc == DifferentPropertiesConstraintDrop) {
|
||||
return a != b;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns a value indicating whether the property can be removed on output
|
||||
*/
|
||||
bool inline pc_remove (PropertyConstraint pc)
|
||||
{
|
||||
return pc == IgnoreProperties || pc == SamePropertiesConstraintDrop || pc == DifferentPropertiesConstraintDrop;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns a normalized property for output
|
||||
*/
|
||||
db::properties_id_type inline pc_norm (PropertyConstraint pc, db::properties_id_type prop_id)
|
||||
{
|
||||
return pc_remove (pc) ? 0 : prop_id;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -73,6 +73,7 @@ RecursiveShapeIterator &RecursiveShapeIterator::operator= (const RecursiveShapeI
|
|||
m_shape = d.m_shape;
|
||||
m_trans = d.m_trans;
|
||||
m_global_trans = d.m_global_trans;
|
||||
m_property_translator = d.m_property_translator;
|
||||
m_trans_stack = d.m_trans_stack;
|
||||
m_inst_iterators = d.m_inst_iterators;
|
||||
m_inst_array_iterators = d.m_inst_array_iterators;
|
||||
|
|
@ -284,6 +285,7 @@ RecursiveShapeIterator::init ()
|
|||
mp_cell = 0;
|
||||
m_current_layer = 0;
|
||||
m_global_trans = cplx_trans_type ();
|
||||
m_property_translator = db::PropertiesTranslator ();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -320,6 +320,41 @@ public:
|
|||
return mp_top_cell;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the installed property translator
|
||||
*
|
||||
* The property translator is not automatically applied, but available to consumers
|
||||
* of shapes to perform property translation.
|
||||
*/
|
||||
const db::PropertiesTranslator &property_translator () const
|
||||
{
|
||||
return m_property_translator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Applies a PropertyTranslator
|
||||
*
|
||||
* The property translator is available for receivers of the recursive shape
|
||||
* iterator items. This method will apply an additional property translator
|
||||
* atop of existing ones.
|
||||
*/
|
||||
void apply_property_translator (const db::PropertiesTranslator &pt)
|
||||
{
|
||||
m_property_translator = pt * m_property_translator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets a PropertyTranslator
|
||||
*
|
||||
* The property translator is available for receivers of the recursive shape
|
||||
* iterator items. This method will apply an additional property translator
|
||||
* atop of existing ones.
|
||||
*/
|
||||
void set_property_translator (const db::PropertiesTranslator &pt)
|
||||
{
|
||||
m_property_translator = pt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the basic region the iterator is using (will be world if none is set)
|
||||
* In addition to the basic region, a complex region may be defined that is further confining the
|
||||
|
|
@ -648,6 +683,21 @@ public:
|
|||
*/
|
||||
bool at_end () const;
|
||||
|
||||
/**
|
||||
* @brief Gets the translated property ID
|
||||
*
|
||||
* This version employs the property translator to deliver the real property ID.
|
||||
*/
|
||||
db::properties_id_type prop_id () const
|
||||
{
|
||||
if (m_property_translator.is_null ()) {
|
||||
return 0;
|
||||
} else {
|
||||
validate (0);
|
||||
return m_property_translator (m_shape->prop_id ());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the current cell's index
|
||||
*/
|
||||
|
|
@ -765,6 +815,7 @@ private:
|
|||
bool m_overlapping;
|
||||
std::set<db::cell_index_type> m_start, m_stop;
|
||||
cplx_trans_type m_global_trans;
|
||||
db::PropertiesTranslator m_property_translator;
|
||||
|
||||
tl::weak_ptr<layout_type> mp_layout;
|
||||
const cell_type *mp_top_cell;
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ const db::RecursiveShapeIterator &
|
|||
Region::iter () const
|
||||
{
|
||||
static db::RecursiveShapeIterator def_iter;
|
||||
const db::RecursiveShapeIterator *i = mp_delegate->iter ();
|
||||
const db::RecursiveShapeIterator *i = mp_delegate ? mp_delegate->iter () : 0;
|
||||
return *(i ? i : &def_iter);
|
||||
}
|
||||
|
||||
|
|
@ -155,9 +155,13 @@ void Region::insert (const Sh &shape)
|
|||
}
|
||||
|
||||
template DB_PUBLIC void Region::insert (const db::Box &);
|
||||
template DB_PUBLIC void Region::insert (const db::BoxWithProperties &);
|
||||
template DB_PUBLIC void Region::insert (const db::SimplePolygon &);
|
||||
template DB_PUBLIC void Region::insert (const db::SimplePolygonWithProperties &);
|
||||
template DB_PUBLIC void Region::insert (const db::Polygon &);
|
||||
template DB_PUBLIC void Region::insert (const db::PolygonWithProperties &);
|
||||
template DB_PUBLIC void Region::insert (const db::Path &);
|
||||
template DB_PUBLIC void Region::insert (const db::PathWithProperties &);
|
||||
|
||||
void Region::insert (const db::Shape &shape)
|
||||
{
|
||||
|
|
@ -197,35 +201,35 @@ Region::mutable_region ()
|
|||
}
|
||||
|
||||
EdgePairs
|
||||
Region::cop_to_edge_pairs (db::CompoundRegionOperationNode &node)
|
||||
Region::cop_to_edge_pairs (db::CompoundRegionOperationNode &node, db::PropertyConstraint prop_constraint)
|
||||
{
|
||||
tl_assert (node.result_type () == db::CompoundRegionOperationNode::EdgePairs);
|
||||
return EdgePairs (mp_delegate->cop_to_edge_pairs (node));
|
||||
return EdgePairs (mp_delegate->cop_to_edge_pairs (node, prop_constraint));
|
||||
}
|
||||
|
||||
Region
|
||||
Region::cop_to_region (db::CompoundRegionOperationNode &node)
|
||||
Region::cop_to_region (db::CompoundRegionOperationNode &node, db::PropertyConstraint prop_constraint)
|
||||
{
|
||||
tl_assert (node.result_type () == db::CompoundRegionOperationNode::Region);
|
||||
return Region (mp_delegate->cop_to_region (node));
|
||||
return Region (mp_delegate->cop_to_region (node, prop_constraint));
|
||||
}
|
||||
|
||||
Edges
|
||||
Region::cop_to_edges (db::CompoundRegionOperationNode &node)
|
||||
Region::cop_to_edges (db::CompoundRegionOperationNode &node, db::PropertyConstraint prop_constraint)
|
||||
{
|
||||
tl_assert (node.result_type () == db::CompoundRegionOperationNode::Edges);
|
||||
return Edges (mp_delegate->cop_to_edges (node));
|
||||
return Edges (mp_delegate->cop_to_edges (node, prop_constraint));
|
||||
}
|
||||
|
||||
tl::Variant
|
||||
Region::cop (db::CompoundRegionOperationNode &node)
|
||||
Region::cop (db::CompoundRegionOperationNode &node, db::PropertyConstraint prop_constraint)
|
||||
{
|
||||
if (node.result_type () == db::CompoundRegionOperationNode::EdgePairs) {
|
||||
return tl::Variant::make_variant (new EdgePairs (mp_delegate->cop_to_edge_pairs (node)));
|
||||
return tl::Variant::make_variant (new EdgePairs (mp_delegate->cop_to_edge_pairs (node, prop_constraint)));
|
||||
} else if (node.result_type () == db::CompoundRegionOperationNode::Edges) {
|
||||
return tl::Variant::make_variant (new Edges (mp_delegate->cop_to_edges (node)));
|
||||
return tl::Variant::make_variant (new Edges (mp_delegate->cop_to_edges (node, prop_constraint)));
|
||||
} else if (node.result_type () == db::CompoundRegionOperationNode::Region) {
|
||||
return tl::Variant::make_variant (new Region (mp_delegate->cop_to_region (node)));
|
||||
return tl::Variant::make_variant (new Region (mp_delegate->cop_to_region (node, prop_constraint)));
|
||||
} else {
|
||||
return tl::Variant ();
|
||||
}
|
||||
|
|
@ -376,6 +380,8 @@ static void fill_texts (const Iter &iter, const std::string &pat, bool pattern,
|
|||
const db::Layout *layout = 0;
|
||||
|
||||
if (org_deep) {
|
||||
// NOTE: deep regions can store texts in a special way - as small boxes with a special property attached.
|
||||
// The property will give the text string. This function can restore these pseudo-texts as Text objects.
|
||||
layout = &org_deep->deep_layer ().layout ();
|
||||
const db::DeepShapeStore *store = org_deep->deep_layer ().store ();
|
||||
if (! store->text_property_name ().is_nil ()) {
|
||||
|
|
@ -451,7 +457,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
virtual void push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box ®ion, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
|
||||
virtual void push (const db::Shape &shape, db::properties_id_type, const db::ICplxTrans &trans, const db::Box ®ion, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
|
||||
{
|
||||
bool is_text = false;
|
||||
std::string text_string;
|
||||
|
|
@ -494,8 +500,8 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
virtual void push (const db::Box &, const db::ICplxTrans &, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *) { }
|
||||
virtual void push (const db::Polygon &, const db::ICplxTrans &, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *) { }
|
||||
virtual void push (const db::Box &, db::properties_id_type, const db::ICplxTrans &, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *) { }
|
||||
virtual void push (const db::Polygon &, db::properties_id_type, const db::ICplxTrans &, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *) { }
|
||||
|
||||
private:
|
||||
Delivery m_delivery;
|
||||
|
|
|
|||
|
|
@ -43,62 +43,7 @@ class DeepShapeStore;
|
|||
class TransformationReducer;
|
||||
class CompoundRegionOperationNode;
|
||||
|
||||
/**
|
||||
* @brief A region iterator
|
||||
*
|
||||
* The iterator delivers the polygons of the region
|
||||
*/
|
||||
class DB_PUBLIC RegionIterator
|
||||
: public generic_shape_iterator<db::Polygon>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor
|
||||
*/
|
||||
RegionIterator ()
|
||||
: generic_shape_iterator<db::Polygon> ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Constructor from a delegate
|
||||
* The iterator will take ownership over the delegate
|
||||
*/
|
||||
RegionIterator (RegionIteratorDelegate *delegate)
|
||||
: generic_shape_iterator<db::Polygon> (delegate)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Copy constructor and assignment
|
||||
*/
|
||||
RegionIterator (const RegionIterator &other)
|
||||
: generic_shape_iterator<db::Polygon> (static_cast<const generic_shape_iterator<db::Polygon> &> (other))
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assignment
|
||||
*/
|
||||
RegionIterator &operator= (const RegionIterator &other)
|
||||
{
|
||||
generic_shape_iterator<db::Polygon>::operator= (other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Increment
|
||||
*/
|
||||
RegionIterator &operator++ ()
|
||||
{
|
||||
generic_shape_iterator<db::Polygon>::operator++ ();
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
typedef generic_shape_iterator<db::Polygon> RegionIterator;
|
||||
typedef addressable_shape_delivery<db::Polygon> AddressablePolygonDelivery;
|
||||
|
||||
/**
|
||||
|
|
@ -168,6 +113,15 @@ public:
|
|||
insert (s);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Constructor from a box with properties
|
||||
*/
|
||||
explicit Region (const db::BoxWithProperties &s)
|
||||
: mp_delegate (0)
|
||||
{
|
||||
insert (s);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Constructor from a polygon
|
||||
*/
|
||||
|
|
@ -177,6 +131,15 @@ public:
|
|||
insert (s);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Constructor from a polygon with properties
|
||||
*/
|
||||
explicit Region (const db::PolygonWithProperties &s)
|
||||
: mp_delegate (0)
|
||||
{
|
||||
insert (s);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Constructor from a simple polygon
|
||||
*/
|
||||
|
|
@ -186,6 +149,15 @@ public:
|
|||
insert (s);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Constructor from a simple polygon with properties
|
||||
*/
|
||||
explicit Region (const db::SimplePolygonWithProperties &s)
|
||||
: mp_delegate (0)
|
||||
{
|
||||
insert (s);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Constructor from a path
|
||||
*/
|
||||
|
|
@ -195,6 +167,15 @@ public:
|
|||
insert (s);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Constructor from a path with properties
|
||||
*/
|
||||
explicit Region (const db::PathWithProperties &s)
|
||||
: mp_delegate (0)
|
||||
{
|
||||
insert (s);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sequence constructor
|
||||
*
|
||||
|
|
@ -262,7 +243,15 @@ public:
|
|||
/**
|
||||
* @brief Gets the underlying delegate object
|
||||
*/
|
||||
RegionDelegate *delegate () const
|
||||
const RegionDelegate *delegate () const
|
||||
{
|
||||
return mp_delegate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the underlying delegate object
|
||||
*/
|
||||
RegionDelegate *delegate ()
|
||||
{
|
||||
return mp_delegate;
|
||||
}
|
||||
|
|
@ -624,7 +613,7 @@ public:
|
|||
* The compound operation needs to feature edge pair output, e.g.
|
||||
* node.result_type() needs to be EdgePairs.
|
||||
*/
|
||||
EdgePairs cop_to_edge_pairs (db::CompoundRegionOperationNode &node);
|
||||
EdgePairs cop_to_edge_pairs (db::CompoundRegionOperationNode &node, PropertyConstraint prop_constraint = db::IgnoreProperties);
|
||||
|
||||
/**
|
||||
* @brief Performs a compound operation rendering a region
|
||||
|
|
@ -632,7 +621,7 @@ public:
|
|||
* The compound operation needs to feature region output, e.g.
|
||||
* node.result_type() needs to be Region.
|
||||
*/
|
||||
Region cop_to_region (db::CompoundRegionOperationNode &node);
|
||||
Region cop_to_region (db::CompoundRegionOperationNode &node, PropertyConstraint prop_constraint = db::IgnoreProperties);
|
||||
|
||||
/**
|
||||
* @brief Performs a compound operation rendering edges
|
||||
|
|
@ -640,7 +629,7 @@ public:
|
|||
* The compound operation needs to feature region output, e.g.
|
||||
* node.result_type() needs to be Edges.
|
||||
*/
|
||||
Edges cop_to_edges (db::CompoundRegionOperationNode &node);
|
||||
Edges cop_to_edges (db::CompoundRegionOperationNode &node, PropertyConstraint prop_constraint = db::IgnoreProperties);
|
||||
|
||||
/**
|
||||
* @brief A universal form of the compound operation
|
||||
|
|
@ -648,7 +637,7 @@ public:
|
|||
* The returned variant will be of the type requested by the
|
||||
* compound operation node.
|
||||
*/
|
||||
tl::Variant cop (db::CompoundRegionOperationNode &node);
|
||||
tl::Variant cop (db::CompoundRegionOperationNode &node, PropertyConstraint prop_constraint = db::IgnoreProperties);
|
||||
|
||||
/**
|
||||
* @brief Applies a width check and returns EdgePairs which correspond to violation markers
|
||||
|
|
@ -992,7 +981,15 @@ public:
|
|||
*/
|
||||
Region operator& (const Region &other) const
|
||||
{
|
||||
return Region (mp_delegate->and_with (other));
|
||||
return Region (mp_delegate->and_with (other, db::IgnoreProperties));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Boolean AND operator with options
|
||||
*/
|
||||
Region bool_and (const Region &other, PropertyConstraint prop_constraint = db::IgnoreProperties) const
|
||||
{
|
||||
return Region (mp_delegate->and_with (other, prop_constraint));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1003,7 +1000,19 @@ public:
|
|||
*/
|
||||
Region &operator&= (const Region &other)
|
||||
{
|
||||
set_delegate (mp_delegate->and_with (other));
|
||||
set_delegate (mp_delegate->and_with (other, db::IgnoreProperties));
|
||||
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::IgnoreProperties)
|
||||
{
|
||||
set_delegate (mp_delegate->and_with (other, prop_constraint));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -1012,7 +1021,15 @@ public:
|
|||
*/
|
||||
Region operator- (const Region &other) const
|
||||
{
|
||||
return Region (mp_delegate->not_with (other));
|
||||
return Region (mp_delegate->not_with (other, db::IgnoreProperties));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Boolean NOT operator with options
|
||||
*/
|
||||
Region bool_not (const Region &other, PropertyConstraint prop_constraint = db::IgnoreProperties) const
|
||||
{
|
||||
return Region (mp_delegate->not_with (other, prop_constraint));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1023,7 +1040,19 @@ public:
|
|||
*/
|
||||
Region &operator-= (const Region &other)
|
||||
{
|
||||
set_delegate (mp_delegate->not_with (other));
|
||||
set_delegate (mp_delegate->not_with (other, db::IgnoreProperties));
|
||||
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::IgnoreProperties)
|
||||
{
|
||||
set_delegate (mp_delegate->not_with (other, prop_constraint));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -1032,7 +1061,17 @@ public:
|
|||
*/
|
||||
Region operator^ (const Region &other) const
|
||||
{
|
||||
return Region (mp_delegate->xor_with (other));
|
||||
return Region (mp_delegate->xor_with (other, db::IgnoreProperties));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Boolean XOR operator with options
|
||||
*
|
||||
* TODO: property constraints are not implemented properly yet.
|
||||
*/
|
||||
Region bool_xor (const Region &other, PropertyConstraint prop_constraint = db::IgnoreProperties) const
|
||||
{
|
||||
return Region (mp_delegate->xor_with (other, prop_constraint));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1043,7 +1082,21 @@ public:
|
|||
*/
|
||||
Region &operator^= (const Region &other)
|
||||
{
|
||||
set_delegate (mp_delegate->xor_with (other));
|
||||
set_delegate (mp_delegate->xor_with (other, db::IgnoreProperties));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief In-place boolean XOR operator with options
|
||||
*
|
||||
* This method does not necessarily merge the region. To ensure the region
|
||||
* is merged, call merge afterwards.
|
||||
*
|
||||
* TODO: property constraints are not implemented properly yet.
|
||||
*/
|
||||
Region &bool_xor_with (const Region &other, PropertyConstraint prop_constraint = db::IgnoreProperties)
|
||||
{
|
||||
set_delegate (mp_delegate->xor_with (other, prop_constraint));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -1054,7 +1107,19 @@ public:
|
|||
*/
|
||||
Region operator| (const Region &other) const
|
||||
{
|
||||
return Region (mp_delegate->or_with (other));
|
||||
return Region (mp_delegate->or_with (other, db::IgnoreProperties));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Boolean OR operator with options
|
||||
*
|
||||
* This method merges the polygons of both regions.
|
||||
*
|
||||
* TODO: property constraints are not implemented properly yet.
|
||||
*/
|
||||
Region bool_or (const Region &other, PropertyConstraint prop_constraint = db::IgnoreProperties) const
|
||||
{
|
||||
return Region (mp_delegate->or_with (other, prop_constraint));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1062,7 +1127,18 @@ public:
|
|||
*/
|
||||
Region &operator|= (const Region &other)
|
||||
{
|
||||
set_delegate (mp_delegate->or_with (other));
|
||||
set_delegate (mp_delegate->or_with (other, db::IgnoreProperties));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief In-place boolean OR operator with options
|
||||
*
|
||||
* TODO: property constraints are not implemented properly yet.
|
||||
*/
|
||||
Region &bool_or_with (const Region &other, PropertyConstraint prop_constraint = db::IgnoreProperties)
|
||||
{
|
||||
set_delegate (mp_delegate->or_with (other, prop_constraint));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -1090,9 +1166,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::IgnoreProperties) 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));
|
||||
}
|
||||
|
||||
|
|
@ -1652,6 +1728,17 @@ public:
|
|||
return mp_delegate->nth (n);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the nth polygon's property ID
|
||||
*
|
||||
* This operation is available only for flat regions - i.e. such for which
|
||||
* "has_valid_polygons" is true.
|
||||
*/
|
||||
db::properties_id_type nth_prop_id (size_t n) const
|
||||
{
|
||||
return mp_delegate->nth_prop_id (n);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Forces flattening of the region
|
||||
*
|
||||
|
|
@ -1743,6 +1830,20 @@ public:
|
|||
return mp_delegate->insert_into (layout, into_cell, into_layer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Pulls the net shapes from a LayoutToNetlist database
|
||||
*
|
||||
* This will pull the net shapes from the LayoutToNetlist database, provided that this
|
||||
* layer was an input to the netlist extraction.
|
||||
*
|
||||
* Netlist names will be attached as properties according to prop_mode and net_prop_name.
|
||||
* A net filter can be provided so that only certain nets are produced.
|
||||
*/
|
||||
Region nets (LayoutToNetlist &l2n, NetPropertyMode prop_mode = db::NPM_NoProperties, const tl::Variant &net_prop_name = tl::Variant (0), const std::vector<const db::Net *> *nets = 0) const
|
||||
{
|
||||
return Region (mp_delegate->nets (&l2n, prop_mode, net_prop_name, nets));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Delivers texts as dots (degenerated edges)
|
||||
*
|
||||
|
|
|
|||
|
|
@ -156,14 +156,14 @@ class DB_PUBLIC_TEMPLATE edge2edge_check
|
|||
: public Edge2EdgeCheckBase
|
||||
{
|
||||
public:
|
||||
edge2edge_check (const EdgeRelationFilter &check, Output &output, bool different_polygons, bool requires_different_layers, bool with_shielding, bool symmetric_edges)
|
||||
: Edge2EdgeCheckBase (check, different_polygons, requires_different_layers, with_shielding, symmetric_edges), mp_output_inter (&output), mp_output_intra (0)
|
||||
edge2edge_check (const EdgeRelationFilter &check, Output &output, bool different_polygons, bool requires_different_layers, bool with_shielding, bool symmetric_edges, db::properties_id_type prop_id = 0)
|
||||
: Edge2EdgeCheckBase (check, different_polygons, requires_different_layers, with_shielding, symmetric_edges), mp_output_inter (&output), mp_output_intra (0), m_prop_id (prop_id)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
edge2edge_check (const EdgeRelationFilter &check, Output &output_inter, Output &output_intra, bool different_polygons, bool requires_different_layers, bool with_shielding, bool symmetric_edges)
|
||||
: Edge2EdgeCheckBase (check, different_polygons, requires_different_layers, with_shielding, symmetric_edges), mp_output_inter (&output_inter), mp_output_intra (&output_intra)
|
||||
edge2edge_check (const EdgeRelationFilter &check, Output &output_inter, Output &output_intra, bool different_polygons, bool requires_different_layers, bool with_shielding, bool symmetric_edges, db::properties_id_type prop_id = 0)
|
||||
: Edge2EdgeCheckBase (check, different_polygons, requires_different_layers, with_shielding, symmetric_edges), mp_output_inter (&output_inter), mp_output_intra (&output_intra), m_prop_id (prop_id)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
|
@ -172,15 +172,24 @@ protected:
|
|||
void put (const db::EdgePair &edge, bool inter_polygon) const
|
||||
{
|
||||
if (! inter_polygon || ! mp_output_intra) {
|
||||
mp_output_inter->insert (edge);
|
||||
if (m_prop_id != 0) {
|
||||
mp_output_inter->insert (db::EdgePairWithProperties(edge, m_prop_id));
|
||||
} else {
|
||||
mp_output_inter->insert (edge);
|
||||
}
|
||||
} else {
|
||||
mp_output_intra->insert (edge);
|
||||
if (m_prop_id != 0) {
|
||||
mp_output_intra->insert (db::EdgePairWithProperties(edge, m_prop_id));
|
||||
} else {
|
||||
mp_output_intra->insert (edge);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Output *mp_output_inter;
|
||||
Output *mp_output_intra;
|
||||
db::properties_id_type m_prop_id;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -194,16 +203,16 @@ class DB_PUBLIC_TEMPLATE edge2edge_check_with_negative_output
|
|||
: public edge2edge_check<Output>
|
||||
{
|
||||
public:
|
||||
edge2edge_check_with_negative_output (const EdgeRelationFilter &check, Output &output, NegativeEdgeOutput &l1_negative_output, NegativeEdgeOutput &l2_negative_output, bool different_polygons, bool requires_different_layers, bool with_shielding, bool symmetric_edges)
|
||||
: edge2edge_check<Output> (check, output, different_polygons, requires_different_layers, with_shielding, symmetric_edges),
|
||||
edge2edge_check_with_negative_output (const EdgeRelationFilter &check, Output &output, NegativeEdgeOutput &l1_negative_output, NegativeEdgeOutput &l2_negative_output, bool different_polygons, bool requires_different_layers, bool with_shielding, bool symmetric_edges, db::properties_id_type prop_id = 0)
|
||||
: edge2edge_check<Output> (check, output, different_polygons, requires_different_layers, with_shielding, symmetric_edges, prop_id),
|
||||
mp_l1_negative_output (&l1_negative_output),
|
||||
mp_l2_negative_output (&l2_negative_output)
|
||||
{
|
||||
edge2edge_check<Output>::set_has_negative_edge_output (true);
|
||||
}
|
||||
|
||||
edge2edge_check_with_negative_output (const EdgeRelationFilter &check, Output &output_inter, Output &output_intra, NegativeEdgeOutput &l1_negative_output, NegativeEdgeOutput &l2_negative_output, bool different_polygons, bool requires_different_layers, bool with_shielding, bool symmetric_edges)
|
||||
: edge2edge_check<Output> (check, output_inter, output_intra, different_polygons, requires_different_layers, with_shielding, symmetric_edges),
|
||||
edge2edge_check_with_negative_output (const EdgeRelationFilter &check, Output &output_inter, Output &output_intra, NegativeEdgeOutput &l1_negative_output, NegativeEdgeOutput &l2_negative_output, bool different_polygons, bool requires_different_layers, bool with_shielding, bool symmetric_edges, db::properties_id_type prop_id = 0)
|
||||
: edge2edge_check<Output> (check, output_inter, output_intra, different_polygons, requires_different_layers, with_shielding, symmetric_edges, prop_id),
|
||||
mp_l1_negative_output (&l1_negative_output),
|
||||
mp_l2_negative_output (&l2_negative_output)
|
||||
{
|
||||
|
|
@ -272,15 +281,15 @@ class DB_PUBLIC_TEMPLATE edge2edge_check_negative_or_positive
|
|||
: public edge2edge_check<Output>
|
||||
{
|
||||
public:
|
||||
edge2edge_check_negative_or_positive (const EdgeRelationFilter &check, Output &output, bool negative_output, bool different_polygons, bool requires_different_layers, bool with_shielding, bool symmetric)
|
||||
: edge2edge_check<Output> (check, output, different_polygons, requires_different_layers, with_shielding, symmetric)
|
||||
edge2edge_check_negative_or_positive (const EdgeRelationFilter &check, Output &output, bool negative_output, bool different_polygons, bool requires_different_layers, bool with_shielding, bool symmetric, db::properties_id_type prop_id = 0)
|
||||
: edge2edge_check<Output> (check, output, different_polygons, requires_different_layers, with_shielding, symmetric, prop_id)
|
||||
{
|
||||
edge2edge_check<Output>::set_has_negative_edge_output (negative_output);
|
||||
edge2edge_check<Output>::set_has_edge_pair_output (! negative_output);
|
||||
}
|
||||
|
||||
edge2edge_check_negative_or_positive (const EdgeRelationFilter &check, Output &output_inter, Output &output_intra, bool negative_output, bool different_polygons, bool requires_different_layers, bool with_shielding, bool symmetric)
|
||||
: edge2edge_check<Output> (check, output_inter, output_intra, different_polygons, requires_different_layers, with_shielding, symmetric)
|
||||
edge2edge_check_negative_or_positive (const EdgeRelationFilter &check, Output &output_inter, Output &output_intra, bool negative_output, bool different_polygons, bool requires_different_layers, bool with_shielding, bool symmetric, db::properties_id_type prop_id = 0)
|
||||
: edge2edge_check<Output> (check, output_inter, output_intra, different_polygons, requires_different_layers, with_shielding, symmetric, prop_id)
|
||||
{
|
||||
edge2edge_check<Output>::set_has_negative_edge_output (negative_output);
|
||||
edge2edge_check<Output>::set_has_edge_pair_output (! negative_output);
|
||||
|
|
|
|||
|
|
@ -35,8 +35,10 @@
|
|||
#include "dbGenericShapeIterator.h"
|
||||
#include "dbRegionLocalOperations.h"
|
||||
#include "dbHash.h"
|
||||
#include "dbLayoutToNetlistEnums.h"
|
||||
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace db {
|
||||
|
|
@ -46,6 +48,8 @@ class EdgeFilterBase;
|
|||
class EdgesDelegate;
|
||||
class EdgePairsDelegate;
|
||||
class CompoundRegionOperationNode;
|
||||
class LayoutToNetlist;
|
||||
class Net;
|
||||
|
||||
/**
|
||||
* @brief A base class for polygon filters
|
||||
|
|
@ -192,6 +196,12 @@ public:
|
|||
|
||||
virtual RegionDelegate *clone () const = 0;
|
||||
|
||||
RegionDelegate *remove_properties (bool remove = true)
|
||||
{
|
||||
ShapeCollectionDelegateBase::remove_properties (remove);
|
||||
return this;
|
||||
}
|
||||
|
||||
void set_base_verbosity (int vb);
|
||||
int base_verbosity () const
|
||||
{
|
||||
|
|
@ -237,9 +247,9 @@ public:
|
|||
virtual perimeter_type perimeter (const db::Box &box) const = 0;
|
||||
virtual Box bbox () const = 0;
|
||||
|
||||
virtual EdgePairsDelegate *cop_to_edge_pairs (db::CompoundRegionOperationNode &node) = 0;
|
||||
virtual RegionDelegate *cop_to_region (db::CompoundRegionOperationNode &node) = 0;
|
||||
virtual EdgesDelegate *cop_to_edges (db::CompoundRegionOperationNode &node) = 0;
|
||||
virtual EdgePairsDelegate *cop_to_edge_pairs (db::CompoundRegionOperationNode &node, db::PropertyConstraint prop_constraint) = 0;
|
||||
virtual RegionDelegate *cop_to_region (db::CompoundRegionOperationNode &node, db::PropertyConstraint prop_constraint) = 0;
|
||||
virtual EdgesDelegate *cop_to_edges (db::CompoundRegionOperationNode &node, db::PropertyConstraint prop_constraint) = 0;
|
||||
|
||||
virtual EdgePairsDelegate *width_check (db::Coord d, const RegionCheckOptions &options) const = 0;
|
||||
virtual EdgePairsDelegate *space_check (db::Coord d, const RegionCheckOptions &options) const = 0;
|
||||
|
|
@ -273,13 +283,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 *xor_with (const Region &other) const = 0;
|
||||
virtual RegionDelegate *or_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, PropertyConstraint prop_constraint) const = 0;
|
||||
virtual RegionDelegate *or_with (const Region &other, PropertyConstraint prop_constraint) 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;
|
||||
|
|
@ -311,16 +321,23 @@ public:
|
|||
virtual std::pair<RegionDelegate *, RegionDelegate *> in_and_out (const Region &other) const = 0;
|
||||
|
||||
virtual const db::Polygon *nth (size_t n) const = 0;
|
||||
virtual db::properties_id_type nth_prop_id (size_t n) const = 0;
|
||||
virtual bool has_valid_polygons () const = 0;
|
||||
virtual bool has_valid_merged_polygons () const = 0;
|
||||
|
||||
virtual const db::RecursiveShapeIterator *iter () const = 0;
|
||||
|
||||
virtual void apply_property_translator (const db::PropertiesTranslator &pt) = 0;
|
||||
virtual db::PropertiesRepository *properties_repository () = 0;
|
||||
virtual const db::PropertiesRepository *properties_repository () const = 0;
|
||||
|
||||
virtual bool equals (const Region &other) const = 0;
|
||||
virtual bool less (const Region &other) const = 0;
|
||||
|
||||
virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const = 0;
|
||||
|
||||
virtual RegionDelegate *nets (LayoutToNetlist *l2n, NetPropertyMode prop_mode, const tl::Variant &net_prop_name, const std::vector<const db::Net *> *net_filter) const = 0;
|
||||
|
||||
const std::string &progress_desc () const
|
||||
{
|
||||
return m_progress_desc;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -27,8 +27,11 @@
|
|||
#include "dbCommon.h"
|
||||
#include "dbEdgePairRelations.h"
|
||||
#include "dbLocalOperation.h"
|
||||
#include "dbLocalOperationUtils.h"
|
||||
#include "dbEdgeProcessor.h"
|
||||
#include "dbRegionCheckUtils.h"
|
||||
#include "dbPropertyConstraint.h"
|
||||
#include "dbLayoutUtils.h"
|
||||
|
||||
#include <vector>
|
||||
#include <unordered_set>
|
||||
|
|
@ -124,7 +127,8 @@ struct DB_PUBLIC RegionCheckOptions
|
|||
bool _shielded = true,
|
||||
OppositeFilter _opposite_filter = NoOppositeFilter,
|
||||
RectFilter _rect_filter = NoRectFilter,
|
||||
bool _negative = false)
|
||||
bool _negative = false,
|
||||
PropertyConstraint _prop_constraint = IgnoreProperties)
|
||||
: whole_edges (_whole_edges),
|
||||
metrics (_metrics),
|
||||
ignore_angle (_ignore_angle),
|
||||
|
|
@ -133,7 +137,8 @@ struct DB_PUBLIC RegionCheckOptions
|
|||
shielded (_shielded),
|
||||
opposite_filter (_opposite_filter),
|
||||
rect_filter (_rect_filter),
|
||||
negative (_negative)
|
||||
negative (_negative),
|
||||
prop_constraint (_prop_constraint)
|
||||
{ }
|
||||
|
||||
/**
|
||||
|
|
@ -198,6 +203,11 @@ struct DB_PUBLIC RegionCheckOptions
|
|||
*/
|
||||
bool negative;
|
||||
|
||||
/**
|
||||
* @brief Specifies a property constraint - e.g. checking only shapes with the same properties
|
||||
*/
|
||||
PropertyConstraint prop_constraint;
|
||||
|
||||
/**
|
||||
* @brief Gets a value indicating whether merged primary input is required
|
||||
*/
|
||||
|
|
@ -212,9 +222,28 @@ struct DB_PUBLIC RegionCheckOptions
|
|||
}
|
||||
};
|
||||
|
||||
template <class TS, class TI>
|
||||
class check_local_operation_base
|
||||
{
|
||||
public:
|
||||
check_local_operation_base (const EdgeRelationFilter &check, bool different_polygons, bool is_merged, bool has_other, bool other_is_merged, const db::RegionCheckOptions &options);
|
||||
|
||||
protected:
|
||||
EdgeRelationFilter m_check;
|
||||
bool m_different_polygons;
|
||||
bool m_is_merged;
|
||||
bool m_has_other;
|
||||
bool m_other_is_merged;
|
||||
db::RegionCheckOptions m_options;
|
||||
|
||||
void compute_results (db::Layout *layout, const std::vector<const TS *> &subjects, const std::set<const TI *> &intruders, std::unordered_set<db::EdgePair> &result, std::unordered_set<db::EdgePair> &intra_polygon_result) const;
|
||||
void apply_opposite_filter (const std::vector<const TS *> &subjects, std::unordered_set<db::EdgePair> &result, std::unordered_set<db::EdgePair> &intra_polygon_result) const;
|
||||
void apply_rectangle_filter (const std::vector<const TS *> &subjects, std::unordered_set<db::EdgePair> &result) const;
|
||||
};
|
||||
|
||||
template <class TS, class TI>
|
||||
class check_local_operation
|
||||
: public local_operation<TS, TI, db::EdgePair>
|
||||
: public local_operation<TS, TI, db::EdgePair>, public check_local_operation_base<TS, TI>
|
||||
{
|
||||
public:
|
||||
check_local_operation (const EdgeRelationFilter &check, bool different_polygons, bool is_merged, bool has_other, bool other_is_merged, const db::RegionCheckOptions &options);
|
||||
|
|
@ -225,14 +254,24 @@ public:
|
|||
virtual std::string description () const;
|
||||
|
||||
virtual void do_compute_local (db::Layout * /*layout*/, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<db::EdgePair> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const;
|
||||
};
|
||||
|
||||
template <class TS, class TI>
|
||||
class check_local_operation_with_properties
|
||||
: public local_operation<db::object_with_properties<TS>, db::object_with_properties<TI>, db::EdgePairWithProperties>, public check_local_operation_base<TS, TI>
|
||||
{
|
||||
public:
|
||||
check_local_operation_with_properties (const EdgeRelationFilter &check, bool different_polygons, bool is_merged, bool has_other, bool other_is_merged, const db::RegionCheckOptions &options, db::PropertiesRepository *target_pr, const db::PropertiesRepository *subject_pr, const db::PropertiesRepository *intruder_pr);
|
||||
|
||||
virtual db::Coord dist () const;
|
||||
virtual OnEmptyIntruderHint on_empty_intruder_hint () const;
|
||||
virtual bool requests_single_subjects () const { return true; }
|
||||
virtual std::string description () const;
|
||||
|
||||
virtual void do_compute_local (db::Layout * /*layout*/, const shape_interactions<db::object_with_properties<TS>, db::object_with_properties<TI> > &interactions, std::vector<std::unordered_set<db::EdgePairWithProperties> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const;
|
||||
|
||||
private:
|
||||
EdgeRelationFilter m_check;
|
||||
bool m_different_polygons;
|
||||
bool m_is_merged;
|
||||
bool m_has_other;
|
||||
bool m_other_is_merged;
|
||||
db::RegionCheckOptions m_options;
|
||||
mutable db::PropertyMapper m_pms, m_pmi;
|
||||
};
|
||||
|
||||
typedef check_local_operation<db::PolygonRef, db::PolygonRef> CheckLocalOperation;
|
||||
|
|
@ -371,6 +410,131 @@ typedef contained_local_operation<db::PolygonRef, db::PolygonRef, db::PolygonRef
|
|||
// the implementation is type-agnostic and can be used for edges too
|
||||
typedef contained_local_operation<db::Edge, db::Edge, db::Edge> ContainedEdgesLocalOperation;
|
||||
|
||||
/**
|
||||
* @brief Implements a boolean AND or NOT operation
|
||||
*/
|
||||
|
||||
template <class TS, class TI, class TR>
|
||||
class DB_PUBLIC bool_and_or_not_local_operation
|
||||
: public local_operation<TS, TI, TR>
|
||||
{
|
||||
public:
|
||||
bool_and_or_not_local_operation (bool is_and);
|
||||
|
||||
virtual void do_compute_local (db::Layout *layout, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<TR> > &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;
|
||||
};
|
||||
|
||||
typedef bool_and_or_not_local_operation<db::PolygonRef, db::PolygonRef, db::PolygonRef> BoolAndOrNotLocalOperation;
|
||||
|
||||
/**
|
||||
* @brief Implements a boolean AND or NOT operation with property handling
|
||||
*/
|
||||
template <class TS, class TI, class TR>
|
||||
class DB_PUBLIC bool_and_or_not_local_operation_with_properties
|
||||
: public local_operation<db::object_with_properties<TS>, db::object_with_properties<TI>, db::object_with_properties<TR> >
|
||||
{
|
||||
public:
|
||||
bool_and_or_not_local_operation_with_properties (bool is_and, db::PropertiesRepository *target_pr, const db::PropertiesRepository *subject_pr, const db::PropertiesRepository *intruder_pr, db::PropertyConstraint property_constraint);
|
||||
|
||||
virtual void do_compute_local (db::Layout * /*layout*/, const shape_interactions<db::object_with_properties<TS>, db::object_with_properties<TI> > &interactions, std::vector<std::unordered_set<db::object_with_properties<TR> > > &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;
|
||||
mutable db::PropertyMapper m_pms;
|
||||
mutable db::PropertyMapper m_pmi;
|
||||
};
|
||||
|
||||
typedef bool_and_or_not_local_operation_with_properties<db::PolygonRef, db::PolygonRef, db::PolygonRef> BoolAndOrNotLocalOperationWithProperties;
|
||||
|
||||
/**
|
||||
* @brief Implements a boolean AND plus NOT operation
|
||||
*
|
||||
* This processor delivers two outputs: the first one having the AND result, the second
|
||||
* one having the NOT result.
|
||||
*/
|
||||
|
||||
template <class TS, class TI, class TR>
|
||||
class DB_PUBLIC two_bool_and_not_local_operation
|
||||
: public local_operation<TS, TI, TR>
|
||||
{
|
||||
public:
|
||||
two_bool_and_not_local_operation ();
|
||||
|
||||
virtual void do_compute_local (db::Layout *layout, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<TR> > &result, size_t max_vertex_count, double area_ratio) const;
|
||||
virtual std::string description () const;
|
||||
};
|
||||
|
||||
typedef two_bool_and_not_local_operation<db::PolygonRef, db::PolygonRef, db::PolygonRef> TwoBoolAndNotLocalOperation;
|
||||
|
||||
/**
|
||||
* @brief Implements a boolean AND plus NOT operation
|
||||
*
|
||||
* This processor delivers two outputs: the first one having the AND result, the second
|
||||
* one having the NOT result.
|
||||
*/
|
||||
template <class TS, class TI, class TR>
|
||||
class DB_PUBLIC two_bool_and_not_local_operation_with_properties
|
||||
: public local_operation<db::object_with_properties<TS>, db::object_with_properties<TI>, db::object_with_properties<TR> >
|
||||
{
|
||||
public:
|
||||
two_bool_and_not_local_operation_with_properties (db::PropertiesRepository *target1_pr, db::PropertiesRepository *target2_pr, const db::PropertiesRepository *subject_pr, const db::PropertiesRepository *intruder_pr, db::PropertyConstraint property_constraint);
|
||||
|
||||
virtual void do_compute_local (db::Layout *layout, const shape_interactions<db::object_with_properties<TS>, db::object_with_properties<TI> > &interactions, std::vector<std::unordered_set<db::object_with_properties<TR> > > &result, size_t max_vertex_count, double area_ratio) const;
|
||||
virtual std::string description () const;
|
||||
|
||||
private:
|
||||
db::PropertyConstraint m_property_constraint;
|
||||
mutable db::PropertyMapper m_pms, m_pmi, m_pm12;
|
||||
};
|
||||
|
||||
typedef two_bool_and_not_local_operation_with_properties<db::PolygonRef, db::PolygonRef, db::PolygonRef> TwoBoolAndNotLocalOperationWithProperties;
|
||||
|
||||
/**
|
||||
* @brief Implements a merge operation with an overlap count
|
||||
* With a given wrap_count, the result will only contains shapes where
|
||||
* the original shapes overlap at least "wrap_count" times.
|
||||
*/
|
||||
class DB_PUBLIC SelfOverlapMergeLocalOperation
|
||||
: public local_operation<db::PolygonRef, db::PolygonRef, db::PolygonRef>
|
||||
{
|
||||
public:
|
||||
SelfOverlapMergeLocalOperation (unsigned int wrap_count);
|
||||
|
||||
virtual void do_compute_local (db::Layout *layout, const shape_interactions<db::PolygonRef, db::PolygonRef> &interactions, std::vector<std::unordered_set<db::PolygonRef> > &result, size_t max_vertex_count, double area_ratio) const;
|
||||
virtual OnEmptyIntruderHint on_empty_intruder_hint () const;
|
||||
virtual std::string description () const;
|
||||
|
||||
private:
|
||||
unsigned int m_wrap_count;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Converts polygons to edges
|
||||
*/
|
||||
class DB_PUBLIC PolygonToEdgeLocalOperation
|
||||
: public local_operation<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::EdgeWithProperties>
|
||||
{
|
||||
public:
|
||||
PolygonToEdgeLocalOperation (db::PropertiesRepository *target_pr, const db::PropertiesRepository *source_pr);
|
||||
|
||||
virtual db::Coord dist () const { return 1; }
|
||||
virtual bool requests_single_subjects () const { return true; }
|
||||
virtual std::string description () const;
|
||||
|
||||
virtual void do_compute_local (db::Layout * /*layout*/, const shape_interactions<db::PolygonRefWithProperties, db::PolygonRefWithProperties> &interactions, std::vector<std::unordered_set<db::EdgeWithProperties> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const;
|
||||
|
||||
private:
|
||||
mutable db::PropertyMapper m_pm;
|
||||
};
|
||||
|
||||
} // namespace db
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -0,0 +1,105 @@
|
|||
|
||||
/*
|
||||
|
||||
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
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "dbShapeCollection.h"
|
||||
#include "dbPropertiesRepository.h"
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------
|
||||
|
||||
DeepShapeCollectionDelegateBase::DeepShapeCollectionDelegateBase ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
DeepShapeCollectionDelegateBase::DeepShapeCollectionDelegateBase (const DeepShapeCollectionDelegateBase &other)
|
||||
{
|
||||
m_deep_layer = other.m_deep_layer.copy ();
|
||||
}
|
||||
|
||||
DeepShapeCollectionDelegateBase &
|
||||
DeepShapeCollectionDelegateBase::operator= (const DeepShapeCollectionDelegateBase &other)
|
||||
{
|
||||
if (this != &other) {
|
||||
m_deep_layer = other.m_deep_layer.copy ();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void
|
||||
DeepShapeCollectionDelegateBase::apply_property_translator (const db::PropertiesTranslator &pt)
|
||||
{
|
||||
db::Layout &layout = m_deep_layer.layout ();
|
||||
for (auto c = layout.begin (); c != layout.end (); ++c) {
|
||||
|
||||
db::Shapes &shapes = c->shapes (m_deep_layer.layer ());
|
||||
if ((shapes.type_mask () & ShapeIterator::Properties) != 0) {
|
||||
|
||||
// properties are present - need to translate them
|
||||
|
||||
db::Shapes new_shapes (shapes.is_editable ());
|
||||
shapes.swap (new_shapes);
|
||||
|
||||
shapes.assign (new_shapes, pt);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------
|
||||
// ShapeCollection implementation
|
||||
|
||||
const db::PropertiesRepository &
|
||||
ShapeCollection::properties_repository () const
|
||||
{
|
||||
static db::PropertiesRepository empty_prop_repo;
|
||||
const db::PropertiesRepository *r = get_delegate () ? get_delegate ()->properties_repository () : 0;
|
||||
return *(r ? r : &empty_prop_repo);
|
||||
}
|
||||
|
||||
db::PropertiesRepository &
|
||||
ShapeCollection::properties_repository ()
|
||||
{
|
||||
db::PropertiesRepository *r = get_delegate () ? get_delegate ()->properties_repository () : 0;
|
||||
tl_assert (r != 0);
|
||||
return *r;
|
||||
}
|
||||
|
||||
bool
|
||||
ShapeCollection::has_properties_repository () const
|
||||
{
|
||||
return get_delegate () && get_delegate ()->properties_repository ();
|
||||
}
|
||||
|
||||
void
|
||||
ShapeCollection::apply_property_translator (const db::PropertiesTranslator &pt)
|
||||
{
|
||||
if (get_delegate ()) {
|
||||
get_delegate ()->apply_property_translator (pt);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -26,31 +26,25 @@
|
|||
#include "dbCommon.h"
|
||||
#include "dbDeepShapeStore.h"
|
||||
#include "tlUniqueId.h"
|
||||
#include "tlVariant.h"
|
||||
#include "gsiObject.h"
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
||||
class PropertiesTranslator;
|
||||
class PropertiesRepository;
|
||||
|
||||
/**
|
||||
* @brief A base class for the deep collection delegates
|
||||
*/
|
||||
class DB_PUBLIC DeepShapeCollectionDelegateBase
|
||||
{
|
||||
public:
|
||||
DeepShapeCollectionDelegateBase () { }
|
||||
DeepShapeCollectionDelegateBase ();
|
||||
DeepShapeCollectionDelegateBase (const DeepShapeCollectionDelegateBase &other);
|
||||
|
||||
DeepShapeCollectionDelegateBase (const DeepShapeCollectionDelegateBase &other)
|
||||
{
|
||||
m_deep_layer = other.m_deep_layer.copy ();
|
||||
}
|
||||
|
||||
DeepShapeCollectionDelegateBase &operator= (const DeepShapeCollectionDelegateBase &other)
|
||||
{
|
||||
if (this != &other) {
|
||||
m_deep_layer = other.m_deep_layer.copy ();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
DeepShapeCollectionDelegateBase &operator= (const DeepShapeCollectionDelegateBase &other);
|
||||
|
||||
const db::DeepLayer &deep_layer () const
|
||||
{
|
||||
|
|
@ -62,6 +56,8 @@ public:
|
|||
return m_deep_layer;
|
||||
}
|
||||
|
||||
void apply_property_translator (const db::PropertiesTranslator &pt);
|
||||
|
||||
protected:
|
||||
virtual void set_deep_layer (const db::DeepLayer &dl)
|
||||
{
|
||||
|
|
@ -83,6 +79,17 @@ public:
|
|||
virtual ~ShapeCollectionDelegateBase () { }
|
||||
|
||||
virtual DeepShapeCollectionDelegateBase *deep () { return 0; }
|
||||
|
||||
virtual void apply_property_translator (const db::PropertiesTranslator & /*pt*/) = 0;
|
||||
virtual db::PropertiesRepository *properties_repository () = 0;
|
||||
virtual const db::PropertiesRepository *properties_repository () const = 0;
|
||||
|
||||
void remove_properties (bool remove = true)
|
||||
{
|
||||
if (remove) {
|
||||
apply_property_translator (db::PropertiesTranslator::make_remove_all ());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -96,6 +103,35 @@ public:
|
|||
virtual ~ShapeCollection () { }
|
||||
|
||||
virtual ShapeCollectionDelegateBase *get_delegate () const = 0;
|
||||
|
||||
/**
|
||||
* @brief Applies a PropertyTranslator
|
||||
*
|
||||
* This method will translate the property IDs according to the given property translator.
|
||||
*
|
||||
* Note that the property translator needs to be built from the PropertiesRepository
|
||||
* delivered by "properties_repository".
|
||||
*/
|
||||
void apply_property_translator (const db::PropertiesTranslator &pt);
|
||||
|
||||
/**
|
||||
* @brief Gets the property repository
|
||||
*
|
||||
* Use this object to decode and encode property IDs.
|
||||
*/
|
||||
db::PropertiesRepository &properties_repository ();
|
||||
|
||||
/**
|
||||
* @brief Gets the property repository (const version)
|
||||
*
|
||||
* Use this object to decode property IDs.
|
||||
*/
|
||||
const db::PropertiesRepository &properties_repository () const;
|
||||
|
||||
/**
|
||||
* @brief Gets a value indicating whether a properties repository is available
|
||||
*/
|
||||
bool has_properties_repository () const;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,9 +39,9 @@
|
|||
namespace db {
|
||||
|
||||
/**
|
||||
* @brief A template base class for edge processors
|
||||
* @brief A template base class for a shape processors
|
||||
*
|
||||
* A polygon processor can turn a edge into something else.
|
||||
* A shape processor can turn a shape into something else.
|
||||
*/
|
||||
template <class Shape, class Result>
|
||||
class DB_PUBLIC_TEMPLATE shape_collection_processor
|
||||
|
|
@ -209,6 +209,7 @@ shape_collection_processed_impl (const db::DeepLayer &input, const shape_collect
|
|||
}
|
||||
|
||||
shape_collection_processor_delivery<Result> delivery (&layout, st);
|
||||
shape_collection_processor_delivery<db::object_with_properties<Result> > delivery_wp (&layout, st);
|
||||
|
||||
const db::ICplxTrans &tr = v->first;
|
||||
db::ICplxTrans trinv = tr.inverted ();
|
||||
|
|
@ -220,7 +221,11 @@ shape_collection_processed_impl (const db::DeepLayer &input, const shape_collect
|
|||
heap.clear ();
|
||||
filter.process (s, heap);
|
||||
for (typename std::vector<Result>::const_iterator i = heap.begin (); i != heap.end (); ++i) {
|
||||
delivery.put (i->transformed (trinv));
|
||||
if (si->prop_id ()) {
|
||||
delivery_wp.put (db::object_with_properties<Result> (i->transformed (trinv), si->prop_id ()));
|
||||
} else {
|
||||
delivery.put (i->transformed (trinv));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -230,6 +235,7 @@ shape_collection_processed_impl (const db::DeepLayer &input, const shape_collect
|
|||
|
||||
db::Shapes &st = c->shapes (res->deep_layer ().layer ());
|
||||
shape_collection_processor_delivery<Result> delivery (&layout, &st);
|
||||
shape_collection_processor_delivery<db::object_with_properties<Result> > delivery_wp (&layout, &st);
|
||||
|
||||
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) {
|
||||
Shape s;
|
||||
|
|
@ -237,7 +243,11 @@ shape_collection_processed_impl (const db::DeepLayer &input, const shape_collect
|
|||
heap.clear ();
|
||||
filter.process (s, heap);
|
||||
for (typename std::vector<Result>::const_iterator i = heap.begin (); i != heap.end (); ++i) {
|
||||
delivery.put (*i);
|
||||
if (si->prop_id ()) {
|
||||
delivery_wp.put (db::object_with_properties<Result> (*i, si->prop_id ()));
|
||||
} else {
|
||||
delivery.put (*i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,48 +26,145 @@
|
|||
|
||||
#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 <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; }
|
||||
static bool with_props () { return false; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct shape_flags_traits<db::PolygonRef>
|
||||
: public shape_flags_traits<void>
|
||||
{
|
||||
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>
|
||||
: public shape_flags_traits<void>
|
||||
{
|
||||
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>
|
||||
: public shape_flags_traits<void>
|
||||
{
|
||||
static unsigned int generic () { return db::ShapeIterator::Boxes; }
|
||||
static unsigned int pure () { return 1 << db::ShapeIterator::Box; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct shape_flags_traits<db::Path>
|
||||
: public shape_flags_traits<void>
|
||||
{
|
||||
static unsigned int generic () { return db::ShapeIterator::Paths; }
|
||||
static unsigned int pure () { return 1 << db::ShapeIterator::Path; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct shape_flags_traits<db::Polygon>
|
||||
: public shape_flags_traits<void>
|
||||
{
|
||||
static unsigned int generic () { return db::ShapeIterator::Regions; }
|
||||
static unsigned int pure () { return 1 << db::ShapeIterator::Polygon; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct shape_flags_traits<db::SimplePolygon>
|
||||
: public shape_flags_traits<void>
|
||||
{
|
||||
static unsigned int generic () { return db::ShapeIterator::Regions; }
|
||||
static unsigned int pure () { return 1 << db::ShapeIterator::SimplePolygon; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct shape_flags_traits<db::Edge>
|
||||
: public shape_flags_traits<void>
|
||||
{
|
||||
static unsigned int generic () { return db::ShapeIterator::Edges; }
|
||||
static unsigned int pure () { return 1 << db::ShapeIterator::Edge; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct shape_flags_traits<db::EdgePair>
|
||||
: public shape_flags_traits<void>
|
||||
{
|
||||
static unsigned int generic () { return db::ShapeIterator::EdgePairs; }
|
||||
static unsigned int pure () { return 1 << db::ShapeIterator::EdgePair; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct shape_flags_traits<db::Text>
|
||||
: public shape_flags_traits<void>
|
||||
{
|
||||
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> >
|
||||
: public shape_flags_traits<T>
|
||||
{
|
||||
static bool with_props () { return true; }
|
||||
};
|
||||
|
||||
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 (); }
|
||||
template <class T> bool shape_flags_with_props () { return shape_flags_traits<T>::with_props (); }
|
||||
|
||||
/**
|
||||
* @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;
|
||||
|
||||
|
|
@ -79,7 +176,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;
|
||||
|
||||
|
|
@ -91,7 +208,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;
|
||||
|
||||
|
|
@ -103,7 +240,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;
|
||||
|
||||
|
|
@ -115,17 +272,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
|
||||
|
|
|
|||
|
|
@ -56,18 +56,32 @@ public:
|
|||
* the start method is called and when the shape container is cleared if "clear_shapes"
|
||||
* is set.
|
||||
*
|
||||
* @param shapes Where to store the shapes
|
||||
* @param clear_shapes If true, the shapes container is cleared on the start event.
|
||||
* @param prop_id The properties ID to assign to all the output shapes (or 0 if no property shall be assigned)
|
||||
*/
|
||||
ShapeGenerator (db::Shapes &shapes, bool clear_shapes = false)
|
||||
: PolygonSink (), mp_shapes (&shapes), m_clear_shapes (clear_shapes)
|
||||
ShapeGenerator (db::Shapes &shapes, bool clear_shapes = false, db::properties_id_type prop_id = 0)
|
||||
: PolygonSink (), mp_shapes (&shapes), m_clear_shapes (clear_shapes), m_prop_id (prop_id)
|
||||
{ }
|
||||
|
||||
/**
|
||||
* @brief Sets the properties ID to be used for the next polygon
|
||||
*/
|
||||
void set_prop_id (db::properties_id_type prop_id)
|
||||
{
|
||||
m_prop_id = prop_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Implementation of the PolygonSink interface
|
||||
*/
|
||||
virtual void put (const db::Polygon &polygon)
|
||||
{
|
||||
mp_shapes->insert (polygon);
|
||||
if (m_prop_id) {
|
||||
mp_shapes->insert (db::PolygonWithProperties (polygon, m_prop_id));
|
||||
} else {
|
||||
mp_shapes->insert (polygon);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -85,6 +99,7 @@ public:
|
|||
private:
|
||||
db::Shapes *mp_shapes;
|
||||
bool m_clear_shapes;
|
||||
db::properties_id_type m_prop_id;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -469,6 +469,8 @@ template <class Trans>
|
|||
Shapes::shape_type
|
||||
Shapes::do_insert (const Shapes::shape_type &shape, const Trans &t, tl::func_delegate_base <db::properties_id_type> &pm)
|
||||
{
|
||||
db::properties_id_type new_pid = shape.has_prop_id () ? pm (shape.prop_id ()) : 0;
|
||||
|
||||
switch (shape.m_type) {
|
||||
case shape_type::Null:
|
||||
default:
|
||||
|
|
@ -478,10 +480,10 @@ Shapes::do_insert (const Shapes::shape_type &shape, const Trans &t, tl::func_del
|
|||
shape_type::polygon_type p (shape.polygon ());
|
||||
// Hint: we don't compress so we don't loose information
|
||||
p.transform (t, false);
|
||||
if (! shape.has_prop_id ()) {
|
||||
if (new_pid == 0) {
|
||||
return insert (p);
|
||||
} else {
|
||||
return insert (db::object_with_properties<shape_type::polygon_type> (p, pm (shape.prop_id ())));
|
||||
return insert (db::object_with_properties<shape_type::polygon_type> (p, new_pid));
|
||||
}
|
||||
}
|
||||
case shape_type::PolygonRef:
|
||||
|
|
@ -492,10 +494,10 @@ Shapes::do_insert (const Shapes::shape_type &shape, const Trans &t, tl::func_del
|
|||
// Hint: we don't compress so we don't loose information
|
||||
p.transform (t, false);
|
||||
// TODO: could create a reference again, but this is what a transform would to as well.
|
||||
if (! shape.has_prop_id ()) {
|
||||
if (new_pid == 0) {
|
||||
return insert (p);
|
||||
} else {
|
||||
return insert (db::object_with_properties<shape_type::polygon_type> (p, pm (shape.prop_id ())));
|
||||
return insert (db::object_with_properties<shape_type::polygon_type> (p, new_pid));
|
||||
}
|
||||
}
|
||||
case shape_type::SimplePolygon:
|
||||
|
|
@ -503,10 +505,10 @@ Shapes::do_insert (const Shapes::shape_type &shape, const Trans &t, tl::func_del
|
|||
shape_type::simple_polygon_type p (shape.simple_polygon ());
|
||||
// Hint: we don't compress so we don't loose information
|
||||
p.transform (t, false);
|
||||
if (! shape.has_prop_id ()) {
|
||||
if (new_pid == 0) {
|
||||
return insert (p);
|
||||
} else {
|
||||
return insert (db::object_with_properties<shape_type::simple_polygon_type> (p, pm (shape.prop_id ())));
|
||||
return insert (db::object_with_properties<shape_type::simple_polygon_type> (p, new_pid));
|
||||
}
|
||||
}
|
||||
case shape_type::SimplePolygonRef:
|
||||
|
|
@ -517,50 +519,50 @@ Shapes::do_insert (const Shapes::shape_type &shape, const Trans &t, tl::func_del
|
|||
// Hint: we don't compress so we don't loose information
|
||||
p.transform (t, false);
|
||||
// TODO: could create a reference again, but this is what a transform would to as well.
|
||||
if (! shape.has_prop_id ()) {
|
||||
if (new_pid == 0) {
|
||||
return insert (p);
|
||||
} else {
|
||||
return insert (db::object_with_properties<shape_type::simple_polygon_type> (p, pm (shape.prop_id ())));
|
||||
return insert (db::object_with_properties<shape_type::simple_polygon_type> (p, new_pid));
|
||||
}
|
||||
}
|
||||
case shape_type::Edge:
|
||||
{
|
||||
shape_type::edge_type p (shape.edge ());
|
||||
p.transform (t);
|
||||
if (! shape.has_prop_id ()) {
|
||||
if (new_pid == 0) {
|
||||
return insert (p);
|
||||
} else {
|
||||
return insert (db::object_with_properties<shape_type::edge_type> (p, pm (shape.prop_id ())));
|
||||
return insert (db::object_with_properties<shape_type::edge_type> (p, new_pid));
|
||||
}
|
||||
}
|
||||
case shape_type::Point:
|
||||
{
|
||||
shape_type::point_type p (shape.point ());
|
||||
p = t.trans (p);
|
||||
if (! shape.has_prop_id ()) {
|
||||
if (new_pid == 0) {
|
||||
return insert (p);
|
||||
} else {
|
||||
return insert (db::object_with_properties<shape_type::point_type> (p, pm (shape.prop_id ())));
|
||||
return insert (db::object_with_properties<shape_type::point_type> (p, new_pid));
|
||||
}
|
||||
}
|
||||
case shape_type::EdgePair:
|
||||
{
|
||||
shape_type::edge_pair_type p (shape.edge_pair ());
|
||||
p.transform (t);
|
||||
if (! shape.has_prop_id ()) {
|
||||
if (new_pid == 0) {
|
||||
return insert (p);
|
||||
} else {
|
||||
return insert (db::object_with_properties<shape_type::edge_pair_type> (p, pm (shape.prop_id ())));
|
||||
return insert (db::object_with_properties<shape_type::edge_pair_type> (p, new_pid));
|
||||
}
|
||||
}
|
||||
case shape_type::Path:
|
||||
{
|
||||
shape_type::path_type p (shape.path ());
|
||||
p.transform (t);
|
||||
if (! shape.has_prop_id ()) {
|
||||
if (new_pid == 0) {
|
||||
return insert (p);
|
||||
} else {
|
||||
return insert (db::object_with_properties<shape_type::path_type> (p, pm (shape.prop_id ())));
|
||||
return insert (db::object_with_properties<shape_type::path_type> (p, new_pid));
|
||||
}
|
||||
}
|
||||
case shape_type::PathRef:
|
||||
|
|
@ -570,10 +572,10 @@ Shapes::do_insert (const Shapes::shape_type &shape, const Trans &t, tl::func_del
|
|||
shape.path (p);
|
||||
p.transform (t);
|
||||
// TODO: could create a reference again, but this is what a transform would to as well.
|
||||
if (! shape.has_prop_id ()) {
|
||||
if (new_pid == 0) {
|
||||
return insert (p);
|
||||
} else {
|
||||
return insert (db::object_with_properties<shape_type::path_type> (p, pm (shape.prop_id ())));
|
||||
return insert (db::object_with_properties<shape_type::path_type> (p, new_pid));
|
||||
}
|
||||
}
|
||||
case shape_type::Box:
|
||||
|
|
@ -584,19 +586,19 @@ Shapes::do_insert (const Shapes::shape_type &shape, const Trans &t, tl::func_del
|
|||
if (t.is_ortho ()) {
|
||||
shape_type::box_type p (shape.box ());
|
||||
p.transform (t);
|
||||
if (! shape.has_prop_id ()) {
|
||||
if (new_pid == 0) {
|
||||
return insert (p);
|
||||
} else {
|
||||
return insert (db::object_with_properties<shape_type::box_type> (p, pm (shape.prop_id ())));
|
||||
return insert (db::object_with_properties<shape_type::box_type> (p, new_pid));
|
||||
}
|
||||
} else {
|
||||
// A box cannot stay a box in this case ...
|
||||
shape_type::simple_polygon_type p (shape.box ());
|
||||
p.transform (t);
|
||||
if (! shape.has_prop_id ()) {
|
||||
if (new_pid == 0) {
|
||||
return insert (p);
|
||||
} else {
|
||||
return insert (db::object_with_properties<shape_type::simple_polygon_type> (p, pm (shape.prop_id ())));
|
||||
return insert (db::object_with_properties<shape_type::simple_polygon_type> (p, new_pid));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -604,10 +606,10 @@ Shapes::do_insert (const Shapes::shape_type &shape, const Trans &t, tl::func_del
|
|||
{
|
||||
shape_type::text_type p (shape.text ());
|
||||
p.transform (t);
|
||||
if (! shape.has_prop_id ()) {
|
||||
if (new_pid == 0) {
|
||||
return insert (p);
|
||||
} else {
|
||||
return insert (db::object_with_properties<shape_type::text_type> (p, pm (shape.prop_id ())));
|
||||
return insert (db::object_with_properties<shape_type::text_type> (p, new_pid));
|
||||
}
|
||||
}
|
||||
case shape_type::TextRef:
|
||||
|
|
@ -617,20 +619,20 @@ Shapes::do_insert (const Shapes::shape_type &shape, const Trans &t, tl::func_del
|
|||
shape.text (p);
|
||||
p.transform (t);
|
||||
// TODO: could create a reference again, but this is what a transform would to as well.
|
||||
if (! shape.has_prop_id ()) {
|
||||
if (new_pid == 0) {
|
||||
return insert (p);
|
||||
} else {
|
||||
return insert (db::object_with_properties<shape_type::text_type> (p, pm (shape.prop_id ())));
|
||||
return insert (db::object_with_properties<shape_type::text_type> (p, new_pid));
|
||||
}
|
||||
}
|
||||
case shape_type::UserObject:
|
||||
{
|
||||
shape_type::user_object_type p (shape.user_object ());
|
||||
p.transform (t);
|
||||
if (! shape.has_prop_id ()) {
|
||||
if (new_pid == 0) {
|
||||
return insert (p);
|
||||
} else {
|
||||
return insert (db::object_with_properties<shape_type::user_object_type> (p, pm (shape.prop_id ())));
|
||||
return insert (db::object_with_properties<shape_type::user_object_type> (p, new_pid));
|
||||
}
|
||||
}
|
||||
case shape_type::PolygonPtrArray:
|
||||
|
|
@ -709,7 +711,7 @@ Shapes::replace_prop_id (const Shapes::shape_type &ref, db::properties_id_type p
|
|||
throw tl::Exception (tl::to_string (tr ("Function 'replace_prop_id' is permitted only in editable mode")));
|
||||
}
|
||||
|
||||
if (ref.with_props ()) {
|
||||
if (ref.has_prop_id ()) {
|
||||
|
||||
// this assumes we can simply patch the properties ID ..
|
||||
switch (ref.m_type) {
|
||||
|
|
@ -1241,7 +1243,7 @@ Shapes::reinsert_member_with_props (typename db::object_tag<Sh1>, const shape_ty
|
|||
}
|
||||
|
||||
// the shape types are not equal - resolve into erase and insert (of new)
|
||||
if (! ref.with_props ()) {
|
||||
if (! ref.has_prop_id ()) {
|
||||
erase_shape (ref);
|
||||
return insert (sh);
|
||||
} else {
|
||||
|
|
@ -1260,7 +1262,7 @@ Shapes::replace_member_with_props (typename db::object_tag<Sh1>, const shape_typ
|
|||
}
|
||||
|
||||
// the shape types are not equal - resolve into erase and insert (of new)
|
||||
if (! ref.with_props ()) {
|
||||
if (! ref.has_prop_id ()) {
|
||||
erase_shape (ref);
|
||||
return insert (sh);
|
||||
} else {
|
||||
|
|
@ -1310,7 +1312,7 @@ Shapes::replace_member_with_props (typename db::object_tag<Sh> tag, const shape_
|
|||
throw tl::Exception (tl::to_string (tr ("Function 'replace' is permitted only in editable mode")));
|
||||
}
|
||||
|
||||
if (! ref.with_props ()) {
|
||||
if (! ref.has_prop_id ()) {
|
||||
|
||||
if (manager () && manager ()->transacting ()) {
|
||||
check_is_editable_for_undo_redo ();
|
||||
|
|
|
|||
|
|
@ -787,7 +787,7 @@ public:
|
|||
} else {
|
||||
// translate and transform into this
|
||||
for (tl::vector<LayerBase *>::const_iterator l = d.m_layers.begin (); l != d.m_layers.end (); ++l) {
|
||||
(*l)->transform_into (this, shape_repository (), array_repository (), pm_delegate);
|
||||
(*l)->translate_into (this, shape_repository (), array_repository (), pm_delegate);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1266,7 +1266,8 @@ public:
|
|||
{
|
||||
size_t n = 0;
|
||||
for (tl::vector<LayerBase *>::const_iterator l = m_layers.begin (); l != m_layers.end (); ++l) {
|
||||
if ((flags & (*l)->type_mask ()) != 0) {
|
||||
unsigned int tm = (*l)->type_mask ();
|
||||
if (((flags & db::ShapeIterator::Properties) == 0 || (tm & db::ShapeIterator::Properties) != 0) && (flags & tm) != 0) {
|
||||
n += (*l)->size ();
|
||||
}
|
||||
}
|
||||
|
|
@ -1465,6 +1466,25 @@ public:
|
|||
return (db::Cell *) (size_t (mp_cell) & ~3);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets a flag indicating whether an update is needed
|
||||
*
|
||||
* This flag means that the shape collection has been modified and the bounding box
|
||||
* and the quad trees will be recomputed (internally).
|
||||
*/
|
||||
bool is_dirty () const
|
||||
{
|
||||
return (size_t (mp_cell) & 1) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets a value indicating that the shape collection is constructed with editable scope
|
||||
*/
|
||||
bool is_editable () const
|
||||
{
|
||||
return (size_t (mp_cell) & 2) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the pointer to layout that the shapes container belongs to
|
||||
*
|
||||
|
|
@ -1472,7 +1492,7 @@ public:
|
|||
*/
|
||||
db::Layout *layout () const;
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Implementation of the redo method
|
||||
*/
|
||||
void redo (db::Op *op);
|
||||
|
|
@ -1504,18 +1524,6 @@ private:
|
|||
return m_layers;
|
||||
}
|
||||
|
||||
// extract dirty flag from mp_cell
|
||||
bool is_dirty () const
|
||||
{
|
||||
return (size_t (mp_cell) & 1) != 0;
|
||||
}
|
||||
|
||||
// extract editable flag from mp_cell
|
||||
bool is_editable () const
|
||||
{
|
||||
return (size_t (mp_cell) & 2) != 0;
|
||||
}
|
||||
|
||||
// get the shape repository associated with this container
|
||||
db::GenericRepository &shape_repository () const;
|
||||
|
||||
|
|
|
|||
|
|
@ -487,7 +487,7 @@ struct translate_into_shapes
|
|||
mp_shapes->insert (new_shape);
|
||||
}
|
||||
|
||||
template <class Sh, class T>
|
||||
template <class Sh>
|
||||
void operator() (const db::object_with_properties<Sh> &sh)
|
||||
{
|
||||
Sh new_shape;
|
||||
|
|
@ -495,7 +495,7 @@ struct translate_into_shapes
|
|||
mp_shapes->insert (db::object_with_properties<Sh> (new_shape, sh.properties_id ()));
|
||||
}
|
||||
|
||||
template <class Sh, class T, class PropIdMap>
|
||||
template <class Sh, class PropIdMap>
|
||||
void operator() (const db::object_with_properties<Sh> &sh, PropIdMap &pm)
|
||||
{
|
||||
Sh new_shape;
|
||||
|
|
@ -755,7 +755,7 @@ inline unsigned int iterator_type_mask (ShapeIterator::user_object_type::tag)
|
|||
template <class Sh>
|
||||
inline unsigned int iterator_type_mask (db::object_tag< db::object_with_properties<Sh> >)
|
||||
{
|
||||
return iterator_type_mask (typename Sh::tag ());
|
||||
return iterator_type_mask (typename Sh::tag ()) | ShapeIterator::Properties;
|
||||
}
|
||||
|
||||
template <class Sh, class StableTag>
|
||||
|
|
|
|||
|
|
@ -419,4 +419,24 @@ bool compare (const db::Box &box, const std::string &string)
|
|||
return box.to_string () == string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Converts a property ID into a property key/value string representation
|
||||
*/
|
||||
std::string prop2string (const db::PropertiesRepository &pr, db::properties_id_type prop_id)
|
||||
{
|
||||
const db::PropertiesRepository::properties_set &ps = pr.properties (prop_id);
|
||||
|
||||
std::string res;
|
||||
for (auto i = ps.begin (); i != ps.end (); ++i) {
|
||||
if (i != ps.begin ()) {
|
||||
res += "\n";
|
||||
}
|
||||
res += pr.prop_name (i->first).to_string ();
|
||||
res += "=";
|
||||
res += i->second.to_string ();
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ namespace tl
|
|||
namespace db
|
||||
{
|
||||
|
||||
class PropertiesRepository;
|
||||
class Layout;
|
||||
class Cell;
|
||||
class LayerMap;
|
||||
|
|
@ -117,6 +118,11 @@ bool DB_PUBLIC compare (const db::Texts &texts, const std::string &string);
|
|||
*/
|
||||
bool DB_PUBLIC compare (const db::Box &box, const std::string &string);
|
||||
|
||||
/**
|
||||
* @brief Converts a property ID into a property key/value string representation
|
||||
*/
|
||||
std::string DB_PUBLIC prop2string (const db::PropertiesRepository &pr, db::properties_id_type prop_id);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -146,10 +146,26 @@ const db::RecursiveShapeIterator &
|
|||
Texts::iter () const
|
||||
{
|
||||
static db::RecursiveShapeIterator def_iter;
|
||||
const db::RecursiveShapeIterator *i = mp_delegate->iter ();
|
||||
const db::RecursiveShapeIterator *i = mp_delegate ? mp_delegate->iter () : 0;
|
||||
return *(i ? i : &def_iter);
|
||||
}
|
||||
|
||||
const db::PropertiesRepository &
|
||||
Texts::properties_repository () const
|
||||
{
|
||||
static db::PropertiesRepository empty_prop_repo;
|
||||
const db::PropertiesRepository *r = delegate () ? delegate ()->properties_repository () : 0;
|
||||
return *(r ? r : &empty_prop_repo);
|
||||
}
|
||||
|
||||
db::PropertiesRepository &
|
||||
Texts::properties_repository ()
|
||||
{
|
||||
db::PropertiesRepository *r = delegate () ? delegate ()->properties_repository () : 0;
|
||||
tl_assert (r != 0);
|
||||
return *r;
|
||||
}
|
||||
|
||||
void Texts::polygons (Region &output, db::Coord e) const
|
||||
{
|
||||
output.set_delegate (mp_delegate->polygons (e));
|
||||
|
|
|
|||
|
|
@ -43,64 +43,8 @@ class Region;
|
|||
class DeepShapeStore;
|
||||
class TransformationReducer;
|
||||
|
||||
/**
|
||||
* @brief An text set iterator
|
||||
*
|
||||
* The iterator delivers the texts of the text set
|
||||
*/
|
||||
|
||||
class DB_PUBLIC TextsIterator
|
||||
: public generic_shape_iterator<db::Text>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor
|
||||
*/
|
||||
TextsIterator ()
|
||||
: generic_shape_iterator<db::Text> ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Constructor from a delegate
|
||||
* The iterator will take ownership over the delegate
|
||||
*/
|
||||
TextsIterator (TextsIteratorDelegate *delegate)
|
||||
: generic_shape_iterator<db::Text> (delegate)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Copy constructor and assignment
|
||||
*/
|
||||
TextsIterator (const TextsIterator &other)
|
||||
: generic_shape_iterator<db::Text> (static_cast<const generic_shape_iterator<db::Text> &> (other))
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assignment
|
||||
*/
|
||||
TextsIterator &operator= (const TextsIterator &other)
|
||||
{
|
||||
generic_shape_iterator<db::Text>::operator= (other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Increment
|
||||
*/
|
||||
TextsIterator &operator++ ()
|
||||
{
|
||||
generic_shape_iterator<db::Text>::operator++ ();
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
typedef addressable_shape_delivery_gen<TextsIterator> AddressableTextDelivery;
|
||||
typedef generic_shape_iterator<Text> TextsIterator;
|
||||
typedef addressable_shape_delivery<Text> AddressableTextDelivery;
|
||||
|
||||
class Texts;
|
||||
|
||||
|
|
@ -248,7 +192,15 @@ public:
|
|||
/**
|
||||
* @brief Gets the underlying delegate object
|
||||
*/
|
||||
TextsDelegate *delegate () const
|
||||
const TextsDelegate *delegate () const
|
||||
{
|
||||
return mp_delegate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the underlying delegate object
|
||||
*/
|
||||
TextsDelegate *delegate ()
|
||||
{
|
||||
return mp_delegate;
|
||||
}
|
||||
|
|
@ -514,7 +466,7 @@ public:
|
|||
*/
|
||||
AddressableTextDelivery addressable_texts () const
|
||||
{
|
||||
return AddressableTextDelivery (begin (), has_valid_texts ());
|
||||
return AddressableTextDelivery (begin ());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -524,6 +476,20 @@ public:
|
|||
*/
|
||||
const db::RecursiveShapeIterator &iter () const;
|
||||
|
||||
/**
|
||||
* @brief Gets the property repository
|
||||
*
|
||||
* Use this object to decode property IDs.
|
||||
*/
|
||||
const db::PropertiesRepository &properties_repository () const;
|
||||
|
||||
/**
|
||||
* @brief Gets the property repository
|
||||
*
|
||||
* Use this object to decode and encode property IDs.
|
||||
*/
|
||||
db::PropertiesRepository &properties_repository ();
|
||||
|
||||
/**
|
||||
* @brief Equality
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -66,6 +66,12 @@ public:
|
|||
|
||||
virtual TextsDelegate *clone () const = 0;
|
||||
|
||||
TextsDelegate *remove_properties (bool remove = true)
|
||||
{
|
||||
ShapeCollectionDelegateBase::remove_properties (remove);
|
||||
return this;
|
||||
}
|
||||
|
||||
void enable_progress (const std::string &progress_desc);
|
||||
void disable_progress ();
|
||||
|
||||
|
|
@ -102,6 +108,9 @@ public:
|
|||
virtual bool has_valid_texts () const = 0;
|
||||
|
||||
virtual const db::RecursiveShapeIterator *iter () const = 0;
|
||||
virtual void apply_property_translator (const db::PropertiesTranslator &pt) = 0;
|
||||
virtual db::PropertiesRepository *properties_repository () = 0;
|
||||
virtual const db::PropertiesRepository *properties_repository () const = 0;
|
||||
|
||||
virtual bool equals (const Texts &other) const = 0;
|
||||
virtual bool less (const Texts &other) const = 0;
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue