PATH: conversion of PathContour to PathArea nearly complete

Path: improve contour to use makeSections
This commit is contained in:
sliptonic
2017-05-01 23:56:36 -05:00
committed by wmayer
parent 018ba981f8
commit 775b91d1a2
4 changed files with 87 additions and 182 deletions

View File

@@ -23,19 +23,19 @@
# ***************************************************************************
import FreeCAD
from FreeCAD import Vector
#from FreeCAD import Vector
import Path
import PathScripts.PathLog as PathLog
from PathScripts import PathUtils
from PathScripts.PathUtils import depth_params
from PySide import QtCore
import TechDraw
#import TechDraw
import ArchPanel
import Part
LOG_MODULE = 'PathContour'
PathLog.setLevel(PathLog.Level.INFO, LOG_MODULE)
#PathLog.trackModule('PathContour')
PathLog.trackModule('PathContour')
if FreeCAD.GuiUp:
import FreeCADGui
@@ -80,14 +80,6 @@ class ObjectContour:
# Start Point Properties
obj.addProperty("App::PropertyVector", "StartPoint", "Start Point", QtCore.QT_TRANSLATE_NOOP("App::Property", "The start point of this path"))
obj.addProperty("App::PropertyBool", "UseStartPoint", "Start Point", QtCore.QT_TRANSLATE_NOOP("App::Property", "make True, if specifying a Start Point"))
obj.addProperty("App::PropertyLength", "ExtendAtStart", "Start Point", QtCore.QT_TRANSLATE_NOOP("App::Property", "extra length of tool path before start of part edge"))
obj.addProperty("App::PropertyLength", "LeadInLineLen", "Start Point", QtCore.QT_TRANSLATE_NOOP("App::Property", "length of straight segment of toolpath that comes in at angle to first part edge"))
# End Point Properties
obj.addProperty("App::PropertyBool", "UseEndPoint", "End Point", QtCore.QT_TRANSLATE_NOOP("App::Property", "make True, if specifying an End Point"))
obj.addProperty("App::PropertyLength", "ExtendAtEnd", "End Point", QtCore.QT_TRANSLATE_NOOP("App::Property", "extra length of tool path after end of part edge"))
obj.addProperty("App::PropertyLength", "LeadOutLineLen", "End Point", QtCore.QT_TRANSLATE_NOOP("App::Property", "length of straight segment of toolpath that comes in at angle to last part edge"))
obj.addProperty("App::PropertyVector", "EndPoint", "End Point", QtCore.QT_TRANSLATE_NOOP("App::Property", "The end point of this path"))
# Contour Properties
obj.addProperty("App::PropertyEnumeration", "Direction", "Contour", QtCore.QT_TRANSLATE_NOOP("App::Property", "The direction that the toolpath should go around the part ClockWise CW or CounterClockWise CCW"))
@@ -97,7 +89,6 @@ class ObjectContour:
obj.Side = ['Left', 'Right', 'On'] # side of profile that cutter is on in relation to direction of profile
obj.setEditorMode('Side', 2) # hide
obj.addProperty("App::PropertyDistance", "RollRadius", "Contour", QtCore.QT_TRANSLATE_NOOP("App::Property", "Radius at start and end"))
obj.addProperty("App::PropertyDistance", "OffsetExtra", "Contour", QtCore.QT_TRANSLATE_NOOP("App::Property", "Extra value to stay away from final Contour- good for roughing toolpath"))
obj.Proxy = self
@@ -132,100 +123,62 @@ class ObjectContour:
obj.ClearanceHeight = 10.0
obj.SafeHeight = 8.0
def _buildPathArea(self, obj, edgelist, start = None):
def _buildPathArea(self, obj, baseobject, start=None):
PathLog.track()
c = Part.Wire(edgelist)
f = Part.makeFace([c], 'Part::FaceMakerSimple')
profile = Path.Area(Offset=self.radius,SectionCount=1)
profile = Path.Area()
profile.setPlane(Part.makeCircle(10))
profile.add(f)
lshapes = [profile.getShape()]
profile.add(baseobject)
profileparams = {'Fill': 0,
'Coplanar' : 0}
if obj.UseComp is False:
profileparams['Offset'] = 0.0
else:
profileparams['Offset'] = self.radius+obj.OffsetExtra.Value
profile.setParams(**profileparams)
PathLog.debug("About to profile with params: {}".format(profileparams))
depthparams = depth_params(
clearance_height = obj.ClearanceHeight.Value,
rapid_safety_space = obj.SafeHeight.Value,
start_depth = obj.StartDepth.Value,
step_down = obj.StepDown.Value,
z_finish_step = 0.0,
final_depth = obj.FinalDepth.Value,
user_depths = None)
clearance_height=obj.ClearanceHeight.Value,
rapid_safety_space=obj.SafeHeight.Value,
start_depth=obj.StartDepth.Value,
step_down=obj.StepDown.Value,
z_finish_step=0.0,
final_depth=obj.FinalDepth.Value,
user_depths=None)
print (depthparams.get_depths())
for l in depthparams.get_depths():
c = lshapes[0].copy()
c.Placement.Base.z = l
lshapes.append(c)
sections = profile.makeSections(mode=0, project=True, heights=depthparams.get_depths())
shapelist = [sec.getShape() for sec in sections]
if start is None:
pp = Path.fromShapes(lshapes, verbose=False)
params = {'shapes': shapelist,
'feedrate': self.horizFeed,
'feedrate_v': self.vertFeed,
'verbose': True,
'resume_height': obj.StepDown.Value,
'retraction': obj.ClearanceHeight.Value}
if obj.Direction == 'CCW':
params['orientation'] = 1
else:
pp = Path.fromShapes(lshapes, start, verbose=False)
params['orientation'] = 0
if obj.UseStartPoint is True and obj.StartPoint is not None:
params['start'] = obj.StartPoint
PathLog.debug("Generating Path with params: {}".format(params))
pp = Path.fromShapes(**params)
PathLog.debug(pp)
return pp
# def _buildPathLibarea(self, obj, edgelist):
# import PathScripts.PathKurveUtils as PathKurveUtils
# PathLog.track()
# # import math
# # import area
# output = ""
# if obj.Comment != "":
# output += '(' + str(obj.Comment)+')\n'
# if obj.StartPoint and obj.UseStartPoint:
# startpoint = obj.StartPoint
# else:
# startpoint = None
# if obj.EndPoint and obj.UseEndPoint:
# endpoint = obj.EndPoint
# else:
# endpoint = None
# PathKurveUtils.output('mem')
# PathKurveUtils.feedrate_hv(self.horizFeed, self.vertFeed)
# output = ""
# output += "G0 Z" + str(obj.ClearanceHeight.Value) + "F " + PathUtils.fmt(self.vertRapid) + "\n"
# curve = PathKurveUtils.makeAreaCurve(edgelist, obj.Direction, startpoint, endpoint)
# roll_radius = 2.0
# extend_at_start = 0.0
# extend_at_end = 0.0
# lead_in_line_len = 0.0
# lead_out_line_len = 0 # obj.FinalDepth.Value, None)
# PathKurveUtils.profile2(
# if obj.UseComp is False:
# obj.Side = 'On'
# else:
# if obj.Direction == 'CW':
# obj.Side = 'Left'
# else:
# obj.Side = 'Right'
# depthparams = depth_params(
# obj.ClearanceHeight.Value,
# obj.SafeHeight.Value, obj.StartDepth.Value, obj.StepDown.Value, 0.0,
# obj.FinalDepth.Value, None)
# PathKurveUtils.profile2(
# curve, obj.Side, self.radius, self.vertFeed, self.horizFeed,
# self.vertRapid, self.horizRapid, obj.OffsetExtra.Value, roll_radius,
# None, None, depthparams, extend_at_start, extend_at_end,
# lead_in_line_len, lead_out_line_len)
# output += PathKurveUtils.retrieve_gcode()
# return output
def execute(self, obj):
PathLog.track()
import Part # math #DraftGeomUtils
commandlist = []
#output = ""
import Part
commandlist = []
toolLoad = obj.ToolController
if toolLoad is None or toolLoad.ToolNumber == 0:
@@ -236,23 +189,18 @@ class ObjectContour:
self.horizFeed = toolLoad.HorizFeed.Value
self.vertRapid = toolLoad.VertRapid.Value
self.horizRapid = toolLoad.HorizRapid.Value
tool = toolLoad.Proxy.getTool(toolLoad) #PathUtils.getTool(obj, toolLoad.ToolNumber)
tool = toolLoad.Proxy.getTool(toolLoad)
if not tool or tool.Diameter == 0:
FreeCAD.Console.PrintError("No Tool found or diameter is zero. We need a tool to build a Path.")
return
#self.radius = 0.25
else:
self.radius = tool.Diameter/2
#output += "(" + obj.Label + ")"
commandlist.append(Path.Command("(" + obj.Label + ")"))
if not obj.UseComp:
#output += "(Compensated Tool Path. Diameter: " + str(self.radius * 2) + ")"
commandlist.append(Path.Command("(Compensated Tool Path. Diameter: " + str(self.radius * 2) + ")"))
else:
#output += "(Uncompensated Tool Path)"
commandlist.append(Path.Command("(Uncompensated Tool Path)"))
parentJob = PathUtils.findParentJob(obj)
@@ -269,34 +217,27 @@ class ObjectContour:
if isinstance(subobj.Proxy, ArchPanel.PanelCut):
shapes = baseobject.Proxy.getOutlines(baseobject, transform=True)
for shape in shapes:
for wire in shape.Wires:
edgelist = wire.Edges
edgelist = Part.__sortEdges__(edgelist)
PathLog.debug("Processing panel perimeter. edges found: {}".format(len(edgelist))) # subobj.Proxy.execute(subobj)
f = Part.makeFace([shape], 'Part::FaceMakerSimple')
thickness = baseobject.Group[0].Source.Thickness
contourshape = f.extrude(FreeCAD.Vector(0,0, thickness))
try:
#output += self._buildPathLibarea(obj, edgelist)
commandlist.extend(self._buildPathArea(obj, edgelist).Commands)
except Exception as e:
print(e)
commandlist.extend(self._buildPathArea(obj, contourshape).Commands)
except Exception as e:
print(e)
FreeCAD.Console.PrintError("Something unexpected happened. Unable to generate a contour path. Check project and tool config.")
else:
fixbase = baseobject.Shape.copy()
fixbase.fix(0.00001,0.00001,0.00001)
contourwire = TechDraw.findShapeOutline(fixbase, 1, Vector(0, 0, 1))
edgelist = contourwire.Edges
edgelist = Part.__sortEdges__(edgelist)
#fixbase = baseobject.Shape.copy()
#fixbase.fix(0.00001, 0.00001, 0.00001)
env = PathUtils.getEnvelope(baseobject.Shape, obj.StartDepth)
try:
commandlist.extend(self._buildPathArea(obj, edgelist).Commands)
except Exception as e:
print(e)
commandlist.extend(self._buildPathArea(obj, env).Commands)
except Exception as e:
print(e)
FreeCAD.Console.PrintError("Something unexpected happened. Unable to generate a contour path. Check project and tool config.")
if obj.Active:
path = Path.Path(commandlist)
# for c in contourcommands.Commands:
# path.addCommands(c)
obj.Path = path
if obj.ViewObject:
obj.ViewObject.Visibility = True
@@ -348,26 +289,6 @@ class _CommandSetStartPoint:
obj.StartPoint.y = point.y
def Activated(self):
FreeCADGui.Snapper.getPoint(callback=self.setpoint)
class _CommandSetEndPoint:
def GetResources(self):
return {'Pixmap': 'Path-EndPoint',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_Contour", "Pick End Point"),
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Contour", "Pick End Point")}
def IsActive(self):
return FreeCAD.ActiveDocument is not None
def setpoint(self, point, o):
obj = FreeCADGui.Selection.getSelection()[0]
obj.EndPoint.x = point.x
obj.EndPoint.y = point.y
def Activated(self):
FreeCADGui.Snapper.getPoint(callback=self.setpoint)
@@ -450,14 +371,10 @@ class TaskPanel:
self.obj.StepDown = FreeCAD.Units.Quantity(self.form.stepDown.text()).Value
if hasattr(self.obj, "OffsetExtra"):
self.obj.OffsetExtra = FreeCAD.Units.Quantity(self.form.extraOffset.text()).Value
if hasattr(self.obj, "RollRadius"):
self.obj.RollRadius = FreeCAD.Units.Quantity(self.form.rollRadius.text()).Value
if hasattr(self.obj, "UseComp"):
self.obj.UseComp = self.form.useCompensation.isChecked()
if hasattr(self.obj, "UseStartPoint"):
self.obj.UseStartPoint = self.form.useStartPoint.isChecked()
if hasattr(self.obj, "UseEndPoint"):
self.obj.UseEndPoint = self.form.useEndPoint.isChecked()
if hasattr(self.obj, "Direction"):
self.obj.Direction = str(self.form.direction.currentText())
if hasattr(self.obj, "ToolController"):
@@ -473,10 +390,8 @@ class TaskPanel:
self.form.clearanceHeight.setText(FreeCAD.Units.Quantity(self.obj.ClearanceHeight.Value, FreeCAD.Units.Length).UserString)
self.form.stepDown.setText(FreeCAD.Units.Quantity(self.obj.StepDown.Value, FreeCAD.Units.Length).UserString)
self.form.extraOffset.setText(FreeCAD.Units.Quantity(self.obj.OffsetExtra.Value, FreeCAD.Units.Length).UserString)
self.form.rollRadius.setText(FreeCAD.Units.Quantity(self.obj.RollRadius.Value, FreeCAD.Units.Length).UserString)
self.form.useCompensation.setChecked(self.obj.UseComp)
self.form.useStartPoint.setChecked(self.obj.UseStartPoint)
self.form.useEndPoint.setChecked(self.obj.UseEndPoint)
index = self.form.direction.findText(
self.obj.Direction, QtCore.Qt.MatchFixedString)
@@ -529,9 +444,7 @@ class TaskPanel:
self.form.uiToolController.currentIndexChanged.connect(self.getFields)
self.form.useCompensation.clicked.connect(self.getFields)
self.form.useStartPoint.clicked.connect(self.getFields)
self.form.useEndPoint.clicked.connect(self.getFields)
self.form.extraOffset.editingFinished.connect(self.getFields)
self.form.rollRadius.editingFinished.connect(self.getFields)
self.setFields()
@@ -554,6 +467,5 @@ if FreeCAD.GuiUp:
# register the FreeCAD command
FreeCADGui.addCommand('Path_Contour', CommandPathContour())
FreeCADGui.addCommand('Set_StartPoint', _CommandSetStartPoint())
FreeCADGui.addCommand('Set_EndPoint', _CommandSetEndPoint())
FreeCAD.Console.PrintLog("Loading PathContour... done\n")

View File

@@ -33,6 +33,7 @@ import numpy
import PathLog
#from math import pi
from FreeCAD import Vector
import Path
LOG_MODULE = 'PathUtils'
PathLog.setLevel(PathLog.Level.INFO, LOG_MODULE)
@@ -193,6 +194,22 @@ def filterArcs(arcEdge):
pass
return splitlist
def getEnvelope(partshape, stockheight=None):
'''
getEnvelop(partshape, stockheight=None)
returns a shape corresponding to the partshape silhouette extruded to height.
if stockheight is given, the returned shape is extruded to that height otherwise the returned shape
is the height of the original shape boundbox
partshape = solid object
stockheight = float
'''
area = Path.Area(Fill=1, Coplanar=0).add(partshape)
area.setPlane(Part.makeCircle(10))
sec = area.makeSections(heights=[1.0], project=True)[0].getShape(rebuild=True)
if stockheight is not None:
return sec.extrude(FreeCAD.Vector(0, 0, stockheight))
else:
return sec.extrude(FreeCAD.Vector(0, 0, partshape.BoundBox.ZMax))
def reverseEdge(e):
if geomType(e) == "Circle":