Draft: clean up ViewProviderLinearDimension class

This class handles linear dimensions of edges, or radial
dimensions of arcs and circles.

Various improvements in style, PEP8, spacing, docstrings.
In particular use more readable variable names.

The modules `Part` and `DraftGeomUtils` have been delayed
in import.

The `updataData` method is modified to return immediately
if the Proxy property modified is different from `Start`,
`End`, `Dimline` or `Direction`.
This commit is contained in:
vocx-fc
2020-06-16 16:48:43 -05:00
committed by Yorik van Havre
parent bbf05f50e6
commit a89eda2428

View File

@@ -32,17 +32,22 @@ They inherit their behavior from the base Annotation viewprovider.
# \brief Provides the Draft Dimension viewprovider classes.
import pivy.coin as coin
import lazy_loader.lazy_loader as lz
from PySide.QtCore import QT_TRANSLATE_NOOP
import FreeCAD as App
import DraftVecUtils
import DraftGeomUtils
import draftutils.units as units
import draftutils.utils as utils
import draftutils.gui_utils as gui_utils
from draftviewproviders.view_draft_annotation \
import ViewProviderDraftAnnotation
# Delay import of module until first use because it is heavy
Part = lz.LazyLoader("Part", globals(), "Part")
DraftGeomUtils = lz.LazyLoader("DraftGeomUtils", globals(), "DraftGeomUtils")
class ViewProviderDimensionBase(ViewProviderDraftAnnotation):
"""The base viewprovider for the Draft Dimensions object.
@@ -330,9 +335,12 @@ class ViewProviderDimensionBase(ViewProviderDraftAnnotation):
class ViewProviderLinearDimension(ViewProviderDimensionBase):
"""The viewprovider for the Linear Dimension objects.
This includes straight edge measurement, as well as measurement
of circular edges, and circumferences.
"""
A View Provider for the Draft Linear Dimension object
"""
def __init__(self, vobj):
super(ViewProviderLinearDimension, self).__init__(vobj)
super(ViewProviderLinearDimension, self).set_properties(vobj)
@@ -340,29 +348,36 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase):
self.Object = vobj.Object
vobj.Proxy = self
def attach(self, vobj):
'''Setup the scene sub-graph of the view provider'''
"""Set up the scene sub-graph of the viewprovider."""
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.text = coin.SoAsciiText() # Can be oriented in 3D space
self.text3d = coin.SoText2() # Faces the camera always
# The text string needs to be initialized to something,
# otherwise it may cause a crash of the system
self.text.string = "d"
self.text3d.string = "d"
self.textpos = coin.SoTransform()
self.text.justification = self.text3d.justification = coin.SoAsciiText.CENTER
self.text.justification = coin.SoAsciiText.CENTER
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()
@@ -371,12 +386,14 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase):
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)
@@ -389,6 +406,7 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase):
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)
@@ -401,254 +419,346 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase):
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")
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 updateData(self, obj, prop):
"""called when the base object is changed"""
import DraftGui
if prop in ["Start","End","Dimline","Direction"]:
"""Execute when a property from the Proxy class is changed.
if obj.Start == obj.End:
return
It only runs if `Start`, `End`, `Dimline`, or `Direction` changed.
"""
if prop not in ("Start", "End", "Dimline", "Direction"):
return
if not hasattr(self,"node"):
return
if obj.Start == obj.End:
return
import Part, DraftGeomUtils
from pivy import coin
if not hasattr(self, "node"):
return
# calculate the 4 points
self.p1 = obj.Start
self.p4 = obj.End
base = None
if hasattr(obj,"Direction"):
if not DraftVecUtils.isNull(obj.Direction):
v2 = self.p1.sub(obj.Dimline)
v3 = self.p4.sub(obj.Dimline)
v2 = DraftVecUtils.project(v2,obj.Direction)
v3 = DraftVecUtils.project(v3,obj.Direction)
self.p2 = obj.Dimline.add(v2)
self.p3 = obj.Dimline.add(v3)
if DraftVecUtils.equals(self.p2,self.p3):
base = None
proj = None
else:
base = Part.LineSegment(self.p2,self.p3).toShape()
proj = DraftGeomUtils.findDistance(self.p1,base)
if proj:
proj = proj.negative()
if not base:
if DraftVecUtils.equals(self.p1,self.p4):
base = None
proj = None
else:
base = Part.LineSegment(self.p1,self.p4).toShape()
proj = DraftGeomUtils.findDistance(obj.Dimline,base)
vobj = obj.ViewObject
# Calculate the 4 points
#
# | d |
# ---p2-------------c----p3---- c
# | |
# | |
# p1 p4
#
# - `c` is the `Dimline`, a point that lies on the dimension line
# or on its extension.
# - The line itself between `p2` to `p3` is the `base`.
# - The distance between `p2` (`base`) to `p1` is `proj`, an extension
# line from the dimension to the measured object.
# - If the `proj` distance is zero, `p1` and `p2` are the same point,
# and same with `p3` and `p4`.
#
self.p1 = obj.Start
self.p4 = obj.End
base = None
if (hasattr(obj, "Direction")
and not DraftVecUtils.isNull(obj.Direction)):
v2 = self.p1 - obj.Dimline
v3 = self.p4 - obj.Dimline
v2 = DraftVecUtils.project(v2, obj.Direction)
v3 = DraftVecUtils.project(v3, obj.Direction)
self.p2 = obj.Dimline + v2
self.p3 = obj.Dimline + v3
if DraftVecUtils.equals(self.p2, self.p3):
base = None
proj = None
else:
base = Part.LineSegment(self.p2, self.p3).toShape()
proj = DraftGeomUtils.findDistance(self.p1, base)
if proj:
self.p2 = self.p1.add(proj.negative())
self.p3 = self.p4.add(proj.negative())
else:
self.p2 = self.p1
self.p3 = self.p4
proj = proj.negative()
if not base:
if DraftVecUtils.equals(self.p1, self.p4):
base = None
proj = None
else:
base = Part.LineSegment(self.p1, self.p4).toShape()
proj = DraftGeomUtils.findDistance(obj.Dimline, base)
if proj:
if hasattr(obj.ViewObject,"ExtLines") and hasattr(obj.ViewObject, "ScaleMultiplier"):
dmax = obj.ViewObject.ExtLines.Value * obj.ViewObject.ScaleMultiplier
if dmax and (proj.Length > dmax):
if (dmax > 0):
self.p1 = self.p2.add(DraftVecUtils.scaleTo(proj,dmax))
self.p4 = self.p3.add(DraftVecUtils.scaleTo(proj,dmax))
else:
rest = proj.Length + dmax
self.p1 = self.p2.add(DraftVecUtils.scaleTo(proj,rest))
self.p4 = self.p3.add(DraftVecUtils.scaleTo(proj,rest))
self.p2 = self.p1 + proj.negative()
self.p3 = self.p4 + proj.negative()
else:
proj = (self.p3.sub(self.p2)).cross(App.Vector(0,0,1))
self.p2 = self.p1
self.p3 = self.p4
# calculate the arrows positions
self.trans1.translation.setValue((self.p2.x,self.p2.y,self.p2.z))
self.coord1.point.setValue((self.p2.x,self.p2.y,self.p2.z))
self.trans2.translation.setValue((self.p3.x,self.p3.y,self.p3.z))
self.coord2.point.setValue((self.p3.x,self.p3.y,self.p3.z))
# calculate dimension and extension lines overshoots positions
self.transDimOvershoot1.translation.setValue((self.p2.x,self.p2.y,self.p2.z))
self.transDimOvershoot2.translation.setValue((self.p3.x,self.p3.y,self.p3.z))
self.transExtOvershoot1.translation.setValue((self.p2.x,self.p2.y,self.p2.z))
self.transExtOvershoot2.translation.setValue((self.p3.x,self.p3.y,self.p3.z))
# calculate the text position and orientation
if hasattr(obj,"Normal"):
if DraftVecUtils.isNull(obj.Normal):
if proj:
norm = (self.p3.sub(self.p2).cross(proj)).negative()
if proj:
if hasattr(vobj, "ExtLines") and hasattr(vobj, "ScaleMultiplier"):
# The scale multiplier also affects the value
# of the extension line; this makes sure a maximum length
# is used if the calculated value is larger than it.
dmax = vobj.ExtLines.Value * vobj.ScaleMultiplier
if dmax and proj.Length > dmax:
if dmax > 0:
self.p1 = self.p2 + DraftVecUtils.scaleTo(proj, dmax)
self.p4 = self.p3 + DraftVecUtils.scaleTo(proj, dmax)
else:
norm = App.Vector(0,0,1)
else:
norm = App.Vector(obj.Normal)
else:
if proj:
norm = (self.p3.sub(self.p2).cross(proj)).negative()
else:
norm = App.Vector(0,0,1)
if not DraftVecUtils.isNull(norm):
norm.normalize()
u = self.p3.sub(self.p2)
u.normalize()
v1 = norm.cross(u)
rot1 = App.Placement(DraftVecUtils.getPlaneRotation(u,v1,norm)).Rotation.Q
self.transDimOvershoot1.rotation.setValue((rot1[0],rot1[1],rot1[2],rot1[3]))
self.transDimOvershoot2.rotation.setValue((rot1[0],rot1[1],rot1[2],rot1[3]))
if hasattr(obj.ViewObject,"FlipArrows"):
if obj.ViewObject.FlipArrows:
u = u.negative()
v2 = norm.cross(u)
rot2 = App.Placement(DraftVecUtils.getPlaneRotation(u,v2,norm)).Rotation.Q
self.trans1.rotation.setValue((rot2[0],rot2[1],rot2[2],rot2[3]))
self.trans2.rotation.setValue((rot2[0],rot2[1],rot2[2],rot2[3]))
if self.p1 != self.p2:
u3 = self.p1.sub(self.p2)
u3.normalize()
v3 = norm.cross(u3)
rot3 = App.Placement(DraftVecUtils.getPlaneRotation(u3,v3,norm)).Rotation.Q
self.transExtOvershoot1.rotation.setValue((rot3[0],rot3[1],rot3[2],rot3[3]))
self.transExtOvershoot2.rotation.setValue((rot3[0],rot3[1],rot3[2],rot3[3]))
if hasattr(obj.ViewObject,"TextSpacing")and hasattr(obj.ViewObject, "ScaleMultiplier"):
ts = obj.ViewObject.TextSpacing.Value * obj.ViewObject.ScaleMultiplier
offset = DraftVecUtils.scaleTo(v1,ts)
else:
offset = DraftVecUtils.scaleTo(v1,0.05)
rott = rot1
if hasattr(obj.ViewObject,"FlipText"):
if obj.ViewObject.FlipText:
rott = App.Rotation(*rott).multiply(App.Rotation(norm,180)).Q
offset = offset.negative()
# setting text
try:
m = obj.ViewObject.DisplayMode
except: # swallow all exceptions here since it always fails on first run (Displaymode enum no set yet)
m = ["2D","3D"][utils.get_param("dimstyle",0)]
if m == "3D":
offset = offset.negative()
self.tbase = (self.p2.add((self.p3.sub(self.p2).multiply(0.5)))).add(offset)
if hasattr(obj.ViewObject,"TextPosition"):
if not DraftVecUtils.isNull(obj.ViewObject.TextPosition):
self.tbase = obj.ViewObject.TextPosition
self.textpos.translation.setValue([self.tbase.x,self.tbase.y,self.tbase.z])
self.textpos.rotation = coin.SbRotation(rott[0],rott[1],rott[2],rott[3])
su = True
if hasattr(obj.ViewObject,"ShowUnit"):
su = obj.ViewObject.ShowUnit
# set text value
l = self.p3.sub(self.p2).Length
unit = None
if hasattr(obj.ViewObject,"UnitOverride"):
unit = obj.ViewObject.UnitOverride
# special representation if "Building US" scheme
if App.ParamGet("User parameter:BaseApp/Preferences/Units").GetInt("UserSchema",0) == 5:
s = App.Units.Quantity(l,App.Units.Length).UserString
self.string = s.replace("' ","'- ")
self.string = s.replace("+"," ")
elif hasattr(obj.ViewObject,"Decimals"):
self.string = DraftGui.displayExternal(l,obj.ViewObject.Decimals,'Length',su,unit)
else:
self.string = DraftGui.displayExternal(l,None,'Length',su,unit)
if hasattr(obj.ViewObject,"Override"):
if obj.ViewObject.Override:
self.string = obj.ViewObject.Override.replace("$dim",\
self.string)
self.text.string = self.text3d.string = utils.string_encode_coin(self.string)
rest = proj.Length + dmax
self.p1 = self.p2 + DraftVecUtils.scaleTo(proj, rest)
self.p4 = self.p3 + DraftVecUtils.scaleTo(proj, rest)
else:
proj = (self.p3 - self.p2).cross(App.Vector(0, 0, 1))
# set the lines
if m == "3D":
# calculate the spacing of the text
textsize = (len(self.string)*obj.ViewObject.FontSize.Value)/4.0
spacing = ((self.p3.sub(self.p2)).Length/2.0) - textsize
self.p2a = self.p2.add(DraftVecUtils.scaleTo(self.p3.sub(self.p2),spacing))
self.p2b = self.p3.add(DraftVecUtils.scaleTo(self.p2.sub(self.p3),spacing))
self.coords.point.setValues([[self.p1.x,self.p1.y,self.p1.z],
[self.p2.x,self.p2.y,self.p2.z],
[self.p2a.x,self.p2a.y,self.p2a.z],
[self.p2b.x,self.p2b.y,self.p2b.z],
[self.p3.x,self.p3.y,self.p3.z],
[self.p4.x,self.p4.y,self.p4.z]])
#self.line.numVertices.setValues([3,3])
self.line.coordIndex.setValues(0,7,(0,1,2,-1,3,4,5))
else:
self.coords.point.setValues([[self.p1.x,self.p1.y,self.p1.z],
[self.p2.x,self.p2.y,self.p2.z],
[self.p3.x,self.p3.y,self.p3.z],
[self.p4.x,self.p4.y,self.p4.z]])
#self.line.numVertices.setValue(4)
self.line.coordIndex.setValues(0,4,(0,1,2,3))
# Calculate the arrow positions
p2 = (self.p2.x, self.p2.y, self.p2.z)
p3 = (self.p3.x, self.p3.y, self.p3.z)
self.trans1.translation.setValue(p2)
self.coord1.point.setValue(p2)
self.trans2.translation.setValue(p3)
self.coord2.point.setValue(p3)
# Calculate dimension and extension lines overshoots positions
self.transDimOvershoot1.translation.setValue(p2)
self.transDimOvershoot2.translation.setValue(p3)
self.transExtOvershoot1.translation.setValue(p2)
self.transExtOvershoot2.translation.setValue(p3)
# Determine the orientation of the text by using a normal direction.
# By default the value of +Z will be used, or a calculated value
# from p2 and p3. So the text will lie on the XY plane
# or a plane coplanar with p2 and p3.
u = self.p3 - self.p2
u.normalize()
if proj:
_norm = u.cross(proj)
norm = _norm.negative()
else:
norm = App.Vector(0, 0, 1)
# If `Normal` exists and is different from the default `(0,0,0)`,
# it will be used.
if hasattr(obj, "Normal") and not DraftVecUtils.isNull(obj.Normal):
norm = App.Vector(obj.Normal)
if not DraftVecUtils.isNull(norm):
norm.normalize()
# Calculate the position of the arrows and extension lines
v1 = norm.cross(u)
_plane_rot = DraftVecUtils.getPlaneRotation(u, v1, norm)
rot1 = App.Placement(_plane_rot).Rotation.Q
self.transDimOvershoot1.rotation.setValue((rot1[0], rot1[1],
rot1[2], rot1[3]))
self.transDimOvershoot2.rotation.setValue((rot1[0], rot1[1],
rot1[2], rot1[3]))
if hasattr(vobj, "FlipArrows") and vobj.FlipArrows:
u = u.negative()
v2 = norm.cross(u)
_plane_rot = DraftVecUtils.getPlaneRotation(u, v2, norm)
rot2 = App.Placement(_plane_rot).Rotation.Q
self.trans1.rotation.setValue((rot2[0], rot2[1],
rot2[2], rot2[3]))
self.trans2.rotation.setValue((rot2[0], rot2[1],
rot2[2], rot2[3]))
if self.p1 != self.p2:
u3 = self.p1 - self.p2
u3.normalize()
v3 = norm.cross(u3)
_plane_rot = DraftVecUtils.getPlaneRotation(u3, v3, norm)
rot3 = App.Placement(_plane_rot).Rotation.Q
self.transExtOvershoot1.rotation.setValue((rot3[0], rot3[1],
rot3[2], rot3[3]))
self.transExtOvershoot2.rotation.setValue((rot3[0], rot3[1],
rot3[2], rot3[3]))
# Offset is the distance from the dimension line to the textual
# element that displays the value of the measurement
if hasattr(vobj, "TextSpacing") and hasattr(vobj, "ScaleMultiplier"):
ts = vobj.TextSpacing.Value * vobj.ScaleMultiplier
offset = DraftVecUtils.scaleTo(v1, ts)
else:
offset = DraftVecUtils.scaleTo(v1, 0.05)
rott = rot1
if hasattr(vobj, "FlipText") and vobj.FlipText:
_rott = App.Rotation(rott[0], rott[1], rott[2], rott[3])
rott = _rott.multiply(App.Rotation(norm, 180)).Q
offset = offset.negative()
# On first run the `DisplayMode` enumeration is not set, so we trap
# the exception and set the display mode using the value
# in the parameter database
try:
m = vobj.DisplayMode
except AssertionError:
m = ["2D", "3D"][utils.get_param("dimstyle", 0)]
if m == "3D":
offset = offset.negative()
# The position of the text element in the dimension is provided
# in absolute coordinates by the value of `TextPosition`,
# if it is different from the default `(0,0,0)`
if (hasattr(vobj, "TextPosition")
and not DraftVecUtils.isNull(vobj.TextPosition)):
self.tbase = vobj.TextPosition
else:
# Otherwise the position is calculated from the end points
# of the dimension line, and the offset that depends
# on `TextSpacing`
center = self.p2 + (self.p3 - self.p2).multiply(0.5)
self.tbase = center + offset
self.textpos.translation.setValue([self.tbase.x,
self.tbase.y,
self.tbase.z])
self.textpos.rotation = coin.SbRotation(rott[0], rott[1],
rott[2], rott[3])
show_unit = True
if hasattr(vobj, "ShowUnit"):
show_unit = vobj.ShowUnit
# Set text element showing the value of the dimension
length = (self.p3 - self.p2).Length
unit = None
if hasattr(vobj, "UnitOverride"):
unit = vobj.UnitOverride
# Special representation if we use 'Building US' scheme
u_params = App.ParamGet("User parameter:BaseApp/Preferences/Units")
if u_params.GetInt("UserSchema", 0) == 5:
s = App.Units.Quantity(length, App.Units.Length).UserString
self.string = s.replace("' ", "'- ") # feet
self.string = s.replace("+", " ")
elif hasattr(vobj, "Decimals"):
self.string = units.display_external(length,
vobj.Decimals,
'Length', show_unit, unit)
else:
self.string = units.display_external(length,
None,
'Length', show_unit, unit)
if hasattr(vobj, "Override") and vobj.Override:
self.string = vobj.Override.replace("$dim", self.string)
self.text.string = utils.string_encode_coin(self.string)
self.text3d.string = utils.string_encode_coin(self.string)
# Set the lines
if m == "3D":
# Calculate the spacing of the text
textsize = len(self.string) * vobj.FontSize.Value / 4.0
spacing = (self.p3 - self.p2).Length/2.0 - textsize
self.p2a = self.p2 + DraftVecUtils.scaleTo(self.p3 - self.p2,
spacing)
self.p2b = self.p3 + DraftVecUtils.scaleTo(self.p2 - self.p3,
spacing)
self.coords.point.setValues([[self.p1.x, self.p1.y, self.p1.z],
[self.p2.x, self.p2.y, self.p2.z],
[self.p2a.x, self.p2a.y, self.p2a.z],
[self.p2b.x, self.p2b.y, self.p2b.z],
[self.p3.x, self.p3.y, self.p3.z],
[self.p4.x, self.p4.y, self.p4.z]])
# self.line.numVertices.setValues([3, 3])
self.line.coordIndex.setValues(0, 7, (0, 1, 2, -1, 3, 4, 5))
else:
self.coords.point.setValues([[self.p1.x, self.p1.y, self.p1.z],
[self.p2.x, self.p2.y, self.p2.z],
[self.p3.x, self.p3.y, self.p3.z],
[self.p4.x, self.p4.y, self.p4.z]])
# self.line.numVertices.setValue(4)
self.line.coordIndex.setValues(0, 4, (0, 1, 2, 3))
def onChanged(self, vobj, prop):
"""Execute when a view property is changed."""
super(ViewProviderLinearDimension, self).onChanged(vobj, prop)
if prop == "ScaleMultiplier" and hasattr(vobj, "ScaleMultiplier"):
# update all dimension values
if hasattr(self,"font"):
obj = vobj.Object
properties = vobj.PropertiesList
if prop == "ScaleMultiplier" and "ScaleMultiplier" in properties:
# Update all dimension values
if hasattr(self, "font"):
self.font.size = vobj.FontSize.Value * vobj.ScaleMultiplier
if hasattr(self,"font3d"):
self.font3d.size = vobj.FontSize.Value * 100 * vobj.ScaleMultiplier
if hasattr(self,"node") and hasattr(self,"p2") and hasattr(vobj,"ArrowSize"):
if hasattr(self, "font3d"):
self.font3d.size = \
vobj.FontSize.Value * 10 * vobj.ScaleMultiplier
if (hasattr(self, "node") and hasattr(self, "p2")
and "ArrowSize" in properties):
self.remove_dim_arrows()
self.draw_dim_arrows(vobj)
if hasattr(vobj,"DimOvershoot"):
if "DimOvershoot" in properties:
self.remove_dim_overshoot()
self.draw_dim_overshoot(vobj)
if hasattr(vobj,"ExtOvershoot"):
if "ExtOvershoot" in properties:
self.remove_ext_overshoot()
self.draw_ext_overshoot(vobj)
self.updateData(vobj.Object,"Start")
vobj.Object.touch()
elif (prop == "FontSize") and hasattr(vobj,"FontSize") and hasattr(vobj, "ScaleMultiplier"):
if hasattr(self,"font"):
self.updateData(obj, "Start")
obj.touch()
elif (prop == "FontSize" and "FontSize" in properties
and "ScaleMultiplier" in properties):
if hasattr(self, "font"):
self.font.size = vobj.FontSize.Value * vobj.ScaleMultiplier
if hasattr(self,"font3d"):
self.font3d.size = vobj.FontSize.Value * 100 * vobj.ScaleMultiplier
vobj.Object.touch()
elif (prop == "FontName") and hasattr(vobj,"FontName"):
if hasattr(self,"font") and hasattr(self,"font3d"):
self.font.name = self.font3d.name = str(vobj.FontName)
vobj.Object.touch()
elif (prop == "LineColor") and hasattr(vobj,"LineColor"):
if hasattr(self,"color"):
c = vobj.LineColor
self.color.rgb.setValue(c[0],c[1],c[2])
elif (prop == "LineWidth") and hasattr(vobj,"LineWidth"):
if hasattr(self,"drawstyle"):
self.drawstyle.lineWidth = vobj.LineWidth
elif (prop in ["ArrowSize","ArrowType"]) and hasattr(vobj,"ArrowSize") and hasattr(vobj, "ScaleMultiplier"):
if hasattr(self,"node") and hasattr(self,"p2"):
self.remove_dim_arrows()
self.draw_dim_arrows(vobj)
vobj.Object.touch()
elif (prop == "DimOvershoot") and hasattr(vobj,"DimOvershoot") and hasattr(vobj, "ScaleMultiplier"):
if hasattr(self, "font3d"):
self.font3d.size = \
vobj.FontSize.Value * 10 * vobj.ScaleMultiplier
obj.touch()
elif (prop == "FontName" and "FontName" in properties
and hasattr(self, "font") and hasattr(self, "font3d")):
self.font.name = str(vobj.FontName)
self.font3d.name = str(vobj.FontName)
obj.touch()
elif (prop == "LineColor" and "LineColor" in properties
and hasattr(self, "color")):
col = vobj.LineColor
self.color.rgb.setValue(col[0], col[1], col[2])
elif (prop == "LineWidth" and "LineWidth" in properties
and hasattr(self, "drawstyle")):
self.drawstyle.lineWidth = vobj.LineWidth
elif (prop in ("ArrowSize", "ArrowType")
and "ArrowSize" in properties
and "ScaleMultiplier" in properties
and hasattr(self, "node") and hasattr(self, "p2")):
self.remove_dim_arrows()
self.draw_dim_arrows(vobj)
obj.touch()
elif (prop == "DimOvershoot"
and "DimOvershoot" in properties
and "ScaleMultiplier" in properties):
self.remove_dim_overshoot()
self.draw_dim_overshoot(vobj)
vobj.Object.touch()
elif (prop == "ExtOvershoot") and hasattr(vobj,"ExtOvershoot") and hasattr(vobj, "ScaleMultiplier"):
obj.touch()
elif (prop == "ExtOvershoot"
and "ExtOvershoot" in properties
and "ScaleMultiplier" in properties):
self.remove_ext_overshoot()
self.draw_ext_overshoot(vobj)
vobj.Object.touch()
elif (prop == "ShowLine") and hasattr(vobj,"ShowLine"):
obj.touch()
elif prop == "ShowLine" and "ShowLine" in properties:
if vobj.ShowLine:
self.lineswitch2.whichChild = -3
self.lineswitch3.whichChild = -3
@@ -656,17 +766,19 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase):
self.lineswitch2.whichChild = -1
self.lineswitch3.whichChild = -1
else:
self.updateData(vobj.Object,"Start")
self.updateData(obj, "Start")
def remove_dim_arrows(self):
# remove existing nodes
"""Remove dimension arrows in the dimension lines.
Remove the existing nodes.
"""
self.node.removeChild(self.marks)
self.node3d.removeChild(self.marks)
def draw_dim_arrows(self, vobj):
from pivy import coin
if not hasattr(vobj,"ArrowType"):
"""Draw dimension arrows."""
if not hasattr(vobj, "ArrowType"):
return
if self.p3.x < self.p2.x:
@@ -674,105 +786,112 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase):
else:
inv = True
# set scale
# Set scale
symbol = utils.ARROW_TYPES.index(vobj.ArrowType)
s = vobj.ArrowSize.Value * vobj.ScaleMultiplier
self.trans1.scaleFactor.setValue((s,s,s))
self.trans2.scaleFactor.setValue((s,s,s))
self.trans1.scaleFactor.setValue((s, s, s))
self.trans2.scaleFactor.setValue((s, s, s))
# set new nodes
# Set new nodes
self.marks = coin.SoSeparator()
self.marks.addChild(self.color)
s1 = coin.SoSeparator()
if symbol == "Circle":
s1.addChild(self.coord1)
else:
s1.addChild(self.trans1)
s1.addChild(gui_utils.dim_symbol(symbol,invert=not(inv)))
s1.addChild(gui_utils.dim_symbol(symbol, invert=not inv))
self.marks.addChild(s1)
s2 = coin.SoSeparator()
if symbol == "Circle":
s2.addChild(self.coord2)
else:
s2.addChild(self.trans2)
s2.addChild(gui_utils.dim_symbol(symbol,invert=inv))
s2.addChild(gui_utils.dim_symbol(symbol, invert=inv))
self.marks.addChild(s2)
self.node.insertChild(self.marks,2)
self.node3d.insertChild(self.marks,2)
self.node.insertChild(self.marks, 2)
self.node3d.insertChild(self.marks, 2)
def remove_dim_overshoot(self):
"""Remove the dimension overshoot lines."""
self.node.removeChild(self.marksDimOvershoot)
self.node3d.removeChild(self.marksDimOvershoot)
def draw_dim_overshoot(self, vobj):
from pivy import coin
# set scale
"""Draw dimension overshoot lines."""
# Set scale
s = vobj.DimOvershoot.Value * vobj.ScaleMultiplier
self.transDimOvershoot1.scaleFactor.setValue((s,s,s))
self.transDimOvershoot2.scaleFactor.setValue((s,s,s))
self.transDimOvershoot1.scaleFactor.setValue((s, s, s))
self.transDimOvershoot2.scaleFactor.setValue((s, s, s))
# remove existing nodes
# set new nodes
# Remove existing nodes, and set new nodes
self.marksDimOvershoot = coin.SoSeparator()
if vobj.DimOvershoot.Value:
self.marksDimOvershoot.addChild(self.color)
s1 = coin.SoSeparator()
s1.addChild(self.transDimOvershoot1)
s1.addChild(gui_utils.dimDash((-1,0,0),(0,0,0)))
s1.addChild(gui_utils.dimDash((-1, 0, 0), (0, 0, 0)))
self.marksDimOvershoot.addChild(s1)
s2 = coin.SoSeparator()
s2.addChild(self.transDimOvershoot2)
s2.addChild(gui_utils.dimDash((0,0,0),(1,0,0)))
s2.addChild(gui_utils.dimDash((0, 0, 0), (1, 0, 0)))
self.marksDimOvershoot.addChild(s2)
self.node.insertChild(self.marksDimOvershoot,2)
self.node3d.insertChild(self.marksDimOvershoot,2)
self.node.insertChild(self.marksDimOvershoot, 2)
self.node3d.insertChild(self.marksDimOvershoot, 2)
def remove_ext_overshoot(self):
"""Remove dimension extension overshoot lines."""
self.node.removeChild(self.marksExtOvershoot)
self.node3d.removeChild(self.marksExtOvershoot)
def draw_ext_overshoot(self, vobj):
from pivy import coin
# set scale
"""Draw dimension extension overshoot lines."""
# Set scale
s = vobj.ExtOvershoot.Value * vobj.ScaleMultiplier
self.transExtOvershoot1.scaleFactor.setValue((s,s,s))
self.transExtOvershoot2.scaleFactor.setValue((s,s,s))
self.transExtOvershoot1.scaleFactor.setValue((s, s, s))
self.transExtOvershoot2.scaleFactor.setValue((s, s, s))
# set new nodes
# Set new nodes
self.marksExtOvershoot = coin.SoSeparator()
if vobj.ExtOvershoot.Value:
self.marksExtOvershoot.addChild(self.color)
s1 = coin.SoSeparator()
s1.addChild(self.transExtOvershoot1)
s1.addChild(gui_utils.dimDash((0,0,0),(-1,0,0)))
s1.addChild(gui_utils.dimDash((0, 0, 0), (-1, 0, 0)))
self.marksExtOvershoot.addChild(s1)
s2 = coin.SoSeparator()
s2.addChild(self.transExtOvershoot2)
s2.addChild(gui_utils.dimDash((0,0,0),(-1,0,0)))
s2.addChild(gui_utils.dimDash((0, 0, 0), (-1, 0, 0)))
self.marksExtOvershoot.addChild(s2)
self.node.insertChild(self.marksExtOvershoot,2)
self.node3d.insertChild(self.marksExtOvershoot,2)
self.node.insertChild(self.marksExtOvershoot, 2)
self.node3d.insertChild(self.marksExtOvershoot, 2)
def is_linked_to_circle(self):
_obj = self.Object
if _obj.LinkedGeometry and len(_obj.LinkedGeometry) == 1:
lobj = _obj.LinkedGeometry[0][0]
lsub = _obj.LinkedGeometry[0][1]
if len(lsub) == 1 and "Edge" in lsub[0]:
n = int(lsub[0][4:]) - 1
edge = lobj.Shape.Edges[n]
"""Return true if the dimension measures a circular edge."""
obj = self.Object
if obj.LinkedGeometry and len(obj.LinkedGeometry) == 1:
linked_obj = obj.LinkedGeometry[0][0]
subelements = obj.LinkedGeometry[0][1]
if len(subelements) == 1 and "Edge" in subelements[0]:
sub = subelements[0]
index = int(sub[4:]) - 1
edge = linked_obj.Shape.Edges[index]
if DraftGeomUtils.geomType(edge) == "Circle":
return True
return False
def getIcon(self):
"""Return the path to the icon used by the viewprovider."""
if self.is_linked_to_circle():
return ":/icons/Draft_DimensionRadius.svg"
return ":/icons/Draft_Dimension_Tree.svg"