def createClippingPlane(clip: ClippingPlane): """ Creates a clipping plane `clip` on the scene graph of FreeCADGui """ global clipPlanes if (clip is None or clip.direction is None or clip.location is None): return False sceneGraph = FreeCADGui.ActiveDocument.ActiveView.getSceneGraph() # create plane that gets added to the scene graph normal = coin.SbVec3f(convertToFreeCADUnits(distance=clip.direction.x), convertToFreeCADUnits(distance=clip.direction.y), convertToFreeCADUnits(distance=clip.direction.z)) ref = coin.SbVec3f(convertToFreeCADUnits(distance=clip.location.x), convertToFreeCADUnits(distance=clip.location.y), convertToFreeCADUnits(distance=clip.location.z)) plane = coin.SbPlane(normal, ref) clipplane = coin.SoClipPlane() clipplane.plane.setValue(plane) # add the clipping plane to the scenegraph sceneGraph.insertChild(clipplane, 0) clipPlanes.append(clipplane) return True
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 _enableClipPlane(self, obj, enable, placement=None, offset=0.0): """Enables or disables clipping for an object. Placement specifies the plane (plane is placement's XY plane), and should be in global CS. Offset shifts the plane; positive offset reveals more material, negative offset hides more material.""" if not hasattr(obj, 'getGlobalPlacement'): print(" {obj} has no attribute 'getGlobalPlacement'".format( obj=obj.Name)) return #can't clip these yet... skip them for now. Example object: Draft Label node = self._getClipplaneNode(obj.ViewObject, make_if_missing=enable) if node is None: if enable: App.Console.PrintError( "TempoVis: failed to set clip plane to {obj}.\n".format( obj=obj.Name)) return if placement is not None: from pivy import coin plm_local = obj.getGlobalPlacement().multiply( obj.Placement.inverse()) # placement of CS the object is in plm_plane = plm_local.inverse().multiply(placement) normal = plm_plane.Rotation.multVec(App.Vector(0, 0, -1)) basepoint = plm_plane.Base + normal * (-offset) normal_coin = coin.SbVec3f(*tuple(normal)) basepoint_coin = coin.SbVec3f(*tuple(basepoint)) node.plane.setValue(coin.SbPlane(normal_coin, basepoint_coin)) node.on.setValue(enable)
def XXupdatencontenth2(viewer,obja,objb): #+# todo: update like quadview v=viewer node= obja.ViewObject.RootNode view=v.getViewer(0) view.setSceneGraph(node) view=v.getViewer(1) marker = coin.SoSeparator() t = coin.SoTransform() t.rotation.setValue(coin.SbVec3f((1,0,0)),-np.pi/2) marker.addChild(t) marker.addChild(node) view.setSceneGraph(marker) node=objb.ViewObject.RootNode view=v.getViewer(2) marker = coin.SoSeparator() t = coin.SoTransform() t.rotation.setValue(coin.SbVec3f((1,0,0)),-np.pi/2) marker.addChild(t) marker.addChild(node) view.setSceneGraph(marker) view=v.getViewer(3) marker = coin.SoSeparator() marker.addChild(node) view.setSceneGraph(marker) v.fitAll() v.viewTop()
def render(outputfile,scene=None,camera=None,zoom=False,width=400,height=300,background=(1.0,1.0,1.0)): """render(outputfile,scene=None,camera=None,zoom=False,width=400,height=300,background=(1.0,1.0,1.0)): Renders a PNG image of given width and height and background color from the given coin scene, using the given coin camera (ortho or perspective). If zoom is True the camera will be resized to fit all objects. The outputfile must be a file path to save a png image.""" # On Linux, the X server must have indirect rendering enabled in order to be able to do offline # PNG rendering. Unfortunately, this is turned off by default on most recent distros. The easiest # way I found is to edit (or create if inexistant) /etc/X11/xorg.conf and add this: # # Section "ServerFlags" # Option "AllowIndirectGLX" "on" # Option "IndirectGLX" "on" # EndSection # # But there are other ways, google of GLX indirect rendering if isinstance(camera,str): camera = getCoinCamera(camera) print("Starting offline renderer") # build an offline scene root separator root = coin.SoSeparator() # add one light (mandatory) light = coin.SoDirectionalLight() root.addChild(light) if not camera: # create a default camera if none was given camera = coin.SoPerspectiveCamera() cameraRotation = coin.SbRotation.identity() cameraRotation *= coin.SbRotation(coin.SbVec3f(1,0,0),-0.4) cameraRotation *= coin.SbRotation(coin.SbVec3f(0,1,0), 0.4) camera.orientation = cameraRotation # make sure all objects get in the view later zoom = True root.addChild(camera) if scene: root.addChild(scene) else: # no scene was given, add a simple cube cube = coin.SoCube() root.addChild(cube) vpRegion = coin.SbViewportRegion(width,height) if zoom: camera.viewAll(root,vpRegion) print("Creating viewport") offscreenRenderer = coin.SoOffscreenRenderer(vpRegion) offscreenRenderer.setBackgroundColor(coin.SbColor(background[0],background[1],background[2])) print("Ready to render") # ref ensures that the node will not be garbage-collected during rendering root.ref() ok = offscreenRenderer.render(root) root.unref() if ok: offscreenRenderer.writeToFile(outputfile,"PNG") print("Rendering",outputfile,"done") else: print("Error rendering image")
def updateGeometryDirection(self, rotation): location = rotation.multVec(FreeCAD.Vector(0, -100000, 0)) # At first we set the location self.updateGeometryLocation(coin.SbVec3f(location.x, location.y, location.z)) axis = rotation.Axis self.transform.rotation.setValue(coin.SbVec3f(axis.x, axis.y, axis.z), rotation.Angle)
def set_arrow_direction(self): pts = np.array(self.points) self.arrow_translate.translation = tuple(pts[-1]) direction = pts[-1] - pts[-2] direction /= np.linalg.norm(direction) _rot = coin.SbRotation() _rot.setValue(coin.SbVec3f(0, 1, 0), coin.SbVec3f(*direction)) self.arrow_rot.rotation.setValue(_rot)
def set_arrow_direction(self): pts = self.points self.arrow_translate.translation = tuple(pts[-1]) direction = pts[-1] - pts[-2] direction.normalize() _rot = coin.SbRotation() _rot.setValue(coin.SbVec3f(0, 1, 0), coin.SbVec3f(*direction)) self.arrow_rot.rotation.setValue(_rot)
def reset_planes(self): '''put the clip planes to an initial position''' ids = self.root.ids ids['cp_green'].plane.setValue( coin.SbPlane(coin.SbVec3f(-1., 0., 0.), -200)) ids['cp_blue_b'].plane.setValue( coin.SbPlane(coin.SbVec3f(-1., 0., 0.), -140)) ids['cp_blue_a'].plane.setValue( coin.SbPlane(coin.SbVec3f(0., 1., 0.), -80))
def draw_glider(self): _rot = coin.SbRotation() _rot.setValue(coin.SbVec3f(0, 1, 0), coin.SbVec3f(1, 0, 0)) rot = coin.SoRotation() rot.rotation.setValue(_rot) self.task_separator += rot draw_glider(self.parametric_glider.get_glider_3d(), self.task_separator, hull=None, ribs=True, fill_ribs=False) draw_lines(self.parametric_glider.get_glider_3d(), vis_lines=self.task_separator, line_num=1)
def get_rotation_angle(from_vector, to_vector): """ Calculate the SbRotation between two vectors, specified as tuples """ _from = coin.SbVec3f(from_vector) _to = coin.SbVec3f(to_vector) _rot = coin.SbRotation(_from, _to) return _rot.getAxisAngle()[1]
def __init__(self,p1=FreeCAD.Vector(0,0,0),p2=FreeCAD.Vector(1,0,0),mode=1): import SketcherGui self.dimnode = coin.SoType.fromName("SoDatumLabel").createInstance() p1node = coin.SbVec3f([p1.x,p1.y,p1.z]) p2node = coin.SbVec3f([p2.x,p2.y,p2.z]) self.dimnode.pnts.setValues([p1node,p2node]) self.dimnode.lineWidth = 1 color = FreeCADGui.draftToolBar.getDefaultColor("snap") self.dimnode.textColor.setValue(coin.SbVec3f(color)) self.setString() self.setMode(mode) Tracker.__init__(self,children=[self.dimnode],name="archDimTracker")
def adjustView(doc): if (FreeCAD.GuiUp): # adjust camara position and orientation g = FreeCADGui.getDocument(doc.Name) v = g.ActiveView c = v.getCameraNode() p = coin.SbVec3f(1, 1, 1) o = coin.SbVec3f(0, 0, 0) u = coin.SbVec3f(0, 1, 0) c.position.setValue(p) c.pointAt( o, u ) FreeCADGui.SendMsgToActiveView("ViewFit")
def draw_label(text=[], prop: propertyValues=None): ''' Draw widgets label relative to the position with alignment''' if text=='' or prop ==None: return # Nothing to do here try: delta=App.Vector(0,0,0) print (prop.vectors) p1=App.Vector(prop.vectors[0]) #You must cast the value or it will fail p2=App.Vector(prop.vectors[1]) delta.x=p1.x+2 delta.y=p1.y+2 delta.z=p1.z (r,thi,phi)=calculateLineSpherical(prop.vectors) #get spherical representation of the point(p2) _transPositionPOS=coin.SoTransform() #_transPositionX = coin.SoTransform() _transPositionY = coin.SoTransform() _transPositionZ = coin.SoTransform() _transPositionPOS.translation.setValue(delta) _transPositionY.translation.setValue(App.Vector(0,0,0)) _transPositionZ.translation.setValue(App.Vector(0,0,0)) print (delta) _transPositionY.rotation.setValue(coin.SbVec3f(1,0, 0),phi) _transPositionZ.rotation.setValue(coin.SbVec3f(0, 0, 1),thi) font = coin.SoFont() font.size = prop.fontsize # Font size font.Name = prop.labelfont # Font used _text3D = coin.SoAsciiText() # Draw text in the 3D world _text3D.string.setValues([l.encode("utf8") for l in text if l]) #_text3D.justification = coin.SoAsciiText.LEFT coinColor = coin.SoMaterial() # Font color coinColor.diffuseColor.set1Value(0, coin.SbColor(*prop.labelcolor)) _textNode = coin.SoSeparator() # A Separator to separate the text from the drawing _textNode.addChild(_transPositionPOS) if phi!=0: _textNode.addChild(_transPositionY) if thi!=0: _textNode.addChild(_transPositionZ) _textNode.addChild(coinColor) _textNode.addChild(font) _textNode.addChild(_text3D) return _textNode # Return the created SoSeparator that contains the text except Exception as err: App.Console.PrintError("'draw_label' Failed. " "{err}\n".format(err=str(err))) exc_type, exc_obj, exc_tb = sys.exc_info() fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] print(exc_type, fname, exc_tb.tb_lineno)
def drag_rotation(self, vector, modify): """ Manage rotation during dragging """ datum = self.datums['rotation'] #center is the first selected node _ctr = datum['center'] #ref_vec is the refernce vector from the previous mouse position #used to calculate the change in rotation _ref_vec = datum['ref_vec'] #angle is the cumulative angle of rotation _angle = datum['angle'] #non-continuous rotation case if not _ctr: _ctr = self.trackers['selected'][0].get() datum['center'] = _ctr _ref_vec = vector.sub(_ctr).normalize() datum['ref_vec'] = _ref_vec self.nodes['transform'].center = coin.SbVec3f(tuple(_ctr)) #scale the rotation by one-tenth if shift is depressed _scale = 1.0 if modify: _scale = 0.1 #calculate the direction of rotation between the current mouse position #vector and the previous. Normalize and reverse sign on direction.z _vec = vector.sub(_ctr).normalize() _dir = _vec.cross(_ref_vec).z if _dir != 0: _dir = -_dir / abs(_dir) #calculate the cumulatibe rotation _rot = _angle + _vec.getAngle(_ref_vec) * _dir * _scale #store the updated values datum['ref_vec'] = _vec datum['angle'] = _rot #return the +z axis rotation for the transformation return coin.SbRotation(coin.SbVec3f(0.0, 0.0, 1.0), _rot)
def cameraUpdate(self): if self.chase_cam: VPos = FreeCAD.ActiveDocument.getObject( 'Pocket001').Shape.Faces[13].CenterOfMass self.cam.position.setValue(VPos + Vec3(0, 0, 50) + tb.dir_x * 100) VLook = VPos + tb.dir_x * -100 self.cam.pointAt(coin.SbVec3f(VLook[0], VLook[1], VLook[2]), coin.SbVec3f(0, 0, 1)) else: VPos = FreeCAD.ActiveDocument.getObject( 'Pocket001').Shape.Faces[13].CenterOfMass self.cam.pointAt(coin.SbVec3f(VPos[0], VPos[1], VPos[2]), coin.SbVec3f(0, 0, 1))
def updateData(self, obj, prop): if prop == "Points": if obj.Points: p = obj.Points[-1] if hasattr(self,"coords"): self.coords.translation.setValue((p.x,p.y,p.z)) if len(obj.Points) >= 2: v1 = obj.Points[-2].sub(obj.Points[-1]) if not DraftVecUtils.isNull(v1): v1.normalize() _rot = coin.SbRotation() _rot.setValue(coin.SbVec3f(1, 0, 0), coin.SbVec3f(v1[0], v1[1], v1[2])) self.coords.rotation.setValue(_rot) return
def getPoint(pX, pY): render_manager = Gui.ActiveDocument.ActiveView.getViewer( ).getSoRenderManager() cam = render_manager.getCamera() ws = render_manager.getWindowSize().getValue() ar = 1.0 * ws[0] / ws[1] vol = cam.getViewVolume() line = coin.SbLine(*vol.projectPointToLine(coin.SbVec2f(pX * ar - 0.5, pY))) normal = coin.SbVec3f(0, 0, 1) center = coin.SbVec3f(0, 0, 0) plane = coin.SbPlane(normal, center) point = plane.intersect(line) return (FreeCAD.Vector(point.getValue()))
def getObjectData(shape): vertices = "" normals = "" items = "" try: fcmesh = shape.tessellate(0.1) fcmeshm = Mesh.Mesh(fcmesh) gen = coin.SoNormalGenerator(True) vertices = [] #non-indexed vertices list normals = [] #non-indexed normals list for f in fcmesh[1]: #indexes rnd = 3 #how many digits v0 = fcmesh[0][f[0]] v1 = fcmesh[0][f[1]] v2 = fcmesh[0][f[2]] #vertices = vertices + [v0.x] + [v0.y] + [v0.z] + [v1.x] + [v1.y] + [v1.z] +[v2.x] + [v2.y] + [v2.z] vertices = vertices + [round(v0.x, rnd)] + [round(v0.y, rnd)] + [ round(v0.z, rnd) ] + [round(v1.x, rnd)] + [round(v1.y, rnd)] + [ round(v1.z, rnd) ] + [round(v2.x, rnd)] + [round(v2.y, rnd)] + [round(v2.z, rnd)] sbv0 = coin.SbVec3f(v0) sbv1 = coin.SbVec3f(v1) sbv2 = coin.SbVec3f(v2) gen.triangle(sbv0, sbv1, sbv2) gen.generate(0.5) #generate normals with crease angle 0.5 rad for i in range(gen.getNumNormals()): #normals = normals + [gen.getNormal(i).getValue()[0]] + [gen.getNormal(i).getValue()[1]] + [gen.getNormal(i).getValue()[2]] normals = normals + [ round(gen.getNormal(i).getValue()[0], rnd) ] + [round(gen.getNormal(i).getValue()[1], rnd)] + [ round(gen.getNormal(i).getValue()[2], rnd) ] #rounded to save space strnormals = str(normals) strvertices = str(vertices) items = str(gen.getNumNormals()) bb = fcmeshm.BoundBox bbmax = max(bb.XLength, bb.YLength, bb.ZLength) bbcenter = bb.Center return strvertices, strnormals, items, bbmax, bbcenter except: print "Something went wrong" return "", "", 0, 0, 0
def setAnnotation(self, recreate=True): if hasattr(self, "Object"): if hasattr(self, "area"): if self.area: self.Object.ViewObject.Annotation.removeChild(self.area) self.area = None self.coords = None self.anno = None if recreate: area = self.getArea(self.Object) if area: from pivy import coin import SketcherGui self.area = coin.SoSeparator() self.coords = coin.SoTransform() if self.Object.Shape: if not self.Object.Shape.isNull(): c = self.Object.Shape.CenterOfMass self.coords.translation.setValue([c.x, c.y, c.z]) self.anno = coin.SoType.fromName( "SoDatumLabel").createInstance() self.anno.string.setValue(area) self.anno.datumtype.setValue(6) color = coin.SbVec3f(self.Object.ViewObject.TextColor[:3]) self.anno.textColor.setValue(color) self.area.addChild(self.coords) self.area.addChild(self.anno) self.Object.ViewObject.Annotation.addChild(self.area)
def set_gui_from_camera(self): """Set GUI camera to this camera.""" assert App.GuiUp, "Cannot set GUI from camera: GUI is down" fpo = self.fpo Gui.ActiveDocument.ActiveView.setCameraType(fpo.Projection) node = Gui.ActiveDocument.ActiveView.getCameraNode() node.position.setValue(fpo.Placement.Base) rot = fpo.Placement.Rotation axis = coin.SbVec3f(rot.Axis.x, rot.Axis.y, rot.Axis.z) node.orientation.setValue(axis, rot.Angle) node.nearDistance.setValue(float(fpo.NearDistance)) node.farDistance.setValue(float(fpo.FarDistance)) node.focalDistance.setValue(float(fpo.FocalDistance)) node.aspectRatio.setValue(float(fpo.AspectRatio)) node.viewportMapping.setValue(getattr(node, fpo.ViewportMapping)) if fpo.Projection == "Orthographic": node.height.setValue(float(fpo.Height)) elif fpo.Projection == "Perspective": node.heightAngle.setValue(radians(float(fpo.HeightAngle)))
def set_rotation_center(self, vector): """ Set the center of rotation for drag operations """ self.datums['rotation']['center'] = vector self.nodes['transform'].center = coin.SbVec3f(tuple(vector))
def _update_placement(self, fpo): """Update camera location.""" location = fpo.Placement.Base[:3] self.coin.transform.translation.setValue(location) angle = float(fpo.Placement.Rotation.Angle) axis = coin.SbVec3f(fpo.Placement.Rotation.Axis) self.coin.transform.rotation.setValue(axis, angle)
def Activated(self): from femtools import femutils overalboundbox = femutils.getBoundBoxOfAllDocumentShapes( FreeCAD.ActiveDocument) # print(overalboundbox) min_bb_length = (min( set([ overalboundbox.XLength, overalboundbox.YLength, overalboundbox.ZLength ]))) dbox = min_bb_length * 0.2 aFace = femutils.getSelectedFace(FreeCADGui.Selection.getSelectionEx()) if aFace: f_CoM = aFace.CenterOfMass f_uvCoM = aFace.Surface.parameter( f_CoM) # u,v at CoM for normalAt calculation f_normal = aFace.normalAt(f_uvCoM[0], f_uvCoM[1]) else: f_CoM = FreeCAD.Vector(0, 0, 0) f_normal = FreeCAD.Vector(0, 0, 1) from pivy import coin coin_normal_vector = coin.SbVec3f(-f_normal.x, -f_normal.y, -f_normal.z) coin_bound_box = coin.SbBox3f(f_CoM.x - dbox, f_CoM.y - dbox, f_CoM.z - dbox * 0.15, f_CoM.x + dbox, f_CoM.y + dbox, f_CoM.z + dbox * 0.15) clip_plane = coin.SoClipPlaneManip() clip_plane.setValue(coin_bound_box, coin_normal_vector, 1) FreeCADGui.ActiveDocument.ActiveView.getSceneGraph().insertChild( clip_plane, 1)
def setup_clipping_plane(self, vobj): """Set-up the clipping plane of the 3dView. This method is called when the property CutView or the object Placement changes. """ sg = Gui.ActiveDocument.ActiveView.getSceneGraph() if self.clip: sg.removeChild(self.clip) self.clip = None '''for o in Draft.getGroupContents(vobj.Object.Objects,walls=True): if hasattr(o.ViewObject,"Lighting"): o.ViewObject.Lighting = "One side"''' # prefer keeping interior lighty self.clip = coin.SoClipPlane() self.clip.on.setValue(True) norm = vobj.Object.Proxy.getNormal(vobj.Object) mp = vobj.Object.Shape.CenterOfMass mp = DraftVecUtils.project(mp, norm) dist = mp.Length #- 0.1 # to not clip exactly on the section object norm = norm.negative() marg = 1 if hasattr(vobj, "CutMargin"): marg = vobj.CutMargin.Value if mp.getAngle(norm) > 1: dist += marg dist = -dist else: dist -= marg plane = coin.SbPlane(coin.SbVec3f(norm.x, norm.y, norm.z), dist) self.clip.plane.setValue(plane) sg.insertChild(self.clip, 0)
def updateTransformNode(self): rotation = math.radians(self.Object.Rotation.Value) translation = coin.SoSFVec3f() translation.setValue(coin.SbVec3f(0, 0, self.Object.ZOffset.Value)) self.transformNode.rotation.setValue(ROTATION_VECTOR, rotation) self.transformNode.translation.setValue(translation)
def updateData(self, feature, prop): r"""If a property of the handled feature has changed, we have the chance to handle this here See Also -------- https://www.freecadweb.org/wiki/Scripted_objects """ debug("ViewProviderAnchor/updateData") p = feature.getPropertyByName("p") u = feature.getPropertyByName("u") v = feature.getPropertyByName("v") self.transform.translation.setValue((p[0], p[1], p[2])) at = anchor_transformation(p0=(0, 0, 0), u0=(0, -1, 0), v0=(0, 0, 1), p1=(p[0], p[1], p[2]), u1=(u[0], u[1], u[2]), v1=(v[0], v[1], v[2])) t = translation_from_matrix(at) self.transform.translation.setValue((t[0], t[1], t[2])) angle, direction, point = rotation_from_matrix(at) # print("angle : %f" % angle) # print("direction : %s" % str(direction)) # print("point : %s" % str(point)) self.transform.rotation.setValue(coin.SbVec3f(direction), angle)
def onChanged(self, vobj, prop): if prop == "SolarDiagramPosition": if hasattr(vobj, "SolarDiagramPosition"): p = vobj.SolarDiagramPosition self.coords.translation.setValue([p.x, p.y, p.z]) if hasattr(vobj.Object, "NorthDeviation"): from pivy import coin self.coords.rotation.setValue( coin.SbVec3f((0, 0, 1)), math.radians(vobj.Object.NorthDeviation.Value)) elif prop == "SolarDiagramColor": if hasattr(vobj, "SolarDiagramColor"): l = vobj.SolarDiagramColor self.color.rgb.setValue([l[0], l[1], l[2]]) elif "SolarDiagram" in prop: if hasattr(self, "diagramnode"): self.diagramsep.removeChild(self.diagramnode) del self.diagramnode if hasattr(vobj, "SolarDiagram") and hasattr( vobj, "SolarDiagramScale"): if vobj.SolarDiagram: self.diagramnode = makeSolarDiagram( vobj.Object.Longitude, vobj.Object.Latitude, vobj.SolarDiagramScale) if self.diagramnode: self.diagramsep.addChild(self.diagramnode) self.diagramswitch.whichChild = 0 else: del self.diagramnode else: self.diagramswitch.whichChild = -1
def setup(self, direction=None, point=None, upvec=None, force=False): """Setup the working plane if it exists but is undefined. If `direction` and `point` are present, it calls `alignToPointAndAxis(point, direction, 0, upvec)`. Otherwise, it gets the camera orientation to define a working plane that is perpendicular to the current view, centered at the origin, and with `v` pointing up on the screen. This method only works when the `weak` attribute is `True`. This method also sets `weak` to `True`. This method only works when `FreeCAD.GuiUp` is `True`, that is, when the graphical interface is loaded. Otherwise it fails silently. Parameters ---------- direction : Base::Vector3, optional It defaults to `None`. It is the new `axis` of the plane. point : Base::Vector3, optional It defaults to `None`. It is the new `position` of the plane. upvec : Base::Vector3, optional It defaults to `None`. It is the new `v` orientation of the plane. force : Bool If True, it sets the plane even if the plane is not in weak mode To do ----- When the interface is not loaded it should fail and print a message, `FreeCAD.Console.PrintError()`. """ if self.weak or force: if direction and point: self.alignToPointAndAxis(point, direction, 0, upvec) else: try: import FreeCADGui from pivy import coin view = FreeCADGui.ActiveDocument.ActiveView camera = view.getCameraNode() rot = camera.getField("orientation").getValue() coin_up = coin.SbVec3f(0, 1, 0) upvec = Vector(rot.multVec(coin_up).getValue()) vdir = view.getViewDirection() # The angle is between 0 and 180 degrees. angle = vdir.getAngle(self.axis) if (angle > 0.001) and (angle < 3.14159): # don't change the plane if it is already # perpendicular to the current view self.alignToPointAndAxis(Vector(0, 0, 0), vdir.negative(), 0, upvec) except: pass if force: self.weak = False else: self.weak = True
def updateTrueNorthRotation(self): if hasattr(self, 'trueNorthRotation') and self.trueNorthRotation is not None: from pivy import coin angle = self.Object.Declination.Value self.trueNorthRotation.rotation.setValue(coin.SbVec3f(0, 0, 1), math.radians(-angle))