WIP: new ratio filters, squares for DRC

This commit is contained in:
Matthias Koefferlein 2021-01-13 02:12:33 +01:00
parent 8c8c9a6911
commit a8f08bffac
4 changed files with 298 additions and 8 deletions

View File

@ -496,6 +496,12 @@ static db::CompoundRegionOperationNode *new_bbox_filter (db::CompoundRegionOpera
return new db::CompoundRegionFilterOperationNode (new db::RegionBBoxFilter (vmin, vmax, inverse, parameter), input, true);
}
static db::CompoundRegionOperationNode *new_ratio_filter (db::CompoundRegionOperationNode *input, db::RegionRatioFilter::parameter_type parameter, bool inverse, double vmin, bool vmin_included, double vmax, bool vmax_included)
{
check_non_null (input, "input");
return new db::CompoundRegionFilterOperationNode (new db::RegionRatioFilter (vmin, vmin_included, vmax, vmax_included, inverse, parameter), input, true);
}
static db::CompoundRegionOperationNode *new_start_segments (db::CompoundRegionOperationNode *input, db::Edges::length_type length, double fraction)
{
check_non_null (input, "input");
@ -663,6 +669,11 @@ Class<db::CompoundRegionOperationNode> decl_CompoundRegionOperationNode ("db", "
"This node renders the input if the specified bounding box parameter of the input shape is between pmin and pmax (exclusively). If 'inverse' is set to true, the "
"input shape is returned if the parameter is less than pmin (exclusively) or larger than pmax (inclusively)."
) +
gsi::constructor ("new_ratio_filter", &new_ratio_filter, gsi::arg ("input"), gsi::arg ("parameter"), gsi::arg ("inverse", false), gsi::arg ("pmin", 0.0), gsi::arg ("pmin_included"), gsi::arg ("pmax", std::numeric_limits<double>::max (), "max"), gsi::arg ("pmax_included", true),
"@brief Creates a node filtering the input by ratio parameters.\n"
"This node renders the input if the specified ratio parameter of the input shape is between pmin and pmax. If 'pmin_included' is true, the range will include pmin. Same for 'pmax_included' and pmax. "
"If 'inverse' is set to true, the input shape is returned if the parameter is not within the specified range."
) +
gsi::constructor ("new_rectilinear_filter", &new_rectilinear_filter, gsi::arg ("input"), gsi::arg ("inverse", false),
"@brief Creates a node filtering the input for rectilinear shapes (or non-rectilinear ones with 'inverse' set to 'true').\n"
) +
@ -851,5 +862,20 @@ gsi::EnumIn<db::CompoundRegionOperationNode, db::RegionBBoxFilter::parameter_typ
"This enum has been introduced in version 0.27."
);
gsi::EnumIn<db::CompoundRegionOperationNode, db::RegionRatioFilter::parameter_type> decl_dbRegionRatioFilter_ParameterType ("db", "ParameterType",
gsi::enum_const ("AreaRatio", db::RegionRatioFilter::AreaRatio,
"@brief Measures the area ratio (bounding box area / polygon area)\n"
) +
gsi::enum_const ("AspectRatio", db::RegionRatioFilter::AspectRatio,
"@brief Measures the aspect ratio of the bounding box (larger / smaller dimension)\n"
) +
gsi::enum_const ("RelativeHeight", db::RegionRatioFilter::RelativeHeight,
"@brief Measures the relative height (height / width)\n"
),
"@brief This class represents the parameter type enum used in \\CompoundRegionOperationNode#new_ratio_filter\n"
"\n"
"This enum has been introduced in version 0.27."
);
}

View File

