def testRayPick(self): if not FreeCAD.GuiUp: return self.planarMesh.append([-16.097176, -29.891157, 15.987688]) self.planarMesh.append([-16.176304, -29.859991, 15.947966]) self.planarMesh.append([-16.071451, -29.900553, 15.912505]) self.planarMesh.append([-16.092241, -29.893408, 16.020439]) self.planarMesh.append([-16.007210, -29.926180, 15.967641]) self.planarMesh.append([-16.064457, -29.904951, 16.090832]) planarMeshObject = Mesh.Mesh(self.planarMesh) from pivy import coin import FreeCADGui Mesh.show(planarMeshObject) view = FreeCADGui.ActiveDocument.ActiveView.getViewer() rp = coin.SoRayPickAction( view.getSoRenderManager().getViewportRegion()) rp.setRay(coin.SbVec3f(-16.05, 16.0, 16.0), coin.SbVec3f(0, -1, 0)) rp.apply(view.getSoRenderManager().getSceneGraph()) pp = rp.getPickedPoint() self.failUnless(pp != None) det = pp.getDetail() self.failUnless(det.getTypeId() == coin.SoFaceDetail.getClassTypeId()) det = coin.cast(det, str(det.getTypeId().getName())) self.failUnless(det.getFaceIndex() == 1)
def SwapEdge(self, cb): event = cb.getEvent() if event.getButton() == coin.SoMouseButtonEvent.BUTTON2 \ and event.getState() == coin.SoMouseButtonEvent.DOWN: FreeCADGui.ActiveDocument.ActiveView.removeEventCallbackPivy( coin.SoMouseButtonEvent.getClassTypeId(), self.MC) if event.getButton() == coin.SoMouseButtonEvent.BUTTON1 \ and event.getState() == coin.SoMouseButtonEvent.DOWN: pp = cb.getPickedPoint() if pp is not None: detail = pp.getDetail() if detail.isOfType(coin.SoFaceDetail.getClassTypeId()): face_detail = coin.cast(detail, str(detail.getTypeId().getName())) index = face_detail.getFaceIndex() self.FaceIndexes.append(index) if len(self.FaceIndexes) == 2: surface = FreeCADGui.Selection.getSelection()[-1] CopyMesh = surface.Mesh.copy() try: CopyMesh.swapEdge(self.FaceIndexes[0], self.FaceIndexes[1]) except: pass
def getNormal(cb): if cb.getEvent().getState() == coin.SoButtonEvent.UP: pp = cb.getPickedPoint() if pp: vec = pp.getNormal().getValue() index = coin.cast(pp.getDetail(), "SoFaceDetail").getFaceIndex() print("Normal: {}, Face index: {}".format(str(vec), index))
def listen_callback(self): """ listen callback and get index of clicked object element. """ # Get event. event = cb.getEvent() # If mouse right button pressed finish callback. if event.getButton() == coin.SoMouseButtonEvent.BUTTON3 \ and event.getState() == coin.SoMouseButtonEvent.DOWN: self.remove_callback() # If mouse left button pressed get picked point. if event.getButton() == coin.SoMouseButtonEvent.BUTTON1 \ and event.getState() == coin.SoMouseButtonEvent.DOWN: pickedPoint = cb.getPickedPoint() # Get index at picket point if pickedPoint is not None: detail = pickedPoint.getDetail() if detail.isOfType(coin.SoFaceDetail.getClassTypeId()): face_detail = coin.cast( detail, str(detail.getTypeId().getName())) index = face_detail.getFaceIndex() return index
def testRayPick(self): if not FreeCAD.GuiUp: return self.planarMesh.append([-16.097176, -29.891157, 15.987688]) self.planarMesh.append([-16.176304, -29.859991, 15.947966]) self.planarMesh.append([-16.071451, -29.900553, 15.912505]) self.planarMesh.append([-16.092241, -29.893408, 16.020439]) self.planarMesh.append([-16.007210, -29.926180, 15.967641]) self.planarMesh.append([-16.064457, -29.904951, 16.090832]) planarMeshObject = Mesh.Mesh(self.planarMesh) from pivy import coin import FreeCADGui Mesh.show(planarMeshObject) view = FreeCADGui.ActiveDocument.ActiveView.getViewer() rp = coin.SoRayPickAction(view.getSoRenderManager().getViewportRegion()) rp.setRay(coin.SbVec3f(-16.05, 16.0, 16.0), coin.SbVec3f(0, -1, 0)) rp.apply(view.getSoRenderManager().getSceneGraph()) pp = rp.getPickedPoint() self.failUnless(pp != None) det = pp.getDetail() self.failUnless(det.getTypeId() == coin.SoFaceDetail.getClassTypeId()) det = coin.cast(det, str(det.getTypeId().getName())) self.failUnless(det.getFaceIndex() == 1)
def SwapEdge(self, cb): """ Take two triangle by mouse clicks and swap edge between them """ # Get event event = cb.getEvent() # If mouse right button pressed finish swap edge operation if event.getTypeId().isDerivedFrom( coin.SoKeyboardEvent.getClassTypeId()): if event.getKey() == coin.SoKeyboardEvent.ESCAPE \ and event.getState() == coin.SoKeyboardEvent.DOWN: self.view.removeEventCallbackPivy( coin.SoButtonEvent.getClassTypeId(), self.MC) # If mouse left button pressed get picked point elif event.getTypeId().isDerivedFrom( coin.SoMouseButtonEvent.getClassTypeId()): if event.getButton() == coin.SoMouseButtonEvent.BUTTON1 \ and event.getState() == coin.SoMouseButtonEvent.DOWN: picked_point = cb.getPickedPoint() # Get triangle index at picket point if picked_point is not None: detail = picked_point.getDetail() if detail.isOfType(coin.SoFaceDetail.getClassTypeId()): face_detail = coin.cast( detail, str(detail.getTypeId().getName())) index = face_detail.getFaceIndex() self.face_indexes.append(index) # try to swap edge between picked triangle if len(self.face_indexes) == 2: surface = FreeCADGui.Selection.getSelection()[-1] copy_mesh = surface.Mesh.copy() try: copy_mesh.swapEdge(self.face_indexes[0], self.face_indexes[1]) except Exception: print( "The edge between these triangles cannot be swappable" ) surface.Mesh = copy_mesh self.face_indexes.clear()
def add_point(self, cb): """ Take two triangle by mouse clicks and swap edge between them """ # Get event event = cb.getEvent() # If mouse right button pressed finish swap edge operation if event.getTypeId().isDerivedFrom( coin.SoKeyboardEvent.getClassTypeId()): if event.getKey() == coin.SoKeyboardEvent.ESCAPE \ and event.getState() == coin.SoKeyboardEvent.DOWN: self.view.removeEventCallbackPivy( coin.SoButtonEvent.getClassTypeId(), self.event_callback) # If mouse left button pressed get picked point elif event.getTypeId().isDerivedFrom( coin.SoMouseButtonEvent.getClassTypeId()): if event.getButton() == coin.SoMouseButtonEvent.BUTTON1 \ and event.getState() == coin.SoMouseButtonEvent.DOWN: picked_point = cb.getPickedPoint() # Get triangle index at picket point if picked_point: detail = picked_point.getDetail() if detail.isOfType(coin.SoFaceDetail.getClassTypeId()): face_detail = coin.cast( detail, str(detail.getTypeId().getName())) index = face_detail.getFaceIndex() obj = self.view.getObjectInfo(self.view.getCursorPos()) curpos = FreeCAD.Vector(float(obj["x"]), float(obj["y"]), float(obj["z"])) surface = FreeCADGui.Selection.getSelection()[-1] copy_mesh = surface.Mesh.copy() copy_mesh.insertVertex(index, curpos) surface.Mesh = copy_mesh else: pass
def getElement(self, detail): if detail.getTypeId() == coin.SoLineDetail.getClassTypeId(): line_detail = coin.cast(detail, str(detail.getTypeId().getName())) edge = line_detail.getLineIndex() + 1 return "Edge" + str(edge)
def __init__(self, *args, **kwargs): """ Constructs a QuarterWidget. QuarterWidget(QWidget parent = None, QGLWidget sharewidget = None, Qt.WindowFlags f = 0, scxml = "coin:scxml/navigation/examiner.xml") QuarterWidget(QGLContext context, QWidget parent = None, QGLWidget sharewidget = None, Qt.WindowFlags f = 0, scxml = "coin:scxml/navigation/examiner.xml") QuarterWidget(QGLFormat format, QWidget parent = None, QGLWidget sharewidget = None, Qt.WindowFlags f = 0, scxml = "coin:scxml/navigation/examiner.xml") """ params = ["parent", "sharewidget"] values = { "parent": None, "sharewidget": None, "f": 0, "scxml": "coin:scxml/navigation/examiner.xml" } values.update(kwargs) if len(args) > 0 and isinstance( args[0], QtOpenGL.QGLContext) or "context" in kwargs: params.insert(0, "context") elif len(args) > 0 and isinstance( args[0], QtOpenGL.QGLFormat) or "format" in kwargs: params.insert(0, "format") if len(args) > len(params): values["f"] = args[len(params)] if len(args) > len(params) + 1: values["scxml"] = args[len(params) + 1] for i in range(len(args), len(params)): args += (values[params[i]], ) QtOpenGL.QGLWidget.__init__(self, *args[:len(params)]) if values["f"]: self.setWindowFlags(values["f"]) # initialize Sensormanager and ImageReader instances only once if not QuarterWidget._sensormanager: QuarterWidget._sensormanager = SensorManager() if not QuarterWidget._imagereader: QuarterWidget._imagereader = ImageReader() self.cachecontext_list = [] self.cachecontext = self.findCacheContext(self, values["sharewidget"]) self.statecursormap = {} self.scene = None self.contextmenu = None self.contextmenuenabled = True self.sorendermanager = coin.SoRenderManager() self.soeventmanager = coin.SoEventManager() # Mind the order of initialization as the XML state machine uses # callbacks which depends on other state being initialized self.eventmanager = EventManager(self) self.devicemanager = DeviceManager(self) statemachine = coin.ScXML.readFile(values["scxml"]) if statemachine and statemachine.isOfType( coin.SoScXMLStateMachine.getClassTypeId()): sostatemachine = coin.cast(statemachine, "SoScXMLStateMachine") statemachine.addStateChangeCallback(statechangeCB, self) self.soeventmanager.addSoScXMLStateMachine(sostatemachine) sostatemachine.initialize() else: raise "could not initialize statemachine, given file not found?" self.headlight = coin.SoDirectionalLight() self.sorendermanager.setAutoClipping( coin.SoRenderManager.VARIABLE_NEAR_PLANE) self.sorendermanager.setRenderCallback(renderCB, self) self.sorendermanager.setBackgroundColor(coin.SbColor4f(0, 0, 0, 0)) self.sorendermanager.activate() self.sorendermanager.addPreRenderCallback(prerenderCB, self) self.sorendermanager.addPostRenderCallback(postrenderCB, self) self.soeventmanager.setNavigationState( coin.SoEventManager.MIXED_NAVIGATION) self.devicemanager.registerDevice(MouseHandler()) self.devicemanager.registerDevice(KeyboardHandler()) self.eventmanager.registerEventHandler(DragDropHandler()) # set up a cache context for the default SoGLRenderAction self.sorendermanager.getGLRenderAction().setCacheContext( self.getCacheContextId()) self.setStateCursor("interact", QtCore.Qt.ArrowCursor) self.setStateCursor("idle", QtCore.Qt.OpenHandCursor) self.setStateCursor("rotate", QtCore.Qt.ClosedHandCursor) self.setStateCursor("pan", QtCore.Qt.SizeAllCursor) self.setStateCursor("zoom", QtCore.Qt.SizeVerCursor) self.setStateCursor("seek", QtCore.Qt.CrossCursor) self.setStateCursor("spin", QtCore.Qt.OpenHandCursor) self.setMouseTracking(True) self.setFocusPolicy(QtCore.Qt.StrongFocus)
def _castDetail(self, detail): return coin.cast(detail, str(detail.getTypeId().getName()))
def __init__(self, *args, **kwargs): """ Constructs a QuarterWidget. QuarterWidget(QWidget parent = None, QGLWidget sharewidget = None, Qt.WindowFlags f = 0, scxml = "coin:scxml/navigation/examiner.xml") QuarterWidget(QGLContext context, QWidget parent = None, QGLWidget sharewidget = None, Qt.WindowFlags f = 0, scxml = "coin:scxml/navigation/examiner.xml") QuarterWidget(QGLFormat format, QWidget parent = None, QGLWidget sharewidget = None, Qt.WindowFlags f = 0, scxml = "coin:scxml/navigation/examiner.xml") """ params = ["parent", "sharewidget"] values = {"parent": None, "sharewidget": None, "f": 0, "scxml": "coin:scxml/navigation/examiner.xml"} values.update(kwargs) if len(args) > 0 and isinstance(args[0], QtOpenGL.QGLContext) or "context" in kwargs: params.insert(0, "context") elif len(args) > 0 and isinstance(args[0], QtOpenGL.QGLFormat) or "format" in kwargs: params.insert(0, "format") if len(args) > len(params): values["f"] = args[len(params)] if len(args) > len(params) + 1: values["scxml"] = args[len(params) + 1] for i in range(len(args), len(params)): args += (values[params[i]],) QtOpenGL.QGLWidget.__init__(self, *args[:len(params)]) if values["f"]: self.setWindowFlags(values["f"]) # initialize Sensormanager and ImageReader instances only once if not QuarterWidget._sensormanager: QuarterWidget._sensormanager = SensorManager() if not QuarterWidget._imagereader: QuarterWidget._imagereader = ImageReader() self.cachecontext_list = [] self.cachecontext = self.findCacheContext(self, values["sharewidget"]) self.statecursormap = {} self.scene = None self.contextmenu = None self.contextmenuenabled = True self.sorendermanager = coin.SoRenderManager() self.soeventmanager = coin.SoEventManager() # Mind the order of initialization as the XML state machine uses # callbacks which depends on other state being initialized self.eventmanager = EventManager(self) self.devicemanager = DeviceManager(self) statemachine = coin.ScXML.readFile(values["scxml"]) if statemachine and statemachine.isOfType(coin.SoScXMLStateMachine.getClassTypeId()): sostatemachine = coin.cast(statemachine, "SoScXMLStateMachine") statemachine.addStateChangeCallback(statechangeCB, self) self.soeventmanager.addSoScXMLStateMachine(sostatemachine) sostatemachine.initialize() else: raise "could not initialize statemachine, given file not found?" self.headlight = coin.SoDirectionalLight() self.sorendermanager.setAutoClipping(coin.SoRenderManager.VARIABLE_NEAR_PLANE) self.sorendermanager.setRenderCallback(renderCB, self) self.sorendermanager.setBackgroundColor(coin.SbColor4f(0, 0, 0, 0)) self.sorendermanager.activate() self.sorendermanager.addPreRenderCallback(prerenderCB, self) self.sorendermanager.addPostRenderCallback(postrenderCB, self) self.soeventmanager.setNavigationState(coin.SoEventManager.MIXED_NAVIGATION) self.devicemanager.registerDevice(MouseHandler()) self.devicemanager.registerDevice(KeyboardHandler()) self.eventmanager.registerEventHandler(DragDropHandler()) # set up a cache context for the default SoGLRenderAction self.sorendermanager.getGLRenderAction().setCacheContext(self.getCacheContextId()) self.setStateCursor("interact", QtCore.Qt.ArrowCursor) self.setStateCursor("idle", QtCore.Qt.OpenHandCursor) self.setStateCursor("rotate", QtCore.Qt.ClosedHandCursor) self.setStateCursor("pan", QtCore.Qt.SizeAllCursor) self.setStateCursor("zoom", QtCore.Qt.SizeVerCursor) self.setStateCursor("seek", QtCore.Qt.CrossCursor) self.setStateCursor("spin", QtCore.Qt.OpenHandCursor) self.setMouseTracking(True) self.setFocusPolicy(QtCore.Qt.StrongFocus);