From 7b2adc25c86b05b5512d9b1c34458dd833b5374e Mon Sep 17 00:00:00 2001 From: Andrei Date: Sun, 21 Feb 2021 18:56:09 +0200 Subject: [PATCH] fix render gerber for outlines --- bin/render_gerber.py | 46 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 9 deletions(-) diff --git a/bin/render_gerber.py b/bin/render_gerber.py index 200a558..8e483e4 100644 --- a/bin/render_gerber.py +++ b/bin/render_gerber.py @@ -42,6 +42,11 @@ class HellenGerberCairoContext(GerberCairoContext): verbose=verbose) self.dump(filename, verbose) + def addPoint(self, start, end, additional): + start = (start[0] + self.origin_in_pixels[0], start[1] + self.origin_in_pixels[1]) + end = (end[0] + self.origin_in_pixels[0], end[1] + self.origin_in_pixels[1]) + self.lineList.append([start, end, additional]) + # this override is needed to gather all line segments from the outline layers def _render_line(self, line, color): if self.isOutline == False or self._render_count != 1: # outline layer @@ -49,24 +54,34 @@ class HellenGerberCairoContext(GerberCairoContext): return start = self.scale_point(line.start) end = self.scale_point(line.end) - start = (start[0] + self.origin_in_pixels[0], start[1] + self.origin_in_pixels[1]) - end = (end[0] + self.origin_in_pixels[0], end[1] + self.origin_in_pixels[1]) # we don't draw lines, we store the line segments with self._clip_primitive(line): - self.lineList.append([start, end]) + self.addPoint(start, end, None) - # thi override is needed to render the actual outline layers in a form of closed filled polygon + # this override is needed to gather all arcs from the outline layers + def _render_arc(self, arc, color): + if self.isOutline == False or self._render_count != 1: # outline layer + GerberCairoContext._render_arc(self, arc, color) + return + start = self.scale_point(arc.start) + end = self.scale_point(arc.end) + # we don't draw arcs, we store them + with self._clip_primitive(arc): + self.addPoint(start, end, arc) + + # this override is needed to render the actual outline layers in a form of closed filled polygon def flatten(self, color=None, alpha=None): if self.isOutline == True and self._render_count == 1: # outline layer # reconstruct the contour (the original lines go in no particular order) curPoint = self.lineList[0] countourPoints = [] for i in range(1000): - countourPoints.append(curPoint[0]) + countourPoints.append([curPoint[0][0], curPoint[0][1], curPoint[2]]) dist = sys.float_info.max # find the closest point among the for ll in self.lineList: - if ll == curPoint: + llinv = [ll[1], ll[0], ll[2]] + if ll == curPoint or llinv == curPoint: continue d = (ll[0][0] - curPoint[1][0])**2 + (ll[0][1] - curPoint[1][1])**2 if d < dist: @@ -75,7 +90,7 @@ class HellenGerberCairoContext(GerberCairoContext): d = (ll[1][0] - curPoint[1][0])**2 + (ll[1][1] - curPoint[1][1])**2 if d < dist: dist = d - nextCurPoint = [ll[1], ll[0]] + nextCurPoint = llinv if dist < 1.e-4: break if nextCurPoint[0] in countourPoints: @@ -84,9 +99,22 @@ class HellenGerberCairoContext(GerberCairoContext): # draw the filled contour with self._new_mask() as mask: - mask.ctx.move_to(*countourPoints[0]) + mask.ctx.move_to(countourPoints[0][0], countourPoints[0][1]) + wasArc = False for ll in countourPoints: - mask.ctx.line_to(*ll) + if ll[2]: + arc = ll[2] + center = self.scale_point(arc.center) + radius = self.scale[0] * arc.radius + two_pi = 2 * math.pi + angle1 = (arc.start_angle + two_pi) % two_pi + angle2 = (arc.end_angle + two_pi) % two_pi + if arc.direction == 'counterclockwise': + mask.ctx.arc(center[0], center[1], radius, angle1, angle2) + else: + mask.ctx.arc_negative(center[0], center[1], radius, angle1, angle2) + else: + mask.ctx.line_to(ll[0], ll[1]) mask.ctx.set_source_rgba(1.0, 1.0, 1.0, 1.0) mask.ctx.fill() self.ctx.mask_surface(mask.surface, 0.0, 0.0)