WIP: Region, Edges, EdgePairs and Texts filters can filter by property now, first implementation of Region property filter.

This commit is contained in:
Matthias Koefferlein 2025-02-16 00:08:35 +01:00
parent 54242bc848
commit a219576296
32 changed files with 446 additions and 171 deletions

View File

@ -233,7 +233,7 @@ AsIfFlatEdgePairs::filtered (const EdgePairFilterBase &filter) const
std::unique_ptr<FlatEdgePairs> new_edge_pairs (new FlatEdgePairs ());
for (EdgePairsIterator p (begin ()); ! p.at_end (); ++p) {
if (filter.selected (*p)) {
if (filter.selected (*p, p.prop_id ())) {
db::properties_id_type prop_id = p.prop_id ();
if (prop_id != 0) {
new_edge_pairs->insert (db::EdgePairWithProperties (*p, prop_id));

View File

@ -711,8 +711,12 @@ AsIfFlatEdges::filtered (const EdgeFilterBase &filter) const
std::unique_ptr<FlatEdges> new_region (new FlatEdges ());
for (EdgesIterator p (begin_merged ()); ! p.at_end (); ++p) {
if (filter.selected (*p)) {
new_region->insert (*p);
if (filter.selected (*p, p.prop_id ())) {
if (p.prop_id () != 0) {
new_region->insert (db::EdgeWithProperties (*p, p.prop_id ()));
} else {
new_region->insert (*p);
}
}
}

View File

@ -167,7 +167,7 @@ AsIfFlatRegion::edges (const EdgeFilterBase *filter, const PolygonToEdgeProcesso
proc->process (*p, heap);
for (auto e = heap.begin (); e != heap.end (); ++e) {
if (! filter || filter->selected (*e)) {
if (! filter || filter->selected (*e, prop_id)) {
if (prop_id != 0) {
result->insert (db::EdgeWithProperties (*e, prop_id));
} else {
@ -179,7 +179,7 @@ AsIfFlatRegion::edges (const EdgeFilterBase *filter, const PolygonToEdgeProcesso
} else {
for (db::Polygon::polygon_edge_iterator e = p->begin_edge (); ! e.at_end (); ++e) {
if (! filter || filter->selected (*e)) {
if (! filter || filter->selected (*e, prop_id)) {
if (prop_id != 0) {
result->insert (db::EdgeWithProperties (*e, prop_id));
} else {
@ -420,8 +420,12 @@ AsIfFlatRegion::filtered (const PolygonFilterBase &filter) const
std::unique_ptr<FlatRegion> new_region (new FlatRegion ());
for (RegionIterator p (begin_merged ()); ! p.at_end (); ++p) {
if (filter.selected (*p)) {
new_region->insert (*p);
if (filter.selected (*p, p.prop_id ())) {
if (p.prop_id () != 0) {
new_region->insert (db::PolygonWithProperties (*p, p.prop_id ()));
} else {
new_region->insert (*p);
}
}
}

View File

@ -159,8 +159,12 @@ AsIfFlatTexts::filtered (const TextFilterBase &filter) const
std::unique_ptr<FlatTexts> new_texts (new FlatTexts ());
for (TextsIterator p (begin ()); ! p.at_end (); ++p) {
if (filter.selected (*p)) {
new_texts->insert (*p);
if (filter.selected (*p, p.prop_id ())) {
if (p.prop_id () != 0) {
new_texts->insert (db::TextWithProperties (*p, p.prop_id ()));
} else {
new_texts->insert (*p);
}
}
}

View File

@ -1260,7 +1260,13 @@ CompoundRegionEdgePairFilterOperationNode::do_compute_local (CompoundRegionOpera
bool
CompoundRegionEdgePairFilterOperationNode::is_selected (const db::EdgePair &p) const
{
return mp_filter->selected (p);
return mp_filter->selected (p, db::properties_id_type (0));
}
bool
CompoundRegionEdgePairFilterOperationNode::is_selected (const db::EdgePairWithProperties &p) const
{
return mp_filter->selected (p, p.properties_id ());
}
// ---------------------------------------------------------------------------------------------

View File

@ -1015,14 +1015,12 @@ private:
child (0)->compute_local (cache, layout, cell, interactions, one, proc);
if (m_sum_of_set) {
std::unordered_set<T> wo_props;
wo_props.insert (one.front ().begin (), one.front ().end ());
if (mp_filter->selected_set (wo_props)) {
if (mp_filter->selected_set (one.front ())) {
results.front ().insert (one.front ().begin (), one.front ().end ());
}
} else {
for (typename std::unordered_set<db::object_with_properties<T> >::const_iterator p = one.front ().begin (); p != one.front ().end (); ++p) {
if (mp_filter->selected (*p)) {
if (mp_filter->selected (*p, p->properties_id ())) {
results.front ().insert (*p);
}
}
@ -1066,14 +1064,12 @@ private:
child (0)->compute_local (cache, layout, cell, interactions, one, proc);
if (m_sum_of) {
std::unordered_set<db::Edge> wo_props;
wo_props.insert (one.front ().begin (), one.front ().end ());
if (mp_filter->selected (wo_props)) {
if (mp_filter->selected (one.front ())) {
results.front ().insert (one.front ().begin (), one.front ().end ());
}
} else {
for (typename std::unordered_set<db::EdgeWithProperties>::const_iterator p = one.front ().begin (); p != one.front ().end (); ++p) {
if (mp_filter->selected (*p)) {
if (mp_filter->selected (*p, p->properties_id ())) {
results.front ().insert (*p);
}
}
@ -1108,6 +1104,7 @@ private:
bool m_owns_filter;
bool is_selected (const db::EdgePair &p) const;
bool is_selected (const db::EdgePairWithProperties &p) const;
template <class T, class TR>
void implement_compute_local (db::CompoundRegionOperationCache *cache, db::Layout *layout, db::Cell *cell, const shape_interactions<T, T> &interactions, std::vector<std::unordered_set<TR> > &results, const db::LocalProcessorBase *proc) const

View File

@ -423,7 +423,7 @@ DeepEdgePairs::apply_filter (const EdgePairFilterBase &filter) const
const db::ICplxTrans &tr = *v;
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::EdgePairs); ! si.at_end (); ++si) {
if (filter.selected (si->edge_pair ().transformed (tr))) {
if (filter.selected (si->edge_pair ().transformed (tr), si->prop_id ())) {
st->insert (*si);
}
}
@ -435,7 +435,7 @@ DeepEdgePairs::apply_filter (const EdgePairFilterBase &filter) const
db::Shapes &st = c->shapes (res->deep_layer ().layer ());
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::EdgePairs); ! si.at_end (); ++si) {
if (filter.selected (si->edge_pair ())) {
if (filter.selected (si->edge_pair (), si->prop_id ())) {
st.insert (*si);
}
}

View File

@ -848,7 +848,7 @@ DeepEdges::apply_filter (const EdgeFilterBase &filter) const
}
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::Edges); ! si.at_end (); ++si) {
if (filter.selected (si->edge ().transformed (*v))) {
if (filter.selected (si->edge ().transformed (*v), si->prop_id ())) {
st->insert (*si);
}
}
@ -860,7 +860,7 @@ DeepEdges::apply_filter (const EdgeFilterBase &filter) const
db::Shapes &st = c->shapes (res->deep_layer ().layer ());
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::Edges); ! si.at_end (); ++si) {
if (filter.selected (si->edge ())) {
if (filter.selected (si->edge (), si->prop_id ())) {
st.insert (*si);
}
}

View File

@ -1511,7 +1511,7 @@ DeepRegion::edges (const EdgeFilterBase *filter, const PolygonToEdgeProcessorBas
proc->process (poly, heap);
for (auto e = heap.begin (); e != heap.end (); ++e) {
if (! filter || filter->selected ((*e).transformed (tr))) {
if (! filter || filter->selected ((*e).transformed (tr), si->prop_id ())) {
st.insert (db::EdgeWithProperties (*e, si->prop_id ()));
}
}
@ -1519,7 +1519,7 @@ DeepRegion::edges (const EdgeFilterBase *filter, const PolygonToEdgeProcessorBas
} else {
for (db::Polygon::polygon_edge_iterator e = poly.begin_edge (); ! e.at_end (); ++e) {
if (! filter || filter->selected ((*e).transformed (tr))) {
if (! filter || filter->selected ((*e).transformed (tr), si->prop_id ())) {
st.insert (db::EdgeWithProperties (*e, si->prop_id ()));
}
}
@ -1641,7 +1641,7 @@ DeepRegion::apply_filter (const PolygonFilterBase &filter) const
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) {
db::Polygon poly;
si->polygon (poly);
if (filter.selected (poly.transformed (*v))) {
if (filter.selected (poly.transformed (*v), si->prop_id ())) {
st->insert (*si);
}
}
@ -1655,7 +1655,7 @@ DeepRegion::apply_filter (const PolygonFilterBase &filter) const
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) {
db::Polygon poly;
si->polygon (poly);
if (filter.selected (poly)) {
if (filter.selected (poly, si->prop_id ())) {
st.insert (*si);
}
}

View File

@ -442,7 +442,7 @@ DeepTexts *DeepTexts::apply_filter (const TextFilterBase &filter) const
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::Texts); ! si.at_end (); ++si) {
db::Text text;
si->text (text);
if (filter.selected (text.transformed (*v))) {
if (filter.selected (text.transformed (*v), si->prop_id ())) {
st->insert (*si);
}
}
@ -456,7 +456,7 @@ DeepTexts *DeepTexts::apply_filter (const TextFilterBase &filter) const
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::Texts); ! si.at_end (); ++si) {
db::Text text;
si->text (text);
if (filter.selected (text)) {
if (filter.selected (text, si->prop_id ())) {
st.insert (*si);
}
}

View File

@ -43,12 +43,12 @@ EdgeFilterBasedEdgePairFilter::~EdgeFilterBasedEdgePairFilter ()
// .. nothing yet ..
}
bool EdgeFilterBasedEdgePairFilter::selected (const db::EdgePair &edge_pair) const
bool EdgeFilterBasedEdgePairFilter::selected (const db::EdgePair &edge_pair, db::properties_id_type prop_id) const
{
if (m_one_must_match) {
return mp_edge_filter->selected (edge_pair.first ()) || mp_edge_filter->selected (edge_pair.second ());
return mp_edge_filter->selected (edge_pair.first (), prop_id) || mp_edge_filter->selected (edge_pair.second (), prop_id);
} else {
return mp_edge_filter->selected (edge_pair.first ()) && mp_edge_filter->selected (edge_pair.second ());
return mp_edge_filter->selected (edge_pair.first (), prop_id) && mp_edge_filter->selected (edge_pair.second (), prop_id);
}
}
@ -71,7 +71,7 @@ EdgePairFilterByDistance::EdgePairFilterByDistance (distance_type min_distance,
// .. nothing yet ..
}
bool EdgePairFilterByDistance::selected (const db::EdgePair &edge_pair) const
bool EdgePairFilterByDistance::selected (const db::EdgePair &edge_pair, db::properties_id_type) const
{
distance_type dist = edge_pair.distance ();
bool sel = (dist >= m_min_distance && dist < m_max_distance);
@ -87,7 +87,7 @@ EdgePairFilterByArea::EdgePairFilterByArea (area_type min_area, area_type max_ar
// .. nothing yet ..
}
bool EdgePairFilterByArea::selected (const db::EdgePair &edge_pair) const
bool EdgePairFilterByArea::selected (const db::EdgePair &edge_pair, db::properties_id_type) const
{
area_type dist = edge_pair.to_simple_polygon (0).area ();
bool sel = (dist >= m_min_area && dist < m_max_area);
@ -110,7 +110,7 @@ InternalAngleEdgePairFilter::InternalAngleEdgePairFilter (double amin, bool incl
}
bool
InternalAngleEdgePairFilter::selected (const db::EdgePair &edge_pair) const
InternalAngleEdgePairFilter::selected (const db::EdgePair &edge_pair, db::properties_id_type) const
{
db::Vector d1 = edge_pair.first ().d ();
db::Vector d2 = edge_pair.second ().d ();

View File

@ -47,7 +47,7 @@ public:
EdgeFilterBasedEdgePairFilter (EdgeFilterBase *edge_filter, bool one_must_match);
virtual ~EdgeFilterBasedEdgePairFilter ();
virtual bool selected (const db::EdgePair &edge_pair) const;
virtual bool selected (const db::EdgePair &edge_pair, properties_id_type prop_id) const;
virtual const TransformationReducer *vars () const;
virtual bool wants_variants () const;
@ -69,7 +69,7 @@ public:
EdgePairFilterByDistance (distance_type min_distance, distance_type max_distance, bool inverted);
virtual bool selected (const db::EdgePair &edge_pair) const;
virtual bool selected (const db::EdgePair &edge_pair, properties_id_type) const;
virtual const TransformationReducer *vars () const { return &m_vars; }
virtual bool wants_variants () const { return true; }
@ -92,7 +92,7 @@ public:
EdgePairFilterByArea (area_type min_area, area_type max_area, bool inverted);
virtual bool selected (const db::EdgePair &edge_pair) const;
virtual bool selected (const db::EdgePair &edge_pair, properties_id_type) const;
virtual const TransformationReducer *vars () const { return &m_vars; }
virtual bool wants_variants () const { return true; }
@ -114,7 +114,7 @@ public:
InternalAngleEdgePairFilter (double a, bool inverted);
InternalAngleEdgePairFilter (double amin, bool include_amin, double amax, bool include_amax, bool inverted);
virtual bool selected (const db::EdgePair &edge_pair) const;
virtual bool selected (const db::EdgePair &edge_pair, properties_id_type) const;
virtual const TransformationReducer *vars () const { return 0; }
virtual bool wants_variants () const { return false; }

View File

@ -58,7 +58,7 @@ public:
EdgePairFilterBase () { }
virtual ~EdgePairFilterBase () { }
virtual bool selected (const db::EdgePair &edge_pair) const = 0;
virtual bool selected (const db::EdgePair &edge_pair, db::properties_id_type prop_id) const = 0;
virtual const TransformationReducer *vars () const = 0;
virtual bool wants_variants () const = 0;
};

View File

@ -56,13 +56,13 @@ public:
* @brief Filters the edge
* If this method returns true, the edge is kept. Otherwise it's discarded.
*/
virtual bool selected (const db::Edge &edge) const = 0;
virtual bool selected (const db::Edge &edge, db::properties_id_type prop_id) const = 0;
/**
* @brief Filters the edge set
* If this method returns true, the edges are kept. Otherwise they are discarded.
*/
virtual bool selected (const std::unordered_set<db::Edge> &edge) const = 0;
virtual bool selected (const std::unordered_set<db::EdgeWithProperties> &edge) const = 0;
/**
* @brief Returns the transformation reducer for building cell variants

View File

@ -304,7 +304,7 @@ EdgeOrientationFilter::EdgeOrientationFilter (double a, bool inverse, bool absol
}
bool
EdgeOrientationFilter::selected (const db::Edge &edge) const
EdgeOrientationFilter::selected (const db::Edge &edge, db::properties_id_type) const
{
// NOTE: this edge normalization confines the angle to a range between (-90 .. 90] (-90 excluded).
// A horizontal edge has 0 degree, a vertical one has 90 degree.
@ -342,7 +342,7 @@ static EdgeAngleChecker s_orthodiagonal_checkers [] = {
};
bool
SpecialEdgeOrientationFilter::selected (const db::Edge &edge) const
SpecialEdgeOrientationFilter::selected (const db::Edge &edge, properties_id_type) const
{
const EdgeAngleChecker *eb, *ee;

View File

@ -71,7 +71,7 @@ struct DB_PUBLIC EdgeLengthFilter
/**
* @brief Returns true if the edge length matches the criterion
*/
virtual bool selected (const db::Edge &edge) const
virtual bool selected (const db::Edge &edge, db::properties_id_type) const
{
return check (edge.length ());
}
@ -79,10 +79,10 @@ struct DB_PUBLIC EdgeLengthFilter
/**
* @brief Returns true if the total edge length matches the criterion
*/
bool selected (const std::unordered_set<db::Edge> &edges) const
bool selected (const std::unordered_set<db::EdgeWithProperties> &edges) const
{
length_type l = 0;
for (std::unordered_set<db::Edge>::const_iterator e = edges.begin (); e != edges.end (); ++e) {
for (std::unordered_set<db::EdgeWithProperties>::const_iterator e = edges.begin (); e != edges.end (); ++e) {
l += e->length ();
}
return check (l);
@ -204,15 +204,15 @@ struct DB_PUBLIC EdgeOrientationFilter
/**
* @brief Returns true if the edge orientation matches the criterion
*/
virtual bool selected (const db::Edge &edge) const;
virtual bool selected (const db::Edge &edge, properties_id_type) const;
/**
* @brief Returns true if all edge orientations match the criterion
*/
virtual bool selected (const std::unordered_set<db::Edge> &edges) const
virtual bool selected (const std::unordered_set<db::EdgeWithProperties> &edges) const
{
for (std::unordered_set<db::Edge>::const_iterator e = edges.begin (); e != edges.end (); ++e) {
if (! selected (*e)) {
for (std::unordered_set<db::EdgeWithProperties>::const_iterator e = edges.begin (); e != edges.end (); ++e) {
if (! selected (*e, e->properties_id ())) {
return false;
}
}
@ -274,15 +274,15 @@ struct DB_PUBLIC SpecialEdgeOrientationFilter
/**
* @brief Returns true if the edge orientation matches the criterion
*/
virtual bool selected (const db::Edge &edge) const;
virtual bool selected (const db::Edge &edge, db::properties_id_type) const;
/**
* @brief Returns true if all edge orientations match the criterion
*/
virtual bool selected (const std::unordered_set<db::Edge> &edges) const
virtual bool selected (const std::unordered_set<db::EdgeWithProperties> &edges) const
{
for (std::unordered_set<db::Edge>::const_iterator e = edges.begin (); e != edges.end (); ++e) {
if (! selected (*e)) {
for (std::unordered_set<db::EdgeWithProperties>::const_iterator e = edges.begin (); e != edges.end (); ++e) {
if (! selected (*e, e->properties_id ())) {
return false;
}
}

View File

@ -103,7 +103,7 @@ FlatEdgePairs::filter_in_place (const EdgePairFilterBase &filter)
edge_pair_iterator_type pw = ep.get_layer<db::EdgePair, db::unstable_layer_tag> ().begin ();
for (EdgePairsIterator p (begin ()); ! p.at_end (); ++p) {
if (filter.selected (*p)) {
if (filter.selected (*p, p.prop_id ())) {
if (pw == ep.get_layer<db::EdgePair, db::unstable_layer_tag> ().end ()) {
ep.get_layer<db::EdgePair, db::unstable_layer_tag> ().insert (*p);
pw = ep.get_layer<db::EdgePair, db::unstable_layer_tag> ().end ();

View File

@ -276,7 +276,7 @@ FlatEdges::filter_in_place (const EdgeFilterBase &filter)
edge_iterator_wp_type pw_wp = e.get_layer<db::EdgeWithProperties, db::unstable_layer_tag> ().begin ();
for (EdgesIterator p (begin_merged ()); ! p.at_end (); ++p) {
if (filter.selected (*p)) {
if (filter.selected (*p, p.prop_id ())) {
if (p.prop_id () != 0) {
if (pw_wp == e.get_layer<db::EdgeWithProperties, db::unstable_layer_tag> ().end ()) {
e.get_layer<db::EdgeWithProperties, db::unstable_layer_tag> ().insert (db::EdgeWithProperties (*p, p.prop_id ()));

View File

@ -184,7 +184,7 @@ RegionDelegate *FlatRegion::filter_in_place (const PolygonFilterBase &filter)
polygon_iterator_wp_type pw_wp = poly_layer_wp.begin ();
for (RegionIterator p (filter.requires_raw_input () ? begin () : begin_merged ()); ! p.at_end (); ++p) {
if (filter.selected (*p)) {
if (filter.selected (*p, p.prop_id ())) {
if (p.prop_id () != 0) {
if (pw_wp == poly_layer_wp.end ()) {
poly_layer_wp.insert (db::PolygonWithProperties (*p, p.prop_id ()));

View File

@ -101,7 +101,7 @@ FlatTexts::filter_in_place (const TextFilterBase &filter)
text_iterator_type pw = texts.get_layer<db::Text, db::unstable_layer_tag> ().begin ();
for (TextsIterator p (begin ()); ! p.at_end (); ++p) {
if (filter.selected (*p)) {
if (filter.selected (*p, p.prop_id ())) {
if (pw == texts.get_layer<db::Text, db::unstable_layer_tag> ().end ()) {
texts.get_layer<db::Text, db::unstable_layer_tag> ().insert (*p);
pw = texts.get_layer<db::Text, db::unstable_layer_tag> ().end ();

View File

@ -68,25 +68,25 @@ public:
* @brief Filters the polygon
* If this method returns true, the polygon is kept. Otherwise it's discarded.
*/
virtual bool selected (const db::Polygon &polygon) const = 0;
virtual bool selected (const db::Polygon &polygon, db::properties_id_type prop_id) const = 0;
/**
* @brief Filters the polygon reference
* If this method returns true, the polygon is kept. Otherwise it's discarded.
*/
virtual bool selected (const db::PolygonRef &polygon) const = 0;
virtual bool selected (const db::PolygonRef &polygon, db::properties_id_type prop_id) const = 0;
/**
* @brief Filters the set of polygons (taking the overall properties)
* If this method returns true, the polygon is kept. Otherwise it's discarded.
*/
virtual bool selected_set (const std::unordered_set<db::Polygon> &polygons) const = 0;
virtual bool selected_set (const std::unordered_set<db::PolygonWithProperties> &polygons) const = 0;
/**
* @brief Filters the set of polygon references (taking the overall properties)
* If this method returns true, the polygon is kept. Otherwise it's discarded.
*/
virtual bool selected_set (const std::unordered_set<db::PolygonRef> &polygons) const = 0;
virtual bool selected_set (const std::unordered_set<db::PolygonRefWithProperties> &polygons) const = 0;
/**
* @brief Returns the transformation reducer for building cell variants

View File

@ -48,29 +48,29 @@ bool RegionPerimeterFilter::check (perimeter_type p) const
}
}
bool RegionPerimeterFilter::selected (const db::Polygon &poly) const
bool RegionPerimeterFilter::selected (const db::Polygon &poly, db::properties_id_type) const
{
return check (poly.perimeter ());
}
bool RegionPerimeterFilter::selected (const db::PolygonRef &poly) const
bool RegionPerimeterFilter::selected (const db::PolygonRef &poly, db::properties_id_type) const
{
return check (poly.perimeter ());
}
bool RegionPerimeterFilter::selected_set (const std::unordered_set<db::Polygon> &poly) const
bool RegionPerimeterFilter::selected_set (const std::unordered_set<db::PolygonWithProperties> &poly) const
{
perimeter_type ps = 0;
for (std::unordered_set<db::Polygon>::const_iterator p = poly.begin (); p != poly.end (); ++p) {
for (std::unordered_set<db::PolygonWithProperties>::const_iterator p = poly.begin (); p != poly.end (); ++p) {
ps += p->perimeter ();
}
return check (ps);
}
bool RegionPerimeterFilter::selected_set (const std::unordered_set<db::PolygonRef> &poly) const
bool RegionPerimeterFilter::selected_set (const std::unordered_set<PolygonRefWithProperties> &poly) const
{
perimeter_type ps = 0;
for (std::unordered_set<db::PolygonRef>::const_iterator p = poly.begin (); p != poly.end (); ++p) {
for (std::unordered_set<db::PolygonRefWithProperties>::const_iterator p = poly.begin (); p != poly.end (); ++p) {
ps += p->perimeter ();
}
return check (ps);
@ -99,29 +99,29 @@ bool RegionAreaFilter::check (area_type a) const
}
}
bool RegionAreaFilter::selected (const db::Polygon &poly) const
bool RegionAreaFilter::selected (const db::Polygon &poly, db::properties_id_type) const
{
return check (poly.area ());
}
bool RegionAreaFilter::selected (const db::PolygonRef &poly) const
bool RegionAreaFilter::selected (const db::PolygonRef &poly, properties_id_type) const
{
return check (poly.area ());
}
bool RegionAreaFilter::selected_set (const std::unordered_set<db::Polygon> &poly) const
bool RegionAreaFilter::selected_set (const std::unordered_set<db::PolygonWithProperties> &poly) const
{
area_type as = 0;
for (std::unordered_set<db::Polygon>::const_iterator p = poly.begin (); p != poly.end (); ++p) {
for (std::unordered_set<db::PolygonWithProperties>::const_iterator p = poly.begin (); p != poly.end (); ++p) {
as += p->area ();
}
return check (as);
}
bool RegionAreaFilter::selected_set (const std::unordered_set<db::PolygonRef> &poly) const
bool RegionAreaFilter::selected_set (const std::unordered_set<db::PolygonRefWithProperties> &poly) const
{
area_type as = 0;
for (std::unordered_set<db::PolygonRef>::const_iterator p = poly.begin (); p != poly.end (); ++p) {
for (std::unordered_set<db::PolygonRefWithProperties>::const_iterator p = poly.begin (); p != poly.end (); ++p) {
as += p->area ();
}
return check (as);
@ -143,13 +143,13 @@ RectilinearFilter::RectilinearFilter (bool inverse)
}
bool
RectilinearFilter::selected (const db::Polygon &poly) const
RectilinearFilter::selected (const db::Polygon &poly, db::properties_id_type) const
{
return poly.is_rectilinear () != m_inverse;
}
bool
RectilinearFilter::selected (const db::PolygonRef &poly) const
RectilinearFilter::selected (const db::PolygonRef &poly, db::properties_id_type) const
{
return poly.is_rectilinear () != m_inverse;
}
@ -170,14 +170,14 @@ HoleCountFilter::HoleCountFilter (size_t min_count, size_t max_count, bool inver
}
bool
HoleCountFilter::selected (const db::Polygon &poly) const
HoleCountFilter::selected (const db::Polygon &poly, db::properties_id_type) const
{
bool ok = poly.holes () < m_max_count && poly.holes () >= m_min_count;
return ok != m_inverse;
}
bool
HoleCountFilter::selected (const db::PolygonRef &poly) const
HoleCountFilter::selected (const db::PolygonRef &poly, properties_id_type) const
{
bool ok = poly.obj ().holes () < m_max_count && poly.obj ().holes () >= m_min_count;
return ok != m_inverse;
@ -198,7 +198,7 @@ RectangleFilter::RectangleFilter (bool is_square, bool inverse)
}
bool
RectangleFilter::selected (const db::Polygon &poly) const
RectangleFilter::selected (const db::Polygon &poly, properties_id_type) const
{
bool ok = poly.is_box ();
if (ok && m_is_square) {
@ -209,7 +209,7 @@ RectangleFilter::selected (const db::Polygon &poly) const
}
bool
RectangleFilter::selected (const db::PolygonRef &poly) const
RectangleFilter::selected (const db::PolygonRef &poly, properties_id_type) const
{
bool ok = poly.is_box ();
if (ok && m_is_square) {
@ -256,13 +256,13 @@ RegionBBoxFilter::check (const db::Box &box) const
}
bool
RegionBBoxFilter::selected (const db::Polygon &poly) const
RegionBBoxFilter::selected (const db::Polygon &poly, properties_id_type) const
{
return check (poly.box ());
}
bool
RegionBBoxFilter::selected (const db::PolygonRef &poly) const
RegionBBoxFilter::selected (const db::PolygonRef &poly, properties_id_type) const
{
return check (poly.box ());
}
@ -322,7 +322,7 @@ static double compute_ratio_parameter (const P &poly, RegionRatioFilter::paramet
return v;
}
bool RegionRatioFilter::selected (const db::Polygon &poly) const
bool RegionRatioFilter::selected (const db::Polygon &poly, properties_id_type) const
{
double v = compute_ratio_parameter (poly, m_parameter);
@ -330,7 +330,7 @@ bool RegionRatioFilter::selected (const db::Polygon &poly) const
return ok != m_inverse;
}
bool RegionRatioFilter::selected (const db::PolygonRef &poly) const
bool RegionRatioFilter::selected (const db::PolygonRef &poly, properties_id_type) const
{
double v = compute_ratio_parameter (poly, m_parameter);

View File

@ -57,22 +57,22 @@ struct DB_PUBLIC RegionPerimeterFilter
/**
* @brief Returns true if the polygon's perimeter matches the criterion
*/
virtual bool selected (const db::Polygon &poly) const;
virtual bool selected (const db::Polygon &poly, properties_id_type) const;
/**
* @brief Returns true if the polygon's perimeter matches the criterion
*/
virtual bool selected (const db::PolygonRef &poly) const;
virtual bool selected (const db::PolygonRef &poly, properties_id_type) const;
/**
* @brief Returns true if the polygon's perimeter sum matches the criterion
*/
virtual bool selected_set (const std::unordered_set<db::PolygonRef> &polygons) const;
virtual bool selected_set (const std::unordered_set<db::PolygonRefWithProperties> &polygons) const;
/**
* @brief Returns true if the polygon's perimeter sum matches the criterion
*/
virtual bool selected_set (const std::unordered_set<db::Polygon> &polygons) const;
virtual bool selected_set (const std::unordered_set<PolygonWithProperties> &polygons) const;
/**
* @brief This filter is isotropic
@ -123,22 +123,22 @@ struct DB_PUBLIC RegionAreaFilter
/**
* @brief Returns true if the polygon's area matches the criterion
*/
virtual bool selected (const db::Polygon &poly) const;
virtual bool selected (const db::Polygon &poly, properties_id_type) const;
/**
* @brief Returns true if the polygon's area matches the criterion
*/
virtual bool selected (const db::PolygonRef &poly) const;
virtual bool selected (const db::PolygonRef &poly, properties_id_type) const;
/**
* @brief Returns true if the polygon's area sum matches the criterion
*/
virtual bool selected_set (const std::unordered_set<db::PolygonRef> &polygons) const;
virtual bool selected_set (const std::unordered_set<db::PolygonRefWithProperties> &polygons) const;
/**
* @brief Returns true if the polygon's area sum matches the criterion
*/
virtual bool selected_set (const std::unordered_set<db::Polygon> &polygons) const;
virtual bool selected_set (const std::unordered_set<PolygonWithProperties> &polygons) const;
/**
* @brief This filter is isotropic
@ -175,20 +175,20 @@ struct DB_PUBLIC AllMustMatchFilter
*/
AllMustMatchFilter () { }
virtual bool selected_set (const std::unordered_set<db::PolygonRef> &polygons) const
virtual bool selected_set (const std::unordered_set<db::PolygonRefWithProperties> &polygons) const
{
for (std::unordered_set<db::PolygonRef>::const_iterator p = polygons.begin (); p != polygons.end (); ++p) {
if (! selected (*p)) {
for (std::unordered_set<db::PolygonRefWithProperties>::const_iterator p = polygons.begin (); p != polygons.end (); ++p) {
if (! selected (*p, p->properties_id ())) {
return false;
}
}
return true;
}
virtual bool selected_set (const std::unordered_set<db::Polygon> &polygons) const
virtual bool selected_set (const std::unordered_set<db::PolygonWithProperties> &polygons) const
{
for (std::unordered_set<db::Polygon>::const_iterator p = polygons.begin (); p != polygons.end (); ++p) {
if (! selected (*p)) {
for (std::unordered_set<db::PolygonWithProperties>::const_iterator p = polygons.begin (); p != polygons.end (); ++p) {
if (! selected (*p, p->properties_id ())) {
return false;
}
}
@ -215,12 +215,12 @@ struct DB_PUBLIC RectilinearFilter
/**
* @brief Returns true if the polygon is rectilinear
*/
virtual bool selected (const db::Polygon &poly) const;
virtual bool selected (const db::Polygon &poly, properties_id_type) const;
/**
* @brief Returns true if the polygon is rectilinear
*/
virtual bool selected (const db::PolygonRef &poly) const;
virtual bool selected (const db::PolygonRef &poly, properties_id_type) const;
/**
* @brief This filter does not need variants
@ -259,12 +259,12 @@ struct DB_PUBLIC RectangleFilter
/**
* @brief Returns true if the polygon is a rectangle
*/
virtual bool selected (const db::Polygon &poly) const;
virtual bool selected (const db::Polygon &poly, properties_id_type) const;
/**
* @brief Returns true if the polygon is a rectangle
*/
virtual bool selected (const db::PolygonRef &poly) const;
virtual bool selected (const db::PolygonRef &poly, properties_id_type) const;
/**
* @brief This filter does not need variants
@ -304,12 +304,12 @@ struct DB_PUBLIC HoleCountFilter
/**
* @brief Returns true if the polygon is a rectangle
*/
virtual bool selected (const db::Polygon &poly) const;
virtual bool selected (const db::Polygon &poly, properties_id_type) const;
/**
* @brief Returns true if the polygon is a rectangle
*/
virtual bool selected (const db::PolygonRef &poly) const;
virtual bool selected (const db::PolygonRef &poly, properties_id_type) const;
/**
* @brief This filter does not need variants
@ -375,12 +375,12 @@ struct DB_PUBLIC RegionBBoxFilter
/**
* @brief Returns true if the polygon's bounding box matches the criterion
*/
virtual bool selected (const db::Polygon &poly) const;
virtual bool selected (const db::Polygon &poly, properties_id_type) const;
/**
* @brief Returns true if the polygon's bounding box matches the criterion
*/
virtual bool selected (const db::PolygonRef &poly) const;
virtual bool selected (const db::PolygonRef &poly, properties_id_type) const;
/**
* @brief This filter is isotropic unless the parameter is width or height
@ -444,12 +444,12 @@ struct DB_PUBLIC RegionRatioFilter
/**
* @brief Returns true if the polygon's area matches the criterion
*/
virtual bool selected (const db::Polygon &poly) const;
virtual bool selected (const db::Polygon &poly, properties_id_type) const;
/**
* @brief Returns true if the polygon's area matches the criterion
*/
virtual bool selected (const db::PolygonRef &poly) const;
virtual bool selected (const db::PolygonRef &poly, properties_id_type) const;
/**
* @brief This filter is isotropic unless the parameter is width or height

View File

@ -57,7 +57,7 @@ public:
TextFilterBase () { }
virtual ~TextFilterBase () { }
virtual bool selected (const db::Text &text) const = 0;
virtual bool selected (const db::Text &text, db::properties_id_type prop_id) const = 0;
virtual const TransformationReducer *vars () const = 0;
virtual bool wants_variants () const = 0;
};

View File

@ -58,7 +58,7 @@ struct DB_PUBLIC TextStringFilter
/**
* @brief Returns true if the text matches the criterion
*/
virtual bool selected (const db::Text &text) const
virtual bool selected (const db::Text &text, db::properties_id_type) const
{
return (text.string () == m_text) != m_inverse;
}
@ -118,7 +118,7 @@ struct DB_PUBLIC TextPatternFilter
/**
* @brief Returns true if the text matches the criterion
*/
virtual bool selected (const db::Text &text) const
virtual bool selected (const db::Text &text, db::properties_id_type) const
{
return m_pattern.match (text.string ()) != m_inverse;
}

View File

@ -45,17 +45,17 @@ class EdgePairFilterImpl
public:
EdgePairFilterImpl () { }
bool issue_selected (const db::EdgePair &) const
bool issue_selected (const db::EdgePairWithProperties &) const
{
return false;
}
virtual bool selected (const db::EdgePair &edge_pair) const
virtual bool selected (const db::EdgePair &edge_pair, db::properties_id_type prop_id) const
{
if (f_selected.can_issue ()) {
return f_selected.issue<EdgePairFilterImpl, bool, const db::EdgePair &> (&EdgePairFilterImpl::issue_selected, edge_pair);
return f_selected.issue<EdgePairFilterImpl, bool, const db::EdgePairWithProperties &> (&EdgePairFilterImpl::issue_selected, db::EdgePairWithProperties (edge_pair, prop_id));
} else {
return issue_selected (edge_pair);
return issue_selected (db::EdgePairWithProperties (edge_pair, prop_id));
}
}
@ -73,6 +73,8 @@ Class<gsi::EdgePairFilterImpl> decl_EdgePairFilterImpl ("db", "EdgePairFilter",
"@brief Selects an edge pair\n"
"This method is the actual payload. It needs to be reimplemented in a derived class.\n"
"It needs to analyze the edge pair and return 'true' if it should be kept and 'false' if it should be discarded."
"\n"
"Since version 0.30, the edge pair carries properties."
),
"@brief A generic edge pair filter adaptor\n"
"\n"

View File

@ -46,26 +46,34 @@ class EdgeFilterImpl
public:
EdgeFilterImpl () { }
bool issue_selected (const db::Edge &) const
bool issue_selected (const db::EdgeWithProperties &) const
{
return false;
}
virtual bool selected (const db::Edge &edge) const
virtual bool selected (const db::Edge &edge, db::properties_id_type prop_id) const
{
if (f_selected.can_issue ()) {
return f_selected.issue<EdgeFilterImpl, bool, const db::Edge &> (&EdgeFilterImpl::issue_selected, edge);
return f_selected.issue<EdgeFilterImpl, bool, const db::EdgeWithProperties &> (&EdgeFilterImpl::issue_selected, db::EdgeWithProperties (edge, prop_id));
} else {
return issue_selected (edge);
return issue_selected (db::EdgeWithProperties (edge, prop_id));
}
}
// Returns true if all edges match the criterion
virtual bool selected (const std::unordered_set<db::Edge> &edges) const
virtual bool selected (const std::unordered_set<db::EdgeWithProperties> &edges) const
{
for (std::unordered_set<db::Edge>::const_iterator e = edges.begin (); e != edges.end (); ++e) {
if (! selected (*e)) {
return false;
if (f_selected.can_issue ()) {
for (std::unordered_set<db::EdgeWithProperties>::const_iterator e = edges.begin (); e != edges.end (); ++e) {
if (! f_selected.issue<EdgeFilterImpl, bool, const db::EdgeWithProperties &> (&EdgeFilterImpl::issue_selected, *e)) {
return false;
}
}
} else {
for (std::unordered_set<db::EdgeWithProperties>::const_iterator e = edges.begin (); e != edges.end (); ++e) {
if (! issue_selected (*e)) {
return false;
}
}
}
return true;
@ -85,6 +93,8 @@ Class<gsi::EdgeFilterImpl> decl_EdgeFilterImpl ("db", "EdgeFilter",
"@brief Selects an edge\n"
"This method is the actual payload. It needs to be reimplemented in a derived class.\n"
"It needs to analyze the edge and return 'true' if it should be kept and 'false' if it should be discarded."
"\n"
"Since version 0.30, the edge carries properties."
),
"@brief A generic edge filter adaptor\n"
"\n"

View File

@ -263,6 +263,26 @@ define_terminal_by_names (GenericDeviceExtractor *extractor, db::Device *device,
extractor->define_terminal (device, terminal_id, layer_id, shape);
}
static void error1 (GenericDeviceExtractor *ext, const std::string &message, const db::DPolygonWithProperties &poly)
{
ext->error (message, poly);
}
static void error2 (GenericDeviceExtractor *ext, const std::string &message, const db::PolygonWithProperties &poly)
{
ext->error (message, poly);
}
static void warn1 (GenericDeviceExtractor *ext, const std::string &message, const db::DPolygonWithProperties &poly)
{
ext->warn (message, poly);
}
static void warn2 (GenericDeviceExtractor *ext, const std::string &message, const db::PolygonWithProperties &poly)
{
ext->warn (message, poly);
}
Class<GenericDeviceExtractor> decl_GenericDeviceExtractor (decl_dbNetlistDeviceExtractor, "db", "GenericDeviceExtractor",
gsi::callback ("setup", &GenericDeviceExtractor::setup, &GenericDeviceExtractor::cb_setup,
"@brief Sets up the extractor.\n"
@ -397,10 +417,20 @@ Class<GenericDeviceExtractor> decl_GenericDeviceExtractor (decl_dbNetlistDeviceE
gsi::arg ("message"), gsi::arg ("geometry"),
"@brief Issues an error with the given message and micrometer-units polygon geometry\n"
) +
gsi::method_ext ("error", &error1,
gsi::arg ("message"), gsi::arg ("geometry"),
"@brief Issues an error with the given message and micrometer-units polygon geometry with properties\n"
"This flavor has been introduced in version 0.30."
) +
gsi::method ("error", (void (GenericDeviceExtractor::*) (const std::string &, const db::Polygon &)) &GenericDeviceExtractor::error,
gsi::arg ("message"), gsi::arg ("geometry"),
"@brief Issues an error with the given message and database-unit polygon geometry\n"
) +
gsi::method_ext ("error", &error2,
gsi::arg ("message"), gsi::arg ("geometry"),
"@brief Issues an error with the given message and database-units polygon geometry with properties\n"
"This flavor has been introduced in version 0.30."
) +
gsi::method ("error", (void (GenericDeviceExtractor::*) (const std::string &, const std::string &, const std::string &)) &GenericDeviceExtractor::error,
gsi::arg ("category_name"), gsi::arg ("category_description"), gsi::arg ("message"),
"@brief Issues an error with the given category name and description, message\n"
@ -423,11 +453,21 @@ Class<GenericDeviceExtractor> decl_GenericDeviceExtractor (decl_dbNetlistDeviceE
"@brief Issues a warning with the given message and micrometer-units polygon geometry\n"
"Warnings have been introduced in version 0.28.13."
) +
gsi::method_ext ("warn", &warn1,
gsi::arg ("message"), gsi::arg ("geometry"),
"@brief Issues a warning with the given message and micrometer-units polygon geometry with properties\n"
"This flavor has been introduced in version 0.30."
) +
gsi::method ("warn", (void (GenericDeviceExtractor::*) (const std::string &, const db::Polygon &)) &GenericDeviceExtractor::warn,
gsi::arg ("message"), gsi::arg ("geometry"),
"@brief Issues a warning with the given message and database-unit polygon geometry\n"
"Warnings have been introduced in version 0.28.13."
) +
gsi::method_ext ("warn", &warn2,
gsi::arg ("message"), gsi::arg ("geometry"),
"@brief Issues a warning with the given message and database-unit polygon geometry\n"
"This flavor has been introduced in version 0.30."
) +
gsi::method ("warn", (void (GenericDeviceExtractor::*) (const std::string &, const std::string &, const std::string &)) &GenericDeviceExtractor::warn,
gsi::arg ("category_name"), gsi::arg ("category_description"), gsi::arg ("message"),
"@brief Issues a warning with the given category name and description, message\n"

View File

@ -36,6 +36,7 @@
#include "dbRegionProcessors.h"
#include "dbCompoundOperation.h"
#include "dbLayoutToNetlist.h"
#include "dbPropertiesRepository.h"
#include "tlGlobPattern.h"
#include "gsiDeclDbContainerHelpers.h"
@ -50,31 +51,38 @@ namespace gsi
// ---------------------------------------------------------------------------------
// PolygonFilter binding
class PolygonFilterImpl
class PolygonFilterBase
: public shape_filter_impl<db::AllMustMatchFilter>
{
public:
PolygonFilterBase () { }
};
class PolygonFilterImpl
: public PolygonFilterBase
{
public:
PolygonFilterImpl () { }
bool issue_selected (const db::Polygon &) const
bool issue_selected (const db::PolygonWithProperties &) const
{
return false;
}
virtual bool selected (const db::Polygon &polygon) const
virtual bool selected (const db::Polygon &polygon, db::properties_id_type prop_id) const
{
if (f_selected.can_issue ()) {
return f_selected.issue<PolygonFilterImpl, bool, const db::Polygon &> (&PolygonFilterImpl::issue_selected, polygon);
return f_selected.issue<PolygonFilterImpl, bool, const db::PolygonWithProperties &> (&PolygonFilterImpl::issue_selected, db::PolygonWithProperties (polygon, prop_id));
} else {
return issue_selected (polygon);
}
}
virtual bool selected (const db::PolygonRef &polygon) const
virtual bool selected (const db::PolygonRef &polygon, db::properties_id_type prop_id) const
{
db::Polygon p;
polygon.instantiate (p);
return selected (p);
return selected (p, prop_id);
}
gsi::Callback f_selected;
@ -85,12 +93,164 @@ private:
PolygonFilterImpl (const PolygonFilterImpl &);
};
Class<gsi::PolygonFilterImpl> decl_PolygonFilterImpl ("db", "PolygonFilter",
/**
* @brief A properties filter
*/
class PropertiesFilter
{
public:
PropertiesFilter (const tl::Variant &name, const tl::Variant &value, bool inverse)
: m_name_id (db::property_names_id (name)), m_value_from (value), m_exact (true), m_glob (false), m_inverse (inverse)
{
// .. nothing yet ..
}
PropertiesFilter (const tl::Variant &name, const tl::Variant &from, const tl::Variant &to, bool inverse)
: m_name_id (db::property_names_id (name)), m_value_from (from), m_value_to (to), m_exact (false), m_glob (false), m_inverse (inverse)
{
// .. nothing yet ..
}
PropertiesFilter (const tl::Variant &name, const std::string &pattern, bool inverse)
: m_name_id (db::property_names_id (name)), m_pattern (pattern), m_exact (true), m_glob (true), m_inverse (inverse)
{
// .. nothing yet ..
}
bool prop_selected (db::properties_id_type prop_id) const
{
auto c = m_cache.find (prop_id);
if (c != m_cache.end ()) {
return c->second;
}
bool res = prop_selected_impl (prop_id);
m_cache.insert (std::make_pair (prop_id, res));
return res;
}
private:
bool prop_selected_impl (db::properties_id_type prop_id) const
{
const db::PropertiesSet &ps = db::properties (prop_id);
if (ps.has_value (m_name_id)) {
const tl::Variant &value = ps.value (m_name_id);
if (m_glob) {
return m_pattern.match (value.to_string ()) != m_inverse;
} else if (m_exact) {
return (value == m_value_from) != m_inverse;
} else {
return ((m_value_from.is_nil () || ! (value < m_value_from)) && (m_value_to.is_nil () || value < m_value_to)) != m_inverse;
}
} else {
return m_inverse;
}
}
mutable std::map<db::properties_id_type, bool> m_cache;
db::property_names_id_type m_name_id;
tl::Variant m_value_from, m_value_to;
tl::GlobPattern m_pattern;
bool m_exact;
bool m_glob;
bool m_inverse;
};
class PolygonPropertiesFilter
: public PolygonFilterBase, public PropertiesFilter
{
public:
PolygonPropertiesFilter (const tl::Variant &name, const std::string &pattern, bool inverse)
: PropertiesFilter (name, pattern, inverse)
{
// .. nothing yet ..
}
PolygonPropertiesFilter (const tl::Variant &name, const tl::Variant &value, bool inverse)
: PropertiesFilter (name, value, inverse)
{
// .. nothing yet ..
}
PolygonPropertiesFilter (const tl::Variant &name, const tl::Variant &from, const tl::Variant &to, bool inverse)
: PropertiesFilter (name, from, to, inverse)
{
// .. nothing yet ..
}
bool selected (const db::Polygon &, db::properties_id_type prop_id) const
{
return PropertiesFilter::prop_selected (prop_id);
}
bool selected (const db::PolygonRef &, db::properties_id_type prop_id) const
{
return PropertiesFilter::prop_selected (prop_id);
}
};
static PolygonFilterBase *make_ppf1 (const tl::Variant &name, const tl::Variant &value, bool inverse)
{
return new PolygonPropertiesFilter (name, value, inverse);
}
static PolygonFilterBase *make_ppf2 (const tl::Variant &name, const tl::Variant &from, const tl::Variant &to, bool inverse)
{
return new PolygonPropertiesFilter (name, from, to, inverse);
}
static PolygonFilterBase *make_pg (const tl::Variant &name, const std::string &glob, bool inverse)
{
return new PolygonPropertiesFilter (name, glob, inverse);
}
Class<gsi::PolygonFilterBase> decl_PolygonFilterBase ("db", "PolygonFilterBase",
gsi::constructor ("property_glob", &make_pg, gsi::arg ("name"), gsi::arg ("pattern"), gsi::arg ("inverse", false),
"@brief Creates a single-valued property filter\n"
"@param name The name of the property to use.\n"
"@param value The glob pattern to match the property value against.\n"
"@param inverse If true, inverts the selection - i.e. all polygons without a matching property are selected.\n"
"\n"
"Apply this filter with \\Region#filtered.\n"
"\n"
"This feature has been introduced in version 0.30."
) +
gsi::constructor ("property_filter", &make_ppf1, gsi::arg ("name"), gsi::arg ("value"), gsi::arg ("inverse", false),
"@brief Creates a single-valued property filter\n"
"@param name The name of the property to use.\n"
"@param value The value against which the property is checked (exact match).\n"
"@param inverse If true, inverts the selection - i.e. all polygons without a property with the given name and value are selected.\n"
"\n"
"Apply this filter with \\Region#filtered.\n"
"\n"
"This feature has been introduced in version 0.30."
) +
gsi::constructor ("property_filter_bounded", &make_ppf2, gsi::arg ("name"), gsi::arg ("from"), gsi::arg ("to"), gsi::arg ("inverse", false),
"@brief Creates a single-valued property filter\n"
"@param name The name of the property to use.\n"
"@param from The lower value against which the property is checked or 'nil' if no lower bound shall be used.\n"
"@param to The upper value against which the property is checked or 'nil' if no upper bound shall be used.\n"
"@param inverse If true, inverts the selection - i.e. all polygons without a property with the given name and value range are selected.\n"
"\n"
"This version does a bounded match. The value of the propery needs to be larger or equal to 'from' and less than 'to'.\n"
"Apply this filter with \\Region#filtered.\n"
"\n"
"This feature has been introduced in version 0.30."
),
"@hide"
);
Class<gsi::PolygonFilterImpl> decl_PolygonFilterImpl (decl_PolygonFilterBase, "db", "PolygonFilter",
PolygonFilterImpl::method_decls (true) +
callback ("selected", &PolygonFilterImpl::issue_selected, &PolygonFilterImpl::f_selected, gsi::arg ("polygon"),
"@brief Selects a polygon\n"
"This method is the actual payload. It needs to be reimplemented in a derived class.\n"
"It needs to analyze the polygon and return 'true' if it should be kept and 'false' if it should be discarded."
"It needs to analyze the polygon and return 'true' if it should be kept and 'false' if it should be discarded.\n"
"\n"
"Since version 0.30, the polygon carries properties."
),
"@brief A generic polygon filter adaptor\n"
"\n"
@ -544,12 +704,12 @@ static db::Edges extent_refs_edges (const db::Region *r, double fx1, double fy1,
return r->processed (db::RelativeExtentsAsEdges (fx1, fy1, fx2, fy2));
}
static db::Region filtered (const db::Region *r, const PolygonFilterImpl *f)
static db::Region filtered (const db::Region *r, const PolygonFilterBase *f)
{
return r->filtered (*f);
}
static void filter (db::Region *r, const PolygonFilterImpl *f)
static void filter (db::Region *r, const PolygonFilterBase *f)
{
r->filter (*f);
}

View File

@ -42,17 +42,17 @@ class TextFilterImpl
public:
TextFilterImpl () { }
bool issue_selected (const db::Text &) const
bool issue_selected (const db::TextWithProperties &) const
{
return false;
}
virtual bool selected (const db::Text &text) const
virtual bool selected (const db::Text &text, db::properties_id_type prop_id) const
{
if (f_selected.can_issue ()) {
return f_selected.issue<TextFilterImpl, bool, const db::Text &> (&TextFilterImpl::issue_selected, text);
return f_selected.issue<TextFilterImpl, bool, const db::TextWithProperties &> (&TextFilterImpl::issue_selected, db::TextWithProperties (text, prop_id));
} else {
return issue_selected (text);
return issue_selected (db::TextWithProperties (text, prop_id));
}
}
@ -70,6 +70,8 @@ Class<gsi::TextFilterImpl> decl_TextFilterImpl ("db", "TextFilter",
"@brief Selects a text\n"
"This method is the actual payload. It needs to be reimplemented in a derived class.\n"
"It needs to analyze the text and return 'true' if it should be kept and 'false' if it should be discarded."
"\n"
"Since version 0.30, the text carries properties."
),
"@brief A generic text filter adaptor\n"
"\n"

View File

@ -115,7 +115,7 @@ TEST(2)
struct EPTestFilter
: public db::EdgePairFilterBase
{
bool selected (const db::EdgePair &ep) const
bool selected (const db::EdgePair &ep, db::properties_id_type) const
{
return ep.first ().double_length () < 50;
}
@ -171,44 +171,44 @@ TEST(5_InternalAngleFilter)
db::EdgePair ep90 (db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 0), db::Point (0, 100)));
db::EdgePair epm90 (db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 100), db::Point (0, 0)));
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, false).selected (ep0), true);
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, false).selected (ep180), true);
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, false).selected (ep90), false);
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, false).selected (epm90), false);
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, false).selected (ep45), false);
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, false).selected (ep0, 0), true);
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, false).selected (ep180, 0), true);
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, false).selected (ep90, 0), false);
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, false).selected (epm90, 0), false);
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, false).selected (ep45, 0), false);
EXPECT_EQ (db::InternalAngleEdgePairFilter (90.0, false).selected (ep0), false);
EXPECT_EQ (db::InternalAngleEdgePairFilter (90.0, false).selected (ep180), false);
EXPECT_EQ (db::InternalAngleEdgePairFilter (90.0, false).selected (ep90), true);
EXPECT_EQ (db::InternalAngleEdgePairFilter (90.0, false).selected (epm90), true);
EXPECT_EQ (db::InternalAngleEdgePairFilter (90.0, false).selected (ep45), false);
EXPECT_EQ (db::InternalAngleEdgePairFilter (90.0, false).selected (ep0, 0), false);
EXPECT_EQ (db::InternalAngleEdgePairFilter (90.0, false).selected (ep180, 0), false);
EXPECT_EQ (db::InternalAngleEdgePairFilter (90.0, false).selected (ep90, 0), true);
EXPECT_EQ (db::InternalAngleEdgePairFilter (90.0, false).selected (epm90, 0), true);
EXPECT_EQ (db::InternalAngleEdgePairFilter (90.0, false).selected (ep45, 0), false);
EXPECT_EQ (db::InternalAngleEdgePairFilter (45.0, false).selected (ep0), false);
EXPECT_EQ (db::InternalAngleEdgePairFilter (45.0, false).selected (ep180), false);
EXPECT_EQ (db::InternalAngleEdgePairFilter (45.0, false).selected (ep90), false);
EXPECT_EQ (db::InternalAngleEdgePairFilter (45.0, false).selected (epm90), false);
EXPECT_EQ (db::InternalAngleEdgePairFilter (45.0, false).selected (ep45), true);
EXPECT_EQ (db::InternalAngleEdgePairFilter (45.0, false).selected (ep45inv), true);
EXPECT_EQ (db::InternalAngleEdgePairFilter (45.0, false).selected (ep0, 0), false);
EXPECT_EQ (db::InternalAngleEdgePairFilter (45.0, false).selected (ep180, 0), false);
EXPECT_EQ (db::InternalAngleEdgePairFilter (45.0, false).selected (ep90, 0), false);
EXPECT_EQ (db::InternalAngleEdgePairFilter (45.0, false).selected (epm90, 0), false);
EXPECT_EQ (db::InternalAngleEdgePairFilter (45.0, false).selected (ep45, 0), true);
EXPECT_EQ (db::InternalAngleEdgePairFilter (45.0, false).selected (ep45inv, 0), true);
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true).selected (ep0), false);
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true).selected (ep180), false);
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true).selected (ep90), true);
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true).selected (epm90), true);
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true).selected (ep45), true);
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true).selected (ep0, 0), false);
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true).selected (ep180, 0), false);
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true).selected (ep90, 0), true);
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true).selected (epm90, 0), true);
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true).selected (ep45, 0), true);
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true, 45.0, true, false).selected (ep0), true);
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true, 45.0, true, false).selected (ep180), true);
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true, 45.0, true, false).selected (ep90), false);
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true, 45.0, true, false).selected (epm90), false);
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true, 45.0, true, false).selected (ep45), true);
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true, 45.0, true, false).selected (ep45inv), true);
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true, 45.0, true, false).selected (ep0, 0), true);
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true, 45.0, true, false).selected (ep180, 0), true);
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true, 45.0, true, false).selected (ep90, 0), false);
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true, 45.0, true, false).selected (epm90, 0), false);
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true, 45.0, true, false).selected (ep45, 0), true);
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true, 45.0, true, false).selected (ep45inv, 0), true);
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true, 45.0, true, true).selected (ep0), false);
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true, 45.0, true, true).selected (ep180), false);
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true, 45.0, true, true).selected (ep90), true);
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true, 45.0, true, true).selected (epm90), true);
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true, 45.0, true, true).selected (ep45), false);
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true, 45.0, true, true).selected (ep45inv), false);
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true, 45.0, true, true).selected (ep0, 0), false);
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true, 45.0, true, true).selected (ep180, 0), false);
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true, 45.0, true, true).selected (ep90, 0), true);
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true, 45.0, true, true).selected (epm90, 0), true);
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true, 45.0, true, true).selected (ep45, 0), false);
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true, 45.0, true, true).selected (ep45inv, 0), false);
}
TEST(6_add_with_properties)

View File

@ -1583,6 +1583,52 @@ class DBRegion_TestClass < TestBase
end
# properties
def test_prop_filters
r = RBA::Region::new
r.insert(RBA::PolygonWithProperties::new(RBA::Box::new(0, 0, 100, 200), { "one" => -1 }))
r.insert(RBA::PolygonWithProperties::new(RBA::Box::new(1, 1, 101, 201), { "one" => 17 }))
r.insert(RBA::PolygonWithProperties::new(RBA::Box::new(2, 2, 102, 202), { "one" => 42 }))
assert_equal(r.filtered(RBA::PolygonFilter::property_filter("one", 11)).to_s, "")
assert_equal(r.filtered(RBA::PolygonFilter::property_filter("two", 17)).to_s, "")
assert_equal(r.filtered(RBA::PolygonFilter::property_filter("one", 17)).to_s, "(1,1;1,201;101,201;101,1){one=>17}")
assert_equal(r.filtered(RBA::PolygonFilter::property_filter("one", 17, true)).to_s, "(2,2;2,202;102,202;102,2){one=>42};(0,0;0,200;100,200;100,0){one=>-1}")
assert_equal(r.filtered(RBA::PolygonFilter::property_filter_bounded("one", 17, nil)).to_s, "(1,1;1,201;101,201;101,1){one=>17};(2,2;2,202;102,202;102,2){one=>42}")
assert_equal(r.filtered(RBA::PolygonFilter::property_filter_bounded("one", 17, 18)).to_s, "(1,1;1,201;101,201;101,1){one=>17}")
assert_equal(r.filtered(RBA::PolygonFilter::property_filter_bounded("one", 17, 18, true)).to_s, "(2,2;2,202;102,202;102,2){one=>42};(0,0;0,200;100,200;100,0){one=>-1}")
assert_equal(r.filtered(RBA::PolygonFilter::property_filter_bounded("one", nil, 18)).to_s, "(1,1;1,201;101,201;101,1){one=>17};(0,0;0,200;100,200;100,0){one=>-1}")
assert_equal(r.filtered(RBA::PolygonFilter::property_glob("one", "1*")).to_s, "(1,1;1,201;101,201;101,1){one=>17}")
assert_equal(r.filtered(RBA::PolygonFilter::property_glob("one", "1*", true)).to_s, "(2,2;2,202;102,202;102,2){one=>42};(0,0;0,200;100,200;100,0){one=>-1}")
ly = RBA::Layout::new
top = ly.create_cell("TOP")
l1 = ly.layer(1, 0)
s = top.shapes(l1)
s.insert(RBA::PolygonWithProperties::new(RBA::Box::new(0, 0, 100, 200), { "one" => -1 }))
s.insert(RBA::PolygonWithProperties::new(RBA::Box::new(1, 1, 101, 201), { "one" => 17 }))
s.insert(RBA::PolygonWithProperties::new(RBA::Box::new(2, 2, 102, 202), { "one" => 42 }))
dss = RBA::DeepShapeStore::new
iter = top.begin_shapes_rec(l1)
iter.enable_properties()
r = RBA::Region::new(iter, dss)
assert_equal(r.filtered(RBA::PolygonFilter::property_filter("one", 11)).to_s, "")
assert_equal(r.filtered(RBA::PolygonFilter::property_filter("two", 17)).to_s, "")
assert_equal(r.filtered(RBA::PolygonFilter::property_filter("one", 17)).to_s, "(1,1;1,201;101,201;101,1){one=>17}")
assert_equal(r.filtered(RBA::PolygonFilter::property_filter("one", 17, true)).to_s, "(0,0;0,200;100,200;100,0){one=>-1};(2,2;2,202;102,202;102,2){one=>42}")
assert_equal(r.filtered(RBA::PolygonFilter::property_filter_bounded("one", 17, nil)).to_s, "(1,1;1,201;101,201;101,1){one=>17};(2,2;2,202;102,202;102,2){one=>42}")
assert_equal(r.filtered(RBA::PolygonFilter::property_filter_bounded("one", 17, 18)).to_s, "(1,1;1,201;101,201;101,1){one=>17}")
assert_equal(r.filtered(RBA::PolygonFilter::property_filter_bounded("one", 17, 18, true)).to_s, "(0,0;0,200;100,200;100,0){one=>-1};(2,2;2,202;102,202;102,2){one=>42}")
assert_equal(r.filtered(RBA::PolygonFilter::property_filter_bounded("one", nil, 18)).to_s, "(0,0;0,200;100,200;100,0){one=>-1};(1,1;1,201;101,201;101,1){one=>17}")
assert_equal(r.filtered(RBA::PolygonFilter::property_glob("one", "1*")).to_s, "(1,1;1,201;101,201;101,1){one=>17}")
assert_equal(r.filtered(RBA::PolygonFilter::property_glob("one", "1*", true)).to_s, "(0,0;0,200;100,200;100,0){one=>-1};(2,2;2,202;102,202;102,2){one=>42}")
end
end
load("test_epilogue.rb")