''' Collection of helper function to extract geometry properties from OCC elements Most of the functions are borrowed directly from assembly2lib.py or lib3D.py in assembly2 ''' import FreeCAD, FreeCADGui, Part import numpy as np from .FCADLogger import FCADLogger rootlogger = FCADLogger('asm3') logger = FCADLogger('asm3.main',parent=rootlogger) guilogger = FCADLogger('asm3.gui',parent=rootlogger) cstrlogger = FCADLogger('asm3.cstr',parent=rootlogger) syslogger = FCADLogger('asm3.sys',parent=rootlogger) proxylogger = FCADLogger('asm3.proxy',parent=rootlogger) import sys, os modulePath = os.path.dirname(os.path.realpath(__file__)) from PySide.QtCore import Qt from PySide.QtGui import QIcon, QPainter, QPixmap iconPath = os.path.join(modulePath,'Gui','Resources','icons') pixmapDisabled = QPixmap(os.path.join(iconPath,'Assembly_Disabled.svg')) iconSize = (16,16) def getIcon(obj,disabled=False,path=None): if not path: path = iconPath if not getattr(obj,'_icon',None): obj._icon = QIcon(os.path.join(path,obj._iconName)) if not disabled: return obj._icon if not getattr(obj,'_iconDisabled',None): pixmap = obj._icon.pixmap(*iconSize,mode=QIcon.Disabled) icon = QIcon(pixmapDisabled) icon.paint(QPainter(pixmap), 0,0,iconSize[0],iconSize[1],Qt.AlignCenter) obj._iconDisabled = QIcon(pixmap) return obj._iconDisabled def addIconToFCAD(iconFile,path=None): iconName = ':asm3/icons/' + iconFile if not path: path = iconPath try: path = os.path.join(path,iconFile) FreeCADGui.addIcon(iconName,path) except AssertionError: pass return iconName def objName(obj): if obj.Label == obj.Name: return '"'+obj.Name+'"' return '"{}({})"'.format(obj.Name,obj.Label) def isLine(param): if hasattr(Part,"LineSegment"): return isinstance(param,(Part.Line,Part.LineSegment)) else: return isinstance(param,Part.Line) def deduceSelectedElement(obj,subname): shape = obj.getSubObject(subname) if not shape: return count = len(shape.Faces) if count==1: return 'Face1' elif not count: count = len(shape.Edges) if count==1: return 'Edge1' elif not count: count = len(shape.Vertexes) if count==1: return 'Vertex1' def getElement(obj,tp): if isinstance(obj,tuple): obj = obj[0].getSubObject(obj[1]) if isinstance(obj,tp): return obj def isElement(obj): if isinstance(obj,tuple): obj = obj[0].getSubObject(obj[1]) return isinstance(obj,Part.Vertex) or \ isinstance(obj,Part.Face) or \ isinstance(obj,Part.Edge) def isPlanar(obj): if isCircularEdge(obj): return True shape = getElement(obj,Part.Face) if not shape: return False elif str(shape.Surface) == '': return True elif hasattr(shape.Surface,'Radius'): return False elif str(shape.Surface).startswith('': return False else: _axis,_center,error=fit_rotation_axis_to_surface1(face.Surface) error_normalized = error / face.BoundBox.DiagonalLength return error_normalized < 10**-6 def isAxisOfPlane(obj): face = getElement(obj,Part.Face) if not face: return False if str(face.Surface) == '': return True else: _axis,_center,error=fit_rotation_axis_to_surface1(face.Surface) error_normalized = error / face.BoundBox.DiagonalLength return error_normalized < 10**-6 def isCircularEdge(obj): edge = getElement(obj,Part.Edge) if not edge: return False elif not hasattr(edge, 'Curve'): #issue 39 return False if hasattr( edge.Curve, 'Radius' ): return True elif isLine(edge.Curve): return False else: BSpline = edge.Curve.toBSpline() try: arcs = BSpline.toBiArcs(10**-6) except Exception: #FreeCAD exception thrown () return False if all( hasattr(a,'Center') for a in arcs ): centers = np.array([a.Center for a in arcs]) sigma = np.std( centers, axis=0 ) return max(sigma) < 10**-6 return False def isLinearEdge(obj): edge = getElement(obj,Part.Edge) if not edge: return False elif not hasattr(edge, 'Curve'): #issue 39 return False if isLine(edge.Curve): return True elif hasattr( edge.Curve, 'Radius' ): return False else: BSpline = edge.Curve.toBSpline() try: arcs = BSpline.toBiArcs(10**-6) except Exception: #FreeCAD exception thrown () return False if all(isLine(a) for a in arcs): lines = arcs D = np.array([L.tangent(0)[0] for L in lines]) #D(irections) return np.std( D, axis=0 ).max() < 10**-9 return False def isVertex(obj): return getElement(obj,Part.Vertex) is not None def hasCenter(obj): return isVertex(obj) or isCircularEdge(obj) or \ isAxisOfPlane(obj) or isSphericalSurface(obj) def isSphericalSurface(obj): face = getElement(obj,Part.Face) if not face: return False return str( face.Surface ).startswith('Sphere ') def getElementPos(obj): pos = None vertex = getElement(obj,Part.Vertex) if vertex: return vertex.Point face = getElement(obj,Part.Face) if face: surface = face.Surface if str(surface) == '': pos = face.BoundBox.Center # pos = surface.Position elif all( hasattr(surface,a) for a in ['Axis','Center','Radius'] ): pos = surface.Center elif str(surface).startswith('