Files
create/src/Mod/Path/PathScripts/PathSelection.py
2015-07-23 23:17:15 -03:00

227 lines
8.6 KiB
Python

# -*- coding: utf-8 -*-
#***************************************************************************
#* *
#* Copyright (c) 2015 Dan Falck <ddfalck@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 *
#* *
#***************************************************************************
'''Path selection function select a face or faces, two edges, etc to get a dictionary with what was selected in order '''
import FreeCAD,FreeCADGui
import Part
from FreeCAD import Vector
def equals(p1,p2):
'''returns True if vertexes have same coordinates within precision amount of digits '''
precision = 12 #hardcoded
p=precision
u = Vector(p1.X,p1.Y,p1.Z)
v = Vector(p2.X,p2.Y,p2.Z)
vector = (u.sub(v))
isNull = (round(vector.x,p)==0 and round(vector.y,p)==0 and round(vector.z,p)==0)
return isNull
def Sort2Edges(edgelist):
'''Sort2Edges(edgelist) simple function to reorder the start and end pts of two edges
based on their selection order. Returns the list, the start point,
and their common point, => edgelist, vertex, vertex'''
if len(edgelist)>=2:
vlist = []
e0 = edgelist[0]
e1=edgelist[1]
a0 = e0.Vertexes[0]
a1 = e0.Vertexes[1]
b0 = e1.Vertexes[0]
b1 = e1.Vertexes[1]
# comparison routine to order two edges:
if equals(a1,b0):
vlist.append((a0.Point.x,a0.Point.y))
vlist.append((a1.Point.x,a1.Point.y))
vlist.append((b1.Point.x,b1.Point.y))
if equals(a0,b0):
vlist.append((a1.Point.x,a1.Point.y))
vlist.append((a0.Point.x,a0.Point.y))
vlist.append((b1.Point.x,b1.Point.y))
if equals(a0,b1):
vlist.append((a1.Point.x,a1.Point.y))
vlist.append((a0.Point.x,a0.Point.y))
vlist.append((b0.Point.x,b0.Point.y))
if equals(a1,b1):
vlist.append((a0.Point.x,a0.Point.y))
vlist.append((a1.Point.x,a1.Point.y))
vlist.append((b0.Point.x,b0.Point.y))
edgestart = Vector(vlist[0][0],vlist[0][1],e0.Vertexes[1].Z)
edgecommon = Vector(vlist[1][0],vlist[1][1],e0.Vertexes[1].Z)
return vlist,edgestart,edgecommon
def segments(poly):
''' A sequence of (x,y) numeric coordinates pairs '''
return zip(poly, poly[1:] + [poly[0]])
def check_clockwise(poly):
'''
check_clockwise(poly) a function for returning a boolean if the selected wire is clockwise or counter clockwise
based on point order. poly = [(x1,y1),(x2,y2),(x3,y3)]
'''
clockwise = False
if (sum(x0*y1 - x1*y0 for ((x0, y0), (x1, y1)) in segments(poly))) < 0:
clockwise = not clockwise
return clockwise
def multiSelect():
'''
multiSelect() A function for selecting elements of an object for CNC path operations.
Select just a face, an edge,or two edges to indicate direction, a vertex on the object, a point not on the object,
or some combination. Returns a dictionary.
'''
sel = FreeCADGui.Selection.getSelectionEx()
numobjs = len([selobj.Object for selobj in sel])
if numobjs == 0:
FreeCAD.Console.PrintError('Please select some objects and try again.\n')
return
goodselect = False
for s in sel:
for i in s.SubObjects:
if i.ShapeType == 'Face':
goodselect = True
if i.ShapeType == 'Edge':
goodselect = True
if i.ShapeType == 'Vertex':
goodselect = True
if not goodselect:
FreeCAD.Console.PrintError('Please select a face and/or edges along with points (optional) and try again.\n')
return
selItems = {}
selItems['objname']=None #the parent object name - a 3D solid
selItems['pointlist']=None #start and end points
selItems['pointnames']=None #names of points for document object
selItems['facenames']=None # the selected face name
selItems['facelist']=None #list of faces selected
selItems['edgelist']=None #some edges that could be selected along with points and faces
selItems['edgenames']=None
selItems['pathwire']=None #the whole wire around edges of the face
selItems['clockwise']=None
selItems['circles']=None
facenames = []
edgelist =[]
edgenames=[]
ptlist=[]
ptnames=[]
circlelist=[]
face = False
edges = False
points = False
wireobj = False
circles = False
facelist= []
for s in sel:
if s.Object.Shape.ShapeType in ['Solid','Compound','Wire','Vertex']:
if not (s.Object.Shape.ShapeType =='Vertex'):
objname = s.ObjectName
selItems['objname'] =objname
if s.Object.Shape.ShapeType == 'Wire':
wireobj = True
if s.Object.Shape.ShapeType == 'Vertex':
ptnames.append(s.ObjectName)
# ptlist.append(s.Object)
points = True
for sub in s.SubObjects:
if sub.ShapeType =='Face':
facelist.append(sub)
face = True
if sub.ShapeType =='Edge':
edge = sub
edgelist.append(edge)
edges = True
if isinstance(sub.Curve,Part.Circle):
circlelist.append(edge)
circles = True
if sub.ShapeType =='Vertex':
ptlist.append(sub)
points = True
for sub in s.SubElementNames:
if 'Face' in sub:
facename = sub
facenames.append(facename)
if 'Edge' in sub:
edgenames.append(sub)
# now indicate which wire is going to be processed, based on which edges are selected
if facelist:
selItems['facelist']=facelist
if edges:
if face:
selItems['edgelist'] =edgelist
for fw in facelist[0].Wires:
for e in fw.Edges:
if e.isSame(edge):
pathwire = fw
selItems['pathwire'] =pathwire
elif wireobj:
selItems['pathwire'] =s.Object.Shape
selItems['edgelist'] =edgelist
else:
for w in s.Object.Shape.Wires:
for e in w.Edges:
if e.BoundBox.ZMax == e.BoundBox.ZMin: #if they are on same plane in Z as sel edge
if e.isSame(edge):
pathwire = w
selItems['pathwire'] =pathwire
selItems['edgelist'] =edgelist
if not edges:
if face:
selItems['pathwire'] =facelist[0].OuterWire
if edges and (len(edgelist)>=2):
vlist,edgestart,edgecommon=Sort2Edges(edgelist)
edgepts ={}
edgepts['vlist'] = vlist
edgepts['edgestart']=edgestart # start point of edges selected
edgepts['edgecommon']=edgecommon # point where two edges join- will be last point in in first gcode line
selItems['edgepts']=edgepts
if check_clockwise(vlist):
selItems['clockwise']=True
elif check_clockwise(vlist) == False:
selItems['clockwise']=False
if points:
selItems['pointlist'] = ptlist
selItems['pointnames'] = ptnames
if edges:
selItems['edgenames']=edgenames
if face:
selItems['facenames'] = facenames
if circles:
selItems['circles'] = circlelist
return selItems