mirror of https://github.com/KLayout/klayout.git
DRC integration of new features
This commit is contained in:
parent
fcdec05863
commit
78c5e229ff
|
|
@ -48,6 +48,37 @@ db::Edge::distance_type edge_projection (const db::Edge &a, const db::Edge &b)
|
||||||
return db::coord_traits<db::Coord>::rounded (a.double_length () * fabs (l2 - l1));
|
return db::coord_traits<db::Coord>::rounded (a.double_length () * fabs (l2 - l1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets a flag indicating whether zero distance is included in the checks
|
||||||
|
*/
|
||||||
|
static bool include_zero_flag (collinear_mode_type coll_mode, const db::Edge &a, const db::Edge &b)
|
||||||
|
{
|
||||||
|
if (coll_mode == AlwaysIncludeCollinear) {
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} else if (coll_mode == AlwaysIncludeCollinear) {
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
int s1 = a.side_of (b.p1 ());
|
||||||
|
int s2 = a.side_of (b.p2 ());
|
||||||
|
|
||||||
|
if (s1 == 0 && s2 == 0) {
|
||||||
|
if (coll_mode == IncludeCollinearWhenTouch) {
|
||||||
|
return a.intersect (b);
|
||||||
|
} else if (coll_mode == IncludeCollinearWhenOverlap) {
|
||||||
|
return a.coincident (b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the part of the "other" edge which is on the inside side of e and within distance d
|
* @brief Returns the part of the "other" edge which is on the inside side of e and within distance d
|
||||||
*
|
*
|
||||||
|
|
@ -67,12 +98,7 @@ bool euclidian_near_part_of_edge (collinear_mode_type coll_mode, db::coord_trait
|
||||||
int s1 = e.side_of (g.p1 ());
|
int s1 = e.side_of (g.p1 ());
|
||||||
int s2 = e.side_of (g.p2 ());
|
int s2 = e.side_of (g.p2 ());
|
||||||
|
|
||||||
// "kissing corner" issue: force include zero if the edges are collinear and overlap.
|
bool include_zero = include_zero_flag (coll_mode, e, g);
|
||||||
bool include_zero = (coll_mode == AlwaysIncludeCollinear);
|
|
||||||
if (coll_mode == IncludeCollinearWhenTouch && s1 == 0 && s2 == 0 && e.intersect (g)) {
|
|
||||||
include_zero = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int thr = include_zero ? 0 : -1;
|
int thr = include_zero ? 0 : -1;
|
||||||
|
|
||||||
// keep only part of other which is on the "inside" side of e
|
// keep only part of other which is on the "inside" side of e
|
||||||
|
|
@ -211,12 +237,7 @@ static bool var_near_part_of_edge (collinear_mode_type coll_mode, db::coord_trai
|
||||||
int s1 = e.side_of (g.p1 ());
|
int s1 = e.side_of (g.p1 ());
|
||||||
int s2 = e.side_of (g.p2 ());
|
int s2 = e.side_of (g.p2 ());
|
||||||
|
|
||||||
// "kissing corner" issue: force include zero if the edges are collinear and overlap
|
bool include_zero = include_zero_flag (coll_mode, e, g);
|
||||||
bool include_zero = (coll_mode == AlwaysIncludeCollinear);
|
|
||||||
if (coll_mode == IncludeCollinearWhenTouch && s1 == 0 && s2 == 0 && e.intersect (g)) {
|
|
||||||
include_zero = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int thr = include_zero ? 0 : -1;
|
int thr = include_zero ? 0 : -1;
|
||||||
|
|
||||||
// keep only part of other which is on the "inside" side of e
|
// keep only part of other which is on the "inside" side of e
|
||||||
|
|
|
||||||
|
|
@ -108,14 +108,19 @@ enum collinear_mode_type {
|
||||||
NeverIncludeCollinear = 0,
|
NeverIncludeCollinear = 0,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief include collinear edges when they touch (e.g. kissing corner case)
|
* @brief include collinear edges when they share at least one common point
|
||||||
*/
|
*/
|
||||||
IncludeCollinearWhenTouch = 1,
|
IncludeCollinearWhenTouch = 1,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief include collinear edges when they share more than a single common point
|
||||||
|
*/
|
||||||
|
IncludeCollinearWhenOverlap = 2,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief always include collinear edges
|
* @brief always include collinear edges
|
||||||
*/
|
*/
|
||||||
AlwaysIncludeCollinear = 2
|
AlwaysIncludeCollinear = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -130,8 +130,8 @@ struct DB_PUBLIC RegionCheckOptions
|
||||||
RectFilter _rect_filter = NoRectFilter,
|
RectFilter _rect_filter = NoRectFilter,
|
||||||
bool _negative = false,
|
bool _negative = false,
|
||||||
PropertyConstraint _prop_constraint = IgnoreProperties,
|
PropertyConstraint _prop_constraint = IgnoreProperties,
|
||||||
collinear_mode_type _include_zero = IncludeCollinearWhenTouch)
|
collinear_mode_type _coll_mode = IncludeCollinearWhenTouch)
|
||||||
: EdgesCheckOptions (_whole_edges, _metrics, _ignore_angle, _min_projection, _max_projection, _include_zero),
|
: EdgesCheckOptions (_whole_edges, _metrics, _ignore_angle, _min_projection, _max_projection, _coll_mode),
|
||||||
shielded (_shielded),
|
shielded (_shielded),
|
||||||
opposite_filter (_opposite_filter),
|
opposite_filter (_opposite_filter),
|
||||||
rect_filter (_rect_filter),
|
rect_filter (_rect_filter),
|
||||||
|
|
|
||||||
|
|
@ -390,23 +390,27 @@ static db::CompoundRegionOperationNode *new_edge_pair_to_second_edges (db::Compo
|
||||||
return new db::CompoundRegionEdgePairToEdgeProcessingOperationNode (new db::EdgePairToSecondEdgesProcessor (), input, true /*processor is owned*/);
|
return new db::CompoundRegionEdgePairToEdgeProcessingOperationNode (new db::EdgePairToSecondEdgesProcessor (), input, true /*processor is owned*/);
|
||||||
}
|
}
|
||||||
|
|
||||||
static db::CompoundRegionOperationNode *new_check_node (db::CompoundRegionOperationNode *other, db::edge_relation_type rel, bool different_polygons, db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, bool negative)
|
static db::CompoundRegionOperationNode *new_check_node (db::CompoundRegionOperationNode *other, db::edge_relation_type rel, bool different_polygons, db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, db::collinear_mode_type collinear_mode, bool negative)
|
||||||
{
|
{
|
||||||
check_non_null (other, "other");
|
check_non_null (other, "other");
|
||||||
return new db::CompoundRegionCheckOperationNode (0, other, rel, different_polygons, d,
|
|
||||||
db::RegionCheckOptions (whole_edges,
|
db::RegionCheckOptions options;
|
||||||
metrics,
|
|
||||||
ignore_angle.is_nil () ? 90 : ignore_angle.to_double (),
|
options.whole_edges = whole_edges;
|
||||||
min_projection.is_nil () ? db::Region::distance_type (0) : min_projection.to<db::Region::distance_type> (),
|
options.metrics = metrics;
|
||||||
max_projection.is_nil () ? std::numeric_limits<db::Region::distance_type>::max () : max_projection.to<db::Region::distance_type> (),
|
options.ignore_angle = ignore_angle.is_nil () ? 90 : ignore_angle.to_double ();
|
||||||
shielded,
|
options.min_projection = min_projection.is_nil () ? db::Region::distance_type (0) : min_projection.to<db::Region::distance_type> ();
|
||||||
opposite_filter,
|
options.max_projection = max_projection.is_nil () ? std::numeric_limits<db::Region::distance_type>::max () : max_projection.to<db::Region::distance_type> ();
|
||||||
rect_filter,
|
options.shielded = shielded;
|
||||||
negative)
|
options.opposite_filter = opposite_filter;
|
||||||
);
|
options.rect_filter = rect_filter;
|
||||||
|
options.negative = negative;
|
||||||
|
options.collinear_mode = collinear_mode;
|
||||||
|
|
||||||
|
return new db::CompoundRegionCheckOperationNode (0, other, rel, different_polygons, d, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
static db::CompoundRegionOperationNode *new_width_check (db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, bool negative)
|
static db::CompoundRegionOperationNode *new_width_check (db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::collinear_mode_type collinear_mode, bool negative)
|
||||||
{
|
{
|
||||||
db::RegionCheckOptions options (whole_edges,
|
db::RegionCheckOptions options (whole_edges,
|
||||||
metrics,
|
metrics,
|
||||||
|
|
@ -415,28 +419,29 @@ static db::CompoundRegionOperationNode *new_width_check (db::Coord d, bool whole
|
||||||
max_projection.is_nil () ? std::numeric_limits<db::Region::distance_type>::max () : max_projection.to<db::Region::distance_type> (),
|
max_projection.is_nil () ? std::numeric_limits<db::Region::distance_type>::max () : max_projection.to<db::Region::distance_type> (),
|
||||||
shielded);
|
shielded);
|
||||||
options.negative = negative;
|
options.negative = negative;
|
||||||
|
options.collinear_mode = collinear_mode;
|
||||||
return new db::CompoundRegionToEdgePairProcessingOperationNode (new db::SinglePolygonCheck (db::WidthRelation, d, options), new_primary (), true /*processor is owned*/);
|
return new db::CompoundRegionToEdgePairProcessingOperationNode (new db::SinglePolygonCheck (db::WidthRelation, d, options), new_primary (), true /*processor is owned*/);
|
||||||
}
|
}
|
||||||
|
|
||||||
static db::CompoundRegionOperationNode *new_space_or_isolated_check (db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, bool negative, bool isolated)
|
static db::CompoundRegionOperationNode *new_space_or_isolated_check (db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, db::collinear_mode_type collinear_mode, bool negative, bool isolated)
|
||||||
{
|
{
|
||||||
// NOTE: we have to use the "foreign" scheme with a filter because only this scheme
|
// NOTE: we have to use the "foreign" scheme with a filter because only this scheme
|
||||||
// guarantees that all subject shapes are visited and receive all intruders. Having all intruders is crucial for the
|
// guarantees that all subject shapes are visited and receive all intruders. Having all intruders is crucial for the
|
||||||
// semantics of the "drc" feature
|
// semantics of the "drc" feature
|
||||||
return new_check_node (new_foreign (), db::SpaceRelation, isolated, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, negative);
|
return new_check_node (new_foreign (), db::SpaceRelation, isolated, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, collinear_mode, negative);
|
||||||
}
|
}
|
||||||
|
|
||||||
static db::CompoundRegionOperationNode *new_space_check (db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, bool negative)
|
static db::CompoundRegionOperationNode *new_space_check (db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, db::collinear_mode_type collinear_mode, bool negative)
|
||||||
{
|
{
|
||||||
return new_space_or_isolated_check (d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, negative, false);
|
return new_space_or_isolated_check (d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, collinear_mode, negative, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static db::CompoundRegionOperationNode *new_isolated_check (db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, bool negative)
|
static db::CompoundRegionOperationNode *new_isolated_check (db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, db::collinear_mode_type collinear_mode, bool negative)
|
||||||
{
|
{
|
||||||
return new_space_or_isolated_check (d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, negative, true);
|
return new_space_or_isolated_check (d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, collinear_mode, negative, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static db::CompoundRegionOperationNode *new_notch_check (db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, bool negative)
|
static db::CompoundRegionOperationNode *new_notch_check (db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::collinear_mode_type collinear_mode, bool negative)
|
||||||
{
|
{
|
||||||
db::RegionCheckOptions options (whole_edges,
|
db::RegionCheckOptions options (whole_edges,
|
||||||
metrics,
|
metrics,
|
||||||
|
|
@ -445,27 +450,28 @@ static db::CompoundRegionOperationNode *new_notch_check (db::Coord d, bool whole
|
||||||
max_projection.is_nil () ? std::numeric_limits<db::Region::distance_type>::max () : max_projection.to<db::Region::distance_type> (),
|
max_projection.is_nil () ? std::numeric_limits<db::Region::distance_type>::max () : max_projection.to<db::Region::distance_type> (),
|
||||||
shielded);
|
shielded);
|
||||||
options.negative = negative;
|
options.negative = negative;
|
||||||
|
options.collinear_mode = collinear_mode;
|
||||||
return new db::CompoundRegionToEdgePairProcessingOperationNode (new db::SinglePolygonCheck (db::SpaceRelation, d, options), new_primary (), true /*processor is owned*/);
|
return new db::CompoundRegionToEdgePairProcessingOperationNode (new db::SinglePolygonCheck (db::SpaceRelation, d, options), new_primary (), true /*processor is owned*/);
|
||||||
}
|
}
|
||||||
|
|
||||||
static db::CompoundRegionOperationNode *new_separation_check (db::CompoundRegionOperationNode *other, db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, bool negative)
|
static db::CompoundRegionOperationNode *new_separation_check (db::CompoundRegionOperationNode *other, db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, db::collinear_mode_type collinear_mode, bool negative)
|
||||||
{
|
{
|
||||||
return new_check_node (other, db::SpaceRelation, true, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, negative);
|
return new_check_node (other, db::SpaceRelation, true, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, collinear_mode, negative);
|
||||||
}
|
}
|
||||||
|
|
||||||
static db::CompoundRegionOperationNode *new_overlap_check (db::CompoundRegionOperationNode *other, db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, bool negative)
|
static db::CompoundRegionOperationNode *new_overlap_check (db::CompoundRegionOperationNode *other, db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, db::collinear_mode_type collinear_mode, bool negative)
|
||||||
{
|
{
|
||||||
return new_check_node (other, db::WidthRelation, true, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, negative);
|
return new_check_node (other, db::WidthRelation, true, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, collinear_mode, negative);
|
||||||
}
|
}
|
||||||
|
|
||||||
static db::CompoundRegionOperationNode *new_enclosing_check (db::CompoundRegionOperationNode *other, db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, bool negative)
|
static db::CompoundRegionOperationNode *new_enclosing_check (db::CompoundRegionOperationNode *other, db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, db::collinear_mode_type collinear_mode, bool negative)
|
||||||
{
|
{
|
||||||
return new_check_node (other, db::OverlapRelation, true, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, negative);
|
return new_check_node (other, db::OverlapRelation, true, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, collinear_mode, negative);
|
||||||
}
|
}
|
||||||
|
|
||||||
static db::CompoundRegionOperationNode *new_enclosed_check (db::CompoundRegionOperationNode *other, db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, bool negative)
|
static db::CompoundRegionOperationNode *new_enclosed_check (db::CompoundRegionOperationNode *other, db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, db::collinear_mode_type collinear_mode, bool negative)
|
||||||
{
|
{
|
||||||
return new_check_node (other, db::InsideRelation, true, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, negative);
|
return new_check_node (other, db::InsideRelation, true, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, collinear_mode, negative);
|
||||||
}
|
}
|
||||||
|
|
||||||
static db::CompoundRegionOperationNode *new_perimeter_filter (db::CompoundRegionOperationNode *input, bool inverse, db::coord_traits<db::Coord>::perimeter_type pmin, db::coord_traits<db::Coord>::perimeter_type pmax)
|
static db::CompoundRegionOperationNode *new_perimeter_filter (db::CompoundRegionOperationNode *input, bool inverse, db::coord_traits<db::Coord>::perimeter_type pmin, db::coord_traits<db::Coord>::perimeter_type pmax)
|
||||||
|
|
@ -660,31 +666,45 @@ Class<db::CompoundRegionOperationNode> decl_CompoundRegionOperationNode ("db", "
|
||||||
gsi::constructor ("new_minkowski_sum|#new_minkowsky_sum", &new_minkowski_sum_node4, gsi::arg ("input"), gsi::arg ("p"),
|
gsi::constructor ("new_minkowski_sum|#new_minkowsky_sum", &new_minkowski_sum_node4, gsi::arg ("input"), gsi::arg ("p"),
|
||||||
"@brief Creates a node providing a Minkowski sum with a point sequence forming a contour.\n"
|
"@brief Creates a node providing a Minkowski sum with a point sequence forming a contour.\n"
|
||||||
) +
|
) +
|
||||||
gsi::constructor ("new_width_check", &new_width_check, gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max."), gsi::arg ("shielded", true), gsi::arg ("negative", false),
|
gsi::constructor ("new_width_check", &new_width_check, gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max."), gsi::arg ("shielded", true), gsi::arg ("collinear_mode", db::IncludeCollinearWhenTouch), gsi::arg ("negative", false),
|
||||||
"@brief Creates a node providing a width check.\n"
|
"@brief Creates a node providing a width check.\n"
|
||||||
|
"\n"
|
||||||
|
"The collinear_mode argument has been inserted in version 0.29.\n"
|
||||||
) +
|
) +
|
||||||
gsi::constructor ("new_space_check", &new_space_check, gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max."), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("negative", false),
|
gsi::constructor ("new_space_check", &new_space_check, gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max."), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("collinear_mode", db::IncludeCollinearWhenTouch), gsi::arg ("negative", false),
|
||||||
"@brief Creates a node providing a space check.\n"
|
"@brief Creates a node providing a space check.\n"
|
||||||
|
"\n"
|
||||||
|
"The collinear_mode argument has been inserted in version 0.29.\n"
|
||||||
) +
|
) +
|
||||||
gsi::constructor ("new_isolated_check", &new_isolated_check, gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max."), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("negative", false),
|
gsi::constructor ("new_isolated_check", &new_isolated_check, gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max."), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("collinear_mode", db::IncludeCollinearWhenTouch), gsi::arg ("negative", false),
|
||||||
"@brief Creates a node providing a isolated polygons (space between different polygons) check.\n"
|
"@brief Creates a node providing a isolated polygons (space between different polygons) check.\n"
|
||||||
|
"\n"
|
||||||
|
"The collinear_mode argument has been inserted in version 0.29.\n"
|
||||||
) +
|
) +
|
||||||
gsi::constructor ("new_notch_check", &new_notch_check, gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max."), gsi::arg ("shielded", true), gsi::arg ("negative", false),
|
gsi::constructor ("new_notch_check", &new_notch_check, gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max."), gsi::arg ("shielded", true), gsi::arg ("collinear_mode", db::IncludeCollinearWhenTouch), gsi::arg ("negative", false),
|
||||||
"@brief Creates a node providing a intra-polygon space check.\n"
|
"@brief Creates a node providing a intra-polygon space check.\n"
|
||||||
|
"\n"
|
||||||
|
"The collinear_mode argument has been inserted in version 0.29.\n"
|
||||||
) +
|
) +
|
||||||
gsi::constructor ("new_separation_check", &new_separation_check, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max."), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("negative", false),
|
gsi::constructor ("new_separation_check", &new_separation_check, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max."), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("collinear_mode", db::IncludeCollinearWhenTouch), gsi::arg ("negative", false),
|
||||||
"@brief Creates a node providing a separation check.\n"
|
"@brief Creates a node providing a separation check.\n"
|
||||||
|
"\n"
|
||||||
|
"The collinear_mode argument has been inserted in version 0.29.\n"
|
||||||
) +
|
) +
|
||||||
gsi::constructor ("new_overlap_check", &new_overlap_check, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max."), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("negative", false),
|
gsi::constructor ("new_overlap_check", &new_overlap_check, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max."), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("collinear_mode", db::IncludeCollinearWhenTouch), gsi::arg ("negative", false),
|
||||||
"@brief Creates a node providing an overlap check.\n"
|
"@brief Creates a node providing an overlap check.\n"
|
||||||
|
"\n"
|
||||||
|
"The collinear_mode argument has been inserted in version 0.29.\n"
|
||||||
) +
|
) +
|
||||||
gsi::constructor ("new_enclosing_check", &new_enclosing_check, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max."), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("negative", false),
|
gsi::constructor ("new_enclosing_check", &new_enclosing_check, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max."), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("collinear_mode", db::IncludeCollinearWhenTouch), gsi::arg ("negative", false),
|
||||||
"@brief Creates a node providing an inside (enclosure) check.\n"
|
"@brief Creates a node providing an inside (enclosure) check.\n"
|
||||||
|
"\n"
|
||||||
|
"The collinear_mode argument has been inserted in version 0.29.\n"
|
||||||
) +
|
) +
|
||||||
gsi::constructor ("new_enclosed_check", &new_enclosed_check, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max."), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("negative", false),
|
gsi::constructor ("new_enclosed_check", &new_enclosed_check, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max."), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("collinear_mode", db::IncludeCollinearWhenTouch), gsi::arg ("negative", false),
|
||||||
"@brief Creates a node providing an enclosed (secondary enclosing primary) check.\n"
|
"@brief Creates a node providing an enclosed (secondary enclosing primary) check.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"This method has been added in version 0.27.5.\n"
|
"This method has been added in version 0.27.5. The collinear_mode argument has been inserted in version 0.29.\n"
|
||||||
) +
|
) +
|
||||||
gsi::constructor ("new_perimeter_filter", &new_perimeter_filter, gsi::arg ("input"), gsi::arg ("inverse", false), gsi::arg ("pmin", 0), gsi::arg ("pmax", std::numeric_limits<db::coord_traits<db::Coord>::perimeter_type>::max (), "max"),
|
gsi::constructor ("new_perimeter_filter", &new_perimeter_filter, gsi::arg ("input"), gsi::arg ("inverse", false), gsi::arg ("pmin", 0), gsi::arg ("pmax", std::numeric_limits<db::coord_traits<db::Coord>::perimeter_type>::max (), "max"),
|
||||||
"@brief Creates a node filtering the input by perimeter.\n"
|
"@brief Creates a node filtering the input by perimeter.\n"
|
||||||
|
|
@ -803,9 +823,7 @@ Class<db::CompoundRegionOperationNode> decl_CompoundRegionOperationNode ("db", "
|
||||||
"\n"
|
"\n"
|
||||||
"The search distance for intruder shapes is determined by the operation and computed from the operation's requirements.\n"
|
"The search distance for intruder shapes is determined by the operation and computed from the operation's requirements.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"NOTE: this feature is experimental and not deployed into the the DRC framework yet.\n"
|
"This class has been introduced in version 0.27. The API is considered internal and will change without notice."
|
||||||
"\n"
|
|
||||||
"This class has been introduced in version 0.27."
|
|
||||||
);
|
);
|
||||||
|
|
||||||
gsi::EnumIn<db::CompoundRegionOperationNode, db::CompoundRegionLogicalBoolOperationNode::LogicalOp> decl_dbCompoundRegionLogicalBoolOperationNode_LogicalOp ("db", "LogicalOp",
|
gsi::EnumIn<db::CompoundRegionOperationNode, db::CompoundRegionLogicalBoolOperationNode::LogicalOp> decl_dbCompoundRegionLogicalBoolOperationNode_LogicalOp ("db", "LogicalOp",
|
||||||
|
|
|
||||||
|
|
@ -3274,7 +3274,12 @@ gsi::Enum<db::collinear_mode_type> decl_CollinearMode ("db", "CollinearMode",
|
||||||
) +
|
) +
|
||||||
gsi::enum_const ("IncludeCollinearWhenTouch", db::IncludeCollinearWhenTouch,
|
gsi::enum_const ("IncludeCollinearWhenTouch", db::IncludeCollinearWhenTouch,
|
||||||
"@brief Specifies that check functions should include collinear edges when they touch\n"
|
"@brief Specifies that check functions should include collinear edges when they touch\n"
|
||||||
"With this specification, the check functions will also check edges which are collinear, but only if they touch in at least one point. "
|
"With this specification, the check functions will also check edges which are collinear, but only if they share at least one point. "
|
||||||
|
"This is the mode that allows checking the 'kissing corner' cases."
|
||||||
|
) +
|
||||||
|
gsi::enum_const ("IncludeCollinearWhenOverlap", db::IncludeCollinearWhenOverlap,
|
||||||
|
"@brief Specifies that check functions should include collinear edges when they overlap\n"
|
||||||
|
"With this specification, the check functions will also check edges which are collinear, but only if they share more than a single point. "
|
||||||
"This is the mode that allows checking the 'kissing corner' cases."
|
"This is the mode that allows checking the 'kissing corner' cases."
|
||||||
),
|
),
|
||||||
"@brief This class represents the collinear_mode type for \\Region#width and related checks.\n"
|
"@brief This class represents the collinear_mode type for \\Region#width and related checks.\n"
|
||||||
|
|
|
||||||
|
|
@ -382,6 +382,22 @@ TEST(8_KissingCornerProblem)
|
||||||
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, -1), db::Point (0, -100)), &output);
|
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, -1), db::Point (0, -100)), &output);
|
||||||
EXPECT_EQ (res, false);
|
EXPECT_EQ (res, false);
|
||||||
|
|
||||||
|
f.set_collinear_mode (db::IncludeCollinearWhenOverlap);
|
||||||
|
|
||||||
|
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 201), db::Point (0, 101)), &output);
|
||||||
|
EXPECT_EQ (res, false);
|
||||||
|
res = f.check (db::Edge (db::Point (1, 0), db::Point (1, 100)), db::Edge (db::Point (0, 201), db::Point (0, 0)), &output);
|
||||||
|
EXPECT_EQ (res, false);
|
||||||
|
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 200), db::Point (0, 100)), &output);
|
||||||
|
EXPECT_EQ (res, false);
|
||||||
|
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 200), db::Point (0, 50)), &output);
|
||||||
|
EXPECT_EQ (res, true);
|
||||||
|
EXPECT_EQ (output.first ().to_string () + ":" + output.second ().to_string (), "(0,40;0,100):(0,110;0,50)");
|
||||||
|
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 0), db::Point (0, -100)), &output);
|
||||||
|
EXPECT_EQ (res, false);
|
||||||
|
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, -1), db::Point (0, -100)), &output);
|
||||||
|
EXPECT_EQ (res, false);
|
||||||
|
|
||||||
f.set_collinear_mode (db::NeverIncludeCollinear);
|
f.set_collinear_mode (db::NeverIncludeCollinear);
|
||||||
|
|
||||||
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 201), db::Point (0, 101)), &output);
|
res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 201), db::Point (0, 101)), &output);
|
||||||
|
|
@ -417,6 +433,22 @@ TEST(8_KissingCornerProblem)
|
||||||
res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, -100), db::Point (0, -1)), &output);
|
res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, -100), db::Point (0, -1)), &output);
|
||||||
EXPECT_EQ (res, false);
|
EXPECT_EQ (res, false);
|
||||||
|
|
||||||
|
f.set_collinear_mode (db::IncludeCollinearWhenOverlap);
|
||||||
|
|
||||||
|
res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, 101), db::Point (0, 201)), &output);
|
||||||
|
EXPECT_EQ (res, false);
|
||||||
|
res = f.check (db::Edge (db::Point (1, 100), db::Point (1, 0)), db::Edge (db::Point (0, 0), db::Point (0, 200)), &output);
|
||||||
|
EXPECT_EQ (res, false);
|
||||||
|
res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, 100), db::Point (0, 200)), &output);
|
||||||
|
EXPECT_EQ (res, false);
|
||||||
|
res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, 50), db::Point (0, 200)), &output);
|
||||||
|
EXPECT_EQ (res, true);
|
||||||
|
EXPECT_EQ (output.first ().to_string () + ":" + output.second ().to_string (), "(0,100;0,40):(0,50;0,110)");
|
||||||
|
res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, -100), db::Point (0, 0)), &output);
|
||||||
|
EXPECT_EQ (res, false);
|
||||||
|
res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, -100), db::Point (0, -1)), &output);
|
||||||
|
EXPECT_EQ (res, false);
|
||||||
|
|
||||||
f.set_collinear_mode (db::NeverIncludeCollinear);
|
f.set_collinear_mode (db::NeverIncludeCollinear);
|
||||||
|
|
||||||
f.set_metrics (db::Euclidian);
|
f.set_metrics (db::Euclidian);
|
||||||
|
|
|
||||||
|
|
@ -1485,6 +1485,7 @@ CODE
|
||||||
shielded = nil
|
shielded = nil
|
||||||
opposite_filter = RBA::Region::NoOppositeFilter
|
opposite_filter = RBA::Region::NoOppositeFilter
|
||||||
rect_filter = RBA::Region::NoRectFilter
|
rect_filter = RBA::Region::NoRectFilter
|
||||||
|
collinear_mode = RBA::Region::IncludeCollinearWhenTouch
|
||||||
|
|
||||||
n = 1
|
n = 1
|
||||||
args.each do |a|
|
args.each do |a|
|
||||||
|
|
@ -1492,6 +1493,10 @@ CODE
|
||||||
metrics = a.value
|
metrics = a.value
|
||||||
elsif a.is_a?(DRCWholeEdges)
|
elsif a.is_a?(DRCWholeEdges)
|
||||||
whole_edges = a.value
|
whole_edges = a.value
|
||||||
|
elsif a.is_a?(DRCPropertiesConstraint)
|
||||||
|
prop_constraint = a.value
|
||||||
|
elsif a.is_a?(DRCCollinearMode)
|
||||||
|
collinear_mode = a.value
|
||||||
elsif a.is_a?(DRCOppositeErrorFilter)
|
elsif a.is_a?(DRCOppositeErrorFilter)
|
||||||
opposite_filter = a.value
|
opposite_filter = a.value
|
||||||
elsif a.is_a?(DRCRectangleErrorFilter)
|
elsif a.is_a?(DRCRectangleErrorFilter)
|
||||||
|
|
@ -1523,6 +1528,8 @@ CODE
|
||||||
elsif rect_filter != RBA::Region::NoRectFilter
|
elsif rect_filter != RBA::Region::NoRectFilter
|
||||||
raise("A rectangle error filter cannot be used with this check")
|
raise("A rectangle error filter cannot be used with this check")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
args << collinear_mode
|
||||||
|
|
||||||
if :#{f} == :width || :#{f} == :space || :#{f} == :notch || :#{f} == :isolated
|
if :#{f} == :width || :#{f} == :space || :#{f} == :notch || :#{f} == :isolated
|
||||||
other && raise("No other layer must be specified for a single-layer check")
|
other && raise("No other layer must be specified for a single-layer check")
|
||||||
|
|
|
||||||
|
|
@ -322,6 +322,12 @@ module DRC
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def without_touching(f = true)
|
||||||
|
self._context("without_touching") do
|
||||||
|
DRCCollinearMode::new(f ? RBA::Region::IncludeCollinearWhenOverlap : RBA::Region::IncludeCollinearWhenTouch)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def euclidian
|
def euclidian
|
||||||
DRCMetrics::new(RBA::Region::Euclidian)
|
DRCMetrics::new(RBA::Region::Euclidian)
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -3687,10 +3687,12 @@ CODE
|
||||||
# but is more intuitive, as "projecting" is written with a condition, like
|
# but is more intuitive, as "projecting" is written with a condition, like
|
||||||
# "projecting < 2.um". Available operators are: "==", "<", "<=", ">" and ">=".
|
# "projecting < 2.um". Available operators are: "==", "<", "<=", ">" and ">=".
|
||||||
# Double-bounded ranges are also available, like: "0.5 <= projecting < 2.0". @/li
|
# Double-bounded ranges are also available, like: "0.5 <= projecting < 2.0". @/li
|
||||||
# @li @b transparent @/b: performs the check without shielding (polygon layers only) @/li
|
# @li @b without_touching @/b: With this option present, touching corners (aka "kissing
|
||||||
# @li @b shielded @/b: performs the check with shielding (polygon layers only) @/li
|
# corners") will not yield errors. The default is to produce errors in these cases. @/li
|
||||||
|
# @li @b transparent @/b: Performs the check without shielding (polygon layers only) @/li
|
||||||
|
# @li @b shielded @/b: Performs the check with shielding (polygon layers only) @/li
|
||||||
# @li @b props_eq @/b, @b props_ne @/b, @b props_copy @/b: (only props_copy applies to width check) -
|
# @li @b props_eq @/b, @b props_ne @/b, @b props_copy @/b: (only props_copy applies to width check) -
|
||||||
# see "Properties constraints" below. @/li
|
# See "Properties constraints" below. @/li
|
||||||
# @/ul
|
# @/ul
|
||||||
#
|
#
|
||||||
# Note that without the angle_limit, acute corners will always be reported, since two
|
# Note that without the angle_limit, acute corners will always be reported, since two
|
||||||
|
|
@ -3792,6 +3794,22 @@ CODE
|
||||||
# space_connected = metal1_nets.space(0.4.um, props_eq + props_copy)
|
# space_connected = metal1_nets.space(0.4.um, props_eq + props_copy)
|
||||||
# @/code
|
# @/code
|
||||||
#
|
#
|
||||||
|
# @h3 Touching shapes @/h3
|
||||||
|
#
|
||||||
|
# The \without_touching option will turn off errors that arise due to
|
||||||
|
# the "kissing corner" configuration (or "checkerboard pattern"). Formally
|
||||||
|
# this is a width violation across the diagonal, but when considering this
|
||||||
|
# configuration as disconnected boxes, no error should be reported.
|
||||||
|
#
|
||||||
|
# The following images illustrate the effect of the \without_touching option:
|
||||||
|
#
|
||||||
|
# @table
|
||||||
|
# @tr
|
||||||
|
# @td @img(/images/drc_width5.png) @/td
|
||||||
|
# @td @img(/images/drc_width6.png) @/td
|
||||||
|
# @/tr
|
||||||
|
# @/table
|
||||||
|
#
|
||||||
|
|
||||||
# %DRC%
|
# %DRC%
|
||||||
# @name space
|
# @name space
|
||||||
|
|
@ -3912,7 +3930,25 @@ CODE
|
||||||
# @/tr
|
# @/tr
|
||||||
# @/table
|
# @/table
|
||||||
#
|
#
|
||||||
# @h3 opposite and rectangle error filtering @/h3
|
# @h3 Touching shapes @/h3
|
||||||
|
#
|
||||||
|
# Like \width and \space, the separation check also supports the \without_touching option.
|
||||||
|
#
|
||||||
|
# This option will turn off errors that arise due to
|
||||||
|
# collinear edges touching in one corner (the "kissing corners" configuration).
|
||||||
|
# By default, such edges will yield an error, as they
|
||||||
|
# form a zero-distance situation. With this option in place, no errors will be reported.
|
||||||
|
#
|
||||||
|
# The following images illustrate the effect of the \without_touching option:
|
||||||
|
#
|
||||||
|
# @table
|
||||||
|
# @tr
|
||||||
|
# @td @img(/images/drc_separation12.png) @/td
|
||||||
|
# @td @img(/images/drc_separation13.png) @/td
|
||||||
|
# @/tr
|
||||||
|
# @/table
|
||||||
|
#
|
||||||
|
# @h3 Opposite and rectangle error filtering @/h3
|
||||||
#
|
#
|
||||||
# The options for the separation check are those available for the \width or \space
|
# The options for the separation check are those available for the \width or \space
|
||||||
# method plus opposite and rectangle error filtering.
|
# method plus opposite and rectangle error filtering.
|
||||||
|
|
@ -4121,6 +4157,7 @@ CODE
|
||||||
opposite_filter = RBA::Region::NoOppositeFilter
|
opposite_filter = RBA::Region::NoOppositeFilter
|
||||||
rect_filter = RBA::Region::NoRectFilter
|
rect_filter = RBA::Region::NoRectFilter
|
||||||
prop_constraint = RBA::Region::IgnoreProperties
|
prop_constraint = RBA::Region::IgnoreProperties
|
||||||
|
collinear_mode = RBA::Region::IncludeCollinearWhenTouch
|
||||||
|
|
||||||
n = 1
|
n = 1
|
||||||
args.each do |a|
|
args.each do |a|
|
||||||
|
|
@ -4132,6 +4169,8 @@ CODE
|
||||||
negative = true
|
negative = true
|
||||||
elsif a.is_a?(DRCPropertiesConstraint)
|
elsif a.is_a?(DRCPropertiesConstraint)
|
||||||
prop_constraint = a.value
|
prop_constraint = a.value
|
||||||
|
elsif a.is_a?(DRCCollinearMode)
|
||||||
|
collinear_mode = a.value
|
||||||
elsif a.is_a?(DRCOppositeErrorFilter)
|
elsif a.is_a?(DRCOppositeErrorFilter)
|
||||||
opposite_filter = a.value
|
opposite_filter = a.value
|
||||||
elsif a.is_a?(DRCRectangleErrorFilter)
|
elsif a.is_a?(DRCRectangleErrorFilter)
|
||||||
|
|
@ -4185,6 +4224,8 @@ CODE
|
||||||
raise("A rectangle error filter can only be used for polygon layers")
|
raise("A rectangle error filter can only be used for polygon layers")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
args << collinear_mode
|
||||||
|
|
||||||
border = (metrics == RBA::Region::Square ? value * 1.5 : value)
|
border = (metrics == RBA::Region::Square ? value * 1.5 : value)
|
||||||
|
|
||||||
if :#{f} == :width || :#{f} == :space || :#{f} == :notch || :#{f} == :isolated
|
if :#{f} == :width || :#{f} == :space || :#{f} == :notch || :#{f} == :isolated
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,16 @@ module DRC
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# A wrapper for the "collinear mode" for
|
||||||
|
# the DRC functions. The purpose of this class
|
||||||
|
# is to identify the value by the class.
|
||||||
|
class DRCCollinearMode
|
||||||
|
attr_accessor :value
|
||||||
|
def initialize(v)
|
||||||
|
self.value = v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# A wrapper for the "as_dots" or "as_boxes" flag for
|
# A wrapper for the "as_dots" or "as_boxes" flag for
|
||||||
# some DRC functions. The purpose of this class
|
# some DRC functions. The purpose of this class
|
||||||
# is to identify the value by the class.
|
# is to identify the value by the class.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue