Merge branch 'drc-enhancements', remote-tracking branch 'origin' into lvs-debug
|
|
@ -378,28 +378,77 @@ AsIfFlatRegion::processed_to_edge_pairs (const PolygonToEdgePairProcessorBase &f
|
|||
return new_edge_pairs.release ();
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
AsIfFlatRegion::selected_interacting_generic (const Edges &other, bool inverse, size_t min_count, size_t max_count) const
|
||||
namespace {
|
||||
|
||||
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);
|
||||
|
||||
if (max_count < min_count || other.empty ()) {
|
||||
if (! inverse) {
|
||||
return new EmptyRegion ();
|
||||
// shortcut
|
||||
if (empty ()) {
|
||||
if (output_mode == Positive || output_mode == Negative) {
|
||||
return std::make_pair (clone (), (RegionDelegate *) 0);
|
||||
} 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 ());
|
||||
|
||||
#if defined(USE_LOCAL_PROCESSOR)
|
||||
|
||||
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;
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
|
|
@ -413,71 +462,42 @@ AsIfFlatRegion::selected_interacting_generic (const Edges &other, bool inverse,
|
|||
std::vector<db::Shapes *> results;
|
||||
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 ();
|
||||
|
||||
#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
|
||||
return oph.region_pair ();
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
AsIfFlatRegion::selected_interacting_generic (const Texts &other, bool inverse, size_t min_count, size_t max_count) const
|
||||
std::pair<RegionDelegate *, RegionDelegate *>
|
||||
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 (! inverse) {
|
||||
return new EmptyRegion ();
|
||||
} else {
|
||||
return clone ();
|
||||
}
|
||||
} else if (empty ()) {
|
||||
return clone ();
|
||||
if (output_mode == None) {
|
||||
return oph.region_pair ();
|
||||
}
|
||||
|
||||
#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::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;
|
||||
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;
|
||||
others.push_back (other.begin ());
|
||||
|
||||
std::unique_ptr<FlatRegion> output (new FlatRegion (merged_semantics ()));
|
||||
std::vector<db::Shapes *> results;
|
||||
results.push_back (&output->raw_polygons ());
|
||||
proc.run_flat (polygons, others, std::vector<bool> (), &op, oph.results ());
|
||||
|
||||
proc.run_flat (polygons, others, std::vector<bool> (), &op, results);
|
||||
|
||||
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
|
||||
return oph.region_pair ();
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
// shortcut
|
||||
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 ()) {
|
||||
// clear, if b is empty and
|
||||
// * mode is inside, enclosing or interacting and inverse is false ("inside" or "interacting")
|
||||
// * mode is outside and inverse is true ("not outside")
|
||||
if ((mode <= 0) != inverse) {
|
||||
return new EmptyRegion ();
|
||||
if ((mode <= 0)) {
|
||||
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 {
|
||||
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 ());
|
||||
|
||||
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;
|
||||
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;
|
||||
others.push_back ((mode < 0 || counting) ? other.begin_merged () : other.begin ());
|
||||
|
||||
std::unique_ptr<FlatRegion> output (new FlatRegion (merged_semantics ()));
|
||||
std::vector<db::Shapes *> results;
|
||||
results.push_back (&output->raw_polygons ());
|
||||
proc.run_flat (polygons, others, std::vector<bool> (), &op, oph.results ());
|
||||
|
||||
proc.run_flat (polygons, others, std::vector<bool> (), &op, results);
|
||||
|
||||
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
|
||||
return oph.region_pair ();
|
||||
}
|
||||
|
||||
EdgesDelegate *
|
||||
|
|
|
|||
|
|
@ -139,72 +139,107 @@ public:
|
|||
|
||||
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
|
||||
{
|
||||
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
|
||||
{
|
||||
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
|
||||
{
|
||||
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
|
||||
{
|
||||
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
|
||||
{
|
||||
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
|
||||
{
|
||||
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
|
||||
{
|
||||
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
|
||||
{
|
||||
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
|
||||
{
|
||||
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
|
||||
{
|
||||
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
|
||||
{
|
||||
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
|
||||
{
|
||||
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
|
||||
{
|
||||
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
|
||||
|
|
@ -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_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 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 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 Region &other, int mode, bool touching, InteractingOutputMode output_mode, 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 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 EdgesDelegate *pull_generic (const Edges &other) const;
|
||||
virtual TextsDelegate *pull_generic (const Texts &other) const;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
: 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 ..
|
||||
}
|
||||
|
||||
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 ..
|
||||
}
|
||||
|
|
@ -1080,7 +1080,7 @@ CompoundRegionInteractOperationNode::generated_description () const
|
|||
// ---------------------------------------------------------------------------------------------
|
||||
|
||||
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 ..
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 { }
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -1519,9 +1519,67 @@ DeepRegion::run_single_polygon_check (db::edge_relation_type rel, db::Coord d, c
|
|||
return res.release ();
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
DeepRegion::selected_interacting_generic (const Region &other, int mode, bool touching, bool inverse, size_t min_count, size_t max_count) const
|
||||
namespace
|
||||
{
|
||||
|
||||
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 ());
|
||||
|
||||
// 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
|
||||
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, inverse, min_count, max_count, true);
|
||||
db::InteractingLocalOperation op (mode, touching, output_mode, min_count, max_count, true);
|
||||
|
||||
db::local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_polygons.layout (), &other_polygons.initial_cell (), polygons.breakout_cells (), other_polygons.breakout_cells ());
|
||||
proc.set_description (progress_desc ());
|
||||
|
|
@ -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.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);
|
||||
if (! split_after && ((mode < 0 && other.merged_semantics ()) || other.is_merged ()) && (merged_semantics () || is_merged ())) {
|
||||
res->set_is_merged (true);
|
||||
}
|
||||
return res;
|
||||
proc.run (&op, polygons.layer (), other_polygons.layer (), orh.layers ());
|
||||
|
||||
return orh.result_pair ();
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
DeepRegion::selected_interacting_generic (const Edges &other, bool inverse, size_t min_count, size_t max_count) const
|
||||
std::pair<RegionDelegate *, RegionDelegate *>
|
||||
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 ());
|
||||
|
||||
|
|
@ -1580,9 +1635,7 @@ DeepRegion::selected_interacting_generic (const Edges &other, bool inverse, size
|
|||
|
||||
const db::DeepLayer &polygons = merged_deep_layer ();
|
||||
|
||||
DeepLayer dl_out (polygons.derived ());
|
||||
|
||||
db::InteractingWithEdgeLocalOperation op (inverse, min_count, max_count, true);
|
||||
db::InteractingWithEdgeLocalOperation op (output_mode, min_count, max_count, true);
|
||||
|
||||
db::local_processor<db::PolygonRef, db::Edge, db::PolygonRef> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell (), polygons.breakout_cells (), other_deep->deep_layer ().breakout_cells ());
|
||||
proc.set_description (progress_desc ());
|
||||
|
|
@ -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.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);
|
||||
if (! split_after) {
|
||||
res->set_is_merged (other.is_merged () && (merged_semantics () || is_merged ()));
|
||||
}
|
||||
return res;
|
||||
proc.run (&op, polygons.layer (), counting ? other_deep->merged_deep_layer ().layer () : other_deep->deep_layer ().layer (), orh.layers ());
|
||||
|
||||
return orh.result_pair ();
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
|
|
@ -1706,8 +1758,9 @@ DeepRegion::pull_generic (const Texts &other) const
|
|||
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.
|
||||
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 ();
|
||||
|
||||
DeepLayer dl_out (polygons.derived ());
|
||||
|
||||
db::InteractingWithTextLocalOperation op (inverse, min_count, max_count);
|
||||
db::InteractingWithTextLocalOperation op (output_mode, min_count, max_count);
|
||||
|
||||
db::local_processor<db::PolygonRef, db::TextRef, db::PolygonRef> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell (), polygons.breakout_cells (), other_deep->deep_layer ().breakout_cells ());
|
||||
proc.set_description (progress_desc ());
|
||||
|
|
@ -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.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);
|
||||
if (! split_after) {
|
||||
res->set_is_merged (merged_semantics () || is_merged ());
|
||||
}
|
||||
return res;
|
||||
proc.run (&op, polygons.layer (), other_deep->deep_layer ().layer (), orh.layers ());
|
||||
|
||||
return orh.result_pair ();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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_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 RegionDelegate *selected_interacting_generic (const Edges &other, bool inverse, 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 Region &other, int mode, bool touching, InteractingOutputMode output_mode, 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 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 EdgesDelegate *pull_generic (const Edges &other) const;
|
||||
virtual TextsDelegate *pull_generic (const Texts &other) const;
|
||||
|
|
|
|||
|
|
@ -108,18 +108,25 @@ public:
|
|||
|
||||
virtual RegionDelegate *selected_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_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_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_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_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_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_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_interacting (const Region &) const { return new EmptyRegion (); }
|
||||
virtual EdgesDelegate *pull_interacting (const Edges &) const { return new EmptyEdges (); }
|
||||
|
|
|
|||
|
|
@ -1280,6 +1280,14 @@ void local_processor<TS, TI, TR>::run (local_operation<TS, TI, TR> *op, unsigned
|
|||
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>
|
||||
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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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 *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, 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 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;
|
||||
|
|
|
|||
|
|
@ -54,6 +54,11 @@ enum OnEmptyIntruderHint {
|
|||
*/
|
||||
Copy,
|
||||
|
||||
/**
|
||||
* @brief Copy the subject shape to the second result
|
||||
*/
|
||||
CopyToSecond,
|
||||
|
||||
/**
|
||||
* @brief Drop the subject shape
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -725,7 +725,7 @@ template DB_PUBLIC void split_polygon<> (const db::DSimplePolygon &polygon, std:
|
|||
// Smoothing tools
|
||||
|
||||
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.reserve (std::distance (from, to));
|
||||
|
|
@ -781,7 +781,9 @@ smooth_contour (db::Polygon::polygon_contour_iterator from, db::Polygon::polygon
|
|||
|
||||
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
|
||||
can_drop = true;
|
||||
} 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
|
||||
smooth (const db::Polygon &polygon, db::Coord d)
|
||||
smooth (const db::Polygon &polygon, db::Coord d, bool keep_hv)
|
||||
{
|
||||
db::Polygon new_poly;
|
||||
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) {
|
||||
|
||||
new_poly.assign_hull (new_pts.begin (), new_pts.end (), false /*don't compress*/);
|
||||
|
||||
for (unsigned int h = 0; h < polygon.holes (); ++h) {
|
||||
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) {
|
||||
new_poly.insert_hole (new_pts.begin (), new_pts.end (), false /*don't compress*/);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
#define KLAYOUT_SMOOTH_HAS_KEEP_HV 1
|
||||
|
||||
/**
|
||||
* @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 new_pts The points that make up the new contour
|
||||
* @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)
|
||||
*/
|
||||
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"
|
||||
|
|
|
|||
|
|
@ -263,15 +263,15 @@ Region::rounded_corners (double rinner, double router, unsigned int n) const
|
|||
}
|
||||
|
||||
void
|
||||
Region::smooth (coord_type d)
|
||||
Region::smooth (coord_type d, bool keep_hv)
|
||||
{
|
||||
process (SmoothingProcessor (d));
|
||||
process (SmoothingProcessor (d, keep_hv));
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -267,6 +267,16 @@ public:
|
|||
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
|
||||
*
|
||||
|
|
@ -1132,6 +1142,19 @@ public:
|
|||
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
|
||||
*
|
||||
|
|
@ -1178,6 +1201,19 @@ public:
|
|||
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
|
||||
*
|
||||
|
|
@ -1224,6 +1260,19 @@ public:
|
|||
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
|
||||
*
|
||||
|
|
@ -1278,6 +1327,19 @@ public:
|
|||
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
|
||||
*
|
||||
|
|
@ -1324,6 +1386,19 @@ public:
|
|||
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
|
||||
*
|
||||
|
|
@ -1370,6 +1445,19 @@ public:
|
|||
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
|
||||
*
|
||||
|
|
@ -1416,6 +1504,19 @@ public:
|
|||
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
|
||||
*
|
||||
|
|
@ -1518,14 +1619,14 @@ public:
|
|||
/**
|
||||
* @brief Smoothes the region (in-place)
|
||||
*/
|
||||
void smooth (coord_type d);
|
||||
void smooth (coord_type d, bool keep_hv);
|
||||
|
||||
/**
|
||||
* @brief Returns the smoothed region
|
||||
*
|
||||
* @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
|
||||
|
|
|
|||
|
|
@ -281,18 +281,25 @@ public:
|
|||
|
||||
virtual RegionDelegate *selected_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_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_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_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_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_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_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_interacting (const Region &other) const = 0;
|
||||
virtual EdgesDelegate *pull_interacting (const Edges &other) const = 0;
|
||||
|
|
|
|||
|
|
@ -537,8 +537,8 @@ private:
|
|||
}
|
||||
|
||||
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)
|
||||
: 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)
|
||||
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_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 ..
|
||||
}
|
||||
|
|
@ -552,8 +552,13 @@ db::Coord interacting_local_operation<TS, TI, TR>::dist () const
|
|||
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
|
||||
{
|
||||
tl_assert (results.size () == 1);
|
||||
std::unordered_set<TR> &result = results.front ();
|
||||
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);
|
||||
}
|
||||
|
||||
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 ()) {
|
||||
count = c->second;
|
||||
}
|
||||
if ((count >= m_min_count && count <= m_max_count) != m_inverse) {
|
||||
const TS &subject = interactions.subject_shape (i->first);
|
||||
result.insert (subject);
|
||||
bool good = (count >= m_min_count && count <= m_max_count);
|
||||
if (good) {
|
||||
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
|
||||
interacting_local_operation<TS, TI, TR>::on_empty_intruder_hint () const
|
||||
{
|
||||
if ((m_mode <= 0) != m_inverse) {
|
||||
return OnEmptyIntruderHint::Drop;
|
||||
if ((m_mode <= 0)) {
|
||||
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 {
|
||||
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>
|
||||
|
|
@ -761,8 +789,8 @@ template class DB_PUBLIC pull_local_operation<db::Polygon, db::Polygon, db::Poly
|
|||
// ---------------------------------------------------------------------------------------------------------------
|
||||
|
||||
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)
|
||||
: 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)
|
||||
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_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 ..
|
||||
}
|
||||
|
|
@ -777,6 +805,14 @@ db::Coord interacting_with_edge_local_operation<TS, TI, TR>::dist () const
|
|||
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
|
||||
{
|
||||
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;
|
||||
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);
|
||||
|
||||
scanner.insert1 (addressable, 0);
|
||||
if (m_inverse) {
|
||||
if (m_output_mode == Negative || m_output_mode == PositiveAndNegative) {
|
||||
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
|
||||
|
||||
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) {
|
||||
bool hit = r->second >= m_min_count && r->second <= m_max_count;
|
||||
if (hit != m_inverse) {
|
||||
result.insert (r->first);
|
||||
if (hit) {
|
||||
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>
|
||||
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;
|
||||
} else {
|
||||
} else if (m_output_mode == Negative) {
|
||||
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>
|
||||
interacting_with_text_local_operation<TS, TI, TR>::interacting_with_text_local_operation (bool inverse, 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)
|
||||
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_output_mode (output_mode), m_min_count (std::max (size_t (1), min_count)), m_max_count (max_count)
|
||||
{
|
||||
// .. 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>
|
||||
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;
|
||||
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);
|
||||
|
||||
scanner.insert1 (addressable, 0);
|
||||
if (m_inverse) {
|
||||
if (m_output_mode == Negative || m_output_mode == PositiveAndNegative) {
|
||||
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
|
||||
|
||||
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) {
|
||||
bool hit = r->second >= m_min_count && r->second <= m_max_count;
|
||||
if (hit != m_inverse) {
|
||||
result.insert (r->first);
|
||||
if (hit) {
|
||||
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>
|
||||
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;
|
||||
} else {
|
||||
} else if (m_output_mode == Negative) {
|
||||
return OnEmptyIntruderHint::Copy;
|
||||
} else if (m_output_mode == PositiveAndNegative) {
|
||||
return OnEmptyIntruderHint::CopyToSecond;
|
||||
} else {
|
||||
return OnEmptyIntruderHint::Ignore;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -222,12 +222,16 @@ private:
|
|||
|
||||
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>
|
||||
class interacting_local_operation
|
||||
: public local_operation<TS, TI, TR>
|
||||
{
|
||||
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 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:
|
||||
int m_mode;
|
||||
bool m_touching;
|
||||
bool m_inverse;
|
||||
InteractingOutputMode m_output_mode;
|
||||
size_t m_min_count, m_max_count;
|
||||
bool m_other_is_merged;
|
||||
};
|
||||
|
|
@ -268,7 +272,7 @@ class interacting_with_edge_local_operation
|
|||
: public local_operation<TS, TI, TR>
|
||||
{
|
||||
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 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;
|
||||
|
||||
private:
|
||||
bool m_inverse;
|
||||
InteractingOutputMode m_output_mode;
|
||||
size_t m_min_count, m_max_count;
|
||||
bool m_other_is_merged;
|
||||
};
|
||||
|
|
@ -303,7 +307,7 @@ class interacting_with_text_local_operation
|
|||
: public local_operation<TS, TI, TR>
|
||||
{
|
||||
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 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;
|
||||
|
||||
private:
|
||||
bool m_inverse;
|
||||
InteractingOutputMode m_output_mode;
|
||||
size_t m_min_count, m_max_count;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -868,14 +868,14 @@ StrangePolygonCheckProcessor::process (const db::Polygon &poly, std::vector<db::
|
|||
// -------------------------------------------------------------------------------------------------------------
|
||||
// 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 () { }
|
||||
|
||||
void
|
||||
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));
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -504,7 +504,7 @@ class DB_PUBLIC SmoothingProcessor
|
|||
: public PolygonProcessorBase
|
||||
{
|
||||
public:
|
||||
SmoothingProcessor (db::Coord d);
|
||||
SmoothingProcessor (db::Coord d, bool keep_hv);
|
||||
~SmoothingProcessor ();
|
||||
|
||||
virtual void process (const db::Polygon &poly, std::vector<db::Polygon> &res) const;
|
||||
|
|
@ -517,6 +517,7 @@ public:
|
|||
|
||||
private:
|
||||
db::Coord m_d;
|
||||
bool m_keep_hv;
|
||||
db::MagnificationReducer m_vars;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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*/);
|
||||
}
|
||||
|
||||
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");
|
||||
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)
|
||||
|
|
@ -572,9 +572,10 @@ Class<db::CompoundRegionOperationNode> decl_CompoundRegionOperationNode ("db", "
|
|||
"@brief Creates a node extracting strange polygons.\n"
|
||||
"'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"
|
||||
"@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"),
|
||||
"@brief Creates a node generating rounded corners.\n"
|
||||
|
|
|
|||
|
|
@ -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*/);
|
||||
}
|
||||
|
||||
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)
|
||||
|
|
@ -1787,17 +1787,18 @@ Class<db::Polygon> decl_Polygon ("db", "Polygon",
|
|||
"\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"
|
||||
"\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"
|
||||
"\n"
|
||||
"@param d The smoothing \"roughness\".\n"
|
||||
"@param keep_hv If true, horizontal and vertical edges will be preserved always.\n"
|
||||
"\n"
|
||||
"@return The smoothed polygon.\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"),
|
||||
"@brief Computes the Minkowsky sum of the polygon and an edge\n"
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
std::pair<db::Region, db::Region> rp = r->andnot (other);
|
||||
return as_2region_vector (r->andnot (other));
|
||||
}
|
||||
|
||||
std::vector<db::Region> res;
|
||||
res.resize (2, db::Region ());
|
||||
res [0] = rp.first;
|
||||
res [1] = rp.second;
|
||||
return res;
|
||||
static std::vector<db::Region> split_inside (const db::Region *r, const db::Region &other)
|
||||
{
|
||||
return as_2region_vector (r->selected_inside_differential (other));
|
||||
}
|
||||
|
||||
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>
|
||||
|
|
@ -681,6 +719,7 @@ int po_any ();
|
|||
|
||||
extern Class<db::ShapeCollection> decl_dbShapeCollection;
|
||||
|
||||
|
||||
Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
||||
constructor ("new", &new_v,
|
||||
"@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 not having the given perimeter 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_perimeter", with_perimeter2, gsi::arg ("min_perimeter"), gsi::arg ("max_perimeter"), gsi::arg ("inverse"),
|
||||
"@brief Filter the polygons by perimeter\n"
|
||||
|
|
@ -915,7 +954,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"If you don't want to specify a lower or upper limit, pass nil to that parameter.\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"),
|
||||
"@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 not having the given area 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_area", with_area2, gsi::arg ("min_area"), gsi::arg ("max_area"), gsi::arg ("inverse"),
|
||||
"@brief Filter the polygons by area\n"
|
||||
|
|
@ -935,7 +974,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"If you don't want to specify a lower or upper limit, pass nil to that parameter.\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"),
|
||||
"@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 not having the given of holes 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"
|
||||
"\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"
|
||||
"If you don't want to specify a lower or upper limit, pass nil to that parameter.\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"
|
||||
"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 does not have the given width 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_width", with_bbox_width2, gsi::arg ("min_width"), gsi::arg ("max_width"), gsi::arg ("inverse"),
|
||||
"@brief Filter the polygons by bounding box width\n"
|
||||
|
|
@ -977,7 +1016,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"If you don't want to specify a lower or upper limit, pass nil to that parameter.\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"),
|
||||
"@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 does not have the given height 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_height", with_bbox_height2, gsi::arg ("min_height"), gsi::arg ("max_height"), gsi::arg ("inverse"),
|
||||
"@brief Filter the polygons by bounding box height\n"
|
||||
|
|
@ -995,7 +1034,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"If you don't want to specify a lower or upper limit, pass nil to that parameter.\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"),
|
||||
"@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. "
|
||||
"If \"inverse\" is true, all polygons not matching this criterion are returned."
|
||||
"\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"),
|
||||
"@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"
|
||||
"If you don't want to specify a lower or upper limit, pass nil to that parameter.\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"),
|
||||
"@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. "
|
||||
"If \"inverse\" is true, all polygons not matching this criterion are returned."
|
||||
"\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"),
|
||||
"@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"
|
||||
"If you don't want to specify a lower or upper limit, pass nil to that parameter.\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"),
|
||||
"@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 true, all other polygons will be 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"
|
||||
"\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"
|
||||
"If you don't want to specify a lower or upper limit, pass nil to that parameter.\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"
|
||||
"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 true, all other polygons will be 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"
|
||||
"\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"
|
||||
"If you don't want to specify a lower or upper limit, pass nil to that parameter.\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"
|
||||
"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 true, all other polygons will be 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"
|
||||
"\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"
|
||||
"If you don't want to specify a lower or upper limit, pass nil to that parameter.\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"
|
||||
"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"
|
||||
"Strange parts of polygons are self-overlapping parts or non-orientable parts (i.e. in the \"8\" configuration).\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"),
|
||||
"@brief Returns the snapped region\n"
|
||||
|
|
@ -1143,7 +1182,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"If gx or gy is 0, no snapping happens in that direction.\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"),
|
||||
"@brief Returns the scaled and snapped region\n"
|
||||
|
|
@ -1159,7 +1198,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"If gx or gy is 0, the result is brought on a grid of 1.\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"
|
||||
"This method has been introduced in version 0.26.1."
|
||||
) +
|
||||
|
|
@ -1171,7 +1210,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"If gx or gy is 0 or less, the grid is not checked in that direction.\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"),
|
||||
"@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"
|
||||
"The edge pair objects returned will contain both edges forming the angle.\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"),
|
||||
"@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"
|
||||
"The edge pair objects returned will contain both edges forming the angle.\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"),
|
||||
"@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 "
|
||||
"of these boxes for example.\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"),
|
||||
"@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 "
|
||||
"of these boxes for example.\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"),
|
||||
"@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 "
|
||||
"of these boxes for example.\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,
|
||||
"@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 "
|
||||
"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"
|
||||
"@param d The smoothing tolerance (in database units)\n"
|
||||
"@param keep_hv If true, horizontal and vertical edges are maintained\n"
|
||||
"\n"
|
||||
"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 "
|
||||
|
|
@ -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 "
|
||||
"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"
|
||||
"@param d The smoothing tolerance (in database units)\n"
|
||||
"@param keep_hv If true, horizontal and vertical edges are maintained\n"
|
||||
"\n"
|
||||
"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."
|
||||
|
|
@ -1444,7 +1485,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"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"
|
||||
"\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"
|
||||
"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"
|
||||
|
|
@ -1466,7 +1507,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"This method is equivalent to \"size(d, d, mode)\".\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"),
|
||||
"@brief Isotropic sizing (biasing)\n"
|
||||
|
|
@ -1475,7 +1516,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"This method is equivalent to \"size(d, d, 2)\".\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"),
|
||||
"@brief Returns the anisotropically sized region\n"
|
||||
|
|
@ -1484,7 +1525,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"This method is returns the sized region (see \\size), but does not modify self.\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"),
|
||||
"@brief Returns the isotropically sized region\n"
|
||||
|
|
@ -1493,7 +1534,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"This method is returns the sized region (see \\size), but does not modify self.\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"),
|
||||
"@brief Isotropic sizing (biasing)\n"
|
||||
|
|
@ -1502,7 +1543,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"This method is equivalent to \"sized(d, d, 2)\".\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"),
|
||||
"@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"
|
||||
"@return A new region containing the polygons which are covering polygons from the other region\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"
|
||||
"This attribute is sometimes called 'enclosing' instead of 'covering', but this term is reserved for the respective DRC function.\n"
|
||||
"\n"
|
||||
|
|
@ -1610,18 +1651,28 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"@return A new region containing the polygons which are not covering polygons from the other region\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"
|
||||
"This attribute is sometimes called 'enclosing' instead of 'covering', but this term is reserved for the respective DRC function.\n"
|
||||
"\n"
|
||||
"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"),
|
||||
"@brief Selects the polygons of this region which are completely covering polygons from the other region\n"
|
||||
"\n"
|
||||
"@return The region after the polygons have been selected (self)\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"
|
||||
"This attribute is sometimes called 'enclosing' instead of 'covering', but this term is reserved for the respective DRC function.\n"
|
||||
"\n"
|
||||
|
|
@ -1632,7 +1683,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"@return The region after the polygons have been selected (self)\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"
|
||||
"This attribute is sometimes called 'enclosing' instead of 'covering', but this term is reserved for the respective DRC function.\n"
|
||||
"\n"
|
||||
|
|
@ -1643,56 +1694,76 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"@return A new region containing the polygons which are inside polygons from the other region\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"),
|
||||
"@brief Returns the polygons of this region which are not completely inside polygons from the other region\n"
|
||||
"\n"
|
||||
"@return A new region containing the polygons which are not inside polygons from the other region\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"),
|
||||
"@brief Selects the polygons of this region which are completely inside polygons from the other region\n"
|
||||
"\n"
|
||||
"@return The region after the polygons have been selected (self)\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"),
|
||||
"@brief Selects the polygons of this region which are not completely inside polygons from the other region\n"
|
||||
"\n"
|
||||
"@return The region after the polygons have been selected (self)\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"),
|
||||
"@brief Returns the polygons of this region which are completely outside polygons from the other region\n"
|
||||
"\n"
|
||||
"@return A new region containing the polygons which are outside polygons from the other region\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"),
|
||||
"@brief Returns the polygons of this region which are not completely outside polygons from the other region\n"
|
||||
"\n"
|
||||
"@return A new region containing the polygons which are not outside polygons from the other region\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"),
|
||||
"@brief Selects the polygons of this region which are completely outside polygons from the other region\n"
|
||||
"\n"
|
||||
"@return The region after the polygons have been selected (self)\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"),
|
||||
"@brief Selects the polygons of this region which are not completely outside polygons from the other region\n"
|
||||
"\n"
|
||||
"@return The region after the polygons have been selected (self)\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"),
|
||||
"@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"
|
||||
"@return A new region containing the polygons overlapping or touching polygons from the other region\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"
|
||||
"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"
|
||||
"@return A new region containing the polygons not overlapping or touching polygons from the other region\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"
|
||||
"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"),
|
||||
"@brief Selects the polygons from this region which overlap or touch polygons from the other region\n"
|
||||
"\n"
|
||||
|
|
@ -1732,7 +1813,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"@return The region after the polygons have been selected (self)\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"
|
||||
"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"
|
||||
"@return The region after the polygons have been selected (self)\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"
|
||||
"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"
|
||||
"@return A new region containing the polygons overlapping or touching edges from the edge collection\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"
|
||||
"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"
|
||||
|
|
@ -1775,11 +1856,21 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"@return A new region containing the polygons not overlapping or touching edges from the edge collection\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"
|
||||
"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"
|
||||
) +
|
||||
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"),
|
||||
"@brief Selects the polygons from this region which overlap or touch edges from the edge collection\n"
|
||||
"\n"
|
||||
|
|
@ -1790,7 +1881,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"@return The region after the polygons have been selected (self)\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"
|
||||
"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"
|
||||
|
|
@ -1805,7 +1896,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"@return The region after the polygons have been selected (self)\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"
|
||||
"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"
|
||||
|
|
@ -1820,7 +1911,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"@return A new region containing the polygons overlapping or touching texts\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"
|
||||
"This method has been introduced in version 0.27\n"
|
||||
) +
|
||||
|
|
@ -1834,10 +1925,20 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"@return A new region containing the polygons not overlapping or touching texts\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"
|
||||
"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"),
|
||||
"@brief Selects the polygons of this region which overlap or touch texts\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 "
|
||||
"(including max_count).\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"
|
||||
"This method has been introduced in version 0.27\n"
|
||||
) +
|
||||
|
|
@ -1862,7 +1963,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"@return The region after the polygons have been selected (self)\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"
|
||||
"This method has been introduced in version 0.27\n"
|
||||
) +
|
||||
|
|
@ -1871,7 +1972,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"@return A new region containing the polygons overlapping polygons from the other region\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"
|
||||
"The count options have been introduced in version 0.27."
|
||||
) +
|
||||
|
|
@ -1880,16 +1981,26 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"@return A new region containing the polygons not overlapping polygons from the other region\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"
|
||||
"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"),
|
||||
"@brief Selects the polygons from this region which overlap polygons from the other region\n"
|
||||
"\n"
|
||||
"@return The region after the polygons have been selected (self)\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"
|
||||
"The count options have been introduced in version 0.27."
|
||||
) +
|
||||
|
|
@ -1898,7 +2009,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"@return The region after the polygons have been selected (self)\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"
|
||||
"The count options have been introduced in version 0.27."
|
||||
) +
|
||||
|
|
@ -1911,7 +2022,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"@return The region after the polygons have been selected (from other)\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"
|
||||
"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"
|
||||
"@return The region after the polygons have been selected (from other)\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"
|
||||
"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"
|
||||
"@return The region after the polygons have been selected (from other)\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"
|
||||
"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"
|
||||
"@return The edge collection after the edges have been selected (from other)\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"
|
||||
"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"
|
||||
"@return The text collection after the texts have been selected (from other)\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"
|
||||
"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 "
|
||||
"possibilities of the edge collection.\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"),
|
||||
"@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"
|
||||
"This method returns all holes as filled polygons.\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 "
|
||||
"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"
|
||||
|
|
@ -2025,7 +2136,7 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"@brief Returns the hulls of the region\n"
|
||||
"This method returns all hulls as polygons. The holes will be removed (filles). "
|
||||
"\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 "
|
||||
"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"
|
||||
|
|
@ -2043,36 +2154,36 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
method_ext ("rectangles", &rectangles,
|
||||
"@brief Returns all polygons which are rectangles\n"
|
||||
"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,
|
||||
"@brief Returns all polygons which are not rectangles\n"
|
||||
"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,
|
||||
"@brief Returns all polygons which are squares\n"
|
||||
"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"
|
||||
"This method has been introduced in version 0.27.\n"
|
||||
) +
|
||||
method_ext ("non_squares", &non_squares,
|
||||
"@brief Returns all polygons which are not squares\n"
|
||||
"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"
|
||||
"This method has been introduced in version 0.27.\n"
|
||||
) +
|
||||
method_ext ("rectilinear", &rectilinear,
|
||||
"@brief Returns all polygons which are rectilinear\n"
|
||||
"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,
|
||||
"@brief Returns all polygons which are not rectilinear\n"
|
||||
"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),
|
||||
"@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"
|
||||
"\n"
|
||||
"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"),
|
||||
"@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"
|
||||
"\n"
|
||||
"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"),
|
||||
"@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"
|
||||
"\n"
|
||||
"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"),
|
||||
"@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"
|
||||
"\n"
|
||||
"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"),
|
||||
"@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 "
|
||||
"false. In general, this will improve performance somewhat.\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"
|
||||
"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. "
|
||||
"\"rect_filter\" allows suppressing specific error configurations on rectangular input figures.\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"
|
||||
"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 "
|
||||
"false. In general, this will improve performance somewhat.\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"
|
||||
"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. "
|
||||
"\"rect_filter\" allows suppressing specific error configurations on rectangular input figures.\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"
|
||||
"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. "
|
||||
"\"rect_filter\" allows suppressing specific error configurations on rectangular input figures.\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"
|
||||
"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. "
|
||||
"\"rect_filter\" allows suppressing specific error configurations on rectangular input figures.\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"
|
||||
"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. "
|
||||
"\"rect_filter\" allows suppressing specific error configurations on rectangular input figures.\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"
|
||||
"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. "
|
||||
"\"rect_filter\" allows suppressing specific error configurations on rectangular input figures.\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"
|
||||
"The 'shielded', 'negative', 'not_opposite' and 'rect_sides' options have been introduced in version 0.27."
|
||||
) +
|
||||
method_ext ("area", &area1,
|
||||
"@brief The area of the region\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"
|
||||
) +
|
||||
method_ext ("area", &area2, gsi::arg ("rect"),
|
||||
"@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"
|
||||
"\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"
|
||||
) +
|
||||
method_ext ("perimeter", &perimeter1,
|
||||
"@brief The total perimeter of the polygons\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"
|
||||
) +
|
||||
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 "
|
||||
"side toward the rectangle (in other words: outside edges must coincide with the rectangle's border in order to be counted).\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"
|
||||
) +
|
||||
method ("bbox", &db::Region::bbox,
|
||||
|
|
|
|||
|
|
@ -733,7 +733,8 @@ TEST(11_RoundAndSmoothed)
|
|||
r1_sized -= r1;
|
||||
|
||||
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;
|
||||
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 (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 (13, 0)), smoothed_keep_hv);
|
||||
|
||||
CHECKPOINT();
|
||||
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au11.gds");
|
||||
|
|
|
|||
|
|
@ -1188,8 +1188,8 @@ TEST(100)
|
|||
db::Polygon p;
|
||||
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, 20).to_string (), "(0,-100;0,0;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, true).to_string (), "(0,-100;0,0;150,0;150,-100)");
|
||||
}
|
||||
|
||||
// smoothing
|
||||
|
|
@ -1207,8 +1207,8 @@ TEST(101)
|
|||
db::Polygon p;
|
||||
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, 20).to_string (), "(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, true).to_string (), "(0,0;0,100;150,100;150,0)");
|
||||
}
|
||||
|
||||
// smoothing
|
||||
|
|
@ -1224,8 +1224,8 @@ TEST(102)
|
|||
db::Polygon p;
|
||||
p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0]));
|
||||
|
||||
EXPECT_EQ (smooth (p, 20).to_string (), "()");
|
||||
EXPECT_EQ (smooth (p, 5).to_string (), "(100,-10;150,0;0,0;50,10)");
|
||||
EXPECT_EQ (smooth (p, 20, true).to_string (), "()");
|
||||
EXPECT_EQ (smooth (p, 5, true).to_string (), "(100,-10;150,0;0,0;50,10)");
|
||||
}
|
||||
|
||||
// smoothing
|
||||
|
|
@ -1251,9 +1251,9 @@ TEST(103)
|
|||
db::Polygon p;
|
||||
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, 50).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, 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, true).to_string (), "(59881,-249925;56852,-237283;63152,-235686;69407,-233919;73105,-246382;69760,-247351)");
|
||||
EXPECT_EQ (smooth (p, 5000, true).to_string (), "(59881,-249925;56852,-237283;69407,-233919;73105,-246382)");
|
||||
}
|
||||
|
||||
// smoothing
|
||||
|
|
@ -1272,7 +1272,8 @@ TEST(104)
|
|||
db::Polygon p;
|
||||
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
|
||||
|
|
@ -1292,11 +1293,46 @@ TEST(105)
|
|||
db::Polygon p;
|
||||
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, 50).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, 90).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, 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, false).to_string (), "(0,0;0,1000;100,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, false).to_string (), "(0,0;100,1100;800,1100;800,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
|
||||
|
|
@ -1501,7 +1537,7 @@ TEST(203)
|
|||
in.push_back (pp);
|
||||
ep.simple_merge (in, out, false /*no cut line*/);
|
||||
pp = out.front ();
|
||||
pp = smooth (pp, 1);
|
||||
pp = smooth (pp, 1, true);
|
||||
|
||||
EXPECT_EQ (pp.hull ().size (), size_t (300));
|
||||
EXPECT_EQ (extract_rad (pp, rinner, router, n, &pr), true);
|
||||
|
|
@ -1547,7 +1583,7 @@ TEST(204)
|
|||
in.push_back (pp);
|
||||
ep.simple_merge (in, out, false /*no cut line*/);
|
||||
pp = out.front ();
|
||||
pp = smooth (pp, 1);
|
||||
pp = smooth (pp, 1, true);
|
||||
|
||||
EXPECT_EQ (pp.hull ().size (), size_t (200));
|
||||
EXPECT_EQ (extract_rad (pp, rinner, router, n, &pr), true);
|
||||
|
|
|
|||
|
|
@ -354,6 +354,8 @@ TEST(10a)
|
|||
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_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 (r.selected_interacting (db::Region (db::Box (db::Point (-200, -200), db::Point (-190, -190)))).to_string (), "");
|
||||
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);
|
||||
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_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).hier_count () + o.selected_not_outside (rr).hier_count (), size_t (6));
|
||||
o.select_not_outside (rr);
|
||||
|
|
@ -848,6 +852,8 @@ TEST(18a)
|
|||
EXPECT_EQ (o.to_string (), "(20,30;20,50;40,50;40,30)");
|
||||
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_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).hier_count () + o.selected_not_inside (rr).hier_count (), size_t (6));
|
||||
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);
|
||||
o = r;
|
||||
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).hier_count () + o.selected_not_interacting (rr).hier_count (), size_t (6));
|
||||
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);
|
||||
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_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).hier_count () + o.selected_not_overlapping (rr).hier_count (), size_t (6));
|
||||
o.select_not_overlapping (rr);
|
||||
|
|
@ -884,6 +894,8 @@ TEST(18a)
|
|||
EXPECT_EQ (o.to_string (), "(0,100;0,130;30,130;30,100)");
|
||||
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_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).hier_count () + o.selected_not_enclosing (rr).hier_count (), size_t (6));
|
||||
o.select_not_enclosing (rr);
|
||||
|
|
@ -1506,6 +1518,8 @@ TEST(30a)
|
|||
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_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 (r.selected_interacting (db::Edges (db::Edge (db::Point (-200, -200), db::Point (-190, -190)))).to_string (), "");
|
||||
db::Region rr = r;
|
||||
|
|
@ -1689,6 +1703,8 @@ TEST(34a)
|
|||
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_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;
|
||||
tt.insert (db::Text ("abc", db::Trans (db::Vector (30, 30))));
|
||||
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, 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_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, 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)");
|
||||
|
|
@ -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, 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_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, 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);
|
||||
|
|
@ -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, 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, 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)");
|
||||
|
|
@ -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, 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_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, 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);
|
||||
|
|
@ -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, 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, 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)");
|
||||
|
|
@ -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, 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_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, 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);
|
||||
|
|
|
|||
|
|
@ -739,16 +739,18 @@ CODE
|
|||
# %DRC%
|
||||
# @name smoothed
|
||||
# @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 plain function is equivalent to "primary.smoothed".
|
||||
|
||||
def smoothed(d)
|
||||
def smoothed(d, keep_hv = false)
|
||||
@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
|
||||
|
||||
|
|
|
|||
|
|
@ -48,6 +48,8 @@ module DRC
|
|||
@deep = false
|
||||
@netter = nil
|
||||
@netter_data = nil
|
||||
@total_timer = nil
|
||||
@drc_progress = nil
|
||||
|
||||
# initialize the defaults for max_area_ratio, max_vertex_count
|
||||
dss = RBA::DeepShapeStore::new
|
||||
|
|
@ -58,7 +60,7 @@ module DRC
|
|||
|
||||
@verbose = false
|
||||
|
||||
@in_context = false
|
||||
@in_context = nil
|
||||
|
||||
end
|
||||
|
||||
|
|
@ -93,7 +95,7 @@ module DRC
|
|||
def transparent
|
||||
DRCShielded::new(false)
|
||||
end
|
||||
|
||||
|
||||
def projection_limits(*args)
|
||||
self._context("projection_limits") do
|
||||
if args.size == 0
|
||||
|
|
@ -211,6 +213,27 @@ module DRC
|
|||
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%
|
||||
# @brief Defines SPICE output format (with options)
|
||||
# @name write_spice
|
||||
|
|
@ -455,15 +478,20 @@ module DRC
|
|||
|
||||
# %DRC%
|
||||
# @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, indent)
|
||||
# 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.
|
||||
|
||||
def info(arg, indent = 0)
|
||||
@verbose && log(arg, indent)
|
||||
if @verbose
|
||||
log(arg, indent)
|
||||
else
|
||||
str = (" " * indent) + arg
|
||||
RBA::Logger::log(str)
|
||||
end
|
||||
end
|
||||
|
||||
# %DRC%
|
||||
|
|
@ -476,7 +504,7 @@ module DRC
|
|||
# verbose mode is enabled.
|
||||
|
||||
def log(arg, indent = 0)
|
||||
str = (" " * indent) + arg
|
||||
str = (" " * indent) + arg
|
||||
if @log_file
|
||||
@log_file.puts(str)
|
||||
else
|
||||
|
|
@ -1828,7 +1856,7 @@ CODE
|
|||
def _wrapper_context(func, *args, &proc)
|
||||
in_context_outer = @in_context
|
||||
begin
|
||||
@in_context = true
|
||||
@in_context = func
|
||||
return yield(*args)
|
||||
rescue => ex
|
||||
raise("'" + func + "': " + ex.to_s)
|
||||
|
|
@ -1842,22 +1870,40 @@ CODE
|
|||
return yield(*args)
|
||||
else
|
||||
begin
|
||||
@in_context = true
|
||||
@in_context = func
|
||||
return yield(*args)
|
||||
rescue => ex
|
||||
raise("'" + func + "': " + ex.to_s)
|
||||
ensure
|
||||
@in_context = false
|
||||
@in_context = nil
|
||||
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)
|
||||
|
||||
log(desc)
|
||||
info(desc)
|
||||
|
||||
# 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)
|
||||
disable_progress = true
|
||||
obj.enable_progress(desc)
|
||||
end
|
||||
|
||||
|
|
@ -1867,39 +1913,37 @@ CODE
|
|||
res = yield
|
||||
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
|
||||
|
||||
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)
|
||||
ensure
|
||||
|
||||
# disable progress again
|
||||
if disable_progress
|
||||
obj.disable_progress
|
||||
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
|
||||
|
||||
end
|
||||
|
||||
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)
|
||||
end
|
||||
end
|
||||
|
|
@ -1929,8 +1973,9 @@ CODE
|
|||
end
|
||||
av = args.size.times.collect { |i| "a#{i}" }.join(", ")
|
||||
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}")
|
||||
res
|
||||
end
|
||||
|
||||
else
|
||||
|
|
@ -1940,17 +1985,12 @@ CODE
|
|||
end
|
||||
|
||||
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)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# disable progress again
|
||||
if obj.is_a?(RBA::Region)
|
||||
obj.disable_progress
|
||||
end
|
||||
|
||||
res
|
||||
|
||||
end
|
||||
|
|
@ -1984,8 +2024,9 @@ CODE
|
|||
end
|
||||
av = args.size.times.collect { |i| "a#{i}" }.join(", ")
|
||||
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}")
|
||||
res
|
||||
end
|
||||
|
||||
else
|
||||
|
|
@ -1995,17 +2036,12 @@ CODE
|
|||
end
|
||||
|
||||
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)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# disable progress again
|
||||
if obj.is_a?(RBA::Region)
|
||||
obj.disable_progress
|
||||
end
|
||||
|
||||
res
|
||||
|
||||
end
|
||||
|
|
@ -2025,8 +2061,9 @@ CODE
|
|||
tp.input("self", obj)
|
||||
tp.threads = (@tt || 1)
|
||||
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}")
|
||||
res
|
||||
end
|
||||
|
||||
res = res.value
|
||||
|
|
@ -2038,39 +2075,40 @@ CODE
|
|||
end
|
||||
|
||||
res = nil
|
||||
run_timed("\"#{method}\" in: #{src_line}", obj) do
|
||||
run_timed("\"#{@in_context || method}\" in: #{src_line}", obj) do
|
||||
res = obj.send(method)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# disable progress again
|
||||
if obj.is_a?(RBA::Region)
|
||||
obj.disable_progress
|
||||
end
|
||||
|
||||
res
|
||||
|
||||
end
|
||||
|
||||
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))
|
||||
end
|
||||
end
|
||||
|
||||
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)
|
||||
end
|
||||
end
|
||||
|
||||
def _start
|
||||
def _start(macro_path)
|
||||
|
||||
# clearing the selection avoids some nasty problems
|
||||
view = RBA::LayoutView::current
|
||||
view && view.cancel
|
||||
|
||||
@total_timer = RBA::Timer::new
|
||||
@total_timer.start
|
||||
|
||||
@drc_progress = RBA::AbstractProgress::new("DRC: " + macro_path)
|
||||
|
||||
|
||||
end
|
||||
|
||||
def _flush
|
||||
|
|
@ -2210,6 +2248,18 @@ CODE
|
|||
@netter = 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
|
||||
@log_file.close
|
||||
@log_file = nil
|
||||
|
|
@ -2218,6 +2268,10 @@ CODE
|
|||
# force garbage collection
|
||||
GC.start
|
||||
|
||||
# unlocks the UI
|
||||
@drc_progress._destroy
|
||||
@drc_progress = nil
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -2526,6 +2580,9 @@ CODE
|
|||
end
|
||||
|
||||
end
|
||||
|
||||
data
|
||||
|
||||
end
|
||||
|
||||
def make_source(layout, cell = nil, path = nil)
|
||||
|
|
|
|||
|
|
@ -983,8 +983,8 @@ CODE
|
|||
# @name corners
|
||||
# @brief Selects corners of polygons
|
||||
# @synopsis layer.corners([ options ])
|
||||
# @synopsis layer.corners(angle, [ options ])
|
||||
# @synopsis layer.corners(amin .. amax, [ options ])
|
||||
# @synopsis layer.corners(angle [, options ])
|
||||
# @synopsis layer.corners(amin .. amax [, options ])
|
||||
#
|
||||
# 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
|
||||
|
|
@ -1263,6 +1263,7 @@ CODE
|
|||
self.data.send(new_data.is_a?(RBA::EdgePairs) ? :each : :each_merged) do |object|
|
||||
block.call(object.transformed(t)) && new_data.insert(object)
|
||||
end
|
||||
new_data
|
||||
end
|
||||
DRCLayer::new(@engine, new_data)
|
||||
|
||||
|
|
@ -1285,7 +1286,7 @@ CODE
|
|||
@engine._wrapper_context("each") do
|
||||
|
||||
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|
|
||||
block.call(object.transformed(t))
|
||||
end
|
||||
|
|
@ -1368,10 +1369,11 @@ CODE
|
|||
t = RBA::CplxTrans::new(@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|
|
||||
insert_object_into(new_data, block.call(object.transformed(t)), dbu_trans)
|
||||
end
|
||||
new_data
|
||||
end
|
||||
|
||||
DRCLayer::new(@engine, new_data)
|
||||
|
|
@ -1660,6 +1662,7 @@ CODE
|
|||
|
||||
@engine._context("andnot") do
|
||||
|
||||
check_is_layer(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
|
||||
# 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%
|
||||
# @name select_covering
|
||||
# @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
|
||||
# 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%
|
||||
# @name select_overlapping
|
||||
# @brief Selects shapes or regions of self which overlap shapes from the other region
|
||||
|
|
@ -1923,6 +1956,19 @@ CODE
|
|||
# @/tr
|
||||
# @/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%
|
||||
# @name select_inside
|
||||
# @brief Selects shapes or regions of self which are inside the other region
|
||||
|
|
@ -1995,6 +2041,19 @@ CODE
|
|||
# @/tr
|
||||
# @/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%
|
||||
# @name select_outside
|
||||
# @brief Selects shapes or regions of self which are outside the other region
|
||||
|
|
@ -2149,6 +2208,21 @@ CODE
|
|||
# @/tr
|
||||
# @/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%
|
||||
# @name select_interacting
|
||||
# @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
|
||||
# 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.
|
||||
|
||||
|
||||
# %DRC%
|
||||
# @name intersections
|
||||
# @brief Returns the intersection points of intersecting edge segments for two edge collections
|
||||
|
|
@ -2285,6 +2359,7 @@ CODE
|
|||
|
||||
@engine._context("#{f}") do
|
||||
|
||||
check_is_layer(other)
|
||||
if :#{f} != :pull_interacting
|
||||
requires_region
|
||||
other.requires_region
|
||||
|
|
@ -2310,11 +2385,16 @@ CODE
|
|||
%w(| ^ inside not_inside outside not_outside in not_in).each do |f|
|
||||
eval <<"CODE"
|
||||
def #{f}(other)
|
||||
|
||||
@engine._context("#{f}") do
|
||||
|
||||
requires_same_type(other)
|
||||
requires_edges_or_region
|
||||
|
||||
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, self.data.class, :#{f}, other.data))
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
CODE
|
||||
end
|
||||
|
|
@ -2325,12 +2405,14 @@ CODE
|
|||
|
||||
@engine._context("#{f}") do
|
||||
|
||||
check_is_layer(other)
|
||||
other.requires_edges_texts_or_region
|
||||
if self.data.is_a?(RBA::Texts)
|
||||
other.requires_region
|
||||
else
|
||||
other.requires_edges_or_region
|
||||
end
|
||||
|
||||
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, self.data.class, :#{f}, other.data))
|
||||
|
||||
end
|
||||
|
|
@ -2342,10 +2424,14 @@ CODE
|
|||
%w(+).each do |f|
|
||||
eval <<"CODE"
|
||||
def #{f}(other)
|
||||
|
||||
@engine._context("#{f}") do
|
||||
|
||||
requires_same_type(other)
|
||||
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, self.data.class, :#{f}, other.data))
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
CODE
|
||||
end
|
||||
|
|
@ -2356,7 +2442,7 @@ CODE
|
|||
|
||||
@engine._context("#{f}") do
|
||||
|
||||
other.requires_edges_texts_or_region
|
||||
check_is_layer(other)
|
||||
if self.data.is_a?(RBA::Text)
|
||||
other.requires_region
|
||||
elsif self.data.is_a?(RBA::Region)
|
||||
|
|
@ -2381,6 +2467,7 @@ CODE
|
|||
|
||||
@engine._context("#{f}") do
|
||||
|
||||
check_is_layer(other)
|
||||
requires_edges_texts_or_region
|
||||
if self.data.is_a?(RBA::Text)
|
||||
other.requires_region
|
||||
|
|
@ -2389,6 +2476,7 @@ CODE
|
|||
else
|
||||
other.requires_edges_or_region
|
||||
end
|
||||
|
||||
if @engine.is_tiled?
|
||||
self.data = @engine._tcmd(self.data, 0, self.data.class, :#{fi}, other.data, *minmax_count(*args))
|
||||
DRCLayer::new(@engine, self.data)
|
||||
|
|
@ -2402,14 +2490,39 @@ CODE
|
|||
CODE
|
||||
end
|
||||
|
||||
%w(overlapping not_overlapping covering not_covering).each do |f|
|
||||
%w(split_interacting).each do |f|
|
||||
eval <<"CODE"
|
||||
def #{f}(other, *args)
|
||||
|
||||
@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_region
|
||||
|
||||
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, self.data.class, :#{f}, other.data, *minmax_count(*args)))
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
CODE
|
||||
end
|
||||
|
|
@ -2424,6 +2537,7 @@ CODE
|
|||
|
||||
requires_region
|
||||
requires_same_type(other)
|
||||
|
||||
if @engine.is_tiled?
|
||||
self.data = @engine._tcmd(self.data, 0, self.data.class, :#{fi}, other.data, *minmax_count(*args))
|
||||
DRCLayer::new(@engine, self.data)
|
||||
|
|
@ -2437,6 +2551,24 @@ CODE
|
|||
CODE
|
||||
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|
|
||||
f = "select_" + fi
|
||||
# In tiled mode, there are no modifying versions. Emulate using the non-modifying one.
|
||||
|
|
@ -2447,6 +2579,7 @@ CODE
|
|||
|
||||
requires_region
|
||||
requires_same_type(other)
|
||||
|
||||
if @engine.is_tiled?
|
||||
self.data = @engine._tcmd(self.data, 0, self.data.class, :#{fi}, other.data)
|
||||
DRCLayer::new(@engine, self.data)
|
||||
|
|
@ -2460,14 +2593,39 @@ CODE
|
|||
CODE
|
||||
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|
|
||||
eval <<"CODE"
|
||||
def #{f}(other)
|
||||
|
||||
@engine._context("#{f}") do
|
||||
|
||||
check_is_layer(other)
|
||||
other.requires_region
|
||||
requires_edges
|
||||
|
||||
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, self.data.class, :#{f}, other.data))
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
CODE
|
||||
end
|
||||
|
|
@ -2475,11 +2633,17 @@ CODE
|
|||
%w(intersections).each do |f|
|
||||
eval <<"CODE"
|
||||
def #{f}(other)
|
||||
|
||||
@engine._context("#{f}") do
|
||||
|
||||
check_is_layer(other)
|
||||
other.requires_edges
|
||||
requires_edges
|
||||
|
||||
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, self.data.class, :#{f}, other.data))
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
CODE
|
||||
end
|
||||
|
|
@ -3496,6 +3660,180 @@ CODE
|
|||
end
|
||||
CODE
|
||||
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%
|
||||
# @name scaled
|
||||
|
|
@ -3915,6 +4253,10 @@ CODE
|
|||
@data = d
|
||||
end
|
||||
|
||||
def check_is_layer(other)
|
||||
other.is_a?(DRCLayer) || raise("Argument needs to be a DRC layer")
|
||||
end
|
||||
|
||||
def requires_region
|
||||
self.data.is_a?(RBA::Region) || raise("Requires a polygon layer")
|
||||
end
|
||||
|
|
|
|||
|
|
@ -180,6 +180,56 @@ module DRC
|
|||
@value
|
||||
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
|
||||
|
||||
|
|
|
|||
|
|
@ -19,13 +19,10 @@ module DRC
|
|||
|
||||
def DRC.execute_drc(macro, generator, rdb_index = nil)
|
||||
|
||||
timer = RBA::Timer::new
|
||||
timer.start
|
||||
drc = DRCEngine::new
|
||||
drc._rdb_index = rdb_index
|
||||
drc._generator = generator
|
||||
|
||||
drc_progress = RBA::AbstractProgress::new("DRC: " + macro.path)
|
||||
drc._start(macro.path)
|
||||
|
||||
begin
|
||||
|
||||
|
|
@ -48,14 +45,8 @@ module DRC
|
|||
# cleans up and creates layout and report views
|
||||
drc._finish
|
||||
|
||||
# unlocks the UI
|
||||
drc_progress._destroy
|
||||
|
||||
end
|
||||
|
||||
timer.stop
|
||||
drc.info("Total run time: #{'%.3f'%(timer.sys+timer.user)}s")
|
||||
|
||||
end
|
||||
|
||||
# A DSL implementation for a DRC language (XML format)
|
||||
|
|
|
|||
|
|
@ -1163,3 +1163,8 @@ TEST(29d_holes)
|
|||
run_test (_this, "29", true);
|
||||
}
|
||||
|
||||
TEST(30_density)
|
||||
{
|
||||
run_test (_this, "30", false);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1387,7 +1387,7 @@ MainService::cm_round_corners ()
|
|||
std::vector <db::Polygon> in;
|
||||
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) {
|
||||
*p = smooth (*p, 1);
|
||||
*p = smooth (*p, 1, true);
|
||||
}
|
||||
|
||||
std::vector <db::Polygon> out = in;
|
||||
|
|
|
|||
|
|
@ -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#squares">squares</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>
|
||||
</p><p>
|
||||
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.
|
||||
See <a href="/about/drc_ref_layer.xml#start_segments">layer#start_segments</a> for details about this functionality.
|
||||
</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 > 2)
|
||||
out = in.drc(primary.with_holes > 2) # equivalent
|
||||
</pre>
|
||||
</p>
|
||||
<a name="|"/><h2>"|" - Boolean OR between the results of two expressions</h2>
|
||||
<keyword name="|"/>
|
||||
<p>Usage:</p>
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
See <a href="#if_all">if_all</a> for an example how to use the if_... functions.
|
||||
</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"/>
|
||||
<p>Usage:</p>
|
||||
<ul>
|
||||
|
|
@ -747,7 +747,7 @@ See <a href="#if_all">if_all</a> for an example how to use the if_... functions.
|
|||
</ul>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<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>
|
||||
In verbose mode, more output is generated in the log file
|
||||
</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>
|
||||
<keyword name="width"/>
|
||||
<p>Usage:</p>
|
||||
|
|
@ -1847,6 +1856,17 @@ shape.
|
|||
</tr>
|
||||
</table>
|
||||
</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>
|
||||
<keyword name="write_spice"/>
|
||||
<p>Usage:</p>
|
||||
|
|
|
|||
|
|
@ -247,8 +247,8 @@ deliver objects that can be converted into polygons. Such objects are of class <
|
|||
<p>Usage:</p>
|
||||
<ul>
|
||||
<li><tt>layer.corners([ options ])</tt></li>
|
||||
<li><tt>layer.corners(angle, [ options ])</tt></li>
|
||||
<li><tt>layer.corners(amin .. amax, [ options ])</tt></li>
|
||||
<li><tt>layer.corners(angle [, options ])</tt></li>
|
||||
<li><tt>layer.corners(amin .. amax [, options ])</tt></li>
|
||||
</ul>
|
||||
<p>
|
||||
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>
|
||||
</table>
|
||||
</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>
|
||||
<keyword name="squares"/>
|
||||
<p>Usage:</p>
|
||||
|
|
@ -3074,6 +3155,86 @@ bounding box.
|
|||
</p><p>
|
||||
This method is available for polygon layers only.
|
||||
</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>
|
||||
<keyword name="with_length"/>
|
||||
<p>Usage:</p>
|
||||
|
|
@ -3228,6 +3389,29 @@ bounding box.
|
|||
</p><p>
|
||||
This method is available for polygon layers only.
|
||||
</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>
|
||||
<keyword name="without_length"/>
|
||||
<p>Usage:</p>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 8.3 KiB |
|
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 9.0 KiB |
|
Before Width: | Height: | Size: 8.8 KiB After Width: | Height: | Size: 9.2 KiB |
|
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 7.5 KiB |
|
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 7.5 KiB |
|
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 7.9 KiB |
|
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 7.8 KiB |
|
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 8.0 KiB |
|
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 9.6 KiB |
|
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 9.0 KiB |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 9.2 KiB |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 9.0 KiB |
|
Before Width: | Height: | Size: 8.8 KiB After Width: | Height: | Size: 9.2 KiB |
|
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 7.5 KiB |
|
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 7.6 KiB |
|
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 7.4 KiB |
|
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 7.5 KiB |
|
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 7.4 KiB |
|
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 7.3 KiB |
|
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 7.4 KiB |
|
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 8.0 KiB After Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 7.7 KiB |
|
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 7.6 KiB |
|
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 7.8 KiB |
|
Before Width: | Height: | Size: 8.0 KiB After Width: | Height: | Size: 8.7 KiB |
|
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 9.0 KiB |
|
Before Width: | Height: | Size: 7.9 KiB After Width: | Height: | Size: 8.9 KiB |
|
Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 9.2 KiB |
|
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 9.1 KiB |
|
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 8.8 KiB |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 9.3 KiB |
|
Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 8.4 KiB |
|
Before Width: | Height: | Size: 9.6 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 7.8 KiB |
|
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 7.9 KiB |
|
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 8.4 KiB |
|
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 8.2 KiB |
|
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 6.9 KiB |
|
Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 8.2 KiB |
|
Before Width: | Height: | Size: 7.8 KiB After Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 9.8 KiB |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 9.1 KiB |
|
Before Width: | Height: | Size: 8.8 KiB After Width: | Height: | Size: 9.8 KiB |
|
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 7.8 KiB |
|
Before Width: | Height: | Size: 7.9 KiB After Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 9.1 KiB |
|
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 9.1 KiB |
|
Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 9.2 KiB |
|
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 9.0 KiB |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 9.4 KiB |