@ -29,6 +29,8 @@ module DRC
# @ul
# @li \global#angle @/li
# @li \global#area @/li
# @li \global#area_ratio @/li
# @li \global#bbox_area_ratio @/li
# @li \global#bbox_height @/li
# @li \global#bbox_max @/li
# @li \global#bbox_min @/li
@ -60,6 +62,7 @@ module DRC
# @li \global#primary @/li
# @li \global#rectangles @/li
# @li \global#rectilinear @/li
# @li \global#relative_height @/li
# @li \global#rounded_corners @/li
# @li \global#secondary @/li
# @li \global#separation @/li
@ -67,6 +70,7 @@ module DRC
# @li \global#sized @/li
# @li \global#smoothed @/li
# @li \global#space @/li
# @li \global#squares @/li
# @li \global#width @/li
# @/ul
#
@ -269,7 +273,7 @@ CODE
# %DRC%
# @name perimeter
# @brief Selects the primary shape if the perimeter is meeting the condition
# @brief Selects the input polygon if the perimeter is meeting the condition
# @synopsis expression.perimeter (in condition)
#
# This operation is used in conditions to select shapes based on their perimeter.
@ -294,7 +298,7 @@ CODE
# %DRC%
# @name bbox_min
# @brief Selects the primary shape if its bounding box smaller dimension is meeting the condition
# @brief Selects the input polygon if its bounding box smaller dimension is meeting the condition
# @synopsis expression.bbox_min (in condition)
#
# This operation is used in conditions to select shapes based on smaller dimension of their bounding boxes.
@ -320,7 +324,7 @@ CODE
# %DRC%
# @name bbox_max
# @brief Selects the primary shape if its bounding box larger dimension is meeting the condition
# @brief Selects the input polygon if its bounding box larger dimension is meeting the condition
# @synopsis expression.bbox_max (in condition)
#
# This operation acts similar to \DRC#bbox_min, but takes the larger dimension of the shape's
@ -335,7 +339,7 @@ CODE
# %DRC%
# @name bbox_width
# @brief Selects the primary shape if its bounding box width is meeting the condition
# @brief Selects the input polygon if its bounding box width is meeting the condition
# @synopsis expression.bbox_width (in condition)
#
# This operation acts similar to \DRC#bbox_min, but takes the width of the shape's
@ -353,7 +357,7 @@ CODE
# %DRC%
# @name bbox_height
# @brief Selects the primary shape if its bounding box height is meeting the condition
# @brief Selects the input polygon if its bounding box height is meeting the condition
# @synopsis expression.bbox_height (in condition)
#
# This operation acts similar to \DRC#bbox_min, but takes the height of the shape's
@ -369,6 +373,95 @@ CODE
DRCOpNodeBBoxParameterFilter::new(@engine, RBA::CompoundRegionOperationNode::ParameterType::BoxHeight, self)
end
# %DRC%
# @name bbox_aspect_ratio
# @brief Selects the input polygon according to the aspect ratio of the bounding box
# @synopsis expression.bbox_aspect_ratio (in condition)
#
# This operation is used in conditions to select shapes based on aspect ratios of their bounding boxes.
# The aspect ratio is computed by dividing the larger of width and height by the smaller of both.
# The aspect ratio is always larger or equal to 1. Square or square-boxed shapes have a
# bounding box aspect ratio of 1.
#
# This filter is applicable on polygon expressions. The result will be the input
# polygon if the bounding box condition is met.
#
# See \Layer#drc for more details about comparison specs.
#
# The following example will select all polygons whose bounding box aspect ratio is larger than 3:
#
# @code
# out = in.drc(bbox_aspect_ratio > 3)
# out = in.drc(primary.bbox_aspect_ratio > 3) # equivalent
# @/code
#
# The "bbox_aspect_ratio" method is available as a plain function or as a method on \DRC## expressions.
# The plain function is equivalent to "primary.bbox_aspect_ratio".
def bbox_aspect_ratio
DRCOpNodeRatioParameterFilter::new(@engine, RBA::CompoundRegionOperationNode::RegionRatioFilter::AspectRatio, self)
end
# %DRC%
# @name relative_height
# @brief Selects the input polygon according to the height vs. width of the bounding box
# @synopsis expression.relative_height (in condition)
#
# This operation is used in conditions to select shapes based on the ratio of bounding box
# height vs. width. The taller the shape, the larger the value. Wide polygons have a value
# below 1. A square has a relative height of 1.
#
# This filter is applicable on polygon expressions. The result will be the input
# polygon if the condition is met.
#
# Don't use this method if you can use \bbox_aspect_ratio, because the latter is
# isotropic and can be used hierarchically without generating rotation variants.
#
# See \Layer#drc for more details about comparison specs.
#
# The following example will select all polygons whose relative height is larger than 3:
#
# @code
# out = in.drc(relative_height > 3)
# out = in.drc(primary.relative_height > 3) # equivalent
# @/code
#
# The "relative_height" method is available as a plain function or as a method on \DRC## expressions.
# The plain function is equivalent to "primary.bbox_aspect_ratio".
def relative_height
DRCOpNodeRatioParameterFilter::new(@engine, RBA::CompoundRegionOperationNode::RegionRatioFilter::RelativeHeight, self)
end
# %DRC%
# @name area_ratio
# @brief Selects the input polygon according to its area ratio (bounding box area by polygon area)
# @synopsis expression.area_ratio (in condition)
#
# This operation is used in conditions to select shapes based on their area ratio.
# The area ratio is the ratio of bounding box vs. polygon area. It's a measure how
# "sparse" the polygons are and how good an approximation the bounding box is.
# The value is always larger or equal than 1. Boxes have a value of 1.
#
# This filter is applicable on polygon expressions. The result will be the input
# polygon if the condition is met.
#
# See \Layer#drc for more details about comparison specs.
#
# The following example will select all polygons whose area ratio is larger than 3:
#
# @code
# out = in.drc(area_ratio > 3)
# out = in.drc(primary.area_ratio > 3) # equivalent
# @/code
#
# The "area_ratio" method is available as a plain function or as a method on \DRC## expressions.
# The plain function is equivalent to "primary.area_ratio".
def area_ratio
DRCOpNodeRatioParameterFilter::new(@engine, RBA::CompoundRegionOperationNode::RegionRatioFilter::AreaRatio, self)
end
# %DRC%
# @name length
# @brief Selects edges based on their length
@ -627,7 +720,25 @@ CODE
# @/code
def rectangles
return DRCOpNodeFilter::new(@engine, self, :new_rectangle_filter, "rectangle")
return DRCOpNodeFilter::new(@engine, self, :new_rectangle_filter, "rectangle", false)
end
# %DRC%
# @name squares
# @brief Selects all polygons which are squares
# @synopsis expression.squares
#
# 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 squares:
#
# @code
# out = in.drc(squares)
# out = in.drc(primary.squares) # equivalent
# @/code
def squares
return DRCOpNodeFilter::new(@engine, self, :new_rectangle_filter, "rectangle", true)
end
# %DRC%

