mirror of https://github.com/KLayout/klayout.git
DRC binding for property computation, filtering
This commit is contained in:
parent
2193f28e2a
commit
c8568e8aed
|
|
@ -743,9 +743,17 @@ AsIfFlatEdges::filtered_pair (const EdgeFilterBase &filter) const
|
||||||
|
|
||||||
for (EdgesIterator p (begin_merged ()); ! p.at_end (); ++p) {
|
for (EdgesIterator p (begin_merged ()); ! p.at_end (); ++p) {
|
||||||
if (filter.selected (*p, p.prop_id ())) {
|
if (filter.selected (*p, p.prop_id ())) {
|
||||||
new_region_true->insert (*p);
|
if (p.prop_id () != 0) {
|
||||||
|
new_region_true->insert (db::EdgeWithProperties (*p, p.prop_id ()));
|
||||||
|
} else {
|
||||||
|
new_region_true->insert (*p);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
new_region_false->insert (*p);
|
if (p.prop_id () != 0) {
|
||||||
|
new_region_false->insert (db::EdgeWithProperties (*p, p.prop_id ()));
|
||||||
|
} else {
|
||||||
|
new_region_false->insert (*p);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -526,9 +526,17 @@ AsIfFlatRegion::filtered_pair (const PolygonFilterBase &filter) const
|
||||||
|
|
||||||
for (RegionIterator p (begin_merged ()); ! p.at_end (); ++p) {
|
for (RegionIterator p (begin_merged ()); ! p.at_end (); ++p) {
|
||||||
if (filter.selected (*p, p.prop_id ())) {
|
if (filter.selected (*p, p.prop_id ())) {
|
||||||
new_region_true->insert (*p);
|
if (p.prop_id () != 0) {
|
||||||
|
new_region_true->insert (db::PolygonWithProperties (*p, p.prop_id ()));
|
||||||
|
} else {
|
||||||
|
new_region_true->insert (*p);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
new_region_false->insert (*p);
|
if (p.prop_id () != 0) {
|
||||||
|
new_region_false->insert (db::PolygonWithProperties (*p, p.prop_id ()));
|
||||||
|
} else {
|
||||||
|
new_region_false->insert (*p);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -179,9 +179,17 @@ AsIfFlatTexts::filtered_pair (const TextFilterBase &filter) const
|
||||||
|
|
||||||
for (TextsIterator p (begin ()); ! p.at_end (); ++p) {
|
for (TextsIterator p (begin ()); ! p.at_end (); ++p) {
|
||||||
if (filter.selected (*p, p.prop_id ())) {
|
if (filter.selected (*p, p.prop_id ())) {
|
||||||
new_texts_true->insert (*p);
|
if (p.prop_id () != 0) {
|
||||||
|
new_texts_true->insert (db::TextWithProperties (*p, p.prop_id ()));
|
||||||
|
} else {
|
||||||
|
new_texts_true->insert (*p);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
new_texts_false->insert (*p);
|
if (p.prop_id () != 0) {
|
||||||
|
new_texts_false->insert (db::TextWithProperties (*p, p.prop_id ()));
|
||||||
|
} else {
|
||||||
|
new_texts_false->insert (*p);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2105,12 +2105,18 @@ LayoutToNetlist::measure_net (const db::Region &primary, const std::map<std::str
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
eval.reset (*cid, *c);
|
try {
|
||||||
compiled_expr.execute ();
|
|
||||||
|
|
||||||
if (! eval.skip ()) {
|
eval.reset (*cid, *c);
|
||||||
db::Shapes &shapes = ly.cell (*cid).shapes (dl.layer ());
|
compiled_expr.execute ();
|
||||||
get_merged_shapes_of_net (*cid, *c, primary_layer, shapes, db::properties_id (eval.prop_set_out ()));
|
|
||||||
|
if (! eval.skip ()) {
|
||||||
|
db::Shapes &shapes = ly.cell (*cid).shapes (dl.layer ());
|
||||||
|
get_merged_shapes_of_net (*cid, *c, primary_layer, shapes, db::properties_id (eval.prop_set_out ()));
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (tl::Exception &ex) {
|
||||||
|
tl::warn << ex.msg ();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,28 @@ private:
|
||||||
MeasureEval *mp_eval;
|
MeasureEval *mp_eval;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SkipFunction
|
||||||
|
: public tl::EvalFunction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SkipFunction (MeasureEval *eval)
|
||||||
|
: mp_eval (eval)
|
||||||
|
{
|
||||||
|
// .. nothing yet ..
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void execute (const tl::ExpressionParserContext &context, tl::Variant & /*out*/, const std::vector<tl::Variant> &args, const std::map<std::string, tl::Variant> * /*kwargs*/) const
|
||||||
|
{
|
||||||
|
if (args.size () != 1) {
|
||||||
|
throw tl::EvalError (tl::to_string (tr ("'skip' function takes one argument (flag)")), context);
|
||||||
|
}
|
||||||
|
mp_eval->skip_func (args [0].to_bool ());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
MeasureEval *mp_eval;
|
||||||
|
};
|
||||||
|
|
||||||
class ValueFunction
|
class ValueFunction
|
||||||
: public tl::EvalFunction
|
: public tl::EvalFunction
|
||||||
{
|
{
|
||||||
|
|
@ -144,7 +166,7 @@ private:
|
||||||
// MeasureEval implementation
|
// MeasureEval implementation
|
||||||
|
|
||||||
MeasureEval::MeasureEval (double dbu, bool with_put)
|
MeasureEval::MeasureEval (double dbu, bool with_put)
|
||||||
: m_shape_type (None), m_prop_id (0), m_dbu (dbu), m_with_put (with_put)
|
: m_shape_type (None), m_prop_id (0), m_skip (false), m_dbu (dbu), m_with_put (with_put)
|
||||||
{
|
{
|
||||||
mp_shape.any = 0;
|
mp_shape.any = 0;
|
||||||
}
|
}
|
||||||
|
|
@ -154,6 +176,7 @@ MeasureEval::init ()
|
||||||
{
|
{
|
||||||
if (m_with_put) {
|
if (m_with_put) {
|
||||||
define_function ("put", new PutFunction (this));
|
define_function ("put", new PutFunction (this));
|
||||||
|
define_function ("skip", new SkipFunction (this));
|
||||||
}
|
}
|
||||||
|
|
||||||
define_function ("shape", new ShapeFunction (this));
|
define_function ("shape", new ShapeFunction (this));
|
||||||
|
|
@ -161,14 +184,6 @@ MeasureEval::init ()
|
||||||
define_function ("values", new ValuesFunction (this));
|
define_function ("values", new ValuesFunction (this));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
MeasureEval::reset_shape () const
|
|
||||||
{
|
|
||||||
m_shape_type = None;
|
|
||||||
mp_shape.any = 0;
|
|
||||||
m_prop_id = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
MeasureEval::set_shape (const db::Polygon *poly) const
|
MeasureEval::set_shape (const db::Polygon *poly) const
|
||||||
{
|
{
|
||||||
|
|
@ -205,9 +220,10 @@ MeasureEval::set_shape (const db::Text *text) const
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MeasureEval::set_prop_id (db::properties_id_type prop_id) const
|
MeasureEval::reset (db::properties_id_type prop_id) const
|
||||||
{
|
{
|
||||||
m_prop_id = prop_id;
|
m_prop_id = prop_id;
|
||||||
|
m_skip = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -223,6 +239,12 @@ MeasureEval::resolve_name (const std::string &name, const tl::EvalFunction *&fun
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MeasureEval::skip_func (bool f) const
|
||||||
|
{
|
||||||
|
m_skip = f;
|
||||||
|
}
|
||||||
|
|
||||||
tl::Variant
|
tl::Variant
|
||||||
MeasureEval::shape_func () const
|
MeasureEval::shape_func () const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -49,13 +49,17 @@ public:
|
||||||
|
|
||||||
void init ();
|
void init ();
|
||||||
|
|
||||||
void reset_shape () const;
|
void reset (db::properties_id_type prop_id) const;
|
||||||
void set_shape (const db::Polygon *poly) const;
|
void set_shape (const db::Polygon *poly) const;
|
||||||
void set_shape (const db::PolygonRef *poly) const;
|
void set_shape (const db::PolygonRef *poly) const;
|
||||||
void set_shape (const db::Edge *edge) const;
|
void set_shape (const db::Edge *edge) const;
|
||||||
void set_shape (const db::EdgePair *edge_pair) const;
|
void set_shape (const db::EdgePair *edge_pair) const;
|
||||||
void set_shape (const db::Text *text) const;
|
void set_shape (const db::Text *text) const;
|
||||||
void set_prop_id (db::properties_id_type prop_id) const;
|
|
||||||
|
bool skip () const
|
||||||
|
{
|
||||||
|
return m_skip;
|
||||||
|
}
|
||||||
|
|
||||||
db::PropertiesSet &prop_set_out () const
|
db::PropertiesSet &prop_set_out () const
|
||||||
{
|
{
|
||||||
|
|
@ -67,6 +71,7 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class ShapeFunction;
|
friend class ShapeFunction;
|
||||||
|
friend class SkipFunction;
|
||||||
friend class ValueFunction;
|
friend class ValueFunction;
|
||||||
friend class ValuesFunction;
|
friend class ValuesFunction;
|
||||||
friend class PropertyFunction;
|
friend class PropertyFunction;
|
||||||
|
|
@ -95,6 +100,7 @@ private:
|
||||||
mutable ShapeType m_shape_type;
|
mutable ShapeType m_shape_type;
|
||||||
mutable ShapeRef mp_shape;
|
mutable ShapeRef mp_shape;
|
||||||
mutable db::properties_id_type m_prop_id;
|
mutable db::properties_id_type m_prop_id;
|
||||||
|
mutable bool m_skip;
|
||||||
mutable db::PropertiesSet m_prop_set_out;
|
mutable db::PropertiesSet m_prop_set_out;
|
||||||
double m_dbu;
|
double m_dbu;
|
||||||
bool m_with_put;
|
bool m_with_put;
|
||||||
|
|
@ -104,6 +110,7 @@ private:
|
||||||
tl::Variant value_func (const tl::Variant &name) const;
|
tl::Variant value_func (const tl::Variant &name) const;
|
||||||
tl::Variant values_func (const tl::Variant &name) const;
|
tl::Variant values_func (const tl::Variant &name) const;
|
||||||
void put_func (const tl::Variant &name, const tl::Variant &value) const;
|
void put_func (const tl::Variant &name, const tl::Variant &value) const;
|
||||||
|
void skip_func (bool f) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -300,13 +300,14 @@ Class<property_computation_processor<db::EdgePairProcessorBase, db::EdgePairs> >
|
||||||
"is attached to the output edge pairs as user properties with the given names.\n"
|
"is attached to the output edge pairs as user properties with the given names.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Alternatively, a single expression can be given. In that case, 'put' needs to be used to attach properties "
|
"Alternatively, a single expression can be given. In that case, 'put' needs to be used to attach properties "
|
||||||
"to the output shape.\n"
|
"to the output shape. You can also use 'skip' to drop shapes in that case.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"The expression may use the following variables and functions:\n"
|
"The expression may use the following variables and functions:\n"
|
||||||
"\n"
|
"\n"
|
||||||
"@ul\n"
|
"@ul\n"
|
||||||
"@li @b shape @/b: The current shape (i.e. 'EdgePair' without DBU specified or 'DEdgePair' otherwise) @/li\n"
|
"@li @b shape @/b: The current shape (i.e. 'EdgePair' without DBU specified or 'DEdgePair' otherwise) @/li\n"
|
||||||
"@li @b put(<name>, <value>) @/b: Attaches the given value as a property with name 'name' to the output shape @/li\n"
|
"@li @b put(<name>, <value>) @/b: Attaches the given value as a property with name 'name' to the output shape @/li\n"
|
||||||
|
"@li @b skip(<flag>) @/b: If called with a 'true' value, the shape is dropped from the output @/li\n"
|
||||||
"@li @b value(<name>) @/b: The value of the property with the given name (the first one if there are multiple properties with the same name) @/li\n"
|
"@li @b value(<name>) @/b: The value of the property with the given name (the first one if there are multiple properties with the same name) @/li\n"
|
||||||
"@li @b values(<name>) @/b: All values of the properties with the given name (returns a list) @/li\n"
|
"@li @b values(<name>) @/b: All values of the properties with the given name (returns a list) @/li\n"
|
||||||
"@li @b <name> @/b: A shortcut for 'value(<name>)' (<name> is used as a symbol) @/li\n"
|
"@li @b <name> @/b: A shortcut for 'value(<name>)' (<name> is used as a symbol) @/li\n"
|
||||||
|
|
|
||||||
|
|
@ -305,13 +305,14 @@ Class<property_computation_processor<db::EdgeProcessorBase, db::Edges> > decl_Ed
|
||||||
"is attached to the output edge pairs as user properties with the given names.\n"
|
"is attached to the output edge pairs as user properties with the given names.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Alternatively, a single expression can be given. In that case, 'put' needs to be used to attach properties "
|
"Alternatively, a single expression can be given. In that case, 'put' needs to be used to attach properties "
|
||||||
"to the output shape.\n"
|
"to the output shape. You can also use 'skip' to drop shapes in that case.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"The expression may use the following variables and functions:\n"
|
"The expression may use the following variables and functions:\n"
|
||||||
"\n"
|
"\n"
|
||||||
"@ul\n"
|
"@ul\n"
|
||||||
"@li @b shape @/b: The current shape (i.e. 'Edge' without DBU specified or 'DEdge' otherwise) @/li\n"
|
"@li @b shape @/b: The current shape (i.e. 'Edge' without DBU specified or 'DEdge' otherwise) @/li\n"
|
||||||
"@li @b put(<name>, <value>) @/b: Attaches the given value as a property with name 'name' to the output shape @/li\n"
|
"@li @b put(<name>, <value>) @/b: Attaches the given value as a property with name 'name' to the output shape @/li\n"
|
||||||
|
"@li @b skip(<flag>) @/b: If called with a 'true' value, the shape is dropped from the output @/li\n"
|
||||||
"@li @b value(<name>) @/b: The value of the property with the given name (the first one if there are multiple properties with the same name) @/li\n"
|
"@li @b value(<name>) @/b: The value of the property with the given name (the first one if there are multiple properties with the same name) @/li\n"
|
||||||
"@li @b values(<name>) @/b: All values of the properties with the given name (returns a list) @/li\n"
|
"@li @b values(<name>) @/b: All values of the properties with the given name (returns a list) @/li\n"
|
||||||
"@li @b <name> @/b: A shortcut for 'value(<name>)' (<name> is used as a symbol) @/li\n"
|
"@li @b <name> @/b: A shortcut for 'value(<name>)' (<name> is used as a symbol) @/li\n"
|
||||||
|
|
|
||||||
|
|
@ -121,36 +121,44 @@ public:
|
||||||
|
|
||||||
virtual void process (const db::object_with_properties<shape_type> &shape, std::vector<db::object_with_properties<shape_type> > &res) const
|
virtual void process (const db::object_with_properties<shape_type> &shape, std::vector<db::object_with_properties<shape_type> > &res) const
|
||||||
{
|
{
|
||||||
res.push_back (shape);
|
try {
|
||||||
|
|
||||||
m_eval.set_prop_id (shape.properties_id ());
|
m_eval.reset (shape.properties_id ());
|
||||||
m_eval.set_shape (&shape);
|
m_eval.set_shape (&shape);
|
||||||
|
|
||||||
|
db::PropertiesSet &ps_out = m_eval.prop_set_out ();
|
||||||
|
if (m_copy_properties) {
|
||||||
|
ps_out = db::properties (shape.properties_id ());
|
||||||
|
for (auto e = m_expressions.begin (); e != m_expressions.end (); ++e) {
|
||||||
|
if (e->first != db::property_names_id_type (0)) {
|
||||||
|
ps_out.erase (e->first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ps_out.clear ();
|
||||||
|
}
|
||||||
|
|
||||||
db::PropertiesSet &ps_out = m_eval.prop_set_out ();
|
|
||||||
if (m_copy_properties) {
|
|
||||||
ps_out = db::properties (shape.properties_id ());
|
|
||||||
for (auto e = m_expressions.begin (); e != m_expressions.end (); ++e) {
|
for (auto e = m_expressions.begin (); e != m_expressions.end (); ++e) {
|
||||||
if (e->first != db::property_names_id_type (0)) {
|
if (e->first != db::property_names_id_type (0)) {
|
||||||
ps_out.erase (e->first);
|
ps_out.insert (e->first, e->second.execute ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
ps_out.clear ();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto e = m_expressions.begin (); e != m_expressions.end (); ++e) {
|
for (auto e = m_expressions.begin (); e != m_expressions.end (); ++e) {
|
||||||
if (e->first != db::property_names_id_type (0)) {
|
if (e->first == db::property_names_id_type (0)) {
|
||||||
ps_out.insert (e->first, e->second.execute ());
|
e->second.execute ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for (auto e = m_expressions.begin (); e != m_expressions.end (); ++e) {
|
if (! m_eval.skip ()) {
|
||||||
if (e->first == db::property_names_id_type (0)) {
|
res.push_back (shape);
|
||||||
e->second.execute ();
|
res.back ().properties_id (db::properties_id (ps_out));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
res.back ().properties_id (db::properties_id (ps_out));
|
} catch (tl::Exception &ex) {
|
||||||
|
tl::warn << ex.msg ();
|
||||||
|
res.clear ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
@ -190,21 +198,35 @@ public:
|
||||||
|
|
||||||
virtual bool selected (const shape_type &shape, db::properties_id_type prop_id) const
|
virtual bool selected (const shape_type &shape, db::properties_id_type prop_id) const
|
||||||
{
|
{
|
||||||
m_eval.set_prop_id (prop_id);
|
try {
|
||||||
m_eval.set_shape (&shape);
|
|
||||||
|
|
||||||
bool res = m_expression.execute ().to_bool ();
|
m_eval.reset (prop_id);
|
||||||
return m_inverse ? !res : res;
|
m_eval.set_shape (&shape);
|
||||||
|
|
||||||
|
bool res = m_expression.execute ().to_bool ();
|
||||||
|
return m_inverse ? !res : res;
|
||||||
|
|
||||||
|
} catch (tl::Exception &ex) {
|
||||||
|
tl::warn << ex.msg ();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// only needed for PolygonFilterBase
|
// only needed for PolygonFilterBase
|
||||||
virtual bool selected (const db::PolygonRef &shape, db::properties_id_type prop_id) const
|
virtual bool selected (const db::PolygonRef &shape, db::properties_id_type prop_id) const
|
||||||
{
|
{
|
||||||
m_eval.set_prop_id (prop_id);
|
try {
|
||||||
m_eval.set_shape (&shape);
|
|
||||||
|
|
||||||
bool res = m_expression.execute ().to_bool ();
|
m_eval.reset (prop_id);
|
||||||
return m_inverse ? !res : res;
|
m_eval.set_shape (&shape);
|
||||||
|
|
||||||
|
bool res = m_expression.execute ().to_bool ();
|
||||||
|
return m_inverse ? !res : res;
|
||||||
|
|
||||||
|
} catch (tl::Exception &ex) {
|
||||||
|
tl::warn << ex.msg ();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
||||||
|
|
@ -320,13 +320,14 @@ Class<property_computation_processor<db::PolygonProcessorBase, db::Region> > dec
|
||||||
"is attached to the output edge pairs as user properties with the given names.\n"
|
"is attached to the output edge pairs as user properties with the given names.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Alternatively, a single expression can be given. In that case, 'put' needs to be used to attach properties "
|
"Alternatively, a single expression can be given. In that case, 'put' needs to be used to attach properties "
|
||||||
"to the output shape.\n"
|
"to the output shape. You can also use 'skip' to drop shapes in that case.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"The expression may use the following variables and functions:\n"
|
"The expression may use the following variables and functions:\n"
|
||||||
"\n"
|
"\n"
|
||||||
"@ul\n"
|
"@ul\n"
|
||||||
"@li @b shape @/b: The current shape (i.e. 'Polygon' without DBU specified or 'DPolygon' otherwise) @/li\n"
|
"@li @b shape @/b: The current shape (i.e. 'Polygon' without DBU specified or 'DPolygon' otherwise) @/li\n"
|
||||||
"@li @b put(<name>, <value>) @/b: Attaches the given value as a property with name 'name' to the output shape @/li\n"
|
"@li @b put(<name>, <value>) @/b: Attaches the given value as a property with name 'name' to the output shape @/li\n"
|
||||||
|
"@li @b skip(<flag>) @/b: If called with a 'true' value, the shape is dropped from the output @/li\n"
|
||||||
"@li @b value(<name>) @/b: The value of the property with the given name (the first one if there are multiple properties with the same name) @/li\n"
|
"@li @b value(<name>) @/b: The value of the property with the given name (the first one if there are multiple properties with the same name) @/li\n"
|
||||||
"@li @b values(<name>) @/b: All values of the properties with the given name (returns a list) @/li\n"
|
"@li @b values(<name>) @/b: All values of the properties with the given name (returns a list) @/li\n"
|
||||||
"@li @b <name> @/b: A shortcut for 'value(<name>)' (<name> is used as a symbol) @/li\n"
|
"@li @b <name> @/b: A shortcut for 'value(<name>)' (<name> is used as a symbol) @/li\n"
|
||||||
|
|
|
||||||
|
|
@ -299,13 +299,14 @@ Class<property_computation_processor<db::TextProcessorBase, db::Texts> > decl_Te
|
||||||
"is attached to the output edge pairs as user properties with the given names.\n"
|
"is attached to the output edge pairs as user properties with the given names.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Alternatively, a single expression can be given. In that case, 'put' needs to be used to attach properties "
|
"Alternatively, a single expression can be given. In that case, 'put' needs to be used to attach properties "
|
||||||
"to the output shape.\n"
|
"to the output shape. You can also use 'skip' to drop shapes in that case.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"The expression may use the following variables and functions:\n"
|
"The expression may use the following variables and functions:\n"
|
||||||
"\n"
|
"\n"
|
||||||
"@ul\n"
|
"@ul\n"
|
||||||
"@li @b shape @/b: The current shape (i.e. 'Text' without DBU specified or 'DText' otherwise) @/li\n"
|
"@li @b shape @/b: The current shape (i.e. 'Text' without DBU specified or 'DText' otherwise) @/li\n"
|
||||||
"@li @b put(<name>, <value>) @/b: Attaches the given value as a property with name 'name' to the output shape @/li\n"
|
"@li @b put(<name>, <value>) @/b: Attaches the given value as a property with name 'name' to the output shape @/li\n"
|
||||||
|
"@li @b skip(<flag>) @/b: If called with a 'true' value, the shape is dropped from the output @/li\n"
|
||||||
"@li @b value(<name>) @/b: The value of the property with the given name (the first one if there are multiple properties with the same name) @/li\n"
|
"@li @b value(<name>) @/b: The value of the property with the given name (the first one if there are multiple properties with the same name) @/li\n"
|
||||||
"@li @b values(<name>) @/b: All values of the properties with the given name (returns a list) @/li\n"
|
"@li @b values(<name>) @/b: All values of the properties with the given name (returns a list) @/li\n"
|
||||||
"@li @b <name> @/b: A shortcut for 'value(<name>)' (<name> is used as a symbol) @/li\n"
|
"@li @b <name> @/b: A shortcut for 'value(<name>)' (<name> is used as a symbol) @/li\n"
|
||||||
|
|
|
||||||
|
|
@ -454,6 +454,19 @@ module DRC
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def aniso(expression)
|
||||||
|
DRCTransformationVariantHint::new(expression, :is_scale_invariant)
|
||||||
|
end
|
||||||
|
|
||||||
|
def scales(expression)
|
||||||
|
DRCTransformationVariantHint::new(expression, :is_isotropic)
|
||||||
|
end
|
||||||
|
|
||||||
|
def aniso_and_scales(expression)
|
||||||
|
DRCTransformationVariantHint::new(expression, nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
# %DRC%
|
# %DRC%
|
||||||
# @brief Specifies "same properties" for operations supporting user properties constraints
|
# @brief Specifies "same properties" for operations supporting user properties constraints
|
||||||
# @name props_eq
|
# @name props_eq
|
||||||
|
|
|
||||||
|
|
@ -5176,7 +5176,7 @@ CODE
|
||||||
# %DRC%
|
# %DRC%
|
||||||
# @name evaluate
|
# @name evaluate
|
||||||
# @brief Evaluate expressions on the shapes of the layer
|
# @brief Evaluate expressions on the shapes of the layer
|
||||||
# @synopsis layer.evaluate(expression [, variables])
|
# @synopsis layer.evaluate(expression [, variables [, keep_properties ]])
|
||||||
#
|
#
|
||||||
# Evaluates the given expression on the shapes of the layer.
|
# Evaluates the given expression on the shapes of the layer.
|
||||||
# The expression needs to be written in the KLayout expressions
|
# The expression needs to be written in the KLayout expressions
|
||||||
|
|
@ -5185,12 +5185,14 @@ CODE
|
||||||
# The expressions can place properties on the shapes using the
|
# The expressions can place properties on the shapes using the
|
||||||
# "put" function. As input, the expressions will receive the
|
# "put" function. As input, the expressions will receive the
|
||||||
# (merged) shapes in micrometer units (e.g. RBA::DPolygon type)
|
# (merged) shapes in micrometer units (e.g. RBA::DPolygon type)
|
||||||
# by calling the "shape" function.
|
# by calling the "shape" function. You can also call 'skip' with
|
||||||
|
# a 'true' value to drop the shape from the output entirely.
|
||||||
#
|
#
|
||||||
# Available functions are:
|
# Available functions are:
|
||||||
#
|
#
|
||||||
# @ul
|
# @ul
|
||||||
# @li "put(name, value)": creates a property with name 'name' and 'value' value @/li
|
# @li "put(name, value)": creates a property with the given name and value @/li
|
||||||
|
# @li "skip(flag)": if called with a 'true' value, the shape will be dropped from the output @/li
|
||||||
# @li "shape": the current shape in micrometer units @/li
|
# @li "shape": the current shape in micrometer units @/li
|
||||||
# @li "value(name)": the value of a property with name 'name' or nil if the current shape does not have a property with this name @/li
|
# @li "value(name)": the value of a property with name 'name' or nil if the current shape does not have a property with this name @/li
|
||||||
# @ul
|
# @ul
|
||||||
|
|
@ -5202,50 +5204,106 @@ CODE
|
||||||
# becomes available as variables in the expression. This eliminates the need
|
# becomes available as variables in the expression. This eliminates the need
|
||||||
# to build expression strings to pass variable values.
|
# to build expression strings to pass variable values.
|
||||||
#
|
#
|
||||||
# The following example computes the area of the shapes and puts them
|
# If 'keep_properties' is true, the existing properties of the shape will be kept.
|
||||||
# into a property 'AREA':
|
# Otherwise (the default), existing properties will be removed before adding new
|
||||||
|
# ones with 'put'.
|
||||||
|
#
|
||||||
|
# The expressions require a hint
|
||||||
|
# whether the they make use of anisotropic or scale-dependent properties.
|
||||||
|
# For example, the height of a box is an anisotropic property. If a check is made
|
||||||
|
# inside a rotated cell, the height transforms to a width and the check renders
|
||||||
|
# different results for the same cell if the cell is placed rotated and non-rotated.
|
||||||
|
# The solution is cell variant formation.
|
||||||
|
#
|
||||||
|
# Similarly, if a check is made against physical dimensions, the check will have
|
||||||
|
# different results for cells placed with different magnifications. Such a check
|
||||||
|
# is not scale-invariant.
|
||||||
|
#
|
||||||
|
# By default it is assumed that the expressions are isotropic and scale invariant.
|
||||||
|
# You can mark an expression as anisotropic and/or scale dependent using the following
|
||||||
|
# expression modifiers:
|
||||||
#
|
#
|
||||||
# @code
|
# @code
|
||||||
# layer.evalute("put('AREA', shape.area)")
|
# # isotropic and scale invariant
|
||||||
|
# layer.evaluate("put('holes', shape.holes)")
|
||||||
|
#
|
||||||
|
# # anisotropic, but scale invariant
|
||||||
|
# layer.evaluate(aniso("put('aspect_ratio', shape.bbox.height/shape.bbox.width)"))
|
||||||
|
#
|
||||||
|
# # isotropic, but not scale invariant
|
||||||
|
# layer.evaluate(scales("put('area', shape.area)"))
|
||||||
|
#
|
||||||
|
# # anisotropic and not scale invariant
|
||||||
|
# layer.evaluate(aniso_and_scales("put('width', shape.bbox.width)"))
|
||||||
# @/code
|
# @/code
|
||||||
#
|
#
|
||||||
|
# If you forget to specify this hint, the expression will use the local
|
||||||
|
# shape properties and fail to correctly produce the results in the presence
|
||||||
|
# of deep mode and rotated or magnified cell instances.
|
||||||
|
#
|
||||||
|
# The following example computes the area of the shapes and puts them
|
||||||
|
# into a property 'area':
|
||||||
|
#
|
||||||
|
# @code
|
||||||
|
# layer.evaluate(scales("put('area', shape.area)"))
|
||||||
|
# @/code
|
||||||
|
#
|
||||||
|
# NOTE: GDS does not support properties with string names, so
|
||||||
|
# either save to OASIS or use integer numbers for the property names.
|
||||||
|
#
|
||||||
# This version modifies the input layer. A version that returns
|
# This version modifies the input layer. A version that returns
|
||||||
# a new layer is \evaluated.
|
# a new layer is \evaluated.
|
||||||
|
|
||||||
# %DRC%
|
# %DRC%
|
||||||
# @name evaluated
|
# @name evaluated
|
||||||
# @brief Evaluate expressions on the shapes of the layer and returns a new layer
|
# @brief Evaluate expressions on the shapes of the layer and returns a new layer
|
||||||
# @synopsis layer.evaluated(expression [, variables])
|
# @synopsis layer.evaluated(expression [, variables [, keep_properties]])
|
||||||
#
|
#
|
||||||
# This method is the out-of-place version of \evaluate.
|
# This method is the out-of-place version of \evaluate.
|
||||||
|
|
||||||
def _make_proc(expression, variables)
|
def _make_proc(expression, variables, keep_properties)
|
||||||
|
|
||||||
expression.is_a?(String) || raise("'expression' must be a string")
|
if expression.is_a?(String)
|
||||||
|
expression = DRCTransformationVariantHint::new(expression)
|
||||||
|
elsif expression.is_a?(DRCTransformationVariantHint)
|
||||||
|
expression.expression.is_a?(String) || raise("'expression' must be a string")
|
||||||
|
else
|
||||||
|
raise("'expression' must be a string or a string decorated with a transformation variant hint")
|
||||||
|
end
|
||||||
variables.is_a?(Hash) || raise("'variables' must be a hash")
|
variables.is_a?(Hash) || raise("'variables' must be a hash")
|
||||||
|
|
||||||
if data.is_a?(RBA::Region)
|
if data.is_a?(RBA::Region)
|
||||||
RBA::PolygonPropertiesExpressions::new(data, expression, dbu: @engine.dbu, variables: variables)
|
pr = RBA::PolygonPropertiesExpressions::new(data, expression.expression, copy_properties: keep_properties, dbu: @engine.dbu, variables: variables)
|
||||||
elsif data.is_a?(RBA::Edges)
|
elsif data.is_a?(RBA::Edges)
|
||||||
RBA::EdgePropertiesExpressions::new(data, expression, dbu: @engine.dbu, variables: variables)
|
pr = RBA::EdgePropertiesExpressions::new(data, expression.expression, copy_properties: keep_properties, dbu: @engine.dbu, variables: variables)
|
||||||
elsif data.is_a?(RBA::EdgePairs)
|
elsif data.is_a?(RBA::EdgePairs)
|
||||||
RBA::EdgePairPropertiesExpressions::new(data, expression, dbu: @engine.dbu, variables: variables)
|
pr = RBA::EdgePairPropertiesExpressions::new(data, expression.expression, copy_properties: keep_properties, dbu: @engine.dbu, variables: variables)
|
||||||
elsif data.is_a?(RBA::Texts)
|
elsif data.is_a?(RBA::Texts)
|
||||||
RBA::TextPropertiesExpressions::new(data, expression, dbu: @engine.dbu, variables: variables)
|
pr = RBA::TextPropertiesExpressions::new(data, expression.expression, copy_properties: keep_properties, dbu: @engine.dbu, variables: variables)
|
||||||
else
|
else
|
||||||
nil
|
pr = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
pr && expression.apply(pr)
|
||||||
|
pr
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def evaluate(expression, variables = {})
|
def evaluate(expression, variables = {}, keep_properties = false)
|
||||||
@engine._context("evaluate") do
|
@engine._context("evaluate") do
|
||||||
pr = _make_proc(expression, variables)
|
pr = _make_proc(expression, variables, keep_properties)
|
||||||
@engine._tcmd(self.data, 0, self.data.class, :process, pr)
|
@engine._tcmd(self.data, 0, self.data.class, :process, pr)
|
||||||
self
|
self
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def evaluated(expression, variables = {}, keep_properties = false)
|
||||||
|
@engine._context("evaluated") do
|
||||||
|
pr = _make_proc(expression, variables, keep_properties)
|
||||||
|
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, self.data.class, :processed, pr))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# %DRC%
|
# %DRC%
|
||||||
# @name select_if
|
# @name select_if
|
||||||
# @brief Selects shapes of a layer based on the evaluation of an expression
|
# @brief Selects shapes of a layer based on the evaluation of an expression
|
||||||
|
|
@ -5255,6 +5313,8 @@ CODE
|
||||||
# If the evaluation gives a 'true' value, the shape is selected. Otherwise
|
# If the evaluation gives a 'true' value, the shape is selected. Otherwise
|
||||||
# it is discarded.
|
# it is discarded.
|
||||||
#
|
#
|
||||||
|
# The expression is written in KLayout expression notation.
|
||||||
|
#
|
||||||
# As input, the expressions will receive the
|
# As input, the expressions will receive the
|
||||||
# (merged) shapes in micrometer units (e.g. RBA::DPolygon type)
|
# (merged) shapes in micrometer units (e.g. RBA::DPolygon type)
|
||||||
# by calling the "shape" function.
|
# by calling the "shape" function.
|
||||||
|
|
@ -5269,6 +5329,39 @@ CODE
|
||||||
# Properties with well-formed names (e.g. "VALUE") are available as
|
# Properties with well-formed names (e.g. "VALUE") are available as
|
||||||
# variables in the expressions as a shortcut.
|
# variables in the expressions as a shortcut.
|
||||||
#
|
#
|
||||||
|
# The expressions require a hint
|
||||||
|
# whether the they make use of anisotropic or scale-dependent properties.
|
||||||
|
# For example, the height of a box is an anisotropic property. If a check is made
|
||||||
|
# inside a rotated cell, the height transforms to a width and the check renders
|
||||||
|
# different results for the same cell if the cell is placed rotated and non-rotated.
|
||||||
|
# The solution is cell variant formation.
|
||||||
|
#
|
||||||
|
# Similarly, if a check is made against physical dimensions, the check will have
|
||||||
|
# different results for cells placed with different magnifications. Such a check
|
||||||
|
# is not scale-invariant.
|
||||||
|
#
|
||||||
|
# By default it is assumed that the expressions are isotropic and scale invariant.
|
||||||
|
# You can mark an expression as anisotropic and/or scale dependent using the following
|
||||||
|
# expression modifiers:
|
||||||
|
#
|
||||||
|
# @code
|
||||||
|
# # isotropic and scale invariant
|
||||||
|
# layer.select_if("shape.holes > 0")
|
||||||
|
#
|
||||||
|
# # anisotropic, but scale invariant
|
||||||
|
# layer.select_if(aniso("shape.bbox.height/shape.bbox.width > 2"))
|
||||||
|
#
|
||||||
|
# # isotropic, but not scale invariant
|
||||||
|
# layer.select_if(scales("shape.area > 10.0"))
|
||||||
|
#
|
||||||
|
# # anisotropic and not scale invariant
|
||||||
|
# layer.select_if(aniso_and_scales("shape.bbox.width > 10.0"))
|
||||||
|
# @/code
|
||||||
|
#
|
||||||
|
# If you forget to specify this hint, the expression will use the local
|
||||||
|
# shape properties and fail to correctly produce the results in the presence
|
||||||
|
# of deep mode and rotated or magnified cell instances.
|
||||||
|
#
|
||||||
# 'variables' can be a hash of arbitrary names and values. Each of these values
|
# 'variables' can be a hash of arbitrary names and values. Each of these values
|
||||||
# becomes available as variables in the expression. This eliminates the need
|
# becomes available as variables in the expression. This eliminates the need
|
||||||
# to build expression strings to pass variable values.
|
# to build expression strings to pass variable values.
|
||||||
|
|
@ -5277,7 +5370,7 @@ CODE
|
||||||
# less than 10 square micrometers:
|
# less than 10 square micrometers:
|
||||||
#
|
#
|
||||||
# @code
|
# @code
|
||||||
# layer.select("shape.area < 10.0")
|
# layer.select(scales("shape.area < 10.0"))
|
||||||
# @/code
|
# @/code
|
||||||
#
|
#
|
||||||
# This version modifies the input layer. A version that returns
|
# This version modifies the input layer. A version that returns
|
||||||
|
|
@ -5302,30 +5395,39 @@ CODE
|
||||||
# less than 10 square micrometers and one with the shapes with a bigger area:
|
# less than 10 square micrometers and one with the shapes with a bigger area:
|
||||||
#
|
#
|
||||||
# @code
|
# @code
|
||||||
# (smaller, bigger) = layer.split_if("shape.area < 10.0")
|
# (smaller, bigger) = layer.split_if(scales("shape.area < 10.0"))
|
||||||
# @/code
|
# @/code
|
||||||
|
|
||||||
def _make_filter(expression, variables)
|
def _make_filter(expression, variables)
|
||||||
|
|
||||||
expression.is_a?(String) || raise("'expression' must be a string")
|
if expression.is_a?(String)
|
||||||
|
expression = DRCTransformationVariantHint::new(expression)
|
||||||
|
elsif expression.is_a?(DRCTransformationVariantHint)
|
||||||
|
expression.expression.is_a?(String) || raise("'expression' must be a string")
|
||||||
|
else
|
||||||
|
raise("'expression' must be a string or a string decorated with a transformation variant hint")
|
||||||
|
end
|
||||||
variables.is_a?(Hash) || raise("'variables' must be a hash")
|
variables.is_a?(Hash) || raise("'variables' must be a hash")
|
||||||
|
|
||||||
if data.is_a?(RBA::Region)
|
if data.is_a?(RBA::Region)
|
||||||
RBA::PolygonFilterBase::expression_filter(expression, variables: variables)
|
f = RBA::PolygonFilterBase::expression_filter(expression.expression, dbu: @engine.dbu, variables: variables)
|
||||||
elsif data.is_a?(RBA::Edges)
|
elsif data.is_a?(RBA::Edges)
|
||||||
RBA::EdgeFilterBase::expression_filter(expression, variables: variables)
|
f = RBA::EdgeFilterBase::expression_filter(expression.expression, dbu: @engine.dbu, variables: variables)
|
||||||
elsif data.is_a?(RBA::EdgePairs)
|
elsif data.is_a?(RBA::EdgePairs)
|
||||||
RBA::EdgeFilterBase::expression_filter(expression, variables: variables)
|
f = RBA::EdgeFilterBase::expression_filter(expression.expression, dbu: @engine.dbu, variables: variables)
|
||||||
elsif data.is_a?(RBA::Texts)
|
elsif data.is_a?(RBA::Texts)
|
||||||
RBA::TextFilterBase::expression_filter(expression, variables: variables)
|
f = RBA::TextFilterBase::expression_filter(expression.expression, dbu: @engine.dbu, variables: variables)
|
||||||
else
|
else
|
||||||
nil
|
f = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
f && expression.apply(f)
|
||||||
|
f
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def select_if(expression, variables = {})
|
def select_if(expression, variables = {})
|
||||||
@engine._context("evaluate") do
|
@engine._context("select_if") do
|
||||||
f = _make_filter(expression, variables)
|
f = _make_filter(expression, variables)
|
||||||
@engine._tcmd(self.data, 0, self.data.class, :filter, f)
|
@engine._tcmd(self.data, 0, self.data.class, :filter, f)
|
||||||
self
|
self
|
||||||
|
|
@ -5333,16 +5435,17 @@ CODE
|
||||||
end
|
end
|
||||||
|
|
||||||
def selected_if(expression, variables = {})
|
def selected_if(expression, variables = {})
|
||||||
@engine._context("evaluated") do
|
@engine._context("selected_if") do
|
||||||
f = _make_filter(expression, variables)
|
f = _make_filter(expression, variables)
|
||||||
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, self.data.class, :filtered, f))
|
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, self.data.class, :filtered, f))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def split_if(expression, variables = {})
|
def split_if(expression, variables = {})
|
||||||
@engine._context("evaluated") do
|
@engine._context("split_if") do
|
||||||
f = _make_filter(expression, variables)
|
f = _make_filter(expression, variables)
|
||||||
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, self.data.class, :split_filter, f))
|
res = @engine._tcmd(self.data, 0, self.data.class, :split_filter, f)
|
||||||
|
[ DRCLayer::new(@engine, res[0]), DRCLayer::new(@engine, res[1]) ]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -833,6 +833,9 @@ module DRC
|
||||||
#
|
#
|
||||||
# antenna_errors = evaluate_nets(gate, { "MET" => metal }, expression, variables)
|
# antenna_errors = evaluate_nets(gate, { "MET" => metal }, expression, variables)
|
||||||
# @/code
|
# @/code
|
||||||
|
#
|
||||||
|
# NOTE: GDS does not support properties with string names, so
|
||||||
|
# either save to OASIS or use integer numbers for the property names.
|
||||||
|
|
||||||
def evaluate_nets(primary, secondary, expression, variables = {})
|
def evaluate_nets(primary, secondary, expression, variables = {})
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -575,5 +575,20 @@ module DRC
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class DRCTransformationVariantHint
|
||||||
|
def initialize(expression, mode = :is_isotropic_and_scale_invariant)
|
||||||
|
@expression = expression
|
||||||
|
@mode = mode
|
||||||
|
end
|
||||||
|
def expression
|
||||||
|
@expression
|
||||||
|
end
|
||||||
|
def apply(pr)
|
||||||
|
if @mode
|
||||||
|
pr.send(@mode)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2024,3 +2024,13 @@ TEST(142d_evaluate_nets)
|
||||||
run_test (_this, "142", true);
|
run_test (_this, "142", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(143_evaluate_and_filter)
|
||||||
|
{
|
||||||
|
run_test (_this, "143", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(143d_evaluate_and_filter)
|
||||||
|
{
|
||||||
|
run_test (_this, "143", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
|
||||||
|
source $drc_test_source
|
||||||
|
target $drc_test_target
|
||||||
|
|
||||||
|
if $drc_test_deep
|
||||||
|
deep
|
||||||
|
end
|
||||||
|
|
||||||
|
l1 = input(1, 0, enable_props)
|
||||||
|
l2 = input(2, 0, enable_props)
|
||||||
|
|
||||||
|
l1.output(1, 0)
|
||||||
|
l2.output(2, 0)
|
||||||
|
|
||||||
|
l2.evaluated("put(2, to_f(value(17))*2.0)").output(10, 0)
|
||||||
|
l2.evaluated("put(2, to_f(value(17))*factor)", { "factor" => 3.0 }, true).output(11, 0)
|
||||||
|
l1.evaluated(aniso("put(2, shape.bbox.height/shape.bbox.width)")).output(12, 0)
|
||||||
|
l1.evaluated(scales("put(2, shape.area)")).output(13, 0)
|
||||||
|
l1.evaluated(aniso_and_scales("put(2, shape.bbox.width)")).output(14, 0)
|
||||||
|
|
||||||
|
d = l2.dup
|
||||||
|
d.evaluate("put(2, to_f(value(17))*2.0)").output(20, 0)
|
||||||
|
d = l2.dup
|
||||||
|
d.evaluate("put(2, to_f(value(17))*factor)", { "factor" => 3.0 }, true).output(21, 0)
|
||||||
|
d = l1.dup
|
||||||
|
d.evaluate(aniso("put(2, shape.bbox.height/shape.bbox.width)")).output(22, 0)
|
||||||
|
d = l1.dup
|
||||||
|
d.evaluate(scales("put(2, shape.area)")).output(23, 0)
|
||||||
|
d = l1.dup
|
||||||
|
d.evaluate(aniso_and_scales("put(2, shape.bbox.width)")).output(24, 0)
|
||||||
|
|
||||||
|
l2.selected_if("to_f(value(17))<3.0").output(30, 0)
|
||||||
|
l2.selected_if("to_f(value(17))<thr)", { "thr" => 3.0 }).output(31, 0)
|
||||||
|
l1.selected_if(aniso("shape.bbox.height/shape.bbox.width<1.0")).output(32, 0)
|
||||||
|
l1.selected_if(scales("shape.area<20.0")).output(33, 0)
|
||||||
|
l1.selected_if(aniso_and_scales("shape.bbox.width<=5")).output(34, 0)
|
||||||
|
|
||||||
|
d = l2.dup
|
||||||
|
d.select_if("to_f(value(17))<3.0").output(40, 0)
|
||||||
|
d = l2.dup
|
||||||
|
d.select_if("to_f(value(17))<thr)", { "thr" => 3.0 }).output(41, 0)
|
||||||
|
d = l1.dup
|
||||||
|
d.select_if(aniso("shape.bbox.height/shape.bbox.width<1.0")).output(42, 0)
|
||||||
|
d = l1.dup
|
||||||
|
d.select_if(scales("shape.area<20.0")).output(43, 0)
|
||||||
|
d = l1.dup
|
||||||
|
d.select_if(aniso_and_scales("shape.bbox.width<=5")).output(44, 0)
|
||||||
|
|
||||||
|
l2.split_if("to_f(value(17))<3.0")[0].output(50, 0)
|
||||||
|
l2.split_if("to_f(value(17))<3.0")[1].output(51, 0)
|
||||||
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue