Dressup to add dragknife corner actions to a path
Dragknives have an offset so paths must be extended to complete the cut. They also require special handling if the incident angle between two segments is small. This dressup provides properties for the filter angle, offset distance, and pivot height. One known area still needs to be addressed: If the segment being processed is shorter than the offset distance, the extension may be added incorrectly. Additional corner strategies could also be added in the future to enhance drag knife performance. Some of the files also got a pep8 cleanup. PathKurveUtils: logic around line #460 to always pass Z value. Previously, the Z was only passed if it changed. This caused some downstream problems for dressup functions. Changes to Dressup so it works with parent objects correctly.
This commit is contained in:
committed by
Yorik van Havre
parent
19306c6d1c
commit
f6654c8a6d
@@ -1,81 +1,92 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#***************************************************************************
|
||||
#* *
|
||||
#* Copyright (c) 2015 Dan Falck <ddfalck@gmail.com> *
|
||||
#* *
|
||||
#* This program is free software; you can redistribute it and/or modify *
|
||||
#* it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
#* as published by the Free Software Foundation; either version 2 of *
|
||||
#* the License, or (at your option) any later version. *
|
||||
#* for detail see the LICENCE text file. *
|
||||
#* *
|
||||
#* This program is distributed in the hope that it will be useful, *
|
||||
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
#* GNU Library General Public License for more details. *
|
||||
#* *
|
||||
#* You should have received a copy of the GNU Library General Public *
|
||||
#* License along with this program; if not, write to the Free Software *
|
||||
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
#* USA *
|
||||
#* *
|
||||
#***************************************************************************
|
||||
# ***************************************************************************
|
||||
# * *
|
||||
# * Copyright (c) 2015 Dan Falck <ddfalck@gmail.com> *
|
||||
# * *
|
||||
# * This program is free software; you can redistribute it and/or modify *
|
||||
# * it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
# * as published by the Free Software Foundation; either version 2 of *
|
||||
# * the License, or (at your option) any later version. *
|
||||
# * for detail see the LICENCE text file. *
|
||||
# * *
|
||||
# * This program is distributed in the hope that it will be useful, *
|
||||
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
# * GNU Library General Public License for more details. *
|
||||
# * *
|
||||
# * You should have received a copy of the GNU Library General Public *
|
||||
# * License along with this program; if not, write to the Free Software *
|
||||
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
# * USA *
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
'''PathKurveUtils - functions needed for using libarea (created by Dan Heeks) for making simple CNC profile paths '''
|
||||
import FreeCAD
|
||||
from FreeCAD import Vector
|
||||
import FreeCADGui as Gui
|
||||
import Part
|
||||
import DraftGeomUtils,DraftVecUtils
|
||||
import DraftGeomUtils
|
||||
import DraftVecUtils
|
||||
from DraftGeomUtils import geomType
|
||||
import math
|
||||
import area
|
||||
import Path
|
||||
from PathScripts import PathUtils
|
||||
# import PathSelection
|
||||
from nc.nc import *
|
||||
import PathScripts.nc.iso
|
||||
|
||||
from PathScripts.nc.nc import *
|
||||
|
||||
def makeAreaVertex(seg):
|
||||
if seg.ShapeType =='Edge':
|
||||
if isinstance(seg.Curve,Part.Circle):
|
||||
segtype = int(seg.Curve.Axis.z) #1=ccw arc,-1=cw arc
|
||||
vertex = area.Vertex(segtype, area.Point(seg.valueAt(seg.LastParameter)[0],seg.valueAt(seg.LastParameter)[1]), area.Point(seg.Curve.Center.x, seg.Curve.Center.y))
|
||||
elif isinstance(seg.Curve,Part.Line):
|
||||
point1 = seg.valueAt(seg.FirstParameter)[0],seg.valueAt(seg.FirstParameter)[1]
|
||||
point2 = seg.valueAt(seg.LastParameter)[0],seg.valueAt(seg.LastParameter)[1]
|
||||
segtype = 0 #0=line
|
||||
vertex = area.Point(seg.valueAt(seg.LastParameter)[0],seg.valueAt(seg.LastParameter)[1])
|
||||
if seg.ShapeType == 'Edge':
|
||||
if isinstance(seg.Curve, Part.Circle):
|
||||
segtype = int(seg.Curve.Axis.z) # 1=ccw arc,-1=cw arc
|
||||
vertex = area.Vertex(segtype, area.Point(seg.valueAt(seg.LastParameter)[0], seg.valueAt(
|
||||
seg.LastParameter)[1]), area.Point(seg.Curve.Center.x, seg.Curve.Center.y))
|
||||
elif isinstance(seg.Curve, Part.Line):
|
||||
point1 = seg.valueAt(seg.FirstParameter)[
|
||||
0], seg.valueAt(seg.FirstParameter)[1]
|
||||
point2 = seg.valueAt(seg.LastParameter)[
|
||||
0], seg.valueAt(seg.LastParameter)[1]
|
||||
segtype = 0 # 0=line
|
||||
vertex = area.Point(seg.valueAt(seg.LastParameter)[
|
||||
0], seg.valueAt(seg.LastParameter)[1])
|
||||
else:
|
||||
pass
|
||||
#print "returning vertex: area.Point(" + str(seg.valueAt(seg.LastParameter)[0]) +"," + str(seg.valueAt(seg.LastParameter)[1]) +")"
|
||||
# print "returning vertex: area.Point(" +
|
||||
# str(seg.valueAt(seg.LastParameter)[0]) +"," +
|
||||
# str(seg.valueAt(seg.LastParameter)[1]) +")"
|
||||
return vertex
|
||||
|
||||
def makeAreaCurve(edges,direction,startpt=None,endpt=None):
|
||||
|
||||
def makeAreaCurve(edges, direction, startpt=None, endpt=None):
|
||||
curveobj = area.Curve()
|
||||
|
||||
cleanededges = Part.__sortEdges__(PathUtils.cleanedges(edges, 0.01))
|
||||
|
||||
#for e in cleanededges:
|
||||
#print str(e.valueAt(e.FirstParameter)) + "," + str(e.valueAt(e.LastParameter))
|
||||
edgelist=[]
|
||||
|
||||
if len(cleanededges) == 1: #user selected a single edge.
|
||||
edgelist = cleanededges
|
||||
else:
|
||||
#edgelist = [] #Multiple edges. Need to sequence the vetexes.
|
||||
#First get the first segment oriented correctly.
|
||||
|
||||
#We first compare the last parameter of the first segment to see if it matches either end of the second segment. If not, it must need flipping.
|
||||
# for e in cleanededges:
|
||||
# print str(e.valueAt(e.FirstParameter)) + "," +
|
||||
# str(e.valueAt(e.LastParameter))
|
||||
edgelist = []
|
||||
|
||||
if len(cleanededges) == 1: # user selected a single edge.
|
||||
edgelist = cleanededges
|
||||
else:
|
||||
# edgelist = [] #Multiple edges. Need to sequence the vetexes.
|
||||
# First get the first segment oriented correctly.
|
||||
|
||||
# We first compare the last parameter of the first segment to see if it
|
||||
# matches either end of the second segment. If not, it must need
|
||||
# flipping.
|
||||
if cleanededges[0].valueAt(cleanededges[0].LastParameter) in [cleanededges[1].valueAt(cleanededges[1].FirstParameter), cleanededges[1].valueAt(cleanededges[1].LastParameter)]:
|
||||
edge0 = cleanededges[0]
|
||||
edge0 = cleanededges[0]
|
||||
else:
|
||||
edge0 = PathUtils.reverseEdge(cleanededges[0])
|
||||
|
||||
|
||||
edgelist.append(edge0)
|
||||
|
||||
#Now iterate the rest of the edges matching the last parameter of the previous segment.
|
||||
# Now iterate the rest of the edges matching the last parameter of the
|
||||
# previous segment.
|
||||
for edge in cleanededges[1:]:
|
||||
|
||||
if edge.valueAt(edge.FirstParameter) == edgelist[-1].valueAt(edgelist[-1].LastParameter):
|
||||
@@ -83,8 +94,11 @@ def makeAreaCurve(edges,direction,startpt=None,endpt=None):
|
||||
else:
|
||||
nextedge = PathUtils.reverseEdge(edge)
|
||||
edgelist.append(nextedge)
|
||||
#print "makeareacurve 87: " + "area.Point(" + str(edgelist[0].Vertexes[0].X) + ", " + str(edgelist[0].Vertexes[0].Y)+")"
|
||||
curveobj.append(area.Point(edgelist[0].Vertexes[0].X,edgelist[0].Vertexes[0].Y))
|
||||
# print "makeareacurve 87: " + "area.Point(" +
|
||||
# str(edgelist[0].Vertexes[0].X) + ", " +
|
||||
# str(edgelist[0].Vertexes[0].Y)+")"
|
||||
curveobj.append(area.Point(edgelist[0].Vertexes[
|
||||
0].X, edgelist[0].Vertexes[0].Y))
|
||||
# seglist =[]
|
||||
# if direction=='CW':
|
||||
# edgelist.reverse()
|
||||
@@ -92,30 +106,30 @@ def makeAreaCurve(edges,direction,startpt=None,endpt=None):
|
||||
# seglist.append(PathUtils.reverseEdge(e)) #swap end points on every segment
|
||||
# else:
|
||||
# for e in edgelist:
|
||||
# seglist.append(e)
|
||||
# seglist.append(e)
|
||||
|
||||
for s in edgelist:
|
||||
curveobj.append(makeAreaVertex(s))
|
||||
|
||||
if startpt:
|
||||
# future nearest point code yet to be worked out -fixme
|
||||
# v1 = Vector(startpt.X,startpt.Y,startpt.Z)
|
||||
# perppoint1 = DraftGeomUtils.findPerpendicular(v1,firstedge)
|
||||
# perppoint1 = DraftGeomUtils.findDistance(v1,firstedge)
|
||||
# if perppoint1:
|
||||
# curveobj.ChangeStart(area.Point(perppoint1[0].x,perppoint1[0].y))
|
||||
# else:
|
||||
# curveobj.ChangeStart(area.Point(startpt.X,startpt.Y))
|
||||
curveobj.ChangeStart(area.Point(startpt.x,startpt.y))
|
||||
# v1 = Vector(startpt.X,startpt.Y,startpt.Z)
|
||||
# perppoint1 = DraftGeomUtils.findPerpendicular(v1,firstedge)
|
||||
# perppoint1 = DraftGeomUtils.findDistance(v1,firstedge)
|
||||
# if perppoint1:
|
||||
# curveobj.ChangeStart(area.Point(perppoint1[0].x,perppoint1[0].y))
|
||||
# else:
|
||||
# curveobj.ChangeStart(area.Point(startpt.X,startpt.Y))
|
||||
curveobj.ChangeStart(area.Point(startpt.x, startpt.y))
|
||||
if endpt:
|
||||
# future nearest point code yet to be worked out -fixme
|
||||
# v2 = Vector(endpt.X,endpt.Y,endpt.Z)
|
||||
# perppoint2 = DraftGeomUtils.findPerpendicular(v2,lastedge)
|
||||
# if perppoint2:
|
||||
# curveobj.ChangeEnd(area.Point(perppoint2[0].x,perppoint2[0].y))
|
||||
# else:
|
||||
# curveobj.ChangeEnd(area.Point(endpt.X,endpt.Y))
|
||||
curveobj.ChangeEnd(area.Point(endpt.x,endpt.y))
|
||||
# v2 = Vector(endpt.X,endpt.Y,endpt.Z)
|
||||
# perppoint2 = DraftGeomUtils.findPerpendicular(v2,lastedge)
|
||||
# if perppoint2:
|
||||
# curveobj.ChangeEnd(area.Point(perppoint2[0].x,perppoint2[0].y))
|
||||
# else:
|
||||
# curveobj.ChangeEnd(area.Point(endpt.X,endpt.Y))
|
||||
curveobj.ChangeEnd(area.Point(endpt.x, endpt.y))
|
||||
|
||||
if curveobj.IsClockwise() and direction == 'CCW':
|
||||
curveobj.Reverse()
|
||||
@@ -126,23 +140,24 @@ def makeAreaCurve(edges,direction,startpt=None,endpt=None):
|
||||
|
||||
# profile command,
|
||||
# side_of_line should be 'Left' or 'Right' or 'On'
|
||||
def profile(curve,side_of_line,radius=1.0,vertfeed=0.0,horizfeed=0.0,offset_extra=0.0, \
|
||||
rapid_safety_space=None,clearance=None,start_depth=None,stepdown=None, \
|
||||
final_depth=None,use_CRC=False, \
|
||||
roll_on=None,roll_off=None,roll_start=False,roll_end=True,roll_radius=None, \
|
||||
roll_start_pt=None,roll_end_pt=None):
|
||||
def profile(curve, side_of_line, radius=1.0, vertfeed=0.0, horizfeed=0.0, offset_extra=0.0,
|
||||
rapid_safety_space=None, clearance=None, start_depth=None, stepdown=None,
|
||||
final_depth=None, use_CRC=False,
|
||||
roll_on=None, roll_off=None, roll_start=False, roll_end=True, roll_radius=None,
|
||||
roll_start_pt=None, roll_end_pt=None):
|
||||
|
||||
output = ""
|
||||
output += "G0 Z" + str(clearance)+"\n"
|
||||
output += "G0 Z" + str(clearance) + "\n"
|
||||
|
||||
offset_curve = area.Curve(curve)
|
||||
if offset_curve.getNumVertices() <= 1:
|
||||
raise Exception,"Sketch has no elements!"
|
||||
raise Exception, "Sketch has no elements!"
|
||||
if side_of_line == "On":
|
||||
use_CRC =False
|
||||
use_CRC = False
|
||||
|
||||
elif (side_of_line == "Left") or (side_of_line == "Right"):
|
||||
# get tool radius plus little bit of extra offset, if needed to clean up profile a little more
|
||||
# get tool radius plus little bit of extra offset, if needed to clean
|
||||
# up profile a little more
|
||||
offset = radius + offset_extra
|
||||
if side_of_line == 'Left':
|
||||
offset_curve.Offset(offset)
|
||||
@@ -150,12 +165,12 @@ def profile(curve,side_of_line,radius=1.0,vertfeed=0.0,horizfeed=0.0,offset_extr
|
||||
else:
|
||||
offset_curve.Offset(-offset)
|
||||
|
||||
if offset_curve == False:
|
||||
if offset_curve is False:
|
||||
raise Exception, "couldn't offset kurve " + str(offset_curve)
|
||||
else:
|
||||
raise Exception,"Side must be 'Left','Right', or 'On'"
|
||||
raise Exception, "Side must be 'Left','Right', or 'On'"
|
||||
|
||||
#===============================================================================
|
||||
# =========================================================================
|
||||
# #roll_on roll_off section
|
||||
# roll_on_curve = area.Curve()
|
||||
# if offset_curve.getNumVertices() <= 1: return
|
||||
@@ -172,23 +187,23 @@ def profile(curve,side_of_line,radius=1.0,vertfeed=0.0,horizfeed=0.0,offset_extr
|
||||
# off_v = area.Point(-v.y, v.x)
|
||||
# rollstart = first_span.p + off_v * roll_radius
|
||||
# else:
|
||||
# rollstart = roll_on
|
||||
#
|
||||
# rollstart = roll_on
|
||||
#
|
||||
# rvertex = area.Vertex(first_span.p)
|
||||
#
|
||||
#
|
||||
# if first_span.p == rollstart:
|
||||
# rvertex.type = 0
|
||||
# rvertex.type = 0
|
||||
# else:
|
||||
# v = first_span.GetVector(0.0) # get start direction
|
||||
# rvertex.c, rvertex.type = area.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)
|
||||
# roll_on_curve.append(rvertex)
|
||||
# #end of roll_on roll_off section
|
||||
#===============================================================================
|
||||
# =========================================================================
|
||||
|
||||
# do multiple depths
|
||||
layer_count = int((start_depth - final_depth) / stepdown)
|
||||
@@ -196,107 +211,131 @@ def profile(curve,side_of_line,radius=1.0,vertfeed=0.0,horizfeed=0.0,offset_extr
|
||||
layer_count += 1
|
||||
current_start_depth = start_depth
|
||||
prev_depth = start_depth
|
||||
for i in range(1, layer_count+1):
|
||||
for i in range(1, layer_count + 1):
|
||||
if i == layer_count:
|
||||
depth = final_depth
|
||||
else:
|
||||
depth = start_depth - i * stepdown
|
||||
mat_depth = prev_depth
|
||||
start_z = mat_depth
|
||||
#first move
|
||||
output += "G0 X"+str(PathUtils.fmt(offset_curve.GetFirstSpan().p.x))+\
|
||||
" Y"+str(PathUtils.fmt(offset_curve.GetFirstSpan().p.y))+\
|
||||
" Z"+str(PathUtils.fmt(mat_depth + rapid_safety_space))+"\n"
|
||||
# first move
|
||||
output += "G0 X" + str(PathUtils.fmt(offset_curve.GetFirstSpan().p.x)) +\
|
||||
" Y" + str(PathUtils.fmt(offset_curve.GetFirstSpan().p.y)) +\
|
||||
" Z" + str(PathUtils.fmt(mat_depth + rapid_safety_space)) + "\n"
|
||||
# feed down to depth
|
||||
mat_depth = depth
|
||||
if start_z > mat_depth:
|
||||
if start_z > mat_depth:
|
||||
mat_depth = start_z
|
||||
# feed down in Z
|
||||
output += "G1 X"+str(PathUtils.fmt(offset_curve.GetFirstSpan().p.x))+\
|
||||
" Y"+str(PathUtils.fmt(offset_curve.GetFirstSpan().p.y))+" Z"+str(PathUtils.fmt(depth))+\
|
||||
" F"+str(PathUtils.fmt(vertfeed))+"\n"
|
||||
output += "G1 X" + str(PathUtils.fmt(offset_curve.GetFirstSpan().p.x)) +\
|
||||
" Y" + str(PathUtils.fmt(offset_curve.GetFirstSpan().p.y)) + " Z" + str(PathUtils.fmt(depth)) +\
|
||||
" F" + str(PathUtils.fmt(vertfeed)) + "\n"
|
||||
if use_CRC:
|
||||
if side_of_line == 'left':
|
||||
output +="G41"+"\n"
|
||||
output += "G41" + "\n"
|
||||
else:
|
||||
output +="G42"+"\n"
|
||||
output += "G42" + "\n"
|
||||
# cut the main kurve
|
||||
current_perim = 0.0
|
||||
lastx=offset_curve.GetFirstSpan().p.x
|
||||
lasty=offset_curve.GetFirstSpan().p.y
|
||||
lastx = offset_curve.GetFirstSpan().p.x
|
||||
lasty = offset_curve.GetFirstSpan().p.y
|
||||
for span in offset_curve.GetSpans():
|
||||
current_perim += span.Length()
|
||||
if span.v.type == 0:#line
|
||||
#feed(span.v.p.x, span.v.p.y, ez)
|
||||
output +="G1 X"+str(PathUtils.fmt(span.v.p.x))+" Y"+str(PathUtils.fmt(span.v.p.y))+\
|
||||
" Z"+str(PathUtils.fmt(depth))+" F"+str(PathUtils.fmt(horizfeed))+"\n"
|
||||
if span.v.type == 0: # line
|
||||
# feed(span.v.p.x, span.v.p.y, ez)
|
||||
output += "G1 X" + str(PathUtils.fmt(span.v.p.x)) + " Y" + str(PathUtils.fmt(span.v.p.y)) +\
|
||||
" Z" + str(PathUtils.fmt(depth)) + " F" + \
|
||||
str(PathUtils.fmt(horizfeed)) + "\n"
|
||||
lastx = span.v.p.x
|
||||
lasty = span.v.p.y
|
||||
elif (span.v.type == 1) or (span.v.type == -1):
|
||||
if span.v.type == 1:# anti-clockwise arc
|
||||
if span.v.type == 1: # anti-clockwise arc
|
||||
command = 'G3'
|
||||
elif span.v.type == -1:#clockwise arc
|
||||
elif span.v.type == -1: # clockwise arc
|
||||
command = 'G2'
|
||||
arc_I= span.v.c.x-lastx
|
||||
arc_J= span.v.c.y-lasty
|
||||
output +=command +"X"+str(PathUtils.fmt(span.v.p.x))+" Y"+ str(PathUtils.fmt(span.v.p.y))#+" Z"+ str(PathUtils.fmt(depth))
|
||||
output +=" I"+str(PathUtils.fmt(arc_I))+ " J"+str(PathUtils.fmt(arc_J))+" F"+str(PathUtils.fmt(horizfeed))+'\n'#" K"+str(PathUtils.fmt(depth)) +"\n"
|
||||
arc_I = span.v.c.x - lastx
|
||||
arc_J = span.v.c.y - lasty
|
||||
output += command + "X" + str(PathUtils.fmt(span.v.p.x)) + " Y" + str(
|
||||
PathUtils.fmt(span.v.p.y)) # +" Z"+ str(PathUtils.fmt(depth))
|
||||
output += " I" + str(PathUtils.fmt(arc_I)) + " J" + str(PathUtils.fmt(arc_J)) + " F" + str(
|
||||
PathUtils.fmt(horizfeed)) + '\n' # " K"+str(PathUtils.fmt(depth)) +"\n"
|
||||
lastx = span.v.p.x
|
||||
lasty = span.v.p.y
|
||||
else:
|
||||
raise Exception, "valid geometry identifier needed"
|
||||
if use_CRC:
|
||||
#end_CRC()
|
||||
output +="G40"+"\n"
|
||||
# end_CRC()
|
||||
output += "G40" + "\n"
|
||||
# rapid up to the clearance height
|
||||
output +="G0 Z"+str(PathUtils.fmt(clearance))+"\n"
|
||||
output += "G0 Z" + str(PathUtils.fmt(clearance)) + "\n"
|
||||
|
||||
del offset_curve
|
||||
|
||||
return output
|
||||
|
||||
def make_smaller( curve, start = None, finish = None, end_beyond = False ):
|
||||
if start != None:
|
||||
|
||||
def make_smaller(curve, start=None, finish=None, end_beyond=False):
|
||||
if start is not None:
|
||||
curve.ChangeStart(curve.NearestPoint(start))
|
||||
|
||||
if finish != None:
|
||||
if finish is not None:
|
||||
if end_beyond:
|
||||
curve2 = area.Curve(curve)
|
||||
curve2.ChangeEnd(curve2.NearestPoint(finish))
|
||||
first = True
|
||||
for vertex in curve2.getVertices():
|
||||
if first == False: curve.append(vertex)
|
||||
if first is False:
|
||||
curve.append(vertex)
|
||||
first = False
|
||||
else:
|
||||
curve.ChangeEnd(curve.NearestPoint(finish))
|
||||
|
||||
|
||||
'''The following procedures are copied almost directly from heekscnc kurve_funcs.py. They depend on nc directory existing below PathScripts and have not been
|
||||
throughly optimized, understood, or tested for FreeCAD.'''
|
||||
'''The following procedures are copied almost directly from heekscnc
|
||||
kurve_funcs.py. They depend on nc directory existing below PathScripts
|
||||
and have not been throughly optimized, understood, or tested for FreeCAD.'''
|
||||
|
||||
|
||||
def profile2(curve, direction = "on", radius = 1.0, vertfeed=0.0,horizfeed=0.0, offset_extra = 0.0, roll_radius = 2.0, roll_on = None, roll_off = None, depthparams = None, extend_at_start = 0.0, extend_at_end = 0.0, lead_in_line_len=0.0,lead_out_line_len= 0.0):
|
||||
from PathScripts.nc.nc import *
|
||||
def profile2(curve, direction="on", radius=1.0, vertfeed=0.0,
|
||||
horizfeed=0.0, offset_extra=0.0, roll_radius=2.0,
|
||||
roll_on=None, roll_off=None, depthparams=None,
|
||||
extend_at_start=0.0, extend_at_end=0.0, lead_in_line_len=0.0,
|
||||
lead_out_line_len=0.0):
|
||||
|
||||
# print "direction: " + str(direction)
|
||||
# print "radius: " + str(radius)
|
||||
# print "vertfeed: " + str(vertfeed)
|
||||
# print "horizfeed: " + str(horizfeed)
|
||||
# print "offset_extra: " + str(offset_extra)
|
||||
# print "roll_radius: " + str(roll_radius)
|
||||
# print "roll_on: " + str(roll_on)
|
||||
# print "roll_off: " + str(roll_off)
|
||||
# print "depthparams: " + str(depthparams)
|
||||
# print "extend_at_start: " + str(extend_at_start)
|
||||
# print "extend_at_end: " + str(extend_at_end)
|
||||
# print "lead_in_line_len: " + str(lead_in_line_len)
|
||||
# print "lead_out_line_len: " + str(lead_out_line_len)
|
||||
|
||||
global tags
|
||||
direction = direction.lower()
|
||||
offset_curve = area.Curve(curve)
|
||||
if direction == "on":
|
||||
use_CRC() == False
|
||||
|
||||
use_CRC() == False
|
||||
|
||||
if direction != "on":
|
||||
if direction != "left" and direction != "right":
|
||||
raise "direction must be left or right", direction
|
||||
|
||||
# get tool diameter
|
||||
offset = radius + offset_extra
|
||||
if use_CRC() == False or (use_CRC()==True and CRC_nominal_path()==True):
|
||||
if use_CRC() is False or (use_CRC() is True and CRC_nominal_path() is True):
|
||||
if math.fabs(offset) > 0.00005:
|
||||
if direction == "right":
|
||||
offset = -offset
|
||||
offset_success = offset_curve.Offset(offset)
|
||||
if offset_success == False:
|
||||
if offset_success is False:
|
||||
global using_area_for_offset
|
||||
if curve.IsClosed() and (using_area_for_offset == False):
|
||||
if curve.IsClosed() and (using_area_for_offset is False):
|
||||
cw = curve.IsClockwise()
|
||||
using_area_for_offset = True
|
||||
a = area.Area()
|
||||
@@ -307,27 +346,29 @@ def profile2(curve, direction = "on", radius = 1.0, vertfeed=0.0,horizfeed=0.0,
|
||||
if cw != curve_cw:
|
||||
curve.Reverse()
|
||||
set_good_start_point(curve, False)
|
||||
profile(curve, direction, 0.0, 0.0, roll_radius, roll_on, roll_off, depthparams, extend_at_start, extend_at_end, lead_in_line_len, lead_out_line_len)
|
||||
profile(curve, direction, 0.0, 0.0, roll_radius, roll_on, roll_off, depthparams,
|
||||
extend_at_start, extend_at_end, lead_in_line_len, lead_out_line_len)
|
||||
using_area_for_offset = False
|
||||
return
|
||||
return
|
||||
else:
|
||||
raise Exception, "couldn't offset kurve " + str(offset_curve)
|
||||
|
||||
raise Exception, "couldn't offset kurve " + \
|
||||
str(offset_curve)
|
||||
|
||||
# extend curve
|
||||
if extend_at_start > 0.0:
|
||||
span = offset_curve.GetFirstSpan()
|
||||
new_start = span.p + span.GetVector(0.0) * ( -extend_at_start)
|
||||
new_start = span.p + span.GetVector(0.0) * (-extend_at_start)
|
||||
new_curve = area.Curve()
|
||||
new_curve.append(new_start)
|
||||
for vertex in offset_curve.getVertices():
|
||||
new_curve.append(vertex)
|
||||
offset_curve = new_curve
|
||||
|
||||
|
||||
if extend_at_end > 0.0:
|
||||
span = offset_curve.GetLastSpan()
|
||||
new_end = span.v.p + span.GetVector(1.0) * extend_at_end
|
||||
offset_curve.append(new_end)
|
||||
|
||||
|
||||
# remove tags further than radius from the offset kurve
|
||||
new_tags = []
|
||||
for tag in tags:
|
||||
@@ -347,126 +388,140 @@ def profile2(curve, direction = "on", radius = 1.0, vertfeed=0.0,horizfeed=0.0,
|
||||
if len(tags) > 0:
|
||||
# make a copy to restore to after each level
|
||||
copy_of_offset_curve = area.Curve(offset_curve)
|
||||
|
||||
|
||||
prev_depth = depthparams.start_depth
|
||||
|
||||
|
||||
endpoint = None
|
||||
|
||||
|
||||
for depth in depths:
|
||||
mat_depth = prev_depth
|
||||
|
||||
|
||||
if len(tags) > 0:
|
||||
split_for_tags(offset_curve, radius, depthparams.start_depth, depth, depthparams.final_depth)
|
||||
split_for_tags(
|
||||
offset_curve, radius, depthparams.start_depth, depth, depthparams.final_depth)
|
||||
|
||||
# make the roll on and roll off kurves
|
||||
roll_on_curve = area.Curve()
|
||||
add_roll_on(offset_curve, roll_on_curve, direction, roll_radius, offset_extra, roll_on)
|
||||
add_roll_on(offset_curve, roll_on_curve, direction,
|
||||
roll_radius, offset_extra, roll_on)
|
||||
roll_off_curve = area.Curve()
|
||||
add_roll_off(offset_curve, roll_off_curve, direction, roll_radius, offset_extra, roll_off)
|
||||
add_roll_off(offset_curve, roll_off_curve, direction,
|
||||
roll_radius, offset_extra, roll_off)
|
||||
if use_CRC():
|
||||
crc_start_point = area.Point()
|
||||
add_CRC_start_line(offset_curve,roll_on_curve,roll_off_curve,radius,direction,crc_start_point,lead_in_line_len)
|
||||
|
||||
add_CRC_start_line(offset_curve, roll_on_curve, roll_off_curve,
|
||||
radius, direction, crc_start_point, lead_in_line_len)
|
||||
|
||||
# get the tag depth at the start
|
||||
start_z = get_tag_z_for_span(0, offset_curve, radius, depthparams.start_depth, depth, depthparams.final_depth)
|
||||
if start_z > mat_depth: mat_depth = start_z
|
||||
start_z = get_tag_z_for_span(
|
||||
0, offset_curve, radius, depthparams.start_depth, depth, depthparams.final_depth)
|
||||
if start_z > mat_depth:
|
||||
mat_depth = start_z
|
||||
|
||||
# rapid across to the start
|
||||
s = roll_on_curve.FirstVertex().p
|
||||
|
||||
# start point
|
||||
if (endpoint == None) or (endpoint != s):
|
||||
|
||||
# start point
|
||||
if (endpoint is None) or (endpoint != s):
|
||||
if use_CRC():
|
||||
rapid(crc_start_point.x,crc_start_point.y)
|
||||
rapid(crc_start_point.x, crc_start_point.y)
|
||||
else:
|
||||
rapid(s.x, s.y)
|
||||
|
||||
|
||||
# rapid down to just above the material
|
||||
if endpoint == None:
|
||||
rapid(z = mat_depth + depthparams.rapid_safety_space)
|
||||
if endpoint is None:
|
||||
rapid(z=mat_depth + depthparams.rapid_safety_space)
|
||||
else:
|
||||
rapid(z = mat_depth)
|
||||
rapid(z=mat_depth)
|
||||
|
||||
# feed down to depth
|
||||
mat_depth = depth
|
||||
if start_z > mat_depth: mat_depth = start_z
|
||||
feed(z = mat_depth)
|
||||
if start_z > mat_depth:
|
||||
mat_depth = start_z
|
||||
feed(s.x, s.y, z=mat_depth)
|
||||
|
||||
if use_CRC():
|
||||
start_CRC(direction == "left", radius)
|
||||
# move to the startpoint
|
||||
feed(s.x, s.y)
|
||||
|
||||
|
||||
# cut the roll on arc
|
||||
cut_curve(roll_on_curve)
|
||||
|
||||
|
||||
# cut the main kurve
|
||||
current_perim = 0.0
|
||||
|
||||
|
||||
for span in offset_curve.GetSpans():
|
||||
# height for tags
|
||||
current_perim += span.Length()
|
||||
ez = get_tag_z_for_span(current_perim, offset_curve, radius, depthparams.start_depth, depth, depthparams.final_depth)
|
||||
|
||||
if span.v.type == 0:#line
|
||||
ez = get_tag_z_for_span(current_perim, offset_curve, radius,
|
||||
depthparams.start_depth, depth, depthparams.final_depth)
|
||||
if ez is None:
|
||||
ez = depth
|
||||
if span.v.type == 0: # line
|
||||
feed(span.v.p.x, span.v.p.y, ez)
|
||||
else:
|
||||
if span.v.type == 1:# anti-clockwise arc
|
||||
arc_ccw(span.v.p.x, span.v.p.y, ez, i = span.v.c.x, j = span.v.c.y)
|
||||
if span.v.type == 1: # anti-clockwise arc
|
||||
arc_ccw(span.v.p.x, span.v.p.y, ez,
|
||||
i=span.v.c.x, j=span.v.c.y)
|
||||
else:
|
||||
arc_cw(span.v.p.x, span.v.p.y, ez, i = span.v.c.x, j = span.v.c.y)
|
||||
|
||||
|
||||
arc_cw(span.v.p.x, span.v.p.y, ez,
|
||||
i=span.v.c.x, j=span.v.c.y)
|
||||
|
||||
# cut the roll off arc
|
||||
cut_curve(roll_off_curve)
|
||||
|
||||
endpoint = offset_curve.LastVertex().p
|
||||
if roll_off_curve.getNumVertices() > 0:
|
||||
endpoint = roll_off_curve.LastVertex().p
|
||||
|
||||
#add CRC end_line
|
||||
|
||||
# add CRC end_line
|
||||
if use_CRC():
|
||||
crc_end_point = area.Point()
|
||||
add_CRC_end_line(offset_curve,roll_on_curve,roll_off_curve,radius,direction,crc_end_point,lead_out_line_len)
|
||||
add_CRC_end_line(offset_curve, roll_on_curve, roll_off_curve,
|
||||
radius, direction, crc_end_point, lead_out_line_len)
|
||||
if direction == "on":
|
||||
rapid(z = depthparams.clearance_height)
|
||||
rapid(z=depthparams.clearance_height)
|
||||
else:
|
||||
feed(crc_end_point.x, crc_end_point.y)
|
||||
|
||||
|
||||
|
||||
# restore the unsplit kurve
|
||||
if len(tags) > 0:
|
||||
offset_curve = area.Curve(copy_of_offset_curve)
|
||||
if use_CRC():
|
||||
end_CRC()
|
||||
|
||||
end_CRC()
|
||||
|
||||
if endpoint != s:
|
||||
# rapid up to the clearance height
|
||||
rapid(z = depthparams.clearance_height)
|
||||
|
||||
rapid(z=depthparams.clearance_height)
|
||||
|
||||
prev_depth = depth
|
||||
|
||||
rapid(z = depthparams.clearance_height)
|
||||
rapid(z=depthparams.clearance_height)
|
||||
|
||||
del offset_curve
|
||||
|
||||
|
||||
if len(tags) > 0:
|
||||
del copy_of_offset_curve
|
||||
|
||||
|
||||
class Tag:
|
||||
|
||||
def __init__(self, p, width, angle, height):
|
||||
self.p = p
|
||||
self.width = width # measured at the top of the tag. In the toolpath, the tag width will be this with plus the tool diameter, so that the finished tag has this "width" at it's smallest
|
||||
self.angle = angle # the angle of the ramp in radians. Between 0 and Pi/2; 0 is horizontal, Pi/2 is vertical
|
||||
self.height = height # the height of the tag, always measured above "final_depth"
|
||||
self.width = width # measured at the top of the tag. In the toolpath, the tag width will be this with plus the tool diameter, so that the finished tag has this "width" at it's smallest
|
||||
# the angle of the ramp in radians. Between 0 and Pi/2; 0 is
|
||||
# horizontal, Pi/2 is vertical
|
||||
self.angle = angle
|
||||
self.height = height # the height of the tag, always measured above "final_depth"
|
||||
self.ramp_width = self.height / math.tan(self.angle)
|
||||
|
||||
|
||||
def split_curve(self, curve, radius, start_depth, depth, final_depth):
|
||||
tag_top_depth = final_depth + self.height
|
||||
|
||||
|
||||
if depth > tag_top_depth - 0.0000001:
|
||||
return # kurve is above this tag, so doesn't need splitting
|
||||
|
||||
return # kurve is above this tag, so doesn't need splitting
|
||||
|
||||
height_above_depth = tag_top_depth - depth
|
||||
ramp_width_at_depth = height_above_depth / math.tan(self.angle)
|
||||
cut_depth = start_depth - depth
|
||||
@@ -476,30 +531,38 @@ class Tag:
|
||||
d0 = d - half_flat_top
|
||||
perim = curve.Perim()
|
||||
if curve.IsClosed():
|
||||
while d0 < 0: d0 += perim
|
||||
while d0 > perim: d0 -= perim
|
||||
while d0 < 0:
|
||||
d0 += perim
|
||||
while d0 > perim:
|
||||
d0 -= perim
|
||||
p = curve.PerimToPoint(d0)
|
||||
curve.Break(p)
|
||||
d1 = d + half_flat_top
|
||||
if curve.IsClosed():
|
||||
while d1 < 0: d1 += perim
|
||||
while d1 > perim: d1 -= perim
|
||||
while d1 < 0:
|
||||
d1 += perim
|
||||
while d1 > perim:
|
||||
d1 -= perim
|
||||
p = curve.PerimToPoint(d1)
|
||||
curve.Break(p)
|
||||
|
||||
|
||||
d0 = d - half_flat_top - ramp_width_at_depth
|
||||
if curve.IsClosed():
|
||||
while d0 < 0: d0 += perim
|
||||
while d0 > perim: d0 -= perim
|
||||
while d0 < 0:
|
||||
d0 += perim
|
||||
while d0 > perim:
|
||||
d0 -= perim
|
||||
p = curve.PerimToPoint(d0)
|
||||
curve.Break(p)
|
||||
d1 = d + half_flat_top + ramp_width_at_depth
|
||||
if curve.IsClosed():
|
||||
while d1 < 0: d1 += perim
|
||||
while d1 > perim: d1 -= perim
|
||||
while d1 < 0:
|
||||
d1 += perim
|
||||
while d1 > perim:
|
||||
d1 -= perim
|
||||
p = curve.PerimToPoint(d1)
|
||||
curve.Break(p)
|
||||
|
||||
|
||||
def get_z_at_perim(self, current_perim, curve, radius, start_depth, depth, final_depth):
|
||||
# return the z for this position on the kurve ( specified by current_perim ), for this tag
|
||||
# if the position is not within the tag, then depth is returned
|
||||
@@ -516,9 +579,10 @@ class Tag:
|
||||
# on ramp
|
||||
dist_up_ramp = (half_flat_top + self.ramp_width) - dist_from_d
|
||||
z = final_depth + dist_up_ramp * math.tan(self.angle)
|
||||
if z < depth: z = depth
|
||||
if z < depth:
|
||||
z = depth
|
||||
return z
|
||||
|
||||
|
||||
def dist(self, curve):
|
||||
# return the distance from the tag point to the given kurve
|
||||
d = curve.PointToPerim(self.p)
|
||||
@@ -528,12 +592,15 @@ class Tag:
|
||||
|
||||
tags = []
|
||||
|
||||
|
||||
def add_roll_on(curve, roll_on_curve, direction, roll_radius, offset_extra, roll_on):
|
||||
if direction == "on": roll_on = None
|
||||
if curve.getNumVertices() <= 1: return
|
||||
if direction == "on":
|
||||
roll_on = None
|
||||
if curve.getNumVertices() <= 1:
|
||||
return
|
||||
first_span = curve.GetFirstSpan()
|
||||
|
||||
if roll_on == None:
|
||||
if roll_on is None:
|
||||
rollstart = first_span.p
|
||||
elif roll_on == 'auto':
|
||||
if roll_radius < 0.0000000001:
|
||||
@@ -545,95 +612,111 @@ def add_roll_on(curve, roll_on_curve, direction, roll_radius, offset_extra, roll
|
||||
off_v = area.Point(-v.y, v.x)
|
||||
rollstart = first_span.p + off_v * roll_radius
|
||||
else:
|
||||
rollstart = roll_on
|
||||
rollstart = roll_on
|
||||
|
||||
rvertex = area.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 = area.TangentialArc(first_span.p, rollstart, -v)
|
||||
rvertex.type = -rvertex.type # because TangentialArc was used in reverse
|
||||
v = first_span.GetVector(0.0) # get start direction
|
||||
rvertex.c, rvertex.type = area.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 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.getNumVertices() <= 1: return
|
||||
if direction == "on":
|
||||
return
|
||||
if roll_off is None:
|
||||
return
|
||||
if curve.getNumVertices() <= 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 roll_radius < 0.0000000001:
|
||||
return
|
||||
v = last_span.GetVector(1.0) # get end direction
|
||||
if direction == 'right':
|
||||
off_v = area.Point(v.y, -v.x)
|
||||
else:
|
||||
off_v = area.Point(-v.y, v.x)
|
||||
|
||||
rollend = last_span.v.p + off_v * roll_radius;
|
||||
rollend = last_span.v.p + off_v * roll_radius
|
||||
else:
|
||||
rollend = roll_off
|
||||
|
||||
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
|
||||
if rollend == last_span.v.p:
|
||||
return
|
||||
rvertex = area.Vertex(rollend)
|
||||
v = last_span.GetVector(1.0) # get end direction
|
||||
v = last_span.GetVector(1.0) # get end direction
|
||||
rvertex.c, rvertex.type = area.TangentialArc(last_span.v.p, rollend, v)
|
||||
|
||||
# add the roll off arc
|
||||
# add the roll off arc
|
||||
roll_off_curve.append(rvertex)
|
||||
|
||||
|
||||
def clear_tags():
|
||||
global tags
|
||||
tags = []
|
||||
|
||||
|
||||
|
||||
def add_tag(p, width, angle, height):
|
||||
global tags
|
||||
tag = Tag(p, width, angle, height)
|
||||
tags.append(tag)
|
||||
|
||||
def split_for_tags( curve, radius, start_depth, depth, final_depth ):
|
||||
|
||||
def split_for_tags(curve, radius, start_depth, depth, final_depth):
|
||||
global tags
|
||||
for tag in tags:
|
||||
tag.split_curve(curve, radius, start_depth, depth, final_depth)
|
||||
|
||||
|
||||
def get_tag_z_for_span(current_perim, curve, radius, start_depth, depth, final_depth):
|
||||
global tags
|
||||
max_z = None
|
||||
perim = curve.Perim()
|
||||
for tag in tags:
|
||||
z = tag.get_z_at_perim(current_perim, curve, radius, start_depth, depth, final_depth)
|
||||
if max_z == None or z > max_z:
|
||||
z = tag.get_z_at_perim(current_perim, curve,
|
||||
radius, start_depth, depth, final_depth)
|
||||
if max_z is None or z > max_z:
|
||||
max_z = z
|
||||
if curve.IsClosed():
|
||||
# do the same test, wrapped around the closed kurve
|
||||
z = tag.get_z_at_perim(current_perim - perim, curve, radius, start_depth, depth, final_depth)
|
||||
if max_z == None or z > max_z:
|
||||
z = tag.get_z_at_perim(
|
||||
current_perim - perim, curve, radius, start_depth, depth, final_depth)
|
||||
if max_z is None or z > max_z:
|
||||
max_z = z
|
||||
z = tag.get_z_at_perim(current_perim + perim, curve, radius, start_depth, depth, final_depth)
|
||||
if max_z == None or z > max_z:
|
||||
z = tag.get_z_at_perim(
|
||||
current_perim + perim, curve, radius, start_depth, depth, final_depth)
|
||||
if max_z is None or z > max_z:
|
||||
max_z = z
|
||||
|
||||
|
||||
return max_z
|
||||
|
||||
|
||||
def cut_curve(curve):
|
||||
for span in curve.GetSpans():
|
||||
if span.v.type == 0:#line
|
||||
if span.v.type == 0: # line
|
||||
feed(span.v.p.x, span.v.p.y)
|
||||
else:
|
||||
if span.v.type == 1:# anti-clockwise arc
|
||||
arc_ccw(span.v.p.x, span.v.p.y, i = span.v.c.x, j = span.v.c.y)
|
||||
if span.v.type == 1: # anti-clockwise arc
|
||||
arc_ccw(span.v.p.x, span.v.p.y, i=span.v.c.x, j=span.v.c.y)
|
||||
else:
|
||||
arc_cw(span.v.p.x, span.v.p.y, i = span.v.c.x, j = span.v.c.y)
|
||||
|
||||
def add_CRC_start_line(curve,roll_on_curve,roll_off_curve,radius,direction,crc_start_point,lead_in_line_len):
|
||||
arc_cw(span.v.p.x, span.v.p.y, i=span.v.c.x, j=span.v.c.y)
|
||||
|
||||
|
||||
def add_CRC_start_line(curve, roll_on_curve, roll_off_curve, radius, direction, crc_start_point, lead_in_line_len):
|
||||
first_span = curve.GetFirstSpan()
|
||||
v = first_span.GetVector(0.0)
|
||||
if direction == 'right':
|
||||
@@ -641,11 +724,12 @@ def add_CRC_start_line(curve,roll_on_curve,roll_off_curve,radius,direction,crc_s
|
||||
else:
|
||||
off_v = area.Point(-v.y, v.x)
|
||||
startpoint_roll_on = roll_on_curve.FirstVertex().p
|
||||
crc_start = startpoint_roll_on + off_v * lead_in_line_len
|
||||
crc_start_point.x = crc_start.x
|
||||
crc_start_point.y = crc_start.y
|
||||
crc_start = startpoint_roll_on + off_v * lead_in_line_len
|
||||
crc_start_point.x = crc_start.x
|
||||
crc_start_point.y = crc_start.y
|
||||
|
||||
def add_CRC_end_line(curve,roll_on_curve,roll_off_curve,radius,direction,crc_end_point,lead_out_line_len):
|
||||
|
||||
def add_CRC_end_line(curve, roll_on_curve, roll_off_curve, radius, direction, crc_end_point, lead_out_line_len):
|
||||
last_span = curve.GetLastSpan()
|
||||
v = last_span.GetVector(1.0)
|
||||
if direction == 'right':
|
||||
@@ -653,10 +737,8 @@ def add_CRC_end_line(curve,roll_on_curve,roll_off_curve,radius,direction,crc_end
|
||||
else:
|
||||
off_v = area.Point(-v.y, v.x)
|
||||
endpoint_roll_off = roll_off_curve.LastVertex().p
|
||||
crc_end = endpoint_roll_off + off_v * lead_out_line_len
|
||||
crc_end_point.x = crc_end.x
|
||||
crc_end_point.y = crc_end.y
|
||||
crc_end = endpoint_roll_off + off_v * lead_out_line_len
|
||||
crc_end_point.x = crc_end.x
|
||||
crc_end_point.y = crc_end.y
|
||||
|
||||
using_area_for_offset = False
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user