View File

@ -499,11 +499,35 @@ CODE
#
# See \Layer#drc, \bbox_min and \DRC#bbox_min for more details.
# %DRC%
# @name bbox_aspect_ratio
# @brief Selects primary shapes based on the aspect ratio of their bounding boxes
# @synopsis bbox_aspect_ratio (in condition)
#
# See \Layer#drc, \bbox_aspect_ratio and \DRC#bbox_aspect_ratio for more details.
# %DRC%
# @name relative_height
# @brief Selects primary shapes based on the ratio of height and width of their bounding boxes
# @synopsis relative_height (in condition)
#
# See \Layer#drc, \relative_height and \DRC#relative_height for more details.
# %DRC%
# @name area_ratio
# @brief Selects primary shapes based on the ratio of bounding box and polygon area
# @synopsis area_ratio (in condition)
#
# See \Layer#drc, \area_ratio and \DRC#area_ratio for more details.
%w(
bbox_height
bbox_max
bbox_min
bbox_width
bbox_aspect_ratio
area_ratio
relative_height
).each do |f|
eval <<"CODE"
def #{f}
@ -584,6 +608,17 @@ CODE
# argument, "rectangles" represents the rectangles filter for primary shapes in
# \DRC# expressions (see \Layer#drc and \DRC#rectangles for more details).
# %DRC%
# @name squares
# @brief Selects all polygons which are squares
# @synopsis squares
# @synopsis squares(layer)
#
# This function can be used with a layer argument in which case it
# is equivalent to "layer.squares" (see \Layer#squares). Without a layer
# argument, "squares" represents the rectangles filter for primary shapes in
# \DRC# expressions (see \Layer#drc and \DRC#squares for more details).
# %DRC%
# @name rectilinear
# @brief Selects all polygons which are rectilinear
@ -623,6 +658,7 @@ CODE
odd_polygons
perimeter
rectangles
squares
rectilinear
length
angle

View File

