Added loop detection for vertical faces and enhanced usability of loop select command accordingly.

This commit is contained in:
Markus Lampert
2017-09-18 00:44:46 -07:00
parent fd3b2220a5
commit 01b0225c4e
3 changed files with 61 additions and 8 deletions

View File

@@ -25,7 +25,8 @@
import FreeCAD
import PathScripts
from PathScripts.PathUtils import loopdetect
from PathScripts.PathUtils import horizontalLoop
from PathScripts.PathUtils import horizontalEdgeLoop
from PathScripts.PathUtils import horizontalFaceLoop
from PathScripts.PathUtils import addToJob
from PathScripts.PathUtils import findParentJob
@@ -57,8 +58,10 @@ class _CommandSelectLoop:
sel = FreeCADGui.Selection.getSelectionEx()[0]
sub1 = sel.SubElementNames[0]
if sub1[0:4] != 'Edge':
if len(sel.SubElementNames) == 1 and sub1[0:4] == 'Face' and horizontalFaceLoop(sel.Object, sel.SubObjects[0]):
return True
return False
if len(sel.SubElementNames) == 1 and horizontalLoop(sel.Object, sel.SubObjects[0]):
if len(sel.SubElementNames) == 1 and horizontalEdgeLoop(sel.Object, sel.SubObjects[0]):
return True
sub2 = sel.SubElementNames[1]
if sub2[0:4] != 'Edge':
@@ -72,11 +75,19 @@ class _CommandSelectLoop:
obj = sel.Object
edge1 = sel.SubObjects[0]
if len(sel.SubObjects) == 1:
loopwire = horizontalLoop(obj, edge1)
if 'Face' in sel.SubElementNames[0]:
loop = horizontalFaceLoop(sel.Object, sel.SubObjects[0])
if loop:
FreeCADGui.Selection.clearSelection()
FreeCADGui.Selection.addSelection(sel.Object, loop)
loopwire = []
else:
loopwire = horizontalEdgeLoop(obj, edge1)
else:
edge2 = sel.SubObjects[1]
loopwire = loopdetect(obj, edge1, edge2)
if loopwire is not None:
if loopwire:
FreeCADGui.Selection.clearSelection()
elist = obj.Shape.Edges
for e in elist:

View File

@@ -39,7 +39,7 @@ __author__ = "sliptonic (Brad Collette)"
__url__ = "http://www.freecadweb.org"
__doc__ = "Class and implementation of shape based Pocket operation."
if True:
if False:
PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule())
PathLog.trackModule(PathLog.thisModule())
else:

View File

@@ -29,6 +29,7 @@ import numpy
import Part
import Path
import PathScripts
import TechDraw
from DraftGeomUtils import geomType
from FreeCAD import Vector
@@ -216,15 +217,56 @@ def loopdetect(obj, edge1, edge2):
loopwire = next(x for x in loop)[1]
return loopwire
def horizontalLoop(obj, edge):
'''horizontalLoopWire(obj, edge) ... returns a wire in the horizontal plane, if that is the only horizontal wire the given edge is a part of.'''
def horizontalEdgeLoop(obj, edge):
'''horizontalEdgeLoop(obj, edge) ... returns a wire in the horizontal plane, if that is the only horizontal wire the given edge is a part of.'''
h = edge.hashCode()
wires = [w for w in obj.Shape.Wires if any(e.hashCode() == h for e in w.Edges)]
loops = [w for w in wires if PathGeom.isVertical(Part.Face(w).Surface.Axis)]
loops = [w for w in wires if PathGeom.isHorizontal(Part.Face(w))]
if len(loops) == 1:
return loops[0]
return None
def horizontalFaceLoop(obj, face):
'''horizontalFaceLoop(obj, face) ... returns a list of face names which form the walls of a vertical hole face is a part of.'''
if not face and not obj:
sel = FreeCADGui.Selection.getSelectionEx()[0]
obj = sel.Object
face = sel.SubObjects[0]
wires = [horizontalEdgeLoop(obj, e) for e in face.Edges]
# Not sure if sorting by Area is a premature optimization - but it seems
# the loop we're looking for is typically the biggest of the them all.
wires = sorted([w for w in wires if w], key=lambda w: Part.Face(w).Area)
for wire in wires:
hashes = [e.hashCode() for e in wire.Edges]
#find all faces that share a an edge with the wire and are vertical
faces = ["Face%d"%(i+1) for i,f in enumerate(obj.Shape.Faces) if any(e.hashCode() in hashes for e in f.Edges) and PathGeom.isVertical(f)]
# verify they form a valid hole by getting the outline and comparing
# the resulting XY footprint with that of the faces
comp = Part.makeCompound([obj.Shape.getElement(f) for f in faces])
outline = TechDraw.findShapeOutline(comp, 1, FreeCAD.Vector(0,0,1))
# findShapeOutline always returns closed wires, by removing the
# trace-backs single edge spikes don't contriubte to the bound box
uniqueEdges = []
for edge in outline.Edges:
if any(PathGeom.edgesMatch(edge, e) for e in uniqueEdges):
continue
uniqueEdges.append(edge)
w = Part.Wire(uniqueEdges)
# if the faces really form the walls of a hole then the resulting
# wire is still closed and it still has the same footprint
bb1 = comp.BoundBox
bb2 = w.BoundBox
if w.isClosed() and PathGeom.isRoughly(bb1.XMin, bb2.XMin) and PathGeom.isRoughly(bb1.XMax, bb2.XMax) and PathGeom.isRoughly(bb1.YMin, bb2.YMin) and PathGeom.isRoughly(bb1.YMax, bb2.YMax):
return faces
return None
def filterArcs(arcEdge):
'''filterArcs(Edge) -used to split arcs that over 180 degrees. Returns list '''
PathLog.track()