Added solid detection and consolidated PathJob Base selection option (removed empty option).

This commit is contained in:
Markus Lampert
2017-06-10 16:30:52 -07:00
parent 71f03bd0bd
commit 1ce3b242f2
6 changed files with 176 additions and 24 deletions

View File

@@ -63,6 +63,7 @@ SET(PathScripts_SRCS
PathScripts/PathToolController.py
PathScripts/PathToolLenOffset.py
PathScripts/PathToolLibraryManager.py
PathScripts/PathUtil.py
PathScripts/PathUtils.py
PathScripts/PostUtils.py
PathScripts/__init__.py
@@ -83,15 +84,16 @@ SET(PathScripts_SRCS
SET(PathTests_SRCS
PathTests/__init__.py
PathTests/PathTestUtils.py
PathTests/test_linuxcnc_00.ngc
PathTests/TestPathCore.py
PathTests/TestPathDepthParams.py
PathTests/TestPathDressupHoldingTags.py
PathTests/TestPathGeom.py
PathTests/TestPathLog.py
PathTests/TestPathPost.py
PathTests/__init__.py
PathTests/test_linuxcnc_00.ngc
PathTests/TestPathUtil.py
)
SET(all_files

View File

@@ -28,6 +28,7 @@ import FreeCAD
import Path
import PathScripts.PathLog as PathLog
import PathScripts.PathToolController as PathToolController
import PathScripts.PathUtil as PathUtil
import glob
import lxml.etree as xml
import os
@@ -66,7 +67,7 @@ class JobTemplate:
class ObjectPathJob:
def __init__(self, obj, base, template = ""):
def __init__(self, obj, base, template = None):
self.obj = obj
obj.addProperty("App::PropertyFile", "PostProcessorOutputFile", "Output", QtCore.QT_TRANSLATE_NOOP("App::Property","The NC output file for this project"))
obj.PostProcessorOutputFile = PathPreferences.defaultOutputFile()
@@ -117,7 +118,7 @@ class ObjectPathJob:
obj.Description = job.get(JobTemplate.Description)
for tc in tree.getroot().iter(JobTemplate.ToolController):
PathToolController.CommandPathToolController.FromTemplate(obj, tc)
else:
elif template is not None:
PathToolController.CommandPathToolController.Create(obj.Name)
def templateAttrs(self, obj):
@@ -160,6 +161,16 @@ class ObjectPathJob:
path = Path.Path(cmds)
obj.Path = path
@classmethod
def baseCandidates(cls):
'''Answer all objects in the current document which could serve as a Base for a job.'''
return sorted(filter(lambda obj: cls.isBaseCandidate(obj) , FreeCAD.ActiveDocument.Objects), key=lambda o: o.Label)
@classmethod
def isBaseCandidate(cls, obj):
'''Answer true if the given object can be used as a Base for a job.'''
return PathUtil.isSolid(obj) or (hasattr(obj, 'Proxy') and isinstance(obj.Proxy, ArchPanel.PanelSheet))
class ViewProviderJob:
@@ -218,10 +229,8 @@ class TaskPanel:
self.obj.PostProcessor = postProcessors
self.obj.PostProcessor = currentPostProcessor
self.form.cboBaseObject.addItem("")
for o in FreeCAD.ActiveDocument.Objects:
if hasattr(o, "Shape"):
self.form.cboBaseObject.addItem(o.Name)
for o in ObjectPathJob.baseCandidates():
self.form.cboBaseObject.addItem(o.Label)
self.postProcessorDefaultTooltip = self.form.cboPostProcessor.toolTip()
@@ -271,7 +280,7 @@ class TaskPanel:
for index in xrange(self.form.PathsList.count()):
item = self.form.PathsList.item(index)
for olditem in oldlist:
if olditem.Name == item.text():
if olditem.Label == item.text():
newlist.append(olditem)
self.obj.Group = newlist
@@ -305,14 +314,14 @@ class TaskPanel:
self.form.PathsList.clear()
for child in self.obj.Group:
self.form.PathsList.addItem(child.Name)
self.form.PathsList.addItem(child.Label)
baseindex = -1
if self.obj.Base:
baseindex = self.form.cboBaseObject.findText(self.obj.Base.Name, QtCore.Qt.MatchFixedString)
baseindex = self.form.cboBaseObject.findText(self.obj.Base.Label, QtCore.Qt.MatchFixedString)
else:
for o in FreeCADGui.Selection.getCompleteSelection():
baseindex = self.form.cboBaseObject.findText(o.Name, QtCore.Qt.MatchFixedString)
baseindex = self.form.cboBaseObject.findText(o.Label, QtCore.Qt.MatchFixedString)
if baseindex >= 0:
self.form.cboBaseObject.setCurrentIndex(baseindex)
@@ -348,10 +357,10 @@ class DlgJobCreate:
else:
selected = None
index = 0
for solid in sorted(filter(lambda obj: (hasattr(obj, 'Shape') and obj.Shape.isClosed()) or (hasattr(obj, 'Proxy') and isinstance(obj.Proxy, ArchPanel.PanelSheet)), FreeCAD.ActiveDocument.Objects), key=lambda o: o.Label):
if solid.Label == selected:
for base in ObjectPathJob.baseCandidates():
if base.Label == selected:
index = self.dialog.cbModel.count()
self.dialog.cbModel.addItem(solid.Label)
self.dialog.cbModel.addItem(base.Label)
self.dialog.cbModel.setCurrentIndex(index)
templateFiles = []

View File

@@ -0,0 +1,51 @@
# -*- 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 *
# * *
# ***************************************************************************
'''
The purpose of this file is to collect some handy functions. The reason they
are not in PathUtils (and there is this confusing naming going on) is that
PathUtils depends on PathJob. Which makes it impossible to use the functions
and classes defined there in PathJob.
So if you add to this file and think about importing anything from PathScripts
other than PathLog, then it probably doesn't belong here.
'''
import PathScripts.PathLog as PathLog
PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule())
def isSolid(obj):
'''isSolid(obj) ... returns true if an object represents a solid.'''
if hasattr(obj, 'Tip'):
return isSolid(obj.Tip)
if hasattr(obj, 'Shape'):
if obj.Shape.ShapeType == 'Solid' and obj.Shape.isClosed():
return True
if obj.Shape.ShapeType == 'Compound':
if hasattr(obj, 'Base') and hasattr(obj, 'Tool'):
return isSolid(obj.Base) and isSolid(obj.Tool)
return False

View File

@@ -46,8 +46,7 @@ class PathPostTestCases(unittest.TestCase):
# Create job and setup tool library + default tool
job = self.doc.addObject("Path::FeatureCompoundPython", "Job")
PathScripts.PathJob.ObjectPathJob(job)
job.Base = self.doc.Box
PathScripts.PathJob.ObjectPathJob(job, box, None)
PathScripts.PathToolController.CommandPathToolController.Create(job.Name, False)
tool1 = Path.Tool()
tool1.Diameter = 5.0

View File

@@ -0,0 +1,92 @@
# -*- 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 *
# * *
# ***************************************************************************
import FreeCAD
import Part
import Path
import PathScripts.PathUtil as PathUtil
import Sketcher
import TestSketcherApp
from PathTests.PathTestUtils import PathTestBase
class TestPathUtil(PathTestBase):
def setUp(self):
self.doc = FreeCAD.newDocument("TestPathUtils")
def tearDown(self):
FreeCAD.closeDocument("TestPathUtils")
def test00(self):
'''Check that isSolid detects solids.'''
box = self.doc.addObject('Part::Box', 'Box')
cylinder = self.doc.addObject('Part::Cylinder', 'Cylinder')
self.doc.recompute()
self.assertTrue(PathUtil.isSolid(box))
self.assertTrue(PathUtil.isSolid(cylinder))
def test01(self):
'''Check that isSolid detects PDs.'''
body = self.doc.addObject('PartDesign::Body', 'Body')
box = self.doc.addObject('PartDesign::AdditiveBox', 'Box')
body.addObject(box)
self.doc.recompute()
self.assertTrue(PathUtil.isSolid(body))
def test02(self):
'''Check that isSolid detects compounds.'''
box = self.doc.addObject('Part::Box', 'Box')
box.Length = 10
box.Width = 10
box.Height = 1
box.Placement = FreeCAD.Placement(FreeCAD.Vector(-5,-5,0), FreeCAD.Rotation(FreeCAD.Vector(0,0,1), 0))
cyl = self.doc.addObject('Part::Cylinder', 'Cylinder')
cyl.Radius = 1
cyl.Height = 10
box.Placement = FreeCAD.Placement(FreeCAD.Vector(0,0,-5), FreeCAD.Rotation(FreeCAD.Vector(0,0,1), 0))
cut = self.doc.addObject('Part::Cut', 'Cut')
cut.Base = box
cut.Tool = cyl
self.doc.recompute()
self.assertTrue(PathUtil.isSolid(cut))
def test03(self):
'''Check that isSolid ignores sketches.'''
body = self.doc.addObject('PartDesign::Body', 'Body')
sketch = self.doc.addObject('Sketcher::SketchObject', 'Sketch')
body.addObject(sketch)
TestSketcherApp.CreateSlotPlateSet(sketch)
self.doc.recompute()
pad = self.doc.addObject('PartDesign::Pad', 'Pad')
body.addObject(pad)
pad.Profile = sketch
self.doc.recompute()
# the body and the pad are solids
self.assertTrue(PathUtil.isSolid(pad))
self.assertTrue(PathUtil.isSolid(body))
# however, the sketch is no
self.assertFalse(PathUtil.isSolid(sketch))

View File

@@ -24,11 +24,10 @@
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.TestPathLog import TestPathLog
from PathTests.TestPathCore import TestPathCore
from PathTests.TestPathPost import PathPostTestCases
from PathTests.TestPathGeom import TestPathGeom
from PathTests.TestPathUtil import TestPathUtil
from PathTests.TestPathDepthParams import depthTestCases
from PathTests.TestPathDressupHoldingTags import TestHoldingTags