@ -517,6 +517,106 @@ CODE
end
end
# %DRC%
# @name with_bbox_aspect_ratio
# @brief Selects polygons by the aspect ratio of their bounding box
# @synopsis layer.with_bbox_aspect_ratio(min .. max)
# @synopsis layer.with_bbox_aspect_ratio(value)
# @synopsis layer.with_bbox_aspect_ratio(min, max)
# The method selects polygons similar to \with_area or \with_perimeter.
# However, the measured value is the aspect ratio of the bounding
# box. It is the larger dimensions divided by the smaller one.
# The "thinner" the polygon, the larger the aspect ratio. A square
# bounding box gives an aspect ratio of 1.
#
# This method is available for polygon layers only.
# %DRC%
# @name without_bbox_height
# @brief Selects polygons by the aspect ratio of their bounding box
# @synopsis layer.without_bbox_aspect_ratio(min .. max)
# @synopsis layer.without_bbox_aspect_ratio(value)
# @synopsis layer.without_bbox_aspect_ratio(min, max)
# The method provides the opposite filter for \with_bbox_aspect_ratio.
#
# This method is available for polygon layers only.
# %DRC%
# @name with_area_ratio
# @brief Selects polygons by the ratio of the bounding box area vs. polygon area
# @synopsis layer.with_area_ratio(min .. max)
# @synopsis layer.with_area_ratio(value)
# @synopsis layer.with_area_ratio(min, max)
# The area ratio is a measure how far a polygon is approximated by it's
# bounding box. The value is always larger or equal to 1. Boxes have a
# area ratio of 1. Larger values mean more empty area inside the bounding box.
#
# This method is available for polygon layers only.
# %DRC%
# @name without_area_ratio
# @brief Selects polygons by the aspect ratio of their bounding box
# @synopsis layer.without_area_ratio(min .. max)
# @synopsis layer.without_area_ratio(value)
# @synopsis layer.without_area_ratio(min, max)
# The method provides the opposite filter for \with_area_ratio.
#
# This method is available for polygon layers only.
# %DRC%
# @name with_relative_height
# @brief Selects polygons by the ratio of the height vs. width of it's bounding box
# @synopsis layer.with_relative_height(min .. max)
# @synopsis layer.with_relative_height(value)
# @synopsis layer.with_relative_height(min, max)
# The relative height is a measure how tall a polygon is. Tall polygons
# have values larger than 1, wide polygons have a value smaller than 1.
# Squares have a value of 1.
#
# Don't use this method when you can use \with_area_ratio, which provides a
# similar measure but is isotropic.
#
# This method is available for polygon layers only.
# %DRC%
# @name without_relative_height
# @brief Selects polygons by the ratio of the height vs. width
# @synopsis layer.without_relative_height(min .. max)
# @synopsis layer.without_relative_height(value)
# @synopsis layer.without_relative_height(min, max)
# The method provides the opposite filter for \with_relative_height.
#
# This method is available for polygon layers only.
%w(area_ratio bbox_aspect_ratio relative_height).each do |f|
[true, false].each do |inv|
mn = (inv ? "without" : "with") + "_" + f
eval <<"CODE"
def #{mn}(*args)
@engine._context("#{mn}") do
requires_region
if args.size == 1
a = args[0]
if a.is_a?(Range)
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, RBA::Region, :with_#{f}, @engine._prep_value(a.first), @engine._make_numeric_value(a.last), #{inv.inspect}))
else
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, RBA::Region, :with_#{f}, @engine._prep_value(a), #{inv.inspect}))
end
elsif args.size == 2
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, RBA::Region, :with_#{f}, @engine._prep_value(args[0]), @engine._make_numeric_value(args[1]), #{inv.inspect}))
else
raise("Invalid number of arguments (1 or 2 expected)")
end
end
end
CODE
end
end
# %DRC%
# @name with_length
# @brief Selects edges by their length
@ -2332,13 +2432,22 @@ CODE
# %DRC%
# @name rectangles
# @brief Selects all rectangle polygons from the input
# @brief Selects all rectangles from the input
# @synopsis layer.rectangles
#
# This method is available for polygon layers. By default "merged" semantics applies,
# i.e. all polygons are merged before rectangles are selected (see \clean and \raw).
# \non_rectangles will select all non-rectangles.
# %DRC%
# @name squares
# @brief Selects all squares from the input
# @synopsis layer.squares
#
# This method is available for polygon layers. By default "merged" semantics applies,
# i.e. all polygons are merged before squares are selected (see \clean and \raw).
# \non_squares will select all non-rectangles.
# %DRC%
# @name rectilinear
# @brief Selects all rectilinear polygons from the input
@ -2348,6 +2457,14 @@ CODE
# i.e. all polygons are merged before rectilinear polygons are selected (see \clean and \raw).
# \non_rectilinear will select all non-rectangles.
# %DRC%
# @name non_squares
# @brief Selects all polygons from the input which are not squares
# @synopsis layer.non_rectangles
#
# This method is available for polygon layers. By default "merged" semantics applies,
# i.e. all polygons are merged before non-squares are selected (see \clean and \raw).
# %DRC%
# @name non_rectangles
# @brief Selects all polygons from the input which are not rectangles
@ -2400,7 +2517,7 @@ CODE
# @/tr
# @/table
%w(rectangles rectilinear non_rectangles non_rectilinear
%w(rectangles rectilinear non_rectangles non_rectilinear squares non_squares
holes hulls).each do |f|
eval <<"CODE"
def #{f}