Path: Vcarve - Added threshold property to remove unwanted segments
code cleanup & debug
This commit is contained in:
@@ -49,6 +49,23 @@ class MESHGate(PathBaseGate):
|
||||
|
||||
class VCARVEGate:
|
||||
def allow(self, doc, obj, sub):
|
||||
try:
|
||||
shape = obj.Shape
|
||||
except Exception: # pylint: disable=broad-except
|
||||
return False
|
||||
|
||||
if math.fabs(shape.Volume) < 1e-9 and len(shape.Wires) > 0:
|
||||
return True
|
||||
|
||||
if shape.ShapeType == 'Edge':
|
||||
return True
|
||||
|
||||
if sub:
|
||||
subShape = shape.getElement(sub)
|
||||
if subShape.ShapeType == 'Edge':
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
class ENGRAVEGate(PathBaseGate):
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
|
||||
import ArchPanel
|
||||
import FreeCAD
|
||||
import Part
|
||||
import Path
|
||||
@@ -30,9 +29,9 @@ import PathScripts.PathEngraveBase as PathEngraveBase
|
||||
import PathScripts.PathLog as PathLog
|
||||
import PathScripts.PathOp as PathOp
|
||||
import PathScripts.PathUtils as PathUtils
|
||||
import PathScripts.PathGeom as PathGeom
|
||||
import traceback
|
||||
import time
|
||||
import PathScripts.PathGeom as pg
|
||||
from PathScripts.PathOpTools import orientWire
|
||||
import math
|
||||
|
||||
@@ -46,148 +45,264 @@ if False:
|
||||
else:
|
||||
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
|
||||
|
||||
|
||||
# Qt tanslation handling
|
||||
def translate(context, text, disambig=None):
|
||||
return QtCore.QCoreApplication.translate(context, text, disambig)
|
||||
|
||||
|
||||
class ObjectVcarve(PathEngraveBase.ObjectOp):
|
||||
'''Proxy class for Vcarve operation.'''
|
||||
|
||||
def opFeatures(self, obj):
|
||||
'''opFeatures(obj) ... return all standard features and edges based geomtries'''
|
||||
return PathOp.FeatureTool | PathOp.FeatureDepths | PathOp.FeatureHeights | PathOp.FeatureStepDown | PathOp.FeatureBaseFaces;
|
||||
return PathOp.FeatureTool | PathOp.FeatureHeights | PathOp.FeatureBaseFaces
|
||||
|
||||
def setupAdditionalProperties(self, obj):
|
||||
if not hasattr(obj, 'BaseShapes'):
|
||||
obj.addProperty("App::PropertyLinkList", "BaseShapes", "Path", QtCore.QT_TRANSLATE_NOOP("PathVcarve", "Additional base objects to be engraved"))
|
||||
obj.setEditorMode('BaseShapes', 2) # hide
|
||||
obj.setEditorMode('BaseShapes', 2) # hide
|
||||
if not hasattr(obj, 'BaseObject'):
|
||||
obj.addProperty("App::PropertyLink", "BaseObject", "Path", QtCore.QT_TRANSLATE_NOOP("PathVcarve", "Additional base objects to be engraved"))
|
||||
obj.setEditorMode('BaseObject', 2) # hide
|
||||
obj.setEditorMode('BaseObject', 2) # hide
|
||||
|
||||
def initOperation(self, obj):
|
||||
'''initOperation(obj) ... create vcarve specific properties.'''
|
||||
obj.addProperty("App::PropertyFloat", "Discretize", "Path", QtCore.QT_TRANSLATE_NOOP("PathVcarve", "The deflection value for discretizing arcs"))
|
||||
obj.addProperty("App::PropertyFloat", "Threshold", "Path", QtCore.QT_TRANSLATE_NOOP("PathVcarve", "cutoff threshold for removing extraneous segments (0-1.0). default=0.8. Larger numbers remove less."))
|
||||
obj.Threshold = 0.8
|
||||
obj.Discretize = 0.01
|
||||
self.setupAdditionalProperties(obj)
|
||||
|
||||
def opOnDocumentRestored(self, obj):
|
||||
# upgrade ...
|
||||
self.setupAdditionalProperties(obj)
|
||||
|
||||
|
||||
def buildPathMedial(self, obj, Faces, zDepths, unitcircle):
|
||||
def buildPathMedial(self, obj, Faces):
|
||||
'''constructs a medial axis path using openvoronoi'''
|
||||
import openvoronoi as ovd
|
||||
#import openvoronoi as ovd
|
||||
|
||||
def insert_wire_points(vd, wire):
|
||||
pts=[]
|
||||
for p in wire.Vertexes:
|
||||
pts.append( ovd.Point( p.X, p.Y ) )
|
||||
print('p1 = FreeCAD.Vector(X:{} Y:{}'.format(p.X, p.Y))
|
||||
id_list = []
|
||||
print("inserting ",len(pts)," point-sites:")
|
||||
for p in pts:
|
||||
id_list.append( vd.addVertexSite( p ) )
|
||||
return id_list
|
||||
# def insert_wire_points(vd, wire):
|
||||
# pts = []
|
||||
# for p in wire.Vertexes:
|
||||
# pts.append(ovd.Point(p.X, p.Y))
|
||||
# PathLog.debug('ovd.Point( {} ,{} )'.format(p.X, p.Y))
|
||||
# id_list = []
|
||||
# PathLog.debug("inserting {} openvoronoi point-sites".format(len(pts)))
|
||||
# for p in pts:
|
||||
# id_list.append(vd.addVertexSite(p))
|
||||
# return id_list
|
||||
|
||||
def insert_wire_segments(vd,id_list):
|
||||
print('insert_polygon-segments')
|
||||
print('inserting {} segments'.format(len(id_list)))
|
||||
for n in range(len(id_list)):
|
||||
n_nxt = n+1
|
||||
if n==(len(id_list)-1):
|
||||
n_nxt=0
|
||||
vd.addLineSite( id_list[n], id_list[n_nxt])
|
||||
# def insert_wire_segments(vd, id_list):
|
||||
# PathLog.debug('inserting {} segments into the voronoi diagram'.format(len(id_list)))
|
||||
# for n in range(len(id_list)):
|
||||
# n_nxt = n + 1
|
||||
# if n == (len(id_list) - 1):
|
||||
# n_nxt = 0
|
||||
# vd.addLineSite(id_list[n], id_list[n_nxt])
|
||||
|
||||
def insert_many_wires(vd, wires):
|
||||
# print('inserting {} wires'.format(len(obj.Wires)))
|
||||
polygon_ids =[]
|
||||
t_before = time.time()
|
||||
for idx, wire in enumerate(wires):
|
||||
print('discretize: {}'.format(obj.Discretize))
|
||||
pointList = wire.discretize(Deflection=obj.Discretize)
|
||||
segwire = Part.Wire([Part.makeLine(p[0],p[1]) for p in zip(pointList, pointList[1:] )])
|
||||
#polygon_ids = []
|
||||
#t_before = time.time()
|
||||
for wire in wires:
|
||||
PathLog.debug('discretize value: {}'.format(obj.Discretize))
|
||||
pts = wire.discretize(QuasiDeflection=obj.Discretize)
|
||||
ptv = [FreeCAD.Vector(p[0], p[1]) for p in pts]
|
||||
ptv.append(ptv[0])
|
||||
|
||||
if idx == 0:
|
||||
segwire = orientWire(segwire, forward=False)
|
||||
else:
|
||||
segwire = orientWire(segwire, forward=True)
|
||||
for i in range(len(pts)):
|
||||
vd.addSegment(ptv[i], ptv[i+1])
|
||||
|
||||
poly_id = insert_wire_points(vd,segwire)
|
||||
polygon_ids.append(poly_id)
|
||||
t_after = time.time()
|
||||
pt_time = t_after-t_before
|
||||
# segwire = Part.Wire([Part.makeLine(p[0], p[1]) for p in zip(pointList, pointList[1:])])
|
||||
|
||||
t_before = time.time()
|
||||
for ids in polygon_ids:
|
||||
insert_wire_segments(vd,ids)
|
||||
t_after = time.time()
|
||||
seg_time = t_after-t_before
|
||||
return [pt_time, seg_time]
|
||||
# if idx == 0:
|
||||
# segwire = orientWire(segwire, forward=False)
|
||||
# else:
|
||||
# segwire = orientWire(segwire, forward=True)
|
||||
|
||||
# poly_id = insert_wire_points(vd, segwire)
|
||||
# polygon_ids.append(poly_id)
|
||||
# t_after = time.time()
|
||||
# pt_time = t_after - t_before
|
||||
|
||||
# t_before = time.time()
|
||||
# for ids in polygon_ids:
|
||||
# insert_wire_segments(vd, ids)
|
||||
# t_after = time.time()
|
||||
# seg_time = t_after - t_before
|
||||
# return [pt_time, seg_time]
|
||||
|
||||
def calculate_depth(MIC):
|
||||
# given a maximum inscribed circle (MIC) and tool angle,
|
||||
# return depth of cut.
|
||||
maxdepth = obj.ToolController.Tool.CuttingEdgeHeight
|
||||
toolangle = obj.ToolController.Tool.CuttingEdgeAngle
|
||||
return MIC / math.tan(math.radians(toolangle/2))
|
||||
d = MIC / math.tan(math.radians(toolangle / 2))
|
||||
return d if d <= maxdepth else maxdepth
|
||||
|
||||
def buildMedial(vd):
|
||||
safeheight = obj.SafeHeight.Value
|
||||
# def buildMedial(vd):
|
||||
# safeheight = obj.SafeHeight.Value
|
||||
# path = []
|
||||
# maw = ovd.MedialAxisWalk(vd.getGraph())
|
||||
# toolpath = maw.walk()
|
||||
# for chain in toolpath:
|
||||
|
||||
# path.append(Path.Command("G0 Z{}".format(safeheight)))
|
||||
# p = chain[0][0][0]
|
||||
# z = -(chain[0][0][1])
|
||||
|
||||
# path.append(Path.Command("G0 X{} Y{} Z{}".format(p.x, p.y, safeheight)))
|
||||
|
||||
# for step in chain:
|
||||
# for point in step:
|
||||
# p = point[0]
|
||||
# z = calculate_depth(-(point[1]))
|
||||
# path.append(Path.Command("G1 X{} Y{} Z{} F{}".format(p.x, p.y, z, obj.ToolController.HorizFeed.Value)))
|
||||
# path.append(Path.Command("G0 Z{}".format(safeheight))) return path pathlist = []
|
||||
def getEdges(vd, color=[0]):
|
||||
if type(color) == int:
|
||||
color = [color]
|
||||
geomList = []
|
||||
for e in vd.Edges:
|
||||
if e.Color not in color:
|
||||
continue
|
||||
# geom = e.toGeom(8)
|
||||
if e.toGeom(8) is None:
|
||||
continue
|
||||
p1 = e.Vertices[0].toGeom(calculate_depth(0-e.getDistances()[0]))
|
||||
p2 = e.Vertices[-1].toGeom(calculate_depth(0-e.getDistances()[-1]))
|
||||
geomList.append(Part.LineSegment(p1, p2))
|
||||
# if individualEdges:
|
||||
# name = "e%04d" % i
|
||||
# Part.show(Part.Edge(geom), name)
|
||||
#geomList.append(Part.Edge(geom))
|
||||
if geomList:
|
||||
return geomList
|
||||
|
||||
def areConnected(seg1, seg2):
|
||||
'''
|
||||
Checks if two segments share an endpoint.
|
||||
returns a new linesegment if connected or original seg1 if not
|
||||
'''
|
||||
l1 = [seg1.StartPoint, seg1.EndPoint]
|
||||
l2 = [seg2.StartPoint, seg2.EndPoint]
|
||||
l3 = [v1 for v1 in l1 for v2 in l2 if PathGeom.pointsCoincide (v1, v2, error=0.01)]
|
||||
# for v1 in l1:
|
||||
# for v2 in l2:
|
||||
# if PathGeom.pointsCoincide(v1, v2):
|
||||
# l3.append(v1)
|
||||
#l3 = [value for value in l1 if value in l2]
|
||||
print('l1: {} l2: {} l3: {}'.format(l1,l2,l3))
|
||||
if len(l3) == 0: # no connection
|
||||
print('no connection')
|
||||
return seg1
|
||||
elif len(l3) == 1: # extend chain
|
||||
print('one vert')
|
||||
p1 = l1[0] if l1[0] == l3[0] else l1[1]
|
||||
p2 = l2[0] if l2[0] == l3[0] else l2[1]
|
||||
return Part.LineSegment(p1, p2)
|
||||
else: # loop
|
||||
print('loop')
|
||||
return None
|
||||
|
||||
def chains(seglist):
|
||||
'''
|
||||
iterates through segements and builds a list of chains
|
||||
'''
|
||||
|
||||
chains = []
|
||||
while len(seglist) > 0:
|
||||
cur_seg = seglist.pop(0)
|
||||
cur_chain = [cur_seg]
|
||||
remaining = []
|
||||
tempseg = cur_seg # tempseg is a linesegment from first vertex to last in curchain
|
||||
for i, seg in enumerate(seglist):
|
||||
|
||||
ac = areConnected(tempseg, seg)
|
||||
if ac != tempseg:
|
||||
cur_chain.append(seg)
|
||||
if ac is None:
|
||||
remaining.extend(seglist[i+1:])
|
||||
break
|
||||
else:
|
||||
tempseg = ac
|
||||
|
||||
#print("c: {}".format(cur_chain))
|
||||
|
||||
chains.append(cur_chain)
|
||||
seglist = remaining
|
||||
|
||||
return chains
|
||||
|
||||
def cutWire(w):
|
||||
path = []
|
||||
maw = ovd.MedialAxisWalk( vd.getGraph() )
|
||||
toolpath = maw.walk()
|
||||
for chain in toolpath:
|
||||
path.append(Path.Command("G0 Z{}".format(safeheight)))
|
||||
p = chain[0][0][0]
|
||||
z = -(chain[0][0][1])
|
||||
|
||||
path.append(Path.Command("G0 X{} Y{} Z{}".format(p.x, p.y, safeheight)))
|
||||
|
||||
for step in chain:
|
||||
for point in step:
|
||||
p = point[0]
|
||||
z = calculate_depth(-(point[1]))
|
||||
path.append(Path.Command("G1 X{} Y{} Z{} F{}".format(p.x, p.y, z, obj.ToolController.HorizFeed.Value)))
|
||||
|
||||
path.append(Path.Command("G0 Z{}".format(safeheight)))
|
||||
p = w.Vertexes[0]
|
||||
path.append(Path.Command("G0 Z{}".format(obj.SafeHeight.Value)))
|
||||
path.append(Path.Command("G0 X{} Y{} Z{}".format(p.X, p.Y, obj.SafeHeight.Value)))
|
||||
# print('\/ \/ \/')
|
||||
# print(p.Point)
|
||||
c = Path.Command("G1 X{} Y{} Z{} F{}".format(p.X, p.Y, p.Z, obj.ToolController.HorizFeed.Value))
|
||||
# print(c)
|
||||
# print('/\ /\ /\ ')
|
||||
path.append(c)
|
||||
#path.append(Path.Command("G1 X{} Y{} Z{} F{}".format(p.X, p.Y, p.Z, obj.ToolController.HorizFeed.Value)))
|
||||
for vert in w.Vertexes[1:]:
|
||||
path.append(Path.Command("G1 X{} Y{} Z{} F{}".format(vert.X, vert.Y, vert.Z, obj.ToolController.HorizFeed.Value)))
|
||||
|
||||
path.append(Path.Command("G0 Z{}".format(obj.SafeHeight.Value)))
|
||||
return path
|
||||
|
||||
pathlist = []
|
||||
bins = 120 # int bins = number of bins for grid-search (affects performance, should not affect correctness)
|
||||
pathlist.append(Path.Command("(starting)"))
|
||||
for f in Faces:
|
||||
#unitcircle = f.BoundBox.DiagonalLength/2
|
||||
print('unitcircle: {}'.format(unitcircle))
|
||||
vd = ovd.VoronoiDiagram(200, bins)
|
||||
vd.set_silent(True) # suppress Warnings!
|
||||
wires = f.Wires
|
||||
insert_many_wires(vd, wires)
|
||||
pi = ovd.PolygonInterior( True )
|
||||
vd.filter_graph(pi)
|
||||
ma = ovd.MedialAxis()
|
||||
vd.filter_graph(ma)
|
||||
pathlist.extend(buildMedial( vd )) # the actual cutting g-code
|
||||
vd = Path.Voronoi()
|
||||
insert_many_wires(vd, f.Wires)
|
||||
|
||||
vd.construct()
|
||||
# vd.colorExterior(1)
|
||||
# vd.colorTwins(2)
|
||||
|
||||
for e in vd.Edges:
|
||||
e.Color = 0 if e.isPrimary() else 5
|
||||
vd.colorExterior(1)
|
||||
vd.colorExterior(4, lambda v: not f.isInside(v.toGeom(), 0.01, True)) # should derive tolerance from geometry
|
||||
vd.colorColinear(3)
|
||||
vd.colorTwins(2)
|
||||
|
||||
edgelist = getEdges(vd)
|
||||
# for e in edgelist:
|
||||
# Part.show(e.toShape())
|
||||
|
||||
# for e in [e_ for e_ in vd.Edges if e_.Color == 2]:
|
||||
# print(e.getDistances())
|
||||
# p1 = e.Vertices[0].toGeom(calculate_depth(0-e.getDistances()[0]))
|
||||
# p2 = e.Vertices[-1].toGeom(calculate_depth(0-e.getDistances()[-1]))
|
||||
# edgelist.append(Part.makeLine(p1, p2))
|
||||
|
||||
# vlist = []
|
||||
# for v, r in zip(e.Vertices, e.getDistances()):
|
||||
# p = v.toGeom()
|
||||
# p.z = calculate_depth(r)
|
||||
# vlist.append(p)
|
||||
# l = Part.makeLine(vlist[0], vlist[-1])
|
||||
# edgelist.append(l)
|
||||
|
||||
# for s in Part.sortEdges(edgelist):
|
||||
# pathlist.extend(cutWire(Part.Wire(s)))
|
||||
|
||||
for chain in chains(edgelist):
|
||||
print('chain length {}'.format(len(chain)))
|
||||
print(chain)
|
||||
Part.show(Part.Wire([e.toShape() for e in chain]))
|
||||
|
||||
#pathlist.extend(sortedWires) # the actual cutting g-code
|
||||
|
||||
self.commandlist = pathlist
|
||||
|
||||
|
||||
|
||||
def opExecute(self, obj):
|
||||
'''opExecute(obj) ... process engraving operation'''
|
||||
PathLog.track()
|
||||
# Openvoronoi must be installed
|
||||
try:
|
||||
import openvoronoi as ovd
|
||||
except:
|
||||
FreeCAD.Console.PrintError(
|
||||
translate("Path_Vcarve", "This operation requires OpenVoronoi to be installed.") + "\n")
|
||||
return
|
||||
|
||||
|
||||
job = PathUtils.findParentJob(obj)
|
||||
|
||||
jobshapes = []
|
||||
zValues = self.getZValues(obj)
|
||||
|
||||
if obj.ToolController.Tool.ToolType != 'Engraver':
|
||||
FreeCAD.Console.PrintError(
|
||||
@@ -199,62 +314,23 @@ class ObjectVcarve(PathEngraveBase.ObjectOp):
|
||||
translate("Path_Vcarve", "Engraver Cutting Edge Angle must be < 180 degrees.") + "\n")
|
||||
return
|
||||
try:
|
||||
if len(self.model) == 1 and self.model[0].isDerivedFrom('Sketcher::SketchObject') or \
|
||||
if obj.Base:
|
||||
PathLog.track()
|
||||
for base in obj.Base:
|
||||
faces = []
|
||||
for sub in base[1]:
|
||||
shape = getattr(base[0].Shape, sub)
|
||||
if isinstance(shape, Part.Face):
|
||||
faces.append(shape)
|
||||
|
||||
modelshape = Part.makeCompound(faces)
|
||||
|
||||
elif len(self.model) == 1 and self.model[0].isDerivedFrom('Sketcher::SketchObject') or \
|
||||
self.model[0].isDerivedFrom('Part::Part2DObject'):
|
||||
PathLog.track()
|
||||
|
||||
# self.commandlist.append(Path.Command('G0', {'Z': obj.ClearanceHeight.Value, 'F': self.vertRapid}))
|
||||
|
||||
# we only consider the outer wire if this is a Face
|
||||
modelshape = self.model[0].Shape
|
||||
modelshape.tessellate(0.01)
|
||||
self.buildPathMedial(obj, modelshape.Faces, zValues, modelshape.BoundBox.DiagonalLength/2)
|
||||
# self.wires = wires
|
||||
|
||||
# elif obj.Base:
|
||||
# PathLog.track()
|
||||
# wires = []
|
||||
# for base, subs in obj.Base:
|
||||
# edges = []
|
||||
# basewires = []
|
||||
# for feature in subs:
|
||||
# sub = base.Shape.getElement(feature)
|
||||
# if type(sub) == Part.Edge:
|
||||
# edges.append(sub)
|
||||
# elif sub.Wires:
|
||||
# basewires.extend(sub.Wires)
|
||||
# else:
|
||||
# basewires.append(Part.Wire(sub.Edges))
|
||||
|
||||
# for edgelist in Part.sortEdges(edges):
|
||||
# basewires.append(Part.Wire(edgelist))
|
||||
|
||||
# wires.extend(basewires)
|
||||
# self.buildpathocc(obj, wires, zValues)
|
||||
# self.wires = wires
|
||||
# elif not obj.BaseShapes:
|
||||
# PathLog.track()
|
||||
# if not obj.Base and not obj.BaseShapes:
|
||||
# for base in self.model:
|
||||
# PathLog.track(base.Label)
|
||||
# if base.isDerivedFrom('Part::Part2DObject'):
|
||||
# jobshapes.append(base)
|
||||
|
||||
# if not jobshapes:
|
||||
# raise ValueError(translate('PathVcarve', "Unknown baseobject type for engraving (%s)") % (obj.Base))
|
||||
|
||||
# if obj.BaseShapes or jobshapes:
|
||||
# PathLog.track()
|
||||
# wires = []
|
||||
# for shape in obj.BaseShapes + jobshapes:
|
||||
# PathLog.track(shape.Label)
|
||||
# shapeWires = shape.Shape.Wires
|
||||
# self.buildpathocc(obj, shapeWires, zValues)
|
||||
# wires.extend(shapeWires)
|
||||
# self.wires = wires
|
||||
# # the last command is a move to clearance, which is automatically added by PathOp
|
||||
# if self.commandlist:
|
||||
# self.commandlist.pop()
|
||||
self.buildPathMedial(obj, modelshape.Faces)
|
||||
|
||||
except Exception as e:
|
||||
PathLog.error(e)
|
||||
@@ -266,13 +342,14 @@ class ObjectVcarve(PathEngraveBase.ObjectOp):
|
||||
job = PathUtils.findParentJob(obj)
|
||||
self.opSetDefaultValues(obj, job)
|
||||
|
||||
def SetupProperties():
|
||||
return [ "Discretize" ]
|
||||
|
||||
def Create(name, obj = None):
|
||||
def SetupProperties():
|
||||
return ["Discretize"]
|
||||
|
||||
|
||||
def Create(name, obj=None):
|
||||
'''Create(name) ... Creates and returns a Vcarve operation.'''
|
||||
if obj is None:
|
||||
obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", name)
|
||||
proxy = ObjectVcarve(obj, name)
|
||||
return obj
|
||||
|
||||
|
||||
@@ -27,7 +27,6 @@ import FreeCADGui
|
||||
import PathScripts.PathVcarve as PathVcarve
|
||||
import PathScripts.PathLog as PathLog
|
||||
import PathScripts.PathOpGui as PathOpGui
|
||||
import PathScripts.PathSelection as PathSelection
|
||||
import PathScripts.PathUtils as PathUtils
|
||||
|
||||
from PySide import QtCore, QtGui
|
||||
@@ -43,9 +42,11 @@ if False:
|
||||
else:
|
||||
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
|
||||
|
||||
|
||||
def translate(context, text, disambig=None):
|
||||
return QtCore.QCoreApplication.translate(context, text, disambig)
|
||||
|
||||
|
||||
class TaskPanelBaseGeometryPage(PathOpGui.TaskPanelBaseGeometryPage):
|
||||
'''Enhanced base geometry page to also allow special base objects.'''
|
||||
|
||||
@@ -59,10 +60,10 @@ class TaskPanelBaseGeometryPage(PathOpGui.TaskPanelBaseGeometryPage):
|
||||
job = PathUtils.findParentJob(self.obj)
|
||||
base = job.Proxy.resourceClone(job, sel.Object)
|
||||
if not base:
|
||||
PathLog.notice((translate("Path", "%s is not a Base Model object of the job %s")+"\n") % (sel.Object.Label, job.Label))
|
||||
PathLog.notice((translate("Path", "%s is not a Base Model object of the job %s") + "\n") % (sel.Object.Label, job.Label))
|
||||
continue
|
||||
if base in shapes:
|
||||
PathLog.notice((translate("Path", "Base shape %s already in the list")+"\n") % (sel.Object.Label))
|
||||
PathLog.notice((translate("Path", "Base shape %s already in the list") + "\n") % (sel.Object.Label))
|
||||
continue
|
||||
if base.isDerivedFrom('Part::Part2DObject'):
|
||||
if sel.HasSubObjects:
|
||||
@@ -74,7 +75,7 @@ class TaskPanelBaseGeometryPage(PathOpGui.TaskPanelBaseGeometryPage):
|
||||
self.obj.Proxy.addBase(self.obj, base, sub)
|
||||
else:
|
||||
# when adding an entire shape to BaseShapes we can take its sub shapes out of Base
|
||||
self.obj.Base = [(p,el) for p,el in self.obj.Base if p != base]
|
||||
self.obj.Base = [(p, el) for p, el in self.obj.Base if p != base]
|
||||
shapes.append(base)
|
||||
self.obj.BaseShapes = shapes
|
||||
added = True
|
||||
@@ -108,6 +109,7 @@ class TaskPanelBaseGeometryPage(PathOpGui.TaskPanelBaseGeometryPage):
|
||||
self.obj.BaseShapes = shapes
|
||||
return self.super().updateBase()
|
||||
|
||||
|
||||
class TaskPanelOpPage(PathOpGui.TaskPanelPage):
|
||||
'''Page controller class for the Vcarve operation.'''
|
||||
|
||||
@@ -119,17 +121,21 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage):
|
||||
'''getFields(obj) ... transfers values from UI to obj's proprties'''
|
||||
if obj.Discretize != self.form.discretize.value():
|
||||
obj.Discretize = self.form.discretize.value()
|
||||
if obj.Threshold != self.form.threshold.value():
|
||||
obj.Threshold = self.form.threshold.value()
|
||||
self.updateToolController(obj, self.form.toolController)
|
||||
|
||||
def setFields(self, obj):
|
||||
'''setFields(obj) ... transfers obj's property values to UI'''
|
||||
self.form.discretize.setValue(obj.Discretize)
|
||||
self.form.threshold.setValue(obj.Threshold)
|
||||
self.setupToolController(obj, self.form.toolController)
|
||||
|
||||
def getSignalsForUpdate(self, obj):
|
||||
'''getSignalsForUpdate(obj) ... return list of signals for updating obj'''
|
||||
signals = []
|
||||
signals.append(self.form.discretize.editingFinished)
|
||||
signals.append(self.form.threshold.editingFinished)
|
||||
signals.append(self.form.toolController.currentIndexChanged)
|
||||
return signals
|
||||
|
||||
@@ -137,11 +143,9 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage):
|
||||
'''taskPanelBaseGeometryPage(obj, features) ... return page for adding base geometries.'''
|
||||
return TaskPanelBaseGeometryPage(obj, features)
|
||||
|
||||
Command = PathOpGui.SetupOperation('Vcarve',
|
||||
PathVcarve.Create,
|
||||
TaskPanelOpPage,
|
||||
'Path-Vcarve',
|
||||
QtCore.QT_TRANSLATE_NOOP("PathVcarve", "Vcarve"),
|
||||
|
||||
Command = PathOpGui.SetupOperation('Vcarve', PathVcarve.Create, TaskPanelOpPage,
|
||||
'Path-Vcarve', QtCore.QT_TRANSLATE_NOOP("PathVcarve", "Vcarve"),
|
||||
QtCore.QT_TRANSLATE_NOOP("PathVcarve", "Creates a medial line engraving path"),
|
||||
PathVcarve.SetupProperties)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user