def AddArcOrLines(check_for_arc, new_vertices, might_be_an_arc, arc, arc_found, arc_added): if check_for_arc and CheckForArc(new_vertices[-1], might_be_an_arc, arc): arc_found = True else: if arc_found: if arc.AlmostALine(): new_vertices.append(geom.Vertex(arc.e, arc.user_data)) else: new_vertices.append( geom.Vertex(1 if arc.dir else -1, arc.e, arc.c, arc.user_data)) arc_added = True arc_found = False back_vt = might_be_an_arc[-1] might_be_an_arc = [] if check_for_arc: might_be_an_arc.append(copy.deepcopy(back_vt)) else: back_vt = might_be_an_arc[-1] if check_for_arc: might_be_an_arc.pop_back() first = True for v in might_be_an_arc: if first == False or len( new_vertices) == 0 or new_vertices[-1].p != v.p: new_vertices.append(copy.deepcopy(v)) might_be_an_arc = [] if check_for_arc: might_be_an_arc.append(copy.deepcopy(back_vt))
def zigzag(a, stepover, zig_unidirectional): if a.NumCurves() == 0: return global rightward_for_zigs global curve_list_for_zigs global sin_angle_for_zigs global cos_angle_for_zigs global sin_minus_angle_for_zigs global cos_minus_angle_for_zigs global one_over_units one_over_units = 1 / geom.get_units() a = rotated_area(a) b = a.GetBox() x0 = b.MinX() - 1.0 x1 = b.MaxX() + 1.0 height = b.MaxY() - b.MinY() num_steps = int(height / stepover + 1) y = b.MinY() + 0.1 * one_over_units null_point = geom.Point(0, 0) rightward_for_zigs = True curve_list_for_zigs = [] for i in range(0, num_steps): y0 = y y = y + stepover p0 = geom.Point(x0, y0) p1 = geom.Point(x0, y) p2 = geom.Point(x1, y) p3 = geom.Point(x1, y0) c = geom.Curve() c.Append(geom.Vertex(0, p0, null_point, 0)) c.Append(geom.Vertex(0, p1, null_point, 0)) c.Append(geom.Vertex(0, p2, null_point, 1)) c.Append(geom.Vertex(0, p3, null_point, 0)) c.Append(geom.Vertex(0, p0, null_point, 1)) a2 = geom.Area() a2.Append(c) a2.Intersect(a) make_zig(a2, y0, y, zig_unidirectional) if zig_unidirectional == False: rightward_for_zigs = (rightward_for_zigs == False) reorder_zigs()
def Append(self, v): if isinstance(v, geom.Point): self.vertices.append(geom.Vertex(v)) elif isinstance(v, geom.Vertex): self.vertices.append(v) else: raise ValueError("Vertex argument expected")
def add_roll_off(curve, roll_off_curve, direction, roll_radius, offset_extra, roll_off): if direction == "on": return if roll_off == None: return if curve.NumVertices() <= 1: return last_span = curve.GetLastSpan() if roll_off == 'auto': if roll_radius < 0.0000000001: return v = last_span.GetVector(1.0) # get end direction if direction == 'right': off_v = geom.Point(v.y, -v.x) else: off_v = geom.Point(-v.y, v.x) rollend = last_span.v.p + off_v * roll_radius; else: rollend = roll_off # add the end of the original kurve roll_off_curve.Append(last_span.v.p) if rollend == last_span.v.p: return rvertex = geom.Vertex(rollend) v = last_span.GetVector(1.0) # get end direction rvertex.c, rvertex.type = geom.TangentialArc(last_span.v.p, rollend, v) # add the roll off arc roll_off_curve.Append(rvertex)
def add_roll_on(curve, roll_on_curve, direction, roll_radius, offset_extra, roll_on): if direction == "on": roll_on = None if curve.NumVertices() <= 1: return first_span = curve.GetFirstSpan() if roll_on == None: rollstart = first_span.p elif roll_on == 'auto': if roll_radius < 0.0000000001: rollstart = first_span.p v = first_span.GetVector(0.0) if direction == 'right': off_v = geom.Point(v.y, -v.x) else: off_v = geom.Point(-v.y, v.x) rollstart = first_span.p + off_v * roll_radius else: rollstart = roll_on rvertex = geom.Vertex(first_span.p) if first_span.p == rollstart: rvertex.type = 0 else: v = first_span.GetVector(0.0) # get start direction rvertex.c, rvertex.type = geom.TangentialArc(first_span.p, rollstart, -v) rvertex.type = -rvertex.type # because TangentialArc was used in reverse # add a start roll on point roll_on_curve.Append(rollstart) # add the roll on arc roll_on_curve.Append(rvertex)
def make_obround(p0, p1, radius): dir = p1 - p0 d = dir.Length() dir.Normalize() right = geom.Point(dir.y, -dir.x) obround = geom.Area() c = geom.Curve() vt0 = p0 + right * radius vt1 = p1 + right * radius vt2 = p1 - right * radius vt3 = p0 - right * radius c.Append(geom.Vertex(0, vt0, geom.Point(0, 0))) c.Append(geom.Vertex(0, vt1, geom.Point(0, 0))) c.Append(geom.Vertex(1, vt2, p1)) c.Append(geom.Vertex(0, vt3, geom.Point(0, 0))) c.Append(geom.Vertex(1, vt0, p0)) obround.Append(c) return obround
def __init__(self, p, v, start_span=False): """ create a Span from a point and a vertex """ if isinstance(p, geom.Point) == False: raise ValueError("Point argument expected") self.p = copy.deepcopy(p) if isinstance(v, geom.Point): self.v = geom.Vertex(p) elif isinstance(v, geom.Vertex): self.v = copy.deepcopy(v) else: raise ValueError("Vertex argument expected") self.start_span = start_span
def calculate_span_cylinders(self, span, color): sz = span.p.y * toolpath.coords.voxels_per_mm ez = span.v.p.y * toolpath.coords.voxels_per_mm z = sz while z < ez: # make a line at this z intersection_line = area.Span( area.Point(0, z), area.Vertex(0, area.Point(300, z), area.Point(0, 0)), False) intersections = span.Intersect(intersection_line) if len(intersections): radius = intersections[0].x * toolpath.coords.voxels_per_mm self.cylinders.append( VoxelCyl(radius, z * toolpath.coords.voxels_per_mm, color)) z += 1 / toolpath.coords.voxels_per_mm
def PointToPerim(self, p): best_dist = None prev_p = None perim = 0.0 first_span = True for vertex in self.vertices: if prev_p: span = Span(prev_p, vertex, first_span) near_point = span.NearestPointToPoint(p) first_span = False dist = near_point.Dist(p) if (best_dist == None or dist < best_dist): best_dist = dist span_to_point( prev_p, geom.Vertex(span.v.type, near_point, span.v.c)) perim_at_best_dist = perim + span_to_point.Length() perim += span.Length() prev_p = vertex.p if best_dist == None: return None return perim_at_best_dist
def unrotated_vertex(v): if v.type: return geom.Vertex(v.type, unrotated_point(v.p), unrotated_point(v.c)) return geom.Vertex(v.type, unrotated_point(v.p), geom.Point(0, 0))
def make_zig_curve(curve, y0, y, zig_unidirectional): if rightward_for_zigs: curve.Reverse() # find a high point to start looking from high_point = None for vertex in curve.GetVertices(): if high_point == None: high_point = vertex.p elif vertex.p.y > high_point.y: # use this as the new high point high_point = vertex.p elif math.fabs(vertex.p.y - high_point.y) < 0.002 * one_over_units: # equal high point if rightward_for_zigs: # use the furthest left point if vertex.p.x < high_point.x: high_point = vertex.p else: # use the furthest right point if vertex.p.x > high_point.x: high_point = vertex.p zig = geom.Curve() high_point_found = False zig_started = False zag_found = False for i in range( 0, 2 ): # process the curve twice because we don't know where it will start prev_p = None for vertex in curve.GetVertices(): if zag_found: break if prev_p != None: if zig_started: zig.Append(unrotated_vertex(vertex)) if math.fabs(vertex.p.y - y) < 0.002 * one_over_units: zag_found = True break elif high_point_found: if math.fabs(vertex.p.y - y0) < 0.002 * one_over_units: if zig_started: zig.Append(unrotated_vertex(vertex)) elif math.fabs( prev_p.y - y0 ) < 0.002 * one_over_units and vertex.type == 0: zig.Append( geom.Vertex(0, unrotated_point(prev_p), geom.Point(0, 0))) zig.Append(unrotated_vertex(vertex)) zig_started = True elif vertex.p.x == high_point.x and vertex.p.y == high_point.y: high_point_found = True prev_p = vertex.p if zig_started: if zig_unidirectional == True: # remove the last bit of zig if math.fabs(zig.LastVertex().p.y - y) < 0.002 * one_over_units: vertices = zig.GetVertices() while len(vertices) > 0: v = vertices[len(vertices) - 1] if math.fabs(v.p.y - y0) < 0.002 * one_over_units: break else: vertices.pop() zig = geom.Curve() for v in vertices: zig.Append(v) curve_list_for_zigs.append(zig)
def _EliminateLoops(self, leftwards_value): new_vertices = [] kinVertex = 0 spans = self.GetSpans() sp0 = geom.Span(geom.Point(0, 0), geom.Point(0, 0)) sp1 = geom.Span(geom.Point(0, 0), geom.Point(0, 0)) while (kinVertex < len(self.vertices)): clipped = False sp0.p = self.vertices[kinVertex].p kinVertex += 1 if kinVertex == 1: new_vertices.append( geom.Vertex(sp0.p) ) # start point mustn't dissappear for this simple method if kinVertex < len(self.vertices): ksaveVertex = kinVertex sp0.v = self.vertices[kinVertex] kinVertex += 1 ksaveVertex1 = kinVertex if kinVertex < len(self.vertices): sp1.p = self.vertices[kinVertex].p kinVertex += 1 ksaveVertex2 = kinVertex fwdCount = 0 while (kinVertex < len(self.vertices)): sp1.v = self.vertices[kinVertex] kinVertex += 1 intersections = sp0.Intersect(sp1) if (len(intersections) > 0) and (sp0.p.Dist( intersections[0]) < geom.tolerance): intersections = [] if len(intersections) > 0: if len(intersections) == 2: # choose first intercept on sp0 intersections.pop() ksaveVertex = ksaveVertex1 clipped = True # in a clipped section if self._DoesIntersInterfere( intersection[0], self, leftwards_value): sp0.v.p = intersections[ 0] # ok so truncate this span to the intersection clipped = False # end of clipped section break # no valid intersection found so carry on sp1.p = sp1.v.p # next ksaveVertex1 = ksaveVertex2 ksaveVertex2 = kinVertex fwdCount += 1 if ((kinVertex > len(self.vertices) + 1) or fwdCount > 25) and clipped == False: break if clipped: # still in a clipped section - error return False print('adding ' + str(sp0.v)) new_vertices.append(sp0.v) kinVertex = ksaveVertex # no more spans - seems ok self.vertices = new_vertices return True
def _Offset(self, leftwards_value): """ offset the curve using Geoff's method """ if (math.fabs(leftwards_value) < geom.tolerance) or len( self.vertices) < 2: return True RollDir = l if leftwards_value < 0 else -1 kOffset = Curve() kOffset_started = False spans = self.GetSpans() bClosed = self.IsClosed() nspans = len(spans) if bClosed: curSpan = spans[-1] prevSpanOff = copy.copy(curSpan) prevSpanOff.Offset(leftwards_value) nspans += 1 for spannumber in range(0, nspans): if spannumber == nspans: curSpan = spans[0] # closed curve - read first span again else: curSpan = spans[spannumber] if curSpan.IsNullSpan() == False: intersections = [] curSpanOff = copy.copy(curSpan) curSpanOff.Offset(leftwards_value) if kOffset_started == False: kOffset.Append(geom.Vertex(curSpanOff.p)) kOffset_started = True if spannumber > 0: # see if tangent d = curSpanOff.p.Dist(prevSpanOff.v.p) if (d > geom.tolerance) and ( curSpanOff.IsNullSpan() == False) and (prevSpanOff.IsNullSpan() == False): # see if offset spans intersect cp = prevSpanOff.GetVector(1.0) ^ curSpanOff.GetVector( 0.0) inters = (cp > 0.0 and leftwards_value > 0) or ( cp < 0.0 and leftwards_value < 0) if inters: intersections = prevSpanOff.Intersect(curSpanOff) if len(intersections) == 1: # intersection - modify previous endpoint kOffset.vertices[-1].p = intersections[0] else: # 0 or 2 intersections, add roll around (remove -ve loops in elimination function) kOffset.vertices.append( geom.Vertex(RollDir, curSpanOff.p, curSpan.p)) if spannumber < len(spans): if kOffset_started == False: kOffset.vertices.append(geom.Vertex(curSpanOff.p)) kOffset_started = True kOffset.vertices.append(curSpanOff.v) elif len(intersections) == 1: kOffset.vertices[0].p = intersections[0] if curSpanOff.IsNullSpan() == False: prevSpanOff = curSpanOff if kOffset._EliminateLoops(leftwards_value) == True and bClosed: # check for inverted offsets of closed kurves if kOffset.IsClosed(): a = self.GetArea() dir = a < 0 ao = kOffset.GetArea() dirOffset = ao < 0 if dir != dirOffset: return False else: # check area change compatible with offset direction - catastrophic failure bigger = (a > 0 and leftward_value > 0) or ( a < 0 and leftward_value < 0) if bigger and math.fabs(ao) < math.fabs(a): return False else: return False # started closed but now open?? self.vertices = kOffset.vertices return True