def __init__(self,pl=None, sizeFont=30, color=(1.0,0.6,0.0), text='TEXT'): import FreeCAD, FreeCADGui self.node=coin.SoSeparator() self.color=coin.SoBaseColor() self.color.rgb=color self.node.addChild(self.color) self.transform=coin.SoTransform() self.node.addChild(self.transform) self.font=coin.SoFont() self.node.addChild(self.font) self.font.size=sizeFont self.text=coin.SoText2() self.text.string=text self.node.addChild(self.text) self.sg=FreeCADGui.ActiveDocument.ActiveView.getSceneGraph() self.sg.addChild(self.node) if not pl: pl=FreeCAD.Placement() self.moveto(pl)
def __init__(self, dotted=False, scolor=None, swidth=None, start=0, end=math.pi * 2, normal=None): self.circle = None self.startangle = math.degrees(start) self.endangle = math.degrees(end) self.trans = coin.SoTransform() self.trans.translation.setValue([0, 0, 0]) self.sep = coin.SoSeparator() if normal: self.normal = normal else: self.normal = FreeCAD.DraftWorkingPlane.axis self.basevector = self.getDeviation() self.recompute() Tracker.__init__(self, dotted, scolor, swidth, [self.trans, self.sep])
def __init__(self, id, coord): self.node = coin.SoSeparator() self.coordinate = coin.SoCoordinate3() self.transform = coin.SoTransform() self.point = coord _selection_node = \ coin.SoType.fromName("SoFCSelection").createInstance() _selection_node.documentName.setValue('Document') _selection_node.objectName.setValue('Test Tracker') _selection_node.subElementName.setValue(str(id)) self.node.addChild(_selection_node) self.node.addChild(self.transform) self.node.addChild(self.coordinate) self.node.addChild(coin.SoMarkerSet()) self.coordinate.point.setValue(tuple(coord))
def attach(self, vobj): ArchFloor._ViewProviderFloor.attach(self, vobj) from pivy import coin self.diagramsep = coin.SoSeparator() self.color = coin.SoBaseColor() self.coords = coin.SoTransform() self.diagramswitch = coin.SoSwitch() self.diagramswitch.whichChild = -1 self.diagramswitch.addChild(self.diagramsep) self.diagramsep.addChild(self.coords) self.diagramsep.addChild(self.color) vobj.Annotation.addChild(self.diagramswitch) self.compass = Compass() self.updateCompassVisibility(self.Object) self.updateCompassScale(self.Object) self.rotateCompass(self.Object) vobj.Annotation.addChild(self.compass.rootNode)
def __init__(self, line=None, width=0.1, height=1, shaded=False): self.trans = coin.SoTransform() m = coin.SoMaterial() m.transparency.setValue(0.8) m.diffuseColor.setValue([0.4, 0.4, 0.6]) w = coin.SoDrawStyle() w.style = coin.SoDrawStyle.LINES self.cube = coin.SoCube() self.cube.height.setValue(width) self.cube.depth.setValue(height) self.baseline = None if line: self.baseline = line self.update() if shaded: Tracker.__init__(self, children=[self.trans, m, self.cube], name="boxTracker") else: Tracker.__init__(self, children=[self.trans, w, self.cube], name="boxTracker")
def __init__(self, sel): self.trans = coin.SoTransform() self.trans.translation.setValue([0, 0, 0]) self.children = [self.trans] self.ivsep = coin.SoSeparator() try: if isinstance(sel, Part.Shape): ivin = coin.SoInput() ivin.setBuffer(sel.writeInventor()) ivob = coin.SoDB.readAll(ivin) self.ivsep.addChild(ivob.getChildren()[1]) else: if not isinstance(sel, list): sel = [sel] for obj in sel: self.ivsep.addChild(obj.ViewObject.RootNode.copy()) except: print "draft: Couldn't create ghost" self.children.append(self.ivsep) Tracker.__init__(self, children=self.children)
def attach(self, vobj): """Set up the scene sub-graph of the view provider.""" # Main attributes of the Coin scenegraph self.mattext = coin.SoMaterial() self.trans = coin.SoTransform() self.font = coin.SoFont() self.text2d = coin.SoText2() # Faces the camera always self.text3d = coin.SoAsciiText() # Can be oriented in 3D space textdrawstyle = coin.SoDrawStyle() textdrawstyle.style = coin.SoDrawStyle.FILLED # The text string needs to be initialized to something, # otherwise it may crash self.text2d.string = self.text3d.string = "Label" self.text2d.justification = coin.SoText2.LEFT self.text3d.justification = coin.SoAsciiText.LEFT self.node2d = coin.SoGroup() self.node2d.addChild(self.trans) self.node2d.addChild(self.mattext) self.node2d.addChild(textdrawstyle) self.node2d.addChild(self.font) self.node2d.addChild(self.text2d) self.node3d = coin.SoGroup() self.node3d.addChild(self.trans) self.node3d.addChild(self.mattext) self.node3d.addChild(textdrawstyle) self.node3d.addChild(self.font) self.node3d.addChild(self.text3d) vobj.addDisplayMode(self.node2d, "2D text") vobj.addDisplayMode(self.node3d, "3D text") self.onChanged(vobj, "TextColor") self.onChanged(vobj, "FontSize") self.onChanged(vobj, "FontName") self.onChanged(vobj, "Justification") self.onChanged(vobj, "LineSpacing") self.onChanged(vobj, "ScaleMultiplier") self.Object = vobj.Object
def create_crosshair(self): _switch = coin.SoSwitch() _node = coin.SoSeparator() _coord = coin.SoCoordinate3() _transform = coin.SoTransform() self.crosshair_coord.point.setValues(0, 5, [(1.0, 0.0, 0.0), (0.0, 1.0, 0.0), (-1.0, 0.0, 0.0), (0.0, -1.0, 0.0), (1.0, 0.0, 0.0)]) _nodes = [_transform, self.crosshair_coord, coin.SoLineSet()] for _v in _nodes: _node.addChild(_v) _switch.addChild(_node) _switch.whichChild = -1 return _switch
def attach(self, vp): # prepare transformation to keep pose corresponding to placement self.tf_object2world = coin.SoTransform() labels = self.makeLabels() self.font = coin.SoFontStyle() frame = self.makeFrame(labels[:3]) frame.insertChild(self.tf_object2world, 0) frame.insertChild(self.font, 1) self.frame = coin.SoSwitch() self.frame.addChild(frame) self.visualisations = coin.SoSwitch() self.visualisations.addChild(self.frame) self.visualisations.whichChild.setValue(coin.SO_SWITCH_ALL) vp.RootNode.addChild(self.visualisations) vp.Object.Proxy.setProperties(vp.Object) self.setProperties(vp) self.fp = vp.Object
def __init__(self): # getting screen distance p1 = Draft.get3DView().getPoint((100, 100)) p2 = Draft.get3DView().getPoint((110, 100)) bl = (p2.sub(p1)).Length * (Draft.getParam("snapRange", 8)/2.0) pick = coin.SoPickStyle() pick.style.setValue(coin.SoPickStyle.UNPICKABLE) self.trans = coin.SoTransform() self.trans.translation.setValue([0, 0, 0]) m1 = coin.SoMaterial() m1.transparency.setValue(0.8) m1.diffuseColor.setValue([0.4, 0.4, 0.6]) c1 = coin.SoCoordinate3() c1.point.setValues([[-bl, -bl, 0], [bl, -bl, 0], [bl, bl, 0], [-bl, bl, 0]]) f = coin.SoIndexedFaceSet() f.coordIndex.setValues([0, 1, 2, 3]) m2 = coin.SoMaterial() m2.transparency.setValue(0.7) m2.diffuseColor.setValue([0.2, 0.2, 0.3]) c2 = coin.SoCoordinate3() c2.point.setValues([[0, bl, 0], [0, 0, 0], [bl, 0, 0], [-0.05*bl, 0.95*bl, 0], [0, bl, 0], [0.05*bl, 0.95*bl, 0], [0.95*bl, 0.05*bl, 0], [bl, 0, 0], [0.95*bl, -0.05*bl, 0]]) l = coin.SoLineSet() l.numVertices.setValues([3, 3, 3]) s = coin.SoSeparator() s.addChild(pick) s.addChild(self.trans) s.addChild(m1) s.addChild(c1) s.addChild(f) s.addChild(m2) s.addChild(c2) s.addChild(l) Tracker.__init__(self, children=[s], name="planeTracker")
def __init__(self,pl=None, scale=[100,100,20],offset=100,name='ARROW'): # define main properties self.view=FreeCADGui.ActiveDocument.ActiveView self.sg=self.view.getSceneGraph() self.cb=self.view.addEventCallbackPivy(coin.SoMouseButtonEvent.getClassTypeId(), self.pickCB) # define OpenInventor properties self.node=coin.SoSeparator() #self.node=coin.SoSelection() self.name=name self.node.setName(self.name) self.color=coin.SoBaseColor(); self.color.rgb=0,0.8,0 self.transform=coin.SoTransform(); self.transform.scaleFactor.setValue(scale) self.cone=coin.SoCone() # create children of node self.node.addChild(self.color) self.node.addChild(self.transform) self.node.addChild(self.cone) # draw the arrow and move it to its Placement with the specified offset self.sg.addChild(self.node) self.offset=offset if not pl: pl=FreeCAD.Placement() self.moveto(pl)
def attach(self, vobj): # We only have a shaded visual group self.shaded = coin.SoGroup() # Takes heavily from SoAxisCrosskit.h, # and Toggle_DH_Frames by galou_breizh on the forums self.vframe = coin.SoType.fromName("SoShapeScale").createInstance() self.vframe.setPart( "shape", coin.SoType.fromName("SoAxisCrossKit").createInstance()) self.vframe.scaleFactor.setValue(0.1) ax = self.vframe.getPart("shape", 0) cone = ax.getPart("xHead.shape", 0) cone.bottomRadius.setValue(vobj.HeadSize) cone = ax.getPart("yHead.shape", 0) cone.bottomRadius.setValue(vobj.HeadSize) cone = ax.getPart("zHead.shape", 0) cone.bottomRadius.setValue(vobj.HeadSize) lwstring = "lineWidth {0}".format(vobj.LineWidth) ax.set("xAxis.appearance.drawStyle", lwstring) ax.set("yAxis.appearance.drawStyle", lwstring) ax.set("zAxis.appearance.drawStyle", lwstring) ax.set("xAxis.pickStyle", "style SHAPE") ax.set("yAxis.pickStyle", "style SHAPE") ax.set("zAxis.pickStyle", "style SHAPE") # Then remember to make it selectable in the viewer selectionNode = coin.SoType.fromName("SoFCSelection").createInstance() selectionNode.documentName.setValue(FreeCAD.ActiveDocument.Name) selectionNode.objectName.setValue(vobj.Object.Name) selectionNode.subElementName.setValue("Frame") selectionNode.addChild(self.vframe) # We would like to place it where we want self.transform = coin.SoTransform() self.shaded.addChild(self.transform) self.shaded.addChild(self.vframe) self.shaded.addChild(selectionNode) vobj.addDisplayMode(self.shaded, "Shaded")
def attach(self, vobj): self.ViewObject = vobj self.Object = vobj.Object self.transformNode = coin.SoTransform() self.coinNode = coin.SoSeparator() self.coinNode.addChild(self.transformNode) self.panoramaNode = self.setupPanoramaNode() self.skyNode = self.setupSkyNode() self.groundNode = self.setupGroundNode() self.updatePanoramaCoordinates() self.updatePanoramaTextureCoordinates() self.updateSkyCoordinates() self.updateGroundCoordinates() self.updateTransformNode() self.updateNodeVisibility() vobj.addDisplayMode(self.coinNode, "Standard")
def attach(self, vobj): """Add display modes' data to the coin scenegraph. Add each display mode as a coin node, whose parent is this view provider. Each display mode's node includes the data needed to display the object in that mode. This might include colors of faces, or the draw style of lines. This data is stored as additional coin nodes which are children of the display mode node. Doe not add display modes, but do add the solar diagram and compass to the scenegraph. """ self.Object = vobj.Object from pivy import coin basesep = coin.SoSeparator() vobj.Annotation.addChild(basesep) self.color = coin.SoBaseColor() self.coords = coin.SoTransform() basesep.addChild(self.coords) basesep.addChild(self.color) self.diagramsep = coin.SoSeparator() self.diagramswitch = coin.SoSwitch() self.diagramswitch.whichChild = -1 self.diagramswitch.addChild(self.diagramsep) basesep.addChild(self.diagramswitch) self.windrosesep = coin.SoSeparator() self.windroseswitch = coin.SoSwitch() self.windroseswitch.whichChild = -1 self.windroseswitch.addChild(self.windrosesep) basesep.addChild(self.windroseswitch) self.compass = Compass() self.updateCompassVisibility(vobj) self.updateCompassScale(vobj) self.rotateCompass(vobj) vobj.Annotation.addChild(self.compass.rootNode)
def draw_box(vertices=[], color=(0.0, 0.0, 0.0), LineWidth=1): """ Draw any box. This will be the base of all multi-point drawing. Curves, and arc is not here. """ if len(vertices) < 4: raise ValueError('Vertices must be 4') dash = coin.SoSeparator() v = coin.SoVertexProperty() coords = coin.SoTransform() p1 = vertices[0] p2 = vertices[1] p3 = vertices[2] p4 = vertices[3] square = coin.SbBox3f(p1, p2, p3, p4) square.vertexProperty = v style = coin.SoDrawStyle() style.lineWidth = LineWidth dash.addChild(style) dash.addChild(color) dash.addChild(square) dash.addChild(coords) return draw_square
def __init__(self, view, names): """ Constructor """ self.viewport = \ view.getViewer().getSoRenderManager().getViewportRegion() self.nodes = { 'connector': coin.SoGroup(), 'selected': coin.SoGroup(), 'switch': coin.SoSwitch(), 'transform': coin.SoTransform(), } self.start_path = None self.trackers = None self.datums = { _k: None for _k in ['origin', 'picked', 'start', 'trans_start'] } self.datums['rotation'] = { 'center': None, 'ref_vec': None, 'angle': 0.0 } names.append('DRAG TRACKER') super().__init__(names, [self.nodes['connector'], self.nodes['selected']], False) self.nodes['switch'].addChild(self.node) self.on(self.nodes['switch'])
def draw_Point(p1, color): try: dash = coin.SoSeparator() v = coin.SoVertexProperty() v.vertex.set1Value(0, p1) coords = coin.SoTransform() line = coin.SoLineSet() line.vertexProperty = v style = coin.SoDrawStyle() dash.addChild(style) col1 = coin.SoBaseColor() # must be converted to SoBaseColor col1.rgb = color dash.addChild(col1) dash.addChild(line) dash.addChild(coords) return dash except Exception as err: App.Console.PrintError("'makeIt' 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 __init__(self): col = self.getGridColor() pick = coin.SoPickStyle() pick.style.setValue(coin.SoPickStyle.UNPICKABLE) self.trans = coin.SoTransform() self.trans.translation.setValue([0,0,0]) mat1 = coin.SoMaterial() mat1.transparency.setValue(0.7) mat1.diffuseColor.setValue(col) self.coords1 = coin.SoCoordinate3() self.lines1 = coin.SoLineSet() mat2 = coin.SoMaterial() mat2.transparency.setValue(0.3) mat2.diffuseColor.setValue(col) self.coords2 = coin.SoCoordinate3() self.lines2 = coin.SoLineSet() mat3 = coin.SoMaterial() mat3.transparency.setValue(0) mat3.diffuseColor.setValue(col) self.coords3 = coin.SoCoordinate3() self.lines3 = coin.SoLineSet() self.pts = [] s = coin.SoSeparator() s.addChild(pick) s.addChild(self.trans) s.addChild(mat1) s.addChild(self.coords1) s.addChild(self.lines1) s.addChild(mat2) s.addChild(self.coords2) s.addChild(self.lines2) s.addChild(mat3) s.addChild(self.coords3) s.addChild(self.lines3) Tracker.__init__(self,children=[s],name="gridTracker") self.reset()
def onChanged(self, vobj, prop): if prop == "LineColor": l = vobj.LineColor self.mat.diffuseColor.setValue([l[0], l[1], l[2]]) elif prop == "DrawStyle": if vobj.DrawStyle == "Solid": self.linestyle.linePattern = 0xffff elif vobj.DrawStyle == "Dashed": self.linestyle.linePattern = 0xf00f elif vobj.DrawStyle == "Dotted": self.linestyle.linePattern = 0x0f0f else: self.linestyle.linePattern = 0xff88 elif prop == "LineWidth": self.linestyle.lineWidth = vobj.LineWidth elif prop in ["BubbleSize", "BubblePosition", "FontName", "FontSize"]: if hasattr(self, "bubbleset"): if self.bubbles: self.bubbleset.removeChild(self.bubbles) self.bubbles = None if vobj.Object.Shape: if vobj.Object.Shape.Edges: self.bubbles = coin.SoSeparator() self.bubblestyle = coin.SoDrawStyle() self.bubblestyle.linePattern = 0xffff self.bubbles.addChild(self.bubblestyle) import Part, Draft self.bubbletexts = [] pos = ["Start"] if hasattr(vobj, "BubblePosition"): if vobj.BubblePosition == "Both": pos = ["Start", "End"] elif vobj.BubblePosition == "None": pos = [] else: pos = [vobj.BubblePosition] for i in range(len(vobj.Object.Shape.Edges)): for p in pos: verts = vobj.Object.Shape.Edges[i].Vertexes if p == "Start": p1 = verts[0].Point p2 = verts[1].Point else: p1 = verts[1].Point p2 = verts[0].Point dv = p2.sub(p1) dv.normalize() if hasattr(vobj.BubbleSize, "Value"): rad = vobj.BubbleSize.Value / 2 else: rad = vobj.BubbleSize / 2 center = p2.add(dv.scale(rad, rad, rad)) buf = Part.makeCircle(rad, center).writeInventor() try: cin = coin.SoInput() cin.setBuffer(buf) cob = coin.SoDB.readAll(cin) except: import re # workaround for pivy SoInput.setBuffer() bug buf = buf.replace("\n", "") pts = re.findall("point \[(.*?)\]", buf)[0] pts = pts.split(",") pc = [] for p in pts: v = p.strip().split() pc.append([ float(v[0]), float(v[1]), float(v[2]) ]) coords = coin.SoCoordinate3() coords.point.setValues(0, len(pc), pc) line = coin.SoLineSet() line.numVertices.setValue(-1) else: coords = cob.getChild(1).getChild( 0).getChild(2) line = cob.getChild(1).getChild( 0).getChild(3) self.bubbles.addChild(coords) self.bubbles.addChild(line) st = coin.SoSeparator() tr = coin.SoTransform() fs = rad * 1.5 if hasattr(vobj, "FontSize"): fs = vobj.FontSize.Value tr.translation.setValue( (center.x, center.y - fs / 2.5, center.z)) fo = coin.SoFont() fn = Draft.getParam("textfont", "Arial,Sans") if hasattr(vobj, "FontName"): if vobj.FontName: try: fn = str(vobj.FontName) except: pass fo.name = fn fo.size = fs tx = coin.SoAsciiText() tx.justification = coin.SoText2.CENTER self.bubbletexts.append(tx) st.addChild(tr) st.addChild(fo) st.addChild(tx) self.bubbles.addChild(st) self.bubbleset.addChild(self.bubbles) self.onChanged(vobj, "NumberingStyle") if prop in ["FontName", "FontSize"]: self.onChanged(vobj, "ShowLabel") elif prop in ["NumberingStyle", "StartNumber"]: if hasattr(self, "bubbletexts"): chars = "abcdefghijklmnopqrstuvwxyz" roman = (('M', 1000), ('CM', 900), ('D', 500), ('CD', 400), ('C', 100), ('XC', 90), ('L', 50), ('XL', 40), ('X', 10), ('IX', 9), ('V', 5), ('IV', 4), ('I', 1)) num = 0 if hasattr(vobj, "StartNumber"): if vobj.StartNumber > 1: num = vobj.StartNumber - 1 alt = False for t in self.bubbletexts: if hasattr(vobj, "NumberingStyle"): if vobj.NumberingStyle == "1,2,3": t.string = str(num + 1) elif vobj.NumberingStyle == "01,02,03": t.string = str(num + 1).zfill(2) elif vobj.NumberingStyle == "001,002,003": t.string = str(num + 1).zfill(3) elif vobj.NumberingStyle == "A,B,C": result = "" base = num / 26 if base: result += chars[base].upper() remainder = num % 26 result += chars[remainder].upper() t.string = result elif vobj.NumberingStyle == "a,b,c": result = "" base = num / 26 if base: result += chars[base] remainder = num % 26 result += chars[remainder] t.string = result elif vobj.NumberingStyle == "I,II,III": result = "" n = num n += 1 for numeral, integer in roman: while n >= integer: result += numeral n -= integer t.string = result elif vobj.NumberingStyle == "L0,L1,L2": t.string = "L" + str(num) else: t.string = str(num + 1) num += 1 if hasattr(vobj, "BubblePosition"): if vobj.BubblePosition == "Both": if not alt: num -= 1 alt = not alt elif prop in ["ShowLabel", "LabelOffset"]: if hasattr(self, "labels"): if self.labels: self.labelset.removeChild(self.labels) self.labels = None if hasattr(vobj, "ShowLabel") and hasattr(vobj.Object, "Labels"): if vobj.ShowLabel: self.labels = coin.SoSeparator() for i in range(len(vobj.Object.Shape.Edges)): if len(vobj.Object.Labels) > i: if vobj.Object.Labels[i]: import Draft vert = vobj.Object.Shape.Edges[i].Vertexes[ 0].Point if hasattr(vobj, "LabelOffset"): pl = FreeCAD.Placement(vobj.LabelOffset) pl.Base = vert.add(pl.Base) st = coin.SoSeparator() tr = coin.SoTransform() fo = coin.SoFont() tx = coin.SoAsciiText() tx.justification = coin.SoText2.LEFT t = vobj.Object.Labels[i] if isinstance(t, unicode): t = t.encode("utf8") tx.string.setValue(t) if hasattr(vobj, "FontSize"): fs = vobj.FontSize.Value elif hasattr(vobj.BubbleSize, "Value"): fs = vobj.BubbleSize.Value * 0.75 else: fs = vobj.BubbleSize * 0.75 tr.translation.setValue(tuple(pl.Base)) tr.rotation.setValue(pl.Rotation.Q) fn = Draft.getParam("textfont", "Arial,Sans") if hasattr(vobj, "FontName"): if vobj.FontName: try: fn = str(vobj.FontName) except: pass fo.name = fn fo.size = fs st.addChild(tr) st.addChild(fo) st.addChild(tx) self.labels.addChild(st) self.labelset.addChild(self.labels)
def dim_symbol(symbol=None, invert=False): """Return the specified dimension symbol. Parameters ---------- symbol: int, optional It defaults to `None`, in which it gets the value from the parameter database, `get_param("dimsymbol", 0)`. A numerical value defines different markers * 0, `SoSphere` * 1, `SoMarkerSet` with a circle * 2, `SoSeparator` with a `soCone` * 3, `SoSeparator` with a `SoFaceSet` * 4, `SoSeparator` with a `SoLineSet`, calling `dim_dash` * Otherwise, `SoSphere` invert: bool, optional It defaults to `False`. If it is `True` and `symbol=2`, the cone will be rotated -90 degrees around the Z axis, otherwise the rotation is positive, +90 degrees. Returns ------- Coin.SoNode A `Coin.SoSphere`, or `Coin.SoMarkerSet` (circle), or `Coin.SoSeparator` (cone, face, line) that will be used as a dimension symbol. """ if symbol is None: symbol = utils.get_param("dimsymbol", 0) if symbol == 0: # marker = coin.SoMarkerSet() # marker.markerIndex = 80 # Returning a sphere means that the bounding box will # be 3-dimensional; a marker will always be planar seen from any # orientation but it currently doesn't work correctly marker = coin.SoSphere() return marker elif symbol == 1: marker = coin.SoMarkerSet() # Should be the same as # marker.markerIndex = 10 marker.markerIndex = Gui.getMarkerIndex("circle", 9) return marker elif symbol == 2: marker = coin.SoSeparator() t = coin.SoTransform() t.translation.setValue((0, -2, 0)) t.center.setValue((0, 2, 0)) if invert: t.rotation.setValue(coin.SbVec3f((0, 0, 1)), -math.pi/2) else: t.rotation.setValue(coin.SbVec3f((0, 0, 1)), math.pi/2) c = coin.SoCone() c.height.setValue(4) marker.addChild(t) marker.addChild(c) return marker elif symbol == 3: marker = coin.SoSeparator() c = coin.SoCoordinate3() c.point.setValues([(-1, -2, 0), (0, 2, 0), (1, 2, 0), (0, -2, 0)]) f = coin.SoFaceSet() marker.addChild(c) marker.addChild(f) return marker elif symbol == 4: return dimDash((-1.5, -1.5, 0), (1.5, 1.5, 0)) else: _wrn(_tr("Symbol not implemented. Use a default symbol.")) return coin.SoSphere()
def attach(self, vobj): '''Setup the scene sub-graph of the view provider''' self.Object = vobj.Object self.color = coin.SoBaseColor() self.font = coin.SoFont() self.font3d = coin.SoFont() self.text = coin.SoAsciiText() self.text3d = coin.SoText2() self.text.string = "d" # some versions of coin crash if string is not set self.text3d.string = "d" self.textpos = coin.SoTransform() self.text.justification = self.text3d.justification = coin.SoAsciiText.CENTER label = coin.SoSeparator() label.addChild(self.textpos) label.addChild(self.color) label.addChild(self.font) label.addChild(self.text) label3d = coin.SoSeparator() label3d.addChild(self.textpos) label3d.addChild(self.color) label3d.addChild(self.font3d) label3d.addChild(self.text3d) self.coord1 = coin.SoCoordinate3() self.trans1 = coin.SoTransform() self.coord2 = coin.SoCoordinate3() self.trans2 = coin.SoTransform() self.transDimOvershoot1 = coin.SoTransform() self.transDimOvershoot2 = coin.SoTransform() self.transExtOvershoot1 = coin.SoTransform() self.transExtOvershoot2 = coin.SoTransform() self.marks = coin.SoSeparator() self.marksDimOvershoot = coin.SoSeparator() self.marksExtOvershoot = coin.SoSeparator() self.drawstyle = coin.SoDrawStyle() self.line = coin.SoType.fromName("SoBrepEdgeSet").createInstance() self.coords = coin.SoCoordinate3() self.node = coin.SoGroup() self.node.addChild(self.color) self.node.addChild(self.drawstyle) self.lineswitch2 = coin.SoSwitch() self.lineswitch2.whichChild = -3 self.node.addChild(self.lineswitch2) self.lineswitch2.addChild(self.coords) self.lineswitch2.addChild(self.line) self.lineswitch2.addChild(self.marks) self.lineswitch2.addChild(self.marksDimOvershoot) self.lineswitch2.addChild(self.marksExtOvershoot) self.node.addChild(label) self.node3d = coin.SoGroup() self.node3d.addChild(self.color) self.node3d.addChild(self.drawstyle) self.lineswitch3 = coin.SoSwitch() self.lineswitch3.whichChild = -3 self.node3d.addChild(self.lineswitch3) self.lineswitch3.addChild(self.coords) self.lineswitch3.addChild(self.line) self.lineswitch3.addChild(self.marks) self.lineswitch3.addChild(self.marksDimOvershoot) self.lineswitch3.addChild(self.marksExtOvershoot) self.node3d.addChild(label3d) vobj.addDisplayMode(self.node, "2D") vobj.addDisplayMode(self.node3d, "3D") self.updateData(vobj.Object, "Start") self.onChanged(vobj, "FontSize") self.onChanged(vobj, "FontName") self.onChanged(vobj, "ArrowType") self.onChanged(vobj, "LineColor") self.onChanged(vobj, "DimOvershoot") self.onChanged(vobj, "ExtOvershoot")
def makeSolarDiagram(longitude, latitude, scale=1, complete=False): """makeSolarDiagram(longitude,latitude,[scale,complete]): returns a solar diagram as a pivy node. If complete is True, the 12 months are drawn""" from subprocess import call py3_failed = call(["python3", "-c", "import Pysolar"]) if py3_failed: try: import Pysolar except: print( "Pysolar is not installed. Unable to generate solar diagrams") return None else: from subprocess import check_output from pivy import coin if not scale: return None def toNode(shape): "builds a pivy node from a simple linear shape" from pivy import coin buf = shape.writeInventor(2, 0.01) buf = buf.replace("\n", "") pts = re.findall("point \[(.*?)\]", buf)[0] pts = pts.split(",") pc = [] for p in pts: v = p.strip().split() pc.append([float(v[0]), float(v[1]), float(v[2])]) coords = coin.SoCoordinate3() coords.point.setValues(0, len(pc), pc) line = coin.SoLineSet() line.numVertices.setValue(-1) item = coin.SoSeparator() item.addChild(coords) item.addChild(line) return item circles = [] sunpaths = [] hourpaths = [] circlepos = [] hourpos = [] # build the base circle + number positions import Part for i in range(1, 9): circles.append(Part.makeCircle(scale * (i / 8.0))) for ad in range(0, 360, 15): a = math.radians(ad) p1 = FreeCAD.Vector(math.cos(a) * scale, math.sin(a) * scale, 0) p2 = FreeCAD.Vector( math.cos(a) * scale * 0.125, math.sin(a) * scale * 0.125, 0) p3 = FreeCAD.Vector( math.cos(a) * scale * 1.08, math.sin(a) * scale * 1.08, 0) circles.append(Part.LineSegment(p1, p2).toShape()) circlepos.append((ad, p3)) # build the sun curves at solstices and equinoxe year = datetime.datetime.now().year hpts = [[] for i in range(24)] m = [(6, 21), (7, 21), (8, 21), (9, 21), (10, 21), (11, 21), (12, 21)] if complete: m.extend([(1, 21), (2, 21), (3, 21), (4, 21), (5, 21)]) for i, d in enumerate(m): pts = [] for h in range(24): if not py3_failed: dt = "datetime.datetime(%s, %s, %s, %s)" % (year, d[0], d[1], h) alt_call = "python3 -c 'import datetime,Pysolar; print (Pysolar.solar.get_altitude_fast(%s, %s, %s))'" % ( latitude, longitude, dt) alt = math.radians( float(check_output(alt_call, shell=True).strip())) az_call = "python3 -c 'import datetime,Pysolar; print (Pysolar.solar.get_azimuth(%s, %s, %s))'" % ( latitude, longitude, dt) az = float( re.search('.+$', check_output(az_call, shell=True)).group(0)) else: dt = datetime.datetime(year, d[0], d[1], h) alt = math.radians( Pysolar.solar.GetAltitudeFast(latitude, longitude, dt)) az = Pysolar.solar.GetAzimuth(latitude, longitude, dt) az = -90 + az # pysolar's zero is south if az < 0: az = 360 + az az = math.radians(az) zc = math.sin(alt) * scale ic = math.cos(alt) * scale xc = math.cos(az) * ic yc = math.sin(az) * ic p = FreeCAD.Vector(xc, yc, zc) pts.append(p) hpts[h].append(p) if i in [0, 6]: ep = FreeCAD.Vector(p) ep.multiply(1.08) if ep.z >= 0: if h == 12: if i == 0: h = "SUMMER" else: h = "WINTER" if latitude < 0: if h == "SUMMER": h = "WINTER" else: h = "SUMMER" hourpos.append((h, ep)) if i < 7: sunpaths.append(Part.makePolygon(pts)) for h in hpts: if complete: h.append(h[0]) hourpaths.append(Part.makePolygon(h)) # cut underground lines sz = 2.1 * scale cube = Part.makeBox(sz, sz, sz) cube.translate(FreeCAD.Vector(-sz / 2, -sz / 2, -sz)) sunpaths = [sp.cut(cube) for sp in sunpaths] hourpaths = [hp.cut(cube) for hp in hourpaths] # build nodes ts = 0.005 * scale # text scale mastersep = coin.SoSeparator() circlesep = coin.SoSeparator() numsep = coin.SoSeparator() pathsep = coin.SoSeparator() hoursep = coin.SoSeparator() hournumsep = coin.SoSeparator() mastersep.addChild(circlesep) mastersep.addChild(numsep) mastersep.addChild(pathsep) mastersep.addChild(hoursep) for item in circles: circlesep.addChild(toNode(item)) for item in sunpaths: for w in item.Edges: pathsep.addChild(toNode(w)) for item in hourpaths: for w in item.Edges: hoursep.addChild(toNode(w)) for p in circlepos: text = coin.SoText2() s = p[0] - 90 s = -s if s > 360: s = s - 360 if s < 0: s = 360 + s if s == 0: s = "N" elif s == 90: s = "E" elif s == 180: s = "S" elif s == 270: s = "W" else: s = str(s) text.string = s text.justification = coin.SoText2.CENTER coords = coin.SoTransform() coords.translation.setValue([p[1].x, p[1].y, p[1].z]) coords.scaleFactor.setValue([ts, ts, ts]) item = coin.SoSeparator() item.addChild(coords) item.addChild(text) numsep.addChild(item) for p in hourpos: text = coin.SoText2() s = str(p[0]) text.string = s text.justification = coin.SoText2.CENTER coords = coin.SoTransform() coords.translation.setValue([p[1].x, p[1].y, p[1].z]) coords.scaleFactor.setValue([ts, ts, ts]) item = coin.SoSeparator() item.addChild(coords) item.addChild(text) numsep.addChild(item) return mastersep
def draw_Text_Wheel(vec=App.Vector(0.0, 0.0, 0.0), _color=FR_COLOR.FR_WHITE, setupRotation=[0, 0, 0], _rotation=[0.0, 0.0, 0.0, 0.0], _Scale=[1, 1, 1], LineWidth=1.0): try: TextScale = 0.04 txtCol = coin.SoBaseColor() # must be converted to SoBaseColor txtCol.rgb = _color txtXSo = coin.SoSeparator() # must be converted to SoBaseColor txtXSo.Name = "90Degree" txtXTransform = coin.SoTransform() txtXTransform.translation.setValue(5.5, 0.0, 0.0) txtXTransform.rotation.setValue(coin.SbVec3f(6.0, 0.0, 0.0), math.radians(0.0)) txtXTransform.scaleFactor.setValue(TextScale, TextScale, TextScale) textX = ["90.0°", ""] text3DX = coin.SoAsciiText() # Draw text in the 3D world text3DX.string.setValues([l.encode("utf8") for l in textX if l]) txtXSo.addChild(txtXTransform) txtXSo.addChild(txtCol) txtXSo.addChild(text3DX) txtXPSo = coin.SoSeparator() # must be converted to SoBaseColor txtXPSo.Name = "270Degree" txtXPTransform = coin.SoTransform() txtXPTransform.translation.setValue(0.0, -5.5, 0.0) txtXPTransform.rotation.setValue(coin.SbVec3f(0.0, 0.0, 0.0), math.radians(0.0)) txtXPTransform.scaleFactor.setValue(TextScale, TextScale, TextScale) textXP = ["270.0°", ""] text3DXP = coin.SoAsciiText() # Draw text in the 3D world text3DXP.string.setValues([l.encode("utf8") for l in textXP if l]) txtXPSo.addChild(txtXPTransform) txtXPSo.addChild(txtCol) txtXPSo.addChild(text3DXP) txtYSo = coin.SoSeparator() # must be converted to SoBaseColor txtYSo.Name = "0Degree" txtYTransform = coin.SoTransform() txtYTransform.translation.setValue(0.0, 5.5, 0.0) txtYTransform.rotation.setValue(coin.SbVec3f(0.0, 0.0, 0.0), math.radians(00.0)) txtYTransform.scaleFactor.setValue(TextScale, TextScale, TextScale) textY = ["0.0°", ""] text3DY = coin.SoAsciiText() # Draw text in the 3D world text3DY.string.setValues([l.encode("utf8") for l in textY if l]) txtYSo.addChild(txtYTransform) txtYSo.addChild(txtCol) txtYSo.addChild(text3DY) txtYPSo = coin.SoSeparator() # must be converted to SoBaseColor txtYPSo.Name = "180Degree" txtYPTransform = coin.SoTransform() txtYPTransform.translation.setValue(-6.0, 0.0, 0.0) txtYPTransform.rotation.setValue(coin.SbVec3f(0.0, 0.0, 0.0), math.radians(0.0)) txtYPTransform.scaleFactor.setValue(TextScale, TextScale, TextScale) textYP = ["180.0°", ""] text3DYP = coin.SoAsciiText() # Draw text in the 3D world text3DYP.string.setValues([l.encode("utf8") for l in textYP if l]) txtYPSo.addChild(txtYPTransform) txtYPSo.addChild(txtCol) txtYPSo.addChild(text3DYP) groupT = coin.SoSeparator() groupT.Name = "GroupT" groupT.addChild(txtXSo) groupT.addChild(txtXPSo) groupT.addChild(txtYSo) groupT.addChild(txtYPSo) txtRoot = coin.SoSeparator() txtRoot.Name = "AllText-coordination" txtrootTrans = coin.SoTransform() txtrootTrans.rotation.setValue(coin.SbVec3f(1.0, 0.0, 0.0), math.radians(0)) txtRoot.addChild(txtrootTrans) txtRoot.addChild(groupT) tRadiusX = coin.SbVec3f() tRadiusY = coin.SbVec3f() tRadiusZ = coin.SbVec3f() transfromX = coin.SoTransform() transfromY = coin.SoTransform() transfromZ = coin.SoTransform() tRadiusX.setValue(1, 0, 0) tRadiusY.setValue(0, 1, 0) tRadiusZ.setValue(0, 0, 1) transfromX.rotation.setValue(tRadiusX, math.radians(setupRotation[0])) transfromY.rotation.setValue(tRadiusY, math.radians(setupRotation[1])) transfromZ.rotation.setValue(tRadiusZ, math.radians(setupRotation[2])) SoSeparatorSetupX = coin.SoSeparator() SoSeparatorSetupX.Name = "SetupX" SoSeparatorSetupY = coin.SoSeparator() SoSeparatorSetupY.Name = "SetupY" SoSeparatorSetupZ = coin.SoSeparator() SoSeparatorSetupZ.Name = "SetupZ" SoSeparatorSetupX.addChild(transfromX) SoSeparatorSetupX.addChild(txtRoot) SoSeparatorSetupY.addChild(transfromY) SoSeparatorSetupY.addChild(SoSeparatorSetupX) SoSeparatorSetupZ.addChild(transfromZ) SoSeparatorSetupZ.addChild(SoSeparatorSetupY) tempR = coin.SbVec3f() tempR.setValue(_rotation[0], _rotation[1], _rotation[2]) rootTransform = coin.SoTransform() rootTransform.rotation.setValue(tempR, math.radians(_rotation[3])) rootTransform.scaleFactor.setValue(_Scale) material = coin.SoMaterial() material.diffuseColor.setValue(_color) material.emissiveColor.setValue(_color) material.transparency.setValue(0.0) root = coin.SoSeparator() root.Name = "RootText" transla = coin.SoTranslation() transla.translation.setValue([vec.x, vec.y, vec.z]) root.addChild(material) col1 = coin.SoBaseColor() # must be converted to SoBaseColor col1.rgb = _color root.addChild(rootTransform) root.addChild(col1) root.addChild(transla) root.addChild(SoSeparatorSetupZ) return root except Exception as err: App.Console.PrintError("'Wheel' 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 draw_AllParts(vec=App.Vector(0, 0, 0), Ptype: str = "", _color=FR_COLOR.FR_RED, setupRotation=[0, 0, 0, 0], _rotation=[0, 0, 0, 0], _Scale=[1, 1, 1], LineWidth=1): style = coin.SoDrawStyle() style.lineWidth = LineWidth objectToDraw = coin.SoSeparator() theObject = coin.SoCylinder() transtheObject = coin.SoTransform() # theObject cylinder tempC = coin.SbVec3f() if Ptype == "Center": objectToDraw.Name = "Center" tempC.setValue(1, 0, 0) transtheObject.rotation.setValue(tempC, math.radians(90)) theObject.radius = 4.5 theObject.height = 0.65 col1 = coin.SoBaseColor() # must be converted to SoBaseColor col1.rgb = FR_COLOR.FR_GLASS elif Ptype == "Xaxis": objectToDraw.Name = "Xaxis" tempC.setValue(0, 0, 1) transtheObject.rotation.setValue(tempC, math.radians(90)) theObject.radius = 0.25 theObject.height = 20 col1 = coin.SoBaseColor() # must be converted to SoBaseColor col1.rgb = FR_COLOR.FR_RED elif Ptype == "Yaxis": objectToDraw.Name = "Yaxis" tempC.setValue(0, 0, 1) transtheObject.rotation.setValue(tempC, math.radians(0)) theObject.radius = 0.25 theObject.height = 20 col1 = coin.SoBaseColor() # must be converted to SoBaseColor col1.rgb = FR_COLOR.FR_GREENYELLOW elif Ptype == "45axis": objectToDraw.Name = "45axis" tempC.setValue(0, 0, 1) transtheObject.rotation.setValue(tempC, math.radians(45)) theObject.radius = 0.25 theObject.height = 14 col1 = coin.SoBaseColor() # must be converted to SoBaseColor col1.rgb = FR_COLOR.FR_BLUEVIOLET elif Ptype == "135axis": objectToDraw.Name = "135Axis" tempC.setValue(0, 0, 1) transtheObject.rotation.setValue(tempC, math.radians(135)) theObject.radius = 0.25 theObject.height = 14 col1 = coin.SoBaseColor() # must be converted to SoBaseColor col1.rgb = FR_COLOR.FR_ORANGE objectToDraw.addChild(col1) objectToDraw.addChild(transtheObject) objectToDraw.addChild(theObject) tRadiusX = coin.SbVec3f() tRadiusY = coin.SbVec3f() tRadiusZ = coin.SbVec3f() tRadiusX.setValue(1, 0, 0) tRadiusY.setValue(0, 1, 0) tRadiusZ.setValue(0, 0, 1) tempTransform_x = coin.SoTransform() tempTransform_y = coin.SoTransform() tempTransform_z = coin.SoTransform() tempTransform_x.rotation.setValue(tRadiusX, math.radians(setupRotation[0])) tempTransform_y.rotation.setValue(tRadiusY, math.radians(setupRotation[1])) tempTransform_z.rotation.setValue(tRadiusZ, math.radians(setupRotation[2])) SoSeparatorSetupX = coin.SoSeparator() SoSeparatorSetupY = coin.SoSeparator() SoSeparatorSetupZ = coin.SoSeparator() SoSeparatorSetupX.addChild(tempTransform_x) SoSeparatorSetupX.addChild(objectToDraw) SoSeparatorSetupY.addChild(tempTransform_y) SoSeparatorSetupY.addChild(SoSeparatorSetupX) SoSeparatorSetupZ.addChild(tempTransform_z) SoSeparatorSetupZ.addChild(SoSeparatorSetupY) tempR = coin.SbVec3f() tempR.setValue(_rotation[0], _rotation[1], _rotation[2]) rootTransform = coin.SoTransform() rootTransform.rotation.setValue(tempR, math.radians(_rotation[3])) rootTransform.scaleFactor.setValue(_Scale) root = coin.SoSeparator() root.Name = "RootAxisDrawing" transla = coin.SoTranslation() transla.translation.setValue([vec.x, vec.y, vec.z]) material = coin.SoMaterial() if (Ptype == "Center"): material.transparency.setValue(0.80) else: material.transparency.setValue(0.0) material.diffuseColor.setValue(_color) material.emissiveColor.setValue(_color) root.addChild(transla) root.addChild(rootTransform) #root.addChild(material) root.addChild(SoSeparatorSetupZ) return root
def __init__(self, doc, object_name, alignment, datum=Vector()): """ Constructor """ self.alignment = alignment self.doc = doc self.names = [doc.Name, object_name, 'ALIGNMENT_TRACKER'] self.user_dragging = False self.status_bar = Gui.getMainWindow().statusBar() self.pi_list = [] self.datum = alignment.model.data.get('meta').get('Start') self.drag_curves = [] self.message_queue = {} #base (placement) transformation for the alignment self.transform = coin.SoTransform() self.transform.translation.setValue( tuple(alignment.model.data.get('meta').get('Start')) ) super().__init__(names=self.names, children=[self.transform]) #scenegraph node structure for editing and dragging operations self.groups = { 'EDIT': coin.SoGroup(), 'DRAG': coin.SoGroup(), 'SELECTED': coin.SoSeparator(), 'PARTIAL': coin.SoSeparator(), } self.state.draggable = True self.drag_transform = coin.SoTransform() #add two nodes to the drag group - the transform and a dummy node #which provides a way to access the transform matrix self.groups['SELECTED'].addChild(self.drag_transform) self.groups['SELECTED'].addChild(coin.SoSeparator()) self.groups['DRAG'].addChild(self.groups['SELECTED']) self.groups['DRAG'].addChild(self.groups['PARTIAL']) self.node.addChild(self.groups['EDIT']) self.node.addChild(self.groups['DRAG']) #generate initial node trackers and wire trackers for mouse interaction #and add them to the scenegraph self.trackers = {} self.build_trackers() _trackers = [] for _v in self.trackers.values(): _trackers.extend(_v) for _v in _trackers: self.insert_node(_v.get_node(), self.groups['EDIT']) #insert in the scenegraph root self.insert_node(self.get_node()) self.select_cb = \ ViewState().view.addEventCallback( 'SoMouseButtonEvent', self.post_select_event)
def calculateAlignment(vectors, align): lblPos =coin.SoTransform() # Use this to put all data needed for the lblPosition p1 = p2 = p3 = p4 = None # These variables will keep the min value of each coordinations # WE HAVE LEFT ALIGNMENT p1 = vectors[0] p2 = vectors[1] FourVector = False if len(vectors == 4): FourVector = True p3 = vectors[0] p4 = vectors[1] minX = minY = minZ = maxX = minY = minZ = None if FourVector == 1: minX = min([p1.x, p2.x, p3.x, p4.x]) minY = min([p1.y, p2.y, p3.y, p4.y]) minZ = min([p1.z, p2.z, p3.z, p4.z]) else: minX = min([p1.x, p2.x]) minY = min([p1.y, p2.y]) minZ = min([p1.z, p2.z]) if FourVector: maxX = max([p1.x, p2.x, p3.x, p4.x]) maxY = max([p1.y, p2.y, p3.y, p4.y]) maxZ = max([p1.z, p2.z, p3.z, p4.z]) else: maxX = max([p1.x, p2.x]) maxY = max([p1.y, p2.y]) maxZ = max([p1.z, p2.z]) if len(vectors) < 2: return (0, 0, 0) # We don't have any vectors, return zero ''' The shape is like this p1___________________ p2 | | | face | | | p3 ___________________ p4 not having p3,p4 means it is a line only ''' if align == FR_ALIGN.FR_ALIGN_LEFT or align == FR_ALIGN.FR_ALIGN_LEFT_BOTTOM: return (p1) elif align == FR_ALIGN.FR_ALIGN_RIGHT or align == FR_ALIGN.FR_ALIGN_RIGHT_BOTTOM: # WE HAVE RIGHT ALIGNMENT pass elif align == FR_ALIGN.FR_ALIGN_CENTER or align == FR_ALIGN.FR_ALIGN_CENTER_BOTTOM: # WE HAVE CENTER-BOTTOM ALIGNMENT pass elif align == FR_ALIGN.FR_ALIGN_LEFT_TOP: # Align LEFT-TOP pass elif align == FR_ALIGN.FR_ALIGN_RIGHT_TOP: # Align RIGHT-TOP pass elif align == FR_ALIGN.FR_ALIGN_CENTER_TOP: # Align CENTER-TOP pass elif align == FR_ALIGN.FR_ALIGN_CENTER_CENTER: # Align LEFT-TOP pass
def onChanged(self, vobj, prop): if prop == "LineColor": l = vobj.LineColor self.mat.diffuseColor.setValue([l[0], l[1], l[2]]) elif prop == "DrawStyle": if vobj.DrawStyle == "Solid": self.linestyle.linePattern = 0xffff elif vobj.DrawStyle == "Dashed": self.linestyle.linePattern = 0xf00f elif vobj.DrawStyle == "Dotted": self.linestyle.linePattern = 0x0f0f else: self.linestyle.linePattern = 0xff88 elif prop == "LineWidth": self.linestyle.lineWidth = vobj.LineWidth elif prop == "BubbleSize": if hasattr(self, "bubbleset"): if self.bubbles: self.bubbleset.removeChild(self.bubbles) self.bubbles = None if vobj.Object.Shape: if vobj.Object.Shape.Edges: self.bubbles = coin.SoSeparator() self.bubblestyle = coin.SoDrawStyle() self.bubblestyle.linePattern = 0xffff self.bubbles.addChild(self.bubblestyle) import Part, Draft self.bubbletexts = [] for i in range(len(vobj.Object.Shape.Edges)): verts = vobj.Object.Shape.Edges[i].Vertexes p1 = verts[0].Point p2 = verts[1].Point dv = p2.sub(p1) dv.normalize() rad = vobj.BubbleSize center = p2.add(dv.scale(rad, rad, rad)) buf = Part.makeCircle(rad, center).writeInventor() try: cin = coin.SoInput() cin.setBuffer(buf) cob = coin.SoDB.readAll(cin) except: import re # workaround for pivy SoInput.setBuffer() bug buf = buf.replace("\n", "") pts = re.findall("point \[(.*?)\]", buf)[0] pts = pts.split(",") pc = [] for p in pts: v = p.strip().split() pc.append([ float(v[0]), float(v[1]), float(v[2]) ]) coords = coin.SoCoordinate3() coords.point.setValues(0, len(pc), pc) line = coin.SoLineSet() line.numVertices.setValue(-1) else: coords = cob.getChild(1).getChild(0).getChild( 2) line = cob.getChild(1).getChild(0).getChild(3) self.bubbles.addChild(coords) self.bubbles.addChild(line) st = coin.SoSeparator() tr = coin.SoTransform() tr.translation.setValue( (center.x, center.y - rad / 4, center.z)) fo = coin.SoFont() fo.name = Draft.getParam("textfont", "Arial,Sans") fo.size = rad * 100 tx = coin.SoText2() tx.justification = coin.SoText2.CENTER self.bubbletexts.append(tx) st.addChild(tr) st.addChild(fo) st.addChild(tx) self.bubbles.addChild(st) self.bubbleset.addChild(self.bubbles) self.onChanged(vobj, "NumberingStyle") elif prop == "NumberingStyle": if hasattr(self, "bubbletexts"): chars = "abcdefghijklmnopqrstuvwxyz" roman = (('M', 1000), ('CM', 900), ('D', 500), ('CD', 400), ('C', 100), ('XC', 90), ('L', 50), ('XL', 40), ('X', 10), ('IX', 9), ('V', 5), ('IV', 4), ('I', 1)) num = 0 for t in self.bubbletexts: if vobj.NumberingStyle == "1,2,3": t.string = str(num + 1) elif vobj.NumberingStyle == "01,02,03": t.string = str(num + 1).zfill(2) elif vobj.NumberingStyle == "001,002,003": t.string = str(num + 1).zfill(3) elif vobj.NumberingStyle == "A,B,C": result = "" base = num / 26 if base: result += chars[base].upper() remainder = num % 26 result += chars[remainder].upper() t.string = result elif vobj.NumberingStyle == "a,b,c": result = "" base = num / 26 if base: result += chars[base] remainder = num % 26 result += chars[remainder] t.string = result elif vobj.NumberingStyle == "I,II,III": result = "" num += 1 for numeral, integer in roman: while num >= integer: result += numeral num -= integer t.string = result elif vobj.NumberingStyle == "L0,L1,L2": t.string = "L" + str(num) num += 1
def setupCoin(self): from pivy import coin compasssep = coin.SoSeparator() self.transform = coin.SoTransform() darkNorthMaterial = coin.SoMaterial() darkNorthMaterial.diffuseColor.set1Value(0, 0.5, 0, 0) # north dark color lightNorthMaterial = coin.SoMaterial() lightNorthMaterial.diffuseColor.set1Value(0, 0.9, 0, 0) # north light color darkGreyMaterial = coin.SoMaterial() darkGreyMaterial.diffuseColor.set1Value(0, 0.9, 0.9, 0.9) # dark color lightGreyMaterial = coin.SoMaterial() lightGreyMaterial.diffuseColor.set1Value(0, 0.5, 0.5, 0.5) # light color coords = self.buildCoordinates() # coordIndex = [0, 1, 2, -1, 2, 3, 0, -1] lightColorFaceset = coin.SoIndexedFaceSet() lightColorCoordinateIndex = [4, 5, 6, -1, 8, 9, 10, -1, 12, 13, 14, -1] lightColorFaceset.coordIndex.setValues(0, len(lightColorCoordinateIndex), lightColorCoordinateIndex) darkColorFaceset = coin.SoIndexedFaceSet() darkColorCoordinateIndex = [6, 7, 4, -1, 10, 11, 8, -1, 14, 15, 12, -1] darkColorFaceset.coordIndex.setValues(0, len(darkColorCoordinateIndex), darkColorCoordinateIndex) lightNorthFaceset = coin.SoIndexedFaceSet() lightNorthCoordinateIndex = [2, 3, 0, -1] lightNorthFaceset.coordIndex.setValues(0, len(lightNorthCoordinateIndex), lightNorthCoordinateIndex) darkNorthFaceset = coin.SoIndexedFaceSet() darkNorthCoordinateIndex = [0, 1, 2, -1] darkNorthFaceset.coordIndex.setValues(0, len(darkNorthCoordinateIndex), darkNorthCoordinateIndex) self.compassswitch = coin.SoSwitch() self.compassswitch.whichChild = coin.SO_SWITCH_NONE self.compassswitch.addChild(compasssep) lightGreySeparator = coin.SoSeparator() lightGreySeparator.addChild(lightGreyMaterial) lightGreySeparator.addChild(lightColorFaceset) darkGreySeparator = coin.SoSeparator() darkGreySeparator.addChild(darkGreyMaterial) darkGreySeparator.addChild(darkColorFaceset) lightNorthSeparator = coin.SoSeparator() lightNorthSeparator.addChild(lightNorthMaterial) lightNorthSeparator.addChild(lightNorthFaceset) darkNorthSeparator = coin.SoSeparator() darkNorthSeparator.addChild(darkNorthMaterial) darkNorthSeparator.addChild(darkNorthFaceset) compasssep.addChild(coords) compasssep.addChild(self.transform) compasssep.addChild(lightGreySeparator) compasssep.addChild(darkGreySeparator) compasssep.addChild(lightNorthSeparator) compasssep.addChild(darkNorthSeparator) return self.compassswitch
def __init__(self): # self.space = 1 self.space = Draft.getParam("gridSpacing") # self.mainlines = 10 self.mainlines = Draft.getParam("gridEvery") self.numlines = 100 col = [0.2, 0.2, 0.3] pick = coin.SoPickStyle() pick.style.setValue(coin.SoPickStyle.UNPICKABLE) self.trans = coin.SoTransform() self.trans.translation.setValue([0, 0, 0]) bound = (self.numlines / 2) * self.space pts = [] mpts = [] apts = [] for i in range(self.numlines + 1): curr = -bound + i * self.space z = 0 if i / float(self.mainlines) == i / self.mainlines: if round(curr, 4) == 0: apts.extend([[-bound, curr, z], [bound, curr, z]]) apts.extend([[curr, -bound, z], [curr, bound, z]]) else: mpts.extend([[-bound, curr, z], [bound, curr, z]]) mpts.extend([[curr, -bound, z], [curr, bound, z]]) else: pts.extend([[-bound, curr, z], [bound, curr, z]]) pts.extend([[curr, -bound, z], [curr, bound, z]]) idx = [] midx = [] aidx = [] for p in range(0, len(pts), 2): idx.append(2) for mp in range(0, len(mpts), 2): midx.append(2) for ap in range(0, len(apts), 2): aidx.append(2) mat1 = coin.SoMaterial() mat1.transparency.setValue(0.7) mat1.diffuseColor.setValue(col) self.coords1 = coin.SoCoordinate3() self.coords1.point.setValues(pts) lines1 = coin.SoLineSet() lines1.numVertices.setValues(idx) mat2 = coin.SoMaterial() mat2.transparency.setValue(0.3) mat2.diffuseColor.setValue(col) self.coords2 = coin.SoCoordinate3() self.coords2.point.setValues(mpts) lines2 = coin.SoLineSet() lines2.numVertices.setValues(midx) mat3 = coin.SoMaterial() mat3.transparency.setValue(0) mat3.diffuseColor.setValue(col) self.coords3 = coin.SoCoordinate3() self.coords3.point.setValues(apts) lines3 = coin.SoLineSet() lines3.numVertices.setValues(aidx) s = coin.SoSeparator() s.addChild(pick) s.addChild(self.trans) s.addChild(mat1) s.addChild(self.coords1) s.addChild(lines1) s.addChild(mat2) s.addChild(self.coords2) s.addChild(lines2) s.addChild(mat3) s.addChild(self.coords3) s.addChild(lines3) Tracker.__init__(self, children=[s]) self.update()
def makeSolarDiagram(longitude, latitude, scale=1, complete=False, tz=None): """makeSolarDiagram(longitude,latitude,[scale,complete,tz]): returns a solar diagram as a pivy node. If complete is True, the 12 months are drawn. Tz is the timezone related to UTC (ex: -3 = UTC-3)""" oldversion = False ladybug = False try: import ladybug from ladybug import location from ladybug import sunpath except Exception: # TODO - remove pysolar dependency # FreeCAD.Console.PrintWarning("Ladybug module not found, using pysolar instead. Warning, this will be deprecated in the future\n") ladybug = False try: import pysolar except Exception: try: import Pysolar as pysolar except Exception: FreeCAD.Console.PrintError( "The pysolar module was not found. Unable to generate solar diagrams\n" ) return None else: oldversion = True if tz: tz = datetime.timezone(datetime.timedelta(hours=-3)) else: tz = datetime.timezone.utc else: loc = ladybug.location.Location(latitude=latitude, longitude=longitude, time_zone=tz) sunpath = ladybug.sunpath.Sunpath.from_location(loc) from pivy import coin if not scale: return None circles = [] sunpaths = [] hourpaths = [] circlepos = [] hourpos = [] # build the base circle + number positions import Part for i in range(1, 9): circles.append(Part.makeCircle(scale * (i / 8.0))) for ad in range(0, 360, 15): a = math.radians(ad) p1 = FreeCAD.Vector(math.cos(a) * scale, math.sin(a) * scale, 0) p2 = FreeCAD.Vector( math.cos(a) * scale * 0.125, math.sin(a) * scale * 0.125, 0) p3 = FreeCAD.Vector( math.cos(a) * scale * 1.08, math.sin(a) * scale * 1.08, 0) circles.append(Part.LineSegment(p1, p2).toShape()) circlepos.append((ad, p3)) # build the sun curves at solstices and equinoxe year = datetime.datetime.now().year hpts = [[] for i in range(24)] m = [(6, 21), (7, 21), (8, 21), (9, 21), (10, 21), (11, 21), (12, 21)] if complete: m.extend([(1, 21), (2, 21), (3, 21), (4, 21), (5, 21)]) for i, d in enumerate(m): pts = [] for h in range(24): if ladybug: sun = sunpath.calculate_sun(month=d[0], day=d[1], hour=h) alt = math.radians(sun.altitude) az = 90 + sun.azimuth elif oldversion: dt = datetime.datetime(year, d[0], d[1], h) alt = math.radians( pysolar.solar.GetAltitudeFast(latitude, longitude, dt)) az = pysolar.solar.GetAzimuth(latitude, longitude, dt) az = -90 + az # pysolar's zero is south, ours is X direction else: dt = datetime.datetime(year, d[0], d[1], h, tzinfo=tz) alt = math.radians( pysolar.solar.get_altitude_fast(latitude, longitude, dt)) az = pysolar.solar.get_azimuth(latitude, longitude, dt) az = 90 + az # pysolar's zero is north, ours is X direction if az < 0: az = 360 + az az = math.radians(az) zc = math.sin(alt) * scale ic = math.cos(alt) * scale xc = math.cos(az) * ic yc = math.sin(az) * ic p = FreeCAD.Vector(xc, yc, zc) pts.append(p) hpts[h].append(p) if i in [0, 6]: ep = FreeCAD.Vector(p) ep.multiply(1.08) if ep.z >= 0: if not oldversion: h = 24 - h # not sure why this is needed now... But it is. if h == 12: if i == 0: h = "SUMMER" else: h = "WINTER" if latitude < 0: if h == "SUMMER": h = "WINTER" else: h = "SUMMER" hourpos.append((h, ep)) if i < 7: sunpaths.append(Part.makePolygon(pts)) for h in hpts: if complete: h.append(h[0]) hourpaths.append(Part.makePolygon(h)) # cut underground lines sz = 2.1 * scale cube = Part.makeBox(sz, sz, sz) cube.translate(FreeCAD.Vector(-sz / 2, -sz / 2, -sz)) sunpaths = [sp.cut(cube) for sp in sunpaths] hourpaths = [hp.cut(cube) for hp in hourpaths] # build nodes ts = 0.005 * scale # text scale mastersep = coin.SoSeparator() circlesep = coin.SoSeparator() numsep = coin.SoSeparator() pathsep = coin.SoSeparator() hoursep = coin.SoSeparator() hournumsep = coin.SoSeparator() mastersep.addChild(circlesep) mastersep.addChild(numsep) mastersep.addChild(pathsep) mastersep.addChild(hoursep) for item in circles: circlesep.addChild(toNode(item)) for item in sunpaths: for w in item.Edges: pathsep.addChild(toNode(w)) for item in hourpaths: for w in item.Edges: hoursep.addChild(toNode(w)) for p in circlepos: text = coin.SoText2() s = p[0] - 90 s = -s if s > 360: s = s - 360 if s < 0: s = 360 + s if s == 0: s = "N" elif s == 90: s = "E" elif s == 180: s = "S" elif s == 270: s = "W" else: s = str(s) text.string = s text.justification = coin.SoText2.CENTER coords = coin.SoTransform() coords.translation.setValue([p[1].x, p[1].y, p[1].z]) coords.scaleFactor.setValue([ts, ts, ts]) item = coin.SoSeparator() item.addChild(coords) item.addChild(text) numsep.addChild(item) for p in hourpos: text = coin.SoText2() s = str(p[0]) text.string = s text.justification = coin.SoText2.CENTER coords = coin.SoTransform() coords.translation.setValue([p[1].x, p[1].y, p[1].z]) coords.scaleFactor.setValue([ts, ts, ts]) item = coin.SoSeparator() item.addChild(coords) item.addChild(text) numsep.addChild(item) return mastersep