mirror of https://github.com/KLayout/klayout.git
Added DRC test suite and "smoothed" function for DRC
This commit is contained in:
parent
14e1c0d5bd
commit
801f83f09c
|
|
@ -261,6 +261,16 @@ Region::rounded_corners (double rinner, double router, unsigned int n) const
|
|||
return r;
|
||||
}
|
||||
|
||||
Region
|
||||
Region::smoothed (coord_type d) const
|
||||
{
|
||||
Region r;
|
||||
for (const_iterator p = begin_merged (); ! p.at_end (); ++p) {
|
||||
r.insert (db::smooth (*p, d));
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
Region
|
||||
Region::in (const Region &other, bool invert) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1445,7 +1445,8 @@ public:
|
|||
*/
|
||||
void round_corners (double rinner, double router, unsigned int n)
|
||||
{
|
||||
*this = rounded_corners (rinner, router, n);
|
||||
Region r = rounded_corners (rinner, router, n);
|
||||
swap (r);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1453,6 +1454,22 @@ public:
|
|||
*/
|
||||
Region rounded_corners (double rinner, double router, unsigned int n) const;
|
||||
|
||||
/**
|
||||
* @brief Returns the smoothed region
|
||||
*
|
||||
* @param d The smoothing accuracy
|
||||
*/
|
||||
Region smoothed (coord_type d) const;
|
||||
|
||||
/**
|
||||
* @brief Smoothes the region (in-place)
|
||||
*/
|
||||
void smooth (coord_type d)
|
||||
{
|
||||
Region r = smoothed (d);
|
||||
swap (r);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the nth polygon
|
||||
*
|
||||
|
|
|
|||
|
|
@ -132,16 +132,6 @@ static void insert_si2 (db::Region *r, db::RecursiveShapeIterator si, db::ICplxT
|
|||
}
|
||||
}
|
||||
|
||||
static db::Region &smooth (db::Region *r, db::Coord d)
|
||||
{
|
||||
db::Region o;
|
||||
for (db::Region::const_iterator p = r->begin_merged (); ! p.at_end (); ++p) {
|
||||
o.insert (db::smooth (*p, d));
|
||||
}
|
||||
r->swap (o);
|
||||
return *r;
|
||||
}
|
||||
|
||||
static db::Region minkowsky_sum_pe (const db::Region *r, const db::Edge &e)
|
||||
{
|
||||
db::Region o;
|
||||
|
|
@ -1004,6 +994,26 @@ Class<db::Region> decl_Region ("Region",
|
|||
"See \\round_corners for a description of this method. This version returns a new region instead of "
|
||||
"modifying self (out-of-place)."
|
||||
) +
|
||||
method ("smooth", &db::Region::smooth,
|
||||
"@brief Smoothing\n"
|
||||
"@args d\n"
|
||||
"@param d The smoothing tolerance (in database units)\n"
|
||||
"\n"
|
||||
"This method will simplify the merged polygons of the region by removing vertexes if the "
|
||||
"resulting polygon stays equivalent with the original polygon. Equivalence is measured "
|
||||
"in terms of a deviation which is guaranteed to not become larger than \\d."
|
||||
"\n"
|
||||
"This method modifies the region. \\smoothed is a method that does the same but returns a new "
|
||||
"region without modifying self. Merged semantics applies for this method.\n"
|
||||
) +
|
||||
method ("smoothed", &db::Region::smoothed,
|
||||
"@brief Smoothing\n"
|
||||
"@args d\n"
|
||||
"@param d The smoothing tolerance (in database units)\n"
|
||||
"\n"
|
||||
"See \\smooth for a description of this method. This version returns a new region instead of "
|
||||
"modifying self (out-of-place). It has been introduced in version 0.25."
|
||||
) +
|
||||
method ("size", (db::Region & (db::Region::*) (db::Coord, db::Coord, unsigned int)) &db::Region::size,
|
||||
"@brief Anisotropic sizing (biasing)\n"
|
||||
"\n"
|
||||
|
|
@ -1346,21 +1356,6 @@ Class<db::Region> decl_Region ("Region",
|
|||
"This method is useful to avoid excessive memory allocation in some cases. "
|
||||
"For managed memory languages such as Ruby, those cases will be rare. "
|
||||
) +
|
||||
method_ext ("smooth", &smooth,
|
||||
"@brief Smooth the region\n"
|
||||
"@args d\n"
|
||||
"\n"
|
||||
"Remove vertices that deviate by more than the distance d from the average contours.\n"
|
||||
"The value d is basically the roughness which is removed.\n"
|
||||
"This method will apply smoothing to all polygons in the region.\n"
|
||||
"This method will modify the region it is called on.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"\n"
|
||||
"@param d The smoothing \"roughness\".\n"
|
||||
"\n"
|
||||
"@return The smoothed region (self).\n"
|
||||
) +
|
||||
method ("holes", &db::Region::holes,
|
||||
"@brief Returns the holes of the region\n"
|
||||
"This method returns all holes as filled polygons.\n"
|
||||
|
|
|
|||
|
|
@ -765,6 +765,9 @@ CODE
|
|||
#
|
||||
# This method return a layer wit the modified polygons. Merged semantics applies for this
|
||||
# method (see \raw and \clean).
|
||||
# If used with tiling, the rounded_corners function may render invalid results because
|
||||
# in tiling mode, not the whole merged region may be captured. In that case, inner
|
||||
# edges may appear as outer ones and their corners will receive rounding.
|
||||
#
|
||||
# The following image shows the effect of the "rounded_corners" method. The upper ends of
|
||||
# the vertical bars are rounded with a smaller radius automatically because their width does not allow
|
||||
|
|
@ -781,6 +784,23 @@ CODE
|
|||
DRCLayer::new(@engine, @engine._tcmd(@data, 0, RBA::Region, :rounded_corners, prep_value(inner), prep_value(outer), n))
|
||||
end
|
||||
|
||||
# %DRC%
|
||||
# @name smoothed
|
||||
# @brief Smoothes the polygons of the region
|
||||
# @synopsis layer.smoothed(d)
|
||||
#
|
||||
# "Smoothing" returns a simplified version of the polygons. Simplification is
|
||||
# achieved by removing vertices unless the resulting polygon deviates by more
|
||||
# than the given distance d from the original polygon.
|
||||
#
|
||||
# This method return a layer wit the modified polygons. Merged semantics applies for this
|
||||
# method (see \raw and \clean).
|
||||
|
||||
def smoothed(d)
|
||||
requires_region("smoothed")
|
||||
DRCLayer::new(@engine, @engine._tcmd(@data, 0, RBA::Region, :smoothed, prep_value(d)))
|
||||
end
|
||||
|
||||
# %DRC%
|
||||
# @name odd_polygons
|
||||
# @brief Checks for odd polygons (self-overlapping, non-orientable)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,564 @@
|
|||
|
||||
verbose(true)
|
||||
|
||||
source(File.dirname(__FILE__) + "/drctest.gds", "TOPTOP")
|
||||
|
||||
big_tests = false # @@@ set to true to enable all tests
|
||||
|
||||
|
||||
|
||||
0.1.um.to_s == "0.1" || raise("unexpected value")
|
||||
0.1.micron.to_s == "0.1" || raise("unexpected value")
|
||||
0.1.um2.to_s == "0.1" || raise("unexpected value")
|
||||
0.1.mm2.to_s == "100000.0" || raise("unexpected value")
|
||||
120.dbu.to_s == "0.12" || raise("unexpected value")
|
||||
(0.1.um + 120.dbu).to_s == "0.22" || raise("unexpected value")
|
||||
0.1.mm.to_s == "100.0" || raise("unexpected value")
|
||||
1e-6.m.to_s == "1.0" || raise("unexpected value")
|
||||
1.um.to_s == "1.0" || raise("unexpected value")
|
||||
1.micron.to_s == "1.0" || raise("unexpected value")
|
||||
1.um2.to_s == "1.0" || raise("unexpected value")
|
||||
1.mm2.to_s == "1000000.0" || raise("unexpected value")
|
||||
(1.um + 120.dbu).to_s == "1.12" || raise("unexpected value")
|
||||
1.mm.to_s == "1000.0" || raise("unexpected value")
|
||||
|
||||
def run_testsuite(dm, ic, tiled = false)
|
||||
|
||||
lb = 100
|
||||
|
||||
a = input(1)
|
||||
b = input(2)
|
||||
c = input(3)
|
||||
x = input(10)
|
||||
y = input(11)
|
||||
|
||||
c.is_merged? == false || raise("unexpected value")
|
||||
|
||||
puts "--- general #{lb}"
|
||||
|
||||
l1 = a&b
|
||||
l1.output(lb, dm)
|
||||
l1.is_empty? && raise("must not be empty")
|
||||
|
||||
a.and(b).xor(l1).is_empty? || raise("xor not empty")
|
||||
tiled || (a.and(b).is_merged? == true || raise("unexpected value"))
|
||||
|
||||
a.xor(b).output(lb + 1, dm)
|
||||
a.xor(b).xor(a ^ b).is_empty? || raise("xor not empty")
|
||||
a.not(b).output(lb + 2, dm)
|
||||
a.not(b).xor(a - b).is_empty? || raise("xor not empty")
|
||||
a.or(b).output(lb + 3, dm)
|
||||
a.or(b).xor(a | b).is_empty? || raise("xor not empty")
|
||||
|
||||
a.join(b).output(lb + 4, dm)
|
||||
a.join(b).xor(a + b).is_empty? || raise("xor not empty")
|
||||
|
||||
if !tiled
|
||||
a.join(b).data.size == 16 * ic || raise("unexpected shape count")
|
||||
end
|
||||
|
||||
c.raw.is_clean? == false || raise("unexpected value")
|
||||
# c.raw switched the semantics
|
||||
c.is_clean? == false || raise("unexpected value")
|
||||
(c.area / ic).to_s == "10.0" || raise("unexpected value")
|
||||
(c.edges.length / ic).to_s == "18.0" || raise("unexpected value")
|
||||
(c.perimeter / ic).to_s == "18.0" || raise("unexpected value")
|
||||
c.clean
|
||||
c.is_clean? == true || raise("unexpected value")
|
||||
(c.area / ic).to_s == "9.0" || raise("unexpected value")
|
||||
(c.edges.length / ic).to_s == "14.0" || raise("unexpected value")
|
||||
(c.perimeter / ic).to_s == "14.0" || raise("unexpected value")
|
||||
(c.dup.area / ic).to_s == "9.0" || raise("unexpected value")
|
||||
(c.raw.clean.area / ic).to_s == "9.0" || raise("unexpected value")
|
||||
(c.area / ic).to_s == "9.0" || raise("unexpected value")
|
||||
(c.raw.area / ic).to_s == "10.0" || raise("unexpected value")
|
||||
c.clean
|
||||
|
||||
if ic == 1
|
||||
c.bbox.to_s == "(-4,-5;0,-2)" || raise("unexpected value")
|
||||
end
|
||||
|
||||
lb += 10
|
||||
puts "--- centers, start_segments, end_segments #{lb}"
|
||||
|
||||
a.edges.centers(0.1).extended_out(0.01).output(lb, dm)
|
||||
a.edges.centers(0, 0.5).extended_out(0.01).output(lb + 1, dm)
|
||||
a.edges.centers(0.5, 0.5).extended_out(0.01).output(lb + 2, dm)
|
||||
a.edges.start_segments(0.1).extended_out(0.01).output(lb + 3, dm)
|
||||
a.edges.start_segments(0, 0.5).extended_out(0.01).output(lb + 4, dm)
|
||||
a.edges.start_segments(0.5, 0.5).extended_out(0.01).output(lb + 5, dm)
|
||||
a.edges.end_segments(0.1).extended_out(0.01).output(lb + 6, dm)
|
||||
a.edges.end_segments(0, 0.5).extended_out(0.01).output(lb + 7, dm)
|
||||
a.edges.end_segments(0.5, 0.5).extended_out(0.01).output(lb + 8, dm)
|
||||
|
||||
a.polygons? == true || raise("unexpected value")
|
||||
a.edges? == false || raise("unexpected value")
|
||||
a.edge_pairs? == false || raise("unexpected value")
|
||||
a.edges.edge_pairs? == false || raise("unexpected value")
|
||||
a.edges.polygons? == false || raise("unexpected value")
|
||||
a.edges.edges? == true || raise("unexpected value")
|
||||
a.space(0.5).edge_pairs? == true || raise("unexpected value")
|
||||
a.space(0.5).polygons? == false || raise("unexpected value")
|
||||
a.space(0.5).edges? == false || raise("unexpected value")
|
||||
|
||||
lb += 10
|
||||
puts "--- extended #{lb}"
|
||||
|
||||
a.edges.with_length(0.6).extended(begin: 0.1, end: 0.15, out: 0.1, in: -0.05).output(lb, dm)
|
||||
a.edges.with_length(0.6).extended(out: 0.1, in: -0.05).output(lb + 1, dm)
|
||||
a.edges.with_length(0..0.7).extended(out: 0.1, in: -0.05).output(lb + 2, dm)
|
||||
a.edges.with_length(0..0.7).extended(out: 0.1, in: -0.05, joined: true).output(lb + 3, dm)
|
||||
a.edges.with_length(0..0.7).extended(begin: 0.1, end: 0.15, out: 0.1, in: 0.05, joined: true).output(lb + 4, dm)
|
||||
a.edges.with_length(0..0.7).extended(0.1, 0.15, 0.1, 0.05).output(lb + 5, dm)
|
||||
a.edges.with_length(0..0.7).extended(0.1, 0.15, 0.1, 0.05, true).output(lb + 6, dm)
|
||||
a.edges.with_length(0..0.7).extended_out(0.1).output(lb + 7, dm)
|
||||
a.edges.with_length(0..0.7).extended_in(0.1).output(lb + 8, dm)
|
||||
|
||||
lb += 10
|
||||
puts "--- extents #{lb}"
|
||||
|
||||
b.extents.output(lb, dm)
|
||||
|
||||
lb += 10
|
||||
puts "--- first_edges, second_edges, edges #{lb}"
|
||||
|
||||
a.enclosing(b, 0.5, whole_edges).first_edges.extended_out(0.01).output(lb, dm)
|
||||
a.enclosing(b, 0.5, whole_edges).second_edges.extended_out(0.01).output(lb + 1, dm)
|
||||
a.enclosing(b, 0.5, whole_edges).edges.extended_out(0.01).output(lb + 2, dm)
|
||||
|
||||
lb += 10
|
||||
puts "--- hulls, holes #{lb}"
|
||||
|
||||
c.xor(b).holes.output(lb, dm)
|
||||
c.xor(b).hulls.output(lb + 1, dm)
|
||||
c.xor(b).xor(c.xor(b).hulls - c.xor(b).holes).is_empty? || raise("xor not empty")
|
||||
|
||||
lb += 10
|
||||
puts "--- interacting, in, not_in #{lb}"
|
||||
|
||||
b.interacting(a).output(lb, dm)
|
||||
b.interacting(a).in(b).output(lb + 1, dm)
|
||||
(b|a).not_in(b).output(lb + 2, dm)
|
||||
x.in(b).output(lb + 3, dm)
|
||||
b.sized(0.1).in(b).is_empty? == true || raise("unexpected value")
|
||||
|
||||
lb += 10
|
||||
puts "--- inside, outside, overlapping, interacting #{lb}"
|
||||
|
||||
b.inside(c).output(lb, dm)
|
||||
b.outside(c).output(lb + 1, dm)
|
||||
b.overlapping(c).output(lb + 2, dm)
|
||||
b.interacting(c).output(lb + 3, dm)
|
||||
bdup = b.dup
|
||||
bdup.select_inside(c)
|
||||
bdup.xor(b.inside(c)).output(lb + 4, dm)
|
||||
bdup = b.dup
|
||||
bdup.select_outside(c)
|
||||
bdup.xor(b.outside(c)).output(lb + 5, dm)
|
||||
bdup = b.dup
|
||||
bdup.select_overlapping(c)
|
||||
bdup.xor(b.overlapping(c)).output(lb + 6, dm)
|
||||
bdup = b.dup
|
||||
bdup.select_interacting(c)
|
||||
bdup.xor(b.interacting(c)).output(lb + 7, dm)
|
||||
|
||||
lb += 10
|
||||
puts "--- merge #{lb}"
|
||||
|
||||
c.raw
|
||||
if !tiled
|
||||
c.merged.is_merged? == true || raise("unexpected value")
|
||||
end
|
||||
c.merged.output(lb, dm)
|
||||
c.merged(2).output(lb + 1, dm)
|
||||
c.merged(3).output(lb + 2, dm)
|
||||
c.clean
|
||||
cdup = c.dup
|
||||
cdup.merge.xor(c.merged).output(lb + 3, dm)
|
||||
cdup.xor(c.merged).output(lb + 4, dm)
|
||||
cdup = c.dup
|
||||
cdup.merge(2).xor(c.merged(2)).output(lb + 5, dm)
|
||||
cdup.xor(c.merged(2)).output(lb + 6, dm)
|
||||
|
||||
lb += 10
|
||||
puts "--- move, transform, rotate, scale #{lb}"
|
||||
|
||||
c.moved(0.2, -0.1).output(lb, dm)
|
||||
cdup = c.dup
|
||||
cdup.move(0.2, -0.1)
|
||||
cdup.xor(c.moved(0.2, -0.1)).is_empty? == true || raise("xor not empty")
|
||||
t = RBA::DCplxTrans::new(0.5)
|
||||
c.transformed(t).output(lb + 1, dm)
|
||||
cdup = c.dup
|
||||
cdup.transform(t)
|
||||
cdup.xor(c.transformed(t)).is_empty? == true || raise("xor not empty")
|
||||
c.scaled(0.5).output(lb + 2, dm)
|
||||
cdup = c.dup
|
||||
cdup.scale(0.5)
|
||||
cdup.xor(c.scaled(0.5)).is_empty? == true || raise("xor not empty")
|
||||
c.rotated(45).output(lb + 3, dm)
|
||||
cdup = c.dup
|
||||
cdup.rotate(45)
|
||||
cdup.xor(c.rotated(45)).is_empty? == true || raise("xor not empty")
|
||||
|
||||
lb += 10
|
||||
puts "--- rectangles, rectilinear #{lb}"
|
||||
|
||||
a.rectangles.output(lb, dm)
|
||||
a.non_rectangles.output(lb + 1, dm)
|
||||
a.rectilinear.output(lb + 2, dm)
|
||||
a.non_rectilinear.output(lb + 3, dm)
|
||||
c.raw
|
||||
c.non_rectangles.output(lb + 4, dm)
|
||||
c.clean
|
||||
c.rectangles.output(lb + 5, dm)
|
||||
|
||||
lb += 10
|
||||
puts "--- enclosing #{lb}"
|
||||
|
||||
a.enclosing(b, 0.5).polygons.output(lb, dm)
|
||||
a.enclosing(b, 0.5).polygons.xor(a.enc(b, 0.5).polygons).is_empty? == true || raise("xor not empty")
|
||||
a.enclosing(b, 0.5, euclidian).polygons.output(lb + 1, dm)
|
||||
a.enclosing(b, 0.5, square).polygons.output(lb + 2, dm)
|
||||
a.enclosing(b, 0.5, projection).polygons.output(lb + 3, dm)
|
||||
a.enclosing(b, 0.5, euclidian, whole_edges).polygons.output(lb + 4, dm)
|
||||
a.enclosing(b, 0.5, euclidian, projection_limits(0.4, nil)).polygons.output(lb + 5, dm)
|
||||
a.enclosing(b, 0.5, euclidian, projection_limits(nil, 0.4)).polygons.output(lb + 6, dm)
|
||||
a.enclosing(b, 0.5, euclidian, projection_limits(0..0.4)).polygons.output(lb + 7, dm)
|
||||
|
||||
lb += 10
|
||||
puts "--- enclosing (edges) #{lb}"
|
||||
|
||||
ae = a.edges
|
||||
be = b.edges
|
||||
ae.enclosing(be, 0.5).polygons.output(lb, dm)
|
||||
ae.enclosing(be, 0.5).polygons.xor(ae.enc(be, 0.5).polygons).is_empty? == true || raise("xor not empty")
|
||||
ae.enclosing(be, 0.5, euclidian).polygons.output(lb + 1, dm)
|
||||
ae.enclosing(be, 0.5, square).polygons.output(lb + 2, dm)
|
||||
ae.enclosing(be, 0.5, projection).polygons.output(lb + 3, dm)
|
||||
ae.enclosing(be, 0.5, euclidian, whole_edges).polygons.output(lb + 4, dm)
|
||||
ae.enclosing(be, 0.5, euclidian, projection_limits(0.4, nil)).polygons.output(lb + 5, dm)
|
||||
ae.enclosing(be, 0.5, euclidian, projection_limits(nil, 0.4)).polygons.output(lb + 6, dm)
|
||||
ae.enclosing(be, 0.5, euclidian, projection_limits(0..0.4)).polygons.output(lb + 7, dm)
|
||||
|
||||
lb += 10
|
||||
puts "--- isolated #{lb}"
|
||||
|
||||
b.isolated(0.4).polygons.output(lb, dm)
|
||||
b.isolated(0.4).polygons.xor(b.iso(0.4).polygons).is_empty? == true || raise("xor not empty")
|
||||
b.isolated(0.4, euclidian).polygons.output(lb + 1, dm)
|
||||
b.isolated(0.4, square).polygons.output(lb + 2, dm)
|
||||
b.isolated(0.4, projection).polygons.output(lb + 3, dm)
|
||||
b.isolated(0.4, euclidian, whole_edges).polygons.output(lb + 4, dm)
|
||||
b.isolated(0.4, euclidian, projection_limits(0.4, nil)).polygons.output(lb + 5, dm)
|
||||
b.isolated(0.4, euclidian, projection_limits(nil, 0.4)).polygons.output(lb + 6, dm)
|
||||
b.isolated(0.4, euclidian, projection_limits(0..0.4)).polygons.output(lb + 7, dm)
|
||||
|
||||
lb += 10
|
||||
puts "--- notch #{lb}"
|
||||
|
||||
b.notch(0.4).polygons.output(lb, dm)
|
||||
b.notch(0.4, euclidian).polygons.output(lb + 1, dm)
|
||||
b.notch(0.4, square).polygons.output(lb + 2, dm)
|
||||
b.notch(0.4, projection).polygons.output(lb + 3, dm)
|
||||
b.notch(0.4, euclidian, whole_edges).polygons.output(lb + 4, dm)
|
||||
b.notch(0.4, euclidian, projection_limits(0.4, nil)).polygons.output(lb + 5, dm)
|
||||
b.notch(0.4, euclidian, projection_limits(nil, 0.4)).polygons.output(lb + 6, dm)
|
||||
b.notch(0.4, euclidian, projection_limits(0..0.4)).polygons.output(lb + 7, dm)
|
||||
|
||||
lb += 10
|
||||
puts "--- overlap #{lb}"
|
||||
|
||||
a.overlap(b, 0.5).polygons.output(lb, dm)
|
||||
a.overlap(b, 0.5, euclidian).polygons.output(lb + 1, dm)
|
||||
a.overlap(b, 0.5, square).polygons.output(lb + 2, dm)
|
||||
a.overlap(b, 0.5, projection).polygons.output(lb + 3, dm)
|
||||
a.overlap(b, 0.5, euclidian, whole_edges).polygons.output(lb + 4, dm)
|
||||
a.overlap(b, 0.5, euclidian, projection_limits(0.4, nil)).polygons.output(lb + 5, dm)
|
||||
a.overlap(b, 0.5, euclidian, projection_limits(nil, 0.4)).polygons.output(lb + 6, dm)
|
||||
a.overlap(b, 0.5, euclidian, projection_limits(0..0.4)).polygons.output(lb + 7, dm)
|
||||
|
||||
lb += 10
|
||||
puts "--- overlap (edges) #{lb}"
|
||||
|
||||
ae = a.edges
|
||||
be = b.edges
|
||||
ae.overlap(be, 0.5).polygons.output(lb, dm)
|
||||
ae.overlap(be, 0.5, euclidian).polygons.output(lb + 1, dm)
|
||||
ae.overlap(be, 0.5, square).polygons.output(lb + 2, dm)
|
||||
ae.overlap(be, 0.5, projection).polygons.output(lb + 3, dm)
|
||||
ae.overlap(be, 0.5, euclidian, whole_edges).polygons.output(lb + 4, dm)
|
||||
ae.overlap(be, 0.5, euclidian, projection_limits(0.4, nil)).polygons.output(lb + 5, dm)
|
||||
ae.overlap(be, 0.5, euclidian, projection_limits(nil, 0.4)).polygons.output(lb + 6, dm)
|
||||
ae.overlap(be, 0.5, euclidian, projection_limits(0..0.4)).polygons.output(lb + 7, dm)
|
||||
|
||||
lb += 10
|
||||
puts "--- separation #{lb}"
|
||||
|
||||
a.separation(b, 0.4).polygons.output(lb, dm)
|
||||
a.separation(b, 0.4).polygons.xor(a.sep(b, 0.4).polygons).is_empty? == true || raise("xor not empty")
|
||||
a.separation(b, 0.4, euclidian).polygons.output(lb + 1, dm)
|
||||
a.separation(b, 0.4, square).polygons.output(lb + 2, dm)
|
||||
a.separation(b, 0.4, projection).polygons.output(lb + 3, dm)
|
||||
a.separation(b, 0.4, euclidian, whole_edges).polygons.output(lb + 4, dm)
|
||||
a.separation(b, 0.4, euclidian, projection_limits(0.4, nil)).polygons.output(lb + 5, dm)
|
||||
a.separation(b, 0.4, euclidian, projection_limits(nil, 0.4)).polygons.output(lb + 6, dm)
|
||||
a.separation(b, 0.4, euclidian, projection_limits(0..0.4)).polygons.output(lb + 7, dm)
|
||||
|
||||
lb += 10
|
||||
puts "--- sized #{lb}"
|
||||
|
||||
x.sized(0.1).output(lb, dm)
|
||||
x.sized(0.1, 0).output(lb + 1, dm)
|
||||
x.sized(0.1, diamond_limit).output(lb + 2, dm)
|
||||
x.sized(0.1, octagon_limit).output(lb + 3, dm)
|
||||
x.sized(0.1, square_limit).output(lb + 4, dm)
|
||||
x.sized(0.1, acute_limit).output(lb + 5, dm)
|
||||
x.sized(0.1, no_limit).output(lb + 6, dm)
|
||||
xdup = x.dup
|
||||
xdup.size(0.1, 0)
|
||||
xdup.xor(x.sized(0.1, 0)).is_empty? == true || raise("xor not empty")
|
||||
a.sized(4.0, no_limit).output(lb + 7, dm)
|
||||
|
||||
lb += 10
|
||||
puts "--- space #{lb}"
|
||||
|
||||
b.space(0.4).polygons.output(lb, dm)
|
||||
b.space(0.4, euclidian).polygons.output(lb + 1, dm)
|
||||
b.space(0.4, square).polygons.output(lb + 2, dm)
|
||||
b.space(0.4, projection).polygons.output(lb + 3, dm)
|
||||
b.space(0.4, euclidian, whole_edges).polygons.output(lb + 4, dm)
|
||||
b.space(0.4, euclidian, projection_limits(0.4, nil)).polygons.output(lb + 5, dm)
|
||||
b.space(0.4, euclidian, projection_limits(nil, 0.4)).polygons.output(lb + 6, dm)
|
||||
b.space(0.4, euclidian, projection_limits(0..0.4)).polygons.output(lb + 7, dm)
|
||||
|
||||
lb += 10
|
||||
puts "--- space (edges) #{lb}"
|
||||
|
||||
be = b.edges
|
||||
be.space(0.4).polygons.output(lb, dm)
|
||||
be.space(0.4, euclidian).polygons.output(lb + 1, dm)
|
||||
be.space(0.4, square).polygons.output(lb + 2, dm)
|
||||
be.space(0.4, projection).polygons.output(lb + 3, dm)
|
||||
be.space(0.4, euclidian, whole_edges).polygons.output(lb + 4, dm)
|
||||
be.space(0.4, euclidian, projection_limits(0.4, nil)).polygons.output(lb + 5, dm)
|
||||
be.space(0.4, euclidian, projection_limits(nil, 0.4)).polygons.output(lb + 6, dm)
|
||||
be.space(0.4, euclidian, projection_limits(0..0.4)).polygons.output(lb + 7, dm)
|
||||
|
||||
lb += 10
|
||||
puts "--- width #{lb}"
|
||||
|
||||
b.width(0.4).polygons.output(lb, dm)
|
||||
b.width(0.4, euclidian).polygons.output(lb + 1, dm)
|
||||
b.width(0.4, square).polygons.output(lb + 2, dm)
|
||||
b.width(0.4, projection).polygons.output(lb + 3, dm)
|
||||
b.width(0.4, euclidian, whole_edges).polygons.output(lb + 4, dm)
|
||||
b.width(0.4, euclidian, projection_limits(0.4, nil)).polygons.output(lb + 5, dm)
|
||||
b.width(0.4, euclidian, projection_limits(nil, 0.4)).polygons.output(lb + 6, dm)
|
||||
b.width(0.4, euclidian, projection_limits(0..0.4)).polygons.output(lb + 7, dm)
|
||||
|
||||
lb += 10
|
||||
puts "--- width (edges) #{lb}"
|
||||
|
||||
be = b.edges
|
||||
be.width(0.4).polygons.output(lb, dm)
|
||||
be.width(0.4, euclidian).polygons.output(lb + 1, dm)
|
||||
be.width(0.4, square).polygons.output(lb + 2, dm)
|
||||
be.width(0.4, projection).polygons.output(lb + 3, dm)
|
||||
be.width(0.4, euclidian, whole_edges).polygons.output(lb + 4, dm)
|
||||
be.width(0.4, euclidian, projection_limits(0.4, nil)).polygons.output(lb + 5, dm)
|
||||
be.width(0.4, euclidian, projection_limits(nil, 0.4)).polygons.output(lb + 6, dm)
|
||||
be.width(0.4, euclidian, projection_limits(0..0.4)).polygons.output(lb + 7, dm)
|
||||
|
||||
lb += 10
|
||||
puts "--- with_angle #{lb}"
|
||||
|
||||
a.edges.with_angle(90.degree).extended_out(0.01).output(lb, dm)
|
||||
a.edges.with_angle(45 .. 90.1).extended_out(0.01).output(lb + 1, dm)
|
||||
a.edges.with_angle(0, 45.1).extended_out(0.01).output(lb + 2, dm)
|
||||
a.edges.without_angle(90.degree).extended_out(0.01).output(lb + 3, dm)
|
||||
a.edges.without_angle(45 .. 90.1).extended_out(0.01).output(lb + 4, dm)
|
||||
a.edges.without_angle(0, 45.1).extended_out(0.01).output(lb + 5, dm)
|
||||
a.with_angle(135).polygons.output(lb + 6, dm)
|
||||
|
||||
lb += 10
|
||||
puts "--- with_area #{lb}"
|
||||
|
||||
b.with_area(0.49.um2).output(lb, dm)
|
||||
b.with_area(0 .. 0.5).output(lb + 1, dm)
|
||||
b.with_area(0.5, nil).output(lb + 2, dm)
|
||||
b.without_area(0.49.um2).output(lb + 3, dm)
|
||||
b.without_area(nil, 0.5).output(lb + 4, dm)
|
||||
b.without_area(0.5, nil).output(lb + 5, dm)
|
||||
|
||||
lb += 10
|
||||
puts "--- with_perimeter #{lb}"
|
||||
|
||||
b.with_perimeter(2.8.um).output(lb, dm)
|
||||
b.with_perimeter(0 .. 3.um).output(lb + 1, dm)
|
||||
b.with_perimeter(3.um, nil).output(lb + 2, dm)
|
||||
b.without_perimeter(2.8.um).output(lb + 3, dm)
|
||||
b.without_perimeter(nil, 3.um).output(lb + 4, dm)
|
||||
b.without_perimeter(3.um, nil).output(lb + 5, dm)
|
||||
|
||||
lb += 10
|
||||
puts "--- with_bbox_height #{lb}"
|
||||
|
||||
b.with_bbox_height(0.7.um).output(lb, dm)
|
||||
b.with_bbox_height(0 .. 0.7.um+1.dbu).output(lb + 1, dm)
|
||||
b.with_bbox_height(0.7.um, nil).output(lb + 2, dm)
|
||||
b.without_bbox_height(0.7.um).output(lb + 3, dm)
|
||||
b.without_bbox_height(nil, 0.7.um+1.dbu).output(lb + 4, dm)
|
||||
b.without_bbox_height(0.7.um, nil).output(lb + 5, dm)
|
||||
|
||||
lb += 10
|
||||
puts "--- with_bbox_width #{lb}"
|
||||
|
||||
b.with_bbox_width(0.7.um).output(lb, dm)
|
||||
b.with_bbox_width(0 .. 0.7.um+1.dbu).output(lb + 1, dm)
|
||||
b.with_bbox_width(0.7.um, nil).output(lb + 2, dm)
|
||||
b.without_bbox_width(0.7.um).output(lb + 3, dm)
|
||||
b.without_bbox_width(nil, 0.7.um+1.dbu).output(lb + 4, dm)
|
||||
b.without_bbox_width(0.7.um, nil).output(lb + 5, dm)
|
||||
|
||||
lb += 10
|
||||
puts "--- with_bbox_min #{lb}"
|
||||
|
||||
b.with_bbox_min(0.7.um).output(lb, dm)
|
||||
b.with_bbox_min(0 .. 0.7.um+1.dbu).output(lb + 1, dm)
|
||||
b.with_bbox_min(0.7.um, nil).output(lb + 2, dm)
|
||||
b.without_bbox_min(0.7.um).output(lb + 3, dm)
|
||||
b.without_bbox_min(nil, 0.7.um+1.dbu).output(lb + 4, dm)
|
||||
b.without_bbox_min(0.7.um, nil).output(lb + 5, dm)
|
||||
|
||||
lb += 10
|
||||
puts "--- with_bbox_max #{lb}"
|
||||
|
||||
b.with_bbox_max(0.7.um).output(lb, dm)
|
||||
b.with_bbox_max(0 .. 0.7.um+1.dbu).output(lb + 1, dm)
|
||||
b.with_bbox_max(0.7.um, nil).output(lb + 2, dm)
|
||||
b.without_bbox_max(0.7.um).output(lb + 3, dm)
|
||||
b.without_bbox_max(nil, 0.7.um+1.dbu).output(lb + 4, dm)
|
||||
b.without_bbox_max(0.7.um, nil).output(lb + 5, dm)
|
||||
|
||||
lb += 10
|
||||
puts "--- with_length #{lb}"
|
||||
|
||||
a.edges.with_length(0.6.um).extended_out(0.01).output(lb, dm)
|
||||
a.edges.with_length(0 .. 0.6.um+1.dbu).extended_out(0.01).output(lb + 1, dm)
|
||||
a.edges.with_length(0.6, nil).extended_out(0.01).output(lb + 2, dm)
|
||||
a.edges.without_length(0.6.um).extended_out(0.01).output(lb + 3, dm)
|
||||
a.edges.without_length(0 .. 0.6.um+1.dbu).extended_out(0.01).output(lb + 4, dm)
|
||||
a.edges.without_length(0.6, nil).extended_out(0.01).output(lb + 5, dm)
|
||||
|
||||
lb += 10
|
||||
puts "--- ongrid, snap #{lb}"
|
||||
|
||||
a.ongrid(0.2).polygons(1.dbu).output(lb, dm)
|
||||
a.ongrid(0, 0.1).polygons(1.dbu).output(lb + 1, dm)
|
||||
a.snapped(0.2).output(lb + 2, dm)
|
||||
a.snapped(0, 0.1).output(lb + 3, dm)
|
||||
adup = a.dup
|
||||
adup.snap(0.2)
|
||||
adup.xor(a.snapped(0.2)).output(lb + 4, dm)
|
||||
|
||||
lb += 10
|
||||
puts "--- odd polygon check #{lb}"
|
||||
|
||||
y.odd_polygons.output(lb, dm)
|
||||
|
||||
end
|
||||
|
||||
cell("TOP")
|
||||
|
||||
x = polygon_layer
|
||||
x.is_empty? == true || raise("unexpected value")
|
||||
x.is_box? == false || raise("unexpected value")
|
||||
x.insert(box(4.0, 0, 4.7, 0.7))
|
||||
x.is_empty? == false || raise("unexpected value")
|
||||
x.is_box? == true || raise("unexpected value")
|
||||
x.insert(polygon([ p(0, 0), p(2.0, 0), p(1.0, 1.0) ]))
|
||||
x.insert(polygon([ p(0, -5.0), p(2.0, -5.0), p(1.0, -6.0) ]))
|
||||
x.insert(path([ p(0, -2), p(2.0, -2) ], 0.2))
|
||||
x.is_box? == false || raise("unexpected value")
|
||||
x.output(10, 0)
|
||||
|
||||
y = polygon_layer
|
||||
y.insert(polygon([ p(0, 0), p(0, 1.0), p(2.0, 1.0), p(2.0, 2.0), p(1.0, 2.0), p(1.0, 0) ]))
|
||||
y.output(11, 0)
|
||||
|
||||
a1 = input(1)
|
||||
b1 = input(2)
|
||||
c1 = input(3)
|
||||
|
||||
puts "=== Simple tests ==="
|
||||
|
||||
cell("TOP")
|
||||
|
||||
c1.rounded_corners(0.5, 0.5, 16).output(1010, 0)
|
||||
c1.smoothed(1.5).output(1011, 0)
|
||||
|
||||
puts "=== Single-cell testsuite ==="
|
||||
|
||||
run_testsuite(0, 1)
|
||||
|
||||
output_cell("NEW")
|
||||
|
||||
puts "=== Foreign-cell test ==="
|
||||
|
||||
a1.and(b1).output(1000, 0)
|
||||
|
||||
cell("TOPTOP")
|
||||
|
||||
a1.and(b1).output(1001, 0)
|
||||
|
||||
if big_tests
|
||||
|
||||
puts "=== Multi-cell testsuite ==="
|
||||
|
||||
run_testsuite(1, 900)
|
||||
|
||||
puts "=== Multi-cell testsuite (tiled) ==="
|
||||
|
||||
tiles(4.1, 5.2)
|
||||
# must be that big ...
|
||||
tile_borders(1.um, 1.um)
|
||||
threads(4)
|
||||
|
||||
run_testsuite(2, 900, true)
|
||||
|
||||
puts "=== Multi-cell testsuite (pseudo-tiled) ==="
|
||||
|
||||
tiles(10000.0, 10000.0)
|
||||
tile_borders(0, 0)
|
||||
threads(4)
|
||||
|
||||
run_testsuite(3, 900, true)
|
||||
|
||||
flat
|
||||
threads(1)
|
||||
|
||||
puts "=== XOR ==="
|
||||
|
||||
(100..900).each do |lo|
|
||||
a = input(lo, 0)
|
||||
b = input(lo, 1)
|
||||
if !a.is_empty? || !b.is_empty?
|
||||
a.xor(b).output(lo, 10)
|
||||
end
|
||||
a = input(lo, 1)
|
||||
b = input(lo, 2)
|
||||
if !a.is_empty? || !b.is_empty?
|
||||
a.xor(b).output(lo, 11)
|
||||
end
|
||||
a = input(lo, 1)
|
||||
b = input(lo, 3)
|
||||
if !a.is_empty? || !b.is_empty?
|
||||
a.xor(b).output(lo, 12)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
source.layout.write("drctest_out.gds")
|
||||
|
||||
Binary file not shown.
|
|
@ -0,0 +1,14 @@
|
|||
|
||||
verbose(true)
|
||||
|
||||
layout = RBA::Layout::new
|
||||
layout.read(File.dirname(__FILE__) + "/drctest.gds")
|
||||
source(layout, "TOPTOP")
|
||||
|
||||
layout2 = RBA::Layout::new
|
||||
target(layout2)
|
||||
|
||||
input(3, 0).output(100, 0)
|
||||
|
||||
layout2.write("drctest2_out.gds")
|
||||
|
||||
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,21 @@
|
|||
#!/bin/sh -e
|
||||
|
||||
# Must be run in the build directory where klayout and strcmp are located.
|
||||
|
||||
inst=$(dirname $0)
|
||||
|
||||
export LD_LIBRARY_PATH=.
|
||||
|
||||
make klayout
|
||||
|
||||
for t in drctest drctest2; do
|
||||
|
||||
echo "-----------------------------------------------"
|
||||
echo "Run drctest.drc ..."
|
||||
|
||||
./klayout -zz -r $inst/$t.drc
|
||||
|
||||
strmcmp ${t}_out.gds $inst/${t}_au.oas.gz
|
||||
|
||||
done
|
||||
|
||||
|
|
@ -260,6 +260,7 @@ class DBRegion_TestClass < TestBase
|
|||
assert_equal(rr.to_s, "(0,0;0,200;11,200;12,201;14,202;16,202;18,201;19,200;100,200;100,0)")
|
||||
rr.smooth(1)
|
||||
assert_equal(rr.to_s, "(0,0;0,200;11,200;14,202;18,201;100,200;100,0)")
|
||||
assert_equal(rr.smoothed(5).to_s, "(0,0;0,200;100,200;100,0)")
|
||||
rr.smooth(5)
|
||||
assert_equal(rr.to_s, "(0,0;0,200;100,200;100,0)")
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue