diff --git a/src/db/db/gsiDeclDbRegion.cc b/src/db/db/gsiDeclDbRegion.cc index 05064472b..b42f8874b 100644 --- a/src/db/db/gsiDeclDbRegion.cc +++ b/src/db/db/gsiDeclDbRegion.cc @@ -48,46 +48,28 @@ namespace gsi { // --------------------------------------------------------------------------------- -// PolygonFilter binding +// Generic shape filter declarations -class PolygonFilterImpl - : public db::AllMustMatchFilter +template +class shape_filter_impl + : public Base { public: - PolygonFilterImpl () + shape_filter_impl () { mp_vars = &m_mag_and_orient; m_wants_variants = true; m_requires_raw_input = false; } - bool issue_selected (const db::Polygon &) const - { - return false; - } - - virtual bool selected (const db::Polygon &polygon) const - { - if (f_selected.can_issue ()) { - return f_selected.issue (&PolygonFilterImpl::issue_selected, polygon); - } else { - return db::AllMustMatchFilter::selected (polygon); - } - } - - virtual bool selected (const db::PolygonRef &polygon) const - { - db::Polygon p; - polygon.instantiate (p); - return selected (p); - } - - virtual const db::TransformationReducer *vars () const + // overrides virtual method + const db::TransformationReducer *vars () const { return mp_vars; } - virtual bool requires_raw_input () const + // maybe overrides virtual method + bool requires_raw_input () const { return m_requires_raw_input; } @@ -97,7 +79,8 @@ public: m_requires_raw_input = f; } - virtual bool wants_variants () const + // overrides virtual method + bool wants_variants () const { return m_wants_variants; } @@ -122,68 +105,120 @@ public: mp_vars = 0; } -public: + static gsi::Methods method_decls (bool with_requires_raw_input) + { + gsi::Methods decls; + + if (with_requires_raw_input) { + decls = + method ("requires_raw_input?", &shape_filter_impl::requires_raw_input, + "@brief Gets a value indicating whether the filter needs raw (unmerged) input\n" + "See \\requires_raw_input= for details.\n" + ) + + method ("requires_raw_input=", &shape_filter_impl::set_requires_raw_input, gsi::arg ("flag"), + "@brief Sets a value indicating whether the filter needs raw (unmerged) input\n" + "This flag must be set before using this filter. It tells the filter implementation whether the " + "filter wants to have raw input (unmerged). The default value is 'false', meaning that\n" + "the filter will receive merged polygons ('merged semantics').\n" + "\n" + "Setting this value to false potentially saves some CPU time needed for merging the polygons.\n" + "Also, raw input means that strange shapes such as dot-like edges, self-overlapping polygons, " + "empty or degenerated polygons are preserved." + ); + } + + decls += + method ("wants_variants?", &shape_filter_impl::wants_variants, + "@brief Gets a value indicating whether the filter prefers cell variants\n" + "See \\wants_variants= for details.\n" + ) + + method ("wants_variants=", &shape_filter_impl::set_wants_variants, gsi::arg ("flag"), + "@brief Sets a value indicating whether the filter prefers cell variants\n" + "This flag must be set before using this filter for hierarchical applications (deep mode). " + "It tells the filter implementation whether cell variants should be created (true, the default) " + "or shape propagation will be applied (false).\n" + "\n" + "This decision needs to be made, if the filter indicates that it will deliver different results\n" + "for scaled or rotated versions of the shape (see \\is_isotropic and the other hints). If a cell\n" + "is present with different qualities - as seen from the top cell - the respective instances\n" + "need to be differentiated. Cell variant formation is one way, shape propagation the other way.\n" + "Typically, cell variant formation is less expensive, but the hierarchy will be modified." + ) + + method ("is_isotropic", &shape_filter_impl::is_isotropic, + "@brief Indicates that the filter has isotropic properties\n" + "Call this method before using the filter to indicate that the selection is independent of " + "the orientation of the shape. This helps the filter algorithm optimizing the filter run, specifically in " + "hierarchical mode.\n" + "\n" + "Examples for isotropic (polygon) filters are area or perimeter filters. The area or perimeter of a polygon " + "depends on the scale, but not on the orientation of the polygon." + ) + + method ("is_scale_invariant", &shape_filter_impl::is_scale_invariant, + "@brief Indicates that the filter is scale invariant\n" + "Call this method before using the filter to indicate that the selection is independent of " + "the scale of the shape. This helps the filter algorithm optimizing the filter run, specifically in " + "hierarchical mode.\n" + "\n" + "An example for a scale invariant (polygon) filter is the bounding box aspect ratio (height/width) filter. " + "The definition of heigh and width depends on the orientation, but the ratio is independent on scale." + ) + + method ("is_isotropic_and_scale_invariant", &shape_filter_impl::is_isotropic_and_scale_invariant, + "@brief Indicates that the filter is isotropic and scale invariant\n" + "Call this method before using the filter to indicate that the selection is independent of " + "the scale and orientation of the shape. This helps the filter algorithm optimizing the filter run, specifically in " + "hierarchical mode.\n" + "\n" + "An example for such a (polygon) filter is the square selector. Whether a polygon is a square or not does not depend on " + "the polygon's orientation nor scale." + ); + + return decls; + } + +private: const db::TransformationReducer *mp_vars; db::OrientationReducer m_orientation; db::MagnificationReducer m_mag; db::MagnificationAndOrientationReducer m_mag_and_orient; bool m_requires_raw_input; bool m_wants_variants; +}; + +// --------------------------------------------------------------------------------- +// PolygonFilter binding + +class PolygonFilterImpl + : public shape_filter_impl +{ +public: + PolygonFilterImpl () { } + + bool issue_selected (const db::Polygon &) const + { + return false; + } + + virtual bool selected (const db::Polygon &polygon) const + { + if (f_selected.can_issue ()) { + return f_selected.issue (&PolygonFilterImpl::issue_selected, polygon); + } else { + return db::AllMustMatchFilter::selected (polygon); + } + } + + virtual bool selected (const db::PolygonRef &polygon) const + { + db::Polygon p; + polygon.instantiate (p); + return selected (p); + } gsi::Callback f_selected; }; Class decl_PluginFactory ("db", "PolygonFilter", - method ("requires_raw_input?", &PolygonFilterImpl::requires_raw_input, - "@brief Gets a value indicating whether the filter needs raw (unmerged) input\n" - "See \\requires_raw_input= for details.\n" - ) + - method ("requires_raw_input=", &PolygonFilterImpl::set_requires_raw_input, gsi::arg ("flag"), - "@brief Sets a value indicating whether the filter needs raw (unmerged) input\n" - "This flag must be set before using this filter. It tells the filter implementation whether the " - "filter wants to have raw input (unmerged). The default value is 'false', meaning that\n" - "the filter will receive merged polygons. Setting this value to false potentially saves some\n" - "CPU time needed for merging the polygons.\n" - ) + - method ("wants_variants?", &PolygonFilterImpl::wants_variants, - "@brief Gets a value indicating whether the filter prefers cell variants\n" - "See \\wants_variants= for details.\n" - ) + - method ("wants_variants=", &PolygonFilterImpl::set_wants_variants, gsi::arg ("flag"), - "@brief Sets a value indicating whether the filter prefers cell variants\n" - "This flag must be set before using this filter. It tells the filter implementation whether cell " - "variants should be created (true, the default) or shape propagation will be applied (false).\n" - "\n" - "This decision needs to be make if the filter indicates that it will deliver different results\n" - "for scaled or rotated versions of the cell (see \\is_isotropic and the other hints). If a cell\n" - "is present with different respective qualities - as seen from the top cell - these instances\n" - "need to be differentiated. Cell variant formation is one way, shape propagation the other way.\n" - "Typically, cell variant formation is less expensive, but the hierarchy will be modified internally." - ) + - method ("is_isotropic", &PolygonFilterImpl::is_isotropic, - "@brief Indicates that the filter has isotropic properties\n" - "Call this method before using the filter to indicate that the selection is independent of " - "the orientation of the shape. This helps the filter algorithm optimizing the filter run, specifically in " - "hierarchical mode.\n" - "\n" - "Examples for isotropic filters are area or perimeter filters." - ) + - method ("is_scale_invariant", &PolygonFilterImpl::is_scale_invariant, - "@brief Indicates that the filter is scale invariant\n" - "Call this method before using the filter to indicate that the selection is independent of " - "the scale of the shape. This helps the filter algorithm optimizing the filter run, specifically in " - "hierarchical mode.\n" - "\n" - "An example for a scale invariant filter is the bounding box aspect ratio (height/width) filter." - ) + - method ("is_isotropic_and_scale_invariant", &PolygonFilterImpl::is_isotropic_and_scale_invariant, - "@brief Indicates that the filter is isotropic and scale invariant\n" - "Call this method before using the filter to indicate that the selection is independent of " - "the scale and orientation of the shape. This helps the filter algorithm optimizing the filter run, specifically in " - "hierarchical mode.\n" - "\n" - "An example for such a filter is the rectangle selector." - ) + + 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"