Merge branch 'drc-enhancements', remote-tracking branch 'origin' into lvs-debug

This commit is contained in:
Matthias Koefferlein 2021-03-14 23:52:03 +01:00
commit f2b1661647
192 changed files with 1859 additions and 630 deletions

View File

@ -378,28 +378,77 @@ AsIfFlatRegion::processed_to_edge_pairs (const PolygonToEdgePairProcessorBase &f
return new_edge_pairs.release (); return new_edge_pairs.release ();
} }
RegionDelegate * namespace {
AsIfFlatRegion::selected_interacting_generic (const Edges &other, bool inverse, size_t min_count, size_t max_count) const
class OutputPairHolder
{ {
public:
OutputPairHolder (InteractingOutputMode output_mode, bool merged_semantics)
{
if (output_mode == None) {
return;
}
if (output_mode == Positive || output_mode == Negative || output_mode == PositiveAndNegative) {
m_positive.reset (new FlatRegion (merged_semantics));
m_results.push_back (& m_positive->raw_polygons ());
} else {
m_results.push_back ((db::Shapes *) 0);
}
if (output_mode == PositiveAndNegative) {
m_negative.reset (new FlatRegion (merged_semantics));
m_results.push_back (& m_negative->raw_polygons ());
}
}
std::pair<RegionDelegate *, RegionDelegate *> region_pair ()
{
return std::make_pair (m_positive.release (), m_negative.release ());
}
const std::vector<db::Shapes *> &results () { return m_results; }
private:
std::unique_ptr<FlatRegion> m_positive, m_negative;
std::vector<db::Shapes *> m_results;
};
}
std::pair<RegionDelegate *, RegionDelegate *>
AsIfFlatRegion::selected_interacting_generic (const Edges &other, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const
{
OutputPairHolder oph (output_mode, merged_semantics ());
if (output_mode == None) {
return oph.region_pair ();
}
min_count = std::max (size_t (1), min_count); min_count = std::max (size_t (1), min_count);
if (max_count < min_count || other.empty ()) { // shortcut
if (! inverse) { if (empty ()) {
return new EmptyRegion (); if (output_mode == Positive || output_mode == Negative) {
return std::make_pair (clone (), (RegionDelegate *) 0);
} else { } else {
return clone (); return std::make_pair (clone (), clone ());
}
} else if (max_count < min_count || other.empty ()) {
if (output_mode == Positive) {
return std::make_pair (new EmptyRegion (), (RegionDelegate *) 0);
} else if (output_mode == Negative) {
return std::make_pair (clone (), (RegionDelegate *) 0);
} else {
return std::make_pair (new EmptyRegion (), clone ());
} }
} else if (empty ()) {
return clone ();
} }
bool counting = !(min_count == 1 && max_count == std::numeric_limits<size_t>::max ()); bool counting = !(min_count == 1 && max_count == std::numeric_limits<size_t>::max ());
#if defined(USE_LOCAL_PROCESSOR)
db::RegionIterator polygons (begin_merged ()); db::RegionIterator polygons (begin_merged ());
db::interacting_with_edge_local_operation<db::Polygon, db::Edge, db::Polygon> op (inverse, min_count, max_count, true); db::interacting_with_edge_local_operation<db::Polygon, db::Edge, db::Polygon> op (output_mode, min_count, max_count, true);
db::local_processor<db::Polygon, db::Edge, db::Polygon> proc; db::local_processor<db::Polygon, db::Edge, db::Polygon> proc;
proc.set_base_verbosity (base_verbosity ()); proc.set_base_verbosity (base_verbosity ());
@ -413,71 +462,42 @@ AsIfFlatRegion::selected_interacting_generic (const Edges &other, bool inverse,
std::vector<db::Shapes *> results; std::vector<db::Shapes *> results;
results.push_back (&output->raw_polygons ()); results.push_back (&output->raw_polygons ());
proc.run_flat (polygons, others, std::vector<bool> (), &op, results); proc.run_flat (polygons, others, std::vector<bool> (), &op, oph.results ());
return output.release (); return oph.region_pair ();
#else
std::unordered_map<const db::Polygon *, size_t, std::ptr_hash_from_value<db::Polygon> > counted_results;
ResultCountingInserter inserter (counted_results);
db::box_scanner2<db::Polygon, size_t, db::Edge, size_t> scanner (report_progress (), progress_desc ());
scanner.reserve1 (count ());
scanner.reserve2 (other.count ());
std::unique_ptr<FlatRegion> output (new FlatRegion (false));
region_to_edge_interaction_filter<db::Polygon, db::Edge, ResultCountingInserter> filter (inserter, false, counting /*get all in counting mode*/);
AddressablePolygonDelivery p (begin_merged ());
for ( ; ! p.at_end (); ++p) {
scanner.insert1 (p.operator-> (), 0);
if (inverse) {
inserter.init (p.operator-> ());
}
}
AddressableEdgeDelivery e (counting ? other.addressable_merged_edges () : other.addressable_edges ());
for ( ; ! e.at_end (); ++e) {
scanner.insert2 (e.operator-> (), 0);
}
scanner.process (filter, 1, db::box_convert<db::Polygon> (), db::box_convert<db::Edge> ());
// select hits based on their count
for (std::unordered_map<const db::Polygon *, size_t, std::ptr_hash_from_value<db::Polygon> >::const_iterator r = counted_results.begin (); r != counted_results.end (); ++r) {
bool hit = r->second >= min_count && r->second <= max_count;
if (hit != inverse) {
output->insert (*r->first);
}
}
return output.release ();
#endif
} }
RegionDelegate * std::pair<RegionDelegate *, RegionDelegate *>
AsIfFlatRegion::selected_interacting_generic (const Texts &other, bool inverse, size_t min_count, size_t max_count) const AsIfFlatRegion::selected_interacting_generic (const Texts &other, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const
{ {
min_count = std::max (size_t (1), min_count); OutputPairHolder oph (output_mode, merged_semantics ());
if (max_count < min_count || other.empty ()) { if (output_mode == None) {
if (! inverse) { return oph.region_pair ();
return new EmptyRegion ();
} else {
return clone ();
}
} else if (empty ()) {
return clone ();
} }
#if defined(USE_LOCAL_PROCESSOR) min_count = std::max (size_t (1), min_count);
// shortcut
if (empty ()) {
if (output_mode == Positive || output_mode == Negative) {
return std::make_pair (clone (), (RegionDelegate *) 0);
} else {
return std::make_pair (clone (), clone ());
}
} else if (max_count < min_count || other.empty ()) {
if (output_mode == Positive) {
return std::make_pair (new EmptyRegion (), (RegionDelegate *) 0);
} else if (output_mode == Negative) {
return std::make_pair (clone (), (RegionDelegate *) 0);
} else {
return std::make_pair (new EmptyRegion (), clone ());
}
}
db::RegionIterator polygons (begin_merged ()); db::RegionIterator polygons (begin_merged ());
db::interacting_with_text_local_operation<db::Polygon, db::Text, db::Polygon> op (inverse, min_count, max_count); db::interacting_with_text_local_operation<db::Polygon, db::Text, db::Polygon> op (output_mode, min_count, max_count);
db::local_processor<db::Polygon, db::Text, db::Polygon> proc; db::local_processor<db::Polygon, db::Text, db::Polygon> proc;
proc.set_base_verbosity (base_verbosity ()); proc.set_base_verbosity (base_verbosity ());
@ -487,84 +507,58 @@ AsIfFlatRegion::selected_interacting_generic (const Texts &other, bool inverse,
std::vector<generic_shape_iterator<db::Text> > others; std::vector<generic_shape_iterator<db::Text> > others;
others.push_back (other.begin ()); others.push_back (other.begin ());
std::unique_ptr<FlatRegion> output (new FlatRegion (merged_semantics ())); proc.run_flat (polygons, others, std::vector<bool> (), &op, oph.results ());
std::vector<db::Shapes *> results;
results.push_back (&output->raw_polygons ());
proc.run_flat (polygons, others, std::vector<bool> (), &op, results); return oph.region_pair ();
return output.release ();
#else
bool counting = !(min_count == 1 && max_count == std::numeric_limits<size_t>::max ());
std::unordered_map<const db::Polygon *, size_t, std::ptr_hash_from_value<db::Polygon> > counted_results;
ResultCountingInserter inserter (counted_results);
db::box_scanner2<db::Polygon, size_t, db::Text, size_t> scanner (report_progress (), progress_desc ());
scanner.reserve1 (count ());
scanner.reserve2 (other.count ());
region_to_text_interaction_filter<db::Polygon, db::Text, ResultCountingInserter> filter (inserter, false, counting /*get all in counting mode*/);
AddressablePolygonDelivery p (begin_merged ());
for ( ; ! p.at_end (); ++p) {
scanner.insert1 (p.operator-> (), 0);
if (inverse) {
inserter.init (p.operator-> ());
}
}
AddressableTextDelivery e (other.addressable_texts ());
for ( ; ! e.at_end (); ++e) {
scanner.insert2 (e.operator-> (), 0);
}
scanner.process (filter, 1, db::box_convert<db::Polygon> (), db::box_convert<db::Text> ());
// select hits based on their count
std::unique_ptr<FlatRegion> output (new FlatRegion (true));
for (std::unordered_map<const db::Polygon *, size_t, std::ptr_hash_from_value<db::Polygon> >::const_iterator r = counted_results.begin (); r != counted_results.end (); ++r) {
bool hit = r->second >= min_count && r->second <= max_count;
if (hit != inverse) {
output->insert (*r->first);
}
}
return output.release ();
#endif
} }
RegionDelegate *
AsIfFlatRegion::selected_interacting_generic (const Region &other, int mode, bool touching, bool inverse, size_t min_count, size_t max_count) const std::pair<RegionDelegate *, RegionDelegate *>
AsIfFlatRegion::selected_interacting_generic (const Region &other, int mode, bool touching, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const
{ {
OutputPairHolder oph (output_mode, merged_semantics ());
if (output_mode == None) {
return oph.region_pair ();
}
min_count = std::max (size_t (1), min_count); min_count = std::max (size_t (1), min_count);
// shortcut // shortcut
if (empty ()) { if (empty ()) {
return clone (); if (output_mode == Positive || output_mode == Negative) {
return std::make_pair (clone (), (RegionDelegate *) 0);
} else {
return std::make_pair (clone (), clone ());
}
} else if (max_count < min_count || other.empty ()) { } else if (max_count < min_count || other.empty ()) {
// clear, if b is empty and // clear, if b is empty and
// * mode is inside, enclosing or interacting and inverse is false ("inside" or "interacting") // * mode is inside, enclosing or interacting and inverse is false ("inside" or "interacting")
// * mode is outside and inverse is true ("not outside") // * mode is outside and inverse is true ("not outside")
if ((mode <= 0) != inverse) { if ((mode <= 0)) {
return new EmptyRegion (); if (output_mode == Positive) {
return std::make_pair (new EmptyRegion (), (RegionDelegate *) 0);
} else if (output_mode == Negative) {
return std::make_pair (clone (), (RegionDelegate *) 0);
} else {
return std::make_pair (new EmptyRegion (), clone ());
}
} else { } else {
return clone (); if (output_mode == Positive) {
return std::make_pair (clone(), (RegionDelegate *) 0);
} else if (output_mode == Negative) {
return std::make_pair (new EmptyRegion (), (RegionDelegate *) 0);
} else {
return std::make_pair (clone (), new EmptyRegion ());
}
} }
} }
#if defined(USE_LOCAL_PROCESSOR)
bool counting = !(min_count == 1 && max_count == std::numeric_limits<size_t>::max ()); bool counting = !(min_count == 1 && max_count == std::numeric_limits<size_t>::max ());
db::RegionIterator polygons (begin_merged ()); db::RegionIterator polygons (begin_merged ());
db::interacting_local_operation<db::Polygon, db::Polygon, db::Polygon> op (mode, touching, inverse, min_count, max_count, true); db::interacting_local_operation<db::Polygon, db::Polygon, db::Polygon> op (mode, touching, output_mode, min_count, max_count, true);
db::local_processor<db::Polygon, db::Polygon, db::Polygon> proc; db::local_processor<db::Polygon, db::Polygon, db::Polygon> proc;
proc.set_base_verbosity (base_verbosity ()); proc.set_base_verbosity (base_verbosity ());
@ -574,121 +568,9 @@ AsIfFlatRegion::selected_interacting_generic (const Region &other, int mode, boo
std::vector<generic_shape_iterator<db::Polygon> > others; std::vector<generic_shape_iterator<db::Polygon> > others;
others.push_back ((mode < 0 || counting) ? other.begin_merged () : other.begin ()); others.push_back ((mode < 0 || counting) ? other.begin_merged () : other.begin ());
std::unique_ptr<FlatRegion> output (new FlatRegion (merged_semantics ())); proc.run_flat (polygons, others, std::vector<bool> (), &op, oph.results ());
std::vector<db::Shapes *> results;
results.push_back (&output->raw_polygons ());
proc.run_flat (polygons, others, std::vector<bool> (), &op, results); return oph.region_pair ();
return output.release ();
#else
db::EdgeProcessor ep (report_progress (), progress_desc ());
ep.set_base_verbosity (base_verbosity ());
size_t n = 0;
size_t nstart = 0;
if (mode < -1) {
// in enclosing mode self must be primary and other the secondary. For other
// modes it's the other way round
for (RegionIterator p (begin_merged ()); ! p.at_end (); ++p, ++n) {
if (mode > 0 || p->box ().touches (other.bbox ())) {
ep.insert (*p, n);
}
}
nstart = n;
}
if (min_count == size_t (1) && max_count == std::numeric_limits<size_t>::max ()) {
if (mode < 0) {
// NOTE: on "inside" or "enclosing", the other region must be merged
for (RegionIterator p = other.begin_merged (); ! p.at_end (); ++p) {
if (p->box ().touches (bbox ())) {
ep.insert (*p, n);
}
}
} else {
for (RegionIterator p = other.begin (); ! p.at_end (); ++p) {
if (p->box ().touches (bbox ())) {
ep.insert (*p, n);
}
}
}
++n;
} else {
// with counting we need to separate the other polygons by different properties
// cannot only have min_count/max_count in outside mode
tl_assert (mode <= 0);
for (RegionIterator p = other.begin_merged (); ! p.at_end (); ++p) {
if (p->box ().touches (bbox ())) {
ep.insert (*p, n);
}
++n;
}
}
if (mode >= -1) {
nstart = n;
for (RegionIterator p (begin_merged ()); ! p.at_end (); ++p, ++n) {
if (mode > 0 || p->box ().touches (other.bbox ())) {
ep.insert (*p, n);
}
}
}
// there should be at least one element to look at for primary
tl_assert (nstart > 0);
db::InteractionDetector id (mode, nstart - 1);
id.set_include_touching (touching);
db::EdgeSink es;
ep.process (es, id);
id.finish ();
std::unique_ptr<FlatRegion> output (new FlatRegion (false));
std::map <size_t, size_t> interaction_counts;
for (db::InteractionDetector::iterator i = id.begin (); i != id.end () ; ++i) {
if (i->first < nstart && i->second >= nstart) {
interaction_counts [mode < -1 ? i->first : i->second] += 1;
}
}
output->reserve (n);
n = (mode < -1 ? 0 : nstart);
for (RegionIterator p (begin_merged ()); ! p.at_end (); ++p, ++n) {
size_t count = 0;
std::map <size_t, size_t>::const_iterator c = interaction_counts.find (n);
if (c != interaction_counts.end ()) {
count = c->second;
}
if ((count >= min_count && count <= max_count) != inverse) {
output->insert (*p);
}
}
return output.release ();
#endif
} }
EdgesDelegate * EdgesDelegate *

View File

@ -139,72 +139,107 @@ public:
virtual RegionDelegate *selected_outside (const Region &other) const virtual RegionDelegate *selected_outside (const Region &other) const
{ {
return selected_interacting_generic (other, 1, false, false); return selected_interacting_generic (other, 1, false, Positive, size_t (0), std::numeric_limits<size_t>::max ()).first;
} }
virtual RegionDelegate *selected_not_outside (const Region &other) const virtual RegionDelegate *selected_not_outside (const Region &other) const
{ {
return selected_interacting_generic (other, 1, false, true); return selected_interacting_generic (other, 1, false, Negative, size_t (0), std::numeric_limits<size_t>::max ()).first;
}
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_outside_pair (const Region &other) const
{
return selected_interacting_generic (other, 1, false, PositiveAndNegative, size_t (0), std::numeric_limits<size_t>::max ());
} }
virtual RegionDelegate *selected_inside (const Region &other) const virtual RegionDelegate *selected_inside (const Region &other) const
{ {
return selected_interacting_generic (other, -1, true, false); return selected_interacting_generic (other, -1, true, Positive, size_t (0), std::numeric_limits<size_t>::max ()).first;
} }
virtual RegionDelegate *selected_not_inside (const Region &other) const virtual RegionDelegate *selected_not_inside (const Region &other) const
{ {
return selected_interacting_generic (other, -1, true, true); return selected_interacting_generic (other, -1, true, Negative, size_t (0), std::numeric_limits<size_t>::max ()).first;
}
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_inside_pair (const Region &other) const
{
return selected_interacting_generic (other, -1, true, PositiveAndNegative, size_t (0), std::numeric_limits<size_t>::max ());
} }
virtual RegionDelegate *selected_enclosing (const Region &other, size_t min_count, size_t max_count) const virtual RegionDelegate *selected_enclosing (const Region &other, size_t min_count, size_t max_count) const
{ {
return selected_interacting_generic (other, -2, false, false, min_count, max_count); return selected_interacting_generic (other, -2, false, Positive, min_count, max_count).first;
} }
virtual RegionDelegate *selected_not_enclosing (const Region &other, size_t min_count, size_t max_count) const virtual RegionDelegate *selected_not_enclosing (const Region &other, size_t min_count, size_t max_count) const
{ {
return selected_interacting_generic (other, -2, false, true, min_count, max_count); return selected_interacting_generic (other, -2, false, Negative, min_count, max_count).first;
}
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_enclosing_pair (const Region &other, size_t min_count, size_t max_count) const
{
return selected_interacting_generic (other, -2, false, PositiveAndNegative, min_count, max_count);
} }
virtual RegionDelegate *selected_interacting (const Region &other, size_t min_count, size_t max_count) const virtual RegionDelegate *selected_interacting (const Region &other, size_t min_count, size_t max_count) const
{ {
return selected_interacting_generic (other, 0, true, false, min_count, max_count); return selected_interacting_generic (other, 0, true, Positive, min_count, max_count).first;
} }
virtual RegionDelegate *selected_not_interacting (const Region &other, size_t min_count, size_t max_count) const virtual RegionDelegate *selected_not_interacting (const Region &other, size_t min_count, size_t max_count) const
{ {
return selected_interacting_generic (other, 0, true, true, min_count, max_count); return selected_interacting_generic (other, 0, true, Negative, min_count, max_count).first;
}
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_interacting_pair (const Region &other, size_t min_count, size_t max_count) const
{
return selected_interacting_generic (other, 0, true, PositiveAndNegative, min_count, max_count);
} }
virtual RegionDelegate *selected_interacting (const Edges &other, size_t min_count, size_t max_count) const virtual RegionDelegate *selected_interacting (const Edges &other, size_t min_count, size_t max_count) const
{ {
return selected_interacting_generic (other, false, min_count, max_count); return selected_interacting_generic (other, Positive, min_count, max_count).first;
} }
virtual RegionDelegate *selected_not_interacting (const Edges &other, size_t min_count, size_t max_count) const virtual RegionDelegate *selected_not_interacting (const Edges &other, size_t min_count, size_t max_count) const
{ {
return selected_interacting_generic (other, true, min_count, max_count); return selected_interacting_generic (other, Negative, min_count, max_count).first;
}
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_interacting_pair (const Edges &other, size_t min_count, size_t max_count) const
{
return selected_interacting_generic (other, PositiveAndNegative, min_count, max_count);
} }
virtual RegionDelegate *selected_interacting (const Texts &other, size_t min_count, size_t max_count) const virtual RegionDelegate *selected_interacting (const Texts &other, size_t min_count, size_t max_count) const
{ {
return selected_interacting_generic (other, false, min_count, max_count); return selected_interacting_generic (other, Positive, min_count, max_count).first;
} }
virtual RegionDelegate *selected_not_interacting (const Texts &other, size_t min_count, size_t max_count) const virtual RegionDelegate *selected_not_interacting (const Texts &other, size_t min_count, size_t max_count) const
{ {
return selected_interacting_generic (other, true, min_count, max_count); return selected_interacting_generic (other, Negative, min_count, max_count).first;
}
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_interacting_pair (const Texts &other, size_t min_count, size_t max_count) const
{
return selected_interacting_generic (other, PositiveAndNegative, min_count, max_count);
} }
virtual RegionDelegate *selected_overlapping (const Region &other, size_t min_count, size_t max_count) const virtual RegionDelegate *selected_overlapping (const Region &other, size_t min_count, size_t max_count) const
{ {
return selected_interacting_generic (other, 0, false, false, min_count, max_count); return selected_interacting_generic (other, 0, false, Positive, min_count, max_count).first;
} }
virtual RegionDelegate *selected_not_overlapping (const Region &other, size_t min_count, size_t max_count) const virtual RegionDelegate *selected_not_overlapping (const Region &other, size_t min_count, size_t max_count) const
{ {
return selected_interacting_generic (other, 0, false, true, min_count, max_count); return selected_interacting_generic (other, 0, false, Negative, min_count, max_count).first;
}
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_overlapping_pair (const Region &other, size_t min_count, size_t max_count) const
{
return selected_interacting_generic (other, 0, false, PositiveAndNegative, min_count, max_count);
} }
virtual RegionDelegate *pull_inside (const Region &other) const virtual RegionDelegate *pull_inside (const Region &other) const
@ -245,9 +280,9 @@ protected:
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_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; virtual EdgePairsDelegate *run_single_polygon_check (db::edge_relation_type rel, db::Coord d, const RegionCheckOptions &options) const;
virtual RegionDelegate *selected_interacting_generic (const Region &other, int mode, bool touching, bool inverse, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ()) const; virtual std::pair<RegionDelegate *, RegionDelegate *> selected_interacting_generic (const Region &other, int mode, bool touching, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const;
virtual RegionDelegate *selected_interacting_generic (const Edges &other, bool inverse, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ()) const; virtual std::pair<RegionDelegate *, RegionDelegate *> selected_interacting_generic (const Edges &other, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const;
virtual RegionDelegate *selected_interacting_generic (const Texts &other, bool inverse, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ()) const; virtual std::pair<RegionDelegate *, RegionDelegate *> selected_interacting_generic (const Texts &other, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const;
virtual RegionDelegate *pull_generic (const Region &other, int mode, bool touching) const; virtual RegionDelegate *pull_generic (const Region &other, int mode, bool touching) const;
virtual EdgesDelegate *pull_generic (const Edges &other) const; virtual EdgesDelegate *pull_generic (const Edges &other) const;
virtual TextsDelegate *pull_generic (const Texts &other) const; virtual TextsDelegate *pull_generic (const Texts &other) const;

View File

@ -1060,13 +1060,13 @@ template void CompoundRegionLogicalCaseSelectOperationNode::implement_compute_lo
// --------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------
CompoundRegionInteractOperationNode::CompoundRegionInteractOperationNode (CompoundRegionOperationNode *a, CompoundRegionOperationNode *b, int mode, bool touching, bool inverse, size_t min_count, size_t max_count) CompoundRegionInteractOperationNode::CompoundRegionInteractOperationNode (CompoundRegionOperationNode *a, CompoundRegionOperationNode *b, int mode, bool touching, bool inverse, size_t min_count, size_t max_count)
: compound_region_generic_operation_node<db::Polygon, db::Polygon, db::Polygon> (&m_op, a, b), m_op (mode, touching, inverse, min_count, max_count, b->is_merged ()) : compound_region_generic_operation_node<db::Polygon, db::Polygon, db::Polygon> (&m_op, a, b), m_op (mode, touching, inverse ? Negative : Positive, min_count, max_count, b->is_merged ())
{ {
// .. nothing yet .. // .. nothing yet ..
} }
CompoundRegionInteractOperationNode::CompoundRegionInteractOperationNode (db::Region *a, db::Region *b, int mode, bool touching, bool inverse, size_t min_count, size_t max_count) CompoundRegionInteractOperationNode::CompoundRegionInteractOperationNode (db::Region *a, db::Region *b, int mode, bool touching, bool inverse, size_t min_count, size_t max_count)
: compound_region_generic_operation_node<db::Polygon, db::Polygon, db::Polygon> (&m_op, a, b), m_op (mode, touching, inverse, min_count, max_count, b->is_merged ()) : compound_region_generic_operation_node<db::Polygon, db::Polygon, db::Polygon> (&m_op, a, b), m_op (mode, touching, inverse ? Negative : Positive, min_count, max_count, b->is_merged ())
{ {
// .. nothing yet .. // .. nothing yet ..
} }
@ -1080,7 +1080,7 @@ CompoundRegionInteractOperationNode::generated_description () const
// --------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------
CompoundRegionInteractWithEdgeOperationNode::CompoundRegionInteractWithEdgeOperationNode (CompoundRegionOperationNode *a, CompoundRegionOperationNode *b, bool inverse, size_t min_count, size_t max_count) CompoundRegionInteractWithEdgeOperationNode::CompoundRegionInteractWithEdgeOperationNode (CompoundRegionOperationNode *a, CompoundRegionOperationNode *b, bool inverse, size_t min_count, size_t max_count)
: compound_region_generic_operation_node<db::Polygon, db::Edge, db::Polygon> (&m_op, a, b), m_op (inverse, min_count, max_count, b->is_merged ()) : compound_region_generic_operation_node<db::Polygon, db::Edge, db::Polygon> (&m_op, a, b), m_op (inverse ? Negative : Positive, min_count, max_count, b->is_merged ())
{ {
// .. nothing yet .. // .. nothing yet ..
} }

View File

@ -753,7 +753,8 @@ public:
virtual void do_compute_local (db::Layout * /*layout*/, const shape_interactions<db::PolygonRef, db::PolygonRef> & /*interactions*/, std::vector<std::unordered_set<db::EdgePair> > & /*results*/, size_t /*max_vertex_count*/, double /*area_ratio*/) const { } virtual void do_compute_local (db::Layout * /*layout*/, const shape_interactions<db::PolygonRef, db::PolygonRef> & /*interactions*/, std::vector<std::unordered_set<db::EdgePair> > & /*results*/, size_t /*max_vertex_count*/, double /*area_ratio*/) const { }
private: private:
db::interacting_local_operation<db::Polygon, db::Polygon, db::Polygon> m_op; typedef db::interacting_local_operation<db::Polygon, db::Polygon, db::Polygon> op_type;
op_type m_op;
}; };
class DB_PUBLIC CompoundRegionInteractWithEdgeOperationNode class DB_PUBLIC CompoundRegionInteractWithEdgeOperationNode

View File

@ -1519,9 +1519,67 @@ DeepRegion::run_single_polygon_check (db::edge_relation_type rel, db::Coord d, c
return res.release (); return res.release ();
} }
RegionDelegate * namespace
DeepRegion::selected_interacting_generic (const Region &other, int mode, bool touching, bool inverse, size_t min_count, size_t max_count) const
{ {
class InteractingResultHolder
{
public:
InteractingResultHolder (InteractingOutputMode output_mode, bool is_merged, const db::DeepLayer &polygons)
: m_output_mode (output_mode), m_is_merged (is_merged)
{
if (m_output_mode == Positive || m_output_mode == Negative) {
m_dl1 = db::DeepLayer (polygons.derived ());
} else if (m_output_mode == PositiveAndNegative) {
m_dl1 = db::DeepLayer (polygons.derived ());
m_dl2 = db::DeepLayer (polygons.derived ());
}
}
std::vector<unsigned int> layers () const
{
std::vector<unsigned int> l;
if (m_output_mode == Positive || m_output_mode == Negative) {
l.push_back (m_dl1.layer ());
} else if (m_output_mode == PositiveAndNegative) {
l.push_back (m_dl1.layer ());
l.push_back (m_dl2.layer ());
}
return l;
}
std::pair<RegionDelegate *, RegionDelegate *> result_pair ()
{
if (m_output_mode == Positive || m_output_mode == Negative) {
db::DeepRegion *res = new db::DeepRegion (m_dl1);
res->set_is_merged (m_is_merged);
return std::pair<RegionDelegate *, RegionDelegate *> (res, 0);
} else if (m_output_mode == PositiveAndNegative) {
db::DeepRegion *res1 = new db::DeepRegion (m_dl1);
res1->set_is_merged (m_is_merged);
db::DeepRegion *res2 = new db::DeepRegion (m_dl2);
res2->set_is_merged (m_is_merged);
return std::pair<RegionDelegate *, RegionDelegate *> (res1, res2);
} else {
return std::pair<RegionDelegate *, RegionDelegate *> (0, 0);
}
}
private:
InteractingOutputMode m_output_mode;
bool m_is_merged;
DeepLayer m_dl1, m_dl2;
};
}
std::pair<RegionDelegate *, RegionDelegate *>
DeepRegion::selected_interacting_generic (const Region &other, int mode, bool touching, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const
{
if (output_mode == None) {
return std::pair<RegionDelegate *, RegionDelegate *> (0, 0);
}
bool counting = !(min_count == 1 && max_count == std::numeric_limits<size_t>::max ()); bool counting = !(min_count == 1 && max_count == std::numeric_limits<size_t>::max ());
// with these flag set to true, the resulting polygons are broken again. // with these flag set to true, the resulting polygons are broken again.
@ -1539,9 +1597,7 @@ DeepRegion::selected_interacting_generic (const Region &other, int mode, bool to
// NOTE: on "inside" or with counting, the other polygons must be merged // NOTE: on "inside" or with counting, the other polygons must be merged
const db::DeepLayer &other_polygons = (mode < 0 || counting) ? other_deep->merged_deep_layer () : other_deep->deep_layer (); const db::DeepLayer &other_polygons = (mode < 0 || counting) ? other_deep->merged_deep_layer () : other_deep->deep_layer ();
DeepLayer dl_out (polygons.derived ()); db::InteractingLocalOperation op (mode, touching, output_mode, min_count, max_count, true);
db::InteractingLocalOperation op (mode, touching, inverse, 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 ()); 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_description (progress_desc ());
@ -1553,17 +1609,16 @@ DeepRegion::selected_interacting_generic (const Region &other, int mode, bool to
proc.set_max_vertex_count (polygons.store ()->max_vertex_count ()); proc.set_max_vertex_count (polygons.store ()->max_vertex_count ());
} }
proc.run (&op, polygons.layer (), other_polygons.layer (), dl_out.layer ()); bool result_is_merged = (! split_after && ((mode < 0 && other.merged_semantics ()) || other.is_merged ()) && (merged_semantics () || is_merged ()));
InteractingResultHolder orh (output_mode, result_is_merged, polygons);
db::DeepRegion *res = new db::DeepRegion (dl_out); proc.run (&op, polygons.layer (), other_polygons.layer (), orh.layers ());
if (! split_after && ((mode < 0 && other.merged_semantics ()) || other.is_merged ()) && (merged_semantics () || is_merged ())) {
res->set_is_merged (true); return orh.result_pair ();
}
return res;
} }
RegionDelegate * std::pair<RegionDelegate *, RegionDelegate *>
DeepRegion::selected_interacting_generic (const Edges &other, bool inverse, size_t min_count, size_t max_count) const DeepRegion::selected_interacting_generic (const Edges &other, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const
{ {
bool counting = !(min_count == 1 && max_count == std::numeric_limits<size_t>::max ()); bool counting = !(min_count == 1 && max_count == std::numeric_limits<size_t>::max ());
@ -1580,9 +1635,7 @@ DeepRegion::selected_interacting_generic (const Edges &other, bool inverse, size
const db::DeepLayer &polygons = merged_deep_layer (); const db::DeepLayer &polygons = merged_deep_layer ();
DeepLayer dl_out (polygons.derived ()); db::InteractingWithEdgeLocalOperation op (output_mode, min_count, max_count, true);
db::InteractingWithEdgeLocalOperation op (inverse, 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 ()); 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_description (progress_desc ());
@ -1594,13 +1647,12 @@ DeepRegion::selected_interacting_generic (const Edges &other, bool inverse, size
proc.set_max_vertex_count (polygons.store ()->max_vertex_count ()); proc.set_max_vertex_count (polygons.store ()->max_vertex_count ());
} }
proc.run (&op, polygons.layer (), counting ? other_deep->merged_deep_layer ().layer () : other_deep->deep_layer ().layer (), dl_out.layer ()); bool result_is_merged = (! split_after && other.is_merged () && (merged_semantics () || is_merged ()));
InteractingResultHolder orh (output_mode, result_is_merged, polygons);
db::DeepRegion *res = new db::DeepRegion (dl_out); proc.run (&op, polygons.layer (), counting ? other_deep->merged_deep_layer ().layer () : other_deep->deep_layer ().layer (), orh.layers ());
if (! split_after) {
res->set_is_merged (other.is_merged () && (merged_semantics () || is_merged ())); return orh.result_pair ();
}
return res;
} }
RegionDelegate * RegionDelegate *
@ -1706,8 +1758,9 @@ DeepRegion::pull_generic (const Texts &other) const
return res; return res;
} }
RegionDelegate *
DeepRegion::selected_interacting_generic (const Texts &other, bool inverse, size_t min_count, size_t max_count) const std::pair<RegionDelegate *, RegionDelegate *>
DeepRegion::selected_interacting_generic (const Texts &other, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const
{ {
// with these flag set to true, the resulting polygons are broken again. // with these flag set to true, the resulting polygons are broken again.
bool split_after = false; bool split_after = false;
@ -1722,9 +1775,7 @@ DeepRegion::selected_interacting_generic (const Texts &other, bool inverse, size
const db::DeepLayer &polygons = merged_deep_layer (); const db::DeepLayer &polygons = merged_deep_layer ();
DeepLayer dl_out (polygons.derived ()); db::InteractingWithTextLocalOperation op (output_mode, min_count, max_count);
db::InteractingWithTextLocalOperation op (inverse, 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 ()); 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_description (progress_desc ());
@ -1736,13 +1787,12 @@ DeepRegion::selected_interacting_generic (const Texts &other, bool inverse, size
proc.set_max_vertex_count (polygons.store ()->max_vertex_count ()); proc.set_max_vertex_count (polygons.store ()->max_vertex_count ());
} }
proc.run (&op, polygons.layer (), other_deep->deep_layer ().layer (), dl_out.layer ()); bool result_is_merged = (! split_after && (merged_semantics () || is_merged ()));
InteractingResultHolder orh (output_mode, result_is_merged, polygons);
db::DeepRegion *res = new db::DeepRegion (dl_out); proc.run (&op, polygons.layer (), other_deep->deep_layer ().layer (), orh.layers ());
if (! split_after) {
res->set_is_merged (merged_semantics () || is_merged ()); return orh.result_pair ();
}
return res;
} }
} }

View File

@ -140,9 +140,9 @@ protected:
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_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; virtual EdgePairsDelegate *run_single_polygon_check (db::edge_relation_type rel, db::Coord d, const RegionCheckOptions &options) const;
virtual RegionDelegate *selected_interacting_generic (const Region &other, int mode, bool touching, bool inverse, size_t min_count, size_t max_count) const; virtual std::pair<RegionDelegate *, RegionDelegate *> selected_interacting_generic (const Region &other, int mode, bool touching, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const;
virtual RegionDelegate *selected_interacting_generic (const Edges &other, bool inverse, size_t min_count, size_t max_count) const; virtual std::pair<RegionDelegate *, RegionDelegate *> selected_interacting_generic (const Edges &other, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const;
virtual RegionDelegate *selected_interacting_generic (const Texts &other, bool inverse, size_t min_count, size_t max_count) const; virtual std::pair<RegionDelegate *, RegionDelegate *> selected_interacting_generic (const Texts &other, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const;
virtual RegionDelegate *pull_generic (const Region &other, int mode, bool touching) const; virtual RegionDelegate *pull_generic (const Region &other, int mode, bool touching) const;
virtual EdgesDelegate *pull_generic (const Edges &other) const; virtual EdgesDelegate *pull_generic (const Edges &other) const;
virtual TextsDelegate *pull_generic (const Texts &other) const; virtual TextsDelegate *pull_generic (const Texts &other) const;

View File

@ -108,18 +108,25 @@ public:
virtual RegionDelegate *selected_outside (const Region &) const { return new EmptyRegion (); } virtual RegionDelegate *selected_outside (const Region &) const { return new EmptyRegion (); }
virtual RegionDelegate *selected_not_outside (const Region &) const { return new EmptyRegion (); } virtual RegionDelegate *selected_not_outside (const Region &) const { return new EmptyRegion (); }
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_outside_pair (const Region &) const { return std::make_pair (new EmptyRegion (), new EmptyRegion ()); }
virtual RegionDelegate *selected_inside (const Region &) const { return new EmptyRegion (); } virtual RegionDelegate *selected_inside (const Region &) const { return new EmptyRegion (); }
virtual RegionDelegate *selected_not_inside (const Region &) const { return new EmptyRegion (); } virtual RegionDelegate *selected_not_inside (const Region &) const { return new EmptyRegion (); }
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_inside_pair (const Region &) const { return std::make_pair (new EmptyRegion (), new EmptyRegion ()); }
virtual RegionDelegate *selected_enclosing (const Region &, size_t, size_t) const { return new EmptyRegion (); } virtual RegionDelegate *selected_enclosing (const Region &, size_t, size_t) const { return new EmptyRegion (); }
virtual RegionDelegate *selected_not_enclosing (const Region &, size_t, size_t) const { return new EmptyRegion (); } virtual RegionDelegate *selected_not_enclosing (const Region &, size_t, size_t) const { return new EmptyRegion (); }
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_enclosing_pair (const Region &, size_t, size_t) const { return std::make_pair (new EmptyRegion (), new EmptyRegion ()); }
virtual RegionDelegate *selected_interacting (const Region &, size_t, size_t) const { return new EmptyRegion (); } virtual RegionDelegate *selected_interacting (const Region &, size_t, size_t) const { return new EmptyRegion (); }
virtual RegionDelegate *selected_not_interacting (const Region &, size_t, size_t) const { return new EmptyRegion (); } virtual RegionDelegate *selected_not_interacting (const Region &, size_t, size_t) const { return new EmptyRegion (); }
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_interacting_pair (const Region &, size_t, size_t) const { return std::make_pair (new EmptyRegion (), new EmptyRegion ()); }
virtual RegionDelegate *selected_interacting (const Edges &, size_t, size_t) const { return new EmptyRegion (); } virtual RegionDelegate *selected_interacting (const Edges &, size_t, size_t) const { return new EmptyRegion (); }
virtual RegionDelegate *selected_not_interacting (const Edges &, size_t, size_t) const { return new EmptyRegion (); } virtual RegionDelegate *selected_not_interacting (const Edges &, size_t, size_t) const { return new EmptyRegion (); }
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_interacting_pair (const Edges &, size_t, size_t) const { return std::make_pair (new EmptyRegion (), new EmptyRegion ()); }
virtual RegionDelegate *selected_interacting (const Texts &, size_t, size_t) const { return new EmptyRegion (); } virtual RegionDelegate *selected_interacting (const Texts &, size_t, size_t) const { return new EmptyRegion (); }
virtual RegionDelegate *selected_not_interacting (const Texts &, size_t, size_t) const { return new EmptyRegion (); } virtual RegionDelegate *selected_not_interacting (const Texts &, size_t, size_t) const { return new EmptyRegion (); }
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_interacting_pair (const Texts &, size_t, size_t) const { return std::make_pair (new EmptyRegion (), new EmptyRegion ()); }
virtual RegionDelegate *selected_overlapping (const Region &, size_t, size_t) const { return new EmptyRegion (); } virtual RegionDelegate *selected_overlapping (const Region &, size_t, size_t) const { return new EmptyRegion (); }
virtual RegionDelegate *selected_not_overlapping (const Region &, size_t, size_t) const { return new EmptyRegion (); } virtual RegionDelegate *selected_not_overlapping (const Region &, size_t, size_t) const { return new EmptyRegion (); }
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_overlapping_pair (const Region &, size_t, size_t) const { return std::make_pair (new EmptyRegion (), new EmptyRegion ()); }
virtual RegionDelegate *pull_inside (const Region &) const { return new EmptyRegion (); } virtual RegionDelegate *pull_inside (const Region &) const { return new EmptyRegion (); }
virtual RegionDelegate *pull_interacting (const Region &) const { return new EmptyRegion (); } virtual RegionDelegate *pull_interacting (const Region &) const { return new EmptyRegion (); }
virtual EdgesDelegate *pull_interacting (const Edges &) const { return new EmptyEdges (); } virtual EdgesDelegate *pull_interacting (const Edges &) const { return new EmptyEdges (); }

View File

@ -1280,6 +1280,14 @@ void local_processor<TS, TI, TR>::run (local_operation<TS, TI, TR> *op, unsigned
run (op, subject_layer, il, ol); run (op, subject_layer, il, ol);
} }
template <class TS, class TI, class TR>
void local_processor<TS, TI, TR>::run (local_operation<TS, TI, TR> *op, unsigned int subject_layer, unsigned int intruder_layer, const std::vector<unsigned int> &output_layers)
{
std::vector<unsigned int> ol, il;
il.push_back (intruder_layer);
run (op, subject_layer, il, output_layers);
}
template <class TS, class TI, class TR> template <class TS, class TI, class TR>
void local_processor<TS, TI, TR>::run (local_operation<TS, TI, TR> *op, unsigned int subject_layer, const std::vector<unsigned int> &intruder_layers, unsigned int output_layer) void local_processor<TS, TI, TR>::run (local_operation<TS, TI, TR> *op, unsigned int subject_layer, const std::vector<unsigned int> &intruder_layers, unsigned int output_layer)
{ {

View File

@ -419,6 +419,7 @@ public:
local_processor (db::Layout *layout = 0, db::Cell *top = 0, const std::set<db::cell_index_type> *breakout_cells = 0); local_processor (db::Layout *layout = 0, db::Cell *top = 0, const std::set<db::cell_index_type> *breakout_cells = 0);
local_processor (db::Layout *subject_layout, db::Cell *subject_top, const db::Layout *intruder_layout, const db::Cell *intruder_cell, const std::set<db::cell_index_type> *subject_breakout_cells = 0, const std::set<db::cell_index_type> *intruder_breakout_cells = 0); local_processor (db::Layout *subject_layout, db::Cell *subject_top, const db::Layout *intruder_layout, const db::Cell *intruder_cell, const std::set<db::cell_index_type> *subject_breakout_cells = 0, const std::set<db::cell_index_type> *intruder_breakout_cells = 0);
void run (local_operation<TS, TI, TR> *op, unsigned int subject_layer, unsigned int intruder_layer, unsigned int output_layers); void run (local_operation<TS, TI, TR> *op, unsigned int subject_layer, unsigned int intruder_layer, unsigned int output_layers);
void run (local_operation<TS, TI, TR> *op, unsigned int subject_layer, unsigned int intruder_layer, const std::vector<unsigned int> &output_layers);
void run (local_operation<TS, TI, TR> *op, unsigned int subject_layer, const std::vector<unsigned int> &intruder_layers, const std::vector<unsigned int> &output_layers); void run (local_operation<TS, TI, TR> *op, unsigned int subject_layer, const std::vector<unsigned int> &intruder_layers, const std::vector<unsigned int> &output_layers);
void run (local_operation<TS, TI, TR> *op, unsigned int subject_layer, const std::vector<unsigned int> &intruder_layers, unsigned int output_layer); void run (local_operation<TS, TI, TR> *op, unsigned int subject_layer, const std::vector<unsigned int> &intruder_layers, unsigned int output_layer);
void compute_contexts (local_processor_contexts<TS, TI, TR> &contexts, const local_operation<TS, TI, TR> *op, unsigned int subject_layer, const std::vector<unsigned int> &intruder_layers) const; void compute_contexts (local_processor_contexts<TS, TI, TR> &contexts, const local_operation<TS, TI, TR> *op, unsigned int subject_layer, const std::vector<unsigned int> &intruder_layers) const;

View File

@ -54,6 +54,11 @@ enum OnEmptyIntruderHint {
*/ */
Copy, Copy,
/**
* @brief Copy the subject shape to the second result
*/
CopyToSecond,
/** /**
* @brief Drop the subject shape * @brief Drop the subject shape
*/ */

View File

@ -725,7 +725,7 @@ template DB_PUBLIC void split_polygon<> (const db::DSimplePolygon &polygon, std:
// Smoothing tools // Smoothing tools
void void
smooth_contour (db::Polygon::polygon_contour_iterator from, db::Polygon::polygon_contour_iterator to, std::vector <db::Point> &points, db::Coord d) smooth_contour (db::Polygon::polygon_contour_iterator from, db::Polygon::polygon_contour_iterator to, std::vector <db::Point> &points, db::Coord d, bool keep_hv)
{ {
points.clear (); points.clear ();
points.reserve (std::distance (from, to)); points.reserve (std::distance (from, to));
@ -781,7 +781,9 @@ smooth_contour (db::Polygon::polygon_contour_iterator from, db::Polygon::polygon
bool can_drop = false; bool can_drop = false;
if (db::Coord (p1.distance(p0)) <= d && db::sprod_sign (p2 - p1, p0 - pm1) > 0 && std::abs (db::vprod (p2 - p1, p0 - pm1)) < 0.8 * p2.distance (p1) * p0.distance (pm1)) { if (keep_hv && (p1.x () == p0.x () || p1.y () == p0.y () || p2.x () == p1.x () || p2.y () == p1.y ())) {
// keep points which participate in either a vertical or horizontal edge
} else if (db::Coord (p1.distance(p0)) <= d && db::sprod_sign (p2 - p1, p0 - pm1) > 0 && std::abs (db::vprod (p2 - p1, p0 - pm1)) < 0.8 * p2.distance (p1) * p0.distance (pm1)) {
// jog configurations with small edges are candidates // jog configurations with small edges are candidates
can_drop = true; can_drop = true;
} else if (db::vprod_sign (p2 - p1, p1 - p0) < 0) { } else if (db::vprod_sign (p2 - p1, p1 - p0) < 0) {
@ -839,19 +841,19 @@ smooth_contour (db::Polygon::polygon_contour_iterator from, db::Polygon::polygon
} }
db::Polygon db::Polygon
smooth (const db::Polygon &polygon, db::Coord d) smooth (const db::Polygon &polygon, db::Coord d, bool keep_hv)
{ {
db::Polygon new_poly; db::Polygon new_poly;
std::vector <db::Point> new_pts; std::vector <db::Point> new_pts;
smooth_contour (polygon.begin_hull (), polygon.end_hull (), new_pts, d); smooth_contour (polygon.begin_hull (), polygon.end_hull (), new_pts, d, keep_hv);
if (new_pts.size () >= 3) { if (new_pts.size () >= 3) {
new_poly.assign_hull (new_pts.begin (), new_pts.end (), false /*don't compress*/); new_poly.assign_hull (new_pts.begin (), new_pts.end (), false /*don't compress*/);
for (unsigned int h = 0; h < polygon.holes (); ++h) { for (unsigned int h = 0; h < polygon.holes (); ++h) {
new_pts.clear (); new_pts.clear ();
smooth_contour (polygon.begin_hole (h), polygon.end_hole (h), new_pts, d); smooth_contour (polygon.begin_hole (h), polygon.end_hole (h), new_pts, d, keep_hv);
if (new_pts.size () >= 3) { if (new_pts.size () >= 3) {
new_poly.insert_hole (new_pts.begin (), new_pts.end (), false /*don't compress*/); new_poly.insert_hole (new_pts.begin (), new_pts.end (), false /*don't compress*/);
} }

View File

@ -449,6 +449,8 @@ db::Polygon DB_PUBLIC compute_rounded (const db::Polygon &poly, double rinner, d
*/ */
db::DPolygon DB_PUBLIC compute_rounded (const db::DPolygon &poly, double rinner, double router, unsigned int n); db::DPolygon DB_PUBLIC compute_rounded (const db::DPolygon &poly, double rinner, double router, unsigned int n);
#define KLAYOUT_SMOOTH_HAS_KEEP_HV 1
/** /**
* @brief Smooth a contour * @brief Smooth a contour
* *
@ -458,13 +460,14 @@ db::DPolygon DB_PUBLIC compute_rounded (const db::DPolygon &poly, double rinner,
* @param to The end of the contour * @param to The end of the contour
* @param new_pts The points that make up the new contour * @param new_pts The points that make up the new contour
* @param d The distance that determines the smoothing "roughness" * @param d The distance that determines the smoothing "roughness"
* @param keep_hv If true, vertical and horizontal edges are maintained
*/ */
void DB_PUBLIC smooth_contour (db::Polygon::polygon_contour_iterator from, db::Polygon::polygon_contour_iterator to, std::vector <db::Point> &new_pts, db::Coord d); void DB_PUBLIC smooth_contour (db::Polygon::polygon_contour_iterator from, db::Polygon::polygon_contour_iterator to, std::vector <db::Point> &new_pts, db::Coord d, bool keep_hv);
/** /**
* @brief Smooth a polygon (apply smoothing to the whole polygon) * @brief Smooth a polygon (apply smoothing to the whole polygon)
*/ */
db::Polygon DB_PUBLIC smooth (const db::Polygon &poly, db::Coord d); db::Polygon DB_PUBLIC smooth (const db::Polygon &poly, db::Coord d, bool keep_hv);
/** /**
* @brief Returns a value indicating whether the polygon is an "strange polygon" * @brief Returns a value indicating whether the polygon is an "strange polygon"

View File

@ -263,15 +263,15 @@ Region::rounded_corners (double rinner, double router, unsigned int n) const
} }
void void
Region::smooth (coord_type d) Region::smooth (coord_type d, bool keep_hv)
{ {
process (SmoothingProcessor (d)); process (SmoothingProcessor (d, keep_hv));
} }
Region Region
Region::smoothed (coord_type d) const Region::smoothed (coord_type d, bool keep_hv) const
{ {
return processed (SmoothingProcessor (d)); return processed (SmoothingProcessor (d, keep_hv));
} }
void void

View File

@ -267,6 +267,16 @@ public:
return mp_delegate; return mp_delegate;
} }
/**
* @brief Takes the underlying delegate object
*/
RegionDelegate *take_delegate ()
{
RegionDelegate *delegate = mp_delegate;
mp_delegate = 0;
return delegate;
}
/** /**
* @brief Sets the base verbosity * @brief Sets the base verbosity
* *
@ -1132,6 +1142,19 @@ public:
return Region (mp_delegate->selected_not_outside (other)); return Region (mp_delegate->selected_not_outside (other));
} }
/**
* @brief Returns all polygons of this which are completly outside polygons from the other region and the opposite ones at the same time
*
* This method is equivalent to calling selected_outside and selected_not_outside, but faster.
*
* Merged semantics applies.
*/
std::pair<Region, Region> selected_outside_differential (const Region &other) const
{
std::pair<db::RegionDelegate *, db::RegionDelegate *> p = mp_delegate->selected_outside_pair (other);
return std::pair<Region, Region> (Region (p.first), Region (p.second));
}
/** /**
* @brief Selects all polygons of this region which are completly inside polygons from the other region * @brief Selects all polygons of this region which are completly inside polygons from the other region
* *
@ -1178,6 +1201,19 @@ public:
return Region (mp_delegate->selected_not_inside (other)); return Region (mp_delegate->selected_not_inside (other));
} }
/**
* @brief Returns all polygons of this which are completly inside polygons from the other region and the opposite ones at the same time
*
* This method is equivalent to calling selected_inside and selected_not_inside, but faster.
*
* Merged semantics applies.
*/
std::pair<Region, Region> selected_inside_differential (const Region &other) const
{
std::pair<db::RegionDelegate *, db::RegionDelegate *> p = mp_delegate->selected_inside_pair (other);
return std::pair<Region, Region> (Region (p.first), Region (p.second));
}
/** /**
* @brief Returns all polygons of this which are enclosing polygons from the other region * @brief Returns all polygons of this which are enclosing polygons from the other region
* *
@ -1224,6 +1260,19 @@ public:
return Region (mp_delegate->selected_not_enclosing (other, min_count, max_count)); return Region (mp_delegate->selected_not_enclosing (other, min_count, max_count));
} }
/**
* @brief Returns all polygons of this which are completly enclosing polygons from the other region and the opposite ones at the same time
*
* This method is equivalent to calling selected_enclosing and selected_not_enclosing, but faster.
*
* Merged semantics applies.
*/
std::pair<Region, Region> selected_enclosing_differential (const Region &other, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ()) const
{
std::pair<db::RegionDelegate *, db::RegionDelegate *> p = mp_delegate->selected_enclosing_pair (other, min_count, max_count);
return std::pair<Region, Region> (Region (p.first), Region (p.second));
}
/** /**
* @brief Selects all polygons of this region which overlap or touch polygons from the other region * @brief Selects all polygons of this region which overlap or touch polygons from the other region
* *
@ -1278,6 +1327,19 @@ public:
return Region (mp_delegate->selected_not_interacting (other, min_count, max_count)); return Region (mp_delegate->selected_not_interacting (other, min_count, max_count));
} }
/**
* @brief Returns all polygons of this which are interacting with polygons from the other region and the opposite ones at the same time
*
* This method is equivalent to calling selected_interacting and selected_not_interacting, but faster.
*
* Merged semantics applies.
*/
std::pair<Region, Region> selected_interacting_differential (const Region &other, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ()) const
{
std::pair<db::RegionDelegate *, db::RegionDelegate *> p = mp_delegate->selected_interacting_pair (other, min_count, max_count);
return std::pair<Region, Region> (Region (p.first), Region (p.second));
}
/** /**
* @brief Selects all polygons of this region which overlap or touch edges from the given edge collection * @brief Selects all polygons of this region which overlap or touch edges from the given edge collection
* *
@ -1324,6 +1386,19 @@ public:
return Region (mp_delegate->selected_not_interacting (other, min_count, max_count)); return Region (mp_delegate->selected_not_interacting (other, min_count, max_count));
} }
/**
* @brief Returns all polygons of this which are interacting with edges from the other region and the opposite ones at the same time
*
* This method is equivalent to calling selected_interacting and selected_not_interacting, but faster.
*
* Merged semantics applies.
*/
std::pair<Region, Region> selected_interacting_differential (const Edges &other, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ()) const
{
std::pair<db::RegionDelegate *, db::RegionDelegate *> p = mp_delegate->selected_interacting_pair (other, min_count, max_count);
return std::pair<Region, Region> (Region (p.first), Region (p.second));
}
/** /**
* @brief Selects all polygons of this region which overlap or touch texts from the text collection * @brief Selects all polygons of this region which overlap or touch texts from the text collection
* *
@ -1370,6 +1445,19 @@ public:
return Region (mp_delegate->selected_not_interacting (other, min_count, max_count)); return Region (mp_delegate->selected_not_interacting (other, min_count, max_count));
} }
/**
* @brief Returns all polygons of this which are interacting with texts from the other region and the opposite ones at the same time
*
* This method is equivalent to calling selected_interacting and selected_not_interacting, but faster.
*
* Merged semantics applies.
*/
std::pair<Region, Region> selected_interacting_differential (const Texts &other, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ()) const
{
std::pair<db::RegionDelegate *, db::RegionDelegate *> p = mp_delegate->selected_interacting_pair (other, min_count, max_count);
return std::pair<Region, Region> (Region (p.first), Region (p.second));
}
/** /**
* @brief Selects all polygons of this region which overlap polygons from the other region * @brief Selects all polygons of this region which overlap polygons from the other region
* *
@ -1416,6 +1504,19 @@ public:
return Region (mp_delegate->selected_not_overlapping (other, min_count, max_count)); return Region (mp_delegate->selected_not_overlapping (other, min_count, max_count));
} }
/**
* @brief Returns all polygons of this which are overlapping polygons from the other region and the opposite ones at the same time
*
* This method is equivalent to calling selected_overlapping and selected_not_overlapping, but faster.
*
* Merged semantics applies.
*/
std::pair<Region, Region> selected_overlapping_differential (const Region &other, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ()) const
{
std::pair<db::RegionDelegate *, db::RegionDelegate *> p = mp_delegate->selected_overlapping_pair (other, min_count, max_count);
return std::pair<Region, Region> (Region (p.first), Region (p.second));
}
/** /**
* @brief Returns all polygons of "other" which are inside polygons of this region * @brief Returns all polygons of "other" which are inside polygons of this region
* *
@ -1518,14 +1619,14 @@ public:
/** /**
* @brief Smoothes the region (in-place) * @brief Smoothes the region (in-place)
*/ */
void smooth (coord_type d); void smooth (coord_type d, bool keep_hv);
/** /**
* @brief Returns the smoothed region * @brief Returns the smoothed region
* *
* @param d The smoothing accuracy * @param d The smoothing accuracy
*/ */
Region smoothed (coord_type d) const; Region smoothed (coord_type d, bool keep_hv) const;
/** /**
* @brief Returns the nth polygon * @brief Returns the nth polygon

View File

@ -281,18 +281,25 @@ public:
virtual RegionDelegate *selected_outside (const Region &other) const = 0; virtual RegionDelegate *selected_outside (const Region &other) const = 0;
virtual RegionDelegate *selected_not_outside (const Region &other) const = 0; virtual RegionDelegate *selected_not_outside (const Region &other) const = 0;
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_outside_pair (const Region &other) const = 0;
virtual RegionDelegate *selected_inside (const Region &other) const = 0; virtual RegionDelegate *selected_inside (const Region &other) const = 0;
virtual RegionDelegate *selected_not_inside (const Region &other) const = 0; virtual RegionDelegate *selected_not_inside (const Region &other) const = 0;
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_inside_pair (const Region &other) const = 0;
virtual RegionDelegate *selected_enclosing (const Region &other, size_t min_count, size_t max_count) const = 0; virtual RegionDelegate *selected_enclosing (const Region &other, size_t min_count, size_t max_count) const = 0;
virtual RegionDelegate *selected_not_enclosing (const Region &other, size_t min_count, size_t max_count) const = 0; virtual RegionDelegate *selected_not_enclosing (const Region &other, size_t min_count, size_t max_count) const = 0;
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_enclosing_pair (const Region &other, size_t min_count, size_t max_count) const = 0;
virtual RegionDelegate *selected_interacting (const Region &other, size_t min_count, size_t max_count) const = 0; virtual RegionDelegate *selected_interacting (const Region &other, size_t min_count, size_t max_count) const = 0;
virtual RegionDelegate *selected_not_interacting (const Region &other, size_t min_count, size_t max_count) const = 0; virtual RegionDelegate *selected_not_interacting (const Region &other, size_t min_count, size_t max_count) const = 0;
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_interacting_pair (const Region &other, size_t min_count, size_t max_count) const = 0;
virtual RegionDelegate *selected_interacting (const Edges &other, size_t min_count, size_t max_count) const = 0; virtual RegionDelegate *selected_interacting (const Edges &other, size_t min_count, size_t max_count) const = 0;
virtual RegionDelegate *selected_not_interacting (const Edges &other, size_t min_count, size_t max_count) const = 0; virtual RegionDelegate *selected_not_interacting (const Edges &other, size_t min_count, size_t max_count) const = 0;
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_interacting_pair (const Edges &other, size_t min_count, size_t max_count) const = 0;
virtual RegionDelegate *selected_interacting (const Texts &other, size_t min_count, size_t max_count) const = 0; virtual RegionDelegate *selected_interacting (const Texts &other, size_t min_count, size_t max_count) const = 0;
virtual RegionDelegate *selected_not_interacting (const Texts &other, size_t min_count, size_t max_count) const = 0; virtual RegionDelegate *selected_not_interacting (const Texts &other, size_t min_count, size_t max_count) const = 0;
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_interacting_pair (const Texts &other, size_t min_count, size_t max_count) const = 0;
virtual RegionDelegate *selected_overlapping (const Region &other, size_t min_count, size_t max_count) const = 0; virtual RegionDelegate *selected_overlapping (const Region &other, size_t min_count, size_t max_count) const = 0;
virtual RegionDelegate *selected_not_overlapping (const Region &other, size_t min_count, size_t max_count) const = 0; virtual RegionDelegate *selected_not_overlapping (const Region &other, size_t min_count, size_t max_count) const = 0;
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_overlapping_pair (const Region &other, size_t min_count, size_t max_count) const = 0;
virtual RegionDelegate *pull_inside (const Region &other) const = 0; virtual RegionDelegate *pull_inside (const Region &other) const = 0;
virtual RegionDelegate *pull_interacting (const Region &other) const = 0; virtual RegionDelegate *pull_interacting (const Region &other) const = 0;
virtual EdgesDelegate *pull_interacting (const Edges &other) const = 0; virtual EdgesDelegate *pull_interacting (const Edges &other) const = 0;

View File

@ -537,8 +537,8 @@ private:
} }
template <class TS, class TI, class TR> template <class TS, class TI, class TR>
interacting_local_operation<TS, TI, TR>::interacting_local_operation (int mode, bool touching, bool inverse, size_t min_count, size_t max_count, bool other_is_merged) interacting_local_operation<TS, TI, TR>::interacting_local_operation (int mode, bool touching, InteractingOutputMode output_mode, size_t min_count, size_t max_count, bool other_is_merged)
: m_mode (mode), m_touching (touching), m_inverse (inverse), m_min_count (std::max (size_t (1), min_count)), m_max_count (max_count), m_other_is_merged (other_is_merged) : m_mode (mode), m_touching (touching), m_output_mode (output_mode), m_min_count (std::max (size_t (1), min_count)), m_max_count (max_count), m_other_is_merged (other_is_merged)
{ {
// .. nothing yet .. // .. nothing yet ..
} }
@ -552,8 +552,13 @@ db::Coord interacting_local_operation<TS, TI, TR>::dist () const
template <class TS, class TI, class TR> template <class TS, class TI, class TR>
void interacting_local_operation<TS, TI, TR>::do_compute_local (db::Layout * /*layout*/, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<TR> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const void interacting_local_operation<TS, TI, TR>::do_compute_local (db::Layout * /*layout*/, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<TR> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const
{ {
tl_assert (results.size () == 1); if (m_output_mode == None) {
std::unordered_set<TR> &result = results.front (); return;
} else if (m_output_mode == Positive || m_output_mode == Negative) {
tl_assert (results.size () == 1);
} else {
tl_assert (results.size () == 2);
}
db::EdgeProcessor ep; db::EdgeProcessor ep;
@ -652,9 +657,21 @@ void interacting_local_operation<TS, TI, TR>::do_compute_local (db::Layout * /*l
if (c != interaction_counts.end ()) { if (c != interaction_counts.end ()) {
count = c->second; count = c->second;
} }
if ((count >= m_min_count && count <= m_max_count) != m_inverse) { bool good = (count >= m_min_count && count <= m_max_count);
const TS &subject = interactions.subject_shape (i->first); if (good) {
result.insert (subject); if (m_output_mode == Positive || m_output_mode == PositiveAndNegative) {
const TS &subject = interactions.subject_shape (i->first);
results [0].insert (subject);
}
} else {
if (m_output_mode == Negative) {
const TS &subject = interactions.subject_shape (i->first);
// Yes, it's "positive_result" as this is the first one.
results [0].insert (subject);
} else if (m_output_mode == PositiveAndNegative) {
const TS &subject = interactions.subject_shape (i->first);
results [1].insert (subject);
}
} }
} }
} }
@ -663,11 +680,22 @@ template <class TS, class TI, class TR>
OnEmptyIntruderHint OnEmptyIntruderHint
interacting_local_operation<TS, TI, TR>::on_empty_intruder_hint () const interacting_local_operation<TS, TI, TR>::on_empty_intruder_hint () const
{ {
if ((m_mode <= 0) != m_inverse) { if ((m_mode <= 0)) {
return OnEmptyIntruderHint::Drop; if (m_output_mode == Positive) {
return OnEmptyIntruderHint::Drop;
} else if (m_output_mode == Negative) {
return OnEmptyIntruderHint::Copy;
} else if (m_output_mode == PositiveAndNegative) {
return OnEmptyIntruderHint::CopyToSecond;
}
} else { } else {
return OnEmptyIntruderHint::Copy; if (m_output_mode == Positive || m_output_mode == PositiveAndNegative) {
return OnEmptyIntruderHint::Copy;
} else if (m_output_mode == Negative) {
return OnEmptyIntruderHint::Drop;
}
} }
return OnEmptyIntruderHint::Ignore;
} }
template <class TS, class TI, class TR> template <class TS, class TI, class TR>
@ -761,8 +789,8 @@ template class DB_PUBLIC pull_local_operation<db::Polygon, db::Polygon, db::Poly
// --------------------------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------------------------
template <class TS, class TI, class TR> template <class TS, class TI, class TR>
interacting_with_edge_local_operation<TS, TI, TR>::interacting_with_edge_local_operation (bool inverse, size_t min_count, size_t max_count, bool other_is_merged) interacting_with_edge_local_operation<TS, TI, TR>::interacting_with_edge_local_operation (InteractingOutputMode output_mode, size_t min_count, size_t max_count, bool other_is_merged)
: m_inverse (inverse), m_min_count (std::max (size_t (1), min_count)), m_max_count (max_count), m_other_is_merged (other_is_merged) : m_output_mode (output_mode), m_min_count (std::max (size_t (1), min_count)), m_max_count (max_count), m_other_is_merged (other_is_merged)
{ {
// .. nothing yet .. // .. nothing yet ..
} }
@ -777,6 +805,14 @@ db::Coord interacting_with_edge_local_operation<TS, TI, TR>::dist () const
template <class TS, class TI, class TR> template <class TS, class TI, class TR>
void interacting_with_edge_local_operation<TS, TI, TR>::do_compute_local (db::Layout *layout, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<TR> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const void interacting_with_edge_local_operation<TS, TI, TR>::do_compute_local (db::Layout *layout, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<TR> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const
{ {
if (m_output_mode == None) {
return;
} else if (m_output_mode == Positive || m_output_mode == Negative) {
tl_assert (results.size () == 1);
} else {
tl_assert (results.size () == 2);
}
std::unordered_map<TR, size_t> counted_results; std::unordered_map<TR, size_t> counted_results;
bool counting = !(m_min_count == 1 && m_max_count == std::numeric_limits<size_t>::max ()); bool counting = !(m_min_count == 1 && m_max_count == std::numeric_limits<size_t>::max ());
@ -829,7 +865,7 @@ void interacting_with_edge_local_operation<TS, TI, TR>::do_compute_local (db::La
const TR *addressable = push_polygon_to_heap (layout, subject, heap); const TR *addressable = push_polygon_to_heap (layout, subject, heap);
scanner.insert1 (addressable, 0); scanner.insert1 (addressable, 0);
if (m_inverse) { if (m_output_mode == Negative || m_output_mode == PositiveAndNegative) {
inserter.init (*addressable); inserter.init (*addressable);
} }
@ -839,13 +875,18 @@ void interacting_with_edge_local_operation<TS, TI, TR>::do_compute_local (db::La
// select hits based on their count // select hits based on their count
tl_assert (results.size () == 1);
std::unordered_set<TR> &result = results.front ();
for (typename std::unordered_map<TR, size_t>::const_iterator r = counted_results.begin (); r != counted_results.end (); ++r) { for (typename std::unordered_map<TR, size_t>::const_iterator r = counted_results.begin (); r != counted_results.end (); ++r) {
bool hit = r->second >= m_min_count && r->second <= m_max_count; bool hit = r->second >= m_min_count && r->second <= m_max_count;
if (hit != m_inverse) { if (hit) {
result.insert (r->first); if (m_output_mode == Positive || m_output_mode == PositiveAndNegative) {
results [0].insert (r->first);
}
} else {
if (m_output_mode == Negative) {
results [0].insert (r->first);
} else if (m_output_mode == PositiveAndNegative) {
results [1].insert (r->first);
}
} }
} }
} }
@ -853,10 +894,14 @@ void interacting_with_edge_local_operation<TS, TI, TR>::do_compute_local (db::La
template <class TS, class TI, class TR> template <class TS, class TI, class TR>
OnEmptyIntruderHint interacting_with_edge_local_operation<TS, TI, TR>::on_empty_intruder_hint () const OnEmptyIntruderHint interacting_with_edge_local_operation<TS, TI, TR>::on_empty_intruder_hint () const
{ {
if (!m_inverse) { if (m_output_mode == Positive) {
return OnEmptyIntruderHint::Drop; return OnEmptyIntruderHint::Drop;
} else { } else if (m_output_mode == Negative) {
return OnEmptyIntruderHint::Copy; return OnEmptyIntruderHint::Copy;
} else if (m_output_mode == PositiveAndNegative) {
return OnEmptyIntruderHint::CopyToSecond;
} else {
return OnEmptyIntruderHint::Ignore;
} }
} }
@ -1000,8 +1045,8 @@ template class DB_PUBLIC pull_with_text_local_operation<db::Polygon, db::Text, d
// --------------------------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------------------------
template <class TS, class TI, class TR> template <class TS, class TI, class TR>
interacting_with_text_local_operation<TS, TI, TR>::interacting_with_text_local_operation (bool inverse, size_t min_count, size_t max_count) interacting_with_text_local_operation<TS, TI, TR>::interacting_with_text_local_operation (InteractingOutputMode output_mode, size_t min_count, size_t max_count)
: m_inverse (inverse), m_min_count (std::max (size_t (1), min_count)), m_max_count (max_count) : m_output_mode (output_mode), m_min_count (std::max (size_t (1), min_count)), m_max_count (max_count)
{ {
// .. nothing yet .. // .. nothing yet ..
} }
@ -1017,6 +1062,14 @@ db::Coord interacting_with_text_local_operation<TS, TI, TR>::dist () const
template <class TS, class TI, class TR> template <class TS, class TI, class TR>
void interacting_with_text_local_operation<TS, TI, TR>::do_compute_local (db::Layout *layout, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<TR> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const void interacting_with_text_local_operation<TS, TI, TR>::do_compute_local (db::Layout *layout, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<TR> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const
{ {
if (m_output_mode == None) {
return;
} else if (m_output_mode == Positive || m_output_mode == Negative) {
tl_assert (results.size () == 1);
} else {
tl_assert (results.size () == 2);
}
std::unordered_map<TR, size_t> counted_results; std::unordered_map<TR, size_t> counted_results;
bool counting = !(m_min_count == 1 && m_max_count == std::numeric_limits<size_t>::max ()); bool counting = !(m_min_count == 1 && m_max_count == std::numeric_limits<size_t>::max ());
@ -1042,7 +1095,7 @@ void interacting_with_text_local_operation<TS, TI, TR>::do_compute_local (db::La
const TR *addressable = push_polygon_to_heap (layout, interactions.subject_shape (i->first), heap); const TR *addressable = push_polygon_to_heap (layout, interactions.subject_shape (i->first), heap);
scanner.insert1 (addressable, 0); scanner.insert1 (addressable, 0);
if (m_inverse) { if (m_output_mode == Negative || m_output_mode == PositiveAndNegative) {
inserter.init (*addressable); inserter.init (*addressable);
} }
@ -1052,13 +1105,19 @@ void interacting_with_text_local_operation<TS, TI, TR>::do_compute_local (db::La
// select hits based on their count // select hits based on their count
tl_assert (results.size () == 1);
std::unordered_set<TR> &result = results.front ();
for (typename std::unordered_map<TR, size_t>::const_iterator r = counted_results.begin (); r != counted_results.end (); ++r) { for (typename std::unordered_map<TR, size_t>::const_iterator r = counted_results.begin (); r != counted_results.end (); ++r) {
bool hit = r->second >= m_min_count && r->second <= m_max_count; bool hit = r->second >= m_min_count && r->second <= m_max_count;
if (hit != m_inverse) { if (hit) {
result.insert (r->first); if (m_output_mode == Positive || m_output_mode == PositiveAndNegative) {
results [0].insert (r->first);
}
} else {
if (m_output_mode == Negative) {
// Yes. It's "positive"! This is the first output.
results [0].insert (r->first);
} else if (m_output_mode == PositiveAndNegative) {
results [1].insert (r->first);
}
} }
} }
} }
@ -1066,10 +1125,14 @@ void interacting_with_text_local_operation<TS, TI, TR>::do_compute_local (db::La
template <class TS, class TI, class TR> template <class TS, class TI, class TR>
OnEmptyIntruderHint interacting_with_text_local_operation<TS, TI, TR>::on_empty_intruder_hint () const OnEmptyIntruderHint interacting_with_text_local_operation<TS, TI, TR>::on_empty_intruder_hint () const
{ {
if (!m_inverse) { if (m_output_mode == Positive) {
return OnEmptyIntruderHint::Drop; return OnEmptyIntruderHint::Drop;
} else { } else if (m_output_mode == Negative) {
return OnEmptyIntruderHint::Copy; return OnEmptyIntruderHint::Copy;
} else if (m_output_mode == PositiveAndNegative) {
return OnEmptyIntruderHint::CopyToSecond;
} else {
return OnEmptyIntruderHint::Ignore;
} }
} }

View File

@ -222,12 +222,16 @@ private:
typedef check_local_operation<db::PolygonRef, db::PolygonRef> CheckLocalOperation; typedef check_local_operation<db::PolygonRef, db::PolygonRef> CheckLocalOperation;
enum InteractingOutputMode {
None = 0, Positive = 1, Negative = 2, PositiveAndNegative = 3
};
template <class TS, class TI, class TR> template <class TS, class TI, class TR>
class interacting_local_operation class interacting_local_operation
: public local_operation<TS, TI, TR> : public local_operation<TS, TI, TR>
{ {
public: public:
interacting_local_operation (int mode, bool touching, bool inverse, size_t min_count, size_t max_count, bool other_is_merged); interacting_local_operation (int mode, bool touching, InteractingOutputMode output_mode, size_t min_count, size_t max_count, bool other_is_merged);
virtual db::Coord dist () const; virtual db::Coord dist () const;
virtual void do_compute_local (db::Layout * /*layout*/, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<TR> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const; virtual void do_compute_local (db::Layout * /*layout*/, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<TR> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const;
@ -237,7 +241,7 @@ public:
private: private:
int m_mode; int m_mode;
bool m_touching; bool m_touching;
bool m_inverse; InteractingOutputMode m_output_mode;
size_t m_min_count, m_max_count; size_t m_min_count, m_max_count;
bool m_other_is_merged; bool m_other_is_merged;
}; };
@ -268,7 +272,7 @@ class interacting_with_edge_local_operation
: public local_operation<TS, TI, TR> : public local_operation<TS, TI, TR>
{ {
public: public:
interacting_with_edge_local_operation (bool inverse, size_t min_count, size_t max_count, bool other_is_merged); interacting_with_edge_local_operation (InteractingOutputMode output_mode, size_t min_count, size_t max_count, bool other_is_merged);
virtual db::Coord dist () const; virtual db::Coord dist () const;
virtual void do_compute_local (db::Layout *layout, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<TR> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const; virtual void do_compute_local (db::Layout *layout, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<TR> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const;
@ -276,7 +280,7 @@ public:
virtual std::string description () const; virtual std::string description () const;
private: private:
bool m_inverse; InteractingOutputMode m_output_mode;
size_t m_min_count, m_max_count; size_t m_min_count, m_max_count;
bool m_other_is_merged; bool m_other_is_merged;
}; };
@ -303,7 +307,7 @@ class interacting_with_text_local_operation
: public local_operation<TS, TI, TR> : public local_operation<TS, TI, TR>
{ {
public: public:
interacting_with_text_local_operation (bool inverse, size_t min_count, size_t max_count); interacting_with_text_local_operation (InteractingOutputMode output_mode, size_t min_count, size_t max_count);
virtual db::Coord dist () const; virtual db::Coord dist () const;
virtual void do_compute_local (db::Layout *layout, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<TR> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const; virtual void do_compute_local (db::Layout *layout, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<TR> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const;
@ -311,7 +315,7 @@ public:
virtual std::string description () const; virtual std::string description () const;
private: private:
bool m_inverse; InteractingOutputMode m_output_mode;
size_t m_min_count, m_max_count; size_t m_min_count, m_max_count;
}; };

View File

@ -868,14 +868,14 @@ StrangePolygonCheckProcessor::process (const db::Polygon &poly, std::vector<db::
// ------------------------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------------------------
// Smoothing processor // Smoothing processor
SmoothingProcessor::SmoothingProcessor (db::Coord d) : m_d (d) { } SmoothingProcessor::SmoothingProcessor (db::Coord d, bool keep_hv) : m_d (d), m_keep_hv (keep_hv) { }
SmoothingProcessor::~SmoothingProcessor () { } SmoothingProcessor::~SmoothingProcessor () { }
void void
SmoothingProcessor::process (const db::Polygon &poly, std::vector<db::Polygon> &res) const SmoothingProcessor::process (const db::Polygon &poly, std::vector<db::Polygon> &res) const
{ {
res.push_back (db::smooth (poly, m_d)); res.push_back (db::smooth (poly, m_d, m_keep_hv));
} }
// ------------------------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------------------------

View File

@ -504,7 +504,7 @@ class DB_PUBLIC SmoothingProcessor
: public PolygonProcessorBase : public PolygonProcessorBase
{ {
public: public:
SmoothingProcessor (db::Coord d); SmoothingProcessor (db::Coord d, bool keep_hv);
~SmoothingProcessor (); ~SmoothingProcessor ();
virtual void process (const db::Polygon &poly, std::vector<db::Polygon> &res) const; virtual void process (const db::Polygon &poly, std::vector<db::Polygon> &res) const;
@ -517,6 +517,7 @@ public:
private: private:
db::Coord m_d; db::Coord m_d;
bool m_keep_hv;
db::MagnificationReducer m_vars; db::MagnificationReducer m_vars;
}; };

View File

@ -185,10 +185,10 @@ static db::CompoundRegionOperationNode *new_strange_polygons_filter (db::Compoun
return new db::CompoundRegionProcessingOperationNode (new db::StrangePolygonCheckProcessor (), input, true /*processor is owned*/); return new db::CompoundRegionProcessingOperationNode (new db::StrangePolygonCheckProcessor (), input, true /*processor is owned*/);
} }
static db::CompoundRegionOperationNode *new_smoothed (db::CompoundRegionOperationNode *input, db::Coord d) static db::CompoundRegionOperationNode *new_smoothed (db::CompoundRegionOperationNode *input, db::Coord d, bool keep_hv)
{ {
check_non_null (input, "input"); check_non_null (input, "input");
return new db::CompoundRegionProcessingOperationNode (new db::SmoothingProcessor (d), input, true /*processor is owned*/, d); return new db::CompoundRegionProcessingOperationNode (new db::SmoothingProcessor (d, keep_hv), input, true /*processor is owned*/, d);
} }
static db::CompoundRegionOperationNode *new_rounded_corners (db::CompoundRegionOperationNode *input, double rinner, double router, unsigned int n) static db::CompoundRegionOperationNode *new_rounded_corners (db::CompoundRegionOperationNode *input, double rinner, double router, unsigned int n)
@ -572,9 +572,10 @@ Class<db::CompoundRegionOperationNode> decl_CompoundRegionOperationNode ("db", "
"@brief Creates a node extracting strange polygons.\n" "@brief Creates a node extracting strange polygons.\n"
"'strange polygons' are ones which cannot be oriented - e.g. '8' shape polygons." "'strange polygons' are ones which cannot be oriented - e.g. '8' shape polygons."
) + ) +
gsi::constructor ("new_smoothed", &new_smoothed, gsi::arg ("input"), gsi::arg ("d"), gsi::constructor ("new_smoothed", &new_smoothed, gsi::arg ("input"), gsi::arg ("d"), gsi::arg ("keep_hv", false),
"@brief Creates a node smoothing the polygons.\n" "@brief Creates a node smoothing the polygons.\n"
"@param d The tolerance to be applied for the smoothing." "@param d The tolerance to be applied for the smoothing.\n"
"@param keep_hv If true, horizontal and vertical edges are maintained.\n"
) + ) +
gsi::constructor ("new_rounded_corners", &new_rounded_corners, gsi::arg ("input"), gsi::arg ("rinner"), gsi::arg ("router"), gsi::arg ("n"), gsi::constructor ("new_rounded_corners", &new_rounded_corners, gsi::arg ("input"), gsi::arg ("rinner"), gsi::arg ("router"), gsi::arg ("n"),
"@brief Creates a node generating rounded corners.\n" "@brief Creates a node generating rounded corners.\n"

View File

@ -1602,9 +1602,9 @@ static db::Polygon transformed_icplx_dp (const db::Polygon *p, const db::ICplxTr
return p->transformed (t, false /*don't compress*/); return p->transformed (t, false /*don't compress*/);
} }
static db::Polygon smooth (const db::Polygon *p, db::Coord d) static db::Polygon smooth (const db::Polygon *p, db::Coord d, bool keep_hv)
{ {
return db::smooth (*p, d); return db::smooth (*p, d, keep_hv);
} }
static db::Polygon minkowsky_sum_pe (const db::Polygon *p, const db::Edge &e, bool rh) static db::Polygon minkowsky_sum_pe (const db::Polygon *p, const db::Edge &e, bool rh)
@ -1787,17 +1787,18 @@ Class<db::Polygon> decl_Polygon ("db", "Polygon",
"\n" "\n"
"This method was introduced in version 0.22.\n" "This method was introduced in version 0.22.\n"
) + ) +
method_ext ("smooth", &smooth, gsi::arg ("d"), method_ext ("smooth", &smooth, gsi::arg ("d"), gsi::arg ("keep_hv", false),
"@brief Smoothes a polygon\n" "@brief Smoothes a polygon\n"
"\n" "\n"
"Remove vertices that deviate by more than the distance d from the average contour.\n" "Remove vertices that deviate by more than the distance d from the average contour.\n"
"The value d is basically the roughness which is removed.\n" "The value d is basically the roughness which is removed.\n"
"\n" "\n"
"@param d The smoothing \"roughness\".\n" "@param d The smoothing \"roughness\".\n"
"@param keep_hv If true, horizontal and vertical edges will be preserved always.\n"
"\n" "\n"
"@return The smoothed polygon.\n" "@return The smoothed polygon.\n"
"\n" "\n"
"This method was introduced in version 0.23.\n" "This method was introduced in version 0.23. The 'keep_hv' optional parameter was added in version 0.27.\n"
) + ) +
method_ext ("minkowsky_sum", &minkowsky_sum_pe, gsi::arg ("e"), gsi::arg ("resolve_holes"), method_ext ("minkowsky_sum", &minkowsky_sum_pe, gsi::arg ("e"), gsi::arg ("resolve_holes"),
"@brief Computes the Minkowsky sum of the polygon and an edge\n" "@brief Computes the Minkowsky sum of the polygon and an edge\n"

View File

@ -610,15 +610,53 @@ static db::EdgePairs separation2 (const db::Region *r, const db::Region &other,
); );
} }
static inline std::vector<db::Region> as_2region_vector (const std::pair<db::Region, db::Region> &rp)
{
std::vector<db::Region> res;
res.reserve (2);
res.push_back (db::Region (const_cast<db::Region &> (rp.first).take_delegate ()));
res.push_back (db::Region (const_cast<db::Region &> (rp.second).take_delegate ()));
return res;
}
static std::vector<db::Region> andnot (const db::Region *r, const db::Region &other) static std::vector<db::Region> andnot (const db::Region *r, const db::Region &other)
{ {
std::pair<db::Region, db::Region> rp = r->andnot (other); return as_2region_vector (r->andnot (other));
}
std::vector<db::Region> res; static std::vector<db::Region> split_inside (const db::Region *r, const db::Region &other)
res.resize (2, db::Region ()); {
res [0] = rp.first; return as_2region_vector (r->selected_inside_differential (other));
res [1] = rp.second; }
return res;
static std::vector<db::Region> split_outside (const db::Region *r, const db::Region &other)
{
return as_2region_vector (r->selected_outside_differential (other));
}
static std::vector<db::Region> split_overlapping (const db::Region *r, const db::Region &other, size_t min_count, size_t max_count)
{
return as_2region_vector (r->selected_overlapping_differential (other, min_count, max_count));
}
static std::vector<db::Region> split_covering (const db::Region *r, const db::Region &other, size_t min_count, size_t max_count)
{
return as_2region_vector (r->selected_enclosing_differential (other, min_count, max_count));
}
static std::vector<db::Region> split_interacting_with_region (const db::Region *r, const db::Region &other, size_t min_count, size_t max_count)
{
return as_2region_vector (r->selected_interacting_differential (other, min_count, max_count));
}
static std::vector<db::Region> split_interacting_with_edges (const db::Region *r, const db::Edges &other, size_t min_count, size_t max_count)
{
return as_2region_vector (r->selected_interacting_differential (other, min_count, max_count));
}
static std::vector<db::Region> split_interacting_with_texts (const db::Region *r, const db::Texts &other, size_t min_count, size_t max_count)
{
return as_2region_vector (r->selected_interacting_differential (other, min_count, max_count));
} }
template <class Container> template <class Container>
@ -681,6 +719,7 @@ int po_any ();
extern Class<db::ShapeCollection> decl_dbShapeCollection; extern Class<db::ShapeCollection> decl_dbShapeCollection;
Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region", Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
constructor ("new", &new_v, constructor ("new", &new_v,
"@brief Default constructor\n" "@brief Default constructor\n"
@ -903,7 +942,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"polygons which have the given perimeter are returned. If \"inverse\" is true, " "polygons which have the given perimeter are returned. If \"inverse\" is true, "
"polygons not having the given perimeter are returned.\n" "polygons not having the given perimeter are returned.\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
) + ) +
method_ext ("with_perimeter", with_perimeter2, gsi::arg ("min_perimeter"), gsi::arg ("max_perimeter"), gsi::arg ("inverse"), method_ext ("with_perimeter", with_perimeter2, gsi::arg ("min_perimeter"), gsi::arg ("max_perimeter"), gsi::arg ("inverse"),
"@brief Filter the polygons by perimeter\n" "@brief Filter the polygons by perimeter\n"
@ -915,7 +954,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n" "\n"
"If you don't want to specify a lower or upper limit, pass nil to that parameter.\n" "If you don't want to specify a lower or upper limit, pass nil to that parameter.\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
) + ) +
method_ext ("with_area", with_area1, gsi::arg ("area"), gsi::arg ("inverse"), method_ext ("with_area", with_area1, gsi::arg ("area"), gsi::arg ("inverse"),
"@brief Filter the polygons by area\n" "@brief Filter the polygons by area\n"
@ -923,7 +962,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"polygons which have the given area are returned. If \"inverse\" is true, " "polygons which have the given area are returned. If \"inverse\" is true, "
"polygons not having the given area are returned.\n" "polygons not having the given area are returned.\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
) + ) +
method_ext ("with_area", with_area2, gsi::arg ("min_area"), gsi::arg ("max_area"), gsi::arg ("inverse"), method_ext ("with_area", with_area2, gsi::arg ("min_area"), gsi::arg ("max_area"), gsi::arg ("inverse"),
"@brief Filter the polygons by area\n" "@brief Filter the polygons by area\n"
@ -935,7 +974,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n" "\n"
"If you don't want to specify a lower or upper limit, pass nil to that parameter.\n" "If you don't want to specify a lower or upper limit, pass nil to that parameter.\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
) + ) +
method_ext ("with_holes", with_holes1, gsi::arg ("nholes"), gsi::arg ("inverse"), method_ext ("with_holes", with_holes1, gsi::arg ("nholes"), gsi::arg ("inverse"),
"@brief Filters the polygons by their number of holes\n" "@brief Filters the polygons by their number of holes\n"
@ -943,7 +982,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"polygons which have the given number of holes are returned. If \"inverse\" is true, " "polygons which have the given number of holes are returned. If \"inverse\" is true, "
"polygons not having the given of holes are returned.\n" "polygons not having the given of holes are returned.\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
"\n" "\n"
"This method has been introduced in version 0.27.\n" "This method has been introduced in version 0.27.\n"
) + ) +
@ -957,7 +996,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n" "\n"
"If you don't want to specify a lower or upper limit, pass nil to that parameter.\n" "If you don't want to specify a lower or upper limit, pass nil to that parameter.\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
"\n" "\n"
"This method has been introduced in version 0.27.\n" "This method has been introduced in version 0.27.\n"
) + ) +
@ -967,7 +1006,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"polygons whose bounding box has the given width are returned. If \"inverse\" is true, " "polygons whose bounding box has the given width are returned. If \"inverse\" is true, "
"polygons whose bounding box does not have the given width are returned.\n" "polygons whose bounding box does not have the given width are returned.\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
) + ) +
method_ext ("with_bbox_width", with_bbox_width2, gsi::arg ("min_width"), gsi::arg ("max_width"), gsi::arg ("inverse"), method_ext ("with_bbox_width", with_bbox_width2, gsi::arg ("min_width"), gsi::arg ("max_width"), gsi::arg ("inverse"),
"@brief Filter the polygons by bounding box width\n" "@brief Filter the polygons by bounding box width\n"
@ -977,7 +1016,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n" "\n"
"If you don't want to specify a lower or upper limit, pass nil to that parameter.\n" "If you don't want to specify a lower or upper limit, pass nil to that parameter.\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
) + ) +
method_ext ("with_bbox_height", with_bbox_height1, gsi::arg ("height"), gsi::arg ("inverse"), method_ext ("with_bbox_height", with_bbox_height1, gsi::arg ("height"), gsi::arg ("inverse"),
"@brief Filter the polygons by bounding box height\n" "@brief Filter the polygons by bounding box height\n"
@ -985,7 +1024,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"polygons whose bounding box has the given height are returned. If \"inverse\" is true, " "polygons whose bounding box has the given height are returned. If \"inverse\" is true, "
"polygons whose bounding box does not have the given height are returned.\n" "polygons whose bounding box does not have the given height are returned.\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
) + ) +
method_ext ("with_bbox_height", with_bbox_height2, gsi::arg ("min_height"), gsi::arg ("max_height"), gsi::arg ("inverse"), method_ext ("with_bbox_height", with_bbox_height2, gsi::arg ("min_height"), gsi::arg ("max_height"), gsi::arg ("inverse"),
"@brief Filter the polygons by bounding box height\n" "@brief Filter the polygons by bounding box height\n"
@ -995,7 +1034,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n" "\n"
"If you don't want to specify a lower or upper limit, pass nil to that parameter.\n" "If you don't want to specify a lower or upper limit, pass nil to that parameter.\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
) + ) +
method_ext ("with_bbox_min", with_bbox_min1, gsi::arg ("dim"), gsi::arg ("inverse"), method_ext ("with_bbox_min", with_bbox_min1, gsi::arg ("dim"), gsi::arg ("inverse"),
"@brief Filter the polygons by bounding box width or height, whichever is smaller\n" "@brief Filter the polygons by bounding box width or height, whichever is smaller\n"
@ -1004,7 +1043,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"are returned. " "are returned. "
"If \"inverse\" is true, all polygons not matching this criterion are returned." "If \"inverse\" is true, all polygons not matching this criterion are returned."
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
) + ) +
method_ext ("with_bbox_min", with_bbox_min2, gsi::arg ("min_dim"), gsi::arg ("max_dim"), gsi::arg ("inverse"), method_ext ("with_bbox_min", with_bbox_min2, gsi::arg ("min_dim"), gsi::arg ("max_dim"), gsi::arg ("inverse"),
"@brief Filter the polygons by bounding box width or height, whichever is smaller\n" "@brief Filter the polygons by bounding box width or height, whichever is smaller\n"
@ -1015,7 +1054,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n" "\n"
"If you don't want to specify a lower or upper limit, pass nil to that parameter.\n" "If you don't want to specify a lower or upper limit, pass nil to that parameter.\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
) + ) +
method_ext ("with_bbox_max", with_bbox_max1, gsi::arg ("dim"), gsi::arg ("inverse"), method_ext ("with_bbox_max", with_bbox_max1, gsi::arg ("dim"), gsi::arg ("inverse"),
"@brief Filter the polygons by bounding box width or height, whichever is larger\n" "@brief Filter the polygons by bounding box width or height, whichever is larger\n"
@ -1024,7 +1063,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"are returned. " "are returned. "
"If \"inverse\" is true, all polygons not matching this criterion are returned." "If \"inverse\" is true, all polygons not matching this criterion are returned."
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
) + ) +
method_ext ("with_bbox_max", with_bbox_max2, gsi::arg ("min_dim"), gsi::arg ("max_dim"), gsi::arg ("inverse"), method_ext ("with_bbox_max", with_bbox_max2, gsi::arg ("min_dim"), gsi::arg ("max_dim"), gsi::arg ("inverse"),
"@brief Filter the polygons by bounding box width or height, whichever is larger\n" "@brief Filter the polygons by bounding box width or height, whichever is larger\n"
@ -1035,7 +1074,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n" "\n"
"If you don't want to specify a lower or upper limit, pass nil to that parameter.\n" "If you don't want to specify a lower or upper limit, pass nil to that parameter.\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
) + ) +
method_ext ("with_bbox_aspect_ratio", with_bbox_aspect_ratio1, gsi::arg ("ratio"), gsi::arg ("inverse"), method_ext ("with_bbox_aspect_ratio", with_bbox_aspect_ratio1, gsi::arg ("ratio"), gsi::arg ("inverse"),
"@brief Filters the polygons by the aspect ratio of their bounding boxes\n" "@brief Filters the polygons by the aspect ratio of their bounding boxes\n"
@ -1046,7 +1085,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"With 'inverse' set to false, this version filters polygons which have a bounding box aspect ratio equal to the given value. " "With 'inverse' set to false, this version filters polygons which have a bounding box aspect ratio equal to the given value. "
"With 'inverse' set to true, all other polygons will be returned.\n" "With 'inverse' set to true, all other polygons will be returned.\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
"\n" "\n"
"This method has been introduced in version 0.27.\n" "This method has been introduced in version 0.27.\n"
) + ) +
@ -1062,7 +1101,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n" "\n"
"If you don't want to specify a lower or upper limit, pass nil to that parameter.\n" "If you don't want to specify a lower or upper limit, pass nil to that parameter.\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
"\n" "\n"
"This method has been introduced in version 0.27.\n" "This method has been introduced in version 0.27.\n"
) + ) +
@ -1075,7 +1114,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"With 'inverse' set to false, this version filters polygons which have an area ratio equal to the given value. " "With 'inverse' set to false, this version filters polygons which have an area ratio equal to the given value. "
"With 'inverse' set to true, all other polygons will be returned.\n" "With 'inverse' set to true, all other polygons will be returned.\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
"\n" "\n"
"This method has been introduced in version 0.27.\n" "This method has been introduced in version 0.27.\n"
) + ) +
@ -1091,7 +1130,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n" "\n"
"If you don't want to specify a lower or upper limit, pass nil to that parameter.\n" "If you don't want to specify a lower or upper limit, pass nil to that parameter.\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
"\n" "\n"
"This method has been introduced in version 0.27.\n" "This method has been introduced in version 0.27.\n"
) + ) +
@ -1105,7 +1144,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"With 'inverse' set to false, this version filters polygons which have a relative height equal to the given value. " "With 'inverse' set to false, this version filters polygons which have a relative height equal to the given value. "
"With 'inverse' set to true, all other polygons will be returned.\n" "With 'inverse' set to true, all other polygons will be returned.\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
"\n" "\n"
"This method has been introduced in version 0.27.\n" "This method has been introduced in version 0.27.\n"
) + ) +
@ -1122,7 +1161,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n" "\n"
"If you don't want to specify a lower or upper limit, pass nil to that parameter.\n" "If you don't want to specify a lower or upper limit, pass nil to that parameter.\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
"\n" "\n"
"This method has been introduced in version 0.27.\n" "This method has been introduced in version 0.27.\n"
) + ) +
@ -1130,7 +1169,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"@brief Returns a region containing those parts of polygons which are \"strange\"\n" "@brief Returns a region containing those parts of polygons which are \"strange\"\n"
"Strange parts of polygons are self-overlapping parts or non-orientable parts (i.e. in the \"8\" configuration).\n" "Strange parts of polygons are self-overlapping parts or non-orientable parts (i.e. in the \"8\" configuration).\n"
"\n" "\n"
"Merged semantics does not apply for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics does not apply for this method (see \\merged_semantics= for a description of this concept)\n"
) + ) +
method ("snapped", &db::Region::snapped, gsi::arg ("gx"), gsi::arg ("gy"), method ("snapped", &db::Region::snapped, gsi::arg ("gx"), gsi::arg ("gy"),
"@brief Returns the snapped region\n" "@brief Returns the snapped region\n"
@ -1143,7 +1182,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n" "\n"
"If gx or gy is 0, no snapping happens in that direction.\n" "If gx or gy is 0, no snapping happens in that direction.\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
) + ) +
method ("scaled_and_snapped", &db::Region::scaled_and_snapped, gsi::arg ("gx"), gsi::arg ("mx"), gsi::arg ("dx"), gsi::arg ("gy"),gsi::arg ("my"), gsi::arg ("dy"), method ("scaled_and_snapped", &db::Region::scaled_and_snapped, gsi::arg ("gx"), gsi::arg ("mx"), gsi::arg ("dx"), gsi::arg ("gy"),gsi::arg ("my"), gsi::arg ("dy"),
"@brief Returns the scaled and snapped region\n" "@brief Returns the scaled and snapped region\n"
@ -1159,7 +1198,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n" "\n"
"If gx or gy is 0, the result is brought on a grid of 1.\n" "If gx or gy is 0, the result is brought on a grid of 1.\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
"\n" "\n"
"This method has been introduced in version 0.26.1." "This method has been introduced in version 0.26.1."
) + ) +
@ -1171,7 +1210,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n" "\n"
"If gx or gy is 0 or less, the grid is not checked in that direction.\n" "If gx or gy is 0 or less, the grid is not checked in that direction.\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
) + ) +
method_ext ("with_angle", angle_check1, gsi::arg ("angle"), gsi::arg ("inverse"), method_ext ("with_angle", angle_check1, gsi::arg ("angle"), gsi::arg ("inverse"),
"@brief Returns markers on every corner with the given angle (or not with the given angle)\n" "@brief Returns markers on every corner with the given angle (or not with the given angle)\n"
@ -1181,7 +1220,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n" "\n"
"The edge pair objects returned will contain both edges forming the angle.\n" "The edge pair objects returned will contain both edges forming the angle.\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
) + ) +
method_ext ("with_angle", angle_check2, gsi::arg ("amin"), gsi::arg ("amax"), gsi::arg ("inverse"), method_ext ("with_angle", angle_check2, gsi::arg ("amin"), gsi::arg ("amax"), gsi::arg ("inverse"),
"@brief Returns markers on every corner with an angle of more than amin and less than amax (or the opposite)\n" "@brief Returns markers on every corner with an angle of more than amin and less than amax (or the opposite)\n"
@ -1191,7 +1230,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n" "\n"
"The edge pair objects returned will contain both edges forming the angle.\n" "The edge pair objects returned will contain both edges forming the angle.\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
) + ) +
method ("insert", (void (db::Region::*)(const db::Box &)) &db::Region::insert, gsi::arg ("box"), method ("insert", (void (db::Region::*)(const db::Box &)) &db::Region::insert, gsi::arg ("box"),
"@brief Inserts a box\n" "@brief Inserts a box\n"
@ -1266,7 +1305,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"The boxes will not be merged, so it is possible to determine overlaps " "The boxes will not be merged, so it is possible to determine overlaps "
"of these boxes for example.\n" "of these boxes for example.\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
) + ) +
method_ext ("extents", &extents1, gsi::arg ("d"), method_ext ("extents", &extents1, gsi::arg ("d"),
"@brief Returns a region with the enlarged bounding boxes of the polygons\n" "@brief Returns a region with the enlarged bounding boxes of the polygons\n"
@ -1275,7 +1314,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"The boxes will not be merged, so it is possible to determine overlaps " "The boxes will not be merged, so it is possible to determine overlaps "
"of these boxes for example.\n" "of these boxes for example.\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
) + ) +
method_ext ("extents", &extents2, gsi::arg ("dx"), gsi::arg ("dy"), method_ext ("extents", &extents2, gsi::arg ("dx"), gsi::arg ("dy"),
"@brief Returns a region with the enlarged bounding boxes of the polygons\n" "@brief Returns a region with the enlarged bounding boxes of the polygons\n"
@ -1284,7 +1323,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"The boxes will not be merged, so it is possible to determine overlaps " "The boxes will not be merged, so it is possible to determine overlaps "
"of these boxes for example.\n" "of these boxes for example.\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
) + ) +
method_ext ("extent_refs", &extent_refs, method_ext ("extent_refs", &extent_refs,
"@hide\n" "@hide\n"
@ -1412,9 +1451,10 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"See \\round_corners for a description of this method. This version returns a new region instead of " "See \\round_corners for a description of this method. This version returns a new region instead of "
"modifying self (out-of-place)." "modifying self (out-of-place)."
) + ) +
method ("smooth", &db::Region::smooth, gsi::arg ("d"), method ("smooth", &db::Region::smooth, gsi::arg ("d"), gsi::arg ("keep_hv", false),
"@brief Smoothing\n" "@brief Smoothing\n"
"@param d The smoothing tolerance (in database units)\n" "@param d The smoothing tolerance (in database units)\n"
"@param keep_hv If true, horizontal and vertical edges are maintained\n"
"\n" "\n"
"This method will simplify the merged polygons of the region by removing vertexes if the " "This method will simplify the merged polygons of the region by removing vertexes if the "
"resulting polygon stays equivalent with the original polygon. Equivalence is measured " "resulting polygon stays equivalent with the original polygon. Equivalence is measured "
@ -1423,9 +1463,10 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"This method modifies the region. \\smoothed is a method that does the same but returns a new " "This method modifies the region. \\smoothed is a method that does the same but returns a new "
"region without modifying self. Merged semantics applies for this method.\n" "region without modifying self. Merged semantics applies for this method.\n"
) + ) +
method ("smoothed", &db::Region::smoothed, gsi::arg ("d"), method ("smoothed", &db::Region::smoothed, gsi::arg ("d"), gsi::arg ("keep_hv", false),
"@brief Smoothing\n" "@brief Smoothing\n"
"@param d The smoothing tolerance (in database units)\n" "@param d The smoothing tolerance (in database units)\n"
"@param keep_hv If true, horizontal and vertical edges are maintained\n"
"\n" "\n"
"See \\smooth for a description of this method. This version returns a new region instead of " "See \\smooth for a description of this method. This version returns a new region instead of "
"modifying self (out-of-place). It has been introduced in version 0.25." "modifying self (out-of-place). It has been introduced in version 0.25."
@ -1444,7 +1485,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"The mode defines at which bending angle cutoff occurs \n" "The mode defines at which bending angle cutoff occurs \n"
"(0:>0, 1:>45, 2:>90, 3:>135, 4:>approx. 168, other:>approx. 179)\n" "(0:>0, 1:>45, 2:>90, 3:>135, 4:>approx. 168, other:>approx. 179)\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
"\n" "\n"
"The result is a set of polygons which may be overlapping, but are not self-\n" "The result is a set of polygons which may be overlapping, but are not self-\n"
"intersecting. Polygons may overlap afterwards because they grew big enough to overlap their neighbors.\n" "intersecting. Polygons may overlap afterwards because they grew big enough to overlap their neighbors.\n"
@ -1466,7 +1507,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n" "\n"
"This method is equivalent to \"size(d, d, mode)\".\n" "This method is equivalent to \"size(d, d, mode)\".\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
) + ) +
method_ext ("size", size_ext, gsi::arg ("d"), method_ext ("size", size_ext, gsi::arg ("d"),
"@brief Isotropic sizing (biasing)\n" "@brief Isotropic sizing (biasing)\n"
@ -1475,7 +1516,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n" "\n"
"This method is equivalent to \"size(d, d, 2)\".\n" "This method is equivalent to \"size(d, d, 2)\".\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
) + ) +
method ("sized", (db::Region (db::Region::*) (db::Coord, db::Coord, unsigned int) const) &db::Region::sized, gsi::arg ("dx"), gsi::arg ("dy"), gsi::arg ("mode"), method ("sized", (db::Region (db::Region::*) (db::Coord, db::Coord, unsigned int) const) &db::Region::sized, gsi::arg ("dx"), gsi::arg ("dy"), gsi::arg ("mode"),
"@brief Returns the anisotropically sized region\n" "@brief Returns the anisotropically sized region\n"
@ -1484,7 +1525,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n" "\n"
"This method is returns the sized region (see \\size), but does not modify self.\n" "This method is returns the sized region (see \\size), but does not modify self.\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
) + ) +
method ("sized", (db::Region (db::Region::*) (db::Coord, unsigned int) const) &db::Region::sized, gsi::arg ("d"), gsi::arg ("mode"), method ("sized", (db::Region (db::Region::*) (db::Coord, unsigned int) const) &db::Region::sized, gsi::arg ("d"), gsi::arg ("mode"),
"@brief Returns the isotropically sized region\n" "@brief Returns the isotropically sized region\n"
@ -1493,7 +1534,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n" "\n"
"This method is returns the sized region (see \\size), but does not modify self.\n" "This method is returns the sized region (see \\size), but does not modify self.\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
) + ) +
method_ext ("sized", sized_ext, gsi::arg ("d"), method_ext ("sized", sized_ext, gsi::arg ("d"),
"@brief Isotropic sizing (biasing)\n" "@brief Isotropic sizing (biasing)\n"
@ -1502,7 +1543,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n" "\n"
"This method is equivalent to \"sized(d, d, 2)\".\n" "This method is equivalent to \"sized(d, d, 2)\".\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
) + ) +
method_ext ("andnot", &andnot, gsi::arg ("other"), method_ext ("andnot", &andnot, gsi::arg ("other"),
"@brief Returns the boolean AND and NOT between self and the other region\n" "@brief Returns the boolean AND and NOT between self and the other region\n"
@ -1599,7 +1640,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n" "\n"
"@return A new region containing the polygons which are covering polygons from the other region\n" "@return A new region containing the polygons which are covering polygons from the other region\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
"\n" "\n"
"This attribute is sometimes called 'enclosing' instead of 'covering', but this term is reserved for the respective DRC function.\n" "This attribute is sometimes called 'enclosing' instead of 'covering', but this term is reserved for the respective DRC function.\n"
"\n" "\n"
@ -1610,18 +1651,28 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n" "\n"
"@return A new region containing the polygons which are not covering polygons from the other region\n" "@return A new region containing the polygons which are not covering polygons from the other region\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
"\n" "\n"
"This attribute is sometimes called 'enclosing' instead of 'covering', but this term is reserved for the respective DRC function.\n" "This attribute is sometimes called 'enclosing' instead of 'covering', but this term is reserved for the respective DRC function.\n"
"\n" "\n"
"This method has been introduced in version 0.27." "This method has been introduced in version 0.27."
) + ) +
method_ext ("split_covering", &split_covering, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
"@brief Returns the polygons of this region which are completely covering polygons from the other region and the ones which are not at the same time\n"
"\n"
"@return Two new regions: the first containing the result of \\covering, the second the result of \\not_covering\n"
"\n"
"This method is equivalent to calling \\covering and \\not_covering, but is faster when both results are required.\n"
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept).\n"
"\n"
"This method has been introduced in version 0.27."
) +
method ("select_covering", &db::Region::select_enclosing, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"), method ("select_covering", &db::Region::select_enclosing, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
"@brief Selects the polygons of this region which are completely covering polygons from the other region\n" "@brief Selects the polygons of this region which are completely covering polygons from the other region\n"
"\n" "\n"
"@return The region after the polygons have been selected (self)\n" "@return The region after the polygons have been selected (self)\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
"\n" "\n"
"This attribute is sometimes called 'enclosing' instead of 'covering', but this term is reserved for the respective DRC function.\n" "This attribute is sometimes called 'enclosing' instead of 'covering', but this term is reserved for the respective DRC function.\n"
"\n" "\n"
@ -1632,7 +1683,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n" "\n"
"@return The region after the polygons have been selected (self)\n" "@return The region after the polygons have been selected (self)\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
"\n" "\n"
"This attribute is sometimes called 'enclosing' instead of 'covering', but this term is reserved for the respective DRC function.\n" "This attribute is sometimes called 'enclosing' instead of 'covering', but this term is reserved for the respective DRC function.\n"
"\n" "\n"
@ -1643,56 +1694,76 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n" "\n"
"@return A new region containing the polygons which are inside polygons from the other region\n" "@return A new region containing the polygons which are inside polygons from the other region\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
) + ) +
method ("not_inside", &db::Region::selected_not_inside, gsi::arg ("other"), method ("not_inside", &db::Region::selected_not_inside, gsi::arg ("other"),
"@brief Returns the polygons of this region which are not completely inside polygons from the other region\n" "@brief Returns the polygons of this region which are not completely inside polygons from the other region\n"
"\n" "\n"
"@return A new region containing the polygons which are not inside polygons from the other region\n" "@return A new region containing the polygons which are not inside polygons from the other region\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
) + ) +
method_ext ("split_inside", &split_inside, gsi::arg ("other"),
"@brief Returns the polygons of this region which are completely inside polygons from the other region and the ones which are not at the same time\n"
"\n"
"@return Two new regions: the first containing the result of \\inside, the second the result of \\not_inside\n"
"\n"
"This method is equivalent to calling \\inside and \\not_inside, but is faster when both results are required.\n"
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept).\n"
"\n"
"This method has been introduced in version 0.27."
) +
method ("select_inside", &db::Region::select_inside, gsi::arg ("other"), method ("select_inside", &db::Region::select_inside, gsi::arg ("other"),
"@brief Selects the polygons of this region which are completely inside polygons from the other region\n" "@brief Selects the polygons of this region which are completely inside polygons from the other region\n"
"\n" "\n"
"@return The region after the polygons have been selected (self)\n" "@return The region after the polygons have been selected (self)\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
) + ) +
method ("select_not_inside", &db::Region::select_not_inside, gsi::arg ("other"), method ("select_not_inside", &db::Region::select_not_inside, gsi::arg ("other"),
"@brief Selects the polygons of this region which are not completely inside polygons from the other region\n" "@brief Selects the polygons of this region which are not completely inside polygons from the other region\n"
"\n" "\n"
"@return The region after the polygons have been selected (self)\n" "@return The region after the polygons have been selected (self)\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
) + ) +
method ("outside", &db::Region::selected_outside, gsi::arg ("other"), method ("outside", &db::Region::selected_outside, gsi::arg ("other"),
"@brief Returns the polygons of this region which are completely outside polygons from the other region\n" "@brief Returns the polygons of this region which are completely outside polygons from the other region\n"
"\n" "\n"
"@return A new region containing the polygons which are outside polygons from the other region\n" "@return A new region containing the polygons which are outside polygons from the other region\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
) + ) +
method ("not_outside", &db::Region::selected_not_outside, gsi::arg ("other"), method ("not_outside", &db::Region::selected_not_outside, gsi::arg ("other"),
"@brief Returns the polygons of this region which are not completely outside polygons from the other region\n" "@brief Returns the polygons of this region which are not completely outside polygons from the other region\n"
"\n" "\n"
"@return A new region containing the polygons which are not outside polygons from the other region\n" "@return A new region containing the polygons which are not outside polygons from the other region\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
) + ) +
method_ext ("split_outside", &split_outside, gsi::arg ("other"),
"@brief Returns the polygons of this region which are completely outside polygons from the other region and the ones which are not at the same time\n"
"\n"
"@return Two new regions: the first containing the result of \\outside, the second the result of \\not_outside\n"
"\n"
"This method is equivalent to calling \\outside and \\not_outside, but is faster when both results are required.\n"
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept).\n"
"\n"
"This method has been introduced in version 0.27."
) +
method ("select_outside", &db::Region::select_outside, gsi::arg ("other"), method ("select_outside", &db::Region::select_outside, gsi::arg ("other"),
"@brief Selects the polygons of this region which are completely outside polygons from the other region\n" "@brief Selects the polygons of this region which are completely outside polygons from the other region\n"
"\n" "\n"
"@return The region after the polygons have been selected (self)\n" "@return The region after the polygons have been selected (self)\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
) + ) +
method ("select_not_outside", &db::Region::select_not_outside, gsi::arg ("other"), method ("select_not_outside", &db::Region::select_not_outside, gsi::arg ("other"),
"@brief Selects the polygons of this region which are not completely outside polygons from the other region\n" "@brief Selects the polygons of this region which are not completely outside polygons from the other region\n"
"\n" "\n"
"@return The region after the polygons have been selected (self)\n" "@return The region after the polygons have been selected (self)\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
) + ) +
method ("interacting", (db::Region (db::Region::*) (const db::Region &, size_t, size_t) const) &db::Region::selected_interacting, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"), method ("interacting", (db::Region (db::Region::*) (const db::Region &, size_t, size_t) const) &db::Region::selected_interacting, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
"@brief Returns the polygons of this region which overlap or touch polygons from the other region\n" "@brief Returns the polygons of this region which overlap or touch polygons from the other region\n"
@ -1704,7 +1775,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n" "\n"
"@return A new region containing the polygons overlapping or touching polygons from the other region\n" "@return A new region containing the polygons overlapping or touching polygons from the other region\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
"\n" "\n"
"The min_count and max_count arguments have been added in version 0.27.\n" "The min_count and max_count arguments have been added in version 0.27.\n"
) + ) +
@ -1718,10 +1789,20 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n" "\n"
"@return A new region containing the polygons not overlapping or touching polygons from the other region\n" "@return A new region containing the polygons not overlapping or touching polygons from the other region\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
"\n" "\n"
"The min_count and max_count arguments have been added in version 0.27.\n" "The min_count and max_count arguments have been added in version 0.27.\n"
) + ) +
method_ext ("split_interacting", &split_interacting_with_region, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
"@brief Returns the polygons of this region which are interacting with polygons from the other region and the ones which are not at the same time\n"
"\n"
"@return Two new regions: the first containing the result of \\interacting, the second the result of \\not_interacting\n"
"\n"
"This method is equivalent to calling \\interacting and \\not_interacting, but is faster when both results are required.\n"
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept).\n"
"\n"
"This method has been introduced in version 0.27."
) +
method ("select_interacting", (db::Region &(db::Region::*) (const db::Region &, size_t, size_t)) &db::Region::select_interacting, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"), method ("select_interacting", (db::Region &(db::Region::*) (const db::Region &, size_t, size_t)) &db::Region::select_interacting, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
"@brief Selects the polygons from this region which overlap or touch polygons from the other region\n" "@brief Selects the polygons from this region which overlap or touch polygons from the other region\n"
"\n" "\n"
@ -1732,7 +1813,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n" "\n"
"@return The region after the polygons have been selected (self)\n" "@return The region after the polygons have been selected (self)\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
"\n" "\n"
"The min_count and max_count arguments have been added in version 0.27.\n" "The min_count and max_count arguments have been added in version 0.27.\n"
) + ) +
@ -1746,7 +1827,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n" "\n"
"@return The region after the polygons have been selected (self)\n" "@return The region after the polygons have been selected (self)\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
"\n" "\n"
"The min_count and max_count arguments have been added in version 0.27.\n" "The min_count and max_count arguments have been added in version 0.27.\n"
) + ) +
@ -1760,7 +1841,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n" "\n"
"@return A new region containing the polygons overlapping or touching edges from the edge collection\n" "@return A new region containing the polygons overlapping or touching edges from the edge collection\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
"\n" "\n"
"This method has been introduced in version 0.25.\n" "This method has been introduced in version 0.25.\n"
"The min_count and max_count arguments have been added in version 0.27.\n" "The min_count and max_count arguments have been added in version 0.27.\n"
@ -1775,11 +1856,21 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n" "\n"
"@return A new region containing the polygons not overlapping or touching edges from the edge collection\n" "@return A new region containing the polygons not overlapping or touching edges from the edge collection\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
"\n" "\n"
"This method has been introduced in version 0.25\n" "This method has been introduced in version 0.25\n"
"The min_count and max_count arguments have been added in version 0.27.\n" "The min_count and max_count arguments have been added in version 0.27.\n"
) + ) +
method_ext ("split_interacting", &split_interacting_with_edges, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
"@brief Returns the polygons of this region which are interacting with edges from the other edge collection and the ones which are not at the same time\n"
"\n"
"@return Two new regions: the first containing the result of \\interacting, the second the result of \\not_interacting\n"
"\n"
"This method is equivalent to calling \\interacting and \\not_interacting, but is faster when both results are required.\n"
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept).\n"
"\n"
"This method has been introduced in version 0.27."
) +
method ("select_interacting", (db::Region &(db::Region::*) (const db::Edges &, size_t, size_t)) &db::Region::select_interacting, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"), method ("select_interacting", (db::Region &(db::Region::*) (const db::Edges &, size_t, size_t)) &db::Region::select_interacting, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
"@brief Selects the polygons from this region which overlap or touch edges from the edge collection\n" "@brief Selects the polygons from this region which overlap or touch edges from the edge collection\n"
"\n" "\n"
@ -1790,7 +1881,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n" "\n"
"@return The region after the polygons have been selected (self)\n" "@return The region after the polygons have been selected (self)\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
"\n" "\n"
"This method has been introduced in version 0.25\n" "This method has been introduced in version 0.25\n"
"The min_count and max_count arguments have been added in version 0.27.\n" "The min_count and max_count arguments have been added in version 0.27.\n"
@ -1805,7 +1896,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n" "\n"
"@return The region after the polygons have been selected (self)\n" "@return The region after the polygons have been selected (self)\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
"\n" "\n"
"This method has been introduced in version 0.25\n" "This method has been introduced in version 0.25\n"
"The min_count and max_count arguments have been added in version 0.27.\n" "The min_count and max_count arguments have been added in version 0.27.\n"
@ -1820,7 +1911,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n" "\n"
"@return A new region containing the polygons overlapping or touching texts\n" "@return A new region containing the polygons overlapping or touching texts\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
"\n" "\n"
"This method has been introduced in version 0.27\n" "This method has been introduced in version 0.27\n"
) + ) +
@ -1834,10 +1925,20 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n" "\n"
"@return A new region containing the polygons not overlapping or touching texts\n" "@return A new region containing the polygons not overlapping or touching texts\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
"\n" "\n"
"This method has been introduced in version 0.27\n" "This method has been introduced in version 0.27\n"
) + ) +
method_ext ("split_interacting", &split_interacting_with_texts, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
"@brief Returns the polygons of this region which are interacting with texts from the other text collection and the ones which are not at the same time\n"
"\n"
"@return Two new regions: the first containing the result of \\interacting, the second the result of \\not_interacting\n"
"\n"
"This method is equivalent to calling \\interacting and \\not_interacting, but is faster when both results are required.\n"
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept).\n"
"\n"
"This method has been introduced in version 0.27."
) +
method ("select_interacting", (db::Region &(db::Region::*) (const db::Texts &, size_t, size_t)) &db::Region::select_interacting, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"), method ("select_interacting", (db::Region &(db::Region::*) (const db::Texts &, size_t, size_t)) &db::Region::select_interacting, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
"@brief Selects the polygons of this region which overlap or touch texts\n" "@brief Selects the polygons of this region which overlap or touch texts\n"
"\n" "\n"
@ -1848,7 +1949,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"selected by this method if the number of texts interacting with the polygon is between min_count and max_count " "selected by this method if the number of texts interacting with the polygon is between min_count and max_count "
"(including max_count).\n" "(including max_count).\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
"\n" "\n"
"This method has been introduced in version 0.27\n" "This method has been introduced in version 0.27\n"
) + ) +
@ -1862,7 +1963,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n" "\n"
"@return The region after the polygons have been selected (self)\n" "@return The region after the polygons have been selected (self)\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
"\n" "\n"
"This method has been introduced in version 0.27\n" "This method has been introduced in version 0.27\n"
) + ) +
@ -1871,7 +1972,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n" "\n"
"@return A new region containing the polygons overlapping polygons from the other region\n" "@return A new region containing the polygons overlapping polygons from the other region\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
"\n" "\n"
"The count options have been introduced in version 0.27." "The count options have been introduced in version 0.27."
) + ) +
@ -1880,16 +1981,26 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n" "\n"
"@return A new region containing the polygons not overlapping polygons from the other region\n" "@return A new region containing the polygons not overlapping polygons from the other region\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
"\n" "\n"
"The count options have been introduced in version 0.27." "The count options have been introduced in version 0.27."
) + ) +
method_ext ("split_overlapping", &split_overlapping, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
"@brief Returns the polygons of this region which are overlapping with polygons from the other region and the ones which are not at the same time\n"
"\n"
"@return Two new regions: the first containing the result of \\overlapping, the second the result of \\not_overlapping\n"
"\n"
"This method is equivalent to calling \\overlapping and \\not_overlapping, but is faster when both results are required.\n"
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept).\n"
"\n"
"This method has been introduced in version 0.27."
) +
method ("select_overlapping", &db::Region::select_overlapping, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"), method ("select_overlapping", &db::Region::select_overlapping, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
"@brief Selects the polygons from this region which overlap polygons from the other region\n" "@brief Selects the polygons from this region which overlap polygons from the other region\n"
"\n" "\n"
"@return The region after the polygons have been selected (self)\n" "@return The region after the polygons have been selected (self)\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
"\n" "\n"
"The count options have been introduced in version 0.27." "The count options have been introduced in version 0.27."
) + ) +
@ -1898,7 +2009,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n" "\n"
"@return The region after the polygons have been selected (self)\n" "@return The region after the polygons have been selected (self)\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
"\n" "\n"
"The count options have been introduced in version 0.27." "The count options have been introduced in version 0.27."
) + ) +
@ -1911,7 +2022,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n" "\n"
"@return The region after the polygons have been selected (from other)\n" "@return The region after the polygons have been selected (from other)\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
"\n" "\n"
"This method has been introduced in version 0.26.1\n" "This method has been introduced in version 0.26.1\n"
) + ) +
@ -1921,7 +2032,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n" "\n"
"@return The region after the polygons have been selected (from other)\n" "@return The region after the polygons have been selected (from other)\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
"\n" "\n"
"This method has been introduced in version 0.26.1\n" "This method has been introduced in version 0.26.1\n"
) + ) +
@ -1931,7 +2042,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n" "\n"
"@return The region after the polygons have been selected (from other)\n" "@return The region after the polygons have been selected (from other)\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
"\n" "\n"
"This method has been introduced in version 0.26.1\n" "This method has been introduced in version 0.26.1\n"
) + ) +
@ -1941,7 +2052,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n" "\n"
"@return The edge collection after the edges have been selected (from other)\n" "@return The edge collection after the edges have been selected (from other)\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
"\n" "\n"
"This method has been introduced in version 0.26.1\n" "This method has been introduced in version 0.26.1\n"
) + ) +
@ -1951,7 +2062,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n" "\n"
"@return The text collection after the texts have been selected (from other)\n" "@return The text collection after the texts have been selected (from other)\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
"\n" "\n"
"This method has been introduced in version 0.27\n" "This method has been introduced in version 0.27\n"
) + ) +
@ -1972,7 +2083,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"The edge collection returned can be manipulated in various ways. See \\Edges for a description of the " "The edge collection returned can be manipulated in various ways. See \\Edges for a description of the "
"possibilities of the edge collection.\n" "possibilities of the edge collection.\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
) + ) +
factory_ext ("decompose_convex", &decompose_convex<db::Shapes>, gsi::arg ("preferred_orientation", po_any (), "\\Polygon#PO_any"), factory_ext ("decompose_convex", &decompose_convex<db::Shapes>, gsi::arg ("preferred_orientation", po_any (), "\\Polygon#PO_any"),
"@brief Decomposes the region into convex pieces.\n" "@brief Decomposes the region into convex pieces.\n"
@ -2016,7 +2127,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"@brief Returns the holes of the region\n" "@brief Returns the holes of the region\n"
"This method returns all holes as filled polygons.\n" "This method returns all holes as filled polygons.\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
"If merge semantics is not enabled, the holes may not be detected if the polygons " "If merge semantics is not enabled, the holes may not be detected if the polygons "
"are taken from a hole-less representation (i.e. GDS2 file). Use explicit merge (\\merge method) " "are taken from a hole-less representation (i.e. GDS2 file). Use explicit merge (\\merge method) "
"in order to merge the polygons and detect holes.\n" "in order to merge the polygons and detect holes.\n"
@ -2025,7 +2136,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"@brief Returns the hulls of the region\n" "@brief Returns the hulls of the region\n"
"This method returns all hulls as polygons. The holes will be removed (filles). " "This method returns all hulls as polygons. The holes will be removed (filles). "
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
"If merge semantics is not enabled, the hull may also enclose holes if the polygons " "If merge semantics is not enabled, the hull may also enclose holes if the polygons "
"are taken from a hole-less representation (i.e. GDS2 file). Use explicit merge (\\merge method) " "are taken from a hole-less representation (i.e. GDS2 file). Use explicit merge (\\merge method) "
"in order to merge the polygons and detect holes.\n" "in order to merge the polygons and detect holes.\n"
@ -2043,36 +2154,36 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
method_ext ("rectangles", &rectangles, method_ext ("rectangles", &rectangles,
"@brief Returns all polygons which are rectangles\n" "@brief Returns all polygons which are rectangles\n"
"This method returns all polygons in self which are rectangles." "This method returns all polygons in self which are rectangles."
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
) + ) +
method_ext ("non_rectangles", &non_rectangles, method_ext ("non_rectangles", &non_rectangles,
"@brief Returns all polygons which are not rectangles\n" "@brief Returns all polygons which are not rectangles\n"
"This method returns all polygons in self which are not rectangles." "This method returns all polygons in self which are not rectangles."
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
) + ) +
method_ext ("squares", &squares, method_ext ("squares", &squares,
"@brief Returns all polygons which are squares\n" "@brief Returns all polygons which are squares\n"
"This method returns all polygons in self which are squares." "This method returns all polygons in self which are squares."
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
"\n" "\n"
"This method has been introduced in version 0.27.\n" "This method has been introduced in version 0.27.\n"
) + ) +
method_ext ("non_squares", &non_squares, method_ext ("non_squares", &non_squares,
"@brief Returns all polygons which are not squares\n" "@brief Returns all polygons which are not squares\n"
"This method returns all polygons in self which are not squares." "This method returns all polygons in self which are not squares."
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
"\n" "\n"
"This method has been introduced in version 0.27.\n" "This method has been introduced in version 0.27.\n"
) + ) +
method_ext ("rectilinear", &rectilinear, method_ext ("rectilinear", &rectilinear,
"@brief Returns all polygons which are rectilinear\n" "@brief Returns all polygons which are rectilinear\n"
"This method returns all polygons in self which are rectilinear." "This method returns all polygons in self which are rectilinear."
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
) + ) +
method_ext ("non_rectilinear", &non_rectilinear, method_ext ("non_rectilinear", &non_rectilinear,
"@brief Returns all polygons which are not rectilinear\n" "@brief Returns all polygons which are not rectilinear\n"
"This method returns all polygons in self which are not rectilinear." "This method returns all polygons in self which are not rectilinear."
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
) + ) +
method_ext ("break", &break_polygons, gsi::arg ("max_vertex_count"), gsi::arg ("max_area_ratio", 0.0), method_ext ("break", &break_polygons, gsi::arg ("max_vertex_count"), gsi::arg ("max_area_ratio", 0.0),
"@brief Breaks the polygons of the region into smaller ones\n" "@brief Breaks the polygons of the region into smaller ones\n"
@ -2101,7 +2212,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"with a pencil that has the shape of the given region.\n" "with a pencil that has the shape of the given region.\n"
"\n" "\n"
"The resulting polygons are not merged. In order to remove overlaps, use the \\merge or \\merged method." "The resulting polygons are not merged. In order to remove overlaps, use the \\merge or \\merged method."
"Merged semantics applies for the input of this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for the input of this method (see \\merged_semantics= for a description of this concept)\n"
) + ) +
method_ext ("minkowsky_sum", &minkowsky_sum_pp, gsi::arg ("p"), method_ext ("minkowsky_sum", &minkowsky_sum_pp, gsi::arg ("p"),
"@brief Compute the Minkowsky sum of the region and a polygon\n" "@brief Compute the Minkowsky sum of the region and a polygon\n"
@ -2114,7 +2225,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"the region with a pen that has the shape of the second polygon.\n" "the region with a pen that has the shape of the second polygon.\n"
"\n" "\n"
"The resulting polygons are not merged. In order to remove overlaps, use the \\merge or \\merged method." "The resulting polygons are not merged. In order to remove overlaps, use the \\merge or \\merged method."
"Merged semantics applies for the input of this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for the input of this method (see \\merged_semantics= for a description of this concept)\n"
) + ) +
method_ext ("minkowsky_sum", &minkowsky_sum_pb, gsi::arg ("b"), method_ext ("minkowsky_sum", &minkowsky_sum_pb, gsi::arg ("b"),
"@brief Compute the Minkowsky sum of the region and a box\n" "@brief Compute the Minkowsky sum of the region and a box\n"
@ -2127,7 +2238,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"as the second polygon.\n" "as the second polygon.\n"
"\n" "\n"
"The resulting polygons are not merged. In order to remove overlaps, use the \\merge or \\merged method." "The resulting polygons are not merged. In order to remove overlaps, use the \\merge or \\merged method."
"Merged semantics applies for the input of this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for the input of this method (see \\merged_semantics= for a description of this concept)\n"
) + ) +
method_ext ("minkowsky_sum", &minkowsky_sum_pc, gsi::arg ("b"), method_ext ("minkowsky_sum", &minkowsky_sum_pc, gsi::arg ("b"),
"@brief Compute the Minkowsky sum of the region and a contour of points (a trace)\n" "@brief Compute the Minkowsky sum of the region and a contour of points (a trace)\n"
@ -2141,7 +2252,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"with a pencil that has the shape of the given region.\n" "with a pencil that has the shape of the given region.\n"
"\n" "\n"
"The resulting polygons are not merged. In order to remove overlaps, use the \\merge or \\merged method." "The resulting polygons are not merged. In order to remove overlaps, use the \\merge or \\merged method."
"Merged semantics applies for the input of this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for the input of this method (see \\merged_semantics= for a description of this concept)\n"
) + ) +
method_ext ("move", &move_p, gsi::arg ("v"), method_ext ("move", &move_p, gsi::arg ("v"),
"@brief Moves the region\n" "@brief Moves the region\n"
@ -2266,7 +2377,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"violations between the original and the shielding features. If not necessary, shielding can be disabled by setting this flag to " "violations between the original and the shielding features. If not necessary, shielding can be disabled by setting this flag to "
"false. In general, this will improve performance somewhat.\n" "false. In general, this will improve performance somewhat.\n"
"\n" "\n"
"Merged semantics applies for the input of this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for the input of this method (see \\merged_semantics= for a description of this concept)\n"
"\n" "\n"
"The 'shielded' and 'negative' options have been introduced in version 0.27." "The 'shielded' and 'negative' options have been introduced in version 0.27."
) + ) +
@ -2308,7 +2419,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\"opposite_filter\" specifies whether to require or reject errors happening on opposite sides of a figure. " "\"opposite_filter\" specifies whether to require or reject errors happening on opposite sides of a figure. "
"\"rect_filter\" allows suppressing specific error configurations on rectangular input figures.\n" "\"rect_filter\" allows suppressing specific error configurations on rectangular input figures.\n"
"\n" "\n"
"Merged semantics applies for the input of this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for the input of this method (see \\merged_semantics= for a description of this concept)\n"
"\n" "\n"
"The 'shielded', 'negative', 'not_opposite' and 'rect_sides' options have been introduced in version 0.27." "The 'shielded', 'negative', 'not_opposite' and 'rect_sides' options have been introduced in version 0.27."
) + ) +
@ -2349,7 +2460,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"violations between the original and the shielding features. If not necessary, shielding can be disabled by setting this flag to " "violations between the original and the shielding features. If not necessary, shielding can be disabled by setting this flag to "
"false. In general, this will improve performance somewhat.\n" "false. In general, this will improve performance somewhat.\n"
"\n" "\n"
"Merged semantics applies for the input of this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for the input of this method (see \\merged_semantics= for a description of this concept)\n"
"\n" "\n"
"The 'shielded' and 'negative' options have been introduced in version 0.27." "The 'shielded' and 'negative' options have been introduced in version 0.27."
) + ) +
@ -2391,7 +2502,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\"opposite_filter\" specifies whether to require or reject errors happening on opposite sides of a figure. " "\"opposite_filter\" specifies whether to require or reject errors happening on opposite sides of a figure. "
"\"rect_filter\" allows suppressing specific error configurations on rectangular input figures.\n" "\"rect_filter\" allows suppressing specific error configurations on rectangular input figures.\n"
"\n" "\n"
"Merged semantics applies for the input of this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for the input of this method (see \\merged_semantics= for a description of this concept)\n"
"\n" "\n"
"The 'shielded', 'negative', 'not_opposite' and 'rect_sides' options have been introduced in version 0.27." "The 'shielded', 'negative', 'not_opposite' and 'rect_sides' options have been introduced in version 0.27."
) + ) +
@ -2434,7 +2545,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\"opposite_filter\" specifies whether to require or reject errors happening on opposite sides of a figure. " "\"opposite_filter\" specifies whether to require or reject errors happening on opposite sides of a figure. "
"\"rect_filter\" allows suppressing specific error configurations on rectangular input figures.\n" "\"rect_filter\" allows suppressing specific error configurations on rectangular input figures.\n"
"\n" "\n"
"Merged semantics applies for the input of this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for the input of this method (see \\merged_semantics= for a description of this concept)\n"
"\n" "\n"
"The 'shielded', 'negative', 'not_opposite' and 'rect_sides' options have been introduced in version 0.27." "The 'shielded', 'negative', 'not_opposite' and 'rect_sides' options have been introduced in version 0.27."
) + ) +
@ -2477,7 +2588,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\"opposite_filter\" specifies whether to require or reject errors happening on opposite sides of a figure. " "\"opposite_filter\" specifies whether to require or reject errors happening on opposite sides of a figure. "
"\"rect_filter\" allows suppressing specific error configurations on rectangular input figures.\n" "\"rect_filter\" allows suppressing specific error configurations on rectangular input figures.\n"
"\n" "\n"
"Merged semantics applies for the input of this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for the input of this method (see \\merged_semantics= for a description of this concept)\n"
"\n" "\n"
"The 'shielded', 'negative', 'not_opposite' and 'rect_sides' options have been introduced in version 0.27." "The 'shielded', 'negative', 'not_opposite' and 'rect_sides' options have been introduced in version 0.27."
) + ) +
@ -2520,7 +2631,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\"opposite_filter\" specifies whether to require or reject errors happening on opposite sides of a figure. " "\"opposite_filter\" specifies whether to require or reject errors happening on opposite sides of a figure. "
"\"rect_filter\" allows suppressing specific error configurations on rectangular input figures.\n" "\"rect_filter\" allows suppressing specific error configurations on rectangular input figures.\n"
"\n" "\n"
"Merged semantics applies for the input of this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for the input of this method (see \\merged_semantics= for a description of this concept)\n"
"\n" "\n"
"The 'shielded', 'negative', 'not_opposite' and 'rect_sides' options have been introduced in version 0.27." "The 'shielded', 'negative', 'not_opposite' and 'rect_sides' options have been introduced in version 0.27."
) + ) +
@ -2563,27 +2674,27 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\"opposite_filter\" specifies whether to require or reject errors happening on opposite sides of a figure. " "\"opposite_filter\" specifies whether to require or reject errors happening on opposite sides of a figure. "
"\"rect_filter\" allows suppressing specific error configurations on rectangular input figures.\n" "\"rect_filter\" allows suppressing specific error configurations on rectangular input figures.\n"
"\n" "\n"
"Merged semantics applies for the input of this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for the input of this method (see \\merged_semantics= for a description of this concept)\n"
"\n" "\n"
"The 'shielded', 'negative', 'not_opposite' and 'rect_sides' options have been introduced in version 0.27." "The 'shielded', 'negative', 'not_opposite' and 'rect_sides' options have been introduced in version 0.27."
) + ) +
method_ext ("area", &area1, method_ext ("area", &area1,
"@brief The area of the region\n" "@brief The area of the region\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
"If merged semantics is not enabled, overlapping areas are counted twice.\n" "If merged semantics is not enabled, overlapping areas are counted twice.\n"
) + ) +
method_ext ("area", &area2, gsi::arg ("rect"), method_ext ("area", &area2, gsi::arg ("rect"),
"@brief The area of the region (restricted to a rectangle)\n" "@brief The area of the region (restricted to a rectangle)\n"
"This version will compute the area of the shapes, restricting the computation to the given rectangle.\n" "This version will compute the area of the shapes, restricting the computation to the given rectangle.\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
"If merged semantics is not enabled, overlapping areas are counted twice.\n" "If merged semantics is not enabled, overlapping areas are counted twice.\n"
) + ) +
method_ext ("perimeter", &perimeter1, method_ext ("perimeter", &perimeter1,
"@brief The total perimeter of the polygons\n" "@brief The total perimeter of the polygons\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
"If merged semantics is not enabled, internal edges are counted as well.\n" "If merged semantics is not enabled, internal edges are counted as well.\n"
) + ) +
method_ext ("perimeter", &perimeter2, gsi::arg ("rect"), method_ext ("perimeter", &perimeter2, gsi::arg ("rect"),
@ -2592,7 +2703,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"Edges along the border are handled in a special way: they are counted when they are oriented with their inside " "Edges along the border are handled in a special way: they are counted when they are oriented with their inside "
"side toward the rectangle (in other words: outside edges must coincide with the rectangle's border in order to be counted).\n" "side toward the rectangle (in other words: outside edges must coincide with the rectangle's border in order to be counted).\n"
"\n" "\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
"If merged semantics is not enabled, internal edges are counted as well.\n" "If merged semantics is not enabled, internal edges are counted as well.\n"
) + ) +
method ("bbox", &db::Region::bbox, method ("bbox", &db::Region::bbox,

View File

@ -733,7 +733,8 @@ TEST(11_RoundAndSmoothed)
r1_sized -= r1; r1_sized -= r1;
db::Region rounded = r1_sized.rounded_corners (3000, 5000, 100); db::Region rounded = r1_sized.rounded_corners (3000, 5000, 100);
db::Region smoothed = rounded.smoothed (100); db::Region smoothed = rounded.smoothed (100, false);
db::Region smoothed_keep_hv = rounded.smoothed (100, true);
db::Layout target; db::Layout target;
unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index)); unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index));
@ -741,6 +742,7 @@ TEST(11_RoundAndSmoothed)
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (10, 0)), r1_sized); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (10, 0)), r1_sized);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), rounded); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), rounded);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (12, 0)), smoothed); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (12, 0)), smoothed);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (13, 0)), smoothed_keep_hv);
CHECKPOINT(); CHECKPOINT();
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au11.gds"); db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au11.gds");

View File

@ -1188,8 +1188,8 @@ TEST(100)
db::Polygon p; db::Polygon p;
p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0])); p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0]));
EXPECT_EQ (smooth (p, 5).to_string (), "(0,-100;0,0;50,10;100,-10;150,0;150,-100)"); EXPECT_EQ (smooth (p, 5, true).to_string (), "(0,-100;0,0;50,10;100,-10;150,0;150,-100)");
EXPECT_EQ (smooth (p, 20).to_string (), "(0,-100;0,0;150,0;150,-100)"); EXPECT_EQ (smooth (p, 20, true).to_string (), "(0,-100;0,0;150,0;150,-100)");
} }
// smoothing // smoothing
@ -1207,8 +1207,8 @@ TEST(101)
db::Polygon p; db::Polygon p;
p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0])); p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0]));
EXPECT_EQ (smooth (p, 5).to_string (), "(100,-10;50,10;0,0;0,100;150,100;150,0)"); EXPECT_EQ (smooth (p, 5, true).to_string (), "(100,-10;50,10;0,0;0,100;150,100;150,0)");
EXPECT_EQ (smooth (p, 20).to_string (), "(0,0;0,100;150,100;150,0)"); EXPECT_EQ (smooth (p, 20, true).to_string (), "(0,0;0,100;150,100;150,0)");
} }
// smoothing // smoothing
@ -1224,8 +1224,8 @@ TEST(102)
db::Polygon p; db::Polygon p;
p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0])); p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0]));
EXPECT_EQ (smooth (p, 20).to_string (), "()"); EXPECT_EQ (smooth (p, 20, true).to_string (), "()");
EXPECT_EQ (smooth (p, 5).to_string (), "(100,-10;150,0;0,0;50,10)"); EXPECT_EQ (smooth (p, 5, true).to_string (), "(100,-10;150,0;0,0;50,10)");
} }
// smoothing // smoothing
@ -1251,9 +1251,9 @@ TEST(103)
db::Polygon p; db::Polygon p;
p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0])); p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0]));
EXPECT_EQ (smooth (p, 0).to_string (), "(59881,-249925;56852,-237283;56961,-237258;60061,-236492;63152,-235686;66231,-234839;69300,-233952;69407,-233919;73105,-246382;72992,-246417;69760,-247351;66516,-248243;63261,-249092;59995,-249899)"); EXPECT_EQ (smooth (p, 0, true).to_string (), "(59881,-249925;56852,-237283;56961,-237258;60061,-236492;63152,-235686;66231,-234839;69300,-233952;69407,-233919;73105,-246382;72992,-246417;69760,-247351;66516,-248243;63261,-249092;59995,-249899)");
EXPECT_EQ (smooth (p, 50).to_string (), "(59881,-249925;56852,-237283;63152,-235686;69407,-233919;73105,-246382;69760,-247351)"); EXPECT_EQ (smooth (p, 50, true).to_string (), "(59881,-249925;56852,-237283;63152,-235686;69407,-233919;73105,-246382;69760,-247351)");
EXPECT_EQ (smooth (p, 5000).to_string (), "(59881,-249925;56852,-237283;69407,-233919;73105,-246382)"); EXPECT_EQ (smooth (p, 5000, true).to_string (), "(59881,-249925;56852,-237283;69407,-233919;73105,-246382)");
} }
// smoothing // smoothing
@ -1272,7 +1272,8 @@ TEST(104)
db::Polygon p; db::Polygon p;
p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0])); p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0]));
EXPECT_EQ (smooth (p, 12).to_string (), "(-244,-942;-942,-246;248,943;943,246)"); EXPECT_EQ (smooth (p, 12, false).to_string (), "(-244,-942;-942,-246;248,943;943,246)");
EXPECT_EQ (smooth (p, 12, true).to_string (), "(-245,-942;-942,-247;-942,-246;247,943;248,943;943,246;-244,-942)");
} }
// smoothing // smoothing
@ -1292,11 +1293,46 @@ TEST(105)
db::Polygon p; db::Polygon p;
p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0])); p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0]));
EXPECT_EQ (smooth (p, 0).to_string (), "(0,0;0,1000;100,1000;100,1100;800,1100;800,1000;2000,1000;2000,0)"); EXPECT_EQ (smooth (p, 0, false).to_string (), "(0,0;0,1000;100,1000;100,1100;800,1100;800,1000;2000,1000;2000,0)");
EXPECT_EQ (smooth (p, 50).to_string (), "(0,0;0,1000;100,1000;100,1100;800,1100;800,1000;2000,1000;2000,0)"); EXPECT_EQ (smooth (p, 50, false).to_string (), "(0,0;0,1000;100,1000;100,1100;800,1100;800,1000;2000,1000;2000,0)");
EXPECT_EQ (smooth (p, 80).to_string (), "(0,0;0,1000;100,1100;800,1100;800,1000;2000,1000;2000,0)"); EXPECT_EQ (smooth (p, 80, false).to_string (), "(0,0;0,1000;100,1100;800,1100;800,1000;2000,1000;2000,0)");
EXPECT_EQ (smooth (p, 90).to_string (), "(0,0;100,1100;800,1100;800,1000;2000,1000;2000,0)"); EXPECT_EQ (smooth (p, 90, false).to_string (), "(0,0;100,1100;800,1100;800,1000;2000,1000;2000,0)");
EXPECT_EQ (smooth (p, 100).to_string (), "(0,0;0,1000;2000,1000;2000,0)"); EXPECT_EQ (smooth (p, 100, false).to_string (), "(0,0;0,1000;2000,1000;2000,0)");
EXPECT_EQ (smooth (p, 100, true).to_string (), "(0,0;0,1000;100,1000;100,1100;800,1100;800,1000;2000,1000;2000,0)");
}
// smoothing
TEST(106)
{
db::Point pattern [] = {
db::Point (0, 0),
db::Point (0, 73235),
db::Point (100, 74568),
db::Point (700, 82468),
db::Point (1200, 90468),
db::Point (2000, 106468),
db::Point (2300, 114468),
db::Point (2700, 130468),
db::Point (2800, 138468),
db::Point (2800, 154468),
db::Point (2700, 162468),
db::Point (2300, 178468),
db::Point (2000, 186468),
db::Point (1200, 202468),
db::Point (700, 210468),
db::Point (100, 218368),
db::Point (0, 219701),
db::Point (0, 272971),
db::Point (126450, 272971),
db::Point (126450, 0),
};
db::Polygon p;
p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0]));
EXPECT_EQ (smooth (p, 0, false).to_string (), "(0,0;0,73235;100,74568;700,82468;1200,90468;2000,106468;2300,114468;2700,130468;2800,138468;2800,154468;2700,162468;2300,178468;2000,186468;1200,202468;700,210468;100,218368;0,219701;0,272971;126450,272971;126450,0)");
EXPECT_EQ (smooth (p, 100, false).to_string (), "(0,0;100,74568;1200,90468;2300,114468;2800,138468;2700,162468;2000,186468;700,210468;0,219701;0,272971;126450,272971;126450,0)");
EXPECT_EQ (smooth (p, 100, true).to_string (), "(0,0;0,73235;1200,90468;2300,114468;2800,138468;2800,154468;2000,186468;700,210468;0,219701;0,272971;126450,272971;126450,0)");
} }
// rounding // rounding
@ -1501,7 +1537,7 @@ TEST(203)
in.push_back (pp); in.push_back (pp);
ep.simple_merge (in, out, false /*no cut line*/); ep.simple_merge (in, out, false /*no cut line*/);
pp = out.front (); pp = out.front ();
pp = smooth (pp, 1); pp = smooth (pp, 1, true);
EXPECT_EQ (pp.hull ().size (), size_t (300)); EXPECT_EQ (pp.hull ().size (), size_t (300));
EXPECT_EQ (extract_rad (pp, rinner, router, n, &pr), true); EXPECT_EQ (extract_rad (pp, rinner, router, n, &pr), true);
@ -1547,7 +1583,7 @@ TEST(204)
in.push_back (pp); in.push_back (pp);
ep.simple_merge (in, out, false /*no cut line*/); ep.simple_merge (in, out, false /*no cut line*/);
pp = out.front (); pp = out.front ();
pp = smooth (pp, 1); pp = smooth (pp, 1, true);
EXPECT_EQ (pp.hull ().size (), size_t (200)); EXPECT_EQ (pp.hull ().size (), size_t (200));
EXPECT_EQ (extract_rad (pp, rinner, router, n, &pr), true); EXPECT_EQ (extract_rad (pp, rinner, router, n, &pr), true);

