Add compass to Arch Site

The compass helps you to locate north in your drawings.

It has the following features:
 - Can be hidden independently from the site. So you can still have the
   site without the compass.
 - Can be rotated relative to the site.
 - Also rotates with the site
 - Always sits 1 meter above the site geometry

https://forum.freecadweb.org/viewtopic.php?f=23&t=34669
This commit is contained in:
furti
2019-03-05 17:41:33 +01:00
committed by Yorik van Havre
parent fe56e51e08
commit fa99516e6e

View File

@@ -257,6 +257,145 @@ def makeSolarDiagram(longitude,latitude,scale=1,complete=False):
numsep.addChild(item)
return mastersep
# Values in mm
COMPASS_POINTER_LENGTH = 1000
COMPASS_POINTER_WIDTH = 100
class Compass(object):
def __init__(self):
self.rootNode = self.setupCoin()
def show(self):
from pivy import coin
self.compassswitch.whichChild = coin.SO_SWITCH_ALL
def hide(self):
from pivy import coin
self.compassswitch.whichChild = coin.SO_SWITCH_NONE
def rotate(self, angleInDegrees):
from pivy import coin
self.transform.rotation.setValue(
coin.SbVec3f(0, 0, 1), math.radians(angleInDegrees))
def setZOffset(self, offsetInMillimeters):
from pivy import coin
self.transform.translation.setValue(0, 0, offsetInMillimeters)
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 buildCoordinates(self):
from pivy import coin
coords = coin.SoCoordinate3()
# North Arrow
coords.point.set1Value(0, 0, 0, 0)
coords.point.set1Value(1, COMPASS_POINTER_WIDTH,
COMPASS_POINTER_WIDTH, 0)
coords.point.set1Value(2, 0, COMPASS_POINTER_LENGTH, 0)
coords.point.set1Value(3, -COMPASS_POINTER_WIDTH,
COMPASS_POINTER_WIDTH, 0)
# East Arrow
coords.point.set1Value(4, 0, 0, 0)
coords.point.set1Value(
5, COMPASS_POINTER_WIDTH, -COMPASS_POINTER_WIDTH, 0)
coords.point.set1Value(6, COMPASS_POINTER_LENGTH, 0, 0)
coords.point.set1Value(7, COMPASS_POINTER_WIDTH,
COMPASS_POINTER_WIDTH, 0)
# South Arrow
coords.point.set1Value(8, 0, 0, 0)
coords.point.set1Value(
9, -COMPASS_POINTER_WIDTH, -COMPASS_POINTER_WIDTH, 0)
coords.point.set1Value(10, 0, -COMPASS_POINTER_LENGTH, 0)
coords.point.set1Value(
11, COMPASS_POINTER_WIDTH, -COMPASS_POINTER_WIDTH, 0)
# West Arrow
coords.point.set1Value(12, 0, 0, 0)
coords.point.set1Value(13, -COMPASS_POINTER_WIDTH,
COMPASS_POINTER_WIDTH, 0)
coords.point.set1Value(14, -COMPASS_POINTER_LENGTH, 0, 0)
coords.point.set1Value(
15, -COMPASS_POINTER_WIDTH, -COMPASS_POINTER_WIDTH, 0)
return coords
class _CommandSite:
@@ -374,6 +513,12 @@ class _Site(ArchFloor._Floor):
obj.addProperty("App::PropertyVector","OriginOffset","Site",QT_TRANSLATE_NOOP("App::Property","An optional offset between the model (0,0,0) origin and the point indicated by the geocoordinates"))
if not hasattr(obj,"Group"):
obj.addExtension("App::GroupExtensionPython", self)
if not "Compass" in pl:
obj.addProperty("App::PropertyBool", "Compass", "Compass", QT_TRANSLATE_NOOP(
"App::Property", "Show compass or not"))
if not "CompassRotation" in pl:
obj.addProperty("App::PropertyAngle", "CompassRotation", "Compass", QT_TRANSLATE_NOOP(
"App::Property", "The rotation of the Compass relative to the Site"))
self.Type = "Site"
obj.setEditorMode('Height',2)
@@ -577,12 +722,24 @@ class _ViewProviderSite(ArchFloor._ViewProviderFloor):
self.diagramsep.addChild(self.color)
vobj.Annotation.addChild(self.diagramswitch)
self.compass = Compass()
self.updateCompassVisibility(self.Object)
self.rotateCompass(self.Object)
vobj.Annotation.addChild(self.compass.rootNode)
def updateData(self,obj,prop):
if prop in ["Longitude","Latitude"]:
self.onChanged(obj.ViewObject,"SolarDiagram")
elif prop == "Declination":
self.onChanged(obj.ViewObject,"SolarDiagramPosition")
elif prop == "Terrain":
self.updateCompassLocation(obj)
elif prop == "Compass":
self.updateCompassVisibility(obj)
elif prop == "CompassRotation":
self.rotateCompass(obj)
def onChanged(self,vobj,prop):
@@ -611,6 +768,40 @@ class _ViewProviderSite(ArchFloor._ViewProviderFloor):
del self.diagramnode
else:
self.diagramswitch.whichChild = -1
elif prop == 'Visibility':
if vobj.Visibility:
self.updateCompassVisibility(self.Object)
else:
self.compass.hide()
def updateCompassVisibility(self, obj):
if not hasattr(self, 'compass'):
return
show = hasattr(obj, 'Compass') and obj.Compass
if show:
self.compass.show()
else:
self.compass.hide()
def rotateCompass(self, obj):
if not hasattr(self, 'compass'):
return
if hasattr(obj, 'CompassRotation'):
self.compass.rotate(obj.CompassRotation.Value)
def updateCompassLocation(self, obj):
if not hasattr(self, 'compass'):
return
boundBox = obj.Shape.BoundBox
pos = obj.Placement.Base
zOffset = boundBox.ZMax = pos.z
self.compass.setZOffset(zOffset + 1000)
if FreeCAD.GuiUp: