''' 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 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 import FreeCAD, FreeCADGui, Part import numpy as np import asm3.FCADLogger logger = asm3.FCADLogger.FCADLogger('assembly3') 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 getElement(obj,tp): if isinstance(obj,tuple): obj = obj[0].getSubObject(obj[1]) if isinstance(obj,tp): return obj 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('