WIP: stashed another version of complex DRC framework

This commit is contained in:
Matthias Koefferlein 2021-01-02 21:32:56 +01:00
parent 815b81ce59
commit 43302dbe68
1 changed files with 78 additions and 93 deletions

View File

@ -32,7 +32,7 @@ class DRCOpNode
attr_accessor :engine
def initialize(engine, node = nil)
@node = nil
@node = node
self.engine = engine
self.description = "Basic"
end
@ -45,37 +45,11 @@ class DRCOpNode
return indent + self.description
end
def _build_log_bool_node(other, op)
if ! other.is_a?(DRCOpNode)
raise("Second argument to #{op.to_s} must be a DRC expression")
end
if self.is_a?(DRCOpNodeLogicalBool) && self.op == op
self.children << other
return self
elsif other.is_a?(DRCOpNodeLogicalBool) && other.op == op
other.children.unshift(self)
return other
else
res = DRCOpNodeLogicalBool::new(op)
res.children = [ self, other ]
res
end
end
%w(and or).each do |f|
eval <<"CODE"
def #
#{f}(other)
self._build_log_bool_node(other, :#{f})
end
CODE
end
def _build_geo_bool_node(other, op)
if ! other.is_a?(DRCOpNode)
raise("Second argument to #{op.to_s} must be a DRC expression")
end
DRCOpNodeBool::new(op, self, other)
DRCOpNodeBool::new(@engine, op, self, other)
end
%w(& - ^ | +).each do |f|
@ -91,10 +65,8 @@ CODE
if self.respond_to?(:inverted)
return self.inverted
else
res = DRCOpNodeCase::new
res.children << self
res.children << nil
res.children << @engine.primary
empty = RBA::CompoundRegionOperationNode::new_empty(RBA::CompoundRegionOperationNode::ResultType::Region)
DRCOpNodeCase::new(@engine, [ self, DRCOpNode::new(@engine, empty), @engine.primary ])
end
end
@ -237,28 +209,28 @@ CODE
CODE
end
def odd_polygons
return DRCOpNodeFilter(@engine, self, :new_strange_polygons_filter, "odd_polygons")
def odd_polygon
return DRCOpNodeFilter::new(@engine, self, :new_strange_polygons_filter, "odd_polygon")
end
def rectangles
return DRCOpNodeFilter(@engine, self, :new_rectangle_filter, "rectangles")
def rectangle
return DRCOpNodeFilter::new(@engine, self, :new_rectangle_filter, "rectangle")
end
def rectilinear
return DRCOpNodeFilter(@engine, self, :new_rectilinear_filter, "rectilinear")
return DRCOpNodeFilter::new(@engine, self, :new_rectilinear_filter, "rectilinear")
end
def holes
return DRCOpNodeFilter(@engine, self, :new_holes, "holes")
return DRCOpNodeFilter::new(@engine, self, :new_holes, "holes")
end
def hulls
return DRCOpNodeFilter(@engine, self, :new_hulls, "hulls")
def hull
return DRCOpNodeFilter::new(@engine, self, :new_hulls, "hull")
end
def edges
return DRCOpNodeFilter(@engine, self, :new_edges, "edges")
return DRCOpNodeFilter::new(@engine, self, :new_edges, "edges")
end
def sized(*args)
@ -288,35 +260,35 @@ CODE
end
args << mode
return DRCOpNodeFilter(@engine, self, :new_sized, "sized", *args)
return DRCOpNodeFilter::new(@engine, self, :new_sized, "sized", *args)
end
def extents(e = 0)
return DRCOpNodeFilter(@engine, self, :new_extents, "extents", self._make_value(e, :e))
return DRCOpNodeFilter::new(@engine, self, :new_extents, "extents", self._make_value(e, :e))
end
def first_edges
return DRCOpNodeFilter(@engine, self, :new_edge_pair_to_first_edges, "first_edges")
return DRCOpNodeFilter::new(@engine, self, :new_edge_pair_to_first_edges, "first_edges")
end
def second_edges
return DRCOpNodeFilter(@engine, self, :new_edge_pair_to_second_edges, "second_edges")
return DRCOpNodeFilter::new(@engine, self, :new_edge_pair_to_second_edges, "second_edges")
end
def end_segments(length, fraction = 0.0)
self._check_numeric(fraction, :fraction)
return DRCOpNodeFilter(@engine, self, :new_end_segments, "end_segments", self._make_value(length, :length), fraction)
return DRCOpNodeFilter::new(@engine, self, :new_end_segments, "end_segments", self._make_value(length, :length), fraction)
end
def start_segments(length, fraction = 0.0)
self._check_numeric(fraction, :fraction)
return DRCOpNodeFilter(@engine, self, :new_start_segments, "start_segments", self._make_value(length, :length), fraction)
return DRCOpNodeFilter::new(@engine, self, :new_start_segments, "start_segments", self._make_value(length, :length), fraction)
end
def centers(length, fraction = 0.0)
self._check_numeric(fraction, :fraction)
return DRCOpNodeFilter(@engine, self, :new_centers, "centers", self._make_value(length, :length), fraction)
return DRCOpNodeFilter::new(@engine, self, :new_centers, "centers", self._make_value(length, :length), fraction)
end
def extended(*args)
@ -336,20 +308,20 @@ CODE
end
end
return DRCOpNodeFilter(@engine, self, :new_extended, "extended", *args)
return DRCOpNodeFilter::new(@engine, self, :new_extended, "extended", *args)
end
def extended_in(e)
return DRCOpNodeFilter(@engine, self, :new_extended_in, "extended_in", self._make_value(e))
return DRCOpNodeFilter::new(@engine, self, :new_extended_in, "extended_in", self._make_value(e))
end
def extended_out(e)
return DRCOpNodeFilter(@engine, self, :new_extended_out, "extended_out", self._make_value(e))
return DRCOpNodeFilter::new(@engine, self, :new_extended_out, "extended_out", self._make_value(e))
end
def polygons
return DRCOpNodeFilter(@engine, self, :new_polygons, "polygons")
return DRCOpNodeFilter::new(@engine, self, :new_polygons, "polygons")
end
end
@ -371,8 +343,8 @@ class DRCOpNodeLogicalBool < DRCOpNode
end
def create_node
log_op = { :and => RBA::CompoundOperationNode::LogAnd, :or => RBA::CompoundOperationNode::LogOr }[self.op]
RBA::CompoundOperationNode::new_logical_boolean(log_op, false, self.children.collect { |c| c.create_node })
log_op = { :land => RBA::CompoundRegionOperationNode::LogicalOp::LogAnd, :lor => RBA::CompoundRegionOperationNode::LogicalOp::LogOr }[self.op]
RBA::CompoundRegionOperationNode::new_logical_boolean(log_op, false, self.children.collect { |c| c.create_node })
end
end
@ -394,17 +366,24 @@ class DRCOpNodeBool < DRCOpNode
end
def create_node
bool_op = { :& => RBA::CompoundOperationNode::And,
:+ => RBA::CompoundOperationNode::Or,
:| => RBA::CompoundOperationNode::Or,
:- => RBA::CompoundOperationNode::Not,
:^ => RBA::CompoundOperationNode::Xor }[self.op]
RBA::CompoundOperationNode::new_logical_boolean(bool_op, false, self.children.collect { |c| c.create_node })
bool_op = { :& => RBA::CompoundRegionOperationNode::GeometricalOp::And,
:+ => RBA::CompoundRegionOperationNode::GeometricalOp::Or,
:| => RBA::CompoundRegionOperationNode::GeometricalOp::Or,
:- => RBA::CompoundRegionOperationNode::GeometricalOp::Not,
:^ => RBA::CompoundRegionOperationNode::GeometricalOp::Xor }[self.op]
nodes = self.children.collect do |c|
n = c.create_node
if n.result_type == RBA::CompoundRegionOperationNode::ResultType::EdgePairs
n = RBA::CompoundRegionOperationNode::new_edge_pair_to_first_edges(n)
end
n
end
RBA::CompoundRegionOperationNode::new_geometrical_boolean(bool_op, *nodes)
end
end
class DRCOpCase < DRCOpNode
class DRCOpNodeCase < DRCOpNode
attr_accessor :children
@ -419,7 +398,7 @@ class DRCOpCase < DRCOpNode
end
def create_node
RBA::CompoundOperationNode::new_case(self.children.collect { |c| c.create_node })
RBA::CompoundRegionOperationNode::new_case(self.children.collect { |c| c.create_node })
end
end
@ -567,7 +546,7 @@ class DRCOpNodeAreaFilter < DRCOpNodeWithCompare
attr_accessor :inverted
def initialize(engine, input)
self.super(engine)
super(engine)
self.input = input
self.inverted = false
self.description = "area"
@ -600,7 +579,7 @@ class DRCOpNodeEdgeLengthFilter < DRCOpNodeWithCompare
attr_accessor :inverted
def initialize(engine, input)
self.super(engine)
super(engine)
self.input = input
self.inverted = false
self.description = "length"
@ -633,7 +612,7 @@ class DRCOpNodeEdgeOrientationFilter < DRCOpNodeWithCompare
attr_accessor :inverted
def initialize(engine, input)
self.super(engine)
super(engine)
self.input = input
self.inverted = false
self.description = "angle"
@ -665,7 +644,7 @@ class DRCOpNodePerimeterFilter < DRCOpNodeWithCompare
attr_accessor :inverted
def initialize(engine, input)
self.super(engine)
super(engine)
self.input = input
self.inverted = false
self.description = "perimeter"
@ -699,7 +678,7 @@ class DRCOpNodeInteractingWithCount < DRCOpNodeWithCompare
attr_accessor :op
def initialize(engine, a, b, op)
self.super(engine)
super(engine)
self.a = a
self.b = b
self.op = op
@ -734,7 +713,7 @@ class DRCOpNodeInteracting < DRCOpNode
attr_accessor :op
def initialize(engine, a, b, op)
self.super(engine)
super(engine)
self.a = a
self.b = b
self.op = op
@ -763,7 +742,7 @@ class DRCOpNodeFilter < DRCOpNode
attr_accessor :args
def initialize(engine, input, factory, description, args = [])
self.super(engine)
super(engine)
self.input = input
self.factory = factory
self.args = args
@ -817,35 +796,28 @@ class DRCOpNodeCheck < DRCOpNodeWithCompare
:isolated => :new_isolated_check, :overlap => :new_overlap_check,
:enclosing => :new_inside_check }[self.check]
res = nil
if self.lt || self.le
dmin = self.le ? self._make_value(self.le, :le) + 1 : self._make_value(self.lt, :lt)
res = RBA::CompoundRegionOperationNode::send(factory, dmin, *self.args)
else
res = nil
end
if self.gt || self.ge
dmax = self.ge ? self._make_value(self.ge, :ge) : self._make_value(self.gt, :gt) + 1
inv = RBA::CompoundRegionOperationNode::send(factory, dmax, *self.args)
# TODO: instead of doing the NOT we could make use of inverse output of the checks
# (needs GSI enabling first)
if self.check == :width || self.check == :notch
# Same polygon check - we need to take both edges of the result
to_subtract = RBA::CompoundRegionOperationNode::new_edges(inv)
else
to_subtract = RBA::CompoundRegionOperationNode::new_edge_pair_to_first_edges(inv)
end
max_check = RBA::CompoundRegionOperationNode::send(factory, dmax, *self.args + [ true ])
res_max = RBA::CompoundRegionOperationNode::new_edge_pair_to_first_edges(max_check)
if res
if self.check == :width || self.check == :notch
# Same polygon check - we need to take both edges of the result
subtract_from = RBA::CompoundRegionOperationNode::new_edges(res)
and_with = RBA::CompoundRegionOperationNode::new_edges(res)
else
subtract_from = RBA::CompoundRegionOperationNode::new_edge_pair_to_first_edges(res)
and_with = RBA::CompoundRegionOperationNode::new_edge_pair_to_first_edges(res)
end
res = RBA::CompoundRegionOperationNode::new_geometrical_boolean(RBA::CompoundRegionOperationNode::GeometricalOp::And, and_with, res_max)
else
subtract_from = RBA::CompoundRegionOperationNode::new_edges(RBA::CompoundRegionOperationNode::new_primary)
res = res_max
end
res = RBA::CompoundRegionOperationNode::new_geometrical_boolean(RBA::CompoundRegionOperationNode::GeometricalOp::Not, subtract_from, to_subtract)
end
return res
@ -861,7 +833,7 @@ class DRCOpNodeBBoxParameterFilter < DRCOpNodeWithCompare
attr_accessor :inverted
def initialize(engine, parameter, input, description)
self.super(engine)
super(engine)
self.parameter = parameter
self.input = input
self.inverted = false
@ -892,7 +864,7 @@ class DRCOpNodeCornersFilter < DRCOpNodeWithCompare
attr_accessor :inverted
def initialize(engine, as_dots, input)
self.super(engine)
super(engine)
self.as_dots = as_dots
self.input = input
self.description = "corners"
@ -919,7 +891,7 @@ class DRCOpNodeRelativeExtents < DRCOpNode
attr_accessor :as_edges, :fx1, :fx2, :fy1, :fy2, :dx, :dy
def initialize(engine, input, as_edges, fx1, fx2, fy1, fy2, dx = 0, dy = 0)
self.super(engine)
super(engine)
self.input = input
self.as_edges = as_edges
self.description = "extents"
@ -953,9 +925,7 @@ class DRCEngine
end
anum += 1
end
res = DRCOpNodeCase::new(self)
res.children = args
return res
DRCOpNodeCase::new(self, args)
end
def secondary(layer)
@ -971,7 +941,22 @@ class DRCEngine
return res
end
%w(area perimeter bbox_min bbox_max bbox_width bbox_height rectangles rectilinear edges odd_polygons hulls holes).each do |f|
%w(land lor).each do |f|
eval <<"CODE"
def #{f}(*args)
args.each_with_index do |a,ia|
if ! a.is_a?(DRCOpNode)
raise("Argument #" + (ia + 1).to_s + " to #{f} must be a DRC expression")
end
end
res = DRCOpNodeLogicalBool::new(self, :#{f})
res.children = args
res
end
CODE
end
%w(area perimeter bbox_min bbox_max bbox_width bbox_height rectangle rectilinear edges odd_polygon hull holes).each do |f|
eval <<"CODE"
def #{f}
primary.#{f}
@ -1048,8 +1033,8 @@ CODE
elsif a.is_a?(DRCOpNode)
other = a
elsif a.is_a?(DRCProjectionLimits)
minp = self._make_value(a.min, :pmin)
maxp = self._make_value(a.max, :pmax)
minp = self._prep_value(a.min)
maxp = self._prep_value(a.max)
elsif a.is_a?(DRCShielded)
shielded = a.value
else