View File

@ -354,6 +354,8 @@ TEST(10a)
r.set_merged_semantics (false); r.set_merged_semantics (false);
EXPECT_EQ (r.selected_interacting (db::Region (db::Box (db::Point (20, 20), db::Point (30, 30)))).to_string (), "(0,0;0,200;100,200;100,0)"); EXPECT_EQ (r.selected_interacting (db::Region (db::Box (db::Point (20, 20), db::Point (30, 30)))).to_string (), "(0,0;0,200;100,200;100,0)");
EXPECT_EQ (r.selected_not_interacting (db::Region (db::Box (db::Point (20, 20), db::Point (30, 30)))).to_string (), "(-100,-100;-100,0;0,0;0,-100)"); EXPECT_EQ (r.selected_not_interacting (db::Region (db::Box (db::Point (20, 20), db::Point (30, 30)))).to_string (), "(-100,-100;-100,0;0,0;0,-100)");
EXPECT_EQ (r.selected_interacting_differential (db::Region (db::Box (db::Point (20, 20), db::Point (30, 30)))).first.to_string (), "(0,0;0,200;100,200;100,0)");
EXPECT_EQ (r.selected_interacting_differential (db::Region (db::Box (db::Point (20, 20), db::Point (30, 30)))).second.to_string (), "(-100,-100;-100,0;0,0;0,-100)");
EXPECT_EQ (db::compare (r.selected_interacting (db::Region (db::Box (db::Point (-20, -20), db::Point (30, 30)))), "(0,0;0,200;100,200;100,0);(-100,-100;-100,0;0,0;0,-100)"), true); EXPECT_EQ (db::compare (r.selected_interacting (db::Region (db::Box (db::Point (-20, -20), db::Point (30, 30)))), "(0,0;0,200;100,200;100,0);(-100,-100;-100,0;0,0;0,-100)"), true);
EXPECT_EQ (r.selected_interacting (db::Region (db::Box (db::Point (-200, -200), db::Point (-190, -190)))).to_string (), ""); EXPECT_EQ (r.selected_interacting (db::Region (db::Box (db::Point (-200, -200), db::Point (-190, -190)))).to_string (), "");
db::Region rr = r; db::Region rr = r;
@ -836,6 +838,8 @@ TEST(18a)
EXPECT_EQ (db::compare (o, "(50,10;50,30;70,30;70,10);(70,60;70,80;90,80;90,60)"), true); EXPECT_EQ (db::compare (o, "(50,10;50,30;70,30;70,10);(70,60;70,80;90,80;90,60)"), true);
o = r; o = r;
EXPECT_EQ (db::compare (o.selected_not_outside (rr), "(0,0;0,20;20,20;20,0);(20,30;20,50;40,50;40,30);(0,60;0,80;60,80;60,60);(0,100;0,130;30,130;30,100)"), true); EXPECT_EQ (db::compare (o.selected_not_outside (rr), "(0,0;0,20;20,20;20,0);(20,30;20,50;40,50;40,30);(0,60;0,80;60,80;60,60);(0,100;0,130;30,130;30,100)"), true);
EXPECT_EQ (db::compare (o.selected_outside_differential (rr).first, "(50,10;50,30;70,30;70,10);(70,60;70,80;90,80;90,60)"), true);
EXPECT_EQ (db::compare (o.selected_outside_differential (rr).second, "(0,0;0,20;20,20;20,0);(20,30;20,50;40,50;40,30);(0,60;0,80;60,80;60,60);(0,100;0,130;30,130;30,100)"), true);
EXPECT_EQ (o.selected_outside (rr).count () + o.selected_not_outside (rr).count (), size_t (6)); EXPECT_EQ (o.selected_outside (rr).count () + o.selected_not_outside (rr).count (), size_t (6));
EXPECT_EQ (o.selected_outside (rr).hier_count () + o.selected_not_outside (rr).hier_count (), size_t (6)); EXPECT_EQ (o.selected_outside (rr).hier_count () + o.selected_not_outside (rr).hier_count (), size_t (6));
o.select_not_outside (rr); o.select_not_outside (rr);
@ -848,6 +852,8 @@ TEST(18a)
EXPECT_EQ (o.to_string (), "(20,30;20,50;40,50;40,30)"); EXPECT_EQ (o.to_string (), "(20,30;20,50;40,50;40,30)");
o = r; o = r;
EXPECT_EQ (db::compare (o.selected_not_inside (rr), "(0,0;0,20;20,20;20,0);(50,10;50,30;70,30;70,10);(70,60;70,80;90,80;90,60);(0,60;0,80;60,80;60,60);(0,100;0,130;30,130;30,100)"), true); EXPECT_EQ (db::compare (o.selected_not_inside (rr), "(0,0;0,20;20,20;20,0);(50,10;50,30;70,30;70,10);(70,60;70,80;90,80;90,60);(0,60;0,80;60,80;60,60);(0,100;0,130;30,130;30,100)"), true);
EXPECT_EQ (db::compare (o.selected_inside_differential (rr).first, "(20,30;20,50;40,50;40,30)"), true);
EXPECT_EQ (db::compare (o.selected_inside_differential (rr).second, "(0,0;0,20;20,20;20,0);(50,10;50,30;70,30;70,10);(70,60;70,80;90,80;90,60);(0,60;0,80;60,80;60,60);(0,100;0,130;30,130;30,100)"), true);
EXPECT_EQ (o.selected_inside (rr).count () + o.selected_not_inside (rr).count (), size_t (6)); EXPECT_EQ (o.selected_inside (rr).count () + o.selected_not_inside (rr).count (), size_t (6));
EXPECT_EQ (o.selected_inside (rr).hier_count () + o.selected_not_inside (rr).hier_count (), size_t (6)); EXPECT_EQ (o.selected_inside (rr).hier_count () + o.selected_not_inside (rr).hier_count (), size_t (6));
o.select_not_inside (rr); o.select_not_inside (rr);
@ -860,6 +866,8 @@ TEST(18a)
EXPECT_EQ (db::compare (o, "(0,0;0,20;20,20;20,0);(50,10;50,30;70,30;70,10);(20,30;20,50;40,50;40,30);(0,60;0,80;60,80;60,60);(0,100;0,130;30,130;30,100)"), true); EXPECT_EQ (db::compare (o, "(0,0;0,20;20,20;20,0);(50,10;50,30;70,30;70,10);(20,30;20,50;40,50;40,30);(0,60;0,80;60,80;60,60);(0,100;0,130;30,130;30,100)"), true);
o = r; o = r;
EXPECT_EQ (o.selected_not_interacting (rr).to_string (), "(70,60;70,80;90,80;90,60)"); EXPECT_EQ (o.selected_not_interacting (rr).to_string (), "(70,60;70,80;90,80;90,60)");
EXPECT_EQ (db::compare (o.selected_interacting_differential (rr).first, "(0,0;0,20;20,20;20,0);(50,10;50,30;70,30;70,10);(20,30;20,50;40,50;40,30);(0,60;0,80;60,80;60,60);(0,100;0,130;30,130;30,100)"), true);
EXPECT_EQ (db::compare (o.selected_interacting_differential (rr).second, "(70,60;70,80;90,80;90,60)"), true);
EXPECT_EQ (o.selected_interacting (rr).count () + o.selected_not_interacting (rr).count (), size_t (6)); EXPECT_EQ (o.selected_interacting (rr).count () + o.selected_not_interacting (rr).count (), size_t (6));
EXPECT_EQ (o.selected_interacting (rr).hier_count () + o.selected_not_interacting (rr).hier_count (), size_t (6)); EXPECT_EQ (o.selected_interacting (rr).hier_count () + o.selected_not_interacting (rr).hier_count (), size_t (6));
o.select_not_interacting (rr); o.select_not_interacting (rr);
@ -872,6 +880,8 @@ TEST(18a)
EXPECT_EQ (db::compare (o, "(0,0;0,20;20,20;20,0);(20,30;20,50;40,50;40,30);(0,60;0,80;60,80;60,60);(0,100;0,130;30,130;30,100)"), true); EXPECT_EQ (db::compare (o, "(0,0;0,20;20,20;20,0);(20,30;20,50;40,50;40,30);(0,60;0,80;60,80;60,60);(0,100;0,130;30,130;30,100)"), true);
o = r; o = r;
EXPECT_EQ (db::compare (o.selected_not_overlapping (rr), "(50,10;50,30;70,30;70,10);(70,60;70,80;90,80;90,60)"), true); EXPECT_EQ (db::compare (o.selected_not_overlapping (rr), "(50,10;50,30;70,30;70,10);(70,60;70,80;90,80;90,60)"), true);
EXPECT_EQ (db::compare (o.selected_overlapping_differential (rr).first, "(0,0;0,20;20,20;20,0);(20,30;20,50;40,50;40,30);(0,60;0,80;60,80;60,60);(0,100;0,130;30,130;30,100)"), true);
EXPECT_EQ (db::compare (o.selected_overlapping_differential (rr).second, "(50,10;50,30;70,30;70,10);(70,60;70,80;90,80;90,60)"), true);
EXPECT_EQ (o.selected_overlapping (rr).count () + o.selected_not_overlapping (rr).count (), size_t (6)); EXPECT_EQ (o.selected_overlapping (rr).count () + o.selected_not_overlapping (rr).count (), size_t (6));
EXPECT_EQ (o.selected_overlapping (rr).hier_count () + o.selected_not_overlapping (rr).hier_count (), size_t (6)); EXPECT_EQ (o.selected_overlapping (rr).hier_count () + o.selected_not_overlapping (rr).hier_count (), size_t (6));
o.select_not_overlapping (rr); o.select_not_overlapping (rr);
@ -884,6 +894,8 @@ TEST(18a)
EXPECT_EQ (o.to_string (), "(0,100;0,130;30,130;30,100)"); EXPECT_EQ (o.to_string (), "(0,100;0,130;30,130;30,100)");
o = r; o = r;
EXPECT_EQ (db::compare (o.selected_not_enclosing (rr), "(0,0;0,20;20,20;20,0);(50,10;50,30;70,30;70,10);(70,60;70,80;90,80;90,60);(20,30;20,50;40,50;40,30);(0,60;0,80;60,80;60,60)"), true); EXPECT_EQ (db::compare (o.selected_not_enclosing (rr), "(0,0;0,20;20,20;20,0);(50,10;50,30;70,30;70,10);(70,60;70,80;90,80;90,60);(20,30;20,50;40,50;40,30);(0,60;0,80;60,80;60,60)"), true);
EXPECT_EQ (db::compare (o.selected_enclosing_differential (rr).first, "(0,100;0,130;30,130;30,100)"), true);
EXPECT_EQ (db::compare (o.selected_enclosing_differential (rr).second, "(0,0;0,20;20,20;20,0);(50,10;50,30;70,30;70,10);(70,60;70,80;90,80;90,60);(20,30;20,50;40,50;40,30);(0,60;0,80;60,80;60,60)"), true);
EXPECT_EQ (o.selected_enclosing (rr).count () + o.selected_not_enclosing (rr).count (), size_t (6)); EXPECT_EQ (o.selected_enclosing (rr).count () + o.selected_not_enclosing (rr).count (), size_t (6));
EXPECT_EQ (o.selected_enclosing (rr).hier_count () + o.selected_not_enclosing (rr).hier_count (), size_t (6)); EXPECT_EQ (o.selected_enclosing (rr).hier_count () + o.selected_not_enclosing (rr).hier_count (), size_t (6));
o.select_not_enclosing (rr); o.select_not_enclosing (rr);
@ -1506,6 +1518,8 @@ TEST(30a)
r.set_merged_semantics (false); r.set_merged_semantics (false);
EXPECT_EQ (r.selected_interacting (db::Edges (db::Edge (db::Point (20, 20), db::Point (30, 30)))).to_string (), "(0,0;0,200;100,200;100,0)"); EXPECT_EQ (r.selected_interacting (db::Edges (db::Edge (db::Point (20, 20), db::Point (30, 30)))).to_string (), "(0,0;0,200;100,200;100,0)");
EXPECT_EQ (r.selected_not_interacting (db::Edges (db::Edge (db::Point (20, 20), db::Point (30, 30)))).to_string (), "(-100,-100;-100,0;0,0;0,-100)"); EXPECT_EQ (r.selected_not_interacting (db::Edges (db::Edge (db::Point (20, 20), db::Point (30, 30)))).to_string (), "(-100,-100;-100,0;0,0;0,-100)");
EXPECT_EQ (r.selected_interacting_differential (db::Edges (db::Edge (db::Point (20, 20), db::Point (30, 30)))).first.to_string (), "(0,0;0,200;100,200;100,0)");
EXPECT_EQ (r.selected_interacting_differential (db::Edges (db::Edge (db::Point (20, 20), db::Point (30, 30)))).second.to_string (), "(-100,-100;-100,0;0,0;0,-100)");
EXPECT_EQ (db::compare (r.selected_interacting (db::Edges (db::Edge (db::Point (-20, -20), db::Point (30, 30)))), "(-100,-100;-100,0;0,0;0,-100);(0,0;0,200;100,200;100,0)"), true); EXPECT_EQ (db::compare (r.selected_interacting (db::Edges (db::Edge (db::Point (-20, -20), db::Point (30, 30)))), "(-100,-100;-100,0;0,0;0,-100);(0,0;0,200;100,200;100,0)"), true);
EXPECT_EQ (r.selected_interacting (db::Edges (db::Edge (db::Point (-200, -200), db::Point (-190, -190)))).to_string (), ""); EXPECT_EQ (r.selected_interacting (db::Edges (db::Edge (db::Point (-200, -200), db::Point (-190, -190)))).to_string (), "");
db::Region rr = r; db::Region rr = r;
@ -1689,6 +1703,8 @@ TEST(34a)
r.set_merged_semantics (false); r.set_merged_semantics (false);
EXPECT_EQ (r.selected_interacting (db::Texts (db::Text ("abc", db::Trans (db::Vector (30, 30))))).to_string (), "(0,0;0,200;100,200;100,0)"); EXPECT_EQ (r.selected_interacting (db::Texts (db::Text ("abc", db::Trans (db::Vector (30, 30))))).to_string (), "(0,0;0,200;100,200;100,0)");
EXPECT_EQ (r.selected_not_interacting (db::Texts (db::Text ("abc", db::Trans (db::Vector (30, 30))))).to_string (), "(-100,-100;-100,0;0,0;0,-100)"); EXPECT_EQ (r.selected_not_interacting (db::Texts (db::Text ("abc", db::Trans (db::Vector (30, 30))))).to_string (), "(-100,-100;-100,0;0,0;0,-100)");
EXPECT_EQ (r.selected_interacting_differential (db::Texts (db::Text ("abc", db::Trans (db::Vector (30, 30))))).first.to_string (), "(0,0;0,200;100,200;100,0)");
EXPECT_EQ (r.selected_interacting_differential (db::Texts (db::Text ("abc", db::Trans (db::Vector (30, 30))))).second.to_string (), "(-100,-100;-100,0;0,0;0,-100)");
db::Texts tt; db::Texts tt;
tt.insert (db::Text ("abc", db::Trans (db::Vector (30, 30)))); tt.insert (db::Text ("abc", db::Trans (db::Vector (30, 30))));
tt.insert (db::Text ("xyz", db::Trans (db::Vector (-100, 0)))); tt.insert (db::Text ("xyz", db::Trans (db::Vector (-100, 0))));
@ -1782,6 +1798,7 @@ TEST(35a_interact_with_count_region)
EXPECT_EQ (r.selected_interacting (rr, 0, 2).to_string (), ""); EXPECT_EQ (r.selected_interacting (rr, 0, 2).to_string (), "");
EXPECT_EQ (r.selected_interacting (rr, 1, 2).to_string (), ""); EXPECT_EQ (r.selected_interacting (rr, 1, 2).to_string (), "");
EXPECT_EQ (r.selected_interacting (rr, 1, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)"); EXPECT_EQ (r.selected_interacting (rr, 1, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
EXPECT_EQ (r.selected_interacting_differential (rr, 1, 4).first.to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
EXPECT_EQ (r.selected_interacting (rr, 2, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)"); EXPECT_EQ (r.selected_interacting (rr, 2, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
EXPECT_EQ (r.selected_interacting (rr, 2, 1).to_string (), ""); EXPECT_EQ (r.selected_interacting (rr, 2, 1).to_string (), "");
EXPECT_EQ (r.selected_interacting (rr, 3, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)"); EXPECT_EQ (r.selected_interacting (rr, 3, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
@ -1797,6 +1814,7 @@ TEST(35a_interact_with_count_region)
EXPECT_EQ (r.selected_not_interacting (rr).to_string (), ""); EXPECT_EQ (r.selected_not_interacting (rr).to_string (), "");
EXPECT_EQ (r.selected_not_interacting (rr, 0, 2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)"); EXPECT_EQ (r.selected_not_interacting (rr, 0, 2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
EXPECT_EQ (r.selected_not_interacting (rr, 1, 2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)"); EXPECT_EQ (r.selected_not_interacting (rr, 1, 2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
EXPECT_EQ (r.selected_interacting_differential (rr, 1, 2).second.to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
EXPECT_EQ (r.selected_not_interacting (rr, 1, 4).to_string (), ""); EXPECT_EQ (r.selected_not_interacting (rr, 1, 4).to_string (), "");
EXPECT_EQ (r.selected_not_interacting (rr, 2, 4).to_string (), ""); EXPECT_EQ (r.selected_not_interacting (rr, 2, 4).to_string (), "");
EXPECT_EQ (db::compare (r.selected_not_interacting (rr, 2, 1), "(0,0;0,200;100,200;100,0);(-100,-100;-100,0;0,0;0,-100)"), true); EXPECT_EQ (db::compare (r.selected_not_interacting (rr, 2, 1), "(0,0;0,200;100,200;100,0);(-100,-100;-100,0;0,0;0,-100)"), true);
@ -1855,6 +1873,7 @@ TEST(35b_interact_with_count_edge)
EXPECT_EQ (r.selected_interacting (rr, 1, 2).to_string (), ""); EXPECT_EQ (r.selected_interacting (rr, 1, 2).to_string (), "");
EXPECT_EQ (r.selected_interacting (rr, 1, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)"); EXPECT_EQ (r.selected_interacting (rr, 1, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
EXPECT_EQ (r.selected_interacting (rr, 2, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)"); EXPECT_EQ (r.selected_interacting (rr, 2, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
EXPECT_EQ (r.selected_interacting_differential (rr, 2, 4).first.to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
EXPECT_EQ (r.selected_interacting (rr, 2, 1).to_string (), ""); EXPECT_EQ (r.selected_interacting (rr, 2, 1).to_string (), "");
EXPECT_EQ (r.selected_interacting (rr, 3, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)"); EXPECT_EQ (r.selected_interacting (rr, 3, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
EXPECT_EQ (r.selected_interacting (rr, 4, 5).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)"); EXPECT_EQ (r.selected_interacting (rr, 4, 5).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
@ -1869,6 +1888,7 @@ TEST(35b_interact_with_count_edge)
EXPECT_EQ (r.selected_not_interacting (rr).to_string (), ""); EXPECT_EQ (r.selected_not_interacting (rr).to_string (), "");
EXPECT_EQ (r.selected_not_interacting (rr, 0, 2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)"); EXPECT_EQ (r.selected_not_interacting (rr, 0, 2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
EXPECT_EQ (r.selected_not_interacting (rr, 1, 2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)"); EXPECT_EQ (r.selected_not_interacting (rr, 1, 2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
EXPECT_EQ (r.selected_interacting_differential (rr, 1, 2).second.to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
EXPECT_EQ (r.selected_not_interacting (rr, 1, 4).to_string (), ""); EXPECT_EQ (r.selected_not_interacting (rr, 1, 4).to_string (), "");
EXPECT_EQ (r.selected_not_interacting (rr, 2, 4).to_string (), ""); EXPECT_EQ (r.selected_not_interacting (rr, 2, 4).to_string (), "");
EXPECT_EQ (db::compare (r.selected_not_interacting (rr, 2, 1), "(0,0;0,200;100,200;100,0);(-100,-100;-100,0;0,0;0,-100)"), true); EXPECT_EQ (db::compare (r.selected_not_interacting (rr, 2, 1), "(0,0;0,200;100,200;100,0);(-100,-100;-100,0;0,0;0,-100)"), true);
@ -1926,6 +1946,7 @@ TEST(35c_interact_with_count_text)
EXPECT_EQ (r.selected_interacting (rr, 1, 2).to_string (), ""); EXPECT_EQ (r.selected_interacting (rr, 1, 2).to_string (), "");
EXPECT_EQ (r.selected_interacting (rr, 1, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)"); EXPECT_EQ (r.selected_interacting (rr, 1, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
EXPECT_EQ (r.selected_interacting (rr, 2, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)"); EXPECT_EQ (r.selected_interacting (rr, 2, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
EXPECT_EQ (r.selected_interacting_differential (rr, 2, 4).first.to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
EXPECT_EQ (r.selected_interacting (rr, 2, 1).to_string (), ""); EXPECT_EQ (r.selected_interacting (rr, 2, 1).to_string (), "");
EXPECT_EQ (r.selected_interacting (rr, 3, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)"); EXPECT_EQ (r.selected_interacting (rr, 3, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
EXPECT_EQ (r.selected_interacting (rr, 4, 5).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)"); EXPECT_EQ (r.selected_interacting (rr, 4, 5).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
@ -1940,6 +1961,7 @@ TEST(35c_interact_with_count_text)
EXPECT_EQ (r.selected_not_interacting (rr).to_string (), ""); EXPECT_EQ (r.selected_not_interacting (rr).to_string (), "");
EXPECT_EQ (r.selected_not_interacting (rr, 0, 2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)"); EXPECT_EQ (r.selected_not_interacting (rr, 0, 2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
EXPECT_EQ (r.selected_not_interacting (rr, 1, 2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)"); EXPECT_EQ (r.selected_not_interacting (rr, 1, 2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
EXPECT_EQ (r.selected_interacting_differential (rr, 1, 2).second.to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
EXPECT_EQ (r.selected_not_interacting (rr, 1, 4).to_string (), ""); EXPECT_EQ (r.selected_not_interacting (rr, 1, 4).to_string (), "");
EXPECT_EQ (r.selected_not_interacting (rr, 2, 4).to_string (), ""); EXPECT_EQ (r.selected_not_interacting (rr, 2, 4).to_string (), "");
EXPECT_EQ (db::compare (r.selected_not_interacting (rr, 2, 1), "(0,0;0,200;100,200;100,0);(-100,-100;-100,0;0,0;0,-100)"), true); EXPECT_EQ (db::compare (r.selected_not_interacting (rr, 2, 1), "(0,0;0,200;100,200;100,0);(-100,-100;-100,0;0,0;0,-100)"), true);

View File

@ -739,16 +739,18 @@ CODE
# %DRC% # %DRC%
# @name smoothed # @name smoothed
# @brief Applies smoothing # @brief Applies smoothing
# @synopsis expression.smoothed(d) # @synopsis expression.smoothed(d [, keep_hv ])
# #
# This operation acts on polygons and applies polygon smoothing with the tolerance d. See \Layer#smoothed for more details. # This operation acts on polygons and applies polygon smoothing with the tolerance d. 'keep_hv' indicates
# whether horizontal and vertical edges are maintained. Default is 'no' which means such edges may be distorted.
# See \Layer#smoothed for more details.
# #
# The "smoothed" method is available as a plain function or as a method on \DRC# expressions. # The "smoothed" method is available as a plain function or as a method on \DRC# expressions.
# The plain function is equivalent to "primary.smoothed". # The plain function is equivalent to "primary.smoothed".
def smoothed(d) def smoothed(d, keep_hv = false)
@engine._context("smoothed") do @engine._context("smoothed") do
DRCOpNodeFilter::new(@engine, self, :new_smoothed, "smoothed", @engine._make_value(d)) DRCOpNodeFilter::new(@engine, self, :new_smoothed, "smoothed", @engine._make_value(d), keep_hv)
end end
end end

View File

@ -48,6 +48,8 @@ module DRC
@deep = false @deep = false
@netter = nil @netter = nil
@netter_data = nil @netter_data = nil
@total_timer = nil
@drc_progress = nil
# initialize the defaults for max_area_ratio, max_vertex_count # initialize the defaults for max_area_ratio, max_vertex_count
dss = RBA::DeepShapeStore::new dss = RBA::DeepShapeStore::new
@ -58,7 +60,7 @@ module DRC
@verbose = false @verbose = false
@in_context = false @in_context = nil
end end
@ -93,7 +95,7 @@ module DRC
def transparent def transparent
DRCShielded::new(false) DRCShielded::new(false)
end end
def projection_limits(*args) def projection_limits(*args)
self._context("projection_limits") do self._context("projection_limits") do
if args.size == 0 if args.size == 0
@ -211,6 +213,27 @@ module DRC
end end
end end
def tile_size(x, y = nil)
DRCTileSize::new(_make_value(x) * self.dbu, _make_value(y || x) * self.dbu)
end
def tile_step(x, y = nil)
DRCTileStep::new(_make_value(x) * self.dbu, _make_value(y || x) * self.dbu)
end
def tile_origin(x, y)
DRCTileOrigin::new(_make_value(x) * self.dbu, _make_value(y) * self.dbu)
end
def tile_count(x, y)
DRCTileCount::new(_make_numeric_value(x), _make_numeric_value(y))
end
def tile_boundary(b)
b.is_a?(DRCLayer) || raise("'tile_boundary' requires a layer argument")
DRCTileBoundary::new(b)
end
# %DRC% # %DRC%
# @brief Defines SPICE output format (with options) # @brief Defines SPICE output format (with options)
# @name write_spice # @name write_spice
@ -455,15 +478,20 @@ module DRC
# %DRC% # %DRC%
# @name info # @name info
# @brief Outputs as message to the logger window # @brief Outputs as message to the logger or progress window
# @synopsis info(message) # @synopsis info(message)
# @synopsis info(message, indent) # @synopsis info(message, indent)
# Prints the message to the log window in verbose mode. # Prints the message to the log window in verbose mode.
# In non-verbose more, nothing is printed. # In non-verbose more, nothing is printed but a statement is put into the progress window.
# \log is a function that always prints a message. # \log is a function that always prints a message.
def info(arg, indent = 0) def info(arg, indent = 0)
@verbose && log(arg, indent) if @verbose
log(arg, indent)
else
str = (" " * indent) + arg
RBA::Logger::log(str)
end
end end
# %DRC% # %DRC%
@ -476,7 +504,7 @@ module DRC
# verbose mode is enabled. # verbose mode is enabled.
def log(arg, indent = 0) def log(arg, indent = 0)
str = (" " * indent) + arg str = (" " * indent) + arg
if @log_file if @log_file
@log_file.puts(str) @log_file.puts(str)
else else
@ -1828,7 +1856,7 @@ CODE
def _wrapper_context(func, *args, &proc) def _wrapper_context(func, *args, &proc)
in_context_outer = @in_context in_context_outer = @in_context
begin begin
@in_context = true @in_context = func
return yield(*args) return yield(*args)
rescue => ex rescue => ex
raise("'" + func + "': " + ex.to_s) raise("'" + func + "': " + ex.to_s)
@ -1842,22 +1870,40 @@ CODE
return yield(*args) return yield(*args)
else else
begin begin
@in_context = true @in_context = func
return yield(*args) return yield(*args)
rescue => ex rescue => ex
raise("'" + func + "': " + ex.to_s) raise("'" + func + "': " + ex.to_s)
ensure ensure
@in_context = false @in_context = nil
end end
end end
end end
def _result_info(res, indent, prefix = "")
if res.is_a?(Array)
res.each_with_index do |a, index|
_result_info(a, indent, "[#{index + 1}] ")
end
elsif res.is_a?(RBA::Region)
info(prefix + "Polygons (raw): #{res.count} (flat) #{res.hier_count} (hierarchical)", indent)
elsif res.is_a?(RBA::Edges)
info(prefix + "Edges: #{res.count} (flat) #{res.hier_count} (hierarchical)", indent)
elsif res.is_a?(RBA::EdgePairs)
info(prefix + "Edge pairs: #{res.count} (flat) #{res.hier_count} (hierarchical)", indent)
elsif res.is_a?(RBA::Texts)
info(prefix + "Texts: #{res.count} (flat) #{res.hier_count} (hierarchical)", indent)
end
end
def run_timed(desc, obj) def run_timed(desc, obj)
log(desc) info(desc)
# enable progress # enable progress
disable_progress = false
if obj.is_a?(RBA::Region) || obj.is_a?(RBA::Edges) || obj.is_a?(RBA::EdgePairs) || obj.is_a?(RBA::Texts) if obj.is_a?(RBA::Region) || obj.is_a?(RBA::Edges) || obj.is_a?(RBA::EdgePairs) || obj.is_a?(RBA::Texts)
disable_progress = true
obj.enable_progress(desc) obj.enable_progress(desc)
end end
@ -1867,39 +1913,37 @@ CODE
res = yield res = yield
t.stop t.stop
if @verbose begin
if @verbose
# Report result statistics
_result_info(res, 1)
mem = RBA::Timer::memory_size
if mem > 0
info("Elapsed: #{'%.3f'%(t.sys+t.user)}s Memory: #{'%.2f'%(mem/(1024*1024))}M", 1)
else
info("Elapsed: #{'%.3f'%(t.sys+t.user)}s", 1)
end
# Report result statistics
if res.is_a?(RBA::Region)
info("Polygons (raw): #{res.count} (flat) #{res.hier_count} (hierarchical)", 1)
elsif res.is_a?(RBA::Edges)
info("Edges: #{res.count} (flat) #{res.hier_count} (hierarchical)", 1)
elsif res.is_a?(RBA::EdgePairs)
info("Edge pairs: #{res.count} (flat) #{res.hier_count} (hierarchical)", 1)
elsif res.is_a?(RBA::Texts)
info("Texts: #{res.count} (flat) #{res.hier_count} (hierarchical)", 1)
end end
mem = RBA::Timer::memory_size ensure
if mem > 0
info("Elapsed: #{'%.3f'%(t.sys+t.user)}s Memory: #{'%.2f'%(mem/(1024*1024))}M", 1) # disable progress again
else if disable_progress
info("Elapsed: #{'%.3f'%(t.sys+t.user)}s", 1) obj.disable_progress
end end
end end
# disable progress
if obj.is_a?(RBA::Region) || obj.is_a?(RBA::Edges) || obj.is_a?(RBA::EdgePairs) || obj.is_a?(RBA::Texts)
obj.disable_progress
end
res res
end end
def _cmd(obj, method, *args) def _cmd(obj, method, *args)
run_timed("\"#{method}\" in: #{src_line}", obj) do run_timed("\"#{@in_context || method}\" in: #{src_line}", obj) do
obj.send(method, *args) obj.send(method, *args)
end end
end end
@ -1929,8 +1973,9 @@ CODE
end end
av = args.size.times.collect { |i| "a#{i}" }.join(", ") av = args.size.times.collect { |i| "a#{i}" }.join(", ")
tp.queue("_output(res, self.#{method}(#{av}))") tp.queue("_output(res, self.#{method}(#{av}))")
run_timed("\"#{method}\" in: #{src_line}", obj) do run_timed("\"#{@in_context || method}\" in: #{src_line}", obj) do
tp.execute("Tiled \"#{method}\" in: #{src_line}") tp.execute("Tiled \"#{method}\" in: #{src_line}")
res
end end
else else
@ -1940,17 +1985,12 @@ CODE
end end
res = nil res = nil
run_timed("\"#{method}\" in: #{src_line}", obj) do run_timed("\"#{@in_context || method}\" in: #{src_line}", obj) do
res = obj.send(method, *args) res = obj.send(method, *args)
end end
end end
# disable progress again
if obj.is_a?(RBA::Region)
obj.disable_progress
end
res res
end end
@ -1984,8 +2024,9 @@ CODE
end end
av = args.size.times.collect { |i| "a#{i}" }.join(", ") av = args.size.times.collect { |i| "a#{i}" }.join(", ")
tp.queue("var rr = self.#{method}(#{av}); _output(res1, rr[0]); _output(res2, rr[1])") tp.queue("var rr = self.#{method}(#{av}); _output(res1, rr[0]); _output(res2, rr[1])")
run_timed("\"#{method}\" in: #{src_line}", obj) do run_timed("\"#{@in_context || method}\" in: #{src_line}", obj) do
tp.execute("Tiled \"#{method}\" in: #{src_line}") tp.execute("Tiled \"#{method}\" in: #{src_line}")
res
end end
else else
@ -1995,17 +2036,12 @@ CODE
end end
res = nil res = nil
run_timed("\"#{method}\" in: #{src_line}", obj) do run_timed("\"#{@in_context || method}\" in: #{src_line}", obj) do
res = obj.send(method, *args) res = obj.send(method, *args)
end end
end end
# disable progress again
if obj.is_a?(RBA::Region)
obj.disable_progress
end
res res
end end
@ -2025,8 +2061,9 @@ CODE
tp.input("self", obj) tp.input("self", obj)
tp.threads = (@tt || 1) tp.threads = (@tt || 1)
tp.queue("_output(res, _tile ? self.#{method}(_tile.bbox) : self.#{method})") tp.queue("_output(res, _tile ? self.#{method}(_tile.bbox) : self.#{method})")
run_timed("\"#{method}\" in: #{src_line}", obj) do run_timed("\"#{@in_context || method}\" in: #{src_line}", obj) do
tp.execute("Tiled \"#{method}\" in: #{src_line}") tp.execute("Tiled \"#{method}\" in: #{src_line}")
res
end end
res = res.value res = res.value
@ -2038,39 +2075,40 @@ CODE
end end
res = nil res = nil
run_timed("\"#{method}\" in: #{src_line}", obj) do run_timed("\"#{@in_context || method}\" in: #{src_line}", obj) do
res = obj.send(method) res = obj.send(method)
end end
end end
# disable progress again
if obj.is_a?(RBA::Region)
obj.disable_progress
end
res res
end end
def _rcmd(obj, method, *args) def _rcmd(obj, method, *args)
run_timed("\"#{method}\" in: #{src_line}", obj) do run_timed("\"#{@in_context || method}\" in: #{src_line}", obj) do
RBA::Region::new(obj.send(method, *args)) RBA::Region::new(obj.send(method, *args))
end end
end end
def _vcmd(obj, method, *args) def _vcmd(obj, method, *args)
run_timed("\"#{method}\" in: #{src_line}", obj) do run_timed("\"#{@in_context || method}\" in: #{src_line}", obj) do
obj.send(method, *args) obj.send(method, *args)
end end
end end
def _start def _start(macro_path)
# clearing the selection avoids some nasty problems # clearing the selection avoids some nasty problems
view = RBA::LayoutView::current view = RBA::LayoutView::current
view && view.cancel view && view.cancel
@total_timer = RBA::Timer::new
@total_timer.start
@drc_progress = RBA::AbstractProgress::new("DRC: " + macro_path)
end end
def _flush def _flush
@ -2210,6 +2248,18 @@ CODE
@netter = nil @netter = nil
@netter_data = nil @netter_data = nil
if final
@total_timer.stop
if @verbose
mem = RBA::Timer::memory_size
if mem > 0
info("Total elapsed: #{'%.3f'%(@total_timer.sys+@total_timer.user)}s Memory: #{'%.2f'%(mem/(1024*1024))}M")
else
info("Total elapsed: #{'%.3f'%(@total_timer.sys+@total_timer.user)}s")
end
end
end
if final && @log_file if final && @log_file
@log_file.close @log_file.close
@log_file = nil @log_file = nil
@ -2218,6 +2268,10 @@ CODE
# force garbage collection # force garbage collection
GC.start GC.start
# unlocks the UI
@drc_progress._destroy
@drc_progress = nil
end end
end end
@ -2526,6 +2580,9 @@ CODE
end end
end end
data
end end
def make_source(layout, cell = nil, path = nil) def make_source(layout, cell = nil, path = nil)

View File

@ -983,8 +983,8 @@ CODE
# @name corners # @name corners
# @brief Selects corners of polygons # @brief Selects corners of polygons
# @synopsis layer.corners([ options ]) # @synopsis layer.corners([ options ])
# @synopsis layer.corners(angle, [ options ]) # @synopsis layer.corners(angle [, options ])
# @synopsis layer.corners(amin .. amax, [ options ]) # @synopsis layer.corners(amin .. amax [, options ])
# #
# This method produces markers on the corners of the polygons. An angle criterion can be given which # This method produces markers on the corners of the polygons. An angle criterion can be given which
# selects corners based on the angle of the connecting edges. Positive angles indicate a left turn # selects corners based on the angle of the connecting edges. Positive angles indicate a left turn
@ -1263,6 +1263,7 @@ CODE
self.data.send(new_data.is_a?(RBA::EdgePairs) ? :each : :each_merged) do |object| self.data.send(new_data.is_a?(RBA::EdgePairs) ? :each : :each_merged) do |object|
block.call(object.transformed(t)) && new_data.insert(object) block.call(object.transformed(t)) && new_data.insert(object)
end end
new_data
end end
DRCLayer::new(@engine, new_data) DRCLayer::new(@engine, new_data)
@ -1285,7 +1286,7 @@ CODE
@engine._wrapper_context("each") do @engine._wrapper_context("each") do
t = RBA::CplxTrans::new(@engine.dbu) t = RBA::CplxTrans::new(@engine.dbu)
@engine.run_timed("\"select\" in: #{@engine.src_line}", self.data) do @engine.run_timed("\"each\" in: #{@engine.src_line}", self.data) do
self.data.send(self.data.is_a?(RBA::EdgePairs) ? :each : :each_merged) do |object| self.data.send(self.data.is_a?(RBA::EdgePairs) ? :each : :each_merged) do |object|
block.call(object.transformed(t)) block.call(object.transformed(t))
end end
@ -1368,10 +1369,11 @@ CODE
t = RBA::CplxTrans::new(@engine.dbu) t = RBA::CplxTrans::new(@engine.dbu)
dbu_trans = RBA::VCplxTrans::new(1.0 / @engine.dbu) dbu_trans = RBA::VCplxTrans::new(1.0 / @engine.dbu)
@engine.run_timed("\\"select\\" in: " + @engine.src_line, self.data) do @engine.run_timed("\\"#{f}\\" in: " + @engine.src_line, self.data) do
self.data.send(new_data.is_a?(RBA::EdgePairs) ? :each : :each_merged) do |object| self.data.send(new_data.is_a?(RBA::EdgePairs) ? :each : :each_merged) do |object|
insert_object_into(new_data, block.call(object.transformed(t)), dbu_trans) insert_object_into(new_data, block.call(object.transformed(t)), dbu_trans)
end end
new_data
end end
DRCLayer::new(@engine, new_data) DRCLayer::new(@engine, new_data)
@ -1660,6 +1662,7 @@ CODE
@engine._context("andnot") do @engine._context("andnot") do
check_is_layer(other)
requires_region requires_region
other.requires_region other.requires_region
@ -1773,6 +1776,21 @@ CODE
# It returns a new layer containing the selected shapes. A version which modifies self # It returns a new layer containing the selected shapes. A version which modifies self
# is \select_not_covering. # is \select_not_covering.
# %DRC%
# @name split_covering
# @brief Returns the results of \covering and \not_covering at the same time
# @synopsis (a, b) = layer.split_covering(other [, options ])
#
# This method returns the polygons covering polygons from the other layer in
# one layer and all others in a second layer. This method is equivalent to calling
# \covering and \not_covering, but is faster than doing this in separate steps:
#
# @code
# (covering, not_covering) = l1.split_covering(l2)
# @/code
#
# The options of this method are the same than \covering.
# %DRC% # %DRC%
# @name select_covering # @name select_covering
# @brief Selects shapes or regions of self which completely cover (enclose) one or more shapes from the other region # @brief Selects shapes or regions of self which completely cover (enclose) one or more shapes from the other region
@ -1849,6 +1867,21 @@ CODE
# It returns a new layer containing the selected shapes. A version which modifies self # It returns a new layer containing the selected shapes. A version which modifies self
# is \select_not_overlapping. # is \select_not_overlapping.
# %DRC%
# @name split_overlapping
# @brief Returns the results of \overlapping and \not_overlapping at the same time
# @synopsis (a, b) = layer.split_overlapping(other [, options ])
#
# This method returns the polygons overlapping polygons from the other layer in
# one layer and all others in a second layer. This method is equivalent to calling
# \overlapping and \not_overlapping, but is faster than doing this in separate steps:
#
# @code
# (overlapping, not_overlapping) = l1.split_overlapping(l2)
# @/code
#
# The options of this method are the same than \overlapping.
# %DRC% # %DRC%
# @name select_overlapping # @name select_overlapping
# @brief Selects shapes or regions of self which overlap shapes from the other region # @brief Selects shapes or regions of self which overlap shapes from the other region
@ -1923,6 +1956,19 @@ CODE
# @/tr # @/tr
# @/table # @/table
# %DRC%
# @name split_inside
# @brief Returns the results of \inside and \not_inside at the same time
# @synopsis (a, b) = layer.split_inside(other)
#
# This method returns the polygons inside of polygons from the other layer in
# one layer and all others in a second layer. This method is equivalent to calling
# \inside and \not_inside, but is faster than doing this in separate steps:
#
# @code
# (inside, not_inside) = l1.split_inside(l2)
# @/code
# %DRC% # %DRC%
# @name select_inside # @name select_inside
# @brief Selects shapes or regions of self which are inside the other region # @brief Selects shapes or regions of self which are inside the other region
@ -1995,6 +2041,19 @@ CODE
# @/tr # @/tr
# @/table # @/table
# %DRC%
# @name split_outside
# @brief Returns the results of \outside and \not_outside at the same time
# @synopsis (a, b) = layer.split_outside(other)
#
# This method returns the polygons outside of polygons from the other layer in
# one layer and all others in a second layer. This method is equivalent to calling
# \outside and \not_outside, but is faster than doing this in separate steps:
#
# @code
# (outside, not_outside) = l1.split_outside(l2)
# @/code
# %DRC% # %DRC%
# @name select_outside # @name select_outside
# @brief Selects shapes or regions of self which are outside the other region # @brief Selects shapes or regions of self which are outside the other region
@ -2149,6 +2208,21 @@ CODE
# @/tr # @/tr
# @/table # @/table
# %DRC%
# @name split_interacting
# @brief Returns the results of \interacting and \not_interacting at the same time
# @synopsis (a, b) = layer.split_interacting(other [, options ])
#
# This method returns the polygons interacting with objects from the other container in
# one layer and all others in a second layer. This method is equivalent to calling
# \interacting and \not_interacting, but is faster than doing this in separate steps:
#
# @code
# (interacting, not_interacting) = l1.split_interacting(l2)
# @/code
#
# The options of this method are the same than \interacting.
# %DRC% # %DRC%
# @name select_interacting # @name select_interacting
# @brief Selects shapes or regions of self which touch or overlap shapes from the other region # @brief Selects shapes or regions of self which touch or overlap shapes from the other region
@ -2192,7 +2266,7 @@ CODE
# number of (different) shapes from the other layer. If a min and max count is given, shapes from # number of (different) shapes from the other layer. If a min and max count is given, shapes from
# self are selected only if they interact with less than min_count or more than max_count different shapes # self are selected only if they interact with less than min_count or more than max_count different shapes
# from the other layer. Two polygons overlapping or touching at two locations are counted as single interactions. # from the other layer. Two polygons overlapping or touching at two locations are counted as single interactions.
# %DRC% # %DRC%
# @name intersections # @name intersections
# @brief Returns the intersection points of intersecting edge segments for two edge collections # @brief Returns the intersection points of intersecting edge segments for two edge collections
@ -2285,6 +2359,7 @@ CODE
@engine._context("#{f}") do @engine._context("#{f}") do
check_is_layer(other)
if :#{f} != :pull_interacting if :#{f} != :pull_interacting
requires_region requires_region
other.requires_region other.requires_region
@ -2310,11 +2385,16 @@ CODE
%w(| ^ inside not_inside outside not_outside in not_in).each do |f| %w(| ^ inside not_inside outside not_outside in not_in).each do |f|
eval <<"CODE" eval <<"CODE"
def #{f}(other) def #{f}(other)
@engine._context("#{f}") do @engine._context("#{f}") do
requires_same_type(other) requires_same_type(other)
requires_edges_or_region requires_edges_or_region
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, self.data.class, :#{f}, other.data)) DRCLayer::new(@engine, @engine._tcmd(self.data, 0, self.data.class, :#{f}, other.data))
end end
end end
CODE CODE
end end
@ -2325,12 +2405,14 @@ CODE
@engine._context("#{f}") do @engine._context("#{f}") do
check_is_layer(other)
other.requires_edges_texts_or_region other.requires_edges_texts_or_region
if self.data.is_a?(RBA::Texts) if self.data.is_a?(RBA::Texts)
other.requires_region other.requires_region
else else
other.requires_edges_or_region other.requires_edges_or_region
end end
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, self.data.class, :#{f}, other.data)) DRCLayer::new(@engine, @engine._tcmd(self.data, 0, self.data.class, :#{f}, other.data))
end end
@ -2342,10 +2424,14 @@ CODE
%w(+).each do |f| %w(+).each do |f|
eval <<"CODE" eval <<"CODE"
def #{f}(other) def #{f}(other)
@engine._context("#{f}") do @engine._context("#{f}") do
requires_same_type(other) requires_same_type(other)
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, self.data.class, :#{f}, other.data)) DRCLayer::new(@engine, @engine._tcmd(self.data, 0, self.data.class, :#{f}, other.data))
end end
end end
CODE CODE
end end
@ -2356,7 +2442,7 @@ CODE
@engine._context("#{f}") do @engine._context("#{f}") do
other.requires_edges_texts_or_region check_is_layer(other)
if self.data.is_a?(RBA::Text) if self.data.is_a?(RBA::Text)
other.requires_region other.requires_region
elsif self.data.is_a?(RBA::Region) elsif self.data.is_a?(RBA::Region)
@ -2381,6 +2467,7 @@ CODE
@engine._context("#{f}") do @engine._context("#{f}") do
check_is_layer(other)
requires_edges_texts_or_region requires_edges_texts_or_region
if self.data.is_a?(RBA::Text) if self.data.is_a?(RBA::Text)
other.requires_region other.requires_region
@ -2389,6 +2476,7 @@ CODE
else else
other.requires_edges_or_region other.requires_edges_or_region
end end
if @engine.is_tiled? if @engine.is_tiled?
self.data = @engine._tcmd(self.data, 0, self.data.class, :#{fi}, other.data, *minmax_count(*args)) self.data = @engine._tcmd(self.data, 0, self.data.class, :#{fi}, other.data, *minmax_count(*args))
DRCLayer::new(@engine, self.data) DRCLayer::new(@engine, self.data)
@ -2402,14 +2490,39 @@ CODE
CODE CODE
end end
%w(overlapping not_overlapping covering not_covering).each do |f| %w(split_interacting).each do |f|
eval <<"CODE" eval <<"CODE"
def #{f}(other, *args) def #{f}(other, *args)
@engine._context("#{f}") do @engine._context("#{f}") do
check_is_layer(other)
requires_region
other.requires_edges_texts_or_region
res = @engine._tcmd_a2(self.data, 0, self.data.class, self.data.class, :#{f}, other.data, *minmax_count(*args))
[ DRCLayer::new(@engine, res[0]), DRCLayer::new(@engine, res[1]) ]
end
end
CODE
end
%w(overlapping not_overlapping covering not_covering).each do |f|
eval <<"CODE"
def #{f}(other, *args)
@engine._context("#{f}") do
requires_same_type(other) requires_same_type(other)
requires_region requires_region
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, self.data.class, :#{f}, other.data, *minmax_count(*args))) DRCLayer::new(@engine, @engine._tcmd(self.data, 0, self.data.class, :#{f}, other.data, *minmax_count(*args)))
end end
end end
CODE CODE
end end
@ -2424,6 +2537,7 @@ CODE
requires_region requires_region
requires_same_type(other) requires_same_type(other)
if @engine.is_tiled? if @engine.is_tiled?
self.data = @engine._tcmd(self.data, 0, self.data.class, :#{fi}, other.data, *minmax_count(*args)) self.data = @engine._tcmd(self.data, 0, self.data.class, :#{fi}, other.data, *minmax_count(*args))
DRCLayer::new(@engine, self.data) DRCLayer::new(@engine, self.data)
@ -2437,6 +2551,24 @@ CODE
CODE CODE
end end
%w(split_overlapping split_covering).each do |f|
eval <<"CODE"
def #{f}(other, *args)
@engine._context("#{f}") do
requires_region
other.requires_region
res = @engine._tcmd_a2(self.data, 0, self.data.class, self.data.class, :#{f}, other.data, *minmax_count(*args))
[ DRCLayer::new(@engine, res[0]), DRCLayer::new(@engine, res[1]) ]
end
end
CODE
end
%w(inside not_inside outside not_outside).each do |fi| %w(inside not_inside outside not_outside).each do |fi|
f = "select_" + fi f = "select_" + fi
# In tiled mode, there are no modifying versions. Emulate using the non-modifying one. # In tiled mode, there are no modifying versions. Emulate using the non-modifying one.
@ -2447,6 +2579,7 @@ CODE
requires_region requires_region
requires_same_type(other) requires_same_type(other)
if @engine.is_tiled? if @engine.is_tiled?
self.data = @engine._tcmd(self.data, 0, self.data.class, :#{fi}, other.data) self.data = @engine._tcmd(self.data, 0, self.data.class, :#{fi}, other.data)
DRCLayer::new(@engine, self.data) DRCLayer::new(@engine, self.data)
@ -2460,14 +2593,39 @@ CODE
CODE CODE
end end
%w(split_inside split_outside).each do |f|
eval <<"CODE"
def #{f}(other)
@engine._context("#{f}") do
check_is_layer(other)
requires_region
other.requires_region
res = @engine._tcmd_a2(self.data, 0, self.data.class, self.data.class, :#{f}, other.data)
[ DRCLayer::new(@engine, res[0]), DRCLayer::new(@engine, res[1]) ]
end
end
CODE
end
%w(inside_part outside_part).each do |f| %w(inside_part outside_part).each do |f|
eval <<"CODE" eval <<"CODE"
def #{f}(other) def #{f}(other)
@engine._context("#{f}") do @engine._context("#{f}") do
check_is_layer(other)
other.requires_region other.requires_region
requires_edges requires_edges
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, self.data.class, :#{f}, other.data)) DRCLayer::new(@engine, @engine._tcmd(self.data, 0, self.data.class, :#{f}, other.data))
end end
end end
CODE CODE
end end
@ -2475,11 +2633,17 @@ CODE
%w(intersections).each do |f| %w(intersections).each do |f|
eval <<"CODE" eval <<"CODE"
def #{f}(other) def #{f}(other)
@engine._context("#{f}") do @engine._context("#{f}") do
check_is_layer(other)
other.requires_edges other.requires_edges
requires_edges requires_edges
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, self.data.class, :#{f}, other.data)) DRCLayer::new(@engine, @engine._tcmd(self.data, 0, self.data.class, :#{f}, other.data))
end end
end end
CODE CODE
end end
@ -3496,6 +3660,180 @@ CODE
end end
CODE CODE
end end
# %DRC%
# @name with_density
# @brief Returns tiles whose density is within a given range
# @synopsis layer.with_density(min_value, max_value [, options ])
# @synopsis layer.with_density(min_value .. max_value [, options ])
#
# This method runs a tiled analysis over the current layout. It reports the tiles whose density
# is between "min_value" and "max_value". "min_value" and "max_value" are given in
# relative units, i.e. within the range of 0 to 1.0 corresponding to a density of 0 to 100%.
#
# "min_value" or "max_value" can be nil or omitted in the ".." range notation.
# In this case, they are taken as "0" and "100%".
#
# The tile size must be specified with the "tile_size" option:
#
# @code
# # reports areas where layer 1/0 density is below 10% on 20x20 um tiles
# low_density = input(1, 0).density(0.0 .. 0.1, tile_size(20.um))
# @/code
#
# Anisotropic tiles can be specified by giving two values, like "tile_size(10.um, 20.um)".
# The first value is the horizontal tile dimension, the second value is the vertical tile
# dimension.
#
# A tile overlap can be specified using "tile_step". If the tile step is less than the
# tile size, the tiles will overlap. The layout window given by "tile_size" is moved
# in increments of the tile step:
#
# @code
# # reports areas where layer 1/0 density is below 10% on 30x30 um tiles
# # with a tile step of 20x20 um:
# low_density = input(1, 0).density(0.0 .. 0.1, tile_size(30.um), tile_step(20.um))
# @/code
#
# For "tile_step", anisotropic values can be given as well by using two values: the first for the
# horizontal and the second for the vertical tile step.
#
# Another option is "tile_origin" which specifies the location of the first tile's position.
# This is the lower left tile's lower left corner. If no origin is given, the tiles are centered over the
# area investigated.
#
# By default, the tiles will cover the bounding box of the input layer. A separate layer
# can be used in addition. This way, the layout's dimensions can be derived from some
# drawn boundary layer. To specify a separate, additional layer included in the bounding box, use the "tile_boundary" option:
#
# @code
# # reports density of layer 1/0 below 10% on 20x20 um tiles. The layout's boundary is taken from
# # layer 0/0:
# cell_frame = input(0, 0)
# low_density = input(1, 0).density(0.0 .. 0.1, tile_size(20.um), tile_boundary(cell_frame))
# @/code
#
# Note that the layer given in "tile_boundary" adds to the input layer for computing the bounding box.
# The computed area is at least the area of the input layer.
#
# Computation of the area can be skipped by explicitly giving a tile count in horizontal and vertical
# direction. With the "tile_origin" option this allows full control over the area covered:
#
# @code
# # reports density of layer 1/0 below 10% on 20x20 um tiles in the region 0,0 .. 2000,3000
# # (100 and 150 tiles of 20 um each are used in horizontal and vertical direction):
# low_density = input(1, 0).density(0.0 .. 0.1, tile_size(20.um), tile_origin(0.0, 0.0), tile_count(100, 150))
# @/code
#
# The complementary version of "with_density" is \without_density.
# %DRC%
# @name without_density
# @brief Returns tiles whose density is not within a given range
# @synopsis layer.without_density(min_value, max_value [, options ])
# @synopsis layer.without_density(min_value .. max_value [, options ])
#
# For details about the operations and the operation see \with_density. This version will return the
# tiles where the density is not within the given range.
def _with_density(method, inverse, *args)
requires_region
limits = [ nil, nil ]
nlimits = 0
tile_size = nil
tile_step = nil
tile_origin = nil
tile_count = nil
tile_boundary = nil
n = 1
args.each do |a|
if a.is_a?(DRCTileSize)
tile_size = a.get
elsif a.is_a?(DRCTileStep)
tile_step = a.get
elsif a.is_a?(DRCTileOrigin)
tile_origin = a.get
elsif a.is_a?(DRCTileCount)
tile_count = a.get
elsif a.is_a?(DRCTileBoundary)
tile_boundary = a.get
elsif a.is_a?(Float) || a.is_a?(1.class) || a == nil
nlimits < 2 || raise("Too many values specified")
limits[nlimits] = @engine._make_numeric_value_with_nil(a)
nlimits += 1
elsif a.is_a?(Range)
nlimits == 0 || raise("Either a range or two limits have to be specified, not both")
limits = [ @engine._make_numeric_value_with_nil(a.begin), @engine._make_numeric_value_with_nil(a.end) ]
nlimits = 2
else
raise("Parameter #" + n.to_s + " does not have an expected type")
end
n += 1
end
tile_size || raise("At least the tile_size option needs to be present")
tile_step ||= tile_size
tp = RBA::TilingProcessor::new
tp.dbu = @engine.dbu
tp.scale_to_dbu = false
tp.tile_size(*tile_step)
if tile_size != tile_step
xb = 0.5 * (tile_size[0] - tile_step[0])
yb = 0.5 * (tile_size[1] - tile_step[1])
tp.tile_border(xb, yb)
tp.var("xoverlap", xb / tp.dbu)
tp.var("yoverlap", yb / tp.dbu)
else
tp.var("xoverlap", 0)
tp.var("yoverlap", 0)
end
if tile_origin
tp.tile_origin(*tile_origin)
end
if tile_count
tp.tiles(*tile_count)
end
res = RBA::Region.new
tp.output("res", res)
tp.input("input", self.data)
tp.threads = (@engine.threads || 1)
if tile_boundary
tp.input("boundary", tile_boundary.data)
end
tp.var("vmin", limits[0] || 0.0)
tp.var("vmax", limits[1] || 1.0)
tp.var("inverse", inverse)
tp.queue(<<"TP_SCRIPT")
_tile && (
var bx = _tile.bbox.enlarged(xoverlap, yoverlap);
var d = to_f(input.area(bx)) / to_f(bx.area);
((d > vmin - 1e-10 && d < vmax + 1e-10) != inverse) && _output(res, bx, false)
)
TP_SCRIPT
@engine.run_timed("\"#{method}\" in: #{@engine.src_line}", self.data) do
tp.execute("Tiled \"#{method}\" in: #{@engine.src_line}")
res
end
DRCLayer::new(@engine, res)
end
def with_density(*args)
self._with_density("with_density", false, *args)
end
def without_density(*args)
self._with_density("without_density", true, *args)
end
# %DRC% # %DRC%
# @name scaled # @name scaled
@ -3915,6 +4253,10 @@ CODE
@data = d @data = d
end end
def check_is_layer(other)
other.is_a?(DRCLayer) || raise("Argument needs to be a DRC layer")
end
def requires_region def requires_region
self.data.is_a?(RBA::Region) || raise("Requires a polygon layer") self.data.is_a?(RBA::Region) || raise("Requires a polygon layer")
end end

View File

@ -180,6 +180,56 @@ module DRC
@value @value
end end
end end
# A wrapper for the tile_size option
class DRCTileSize
def initialize(*args)
@xy = args
end
def get
@xy
end
end
# A wrapper for the tile_step option
class DRCTileStep
def initialize(*args)
@xy = args
end
def get
@xy
end
end
# A wrapper for the tile_origin option
class DRCTileOrigin
def initialize(*args)
@xy = args
end
def get
@xy
end
end
# A wrapper for the tile_count option
class DRCTileCount
def initialize(*args)
@xy = args
end
def get
@xy
end
end
# A wrapper for the tile_boundary option
class DRCTileBoundary
def initialize(layer)
@b = layer
end
def get
@b
end
end
end end

View File

@ -19,13 +19,10 @@ module DRC
def DRC.execute_drc(macro, generator, rdb_index = nil) def DRC.execute_drc(macro, generator, rdb_index = nil)
timer = RBA::Timer::new
timer.start
drc = DRCEngine::new drc = DRCEngine::new
drc._rdb_index = rdb_index drc._rdb_index = rdb_index
drc._generator = generator drc._generator = generator
drc._start(macro.path)
drc_progress = RBA::AbstractProgress::new("DRC: " + macro.path)
begin begin
@ -48,14 +45,8 @@ module DRC
# cleans up and creates layout and report views # cleans up and creates layout and report views
drc._finish drc._finish
# unlocks the UI
drc_progress._destroy
end end
timer.stop
drc.info("Total run time: #{'%.3f'%(timer.sys+timer.user)}s")
end end
# A DSL implementation for a DRC language (XML format) # A DSL implementation for a DRC language (XML format)

View File

@ -1163,3 +1163,8 @@ TEST(29d_holes)
run_test (_this, "29", true); run_test (_this, "29", true);
} }
TEST(30_density)
{
run_test (_this, "30", false);
}

View File

@ -1387,7 +1387,7 @@ MainService::cm_round_corners ()
std::vector <db::Polygon> in; std::vector <db::Polygon> in;
ep.merge (primary, in, 0 /*min_wc*/, false /*resolve holes*/, true /*min coherence*/); ep.merge (primary, in, 0 /*min_wc*/, false /*resolve holes*/, true /*min coherence*/);
for (std::vector <db::Polygon>::iterator p = in.begin (); p != in.end (); ++p) { for (std::vector <db::Polygon>::iterator p = in.begin (); p != in.end (); ++p) {
*p = smooth (*p, 1); *p = smooth (*p, 1, true);
} }
std::vector <db::Polygon> out = in; std::vector <db::Polygon> out = in;

View File

@ -72,6 +72,7 @@ The following global functions are relevant for the DRC expressions:
<li><a href="/about/drc_ref_global.xml#space">space</a> </li> <li><a href="/about/drc_ref_global.xml#space">space</a> </li>
<li><a href="/about/drc_ref_global.xml#squares">squares</a> </li> <li><a href="/about/drc_ref_global.xml#squares">squares</a> </li>
<li><a href="/about/drc_ref_global.xml#width">width</a> </li> <li><a href="/about/drc_ref_global.xml#width">width</a> </li>
<li><a href="/about/drc_ref_global.xml#with_holes">with_holes</a> </li>
</ul> </ul>
</p><p> </p><p>
The following documentation will list the methods available for DRC expression objects. The following documentation will list the methods available for DRC expression objects.
@ -921,6 +922,22 @@ out = in.drc(primary.squares) # equivalent
This method acts on edge expressions and delivers a specific part of each edge. This method acts on edge expressions and delivers a specific part of each edge.
See <a href="/about/drc_ref_layer.xml#start_segments">layer#start_segments</a> for details about this functionality. See <a href="/about/drc_ref_layer.xml#start_segments">layer#start_segments</a> for details about this functionality.
</p> </p>
<a name="with_holes"/><h2>"with_holes" - Selects all input polygons with the specified number of holes</h2>
<keyword name="with_holes"/>
<p>Usage:</p>
<ul>
<li><tt>expression.with_holes (in condition)</tt></li>
</ul>
<p>
This operation can be used as a plain function in which case it acts on primary
shapes or can be used as method on another DRC expression.
The following example selects all polygons with more than 2 holes:
</p><p>
<pre>
out = in.drc(with_holes &gt; 2)
out = in.drc(primary.with_holes &gt; 2) # equivalent
</pre>
</p>
<a name="|"/><h2>"|" - Boolean OR between the results of two expressions</h2> <a name="|"/><h2>"|" - Boolean OR between the results of two expressions</h2>
<keyword name="|"/> <keyword name="|"/>
<p>Usage:</p> <p>Usage:</p>

View File

@ -738,7 +738,7 @@ This function will evaluate the conditions c1 to cn and return the
current primary shape if all conditions renders an empty result. current primary shape if all conditions renders an empty result.
See <a href="#if_all">if_all</a> for an example how to use the if_... functions. See <a href="#if_all">if_all</a> for an example how to use the if_... functions.
</p> </p>
<a name="info"/><h2>"info" - Outputs as message to the logger window</h2> <a name="info"/><h2>"info" - Outputs as message to the logger or progress window</h2>
<keyword name="info"/> <keyword name="info"/>
<p>Usage:</p> <p>Usage:</p>
<ul> <ul>
@ -747,7 +747,7 @@ See <a href="#if_all">if_all</a> for an example how to use the if_... functions.
</ul> </ul>
<p> <p>
Prints the message to the log window in verbose mode. Prints the message to the log window in verbose mode.
In non-verbose more, nothing is printed. In non-verbose more, nothing is printed but a statement is put into the progress window.
<a href="#log">log</a> is a function that always prints a message. <a href="#log">log</a> is a function that always prints a message.
</p> </p>
<a name="input"/><h2>"input" - Fetches the shapes from the specified input from the default source</h2> <a name="input"/><h2>"input" - Fetches the shapes from the specified input from the default source</h2>
@ -1775,6 +1775,15 @@ In verbose mode, more output is generated in the log file
<p> <p>
In verbose mode, more output is generated in the log file In verbose mode, more output is generated in the log file
</p> </p>
<a name="warn"/><h2>"warn" - Prints a warning</h2>
<keyword name="warn"/>
<p>Usage:</p>
<ul>
<li><tt>warn(message)</tt></li>
</ul>
<p>
Similar to <a href="#log">log</a>, but the message is printed formatted as a warning
</p>
<a name="width"/><h2>"width" - Performs a width check</h2> <a name="width"/><h2>"width" - Performs a width check</h2>
<keyword name="width"/> <keyword name="width"/>
<p>Usage:</p> <p>Usage:</p>
@ -1847,6 +1856,17 @@ shape.
</tr> </tr>
</table> </table>
</p> </p>
<a name="with_holes"/><h2>"with_holes" - Selects all input polygons according to their number of holes in DRC expressions</h2>
<keyword name="with_holes"/>
<p>Usage:</p>
<ul>
<li><tt>with_holes (in condition)</tt></li>
</ul>
<p>
"with_holes" represents a polygon selector for
<a href="/about/drc_ref_drc.xml">DRC</a> expressions selecting polygons of the primary by their number of holes
(see <a href="/about/drc_ref_layer.xml#drc">Layer#drc</a> and <a href="/about/drc_ref_drc.xml#with_holes">DRC#with_holes</a> for more details).
</p>
<a name="write_spice"/><h2>"write_spice" - Defines SPICE output format (with options)</h2> <a name="write_spice"/><h2>"write_spice" - Defines SPICE output format (with options)</h2>
<keyword name="write_spice"/> <keyword name="write_spice"/>
<p>Usage:</p> <p>Usage:</p>

View File

@ -247,8 +247,8 @@ deliver objects that can be converted into polygons. Such objects are of class <
<p>Usage:</p> <p>Usage:</p>
<ul> <ul>
<li><tt>layer.corners([ options ])</tt></li> <li><tt>layer.corners([ options ])</tt></li>
<li><tt>layer.corners(angle, [ options ])</tt></li> <li><tt>layer.corners(angle [, options ])</tt></li>
<li><tt>layer.corners(amin .. amax, [ options ])</tt></li> <li><tt>layer.corners(amin .. amax [, options ])</tt></li>
</ul> </ul>
<p> <p>
This method produces markers on the corners of the polygons. An angle criterion can be given which This method produces markers on the corners of the polygons. An angle criterion can be given which
@ -2659,6 +2659,87 @@ The following image shows the effect of the space check:
</tr> </tr>
</table> </table>
</p> </p>
<a name="split_covering"/><h2>"split_covering" - Returns the results of <a href="#covering">covering</a> and <a href="#not_covering">not_covering</a> at the same time</h2>
<keyword name="split_covering"/>
<p>Usage:</p>
<ul>
<li><tt>(a, b) = layer.split_covering(other [, options ])</tt></li>
</ul>
<p>
This method returns the polygons covering polygons from the other layer in
one layer and all others in a second layer. This method is equivalent to calling
<a href="#covering">covering</a> and <a href="#not_covering">not_covering</a>, but is faster than doing this in separate steps:
</p><p>
<pre>
(covering, not_covering) = l1.split_covering(l2)
</pre>
</p><p>
The options of this method are the same than <a href="#covering">covering</a>.
</p>
<a name="split_inside"/><h2>"split_inside" - Returns the results of <a href="#inside">inside</a> and <a href="#not_inside">not_inside</a> at the same time</h2>
<keyword name="split_inside"/>
<p>Usage:</p>
<ul>
<li><tt>(a, b) = layer.split_inside(other)</tt></li>
</ul>
<p>
This method returns the polygons inside of polygons from the other layer in
one layer and all others in a second layer. This method is equivalent to calling
<a href="#inside">inside</a> and <a href="#not_inside">not_inside</a>, but is faster than doing this in separate steps:
</p><p>
<pre>
(inside, not_inside) = l1.split_inside(l2)
</pre>
</p>
<a name="split_interacting"/><h2>"split_interacting" - Returns the results of <a href="#interacting">interacting</a> and <a href="#not_interacting">not_interacting</a> at the same time</h2>
<keyword name="split_interacting"/>
<p>Usage:</p>
<ul>
<li><tt>(a, b) = layer.split_interacting(other [, options ])</tt></li>
</ul>
<p>
This method returns the polygons interacting with objects from the other container in
one layer and all others in a second layer. This method is equivalent to calling
<a href="#interacting">interacting</a> and <a href="#not_interacting">not_interacting</a>, but is faster than doing this in separate steps:
</p><p>
<pre>
(interacting, not_interacting) = l1.split_interacting(l2)
</pre>
</p><p>
The options of this method are the same than <a href="#interacting">interacting</a>.
</p>
<a name="split_outside"/><h2>"split_outside" - Returns the results of <a href="#outside">outside</a> and <a href="#not_outside">not_outside</a> at the same time</h2>
<keyword name="split_outside"/>
<p>Usage:</p>
<ul>
<li><tt>(a, b) = layer.split_outside(other)</tt></li>
</ul>
<p>
This method returns the polygons outside of polygons from the other layer in
one layer and all others in a second layer. This method is equivalent to calling
<a href="#outside">outside</a> and <a href="#not_outside">not_outside</a>, but is faster than doing this in separate steps:
</p><p>
<pre>
(outside, not_outside) = l1.split_outside(l2)
</pre>
</p>
<a name="split_overlapping"/><h2>"split_overlapping" - Returns the results of <a href="#overlapping">overlapping</a> and <a href="#not_overlapping">not_overlapping</a> at the same time</h2>
<keyword name="split_overlapping"/>
<p>Usage:</p>
<ul>
<li><tt>(a, b) = layer.split_overlapping(other [, options ])</tt></li>
</ul>
<p>
This method returns the polygons overlapping polygons from the other layer in
one layer and all others in a second layer. This method is equivalent to calling
<a href="#overlapping">overlapping</a> and <a href="#not_overlapping">not_overlapping</a>, but is faster than doing this in separate steps:
</p><p>
<pre>
(overlapping, not_overlapping) = l1.split_overlapping(l2)
</pre>
</p><p>
The options of this method are the same than <a href="#overlapping">overlapping</a>.
</p>
<a name="squares"/><h2>"squares" - Selects all squares from the input</h2> <a name="squares"/><h2>"squares" - Selects all squares from the input</h2>
<keyword name="squares"/> <keyword name="squares"/>
<p>Usage:</p> <p>Usage:</p>
@ -3074,6 +3155,86 @@ bounding box.
</p><p> </p><p>
This method is available for polygon layers only. This method is available for polygon layers only.
</p> </p>
<a name="with_density"/><h2>"with_density" - Returns tiles whose density is within a given range</h2>
<keyword name="with_density"/>
<p>Usage:</p>
<ul>
<li><tt>layer.with_density(min_value, max_value [, options ])</tt></li>
<li><tt>layer.with_density(min_value .. max_value [, options ])</tt></li>
</ul>
<p>
This method runs a tiled analysis over the current layout. It reports the tiles whose density
is between "min_value" and "max_value". "min_value" and "max_value" are given in
relative units, i.e. within the range of 0 to 1.0 corresponding to a density of 0 to 100%.
</p><p>
"min_value" or "max_value" can be nil or omitted in the ".." range notation.
In this case, they are taken as "0" and "100%".
</p><p>
The tile size must be specified with the "tile_size" option:
</p><p>
<pre>
# reports areas where layer 1/0 density is below 10% on 20x20 um tiles
low_density = input(1, 0).density(0.0 .. 0.1, tile_size(20.um))
</pre>
</p><p>
Anisotropic tiles can be specified by giving two values, like "tile_size(10.um, 20.um)".
The first value is the horizontal tile dimension, the second value is the vertical tile
dimension.
</p><p>
A tile overlap can be specified using "tile_step". If the tile step is less than the
tile size, the tiles will overlap. The layout window given by "tile_size" is moved
in increments of the tile step:
</p><p>
<pre>
# reports areas where layer 1/0 density is below 10% on 30x30 um tiles
# with a tile step of 20x20 um:
low_density = input(1, 0).density(0.0 .. 0.1, tile_size(30.um), tile_step(20.um))
</pre>
</p><p>
For "tile_step", anisotropic values can be given as well by using two values: the first for the
horizontal and the second for the vertical tile step.
</p><p>
Another option is "tile_origin" which specifies the location of the first tile's position.
This is the lower left tile's lower left corner. If no origin is given, the tiles are centered over the
area investigated.
</p><p>
By default, the tiles will cover the bounding box of the input layer. A separate layer
can be used in addition. This way, the layout's dimensions can be derived from some
drawn boundary layer. To specify a separate, additional layer included in the bounding box, use the "tile_boundary" option:
</p><p>
<pre>
# reports density of layer 1/0 below 10% on 20x20 um tiles. The layout's boundary is taken from
# layer 0/0:
cell_frame = input(0, 0)
low_density = input(1, 0).density(0.0 .. 0.1, tile_size(20.um), tile_boundary(cell_frame))
</pre>
</p><p>
Note that the layer given in "tile_boundary" adds to the input layer for computing the bounding box.
The computed area is at least the area of the input layer.
</p><p>
Computation of the area can be skipped by explicitly giving a tile count in horizontal and vertical
direction. With the "tile_origin" option this allows full control over the area covered:
</p><p>
<pre>
# reports density of layer 1/0 below 10% on 20x20 um tiles in the region 0,0 .. 2000,3000
# (100 and 150 tiles of 20 um each are used in horizontal and vertical direction):
low_density = input(1, 0).density(0.0 .. 0.1, tile_size(20.um), tile_origin(0.0, 0.0), tile_count(100, 150))
</pre>
</p><p>
The complementary version of "with_density" is <a href="#without_density">without_density</a>.
</p>
<a name="with_holes"/><h2>"with_holes" - Selects all polygons with the specified number of holes</h2>
<keyword name="with_holes"/>
<p>Usage:</p>
<ul>
<li><tt>layer.with_holes(count)</tt></li>
<li><tt>layer.with_holes(min_count, max_count)</tt></li>
<li><tt>layer.with_holes(min_count .. max_count)</tt></li>
</ul>
<p>
This method is available for polygon layers. It will select all polygons from the input layer
which have the specified number of holes.
</p>
<a name="with_length"/><h2>"with_length" - Selects edges by their length</h2> <a name="with_length"/><h2>"with_length" - Selects edges by their length</h2>
<keyword name="with_length"/> <keyword name="with_length"/>
<p>Usage:</p> <p>Usage:</p>
@ -3228,6 +3389,29 @@ bounding box.
</p><p> </p><p>
This method is available for polygon layers only. This method is available for polygon layers only.
</p> </p>
<a name="without_density"/><h2>"without_density" - Returns tiles whose density is not within a given range</h2>
<keyword name="without_density"/>
<p>Usage:</p>
<ul>
<li><tt>layer.without_density(min_value, max_value [, options ])</tt></li>
<li><tt>layer.without_density(min_value .. max_value [, options ])</tt></li>
</ul>
<p>
For details about the operations and the operation see <a href="#with_density">with_density</a>. This version will return the
tiles where the density is not within the given range.
</p>
<a name="without_holes"/><h2>"without_holes" - Selects all polygons with the specified number of holes</h2>
<keyword name="without_holes"/>
<p>Usage:</p>
<ul>
<li><tt>layer.without_holes(count)</tt></li>
<li><tt>layer.without_holes(min_count, max_count)</tt></li>
<li><tt>layer.without_holes(min_count .. max_count)</tt></li>
</ul>
<p>
This method is available for polygon layers. It will select all polygons from the input layer
which do not have the specified number of holes.
</p>
<a name="without_length"/><h2>"without_length" - Selects edges by the their length</h2> <a name="without_length"/><h2>"without_length" - Selects edges by the their length</h2>
<keyword name="without_length"/> <keyword name="without_length"/>
<p>Usage:</p> <p>Usage:</p>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.0 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.0 KiB

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 KiB

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.3 KiB

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.6 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.3 KiB

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

Some files were not shown because too many files have changed in this diff Show More