Some refactoring.

This commit is contained in:
Matthias Koefferlein 2024-01-26 10:30:03 +01:00
parent 0b77ef996b
commit 2dca4158f2
1 changed files with 114 additions and 79 deletions

View File

@ -48,46 +48,28 @@ namespace gsi
{
// ---------------------------------------------------------------------------------
// PolygonFilter binding
// Generic shape filter declarations
class PolygonFilterImpl
: public db::AllMustMatchFilter
template <class Base>
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, bool, const db::Polygon &> (&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<db::AllMustMatchFilter>
{
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, bool, const db::Polygon &> (&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<gsi::PolygonFilterImpl> 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"