From 3f6b4a0b790a200c656bda038ecf98db27475f07 Mon Sep 17 00:00:00 2001 From: Markus Lampert Date: Thu, 19 Jan 2017 15:48:32 -0800 Subject: [PATCH 1/3] Path logging interface and bulk transfer of HoldingTags dressup to use module. --- src/Mod/Path/CMakeLists.txt | 2 + .../PathScripts/PathDressupHoldingTags.py | 124 +++++------ src/Mod/Path/PathScripts/PathLog.py | 163 +++++++++++++++ src/Mod/Path/PathTests/TestPathLog.py | 195 ++++++++++++++++++ src/Mod/Path/PathTests/TestPathPost.py | 1 - src/Mod/Path/TestPathApp.py | 3 +- 6 files changed, 419 insertions(+), 69 deletions(-) create mode 100644 src/Mod/Path/PathScripts/PathLog.py create mode 100644 src/Mod/Path/PathTests/TestPathLog.py diff --git a/src/Mod/Path/CMakeLists.txt b/src/Mod/Path/CMakeLists.txt index aecf79d898..3068df25c9 100644 --- a/src/Mod/Path/CMakeLists.txt +++ b/src/Mod/Path/CMakeLists.txt @@ -39,6 +39,7 @@ SET(PathScripts_SRCS PathScripts/PathJob.py PathScripts/PathKurveUtils.py PathScripts/PathLoadTool.py + PathScripts/PathLog.py PathScripts/PathMillFace.py PathScripts/PathPlane.py PathScripts/PathPocket.py @@ -79,6 +80,7 @@ SET(PathScripts_SRCS PathTests/TestPathDepthParams.py PathTests/TestPathDressupHoldingTags.py PathTests/TestPathGeom.py + PathTests/TestPathLog.py PathTests/TestPathPost.py PathTests/__init__.py PathTests/test_linuxcnc_00.ngc diff --git a/src/Mod/Path/PathScripts/PathDressupHoldingTags.py b/src/Mod/Path/PathScripts/PathDressupHoldingTags.py index 62666c591d..df498396cf 100644 --- a/src/Mod/Path/PathScripts/PathDressupHoldingTags.py +++ b/src/Mod/Path/PathScripts/PathDressupHoldingTags.py @@ -27,14 +27,12 @@ import Draft import DraftGeomUtils import DraftGui import Path +import PathScripts.PathLog as PathLog import PathScripts.PathPreferencesPathDressup as PathPreferencesPathDressup import Part import copy import math -import cProfile -import time - from DraftGui import todo from PathScripts import PathUtils from PathScripts.PathGeom import * @@ -48,16 +46,13 @@ from pivy import coin def translate(text, context = "PathDressup_HoldingTags", disambig=None): return QtCore.QCoreApplication.translate(context, text, disambig) -debugDressup = False -def debugPrint(msg): - if debugDressup: - print(msg) +#PathLog.setLevel(PathLog.Level.DEBUG) def debugEdge(edge, prefix, force = False): - pf = edge.valueAt(edge.FirstParameter) - pl = edge.valueAt(edge.LastParameter) - if force or debugDressup: + if force or PathLog.getLevel() == PathLog.Level.DEBUG: + pf = edge.valueAt(edge.FirstParameter) + pl = edge.valueAt(edge.LastParameter) if type(edge.Curve) == Part.Line or type(edge.Curve) == Part.LineSegment: print("%s %s((%.2f, %.2f, %.2f) - (%.2f, %.2f, %.2f))" % (prefix, type(edge.Curve), pf.x, pf.y, pf.z, pl.x, pl.y, pl.z)) else: @@ -65,7 +60,7 @@ def debugEdge(edge, prefix, force = False): print("%s %s((%.2f, %.2f, %.2f) - (%.2f, %.2f, %.2f) - (%.2f, %.2f, %.2f))" % (prefix, type(edge.Curve), pf.x, pf.y, pf.z, pm.x, pm.y, pm.z, pl.x, pl.y, pl.z)) def debugMarker(vector, label, color = None, radius = 0.5): - if debugDressup: + if PathLog.getLevel() == PathLog.Level.DEBUG: obj = FreeCAD.ActiveDocument.addObject("Part::Sphere", label) obj.Label = label obj.Radius = radius @@ -74,7 +69,7 @@ def debugMarker(vector, label, color = None, radius = 0.5): obj.ViewObject.ShapeColor = color def debugCylinder(vector, r, height, label, color = None): - if debugDressup: + if PathLog.getLevel() == PathLog.Level.DEBUG: obj = FreeCAD.ActiveDocument.addObject("Part::Cylinder", label) obj.Label = label obj.Radius = r @@ -85,7 +80,7 @@ def debugCylinder(vector, r, height, label, color = None): obj.ViewObject.ShapeColor = color def debugCone(vector, r1, r2, height, label, color = None): - if debugDressup: + if PathLog.getLevel() == PathLog.Level.DEBUG: obj = FreeCAD.ActiveDocument.addObject("Part::Cone", label) obj.Label = label obj.Radius1 = r1 @@ -162,7 +157,7 @@ class HoldingTagsPreferences: class Tag: def __init__(self, x, y, width, height, angle, radius, enabled=True): - debugPrint("Tag(%.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %d)" % (x, y, width, height, angle, radius, enabled)) + PathLog.track("%.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %d" % (x, y, width, height, angle, radius, enabled)) self.x = x self.y = y self.width = math.fabs(width) @@ -198,7 +193,7 @@ class Tag: self.isSquare = True self.solid = Part.makeCylinder(r1, height) radius = min(min(self.radius, r1), self.height) - debugPrint("Part.makeCone(%f, %f)" % (r1, height)) + PathLog.debug("Part.makeCone(%f, %f)" % (r1, height)) elif self.angle > 0.0 and height > 0.0: # cone rad = math.radians(self.angle) @@ -215,29 +210,29 @@ class Tag: height = r1 * tangens * 1.01 self.actualHeight = height self.r2 = r2 - debugPrint("Part.makeCone(%f, %f, %f)" % (r1, r2, height)) + PathLog.debug("Part.makeCone(%f, %f, %f)" % (r1, r2, height)) self.solid = Part.makeCone(r1, r2, height) else: # degenerated case - no tag - debugPrint("Part.makeSphere(%f / 10000)" % (r1)) + PathLog.debug("Part.makeSphere(%f / 10000)" % (r1)) self.solid = Part.makeSphere(r1 / 10000) if not R == 0: # testing is easier if the solid is not rotated angle = -PathGeom.getAngle(self.originAt(0)) * 180 / math.pi - debugPrint("solid.rotate(%f)" % angle) + PathLog.debug("solid.rotate(%f)" % angle) self.solid.rotate(FreeCAD.Vector(0,0,0), FreeCAD.Vector(0,0,1), angle) - debugPrint("solid.translate(%s)" % self.originAt(z)) + PathLog.debug("solid.translate(%s)" % self.originAt(z)) self.solid.translate(self.originAt(z - 0.01 * self.actualHeight)) self.realRadius = radius if radius != 0: - debugPrint("makeFillet(%.4f)" % radius) + PathLog.debug("makeFillet(%.4f)" % radius) self.solid = self.solid.makeFillet(radius, [self.solid.Edges[0]]) def filterIntersections(self, pts, face): if type(face.Surface) == Part.Cone or type(face.Surface) == Part.Cylinder or type(face.Surface) == Part.Toroid: - #print("it's a cone/cylinder, checking z") + PathLog.track("it's a cone/cylinder, checking z") return filter(lambda pt: pt.z >= self.bottom() and pt.z <= self.top(), pts) if type(face.Surface) == Part.Plane: - #print("it's a plane, checking R") + PathLog.track("it's a plane, checking R") c = face.Edges[0].Curve if (type(c) == Part.Circle): return filter(lambda pt: (pt - c.Center).Length <= c.Radius or PathGeom.isRoughly((pt - c.Center).Length, c.Radius), pts) @@ -312,9 +307,9 @@ class MapWireToTag: self.edges = [] self.entry = i if tail: - debugPrint("MapWireToTag(%s - %s)" % (i, tail.valueAt(tail.FirstParameter))) + PathLog.debug("MapWireToTag(%s - %s)" % (i, tail.valueAt(tail.FirstParameter))) else: - debugPrint("MapWireToTag(%s - )" % i) + PathLog.debug("MapWireToTag(%s - )" % i) self.complete = False self.haveProblem = False @@ -342,11 +337,11 @@ class MapWireToTag: def cleanupEdges(self, edges): # want to remove all edges from the wire itself, and all internal struts - #print("+cleanupEdges") - #print(" edges:") + PathLog.track("+cleanupEdges") + PathLog.debug(" edges:") for e in edges: debugEdge(e, ' ') - #print(":") + PathLog.debug(":") self.edgesCleanup = [copy.copy(edges)] # remove any edge that has a point inside the tag solid @@ -413,7 +408,7 @@ class MapWireToTag: return edges def orderAndFlipEdges(self, edges): - #print("entry(%.2f, %.2f, %.2f), exit(%.2f, %.2f, %.2f)" % (self.entry.x, self.entry.y, self.entry.z, self.exit.x, self.exit.y, self.exit.z)) + PathLog.track("entry(%.2f, %.2f, %.2f), exit(%.2f, %.2f, %.2f)" % (self.entry.x, self.entry.y, self.entry.z, self.exit.x, self.exit.y, self.exit.z)) self.edgesOrder = [] outputEdges = [] p0 = self.entry @@ -450,11 +445,11 @@ class MapWireToTag: debugEdge(e, ' ', False) raise ValueError("No connection to %s" % (p0)) elif lastP: - debugPrint("xxxxxx (%.2f, %.2f, %.2f) (%.2f, %.2f, %.2f)" % (p0.x, p0.y, p0.z, lastP.x, lastP.y, lastP.z)) + PathLog.debug("xxxxxx (%.2f, %.2f, %.2f) (%.2f, %.2f, %.2f)" % (p0.x, p0.y, p0.z, lastP.x, lastP.y, lastP.z)) else: - debugPrint("xxxxxx (%.2f, %.2f, %.2f) -" % (p0.x, p0.y, p0.z)) + PathLog.debug("xxxxxx (%.2f, %.2f, %.2f) -" % (p0.x, p0.y, p0.z)) lastP = p0 - #print("-cleanupEdges") + PathLog.track("-") return outputEdges def isStrut(self, edge): @@ -546,14 +541,9 @@ class _RapidEdges: return True return False - def debugPrint(self): - debugPrint('rapid:') - for r in self.rapid: - debugEdge(r, ' ') - class PathData: def __init__(self, obj): - debugPrint("PathData(%s)" % obj.Base.Name) + PathLog.track(obj.Base.Name) self.obj = obj self.wire, rapid = PathGeom.wireForPath(obj.Base.Path) self.rapid = _RapidEdges(rapid) @@ -593,7 +583,7 @@ class PathData: return (edges[0], edges[-1]) def generateTags(self, obj, count, width=None, height=None, angle=None, radius=None, spacing=None): - debugPrint("generateTags(%s, %s, %s, %s, %s)" % (count, width, height, angle, spacing)) + PathLog.track(count, width, height, angle, spacing) #for e in self.base.Edges: # debugMarker(e.Vertexes[0].Point, 'base', (0.0, 1.0, 1.0), 0.2) @@ -613,7 +603,7 @@ class PathData: startIndex = 0 for i in range(0, len(self.base.Edges)): edge = self.base.Edges[i] - debugPrint(' %d: %.2f' % (i, edge.Length)) + PathLog.debug(' %d: %.2f' % (i, edge.Length)) if edge.Length == longestEdge.Length: startIndex = i break @@ -628,10 +618,10 @@ class PathData: minLength = min(2. * W, longestEdge.Length) - debugPrint("length=%.2f shortestEdge=%.2f(%.2f) longestEdge=%.2f(%.2f) minLength=%.2f" % (self.base.Length, shortestEdge.Length, shortestEdge.Length/self.base.Length, longestEdge.Length, longestEdge.Length / self.base.Length, minLength)) - debugPrint(" start: index=%-2d count=%d (length=%.2f, distance=%.2f)" % (startIndex, startCount, startEdge.Length, tagDistance)) - debugPrint(" -> lastTagLength=%.2f)" % lastTagLength) - debugPrint(" -> currentLength=%.2f)" % currentLength) + PathLog.debug("length=%.2f shortestEdge=%.2f(%.2f) longestEdge=%.2f(%.2f) minLength=%.2f" % (self.base.Length, shortestEdge.Length, shortestEdge.Length/self.base.Length, longestEdge.Length, longestEdge.Length / self.base.Length, minLength)) + PathLog.debug(" start: index=%-2d count=%d (length=%.2f, distance=%.2f)" % (startIndex, startCount, startEdge.Length, tagDistance)) + PathLog.debug(" -> lastTagLength=%.2f)" % lastTagLength) + PathLog.debug(" -> currentLength=%.2f)" % currentLength) edgeDict = { startIndex: startCount } @@ -646,7 +636,7 @@ class PathData: for (i, count) in edgeDict.iteritems(): edge = self.base.Edges[i] - debugPrint(" %d: %d" % (i, count)) + PathLog.debug(" %d: %d" % (i, count)) #debugMarker(edge.Vertexes[0].Point, 'base', (1.0, 0.0, 0.0), 0.2) #debugMarker(edge.Vertexes[1].Point, 'base', (0.0, 1.0, 0.0), 0.2) if 0 != count: @@ -665,10 +655,10 @@ class PathData: tagCount += 1 lastTagLength += tagDistance if tagCount > 0: - debugPrint(" index=%d -> count=%d" % (index, tagCount)) + PathLog.debug(" index=%d -> count=%d" % (index, tagCount)) edgeDict[index] = tagCount else: - debugPrint(" skipping=%-2d (%.2f)" % (index, edge.Length)) + PathLog.debug(" skipping=%-2d (%.2f)" % (index, edge.Length)) return (currentLength, lastTagLength) @@ -701,7 +691,7 @@ class PathData: ordered.append(t) # disable all tags that are not on the base wire. for tag in tags: - FreeCAD.Console.PrintMessage("Tag #%d not on base wire - disabling\n" % len(ordered)) + PathLog.notice("Tag #%d not on base wire - disabling\n" % len(ordered)) tag.enabled = False ordered.append(tag) return ordered @@ -756,7 +746,7 @@ class ObjectDressup: return True def createPath(self, obj, pathData, tags): - #print("createPath") + PathLog.track() commands = [] lastEdge = 0 lastTag = 0 @@ -776,7 +766,7 @@ class ObjectDressup: mapper = None while edge or lastEdge < len(pathData.edges): - debugPrint("------- lastEdge = %d/%d.%d/%d" % (lastEdge, lastTag, t, len(tags))) + PathLog.debug("------- lastEdge = %d/%d.%d/%d" % (lastEdge, lastTag, t, len(tags))) if not edge: edge = pathData.edges[lastEdge] debugEdge(edge, "======= new edge: %d/%d" % (lastEdge, len(pathData.edges))) @@ -836,19 +826,19 @@ class ObjectDressup: if tag.enabled: if prev: if prev.solid.common(tag.solid).Faces: - FreeCAD.Console.PrintMessage("Tag #%d intersects with previous tag - disabling\n" % i) - debugPrint("this tag = %d [%s]" % (i, tag.solid.BoundBox)) + PathLog.notice("Tag #%d intersects with previous tag - disabling\n" % i) + PathLog.debug("this tag = %d [%s]" % (i, tag.solid.BoundBox)) tag.enabled = False elif self.pathData.edges: e = self.pathData.edges[0] p0 = e.valueAt(e.FirstParameter) p1 = e.valueAt(e.LastParameter) if tag.solid.isInside(p0, PathGeom.Tolerance, True) or tag.solid.isInside(p1, PathGeom.Tolerance, True): - FreeCAD.Console.PrintMessage("Tag #%d intersects with starting point - disabling\n" % i) + PathLog.notice("Tag #%d intersects with starting point - disabling\n" % i) tag.enabled = False if tag.enabled: prev = tag - debugPrint("previousTag = %d [%s]" % (i, prev)) + PathLog.debug("previousTag = %d [%s]" % (i, prev)) else: disabled.append(i) tags.append(tag) @@ -856,6 +846,7 @@ class ObjectDressup: return (tags, positions, disabled) def execute(self, obj): + #import cProfile #pr = cProfile.Profile() #pr.enable() self.doExecute(obj) @@ -881,7 +872,7 @@ class ObjectDressup: if hasattr(obj, "Positions"): self.tags, positions, disabled = self.createTagsPositionDisabled(obj, obj.Positions, obj.Disabled) if obj.Disabled != disabled: - debugPrint("Updating properties.... %s vs. %s" % (obj.Disabled, disabled)) + PathLog.debug("Updating properties.... %s vs. %s" % (obj.Disabled, disabled)) obj.Positions = positions obj.Disabled = disabled @@ -894,11 +885,11 @@ class ObjectDressup: def processTags(self, obj): tagID = 0 - if debugDressup: + if PathLog.getLevel() == PathLog.Level.DEBUG: for tag in self.tags: tagID += 1 if tag.enabled: - debugPrint("x=%s, y=%s, z=%s" % (tag.x, tag.y, self.pathData.minZ)) + PathLog.debug("x=%s, y=%s, z=%s" % (tag.x, tag.y, self.pathData.minZ)) #debugMarker(FreeCAD.Vector(tag.x, tag.y, self.pathData.minZ), "tag-%02d" % tagID , (1.0, 0.0, 1.0), 0.5) #if tag.angle != 90: # debugCone(tag.originAt(self.pathData.minZ), tag.r1, tag.r2, tag.actualHeight, "tag-%02d" % tagID) @@ -906,15 +897,14 @@ class ObjectDressup: # debugCylinder(tag.originAt(self.pathData.minZ), tag.fullWidth()/2, tag.actualHeight, "tag-%02d" % tagID) obj.Path = self.createPath(obj, self.pathData, self.tags) - #print("execute - done") def setup(self, obj, generate=False): - debugPrint("setup") + PathLog.debug("setup") self.obj = obj try: pathData = PathData(obj) except ValueError: - FreeCAD.Console.PrintError(translate("Cannot insert holding tags for this path - please select a Profile path\n")) + PathLog.error(translate("Cannot insert holding tags for this path - please select a Profile path\n")) return None self.toolRadius = 5 @@ -938,7 +928,7 @@ class ObjectDressup: return self.pathData def setXyEnabled(self, triples): - debugPrint("setXyEnabled") + PathLog.track() if not hasattr(self, 'pathData'): self.setup(self.obj) positions = [] @@ -1038,7 +1028,7 @@ class TaskPanel: self.obj.Proxy.setXyEnabled(tags) def updateTagsView(self): - #print("updateTagsView") + PathLog.track() self.formTags.lwTags.blockSignals(True) self.formTags.lwTags.clear() for i, pos in enumerate(self.obj.Positions): @@ -1066,7 +1056,7 @@ class TaskPanel: self.obj.Proxy.execute(self.obj) self.updateTagsView() - #if debugDressup: + #if PathLog.getLevel() == PathLog.Level.DEBUG: # # this causes a big of an echo and a double click on the spin buttons, don't know why though # FreeCAD.ActiveDocument.recompute() @@ -1359,7 +1349,7 @@ class ViewProviderDressup: self.tags = tags def selectTag(self, index): - #print("selectTag(%s)" % index) + PathLog.track(index) for i, tag in enumerate(self.tags): tag.setSelected(i == index) @@ -1401,14 +1391,14 @@ class CommandPathDressupHoldingTags: # check that the selection contains exactly what we want selection = FreeCADGui.Selection.getSelection() if len(selection) != 1: - FreeCAD.Console.PrintError(translate("Please select one path object\n")) + PathLog.error(translate("Please select one path object\n")) return baseObject = selection[0] if not baseObject.isDerivedFrom("Path::Feature"): - FreeCAD.Console.PrintError(translate("The selected object is not a path\n")) + PathLog.error(translate("The selected object is not a path\n")) return if baseObject.isDerivedFrom("Path::FeatureCompoundPython"): - FreeCAD.Console.PrintError(translate("Please select a Profile object")) + PathLog.error(translate("Please select a Profile object")) return # everything ok! @@ -1430,4 +1420,4 @@ if FreeCAD.GuiUp: # register the FreeCAD command FreeCADGui.addCommand('PathDressup_HoldingTags', CommandPathDressupHoldingTags()) -FreeCAD.Console.PrintLog("Loading PathDressupHoldingTags... done\n") +PathLog.notice("Loading PathDressupHoldingTags... done\n") diff --git a/src/Mod/Path/PathScripts/PathLog.py b/src/Mod/Path/PathScripts/PathLog.py new file mode 100644 index 0000000000..193712768e --- /dev/null +++ b/src/Mod/Path/PathScripts/PathLog.py @@ -0,0 +1,163 @@ +# -*- coding: utf-8 -*- + +# *************************************************************************** +# * * +# * Copyright (c) 2016 sliptonic * +# * * +# * 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 os +import traceback + +class Level: + """Enumeration of log levels, used for setLevel and getLevel.""" + RESET = -1 + ERROR = 0 + WARNING = 1 + NOTICE = 2 + INFO = 3 + DEBUG = 4 + + _names = { ERROR: 'ERROR', WARNING: 'WARNING', NOTICE: 'NOTICE', INFO: 'INFO', DEBUG: 'DEBUG' } + + @classmethod + def toString(cls, level): + return cls._names.get(level, 'UNKNOWN') + +_defaultLogLevel = Level.NOTICE +_moduleLogLevel = { } +_useConsole = True +_trackModule = { } +_trackAll = False + +def logToConsole(yes): + """(boolean) - if set to True (default behaviour) log messages are printed to the console. Otherwise they are printed to stdout.""" + global _useConsole + _useConsole = yes + +def setLevel(level, module = None): + """(level, module = None) + if no module is specified the default log level is set. + Otherwise the module specific log level is changed (use RESET to clear).""" + global _defaultLogLevel + global _moduleLogLevel + if module: + if level == Level.RESET: + if _moduleLogLevel.get(module, -1) != -1: + del _moduleLogLevel[module] + else: + _moduleLogLevel[module] = level + else: + if level == Level.RESET: + _defaultLogLevel = Level.NOTICE + _moduleLogLevel = { } + else: + _defaultLogLevel = level + +def getLevel(module = None): + """(module = None) - return the global (None) or module specific log level.""" + if module: + return _moduleLogLevel.get(module, _defaultLogLevel) + return _defaultLogLevel + +def _caller(): + """internal function to determine the calling module.""" + file, line, func, text = traceback.extract_stack(limit=3)[0] + return os.path.splitext(os.path.basename(file))[0], line, func + +def _log(level, (module, line, func), msg): + """internal function to do the logging""" + if getLevel(module) >= level: + message = "%s.%s: %s" % (module, Level.toString(level), msg) + if _useConsole: + message += "\n" + if level == Level.NOTICE: + FreeCAD.Console.PrintLog(message) + elif level == Level.WARNING: + FreeCAD.Console.PrintWarning(message) + elif level == Level.ERROR: + FreeCAD.Console.PrintError(message) + else: + FreeCAD.Console.PrintMessage(message) + else: + print(message) + return message + return None + +def debug(msg): + """(message)""" + return _log(Level.DEBUG, _caller(), msg) +def info(msg): + """(message)""" + return _log(Level.INFO, _caller(), msg) +def notice(msg): + """(message)""" + return _log(Level.NOTICE, _caller(), msg) +def warning(msg): + """(message)""" + return _log(Level.WARNING, _caller(), msg) +def error(msg): + """(message)""" + return _log(Level.ERROR, _caller(), msg) + +def trackAllModules(boolean): + """(boolean) - if True all modules will be tracked, otherwise tracking is up to the module setting.""" + global _trackAll + _trackAll = boolean + +def untrackAllModules(): + """In addition to stop tracking all modules it also clears the tracking flag for all individual modules.""" + global _trackAll + global _trackModule + _trackAll = False + _trackModule = { } + +def trackModule(module = None): + """(module = None) - start tracking given module, current module if not set.""" + global _trackModule + if module: + _trackModule[module] = True + else: + mod, line, func = _caller() + _trackModule[mod] = True + +def untrackModule(module = None): + """(module = None) - stop tracking given module, current module if not set.""" + global _trackModule + if module and _trackModule.get(module, None): + del _trackModule[module] + elif not module: + mod, line, func = _caller() + if _trackModule.get(mod, None): + del _trackModule[mod] + +def track(*args): + """(....) - call with arguments of current function you want logged if tracking is enabled.""" + module, line, func = _caller() + if _trackAll or _trackModule.get(module, None): + message = "%s(%d).%s(%s)" % (module, line, func, ', '.join([str(arg) for arg in args])) + if _useConsole: + FreeCAD.Console.PrintMessage(message + "\n") + else: + print(message) + return message + return None + + diff --git a/src/Mod/Path/PathTests/TestPathLog.py b/src/Mod/Path/PathTests/TestPathLog.py new file mode 100644 index 0000000000..f9b1c81bb5 --- /dev/null +++ b/src/Mod/Path/PathTests/TestPathLog.py @@ -0,0 +1,195 @@ +# -*- coding: utf-8 -*- + +# *************************************************************************** +# * * +# * Copyright (c) 2016 sliptonic * +# * * +# * 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 PathScripts.PathLog as PathLog +import unittest + +class TestPathLog(unittest.TestCase): + """Some basic tests for the logging framework.""" + + MODULE = 'TestPathLog' # file name without extension + + def setUp(self): + PathLog.setLevel(PathLog.Level.RESET) + PathLog.untrackAllModules() + + def callerFile(self): + return PathLog._caller()[0] + def callerLine(self): + return PathLog._caller()[1] + def callerFunc(self): + return PathLog._caller()[2] + + def test00(self): + """Check for proper module extraction.""" + self.assertEqual(self.callerFile(), self.MODULE) + + def test01(self): + """Check for proper function extraction.""" + self.assertEqual(self.callerFunc(), 'test01') + + def test10(self): + """Verify default log levels is NOTICE.""" + self.assertEqual(PathLog.getLevel(), PathLog.Level.NOTICE) + self.assertEqual(PathLog.getLevel(self.MODULE), PathLog.Level.NOTICE) + + def test11(self): + """Verify setting global log level.""" + PathLog.setLevel(PathLog.Level.DEBUG) + + self.assertEqual(PathLog.getLevel(), PathLog.Level.DEBUG) + self.assertEqual(PathLog.getLevel(self.MODULE), PathLog.Level.DEBUG) + + def test12(self): + """Verify setting module log level.""" + PathLog.setLevel(PathLog.Level.DEBUG, self.MODULE) + + self.assertEqual(PathLog.getLevel(), PathLog.Level.NOTICE) + self.assertEqual(PathLog.getLevel(self.MODULE), PathLog.Level.DEBUG) + + def test13(self): + """Verify setting other modul's log level doesn't change this one's.""" + # if this test fails then most likely the global RESET is broken + PathLog.setLevel(PathLog.Level.DEBUG, 'SomeOtherModule') + + self.assertEqual(PathLog.getLevel(), PathLog.Level.NOTICE) + self.assertEqual(PathLog.getLevel(self.MODULE), PathLog.Level.NOTICE) + + def test14(self): + """Verify resetting log level for module falls back to global level.""" + PathLog.setLevel(PathLog.Level.DEBUG, self.MODULE) + self.assertEqual(PathLog.getLevel(self.MODULE), PathLog.Level.DEBUG) + # changing global log level does not affect module + PathLog.setLevel(PathLog.Level.ERROR) + self.assertEqual(PathLog.getLevel(self.MODULE), PathLog.Level.DEBUG) + # resetting module log level restores global log level for module + PathLog.setLevel(PathLog.Level.RESET, self.MODULE) + self.assertEqual(PathLog.getLevel(self.MODULE), PathLog.Level.ERROR) + # changing the global log level will also change the module log level + PathLog.setLevel(PathLog.Level.DEBUG) + self.assertEqual(PathLog.getLevel(self.MODULE), PathLog.Level.DEBUG) + + def test20(self): + """Verify debug logs aren't logged by default.""" + self.assertIsNone(PathLog.debug("this")) + + def test21(self): + """Verify debug logs are logged if log level is set to DEBUG.""" + PathLog.setLevel(PathLog.Level.DEBUG) + self.assertIsNotNone(PathLog.debug("this")) + + def test30(self): + """Verify log level ERROR.""" + PathLog.setLevel(PathLog.Level.ERROR) + self.assertIsNone(PathLog.debug('something')) + self.assertIsNone(PathLog.info('something')) + self.assertIsNone(PathLog.notice('something')) + self.assertIsNone(PathLog.warning('something')) + self.assertIsNotNone(PathLog.error('something')) + + def test31(self): + """Verify log level WARNING.""" + PathLog.setLevel(PathLog.Level.WARNING) + self.assertIsNone(PathLog.debug('something')) + self.assertIsNone(PathLog.info('something')) + self.assertIsNone(PathLog.notice('something')) + self.assertIsNotNone(PathLog.warning('something')) + self.assertIsNotNone(PathLog.error('something')) + + def test32(self): + """Verify log level NOTICE.""" + PathLog.setLevel(PathLog.Level.NOTICE) + self.assertIsNone(PathLog.debug('something')) + self.assertIsNone(PathLog.info('something')) + self.assertIsNotNone(PathLog.notice('something')) + self.assertIsNotNone(PathLog.warning('something')) + self.assertIsNotNone(PathLog.error('something')) + + def test33(self): + """Verify log level INFO.""" + PathLog.setLevel(PathLog.Level.INFO) + self.assertIsNone(PathLog.debug('something')) + self.assertIsNotNone(PathLog.info('something')) + self.assertIsNotNone(PathLog.notice('something')) + self.assertIsNotNone(PathLog.warning('something')) + self.assertIsNotNone(PathLog.error('something')) + + def test34(self): + """Verify log level DEBUG.""" + PathLog.setLevel(PathLog.Level.DEBUG) + self.assertIsNotNone(PathLog.debug('something')) + self.assertIsNotNone(PathLog.info('something')) + self.assertIsNotNone(PathLog.notice('something')) + self.assertIsNotNone(PathLog.warning('something')) + self.assertIsNotNone(PathLog.error('something')) + + def test50(self): + """Verify no tracking by default.""" + self.assertIsNone(PathLog.track('this', 'and', 'that')) + + def test51(self): + """Verify enabling tracking for module results in tracking.""" + PathLog.trackModule() + # Don't want to rely on the line number matching - still want some + # indication that track does the right thing .... + msg = PathLog.track('this', 'and', 'that') + self.assertTrue(msg.startswith(self.MODULE)) + self.assertTrue(msg.endswith('test51(this, and, that)')) + + def test52(self): + """Verify untracking stops tracking.""" + PathLog.trackModule() + self.assertIsNotNone(PathLog.track('this', 'and', 'that')) + PathLog.untrackModule() + self.assertIsNone(PathLog.track('this', 'and', 'that')) + + def test53(self): + """Verify trackAllModules works correctly.""" + PathLog.trackAllModules(True) + self.assertIsNotNone(PathLog.track('this', 'and', 'that')) + PathLog.trackAllModules(False) + self.assertIsNone(PathLog.track('this', 'and', 'that')) + PathLog.trackAllModules(True) + PathLog.trackModule() + self.assertIsNotNone(PathLog.track('this', 'and', 'that')) + PathLog.trackAllModules(False) + self.assertIsNotNone(PathLog.track('this', 'and', 'that')) + + def test60(self): + """Verify track handles no argument.""" + PathLog.trackModule() + msg = PathLog.track() + self.assertTrue(msg.startswith(self.MODULE)) + self.assertTrue(msg.endswith('test60()')) + + def test61(self): + """Verify track handles arbitrary argument types correctly.""" + PathLog.trackModule() + msg = PathLog.track('this', None, 1, 18.25) + self.assertTrue(msg.startswith(self.MODULE)) + self.assertTrue(msg.endswith('test61(this, None, 1, 18.25)')) + + def testzz(self): + """Restoring environment after tests.""" + PathLog.setLevel(PathLog.Level.RESET) diff --git a/src/Mod/Path/PathTests/TestPathPost.py b/src/Mod/Path/PathTests/TestPathPost.py index 0ea6ba81d2..efcdc1a323 100644 --- a/src/Mod/Path/PathTests/TestPathPost.py +++ b/src/Mod/Path/PathTests/TestPathPost.py @@ -74,7 +74,6 @@ class PathPostTestCases(unittest.TestCase): contour.OffsetExtra = 0.0 contour.Direction = 'CW' contour.UseComp = True - contour.PlungeAngle = 90.0 PathScripts.PathUtils.addToJob(contour) PathScripts.PathContour.ObjectContour.setDepths(contour.Proxy, contour) self.doc.recompute() diff --git a/src/Mod/Path/TestPathApp.py b/src/Mod/Path/TestPathApp.py index 074643ad36..f5e3abf0c2 100644 --- a/src/Mod/Path/TestPathApp.py +++ b/src/Mod/Path/TestPathApp.py @@ -24,10 +24,11 @@ import TestApp +from PathTests.TestPathLog import TestPathLog from PathTests.TestPathCore import TestPathCore from PathTests.TestPathPost import PathPostTestCases from PathTests.TestPathGeom import TestPathGeom from PathTests.TestPathDepthParams import depthTestCases -from PathTests.TestPathDressupHoldingTags import TestHoldingTags +#from PathTests.TestPathDressupHoldingTags import TestHoldingTags From f2ea9cb60719cd0ca49403b6b5b87067a05e3d8f Mon Sep 17 00:00:00 2001 From: Markus Lampert Date: Thu, 19 Jan 2017 16:05:48 -0800 Subject: [PATCH 2/3] Fixed secondary debug logging in holding tags. --- .../Path/PathScripts/PathDressupHoldingTags.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/Mod/Path/PathScripts/PathDressupHoldingTags.py b/src/Mod/Path/PathScripts/PathDressupHoldingTags.py index df498396cf..215c6f0fc0 100644 --- a/src/Mod/Path/PathScripts/PathDressupHoldingTags.py +++ b/src/Mod/Path/PathScripts/PathDressupHoldingTags.py @@ -47,10 +47,11 @@ def translate(text, context = "PathDressup_HoldingTags", disambig=None): return QtCore.QCoreApplication.translate(context, text, disambig) -#PathLog.setLevel(PathLog.Level.DEBUG) +LOG_MODULE = 'PathDressupHoldingTags' +#PathLog.setLevel(PathLog.Level.DEBUG, LOG_MODULE) def debugEdge(edge, prefix, force = False): - if force or PathLog.getLevel() == PathLog.Level.DEBUG: + if force or PathLog.getLevel(LOG_MODULE) == PathLog.Level.DEBUG: pf = edge.valueAt(edge.FirstParameter) pl = edge.valueAt(edge.LastParameter) if type(edge.Curve) == Part.Line or type(edge.Curve) == Part.LineSegment: @@ -60,7 +61,7 @@ def debugEdge(edge, prefix, force = False): print("%s %s((%.2f, %.2f, %.2f) - (%.2f, %.2f, %.2f) - (%.2f, %.2f, %.2f))" % (prefix, type(edge.Curve), pf.x, pf.y, pf.z, pm.x, pm.y, pm.z, pl.x, pl.y, pl.z)) def debugMarker(vector, label, color = None, radius = 0.5): - if PathLog.getLevel() == PathLog.Level.DEBUG: + if PathLog.getLevel(LOG_MODULE) == PathLog.Level.DEBUG: obj = FreeCAD.ActiveDocument.addObject("Part::Sphere", label) obj.Label = label obj.Radius = radius @@ -69,7 +70,7 @@ def debugMarker(vector, label, color = None, radius = 0.5): obj.ViewObject.ShapeColor = color def debugCylinder(vector, r, height, label, color = None): - if PathLog.getLevel() == PathLog.Level.DEBUG: + if PathLog.getLevel(LOG_MODULE) == PathLog.Level.DEBUG: obj = FreeCAD.ActiveDocument.addObject("Part::Cylinder", label) obj.Label = label obj.Radius = r @@ -80,7 +81,7 @@ def debugCylinder(vector, r, height, label, color = None): obj.ViewObject.ShapeColor = color def debugCone(vector, r1, r2, height, label, color = None): - if PathLog.getLevel() == PathLog.Level.DEBUG: + if PathLog.getLevel(LOG_MODULE) == PathLog.Level.DEBUG: obj = FreeCAD.ActiveDocument.addObject("Part::Cone", label) obj.Label = label obj.Radius1 = r1 @@ -885,7 +886,7 @@ class ObjectDressup: def processTags(self, obj): tagID = 0 - if PathLog.getLevel() == PathLog.Level.DEBUG: + if PathLog.getLevel(LOG_MODULE) == PathLog.Level.DEBUG: for tag in self.tags: tagID += 1 if tag.enabled: @@ -1056,7 +1057,7 @@ class TaskPanel: self.obj.Proxy.execute(self.obj) self.updateTagsView() - #if PathLog.getLevel() == PathLog.Level.DEBUG: + #if PathLog.getLevel(LOG_MODULE) == PathLog.Level.DEBUG: # # this causes a big of an echo and a double click on the spin buttons, don't know why though # FreeCAD.ActiveDocument.recompute() From 287094cf830d2bf4643e53d6ccbeb8ac4bd92cbc Mon Sep 17 00:00:00 2001 From: Markus Lampert Date: Thu, 26 Jan 2017 10:47:33 -0800 Subject: [PATCH 3/3] Fixed moved dogbone to use logging module - and fixed a bug while I was at it. --- .../Path/PathScripts/PathDressupDogbone.py | 123 +++++++++--------- .../PathScripts/PathDressupHoldingTags.py | 4 +- 2 files changed, 67 insertions(+), 60 deletions(-) diff --git a/src/Mod/Path/PathScripts/PathDressupDogbone.py b/src/Mod/Path/PathScripts/PathDressupDogbone.py index 9aa008b7b7..dfc6788545 100644 --- a/src/Mod/Path/PathScripts/PathDressupDogbone.py +++ b/src/Mod/Path/PathScripts/PathDressupDogbone.py @@ -21,31 +21,26 @@ # * USA * # * * # *************************************************************************** +import DraftGeomUtils import FreeCAD import FreeCADGui -import Path -from PathScripts import PathUtils -from PathScripts.PathGeom import * -from PySide import QtCore, QtGui import math import Part -import DraftGeomUtils +import Path +import PathScripts.PathLog as PathLog + +from PathScripts import PathUtils +from PathScripts.PathGeom import PathGeom +from PySide import QtCore, QtGui """Dogbone Dressup object and FreeCAD command""" -debugDressup = False +LOG_MODULE = 'PathDressupDogbone' +#PathLog.setLevel(PathLog.Level.INFO, LOG_MODULE) # Qt tanslation handling -try: - _encoding = QtGui.QApplication.UnicodeUTF8 - - def translate(context, text, disambig=None): - return QtGui.QApplication.translate(context, text, disambig, _encoding) - -except AttributeError: - - def translate(context, text, disambig=None): - return QtGui.QApplication.translate(context, text, disambig) +def translate(text, context = "PathDressup_Dogbone", disambig=None): + return QtCore.QCoreApplication.translate(context, text, disambig) movecommands = ['G0', 'G00', 'G1', 'G01', 'G2', 'G02', 'G3', 'G03'] movestraight = ['G1', 'G01'] @@ -53,12 +48,8 @@ movecw = ['G2', 'G02'] moveccw = ['G3', 'G03'] movearc = movecw + moveccw -def debugPrint(msg): - if debugDressup: - print(msg) - def debugMarker(vector, label, color = None, radius = 0.5): - if debugDressup: + if PathLog.getLevel(LOG_MODULE) == PathLog.Level.DEBUG: obj = FreeCAD.ActiveDocument.addObject("Part::Sphere", label) obj.Label = label obj.Radius = radius @@ -67,7 +58,7 @@ def debugMarker(vector, label, color = None, radius = 0.5): obj.ViewObject.ShapeColor = color def debugCircle(vector, r, label, color = None): - if debugDressup: + if PathLog.getLevel(LOG_MODULE) == PathLog.Level.DEBUG: obj = FreeCAD.ActiveDocument.addObject("Part::Cylinder", label) obj.Label = label obj.Radius = r @@ -285,6 +276,7 @@ class Bone: self.inChord = inChord self.outChord = outChord self.smooth = smooth + self.smooth = Smooth.Neither def angle(self): if not hasattr(self, 'cAngle'): @@ -318,9 +310,9 @@ class Bone: # for some reason pi/2 is not equal to pi/2 if math.fabs(angle - boneAngle) < 0.00001: # moving directly towards the corner - debugPrint("adaptive - on target: %.2f - %.2f" % (distance, toolRadius)) + PathLog.debug("adaptive - on target: %.2f - %.2f" % (distance, toolRadius)) return distance - toolRadius - debugPrint("adaptive - angles: corner=%.2f bone=%.2f diff=%.12f" % (angle/math.pi, boneAngle/math.pi, angle - boneAngle)) + PathLog.debug("adaptive - angles: corner=%.2f bone=%.2f diff=%.12f" % (angle/math.pi, boneAngle/math.pi, angle - boneAngle)) # The bones root and end point form a triangle with the intersection of the tool path # with the toolRadius circle around the bone end point. @@ -331,7 +323,7 @@ class Bone: beta = math.fabs(addAngle(boneAngle, -angle)) D = (distance / toolRadius) * math.sin(beta) if D > 1: # no intersection - debugPrint("adaptive - no intersection - no bone") + PathLog.debug("adaptive - no intersection - no bone") return 0 gamma = math.asin(D) alpha = math.pi - beta - gamma @@ -343,7 +335,7 @@ class Bone: length2 = toolRadius * math.sin(alpha2) / math.sin(beta2) length = min(length, length2) - debugPrint("adaptive corner=%.2f * %.2f˚ -> bone=%.2f * %.2f˚" % (distance, angle, length, boneAngle)) + PathLog.debug("adaptive corner=%.2f * %.2f˚ -> bone=%.2f * %.2f˚" % (distance, angle, length, boneAngle)) return length def edges(self): @@ -390,26 +382,26 @@ class ObjectDressup: return outChord.foldsBackOrTurns(inChord, self.theOtherSideOf(obj.Side)) def findPivotIntersection(self, pivot, pivotEdge, edge, refPt, d, color): - debugPrint("Intersection (%.2f, %.2f)^%.2f - [(%.2f, %.2f), (%.2f, %.2f)]" % (pivotEdge.Curve.Center.x, pivotEdge.Curve.Center.y, pivotEdge.Curve.Radius, edge.Vertexes[0].Point.x, edge.Vertexes[0].Point.y, edge.Vertexes[1].Point.x, edge.Vertexes[1].Point.y)) + PathLog.track("(%.2f, %.2f)^%.2f - [(%.2f, %.2f), (%.2f, %.2f)]" % (pivotEdge.Curve.Center.x, pivotEdge.Curve.Center.y, pivotEdge.Curve.Radius, edge.Vertexes[0].Point.x, edge.Vertexes[0].Point.y, edge.Vertexes[1].Point.x, edge.Vertexes[1].Point.y)) ppt = None pptDistance = 0 for pt in DraftGeomUtils.findIntersection(edge, pivotEdge, dts=False): #debugMarker(pt, "pti.%d-%s.in" % (self.boneId, d), color, 0.2) distance = (pt - refPt).Length - debugPrint(" --> (%.2f, %.2f): %.2f" % (pt.x, pt.y, distance)) + PathLog.debug(" --> (%.2f, %.2f): %.2f" % (pt.x, pt.y, distance)) if not ppt or pptDistance < distance: ppt = pt pptDistance = distance if not ppt: tangent = DraftGeomUtils.findDistance(pivot, edge) if tangent: - debugPrint("Taking tangent as intersect %s" % tangent) + PathLog.debug("Taking tangent as intersect %s" % tangent) ppt = pivot + tangent else: - debugPrint("Taking chord start as intersect %s" % inChordStart) + PathLog.debug("Taking chord start as intersect %s" % inChordStart) ppt = inChord.Start #debugMarker(ppt, "ptt.%d-%s.in" % (self.boneId, d), color, 0.2) - debugPrint(" --> (%.2f, %.2f)" % (ppt.x, ppt.y)) + PathLog.debug(" --> (%.2f, %.2f)" % (ppt.x, ppt.y)) return ppt def pointIsOnEdge(self, point, edge): @@ -418,7 +410,7 @@ class ObjectDressup: def smoothChordCommands(self, bone, inChord, outChord, edge, wire, corner, smooth, color = None): if smooth == 0: - debugPrint(" No smoothing requested") + PathLog.info(" No smoothing requested") return [ bone.lastCommand, outChord.g1Command() ] d = 'in' @@ -428,32 +420,32 @@ class ObjectDressup: refPoint = outChord.End if DraftGeomUtils.areColinear(inChord.asEdge(), outChord.asEdge()): - debugPrint(" straight edge %s" % d) + PathLog.info(" straight edge %s" % d) return [ outChord.g1Command() ] pivot = None pivotDistance = 0 - debugPrint("smooth: (%.2f, %.2f)-(%.2f, %.2f)" % (edge.Vertexes[0].Point.x, edge.Vertexes[0].Point.y, edge.Vertexes[1].Point.x, edge.Vertexes[1].Point.y)) + PathLog.info("smooth: (%.2f, %.2f)-(%.2f, %.2f)" % (edge.Vertexes[0].Point.x, edge.Vertexes[0].Point.y, edge.Vertexes[1].Point.x, edge.Vertexes[1].Point.y)) for e in wire.Edges: self.dbg.append(e) if type(e.Curve) == Part.LineSegment or type(e.Curve) == Part.Line: - debugPrint(" (%.2f, %.2f)-(%.2f, %.2f)" % (e.Vertexes[0].Point.x, e.Vertexes[0].Point.y, e.Vertexes[1].Point.x, e.Vertexes[1].Point.y)) + PathLog.debug(" (%.2f, %.2f)-(%.2f, %.2f)" % (e.Vertexes[0].Point.x, e.Vertexes[0].Point.y, e.Vertexes[1].Point.x, e.Vertexes[1].Point.y)) else: - debugPrint(" (%.2f, %.2f)^%.2f" % (e.Curve.Center.x, e.Curve.Center.y, e.Curve.Radius)) + PathLog.debug(" (%.2f, %.2f)^%.2f" % (e.Curve.Center.x, e.Curve.Center.y, e.Curve.Radius)) for pt in DraftGeomUtils.findIntersection(edge, e, True, findAll=True): if not PathGeom.pointsCoincide(pt, corner) and self.pointIsOnEdge(pt, e): - debugMarker(pt, "candidate-%d-%s" % (self.boneId, d), color, 0.05) - debugPrint(" -> candidate") + #debugMarker(pt, "candidate-%d-%s" % (self.boneId, d), color, 0.05) + PathLog.debug(" -> candidate") distance = (pt - refPoint).Length if not pivot or pivotDistance > distance: pivot = pt pivotDistance = distance else: - debugPrint(" -> corner intersect") + PathLog.debug(" -> corner intersect") if pivot: - debugCircle(pivot, self.toolRadius, "pivot.%d-%s" % (self.boneId, d), color) + #debugCircle(pivot, self.toolRadius, "pivot.%d-%s" % (self.boneId, d), color) pivotEdge = Part.Edge(Part.Circle(pivot, FreeCAD.Vector(0,0,1), self.toolRadius)) t1 = self.findPivotIntersection(pivot, pivotEdge, inChord.asEdge(), inChord.End, d, color) @@ -461,16 +453,16 @@ class ObjectDressup: commands = [] if not PathGeom.pointsCoincide(t1, inChord.Start): - debugPrint(" add lead in") + PathLog.debug(" add lead in") commands.append(Chord(inChord.Start, t1).g1Command()) if bone.obj.Side == Side.Left: - debugPrint(" add g3 command") + PathLog.debug(" add g3 command") commands.append(Chord(t1, t2).g3Command(pivot)) else: - debugPrint(" add g2 command center=(%.2f, %.2f) -> from (%2f, %.2f) to (%.2f, %.2f" % (pivot.x, pivot.y, t1.x, t1.y, t2.x, t2.y)) + PathLog.debug(" add g2 command center=(%.2f, %.2f) -> from (%2f, %.2f) to (%.2f, %.2f" % (pivot.x, pivot.y, t1.x, t1.y, t2.x, t2.y)) commands.append(Chord(t1, t2).g2Command(pivot)) if not PathGeom.pointsCoincide(t2, outChord.End): - debugPrint(" add lead out") + PathLog.debug(" add lead out") commands.append(Chord(t2, outChord.End).g1Command()) #debugMarker(pivot, "pivot.%d-%s" % (self.boneId, d), color, 0.2) @@ -479,7 +471,7 @@ class ObjectDressup: return commands - debugPrint(" no pivot found - straight command") + PathLog.info(" no pivot found - straight command") return [ inChord.g1Command(), outChord.g1Command() ] def inOutBoneCommands(self, bone, boneAngle, fixedLength): @@ -487,8 +479,8 @@ class ObjectDressup: bone.tip = bone.inChord.End # in case there is no bone - debugPrint("corner = (%.2f, %.2f)" % (corner.x, corner.y)) - debugMarker(corner, 'corner', (1., 0., 1.), self.toolRadius) + PathLog.debug("corner = (%.2f, %.2f)" % (corner.x, corner.y)) + #debugMarker(corner, 'corner', (1., 0., 1.), self.toolRadius) length = fixedLength if bone.obj.Incision == Incision.Custom: @@ -497,7 +489,7 @@ class ObjectDressup: length = bone.adaptiveLength(boneAngle, self.toolRadius) if length == 0: - # no bone after all .. + PathLog.info("no bone after all ..") return [ bone.lastCommand, bone.outChord.g1Command() ] boneInChord = bone.inChord.move(length, boneAngle) @@ -576,7 +568,7 @@ class ObjectDressup: onInString = 'out' if onIn: onInString = 'in' - debugPrint("tboneEdge boneAngle[%s]=%.2f (in=%.2f, out=%.2f)" % (onInString, boneAngle/math.pi, bone.inChord.getAngleXY()/math.pi, bone.outChord.getAngleXY()/math.pi)) + PathLog.debug("tboneEdge boneAngle[%s]=%.2f (in=%.2f, out=%.2f)" % (onInString, boneAngle/math.pi, bone.inChord.getAngleXY()/math.pi, bone.outChord.getAngleXY()/math.pi)) return self.inOutBoneCommands(bone, boneAngle, self.toolRadius) def tboneLongEdge(self, bone): @@ -619,21 +611,21 @@ class ObjectDressup: return [ bone.lastCommand, bone.outChord.g1Command() ] def insertBone(self, bone): - debugPrint(">----------------------------------- %d --------------------------------------" % bone.boneId) + PathLog.debug(">----------------------------------- %d --------------------------------------" % bone.boneId) self.boneShapes = [] blacklisted, inaccessible = self.boneIsBlacklisted(bone) enabled = not blacklisted self.bones.append((bone.boneId, bone.location(), enabled, inaccessible)) self.boneId = bone.boneId - if debugDressup and bone.boneId > 2: + if False and PathLog.getLevel(LOG_MODULE) == PathLog.Level.DEBUG and bone.boneId > 2: commands = self.boneCommands(bone, False) else: commands = self.boneCommands(bone, enabled) bone.commands = commands self.shapes[bone.boneId] = self.boneShapes - debugPrint("<----------------------------------- %d --------------------------------------" % bone.boneId) + PathLog.debug("<----------------------------------- %d --------------------------------------" % bone.boneId) return commands def removePathCrossing(self, commands, bone1, bone2): @@ -652,7 +644,7 @@ class ObjectDressup: #debugCircle(e2.Curve.Center, e2.Curve.Radius, "bone.%d-2" % (self.boneId), (0.,1.,0.)) if PathGeom.pointsCoincide(pt, e1.valueAt(e1.LastParameter)) or PathGeom.pointsCoincide(pt, e2.valueAt(e2.FirstParameter)): continue - debugMarker(pt, "it", (0.0, 1.0, 1.0)) + #debugMarker(pt, "it", (0.0, 1.0, 1.0)) # 1. remove all redundant commands commands = commands[:-(len(inEdges) - i)] # 2., correct where c1 ends @@ -702,40 +694,52 @@ class ObjectDressup: boneIserted = False for thisCommand in obj.Base.Path.Commands: + PathLog.info("Command: %s" % thisCommand) if thisCommand.Name in movecommands: thisChord = lastChord.moveToParameters(thisCommand.Parameters) thisIsACandidate = self.canAttachDogbone(thisCommand, thisChord) if thisIsACandidate and lastCommand and self.shouldInsertDogbone(obj, lastChord, thisChord): + PathLog.info(" Found bone corner") bone = Bone(boneId, obj, lastCommand, lastChord, thisChord, Smooth.InAndOut) bones = self.insertBone(bone) boneId += 1 if lastBone: + PathLog.info(" removing potential path crossing") #debugMarker(thisChord.Start, "it", (1.0, 0.0, 1.0)) commands, bones = self.removePathCrossing(commands, lastBone, bone) commands.extend(bones[:-1]) lastCommand = bones[-1] lastBone = bone elif lastCommand and thisChord.isAPlungeMove(): + PathLog.info(" Looking for connection in odds and ends") + haveNewLastCommand = False for chord in (chord for chord in oddsAndEnds if lastChord.connectsTo(chord)): if self.shouldInsertDogbone(obj, lastChord, chord): + PathLog.info(" and there is one") bone = Bone(boneId, obj, lastCommand, lastChord, chord, Smooth.In) bones = self.insertBone(bone) boneId += 1 if lastBone: + PathLog.info(" removing potential path crossing") #debugMarker(chord.Start, "it", (0.0, 1.0, 1.0)) commands, bones = self.removePathCrossing(commands, lastBone, bone) commands.extend(bones[:-1]) lastCommand = bones[-1] + haveNewLastCommand = True + if not haveNewLastCommand: + commands.append(lastCommand) lastCommand = None commands.append(thisCommand) lastBone = None elif thisIsACandidate: + PathLog.info(" is a candidate, keeping for later") if lastCommand: commands.append(lastCommand) lastCommand = thisCommand lastBone = None else: + PathLog.info(" nope") if lastCommand: commands.append(lastCommand) lastCommand = None @@ -743,21 +747,24 @@ class ObjectDressup: lastBone = None if lastChord.isAPlungeMove() and thisIsACandidate: + PathLog.info(" adding to odds and ends") oddsAndEnds.append(thisChord) lastChord = thisChord else: + PathLog.info(" Clean slate") if lastCommand: commands.append(lastCommand) lastCommand = None commands.append(thisCommand) + lastBone = None #for cmd in commands: - # debugPrint("cmd = '%s'" % cmd) + # PathLog.debug("cmd = '%s'" % cmd) path = Path.Path(commands) obj.Path = path def setup(self, obj): - debugPrint("Here we go ... ") + PathLog.info("Here we go ... ") if hasattr(obj.Base, "BoneBlacklist"): # dressing up a bone dressup obj.Side = obj.Base.Side @@ -861,18 +868,18 @@ class TaskPanel: self.form.customLabel.setEnabled(customSelected) self.updateBoneList() - if debugDressup: + if PathLog.getLevel(LOG_MODULE) == PathLog.Level.DEBUG: for obj in FreeCAD.ActiveDocument.Objects: if obj.Name.startswith('Shape'): FreeCAD.ActiveDocument.removeObject(obj.Name) print('object name %s' % self.obj.Name) if hasattr(self.obj.Proxy, "shapes"): - debugPrint("showing shapes attribute") + PathLog.info("showing shapes attribute") for shapes in self.obj.Proxy.shapes.itervalues(): for shape in shapes: Part.show(shape) else: - debugPrint("no shapes attribute found") + PathLog.info("no shapes attribute found") def updateModel(self): diff --git a/src/Mod/Path/PathScripts/PathDressupHoldingTags.py b/src/Mod/Path/PathScripts/PathDressupHoldingTags.py index 215c6f0fc0..b279d33faf 100644 --- a/src/Mod/Path/PathScripts/PathDressupHoldingTags.py +++ b/src/Mod/Path/PathScripts/PathDressupHoldingTags.py @@ -35,8 +35,8 @@ import math from DraftGui import todo from PathScripts import PathUtils -from PathScripts.PathGeom import * -from PathScripts.PathPreferences import * +from PathScripts.PathGeom import PathGeom +from PathScripts.PathPreferences import PathPreferences from PySide import QtCore, QtGui from pivy import coin