Moved dressups into Path.Dressup module

This commit is contained in:
Markus Lampert
2022-08-10 22:48:43 -07:00
parent 7fe03f2b78
commit 289c1f8c87
28 changed files with 86 additions and 503 deletions

View File

@@ -30,6 +30,27 @@ SET(PathPython_SRCS
Path/Log.py
)
SET(PathPythonDressup_SRCS
Path/Dressup/__init__.py
Path/Dressup/Utils.py
Path/Dressup/PathBoundary.py
Path/Dressup/Tags.py
)
SET(PathPythonDressupGui_SRCS
Path/Dressup/Gui/__init__.py
Path/Dressup/Gui/AxisMap.py
Path/Dressup/Gui/Dogbone.py
Path/Dressup/Gui/Dragknife.py
Path/Dressup/Gui/LeadInOut.py
Path/Dressup/Gui/PathBoundary.py
Path/Dressup/Gui/Preferences.py
Path/Dressup/Gui/RampEntry.py
Path/Dressup/Gui/Tags.py
Path/Dressup/Gui/TagPreferences.py
Path/Dressup/Gui/ZCorrect.py
)
SET(PathPythonOp_SRCS
Path/Op/__init__.py
Path/Op/Adaptive.py
@@ -112,19 +133,6 @@ SET(PathScripts_SRCS
PathScripts/PathCustomGui.py
PathScripts/PathDeburr.py
PathScripts/PathDeburrGui.py
PathScripts/PathDressup.py
PathScripts/PathDressupAxisMap.py
PathScripts/PathDressupDogbone.py
PathScripts/PathDressupDragknife.py
PathScripts/PathDressupHoldingTags.py
PathScripts/PathDressupLeadInOut.py
PathScripts/PathDressupPathBoundary.py
PathScripts/PathDressupPathBoundaryGui.py
PathScripts/PathDressupRampEntry.py
PathScripts/PathDressupTag.py
PathScripts/PathDressupTagGui.py
PathScripts/PathDressupTagPreferences.py
PathScripts/PathDressupZCorrect.py
PathScripts/PathDrilling.py
PathScripts/PathDrillingGui.py
PathScripts/PathEngrave.py
@@ -159,7 +167,6 @@ SET(PathScripts_SRCS
PathScripts/PathPocketShapeGui.py
PathScripts/PathPreferences.py
PathScripts/PathPreferencesAdvanced.py
PathScripts/PathPreferencesPathDressup.py
PathScripts/PathPreferencesPathJob.py
PathScripts/PathProbe.py
PathScripts/PathProbeGui.py
@@ -338,6 +345,8 @@ SET(Path_Data
SET(all_files
${PathScripts_SRCS}
${PathPython_SRCS}
${PathPythonDressup_SRCS}
${PathPythonDressupGui_SRCS}
${PathPythonOp_SRCS}
${PathPythonOpGui_SRCS}
${PathPythonPost_SRCS}
@@ -384,6 +393,20 @@ INSTALL(
Mod/Path/Path
)
INSTALL(
FILES
${PathPythonDressup_SRCS}
DESTINATION
Mod/Path/Path/Dressup
)
INSTALL(
FILES
${PathPythonDressupGui_SRCS}
DESTINATION
Mod/Path/Path/Dressup/Gui
)
INSTALL(
FILES
${PathPythonOp_SRCS}

View File

@@ -31,7 +31,7 @@ __doc__ = "Generates the helix for a single spot targetshape"
__contributors__ = "russ4262 (Russell Johnson), Lorenz Hüdepohl"
if True:
if False:
Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule())
Path.Log.trackModule(Path.Log.thisModule())
else:

View File

@@ -59,7 +59,8 @@ class PathWorkbench(Workbench):
global PathCommandGroup
# Add preferences pages - before loading PathGui to properly order pages of Path group
from PathScripts import PathPreferencesPathJob, PathPreferencesPathDressup
from PathScripts import PathPreferencesPathJob
import Path.Dressup.Gui.Preferences as PathPreferencesPathDressup
translate = FreeCAD.Qt.translate

View File

@@ -298,19 +298,19 @@ class CommandPathDressup:
# everything ok!
FreeCAD.ActiveDocument.openTransaction("Create Dress-up")
FreeCADGui.addModule("PathScripts.PathDressupAxisMap")
FreeCADGui.addModule("Path.Dressup.Gui.AxisMap")
FreeCADGui.addModule("PathScripts.PathUtils")
FreeCADGui.doCommand(
'obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", "AxisMapDressup")'
)
FreeCADGui.doCommand("PathScripts.PathDressupAxisMap.ObjectDressup(obj)")
FreeCADGui.doCommand("Path.Dressup.Gui.AxisMap.ObjectDressup(obj)")
FreeCADGui.doCommand("base = FreeCAD.ActiveDocument." + selection[0].Name)
FreeCADGui.doCommand("job = PathScripts.PathUtils.findParentJob(base)")
FreeCADGui.doCommand("obj.Base = base")
FreeCADGui.doCommand("obj.Radius = 45")
FreeCADGui.doCommand("job.Proxy.addOperation(obj, base)")
FreeCADGui.doCommand(
"obj.ViewObject.Proxy = PathScripts.PathDressupAxisMap.ViewProviderDressup(obj.ViewObject)"
"obj.ViewObject.Proxy = Path.Dressup.Gui.AxisMap.ViewProviderDressup(obj.ViewObject)"
)
FreeCADGui.doCommand(
"Gui.ActiveDocument.getObject(base.Name).Visibility = False"

View File

@@ -26,7 +26,7 @@ from PySide import QtCore
from PySide.QtCore import QT_TRANSLATE_NOOP
import FreeCAD
import Path
import PathScripts.PathDressup as PathDressup
import Path.Dressup.Utils as PathDressup
import PathScripts.PathGeom as PathGeom
import PathScripts.PathUtil as PathUtil
import PathScripts.PathUtils as PathUtils
@@ -1394,9 +1394,9 @@ class CommandDressupDogbone(object):
# everything ok!
FreeCAD.ActiveDocument.openTransaction("Create Dogbone Dress-up")
FreeCADGui.addModule("PathScripts.PathDressupDogbone")
FreeCADGui.addModule("Path.Dressup.Gui.Dogbone")
FreeCADGui.doCommand(
"PathScripts.PathDressupDogbone.Create(FreeCAD.ActiveDocument.%s)"
"Path.Dressup.Gui.Dogbone.Create(FreeCAD.ActiveDocument.%s)"
% baseObject.Name
)
# FreeCAD.ActiveDocument.commitTransaction() # Final `commitTransaction()` called via TaskPanel.accept()

View File

@@ -639,18 +639,18 @@ class CommandDressupDragknife:
# everything ok!
FreeCAD.ActiveDocument.openTransaction("Create Dress-up")
FreeCADGui.addModule("PathScripts.PathDressupDragknife")
FreeCADGui.addModule("Path.Dressup.Gui.Dragknife")
FreeCADGui.addModule("PathScripts.PathUtils")
FreeCADGui.doCommand(
'obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython","DragknifeDressup")'
)
FreeCADGui.doCommand("PathScripts.PathDressupDragknife.ObjectDressup(obj)")
FreeCADGui.doCommand("Path.Dressup.Gui.Dragknife.ObjectDressup(obj)")
FreeCADGui.doCommand("base = FreeCAD.ActiveDocument." + selection[0].Name)
FreeCADGui.doCommand("job = PathScripts.PathUtils.findParentJob(base)")
FreeCADGui.doCommand("obj.Base = base")
FreeCADGui.doCommand("job.Proxy.addOperation(obj, base)")
FreeCADGui.doCommand(
"obj.ViewObject.Proxy = PathScripts.PathDressupDragknife.ViewProviderDressup(obj.ViewObject)"
"obj.ViewObject.Proxy = Path.Dressup.Gui.Dragknife.ViewProviderDressup(obj.ViewObject)"
)
FreeCADGui.doCommand(
"Gui.ActiveDocument.getObject(base.Name).Visibility = False"

View File

@@ -26,7 +26,7 @@ from __future__ import print_function
import FreeCAD
import FreeCADGui
import Path
import PathScripts.PathDressup as PathDressup
import Path.Dressup.Utils as PathDressup
import PathScripts.PathGeom as PathGeom
import PathScripts.PathUtils as PathUtils
import math
@@ -749,13 +749,13 @@ class CommandPathDressupLeadInOut:
# everything ok!
FreeCAD.ActiveDocument.openTransaction("Create LeadInOut Dressup")
FreeCADGui.addModule("PathScripts.PathDressupLeadInOut")
FreeCADGui.addModule("Path.Dressup.Gui.LeadInOut")
FreeCADGui.addModule("PathScripts.PathUtils")
FreeCADGui.doCommand(
'obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", "LeadInOutDressup")'
)
FreeCADGui.doCommand(
"dbo = PathScripts.PathDressupLeadInOut.ObjectDressup(obj)"
"dbo = Path.Dressup.Gui.LeadInOut.ObjectDressup(obj)"
)
FreeCADGui.doCommand("base = FreeCAD.ActiveDocument." + selection[0].Name)
FreeCADGui.doCommand("job = PathScripts.PathUtils.findParentJob(base)")
@@ -763,7 +763,7 @@ class CommandPathDressupLeadInOut:
FreeCADGui.doCommand("job.Proxy.addOperation(obj, base)")
FreeCADGui.doCommand("dbo.setup(obj)")
FreeCADGui.doCommand(
"obj.ViewObject.Proxy = PathScripts.PathDressupLeadInOut.ViewProviderDressup(obj.ViewObject)"
"obj.ViewObject.Proxy = Path.Dressup.Gui.LeadInOut.ViewProviderDressup(obj.ViewObject)"
)
FreeCADGui.doCommand(
"Gui.ActiveDocument.getObject(base.Name).Visibility = False"

View File

@@ -25,8 +25,8 @@ from PySide.QtCore import QT_TRANSLATE_NOOP
import FreeCAD
import FreeCADGui
import Path
import Path.Dressup.PathBoundary as PathDressupPathBoundary
import PathGui as PGui # ensure Path/Gui/Resources are loaded
import PathScripts.PathDressupPathBoundary as PathDressupPathBoundary
if False:
Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule())
@@ -289,9 +289,9 @@ class CommandPathDressupPathBoundary:
# everything ok!
FreeCAD.ActiveDocument.openTransaction("Create Path Boundary Dress-up")
FreeCADGui.addModule("PathScripts.PathDressupPathBoundaryGui")
FreeCADGui.addModule("Path.Dressup.Gui.PathBoundary")
FreeCADGui.doCommand(
"PathScripts.PathDressupPathBoundaryGui.Create(App.ActiveDocument.%s)"
"Path.Dressup.Gui.PathBoundary.Create(App.ActiveDocument.%s)"
% baseObject.Name
)
# FreeCAD.ActiveDocument.commitTransaction() # Final `commitTransaction()` called via TaskPanel.accept()

View File

@@ -24,7 +24,7 @@ from PathScripts import PathUtils
from PySide.QtCore import QT_TRANSLATE_NOOP
import FreeCAD
import Path
import PathScripts.PathDressup as PathDressup
import Path.Dressup.Utils as PathDressup
import PathScripts.PathGeom as PathGeom
import math
@@ -936,20 +936,20 @@ class CommandPathDressupRampEntry:
# everything ok!
FreeCAD.ActiveDocument.openTransaction("Create RampEntry Dress-up")
FreeCADGui.addModule("PathScripts.PathDressupRampEntry")
FreeCADGui.addModule("Path.Dressup.Gui.RampEntry")
FreeCADGui.addModule("PathScripts.PathUtils")
FreeCADGui.doCommand(
'obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", "RampEntryDressup")'
)
FreeCADGui.doCommand(
"dbo = PathScripts.PathDressupRampEntry.ObjectDressup(obj)"
"dbo = Path.Dressup.Gui.RampEntry.ObjectDressup(obj)"
)
FreeCADGui.doCommand("base = FreeCAD.ActiveDocument." + selection[0].Name)
FreeCADGui.doCommand("job = PathScripts.PathUtils.findParentJob(base)")
FreeCADGui.doCommand("obj.Base = base")
FreeCADGui.doCommand("job.Proxy.addOperation(obj, base)")
FreeCADGui.doCommand(
"obj.ViewObject.Proxy = PathScripts.PathDressupRampEntry.ViewProviderDressup(obj.ViewObject)"
"obj.ViewObject.Proxy = Path.Dressup.Gui.RampEntry.ViewProviderDressup(obj.ViewObject)"
)
FreeCADGui.doCommand(
"Gui.ActiveDocument.getObject(base.Name).Visibility = False"

View File

@@ -22,8 +22,8 @@
import FreeCAD
import Path
import Path.Dressup.Gui.Preferences as PathPreferencesPathDressup
import PathScripts.PathPreferences as PathPreferences
import PathScripts.PathPreferencesPathDressup as PathPreferencesPathDressup
if False:
Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule())

View File

@@ -26,8 +26,8 @@ from pivy import coin
import FreeCAD
import FreeCADGui
import Path
import Path.Dressup.Tags as PathDressupTag
import PathGui as PGui # ensure Path/Gui/Resources are loaded
import PathScripts.PathDressupHoldingTags as PathDressupTag
import PathScripts.PathGeom as PathGeom
import PathScripts.PathGetPoint as PathGetPoint
import PathScripts.PathPreferences as PathPreferences
@@ -588,9 +588,9 @@ class CommandPathDressupTag:
# everything ok!
FreeCAD.ActiveDocument.openTransaction("Create Tag Dress-up")
FreeCADGui.addModule("PathScripts.PathDressupTagGui")
FreeCADGui.addModule("Path.Dressup.Gui.Tags")
FreeCADGui.doCommand(
"PathScripts.PathDressupTagGui.Create(App.ActiveDocument.%s)"
"Path.Dressup.Gui.Tags.Create(App.ActiveDocument.%s)"
% baseObject.Name
)
# FreeCAD.ActiveDocument.commitTransaction() # Final `commitTransaction()` called via TaskPanel.accept()

View File

@@ -380,15 +380,15 @@ class CommandPathDressup:
# everything ok!
FreeCAD.ActiveDocument.openTransaction("Create Dress-up")
FreeCADGui.addModule("PathScripts.PathDressupZCorrect")
FreeCADGui.addModule("Path.Dressup.Gui.ZCorrect")
FreeCADGui.addModule("PathScripts.PathUtils")
FreeCADGui.doCommand(
'obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", "ZCorrectDressup")'
)
FreeCADGui.doCommand("PathScripts.PathDressupZCorrect.ObjectDressup(obj)")
FreeCADGui.doCommand("Path.Dressup.Gui.ZCorrect.ObjectDressup(obj)")
FreeCADGui.doCommand("obj.Base = FreeCAD.ActiveDocument." + selection[0].Name)
FreeCADGui.doCommand(
"PathScripts.PathDressupZCorrect.ViewProviderDressup(obj.ViewObject)"
"Path.Dressup.Gui.ZCorrect.ViewProviderDressup(obj.ViewObject)"
)
FreeCADGui.doCommand("PathScripts.PathUtils.addToJob(obj)")
FreeCADGui.doCommand(

View File

@@ -23,7 +23,7 @@
from PySide.QtCore import QT_TRANSLATE_NOOP
import FreeCAD
import Path
import PathScripts.PathDressup as PathDressup
import Path.Dressup.Utils as PathDressup
import PathScripts.PathGeom as PathGeom
import PathScripts.PathStock as PathStock
import PathScripts.PathUtil as PathUtil

View File

@@ -20,12 +20,12 @@
# * *
# ***************************************************************************
from PathScripts.PathDressupTagPreferences import HoldingTagPreferences
from Path.Dressup.Gui.TagPreferences import HoldingTagPreferences
from PathScripts.PathUtils import waiting_effects
from PySide.QtCore import QT_TRANSLATE_NOOP
import FreeCAD
import Path
import PathScripts.PathDressup as PathDressup
import Path.Dressup.Utils as PathDressup
import PathScripts.PathGeom as PathGeom
import PathScripts.PathUtil as PathUtil
import PathScripts.PathUtils as PathUtils

View File

View File

@@ -41,7 +41,7 @@ from PySide.QtCore import QT_TRANSLATE_NOOP
LOG_MODULE = Path.Log.thisModule()
if True:
if False:
Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule())
Path.Log.trackModule(Path.Log.thisModule())
else:

View File

@@ -161,7 +161,7 @@ class _ToggleOperation:
return False
try:
for sel in FreeCADGui.Selection.getSelectionEx():
selProxy = PathScripts.PathDressup.baseOp(sel.Object).Proxy
selProxy = Path.Dressup.Utils.baseOp(sel.Object).Proxy
if not isinstance(
selProxy, PathScripts.PathOp.ObjectOp
) and not isinstance(selProxy, PathScripts.PathArray.ObjectArray):
@@ -172,7 +172,7 @@ class _ToggleOperation:
def Activated(self):
for sel in FreeCADGui.Selection.getSelectionEx():
op = PathScripts.PathDressup.baseOp(sel.Object)
op = Path.Dressup.Utils.baseOp(sel.Object)
op.Active = not op.Active
op.ViewObject.Visibility = op.Active

View File

@@ -30,7 +30,7 @@ import Path
import FreeCAD
from PathScripts.PathGeom import CmdMoveRapid, CmdMoveAll, CmdMoveDrill
if True:
if False:
Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule())
Path.Log.trackModule(Path.Log.thisModule())
else:

View File

@@ -24,7 +24,7 @@ import FreeCAD
import FreeCADGui
import Path
import PathScripts
from PathScripts.PathDressup import toolController
from Path.Dressup.Utils import toolController
from PySide import QtCore
import math
import random

View File

@@ -1,123 +0,0 @@
# -*- coding: utf-8 -*-
# ***************************************************************************
# * Copyright (c) 2022 sliptonic <shopinthewoods@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 *
# * *
# ***************************************************************************
import FreeCAD
import Path
import PathScripts.PathGeom as PathGeom
import PathScripts.PathLanguage as PathLanguage
import PathScripts.Path.Log as Path.Log
import math
class Kink (object):
'''A Kink represents the angle at which two moves connect.
A positive kink angle represents a move to the left, and a negative angle represents a move to the right.'''
def __init__(self, m0, m1):
if m1 is None:
m1 = m0[1]
m0 = m0[0]
self.m0 = m0
self.m1 = m1
self.t0 = m0.anglesOfTangents()[1]
self.t1 = m1.anglesOfTangents()[0]
def deflection(self):
'''deflection() ... returns the tangential difference of the two edges at their intersection'''
return PathGeom.normalizeAngle(self.t1 - self.t0)
def normAngle(self):
'''normAngle() ... returns the angle opposite between the two tangents'''
# The normal angle is perpendicular to the "average tangent" of the kink. The question
# is into which direction to turn. One lies in the center between the two edges and the
# other is opposite to that. As it turns out, the magnitude of the tangents tell it all.
if self.t0 > self.t1:
return PathGeom.normalizeAngle((self.t0 + self.t1 + math.pi) / 2)
return PathGeom.normalizeAngle((self.t0 + self.t1 - math.pi) / 2)
def position(self):
'''position() ... position of the edge's intersection'''
return self.m0.positionEnd()
def x(self):
return self.position().x
def y(self):
return self.position().y
def __repr__(self):
return f"({self.x():.4f}, {self.y():.4f})[t0={180*self.t0/math.pi:.2f}, t1={180*self.t1/math.pi:.2f}, deflection={180*self.deflection()/math.pi:.2f}, normAngle={180*self.normAngle()/math.pi:.2f}]"
def createKinks(maneuver):
k = []
moves = maneuver.getMoves()
if moves:
move0 = moves[0]
prev = move0
for m in moves[1:]:
k.append(Kink(prev, m))
prev = m
if PathGeom.pointsCoincide(move0.positionBegin(), prev.positionEnd()):
k.append(Kink(prev, move0))
return k
def findDogboneKinks(maneuver, threshold):
'''findDogboneKinks(maneuver, threshold) ... return all kinks fitting the criteria.
A positive threshold angle returns all kinks on the right side, and a negative all kinks on the left side'''
if threshold > 0:
return [k for k in createKinks(maneuver) if k.deflection() > threshold]
if threshold < 0:
return [k for k in createKinks(maneuver) if k.deflection() < threshold]
# you asked for it ...
return createKinks(maneuver)
class Bone (object):
'''A Bone holds all the information of a bone and the kink it is attached to'''
def __init__(self, kink, angle, instr=None):
self.kink = kink
self.angle = angle
self.instr = [] if instr is None else instr
def addInstruction(self, instr):
self.instr.append(instr)
def kink_to_path(kink, g0=False):
return Path.Path([PathLanguage.instruction_to_command(instr) for instr in [kink.m0, kink.m1]])
def bone_to_path(bone, g0=False):
kink = bone.kink
cmds = []
if g0 and not PathGeom.pointsCoincide(kink.m0.positionBegin(), FreeCAD.Vector(0, 0, 0)):
pos = kink.m0.positionBegin()
param = {}
if not PathGeom.isRoughly(pos.x, 0):
param['X'] = pos.x
if not PathGeom.isRoughly(pos.y, 0):
param['Y'] = pos.y
cmds.append(Path.Command('G0', param))
for instr in [kink.m0, bone.instr[0], bone.instr[1], kink.m1]:
cmds.append(PathLanguage.instruction_to_command(instr))
return Path.Path(cmds)

View File

@@ -1,318 +0,0 @@
# -*- coding: utf-8 -*-
# ***************************************************************************
# * Copyright (c) 2017 sliptonic <shopinthewoods@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 *
# * *
# ***************************************************************************
from PathScripts.PathDressupTagPreferences import HoldingTagPreferences
from PySide.QtCore import QT_TRANSLATE_NOOP
import FreeCAD
import Path
import PathScripts.PathDressup as PathDressup
import PathScripts.PathGeom as PathGeom
import PathScripts.PathUtils as PathUtils
import math
# lazily loaded modules
from lazy_loader.lazy_loader import LazyLoader
DraftGeomUtils = LazyLoader("DraftGeomUtils", globals(), "DraftGeomUtils")
Part = LazyLoader("Part", globals(), "Part")
if False:
Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule())
Path.Log.trackModule(Path.Log.thisModule())
else:
Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule())
translate = FreeCAD.Qt.translate
MaxInt = 99999999999999
class TagSolid:
def __init__(self, proxy, z, R):
self.proxy = proxy
self.z = z
self.toolRadius = R
self.angle = math.fabs(proxy.obj.Angle)
self.width = math.fabs(proxy.obj.Width)
self.height = math.fabs(proxy.obj.Height)
self.radius = math.fabs(proxy.obj.Radius)
self.actualHeight = self.height
self.fullWidth = 2 * self.toolRadius + self.width
r1 = self.fullWidth / 2
self.r1 = r1
self.r2 = r1
height = self.actualHeight * 1.01
radius = 0
if self.angle == 90 and height > 0:
# cylinder
self.solid = Part.makeCylinder(r1, height)
radius = min(min(self.radius, r1), self.height)
Path.Log.debug("Part.makeCylinder(%f, %f)" % (r1, height))
elif self.angle > 0.0 and height > 0.0:
# cone
rad = math.radians(self.angle)
tangens = math.tan(rad)
dr = height / tangens
if dr < r1:
# with top
r2 = r1 - dr
s = height / math.sin(rad)
radius = min(r2, s) * math.tan((math.pi - rad) / 2) * 0.95
else:
# triangular
r2 = 0
height = r1 * tangens * 1.01
self.actualHeight = height
self.r2 = r2
Path.Log.debug("Part.makeCone(r1=%.2f, r2=%.2f, h=%.2f)" % (r1, r2, height))
self.solid = Part.makeCone(r1, r2, height)
else:
# degenerated case - no tag
Path.Log.debug("Part.makeSphere(%.2f)" % (r1 / 10000))
self.solid = Part.makeSphere(r1 / 10000)
radius = min(self.radius, radius)
self.realRadius = radius
if radius != 0:
Path.Log.debug("makeFillet(%.4f)" % radius)
self.solid = self.solid.makeFillet(radius, [self.solid.Edges[0]])
# lastly determine the center of the model, we want to make sure the seam of
# the tag solid points away (in the hopes it doesn't coincide with a path)
self.baseCenter = FreeCAD.Vector(
(proxy.ptMin.x + proxy.ptMax.x) / 2, (proxy.ptMin.y + proxy.ptMax.y) / 2, 0
)
def cloneAt(self, pos):
clone = self.solid.copy()
pos.z = 0
angle = -PathGeom.getAngle(pos - self.baseCenter) * 180 / math.pi
clone.rotate(FreeCAD.Vector(0, 0, 0), FreeCAD.Vector(0, 0, 1), angle)
pos.z = self.z - self.actualHeight * 0.01
clone.translate(pos)
return clone
class ObjectDressup:
def __init__(self, obj, base):
obj.addProperty(
"App::PropertyLink",
"Base",
"Base",
QT_TRANSLATE_NOOP("App::Property", "The base path to modify"),
)
obj.addProperty(
"App::PropertyLength",
"Width",
"Tag",
QT_TRANSLATE_NOOP("App::Property", "Width of tags."),
)
obj.addProperty(
"App::PropertyLength",
"Height",
"Tag",
QT_TRANSLATE_NOOP("App::Property", "Height of tags."),
)
obj.addProperty(
"App::PropertyAngle",
"Angle",
"Tag",
QT_TRANSLATE_NOOP("App::Property", "Angle of tag plunge and ascent."),
)
obj.addProperty(
"App::PropertyLength",
"Radius",
"Tag",
QT_TRANSLATE_NOOP("App::Property", "Radius of the fillet for the tag."),
)
obj.addProperty(
"App::PropertyVectorList",
"Positions",
"Tag",
QT_TRANSLATE_NOOP("App::Property", "Locations of inserted holding tags"),
)
obj.addProperty(
"App::PropertyIntegerList",
"Disabled",
"Tag",
QT_TRANSLATE_NOOP("App::Property", "IDs of disabled holding tags"),
)
obj.addProperty(
"App::PropertyInteger",
"SegmentationFactor",
"Tag",
QT_TRANSLATE_NOOP(
"App::Property",
"Factor determining the # of segments used to approximate rounded tags.",
),
)
obj.Proxy = self
obj.Base = base
self.obj = obj
self.solids = []
# initialized later
self.edges = None
self.masterSolid = None
self.ptMax = None
self.ptMin = None
self.tagSolid = None
self.wire = None
def __getstate__(self):
return None
def __setstate__(self, state):
return None
def assignDefaultValues(self):
self.obj.Width = HoldingTagPreferences.defaultWidth(self.toolRadius() * 2)
self.obj.Height = HoldingTagPreferences.defaultHeight(self.toolRadius())
self.obj.Angle = HoldingTagPreferences.defaultAngle()
self.obj.Radius = HoldingTagPreferences.defaultRadius()
def execute(self, obj):
Path.Log.track()
if not obj.Base:
Path.Log.error(translate("Path_DressupTag", "No Base object found."))
return
if not obj.Base.isDerivedFrom("Path::Feature"):
Path.Log.error(
translate("Path_DressupTag", "Base is not a Path::Feature object.")
)
return
if not obj.Base.Path:
Path.Log.error(
translate("Path_DressupTag", "Base doesn't have a Path to dress-up.")
)
return
if not obj.Base.Path.Commands:
Path.Log.error(translate("Path_DressupTag", "Base Path is empty."))
return
self.obj = obj
minZ = +MaxInt
minX = minZ
minY = minZ
maxZ = -MaxInt
maxX = maxZ
maxY = maxZ
# the assumption is that all helixes are in the xy-plane - in other words there is no
# intermittent point of a command that has a lower/higher Z-position than the start and
# and end positions of a command.
lastPt = FreeCAD.Vector(0, 0, 0)
for cmd in obj.Base.Path.Commands:
pt = PathGeom.commandEndPoint(cmd, lastPt)
if lastPt.x != pt.x:
maxX = max(pt.x, maxX)
minX = min(pt.x, minX)
if lastPt.y != pt.y:
maxY = max(pt.y, maxY)
minY = min(pt.y, minY)
if lastPt.z != pt.z:
maxZ = max(pt.z, maxZ)
minZ = min(pt.z, minZ)
lastPt = pt
Path.Log.debug(
"bb = (%.2f, %.2f, %.2f) ... (%.2f, %.2f, %.2f)"
% (minX, minY, minZ, maxX, maxY, maxZ)
)
self.ptMin = FreeCAD.Vector(minX, minY, minZ)
self.ptMax = FreeCAD.Vector(maxX, maxY, maxZ)
self.masterSolid = TagSolid(self, minZ, self.toolRadius())
self.solids = [self.masterSolid.cloneAt(pos) for pos in self.obj.Positions]
self.tagSolid = Part.Compound(self.solids)
self.wire, rapid = PathGeom.wireForPath(obj.Base.Path)
self.edges = self.wire.Edges
maxTagZ = minZ + obj.Height.Value
# lastX = 0
# lastY = 0
lastZ = 0
commands = []
for cmd in obj.Base.Path.Commands:
if cmd in PathGeom.CmdMove:
if lastZ <= maxTagZ or cmd.Parameters.get("Z", lastZ) <= maxTagZ:
pass
else:
commands.append(cmd)
else:
commands.append(cmd)
obj.Path = obj.Base.Path
Path.Log.track()
def toolRadius(self):
return float(PathDressup.toolController(self.obj.Base).Tool.Diameter) / 2.0
def addTagsToDocument(self):
for i, solid in enumerate(self.solids):
obj = FreeCAD.ActiveDocument.addObject("Part::Compound", "tag_%02d" % i)
obj.Shape = solid
def supportsTagGeneration(self, obj):
return False
def pointIsOnPath(self, obj, p):
for e in self.edges:
if DraftGeomUtils.isPtOnEdge(p, e):
return True
return False
def Create(baseObject, name="DressupTag"):
"""
Create(basePath, name = 'DressupTag') ... create tag dressup object for the given base path.
"""
if not baseObject.isDerivedFrom("Path::Feature"):
Path.Log.error(
translate("Path_DressupTag", "The selected object is not a path") + "\n"
)
return None
if baseObject.isDerivedFrom("Path::FeatureCompoundPython"):
Path.Log.error(translate("Path_DressupTag", "Please select a Profile object"))
return None
obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", name)
dbo = ObjectDressup(obj, baseObject)
job = PathUtils.findParentJob(baseObject)
job.addOperation(obj)
dbo.assignDefaultValues()
return obj
Path.Log.notice("Loading Path_DressupTag... done\n")

View File

@@ -39,6 +39,14 @@ def Startup():
if not Processed:
Path.Log.debug("Initializing PathGui")
from Path.Op.Gui import Adaptive
from Path.Dressup.Gui import AxisMap
from Path.Dressup.Gui import Dogbone
from Path.Dressup.Gui import Dragknife
from Path.Dressup.Gui import LeadInOut
from Path.Dressup.Gui import PathBoundary
from Path.Dressup.Gui import RampEntry
from Path.Dressup.Gui import Tags
from Path.Dressup.Gui import ZCorrect
from Path.Post import Command
from Path.Tools import Controller
from Path.Tools.Gui import Controller
@@ -46,14 +54,6 @@ def Startup():
from PathScripts import PathComment
from PathScripts import PathCustomGui
from PathScripts import PathDeburrGui
from PathScripts import PathDressupAxisMap
from PathScripts import PathDressupDogbone
from PathScripts import PathDressupDragknife
from PathScripts import PathDressupLeadInOut
from PathScripts import PathDressupPathBoundaryGui
from PathScripts import PathDressupRampEntry
from PathScripts import PathDressupTagGui
from PathScripts import PathDressupZCorrect
from PathScripts import PathDrillingGui
from PathScripts import PathEngraveGui
from PathScripts import PathFixture

View File

@@ -22,8 +22,8 @@
import FreeCAD
import Path
import Path.Dressup.Utils as PathDressup
import PathGui as PGui # ensure Path/Gui/Resources are loaded
import PathScripts.PathDressup as PathDressup
import PathScripts.PathGeom as PathGeom
import PathScripts.PathUtil as PathUtil
import PathScripts.PathJob as PathJob

View File

@@ -22,7 +22,7 @@
import FreeCAD
import Path
import PathScripts.PathDressupDogbone as PathDressupDogbone
import Path.Dressup.Gui.Dogbone as PathDressupDogbone
import PathScripts.PathJob as PathJob
import PathScripts.PathProfileFaces as PathProfileFaces

View File

@@ -24,7 +24,7 @@ import PathTests.PathTestUtils as PathTestUtils
import math
from FreeCAD import Vector
from PathScripts.PathDressupHoldingTags import Tag
from Path.Dressup.Tags import Tag
class TestHoldingTags(PathTestUtils.PathTestBase):