Add Draft workbench to .pre-commit-config (#24664)

* Add Draft workbench to .pre-commit-config

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
marcuspollio
2025-10-15 11:21:09 +02:00
committed by GitHub
parent f43af65eca
commit e831fc9163
225 changed files with 10713 additions and 9269 deletions

View File

@@ -75,7 +75,7 @@ class Array(DraftLink):
_log("v1.1, " + obj.Name + ", added hidden property 'PlacementList'")
self.set_general_properties(obj)
self.execute(obj) # Required to update Count and/or PlacementList.
self.execute(obj) # Required to update Count and/or PlacementList.
def set_properties(self, obj):
"""Set properties only if they don't exist."""
@@ -94,67 +94,57 @@ class Array(DraftLink):
properties = obj.PropertiesList
if "Base" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"The base object that will be duplicated")
_tip = QT_TRANSLATE_NOOP("App::Property", "The base object that will be duplicated")
obj.addProperty("App::PropertyLink", "Base", "Objects", _tip, locked=True)
obj.Base = None
if "ArrayType" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"The type of array to create.\n"
"- Ortho: places the copies "
"in the direction of the global X, "
"Y, Z axes.\n"
"- Polar: places the copies along "
"a circular arc, up to a specified "
"angle, and with certain orientation "
"defined by a center and an axis.\n"
"- Circular: places the copies "
"in concentric circles "
"around the base object.")
obj.addProperty("App::PropertyEnumeration",
"ArrayType",
"Objects",
_tip,
locked=True)
obj.ArrayType = ['ortho', 'polar', 'circular']
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"The type of array to create.\n"
"- Ortho: places the copies "
"in the direction of the global X, "
"Y, Z axes.\n"
"- Polar: places the copies along "
"a circular arc, up to a specified "
"angle, and with certain orientation "
"defined by a center and an axis.\n"
"- Circular: places the copies "
"in concentric circles "
"around the base object.",
)
obj.addProperty("App::PropertyEnumeration", "ArrayType", "Objects", _tip, locked=True)
obj.ArrayType = ["ortho", "polar", "circular"]
if "Fuse" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"Specifies if the copies "
"should be fused together "
"if they touch each other (slower)")
obj.addProperty("App::PropertyBool",
"Fuse",
"Objects",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"Specifies if the copies "
"should be fused together "
"if they touch each other (slower)",
)
obj.addProperty("App::PropertyBool", "Fuse", "Objects", _tip, locked=True)
obj.Fuse = False
if "Count" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"Total number of elements "
"in the array.\n"
"This property is read-only, "
"as the number depends "
"on the parameters of the array.")
obj.addProperty("App::PropertyInteger",
"Count",
"Objects",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"Total number of elements "
"in the array.\n"
"This property is read-only, "
"as the number depends "
"on the parameters of the array.",
)
obj.addProperty("App::PropertyInteger", "Count", "Objects", _tip, locked=True)
obj.Count = 0
obj.setEditorMode("Count", 1) # Read only
if not self.use_link:
if "PlacementList" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"The placement for each array element")
obj.addProperty("App::PropertyPlacementList",
"PlacementList",
"Objects",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property", "The placement for each array element")
obj.addProperty(
"App::PropertyPlacementList", "PlacementList", "Objects", _tip, locked=True
)
obj.PlacementList = []
def set_ortho_properties(self, obj):
@@ -162,66 +152,51 @@ class Array(DraftLink):
properties = obj.PropertiesList
if "NumberX" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"Number of copies in X-direction")
obj.addProperty("App::PropertyInteger",
"NumberX",
"Orthogonal array",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property", "Number of copies in X-direction")
obj.addProperty(
"App::PropertyInteger", "NumberX", "Orthogonal array", _tip, locked=True
)
obj.NumberX = 2
if "NumberY" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"Number of copies in Y-direction")
obj.addProperty("App::PropertyInteger",
"NumberY",
"Orthogonal array",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property", "Number of copies in Y-direction")
obj.addProperty(
"App::PropertyInteger", "NumberY", "Orthogonal array", _tip, locked=True
)
obj.NumberY = 2
if "NumberZ" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"Number of copies in Z-direction")
obj.addProperty("App::PropertyInteger",
"NumberZ",
"Orthogonal array",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property", "Number of copies in Z-direction")
obj.addProperty(
"App::PropertyInteger", "NumberZ", "Orthogonal array", _tip, locked=True
)
obj.NumberZ = 1
if "IntervalX" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"Distance and orientation "
"of intervals in X-direction")
obj.addProperty("App::PropertyVectorDistance",
"IntervalX",
"Orthogonal array",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property", "Distance and orientation " "of intervals in X-direction"
)
obj.addProperty(
"App::PropertyVectorDistance", "IntervalX", "Orthogonal array", _tip, locked=True
)
obj.IntervalX = App.Vector(50, 0, 0)
if "IntervalY" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"Distance and orientation "
"of intervals in Y-direction")
obj.addProperty("App::PropertyVectorDistance",
"IntervalY",
"Orthogonal array",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property", "Distance and orientation " "of intervals in Y-direction"
)
obj.addProperty(
"App::PropertyVectorDistance", "IntervalY", "Orthogonal array", _tip, locked=True
)
obj.IntervalY = App.Vector(0, 50, 0)
if "IntervalZ" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"Distance and orientation "
"of intervals in Z-direction")
obj.addProperty("App::PropertyVectorDistance",
"IntervalZ",
"Orthogonal array",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property", "Distance and orientation " "of intervals in Z-direction"
)
obj.addProperty(
"App::PropertyVectorDistance", "IntervalZ", "Orthogonal array", _tip, locked=True
)
obj.IntervalZ = App.Vector(0, 0, 50)
def set_polar_circular_properties(self, obj):
@@ -229,47 +204,47 @@ class Array(DraftLink):
properties = obj.PropertiesList
if "Axis" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"The axis direction around which "
"the elements in a polar or "
"a circular array will be created")
obj.addProperty("App::PropertyVector",
"Axis",
"Polar/circular array",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"The axis direction around which "
"the elements in a polar or "
"a circular array will be created",
)
obj.addProperty(
"App::PropertyVector", "Axis", "Polar/circular array", _tip, locked=True
)
obj.Axis = App.Vector(0, 0, 1)
if "Center" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"Center point for polar and "
"circular arrays.\n"
"The 'Axis' passes through this point.")
obj.addProperty("App::PropertyVectorDistance",
"Center",
"Polar/circular array",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"Center point for polar and "
"circular arrays.\n"
"The 'Axis' passes through this point.",
)
obj.addProperty(
"App::PropertyVectorDistance", "Center", "Polar/circular array", _tip, locked=True
)
obj.Center = App.Vector(0, 0, 0)
# The AxisReference property must be attached after Axis and Center
# so that onChanged works properly
if "AxisReference" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"The axis object that overrides "
"the value of 'Axis' and 'Center', "
"for example, a datum line.\n"
"Its placement, position and rotation, "
"will be used when creating polar "
"and circular arrays.\n"
"Leave this property empty "
"to be able to set 'Axis' and 'Center' "
"manually.")
obj.addProperty("App::PropertyLinkGlobal",
"AxisReference",
"Objects",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"The axis object that overrides "
"the value of 'Axis' and 'Center', "
"for example, a datum line.\n"
"Its placement, position and rotation, "
"will be used when creating polar "
"and circular arrays.\n"
"Leave this property empty "
"to be able to set 'Axis' and 'Center' "
"manually.",
)
obj.addProperty(
"App::PropertyLinkGlobal", "AxisReference", "Objects", _tip, locked=True
)
obj.AxisReference = None
def set_polar_properties(self, obj):
@@ -277,34 +252,22 @@ class Array(DraftLink):
properties = obj.PropertiesList
if "NumberPolar" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"Number of copies in the polar direction")
obj.addProperty("App::PropertyInteger",
"NumberPolar",
"Polar array",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property", "Number of copies in the polar direction")
obj.addProperty("App::PropertyInteger", "NumberPolar", "Polar array", _tip, locked=True)
obj.NumberPolar = 5
if "IntervalAxis" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"Distance and orientation "
"of intervals in 'Axis' direction")
obj.addProperty("App::PropertyVectorDistance",
"IntervalAxis",
"Polar array",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property", "Distance and orientation " "of intervals in 'Axis' direction"
)
obj.addProperty(
"App::PropertyVectorDistance", "IntervalAxis", "Polar array", _tip, locked=True
)
obj.IntervalAxis = App.Vector(0, 0, 0)
if "Angle" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"Angle to cover with copies")
obj.addProperty("App::PropertyAngle",
"Angle",
"Polar array",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property", "Angle to cover with copies")
obj.addProperty("App::PropertyAngle", "Angle", "Polar array", _tip, locked=True)
obj.Angle = 360
def set_circular_properties(self, obj):
@@ -312,47 +275,39 @@ class Array(DraftLink):
properties = obj.PropertiesList
if "RadialDistance" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"Distance between concentric circles")
obj.addProperty("App::PropertyDistance",
"RadialDistance",
"Circular array",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property", "Distance between concentric circles")
obj.addProperty(
"App::PropertyDistance", "RadialDistance", "Circular array", _tip, locked=True
)
obj.RadialDistance = 50
if "TangentialDistance" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"Distance between copies "
"in the same circle")
obj.addProperty("App::PropertyDistance",
"TangentialDistance",
"Circular array",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property", "Distance between copies " "in the same circle"
)
obj.addProperty(
"App::PropertyDistance", "TangentialDistance", "Circular array", _tip, locked=True
)
obj.TangentialDistance = 25
if "NumberCircles" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"Number of concentric circle. "
"The 'Base' object counts as one circle.")
obj.addProperty("App::PropertyInteger",
"NumberCircles",
"Circular array",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"Number of concentric circle. " "The 'Base' object counts as one circle.",
)
obj.addProperty(
"App::PropertyInteger", "NumberCircles", "Circular array", _tip, locked=True
)
obj.NumberCircles = 3
if "Symmetry" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"A parameter that determines "
"how many symmetry planes "
"the circular array will have")
obj.addProperty("App::PropertyInteger",
"Symmetry",
"Circular array",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"A parameter that determines "
"how many symmetry planes "
"the circular array will have",
)
obj.addProperty("App::PropertyInteger", "Symmetry", "Circular array", _tip, locked=True)
obj.Symmetry = 1
def set_link_properties(self, obj):
@@ -361,21 +316,17 @@ class Array(DraftLink):
if self.use_link:
if "ExpandArray" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"Show the individual array elements "
"(only for Link arrays)")
obj.addProperty("App::PropertyBool",
"ExpandArray",
"Objects",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property", "Show the individual array elements " "(only for Link arrays)"
)
obj.addProperty("App::PropertyBool", "ExpandArray", "Objects", _tip, locked=True)
obj.ExpandArray = False
def linkSetup(self, obj):
"""Set up the object as a link object."""
super(Array, self).linkSetup(obj)
obj.configLinkProperty(ElementCount='Count')
obj.setPropertyStatus('Count', 'Hidden')
obj.configLinkProperty(ElementCount="Count")
obj.setPropertyStatus("Count", "Hidden")
def onChanged(self, obj, prop):
"""Execute when a property is changed."""
@@ -395,42 +346,67 @@ class Array(DraftLink):
if prop == "ArrayType":
if obj.ArrayType == "ortho":
for pr in ("NumberX", "NumberY", "NumberZ",
"IntervalX", "IntervalY", "IntervalZ"):
for pr in ("NumberX", "NumberY", "NumberZ", "IntervalX", "IntervalY", "IntervalZ"):
obj.setPropertyStatus(pr, "-Hidden")
for pr in ("Axis", "Center", "NumberPolar", "Angle",
"IntervalAxis", "NumberCircles",
"RadialDistance", "TangentialDistance",
"Symmetry"):
for pr in (
"Axis",
"Center",
"NumberPolar",
"Angle",
"IntervalAxis",
"NumberCircles",
"RadialDistance",
"TangentialDistance",
"Symmetry",
):
obj.setPropertyStatus(pr, "Hidden")
if obj.ArrayType == "polar":
for pr in ("Axis", "Center", "NumberPolar",
"Angle", "IntervalAxis"):
for pr in ("Axis", "Center", "NumberPolar", "Angle", "IntervalAxis"):
obj.setPropertyStatus(pr, "-Hidden")
for pr in ("NumberX", "NumberY", "NumberZ",
"IntervalX", "IntervalY", "IntervalZ",
"NumberCircles", "RadialDistance",
"TangentialDistance", "Symmetry"):
for pr in (
"NumberX",
"NumberY",
"NumberZ",
"IntervalX",
"IntervalY",
"IntervalZ",
"NumberCircles",
"RadialDistance",
"TangentialDistance",
"Symmetry",
):
obj.setPropertyStatus(pr, "Hidden")
if obj.ArrayType == "circular":
for pr in ("Axis", "Center", "NumberCircles",
"RadialDistance", "TangentialDistance",
"Symmetry"):
for pr in (
"Axis",
"Center",
"NumberCircles",
"RadialDistance",
"TangentialDistance",
"Symmetry",
):
obj.setPropertyStatus(pr, "-Hidden")
for pr in ("NumberX", "NumberY", "NumberZ",
"IntervalX", "IntervalY", "IntervalZ",
"NumberPolar", "Angle", "IntervalAxis"):
for pr in (
"NumberX",
"NumberY",
"NumberZ",
"IntervalX",
"IntervalY",
"IntervalZ",
"NumberPolar",
"Angle",
"IntervalAxis",
):
obj.setPropertyStatus(pr, "Hidden")
def execute(self, obj):
"""Execute when the object is created or recomputed."""
if self.props_changed_placement_only(obj) \
or not obj.Base:
if self.props_changed_placement_only(obj) or not obj.Base:
self.props_changed_clear()
return
@@ -444,43 +420,49 @@ class Array(DraftLink):
axis = reference.Rotation * App.Vector(0, 0, 1)
center = reference.Base
else:
_info = ("'AxisReference' has no 'Placement' property. "
"Please select a different object to use as "
"reference.")
_info = (
"'AxisReference' has no 'Placement' property. "
"Please select a different object to use as "
"reference."
)
raise TypeError(_info)
if obj.ArrayType == "ortho":
pls = rect_placements(obj.Base.Placement,
obj.IntervalX,
obj.IntervalY,
obj.IntervalZ,
obj.NumberX,
obj.NumberY,
obj.NumberZ)
pls = rect_placements(
obj.Base.Placement,
obj.IntervalX,
obj.IntervalY,
obj.IntervalZ,
obj.NumberX,
obj.NumberY,
obj.NumberZ,
)
elif obj.ArrayType == "polar":
av = obj.IntervalAxis if hasattr(obj, "IntervalAxis") else None
pls = polar_placements(obj.Base.Placement,
center, obj.Angle.Value,
obj.NumberPolar, axis, av)
pls = polar_placements(
obj.Base.Placement, center, obj.Angle.Value, obj.NumberPolar, axis, av
)
elif obj.ArrayType == "circular":
pls = circ_placements(obj.Base.Placement,
obj.RadialDistance,
obj.TangentialDistance,
axis, center,
obj.NumberCircles, obj.Symmetry)
pls = circ_placements(
obj.Base.Placement,
obj.RadialDistance,
obj.TangentialDistance,
axis,
center,
obj.NumberCircles,
obj.Symmetry,
)
self.buildShape(obj, pl, pls)
self.props_changed_clear()
return (not self.use_link)
return not self.use_link
# Alias for compatibility with v0.18 and earlier
_Array = Array
def rect_placements(base_placement,
xvector, yvector, zvector,
xnum, ynum, znum):
def rect_placements(base_placement, xvector, yvector, zvector, xnum, ynum, znum):
"""Determine the placements where the rectangular copies will be."""
pl = base_placement
placements = [pl.copy()]
@@ -513,9 +495,7 @@ def rect_placements(base_placement,
return placements
def polar_placements(base_placement,
center, angle,
number, axis, axisvector):
def polar_placements(base_placement, center, angle, number, axis, axisvector):
"""Determine the placements where the polar copies will be."""
# print("angle ",angle," num ",num)
placements = [base_placement.copy()]
@@ -540,10 +520,9 @@ def polar_placements(base_placement,
return placements
def circ_placements(base_placement,
r_distance, tan_distance,
axis, center,
circle_number, symmetry):
def circ_placements(
base_placement, r_distance, tan_distance, axis, center, circle_number, symmetry
):
"""Determine the placements where the circular copies will be."""
symmetry = max(1, symmetry)
lead = (0, 1, 0)
@@ -572,4 +551,5 @@ def circ_placements(base_placement,
return placements
## @}

View File

@@ -79,7 +79,7 @@ class DraftObject(object):
obj.Proxy = self
self.Type = tp
def onDocumentRestored(self,obj):
def onDocumentRestored(self, obj):
# Object properties are updated when the document is opened.
self.props_changed_clear()

View File

@@ -41,39 +41,32 @@ class BezCurve(DraftObject):
def __init__(self, obj):
super().__init__(obj, "BezCurve")
_tip = QT_TRANSLATE_NOOP("App::Property",
"The points of the Bezier curve")
_tip = QT_TRANSLATE_NOOP("App::Property", "The points of the Bezier curve")
obj.addProperty("App::PropertyVectorList", "Points", "Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property",
"The degree of the Bezier function")
_tip = QT_TRANSLATE_NOOP("App::Property", "The degree of the Bezier function")
obj.addProperty("App::PropertyInteger", "Degree", "Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property",
"Continuity")
_tip = QT_TRANSLATE_NOOP("App::Property", "Continuity")
obj.addProperty("App::PropertyIntegerList", "Continuity", "Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property",
"If the Bezier curve should be closed or not")
_tip = QT_TRANSLATE_NOOP("App::Property", "If the Bezier curve should be closed or not")
obj.addProperty("App::PropertyBool", "Closed", "Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property",
"Create a face if this curve is closed")
_tip = QT_TRANSLATE_NOOP("App::Property", "Create a face if this curve is closed")
obj.addProperty("App::PropertyBool", "MakeFace", "Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property",
"The length of this object")
_tip = QT_TRANSLATE_NOOP("App::Property", "The length of this object")
obj.addProperty("App::PropertyLength", "Length", "Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property",
"The area of this object")
_tip = QT_TRANSLATE_NOOP("App::Property", "The area of this object")
obj.addProperty("App::PropertyArea", "Area", "Draft", _tip, locked=True)
obj.MakeFace = params.get_param("MakeFaceMode")
obj.Closed = False
obj.Degree = 3
obj.Continuity = []
#obj.setEditorMode("Degree", 2)
# obj.setEditorMode("Degree", 2)
obj.setEditorMode("Continuity", 1)
def onDocumentRestored(self, obj):
@@ -92,67 +85,69 @@ class BezCurve(DraftObject):
fp.positionBySupport()
self.props_changed_clear()
def _segpoleslst(self,fp):
def _segpoleslst(self, fp):
"""Split the points into segments."""
if not fp.Closed and len(fp.Points) >= 2: #allow lower degree segment
poles=fp.Points[1:]
elif fp.Closed and len(fp.Points) >= fp.Degree: #drawable
#poles=fp.Points[1:(fp.Degree*(len(fp.Points)//fp.Degree))]+fp.Points[0:1]
poles=fp.Points[1:]+fp.Points[0:1]
if not fp.Closed and len(fp.Points) >= 2: # allow lower degree segment
poles = fp.Points[1:]
elif fp.Closed and len(fp.Points) >= fp.Degree: # drawable
# poles=fp.Points[1:(fp.Degree*(len(fp.Points)//fp.Degree))]+fp.Points[0:1]
poles = fp.Points[1:] + fp.Points[0:1]
else:
poles=[]
return [poles[x:x+fp.Degree] for x in \
range(0, len(poles), (fp.Degree or 1))]
poles = []
return [poles[x : x + fp.Degree] for x in range(0, len(poles), (fp.Degree or 1))]
def resetcontinuity(self,fp):
fp.Continuity = [0]*(len(self._segpoleslst(fp))-1+1*fp.Closed)
#nump= len(fp.Points)-1+fp.Closed*1
#numsegments = (nump // fp.Degree) + 1 * (nump % fp.Degree > 0) -1
#fp.Continuity = [0]*numsegments
def resetcontinuity(self, fp):
fp.Continuity = [0] * (len(self._segpoleslst(fp)) - 1 + 1 * fp.Closed)
# nump= len(fp.Points)-1+fp.Closed*1
# numsegments = (nump // fp.Degree) + 1 * (nump % fp.Degree > 0) -1
# fp.Continuity = [0]*numsegments
def onChanged(self, fp, prop):
self.props_changed_store(prop)
if prop == 'Closed':
if prop == "Closed":
# if remove the last entry when curve gets opened
oldlen = len(fp.Continuity)
newlen = (len(self._segpoleslst(fp))-1+1*fp.Closed)
newlen = len(self._segpoleslst(fp)) - 1 + 1 * fp.Closed
if oldlen > newlen:
fp.Continuity = fp.Continuity[:newlen]
if oldlen < newlen:
fp.Continuity = fp.Continuity + [0]*(newlen-oldlen)
fp.Continuity = fp.Continuity + [0] * (newlen - oldlen)
if (hasattr(fp,'Closed') and
fp.Closed and
prop in ['Points','Degree','Closed'] and
len(fp.Points) % fp.Degree):
if (
hasattr(fp, "Closed")
and fp.Closed
and prop in ["Points", "Degree", "Closed"]
and len(fp.Points) % fp.Degree
):
# the curve editing tools can't handle extra points
fp.Points=fp.Points[:(fp.Degree*(len(fp.Points)//fp.Degree))]
#for closed curves
fp.Points = fp.Points[: (fp.Degree * (len(fp.Points) // fp.Degree))]
# for closed curves
if prop in ["Degree"] and fp.Degree >= 1:
self.resetcontinuity(fp)
if prop in ["Points","Degree","Continuity","Closed"]:
if prop in ["Points", "Degree", "Continuity", "Closed"]:
self.createGeometry(fp)
def createGeometry(self,fp):
def createGeometry(self, fp):
import Part
plm = fp.Placement
if fp.Points:
startpoint = fp.Points[0]
edges = []
for segpoles in self._segpoleslst(fp):
# if len(segpoles) == fp.Degree # would skip additional poles
c = Part.BezierCurve() #last segment may have lower degree
# if len(segpoles) == fp.Degree # would skip additional poles
c = Part.BezierCurve() # last segment may have lower degree
c.increase(len(segpoles))
c.setPoles([startpoint]+segpoles)
c.setPoles([startpoint] + segpoles)
edges.append(Part.Edge(c))
startpoint = segpoles[-1]
w = Part.Wire(edges)
if fp.Closed and w.isClosed():
try:
if hasattr(fp,"MakeFace"):
if hasattr(fp, "MakeFace"):
if fp.MakeFace:
w = Part.Face(w)
else:
@@ -160,31 +155,31 @@ class BezCurve(DraftObject):
except Part.OCCError:
pass
fp.Shape = w
if hasattr(fp,"Area") and hasattr(w,"Area"):
if hasattr(fp, "Area") and hasattr(w, "Area"):
fp.Area = w.Area
if hasattr(fp,"Length") and hasattr(w,"Length"):
if hasattr(fp, "Length") and hasattr(w, "Length"):
fp.Length = w.Length
fp.Placement = plm
@classmethod
def symmetricpoles(cls,knot, p1, p2):
def symmetricpoles(cls, knot, p1, p2):
"""Make two poles symmetric respective to the knot."""
p1h = App.Vector(p1)
p2h = App.Vector(p2)
p1h.multiply(0.5)
p2h.multiply(0.5)
return ( knot+p1h-p2h , knot+p2h-p1h )
return (knot + p1h - p2h, knot + p2h - p1h)
@classmethod
def tangentpoles(cls,knot, p1, p2,allowsameside=False):
def tangentpoles(cls, knot, p1, p2, allowsameside=False):
"""Make two poles have the same tangent at knot."""
p12n = p2.sub(p1)
p12n.normalize()
p1k = knot-p1
p2k = knot-p2
p1k_= App.Vector(p12n)
kon12=(p1k * p12n)
if allowsameside or not (kon12 < 0 or p2k * p12n > 0):# instead of moving
p1k = knot - p1
p2k = knot - p2
p1k_ = App.Vector(p12n)
kon12 = p1k * p12n
if allowsameside or not (kon12 < 0 or p2k * p12n > 0): # instead of moving
p1k_.multiply(kon12)
pk_k = knot - p1 - p1k_
return (p1 + pk_k, p2 + pk_k)
@@ -192,13 +187,13 @@ class BezCurve(DraftObject):
return cls.symmetricpoles(knot, p1, p2)
@staticmethod
def modifysymmetricpole(knot,p1):
def modifysymmetricpole(knot, p1):
"""calculate the coordinates of the opposite pole
of a symmetric knot"""
return knot + knot - p1
@staticmethod
def modifytangentpole(knot,p1,oldp2):
def modifytangentpole(knot, p1, oldp2):
"""calculate the coordinates of the opposite pole
of a tangent knot"""
pn = knot - p1

View File

@@ -39,9 +39,8 @@ class Block(DraftObject):
def __init__(self, obj):
super().__init__(obj, "Block")
_tip = QT_TRANSLATE_NOOP("App::Property",
"The components of this block")
obj.addProperty("App::PropertyLinkList","Components", "Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property", "The components of this block")
obj.addProperty("App::PropertyLinkList", "Components", "Draft", _tip, locked=True)
def onDocumentRestored(self, obj):
super().onDocumentRestored(obj)
@@ -56,6 +55,7 @@ class Block(DraftObject):
return
import Part
plm = obj.Placement
shps = []
for c in obj.Components:

View File

@@ -41,20 +41,17 @@ class BSpline(DraftObject):
def __init__(self, obj):
super().__init__(obj, "BSpline")
_tip = QT_TRANSLATE_NOOP("App::Property",
"The points of the B-spline")
obj.addProperty("App::PropertyVectorList","Points", "Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property", "The points of the B-spline")
obj.addProperty("App::PropertyVectorList", "Points", "Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property",
"If the B-spline is closed or not")
obj.addProperty("App::PropertyBool","Closed", "Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property", "If the B-spline is closed or not")
obj.addProperty("App::PropertyBool", "Closed", "Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property",
"Create a face if this B-spline is closed")
obj.addProperty("App::PropertyBool","MakeFace", "Draft",_tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property", "Create a face if this B-spline is closed")
obj.addProperty("App::PropertyBool", "MakeFace", "Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property", "The area of this object")
obj.addProperty("App::PropertyArea","Area", "Draft", _tip, locked=True)
obj.addProperty("App::PropertyArea", "Area", "Draft", _tip, locked=True)
obj.MakeFace = params.get_param("MakeFaceMode")
obj.Closed = False
@@ -63,28 +60,26 @@ class BSpline(DraftObject):
def onDocumentRestored(self, obj):
super().onDocumentRestored(obj)
gui_utils.restore_view_object(
obj, vp_module="view_bspline", vp_class="ViewProviderBSpline"
)
gui_utils.restore_view_object(obj, vp_module="view_bspline", vp_class="ViewProviderBSpline")
def assureProperties(self, obj): # for Compatibility with older versions
def assureProperties(self, obj): # for Compatibility with older versions
if not hasattr(obj, "Parameterization"):
_tip = QT_TRANSLATE_NOOP("App::Property","Parameterization factor")
_tip = QT_TRANSLATE_NOOP("App::Property", "Parameterization factor")
obj.addProperty("App::PropertyFloat", "Parameterization", "Draft", _tip, locked=True)
obj.Parameterization = 1.0
self.knotSeq = []
def parameterization (self, pts, a, closed):
def parameterization(self, pts, a, closed):
"""Computes a knot Sequence for a set of points.
fac (0-1) : parameterization factor
fac = 0 -> Uniform / fac=0.5 -> Centripetal / fac=1.0 -> Chord-Length
"""
if closed: # we need to add the first point as the end point
if closed: # we need to add the first point as the end point
pts.append(pts[0])
params = [0]
for i in range(1,len(pts)):
p = pts[i].sub(pts[i-1])
pl = pow(p.Length,a)
for i in range(1, len(pts)):
p = pts[i].sub(pts[i - 1])
pl = pow(p.Length, a)
params.append(params[-1] + pl)
return params
@@ -92,14 +87,13 @@ class BSpline(DraftObject):
self.props_changed_store(prop)
if prop == "Parameterization":
if fp.Parameterization < 0.:
fp.Parameterization = 0.
if fp.Parameterization < 0.0:
fp.Parameterization = 0.0
if fp.Parameterization > 1.0:
fp.Parameterization = 1.0
def execute(self, obj):
if self.props_changed_placement_only() \
or not obj.Points:
if self.props_changed_placement_only() or not obj.Points:
obj.positionBySupport()
self.props_changed_clear()
return
@@ -112,18 +106,21 @@ class BSpline(DraftObject):
plm = obj.Placement
if obj.Closed and (len(obj.Points) > 2):
if obj.Points[0] == obj.Points[-1]: # should not occur, but OCC will crash
_err = QT_TRANSLATE_NOOP('Draft', "_BSpline.createGeometry: "
"Closed with same first/last Point. Geometry not updated.")
App.Console.PrintError(_err+"\n")
_err = QT_TRANSLATE_NOOP(
"Draft",
"_BSpline.createGeometry: "
"Closed with same first/last Point. Geometry not updated.",
)
App.Console.PrintError(_err + "\n")
return
spline = Part.BSplineCurve()
spline.interpolate(obj.Points, PeriodicFlag = True, Parameters = self.knotSeq)
spline.interpolate(obj.Points, PeriodicFlag=True, Parameters=self.knotSeq)
# DNC: bug fix: convert to face if closed
shape = Part.Wire(spline.toShape())
# Creating a face from a closed spline cannot be expected to always work
# Usually, if the spline is not flat the call of Part.Face() fails
try:
if hasattr(obj,"MakeFace"):
if hasattr(obj, "MakeFace"):
if obj.MakeFace:
shape = Part.Face(shape)
else:
@@ -131,14 +128,14 @@ class BSpline(DraftObject):
except Part.OCCError:
pass
obj.Shape = shape
if hasattr(obj,"Area") and hasattr(shape,"Area"):
if hasattr(obj, "Area") and hasattr(shape, "Area"):
obj.Area = shape.Area
else:
spline = Part.BSplineCurve()
spline.interpolate(obj.Points, PeriodicFlag = False, Parameters = self.knotSeq)
spline.interpolate(obj.Points, PeriodicFlag=False, Parameters=self.knotSeq)
shape = spline.toShape()
obj.Shape = shape
if hasattr(obj,"Area") and hasattr(shape,"Area"):
if hasattr(obj, "Area") and hasattr(shape, "Area"):
obj.Area = shape.Area
obj.Placement = plm
obj.positionBySupport()

View File

@@ -42,25 +42,23 @@ class Circle(DraftObject):
super().__init__(obj, "Circle")
_tip = QT_TRANSLATE_NOOP("App::Property", "Start angle of the arc")
obj.addProperty("App::PropertyAngle", "FirstAngle",
"Draft", _tip, locked=True)
obj.addProperty("App::PropertyAngle", "FirstAngle", "Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property", "End angle of the arc (for a full circle, \
give it same value as First Angle)")
obj.addProperty("App::PropertyAngle","LastAngle",
"Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"End angle of the arc (for a full circle, \
give it same value as First Angle)",
)
obj.addProperty("App::PropertyAngle", "LastAngle", "Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property", "Radius of the circle")
obj.addProperty("App::PropertyLength", "Radius",
"Draft", _tip, locked=True)
obj.addProperty("App::PropertyLength", "Radius", "Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property", "Create a face")
obj.addProperty("App::PropertyBool", "MakeFace",
"Draft", _tip, locked=True)
obj.addProperty("App::PropertyBool", "MakeFace", "Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property", "The area of this object")
obj.addProperty("App::PropertyArea", "Area",
"Draft", _tip, locked=True)
obj.addProperty("App::PropertyArea", "Area", "Draft", _tip, locked=True)
obj.MakeFace = params.get_param("MakeFaceMode")
@@ -79,20 +77,22 @@ class Circle(DraftObject):
plm = obj.Placement
shape = Part.makeCircle(obj.Radius.Value,
App.Vector(0,0,0),
App.Vector(0,0,1),
obj.FirstAngle.Value,
obj.LastAngle.Value)
shape = Part.makeCircle(
obj.Radius.Value,
App.Vector(0, 0, 0),
App.Vector(0, 0, 1),
obj.FirstAngle.Value,
obj.LastAngle.Value,
)
if obj.FirstAngle.Value == obj.LastAngle.Value:
shape = Part.Wire(shape)
if getattr(obj,"MakeFace",True):
if getattr(obj, "MakeFace", True):
shape = Part.Face(shape)
obj.Shape = shape
if hasattr(obj,"Area") and hasattr(shape,"Area"):
if hasattr(obj, "Area") and hasattr(shape, "Area"):
obj.Area = shape.Area
obj.Placement = plm

View File

@@ -43,7 +43,6 @@ class Clone(DraftObject):
self.set_properties(obj)
super().__init__(obj, "Clone")
def set_properties(self, obj):
pl = obj.PropertiesList
if not "Objects" in pl:
@@ -54,9 +53,10 @@ class Clone(DraftObject):
obj.addProperty("App::PropertyVector", "Scale", "Draft", _tip, locked=True)
obj.Scale = App.Vector(1, 1, 1)
if not "Fuse" in pl:
_tip = QT_TRANSLATE_NOOP("App::Property",
"If Clones includes several objects,\n"
"set True for fusion or False for compound")
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"If Clones includes several objects,\n" "set True for fusion or False for compound",
)
obj.addProperty("App::PropertyBool", "Fuse", "Draft", _tip, locked=True)
if not "ForceCompound" in pl:
_tip = QT_TRANSLATE_NOOP("App::Property", "Always create a compound")
@@ -88,6 +88,7 @@ class Clone(DraftObject):
tmps += s.Edges
shapes = tmps
import Part
if len(shapes) == 1:
if force_compound:
return Part.makeCompound([shapes[0]])
@@ -106,21 +107,24 @@ class Clone(DraftObject):
return sh
return Part.makeCompound(shapes)
def execute(self,obj):
def execute(self, obj):
if self.props_changed_placement_only(obj):
if hasattr(obj,"positionBySupport"):
if hasattr(obj, "positionBySupport"):
obj.positionBySupport()
self.props_changed_clear()
return
import Part
pl = obj.Placement
shapes = []
if obj.isDerivedFrom("Part::Part2DObject"):
# if our clone is 2D, make sure all its linked geometry is 2D too
for o in obj.Objects:
if not o.getLinkedObject(True).isDerivedFrom("Part::Part2DObject"):
App.Console.PrintWarning("Warning 2D Clone "+obj.Name+" contains 3D geometry")
App.Console.PrintWarning(
"Warning 2D Clone " + obj.Name + " contains 3D geometry"
)
return
for o in obj.Objects:
sh = Part.getShape(o)
@@ -129,7 +133,7 @@ class Clone(DraftObject):
if shapes:
sh = self.join(obj, shapes)
m = App.Matrix()
if hasattr(obj,"Scale") and not sh.isNull():
if hasattr(obj, "Scale") and not sh.isNull():
if not DraftVecUtils.equals(obj.Scale, App.Vector(1, 1, 1)):
op = sh.Placement
sh.Placement = App.Placement()
@@ -139,17 +143,17 @@ class Clone(DraftObject):
obj.Shape = sh
obj.Placement = pl
if hasattr(obj,"positionBySupport"):
if hasattr(obj, "positionBySupport"):
obj.positionBySupport()
self.props_changed_clear()
def onChanged(self, obj, prop):
self.props_changed_store(prop)
def getSubVolume(self,obj,placement=None):
def getSubVolume(self, obj, placement=None):
# this allows clones of arch windows to return a subvolume too
if obj.Objects:
if hasattr(obj.Objects[0],"Proxy"):
if hasattr(obj.Objects[0], "Proxy"):
if hasattr(obj.Objects[0].Proxy, "getSubVolume"):
if not placement:
# clones must displace the original subvolume too

View File

@@ -1,4 +1,4 @@
#
#
# ***************************************************************************
# * Copyright (c) 2009, 2010 Yorik van Havre <yorik@uncreated.net> *
# * Copyright (c) 2009, 2010 Ken Cline <cline@frii.com> *
@@ -128,69 +128,60 @@ class DimensionBase(DraftAnnotation):
properties = obj.PropertiesList
if "Normal" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"The normal direction of the text "
"of the dimension")
obj.addProperty("App::PropertyVector",
"Normal",
"Dimension",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property", "The normal direction of the text " "of the dimension"
)
obj.addProperty("App::PropertyVector", "Normal", "Dimension", _tip, locked=True)
obj.Normal = App.Vector(0, 0, 1)
# TODO: remove Support property as it is not used at all.
# It is just set at creation time by the make_dimension function
# but it is not used.
if "Support" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"The object measured by this dimension")
obj.addProperty("App::PropertyLink",
"Support",
"Dimension",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property", "The object measured by this dimension")
obj.addProperty("App::PropertyLink", "Support", "Dimension", _tip, locked=True)
obj.Support = None
if "LinkedGeometry" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"The object, and specific subelements "
"of it,\n"
"that this dimension "
"is measuring.\n"
"\n"
"There are various possibilities:\n"
"- An object, and one of its edges.\n"
"- An object, and two of its vertices.\n"
"- An arc object, and its edge.")
obj.addProperty("App::PropertyLinkSubList",
"LinkedGeometry",
"Dimension",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"The object, and specific subelements "
"of it,\n"
"that this dimension "
"is measuring.\n"
"\n"
"There are various possibilities:\n"
"- An object, and one of its edges.\n"
"- An object, and two of its vertices.\n"
"- An arc object, and its edge.",
)
obj.addProperty(
"App::PropertyLinkSubList", "LinkedGeometry", "Dimension", _tip, locked=True
)
obj.LinkedGeometry = []
if "Dimline" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"A point through which the dimension "
"line, or an extrapolation of it, "
"will pass.\n"
"\n"
"- For linear dimensions, this property "
"controls how close the dimension line\n"
"is to the measured object.\n"
"- For radial dimensions, this controls "
"the direction of the dimension line\n"
"that displays the measured radius or "
"diameter.\n"
"- For angular dimensions, "
"this controls the radius of the "
"dimension arc\n"
"that displays the measured angle.")
obj.addProperty("App::PropertyVectorDistance",
"Dimline",
"Dimension",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"A point through which the dimension "
"line, or an extrapolation of it, "
"will pass.\n"
"\n"
"- For linear dimensions, this property "
"controls how close the dimension line\n"
"is to the measured object.\n"
"- For radial dimensions, this controls "
"the direction of the dimension line\n"
"that displays the measured radius or "
"diameter.\n"
"- For angular dimensions, "
"this controls the radius of the "
"dimension arc\n"
"that displays the measured angle.",
)
obj.addProperty(
"App::PropertyVectorDistance", "Dimline", "Dimension", _tip, locked=True
)
obj.Dimline = App.Vector(0, 1, 0)
def update_properties_0v21(self, obj, vobj):
@@ -223,77 +214,75 @@ class LinearDimension(DimensionBase):
properties = obj.PropertiesList
if "Start" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"Starting point of the dimension line.\n"
"\n"
"If it is a radius dimension it will be "
"the center of the arc.\n"
"If it is a diameter dimension "
"it will be a point that lies "
"on the arc.")
obj.addProperty("App::PropertyVectorDistance",
"Start",
"Linear/radial dimension",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"Starting point of the dimension line.\n"
"\n"
"If it is a radius dimension it will be "
"the center of the arc.\n"
"If it is a diameter dimension "
"it will be a point that lies "
"on the arc.",
)
obj.addProperty(
"App::PropertyVectorDistance", "Start", "Linear/radial dimension", _tip, locked=True
)
obj.Start = App.Vector(0, 0, 0)
if "End" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"Ending point of the dimension line.\n"
"\n"
"If it is a radius or diameter "
"dimension\n"
"it will be a point that lies "
"on the arc.")
obj.addProperty("App::PropertyVectorDistance",
"End",
"Linear/radial dimension",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"Ending point of the dimension line.\n"
"\n"
"If it is a radius or diameter "
"dimension\n"
"it will be a point that lies "
"on the arc.",
)
obj.addProperty(
"App::PropertyVectorDistance", "End", "Linear/radial dimension", _tip, locked=True
)
obj.End = App.Vector(1, 0, 0)
if "Direction" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"The direction of the dimension line.\n"
"If this remains '(0,0,0)', "
"the direction will be calculated "
"automatically.")
obj.addProperty("App::PropertyVector",
"Direction",
"Linear/radial dimension",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"The direction of the dimension line.\n"
"If this remains '(0,0,0)', "
"the direction will be calculated "
"automatically.",
)
obj.addProperty(
"App::PropertyVector", "Direction", "Linear/radial dimension", _tip, locked=True
)
if "Distance" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"The value of the measurement.\n"
"\n"
"This property is read-only because "
"the value is calculated\n"
"from the 'Start' and 'End' properties.\n"
"\n"
"If the 'Linked Geometry' "
"is an arc or circle, this 'Distance'\n"
"is the radius or diameter, depending "
"on the 'Diameter' property.")
obj.addProperty("App::PropertyLength",
"Distance",
"Linear/radial dimension",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"The value of the measurement.\n"
"\n"
"This property is read-only because "
"the value is calculated\n"
"from the 'Start' and 'End' properties.\n"
"\n"
"If the 'Linked Geometry' "
"is an arc or circle, this 'Distance'\n"
"is the radius or diameter, depending "
"on the 'Diameter' property.",
)
obj.addProperty(
"App::PropertyLength", "Distance", "Linear/radial dimension", _tip, locked=True
)
obj.Distance = 0
if "Diameter" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"When measuring circular arcs, "
"it determines whether to display\n"
"the radius or the diameter value")
obj.addProperty("App::PropertyBool",
"Diameter",
"Radial dimension",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"When measuring circular arcs, "
"it determines whether to display\n"
"the radius or the diameter value",
)
obj.addProperty("App::PropertyBool", "Diameter", "Radial dimension", _tip, locked=True)
obj.Diameter = False
def onDocumentRestored(self, obj):
@@ -320,12 +309,12 @@ class LinearDimension(DimensionBase):
as they aren't used.
"""
if hasattr(obj, "Distance"):
obj.setPropertyStatus('Distance', 'ReadOnly')
obj.setPropertyStatus("Distance", "ReadOnly")
# if hasattr(obj, "Normal"):
# obj.setPropertyStatus('Normal', 'Hidden')
if hasattr(obj, "Support"):
obj.setPropertyStatus('Support', 'Hidden')
obj.setPropertyStatus("Support", "Hidden")
def transform(self, obj, pla):
"""Transform the object by applying a placement."""
@@ -353,24 +342,20 @@ class LinearDimension(DimensionBase):
# If it has one subelement, we assume an edge
# that can be a straight line, or a circular edge
subelement = sub_list[0]
(obj.Start,
obj.End) = measure_one_obj_edge(linked_obj,
subelement,
obj.Dimline,
obj.Diameter)
(obj.Start, obj.End) = measure_one_obj_edge(
linked_obj, subelement, obj.Dimline, obj.Diameter
)
elif len(sub_list) == 2:
# If it has two subelements, we assume a straight edge
# that is measured by two vertices
(obj.Start,
obj.End) = measure_one_obj_vertices(linked_obj,
sub_list)
(obj.Start, obj.End) = measure_one_obj_vertices(linked_obj, sub_list)
elif len(obj.LinkedGeometry) == 2:
# If the list has two objects, it measures the distance
# between the two vertices in those two objects
(obj.Start,
obj.End) = measure_two_objects(obj.LinkedGeometry[0],
obj.LinkedGeometry[1])
(obj.Start, obj.End) = measure_two_objects(
obj.LinkedGeometry[0], obj.LinkedGeometry[1]
)
# Update the distance property by comparing the floats
# with the precision
@@ -521,58 +506,56 @@ class AngularDimension(DimensionBase):
properties = obj.PropertiesList
if "FirstAngle" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"Starting angle of the dimension line "
"(circular arc).\n"
"The arc is drawn counter-clockwise.")
obj.addProperty("App::PropertyAngle",
"FirstAngle",
"Angular dimension",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"Starting angle of the dimension line "
"(circular arc).\n"
"The arc is drawn counter-clockwise.",
)
obj.addProperty(
"App::PropertyAngle", "FirstAngle", "Angular dimension", _tip, locked=True
)
obj.FirstAngle = 0
if "LastAngle" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"Ending angle of the dimension line "
"(circular arc).\n"
"The arc is drawn counter-clockwise.")
obj.addProperty("App::PropertyAngle",
"LastAngle",
"Angular dimension",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"Ending angle of the dimension line "
"(circular arc).\n"
"The arc is drawn counter-clockwise.",
)
obj.addProperty(
"App::PropertyAngle", "LastAngle", "Angular dimension", _tip, locked=True
)
obj.LastAngle = 90
if "Center" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"The center point of the dimension "
"line, which is a circular arc.\n"
"\n"
"This is normally the point where two "
"line segments, or their extensions\n"
"intersect, resulting in the "
"measured 'Angle' between them.")
obj.addProperty("App::PropertyVectorDistance",
"Center",
"Angular dimension",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"The center point of the dimension "
"line, which is a circular arc.\n"
"\n"
"This is normally the point where two "
"line segments, or their extensions\n"
"intersect, resulting in the "
"measured 'Angle' between them.",
)
obj.addProperty(
"App::PropertyVectorDistance", "Center", "Angular dimension", _tip, locked=True
)
obj.Center = App.Vector(0, 0, 0)
if "Angle" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"The value of the measurement.\n"
"\n"
"This property is read-only because "
"the value is calculated from\n"
"the 'First Angle' and "
"'Last Angle' properties.")
obj.addProperty("App::PropertyAngle",
"Angle",
"Angular dimension",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"The value of the measurement.\n"
"\n"
"This property is read-only because "
"the value is calculated from\n"
"the 'First Angle' and "
"'Last Angle' properties.",
)
obj.addProperty("App::PropertyAngle", "Angle", "Angular dimension", _tip, locked=True)
obj.Angle = 0
def onDocumentRestored(self, obj):
@@ -644,14 +627,14 @@ class AngularDimension(DimensionBase):
as they aren't used.
"""
if hasattr(obj, "Angle"):
obj.setPropertyStatus('Angle', 'ReadOnly')
obj.setPropertyStatus("Angle", "ReadOnly")
if hasattr(obj, "Normal"):
obj.setPropertyStatus('Normal', 'Hidden')
obj.setPropertyStatus("Normal", "Hidden")
if hasattr(obj, "Support"):
obj.setPropertyStatus('Support', 'Hidden')
obj.setPropertyStatus("Support", "Hidden")
if hasattr(obj, "LinkedGeometry"):
obj.setPropertyStatus('LinkedGeometry', 'Hidden')
obj.setPropertyStatus("LinkedGeometry", "Hidden")
def measure_two_obj_angles(link_sub_1, link_sub_2):

View File

@@ -92,9 +92,7 @@ class DraftAnnotation(object):
typ = obj.Proxy.Type
if typ == "Label":
vobj.ArrowTypeStart = vobj.ArrowType
elif typ == "AngularDimension" \
or obj.Diameter \
or not vobj.Proxy.is_linked_to_circle():
elif typ == "AngularDimension" or obj.Diameter or not vobj.Proxy.is_linked_to_circle():
vobj.ArrowTypeStart = vobj.ArrowType
vobj.ArrowTypeEnd = vobj.ArrowType
else: # Radial dimension
@@ -115,7 +113,7 @@ class DraftAnnotation(object):
return
def loads(self,state):
def loads(self, state):
return

View File

@@ -80,7 +80,7 @@ class DraftLink(DraftObject):
def attach(self, obj):
"""Set up the properties when the object is attached."""
if self.use_link:
obj.addExtension('App::LinkExtensionPython')
obj.addExtension("App::LinkExtensionPython")
self.linkSetup(obj)
def canLinkProperties(self, _obj):
@@ -92,68 +92,55 @@ class DraftLink(DraftObject):
def linkSetup(self, obj):
"""Set up the link properties on attachment."""
obj.configLinkProperty('Placement', LinkedObject='Base')
obj.configLinkProperty("Placement", LinkedObject="Base")
if not hasattr(obj, 'AlwaysSyncPlacement'):
_tip = QT_TRANSLATE_NOOP("App::Property",
'Force sync pattern placements even when array elements are expanded')
obj.addProperty("App::PropertyBool",
"AlwaysSyncPlacement",
"Draft",
_tip,
locked=True)
if not hasattr(obj, "AlwaysSyncPlacement"):
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"Force sync pattern placements even when array elements are expanded",
)
obj.addProperty("App::PropertyBool", "AlwaysSyncPlacement", "Draft", _tip, locked=True)
if hasattr(obj, 'ShowElement'):
if hasattr(obj, "ShowElement"):
# Rename 'ShowElement' property to 'ExpandArray' to avoid conflict
# with native App::Link
obj.configLinkProperty('ShowElement')
obj.configLinkProperty("ShowElement")
showElement = obj.ShowElement
_tip = QT_TRANSLATE_NOOP("App::Property",
"Show the individual array elements")
obj.addProperty("App::PropertyBool",
"ExpandArray",
"Draft",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property", "Show the individual array elements")
obj.addProperty("App::PropertyBool", "ExpandArray", "Draft", _tip, locked=True)
obj.ExpandArray = showElement
obj.configLinkProperty(ShowElement='ExpandArray')
obj.removeProperty('ShowElement')
obj.configLinkProperty(ShowElement="ExpandArray")
obj.removeProperty("ShowElement")
else:
obj.configLinkProperty(ShowElement='ExpandArray')
obj.configLinkProperty(ShowElement="ExpandArray")
if getattr(obj, 'ExpandArray', False):
obj.setPropertyStatus('PlacementList', 'Immutable')
if getattr(obj, "ExpandArray", False):
obj.setPropertyStatus("PlacementList", "Immutable")
else:
obj.setPropertyStatus('PlacementList', '-Immutable')
obj.setPropertyStatus("PlacementList", "-Immutable")
if not hasattr(obj, 'LinkTransform'):
obj.addProperty('App::PropertyBool',
'LinkTransform',
' Link',
locked=True)
if not hasattr(obj, "LinkTransform"):
obj.addProperty("App::PropertyBool", "LinkTransform", " Link", locked=True)
if not hasattr(obj, 'ColoredElements'):
obj.addProperty('App::PropertyLinkSubHidden',
'ColoredElements',
' Link',
locked=True)
obj.setPropertyStatus('ColoredElements', 'Hidden')
if not hasattr(obj, "ColoredElements"):
obj.addProperty("App::PropertyLinkSubHidden", "ColoredElements", " Link", locked=True)
obj.setPropertyStatus("ColoredElements", "Hidden")
if not hasattr(obj,'LinkCopyOnChange'):
obj.addProperty("App::PropertyEnumeration","LinkCopyOnChange"," Link",locked=True)
if not hasattr(obj, "LinkCopyOnChange"):
obj.addProperty("App::PropertyEnumeration", "LinkCopyOnChange", " Link", locked=True)
obj.configLinkProperty('LinkCopyOnChange','LinkTransform','ColoredElements')
obj.configLinkProperty("LinkCopyOnChange", "LinkTransform", "ColoredElements")
if not getattr(obj, 'Fuse', False):
obj.setPropertyStatus('Shape', 'Transient')
if not getattr(obj, "Fuse", False):
obj.setPropertyStatus("Shape", "Transient")
def getViewProviderName(self, _obj):
"""Override the view provider name."""
if self.use_link:
return 'Gui::ViewProviderLinkPython'
return ''
return "Gui::ViewProviderLinkPython"
return ""
def migrate_attributes(self, obj):
"""Migrate old attribute names to new names if they exist.
@@ -177,10 +164,10 @@ class DraftLink(DraftObject):
if self.use_link:
self.linkSetup(obj)
else:
obj.setPropertyStatus('Shape', '-Transient')
obj.setPropertyStatus("Shape", "-Transient")
if obj.Shape.isNull():
if getattr(obj, 'PlacementList', None):
if getattr(obj, "PlacementList", None):
self.buildShape(obj, obj.Placement, obj.PlacementList)
else:
self.execute(obj)
@@ -198,14 +185,13 @@ class DraftLink(DraftObject):
def buildShape(self, obj, pl, pls):
"""Build the shape of the link object."""
if self.use_link:
if not getattr(obj, 'ExpandArray', False) or obj.Count != len(pls):
obj.setPropertyStatus('PlacementList', '-Immutable')
if not getattr(obj, "ExpandArray", False) or obj.Count != len(pls):
obj.setPropertyStatus("PlacementList", "-Immutable")
obj.PlacementList = pls
obj.setPropertyStatus('PlacementList', 'Immutable')
obj.setPropertyStatus("PlacementList", "Immutable")
obj.Count = len(pls)
if getattr(obj, 'ExpandArray', False) \
and getattr(obj, 'AlwaysSyncPlacement', False):
for pla,child in zip(pls,obj.ElementList):
if getattr(obj, "ExpandArray", False) and getattr(obj, "AlwaysSyncPlacement", False):
for pla, child in zip(pls, obj.ElementList):
child.Placement = pla
else:
obj.PlacementList = pls
@@ -213,12 +199,13 @@ class DraftLink(DraftObject):
obj.Count = len(pls)
if obj.Base:
shape = getattr(obj.Base, 'Shape', None)
shape = getattr(obj.Base, "Shape", None)
if not isinstance(shape, Part.Shape):
obj.Shape = Part.Shape()
elif shape.isNull():
_err_msg = ("'{}' cannot build shape "
"from '{}'\n".format(obj.Label, obj.Base.Label))
_err_msg = "'{}' cannot build shape " "from '{}'\n".format(
obj.Label, obj.Base.Label
)
raise RuntimeError(_err_msg)
else:
# Resetting the Placement of the copied shape does not work for
@@ -228,13 +215,13 @@ class DraftLink(DraftObject):
shape.transformShape(place.Matrix.inverse())
base = []
for i, pla in enumerate(pls):
vis = getattr(obj, 'VisibilityList', [])
vis = getattr(obj, "VisibilityList", [])
if len(vis) > i and not vis[i]:
continue
base.append(shape.transformed(pla.toMatrix()))
if getattr(obj, 'Fuse', False) and len(base) > 1:
if getattr(obj, "Fuse", False) and len(base) > 1:
obj.Shape = base[0].multiFuse(base[1:]).removeSplitter()
else:
obj.Shape = Part.makeCompound(base)
@@ -249,20 +236,20 @@ class DraftLink(DraftObject):
"""Execute when a property changes."""
self.props_changed_store(prop)
if not getattr(self, 'use_link', False):
if not getattr(self, "use_link", False):
return
if prop == 'Fuse':
if prop == "Fuse":
if obj.Fuse:
obj.setPropertyStatus('Shape', '-Transient')
obj.setPropertyStatus("Shape", "-Transient")
else:
obj.setPropertyStatus('Shape', 'Transient')
elif prop == 'ExpandArray':
if hasattr(obj, 'PlacementList'):
obj.setPropertyStatus("Shape", "Transient")
elif prop == "ExpandArray":
if hasattr(obj, "PlacementList"):
if obj.ExpandArray:
obj.setPropertyStatus('PlacementList', '-Immutable')
obj.setPropertyStatus("PlacementList", "-Immutable")
else:
obj.setPropertyStatus('PlacementList', 'Immutable')
obj.setPropertyStatus("PlacementList", "Immutable")
# Alias for compatibility with old versions of v0.19

View File

@@ -41,24 +41,27 @@ class Ellipse(DraftObject):
def __init__(self, obj):
super().__init__(obj, "Ellipse")
_tip = QT_TRANSLATE_NOOP("App::Property","Start angle of the elliptical arc")
_tip = QT_TRANSLATE_NOOP("App::Property", "Start angle of the elliptical arc")
obj.addProperty("App::PropertyAngle", "FirstAngle", "Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property","End angle of the elliptical arc \n\
(for a full circle, give it same value as First Angle)")
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"End angle of the elliptical arc \n\
(for a full circle, give it same value as First Angle)",
)
obj.addProperty("App::PropertyAngle", "LastAngle", "Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property","Minor radius of the ellipse")
_tip = QT_TRANSLATE_NOOP("App::Property", "Minor radius of the ellipse")
obj.addProperty("App::PropertyLength", "MinorRadius", "Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property","Major radius of the ellipse")
_tip = QT_TRANSLATE_NOOP("App::Property", "Major radius of the ellipse")
obj.addProperty("App::PropertyLength", "MajorRadius", "Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property","Create a face")
_tip = QT_TRANSLATE_NOOP("App::Property", "Create a face")
obj.addProperty("App::PropertyBool", "MakeFace", "Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property","Area of this object")
obj.addProperty("App::PropertyArea", "Area","Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property", "Area of this object")
obj.addProperty("App::PropertyArea", "Area", "Draft", _tip, locked=True)
obj.MakeFace = params.get_param("MakeFaceMode")
@@ -73,24 +76,23 @@ class Ellipse(DraftObject):
return
import Part
plm = obj.Placement
if obj.MajorRadius.Value < obj.MinorRadius.Value:
_err = "Error: Major radius is smaller than the minor radius"
App.Console.PrintMessage(QT_TRANSLATE_NOOP("Draft", _err))
return
if obj.MajorRadius.Value and obj.MinorRadius.Value:
ell = Part.Ellipse(App.Vector(0, 0, 0),
obj.MajorRadius.Value,
obj.MinorRadius.Value)
ell = Part.Ellipse(App.Vector(0, 0, 0), obj.MajorRadius.Value, obj.MinorRadius.Value)
shape = ell.toShape()
if hasattr(obj,"FirstAngle"):
if hasattr(obj, "FirstAngle"):
if obj.FirstAngle.Value != obj.LastAngle.Value:
a1 = obj.FirstAngle.getValueAs(App.Units.Radian)
a2 = obj.LastAngle.getValueAs(App.Units.Radian)
shape = Part.ArcOfEllipse(ell, a1, a2).toShape()
shape = Part.Wire(shape)
if shape.isClosed():
if hasattr(obj,"MakeFace"):
if hasattr(obj, "MakeFace"):
if obj.MakeFace:
shape = Part.Face(shape)
else:

View File

@@ -40,26 +40,31 @@ from draftutils.translate import translate
class Facebinder(DraftObject):
"""The Draft Facebinder object"""
def __init__(self,obj):
def __init__(self, obj):
super().__init__(obj, "Facebinder")
_tip = QT_TRANSLATE_NOOP("App::Property","Linked faces")
_tip = QT_TRANSLATE_NOOP("App::Property", "Linked faces")
obj.addProperty("App::PropertyLinkSubList", "Faces", "Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property","Specifies if splitter lines must be removed")
obj.addProperty("App::PropertyBool","RemoveSplitter", "Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property", "Specifies if splitter lines must be removed")
obj.addProperty("App::PropertyBool", "RemoveSplitter", "Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property","An optional extrusion value to be applied to all faces")
obj.addProperty("App::PropertyDistance","Extrusion", "Draft" , _tip, locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property", "An optional extrusion value to be applied to all faces"
)
obj.addProperty("App::PropertyDistance", "Extrusion", "Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property","An optional offset value to be applied to all faces")
obj.addProperty("App::PropertyDistance","Offset", "Draft" , _tip, locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property", "An optional offset value to be applied to all faces"
)
obj.addProperty("App::PropertyDistance", "Offset", "Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property","This specifies if the shapes sew")
obj.addProperty("App::PropertyBool","Sew", "Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property", "This specifies if the shapes sew")
obj.addProperty("App::PropertyBool", "Sew", "Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property","The area of the faces of this Facebinder")
obj.addProperty("App::PropertyArea","Area", "Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property", "The area of the faces of this Facebinder")
obj.addProperty("App::PropertyArea", "Area", "Draft", _tip, locked=True)
obj.setEditorMode("Area", 1)
def onDocumentRestored(self, obj):
@@ -78,6 +83,7 @@ class Facebinder(DraftObject):
return
import Part
faces = []
try:
for sel in obj.Faces:
@@ -131,11 +137,16 @@ class Facebinder(DraftObject):
_wrn(obj.Label + ": " + translate("draft", "No valid faces for facebinder"))
def _report_sew_error(self, obj):
_wrn(obj.Label + ": " + translate("draft", "Unable to build facebinder, resuming with sew disabled"))
_wrn(
obj.Label
+ ": "
+ translate("draft", "Unable to build facebinder, resuming with sew disabled")
)
def _build_shape(self, obj, faces, sew=False):
"""returns the built shape and the area of the offset faces"""
import Part
offs_val = getattr(obj, "Offset", 0)
extr_val = getattr(obj, "Extrusion", 0)
@@ -175,6 +186,7 @@ class Facebinder(DraftObject):
def _convert_to_planar(self, obj, shp):
"""convert flat B-spline faces to planar faces if possible"""
import Part
faces = []
for face in shp.Faces:
if face.Surface.TypeId == "Part::GeomPlane":
@@ -196,9 +208,13 @@ class Facebinder(DraftObject):
solid = Part.makeSolid(Part.makeShell(faces))
if solid.isValid():
return solid
_msg(obj.Label + ": " + translate("draft",
"Converting flat B-spline faces of facebinder to planar faces failed"
))
_msg(
obj.Label
+ ": "
+ translate(
"draft", "Converting flat B-spline faces of facebinder to planar faces failed"
)
)
return shp
def onChanged(self, obj, prop):

View File

@@ -47,38 +47,22 @@ class Fillet(DraftObject):
"""Set the properties of objects if they don't exist."""
if not hasattr(obj, "Start"):
_tip = QT_TRANSLATE_NOOP("App::Property", "The start point of this line.")
obj.addProperty("App::PropertyVectorDistance",
"Start",
"Draft",
_tip,
locked=True)
obj.addProperty("App::PropertyVectorDistance", "Start", "Draft", _tip, locked=True)
obj.Start = App.Vector(0, 0, 0)
if not hasattr(obj, "End"):
_tip = QT_TRANSLATE_NOOP("App::Property", "The end point of this line.")
obj.addProperty("App::PropertyVectorDistance",
"End",
"Draft",
_tip,
locked=True)
obj.addProperty("App::PropertyVectorDistance", "End", "Draft", _tip, locked=True)
obj.End = App.Vector(0, 0, 0)
if not hasattr(obj, "Length"):
_tip = QT_TRANSLATE_NOOP("App::Property", "The length of this line.")
obj.addProperty("App::PropertyLength",
"Length",
"Draft",
_tip,
locked=True)
obj.addProperty("App::PropertyLength", "Length", "Draft", _tip, locked=True)
obj.Length = 0
if not hasattr(obj, "FilletRadius"):
_tip = QT_TRANSLATE_NOOP("App::Property", "Radius to use to fillet the corner.")
obj.addProperty("App::PropertyLength",
"FilletRadius",
"Draft",
_tip,
locked=True)
obj.addProperty("App::PropertyLength", "FilletRadius", "Draft", _tip, locked=True)
obj.FilletRadius = 0
# TODO: these two properties should link two straight lines
@@ -117,7 +101,7 @@ class Fillet(DraftObject):
obj.End = obj.Shape.Vertexes[-1].Point
def _update_radius(self, obj, radius):
#if (hasattr(obj, "Line1") and hasattr(obj, "Line2")
# if (hasattr(obj, "Line1") and hasattr(obj, "Line2")
# and obj.Line1 and obj.Line2):
# do the unimplemented work
pass
@@ -131,4 +115,5 @@ class Fillet(DraftObject):
if prop in "FilletRadius":
self._update_radius(obj, obj.FilletRadius)
## @}

View File

@@ -1,24 +1,24 @@
#***************************************************************************
#* *
#* Copyright (c) 2021 Yorik van Havre <yorik@uncreated.net> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
# ***************************************************************************
# * *
# * Copyright (c) 2021 Yorik van Havre <yorik@uncreated.net> *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * This program is distributed in the hope that it will be useful, *
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
# * GNU Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
"""This module contains FreeCAD commands for the Draft workbench"""
@@ -36,37 +36,69 @@ from draftutils.translate import translate
class Hatch(DraftObject):
def __init__(self,obj):
def __init__(self, obj):
obj.Proxy = self
self.Type = "Hatch"
self.setProperties(obj)
def setProperties(self,obj):
def setProperties(self, obj):
pl = obj.PropertiesList
if not "Base" in pl:
obj.addProperty("App::PropertyLink","Base","Hatch",
QT_TRANSLATE_NOOP("App::Property","The base object used by this object"), locked=True)
obj.addProperty(
"App::PropertyLink",
"Base",
"Hatch",
QT_TRANSLATE_NOOP("App::Property", "The base object used by this object"),
locked=True,
)
if not "File" in pl:
obj.addProperty("App::PropertyFile","File","Hatch",
QT_TRANSLATE_NOOP("App::Property","The PAT file used by this object"), locked=True)
obj.addProperty(
"App::PropertyFile",
"File",
"Hatch",
QT_TRANSLATE_NOOP("App::Property", "The PAT file used by this object"),
locked=True,
)
if not "Pattern" in pl:
obj.addProperty("App::PropertyString","Pattern","Hatch",
QT_TRANSLATE_NOOP("App::Property","The pattern name used by this object"), locked=True)
obj.addProperty(
"App::PropertyString",
"Pattern",
"Hatch",
QT_TRANSLATE_NOOP("App::Property", "The pattern name used by this object"),
locked=True,
)
if not "Scale" in pl:
obj.addProperty("App::PropertyFloat","Scale","Hatch",
QT_TRANSLATE_NOOP("App::Property","The pattern scale used by this object"), locked=True)
obj.addProperty(
"App::PropertyFloat",
"Scale",
"Hatch",
QT_TRANSLATE_NOOP("App::Property", "The pattern scale used by this object"),
locked=True,
)
if not "Rotation" in pl:
obj.addProperty("App::PropertyAngle","Rotation","Hatch",
QT_TRANSLATE_NOOP("App::Property","The pattern rotation used by this object"), locked=True)
obj.addProperty(
"App::PropertyAngle",
"Rotation",
"Hatch",
QT_TRANSLATE_NOOP("App::Property", "The pattern rotation used by this object"),
locked=True,
)
if not "Translate" in pl:
obj.addProperty("App::PropertyBool","Translate","Hatch",
QT_TRANSLATE_NOOP("App::Property","If set to False, hatch is applied as is to the faces, without translation (this might give wrong results for non-XY faces)"), locked=True)
obj.addProperty(
"App::PropertyBool",
"Translate",
"Hatch",
QT_TRANSLATE_NOOP(
"App::Property",
"If set to False, hatch is applied as is to the faces, without translation (this might give wrong results for non-XY faces)",
),
locked=True,
)
obj.Translate = True
def onDocumentRestored(self,obj):
def onDocumentRestored(self, obj):
self.setProperties(obj)
super().onDocumentRestored(obj)
gui_utils.restore_view_object(
@@ -79,15 +111,17 @@ class Hatch(DraftObject):
def loads(self, state):
self.Type = "Hatch"
def execute(self,obj):
def execute(self, obj):
if self.props_changed_placement_only(obj) \
or not obj.Base \
or not obj.File \
or not obj.Pattern \
or not obj.Scale \
or not obj.Base.isDerivedFrom("Part::Feature") \
or not obj.Base.Shape.Faces:
if (
self.props_changed_placement_only(obj)
or not obj.Base
or not obj.File
or not obj.Pattern
or not obj.Scale
or not obj.Base.isDerivedFrom("Part::Feature")
or not obj.Base.Shape.Faces
):
self.props_changed_clear()
return
@@ -131,7 +165,7 @@ class Hatch(DraftObject):
shapes = []
for face in obj.Base.Shape.Faces:
if face.findPlane(): # Only planar faces.
if face.findPlane(): # Only planar faces.
face = face.copy()
if obj.Translate:
mtx = None
@@ -183,8 +217,7 @@ class Hatch(DraftObject):
self.props_changed_store(prop)
def getPatterns(self,filename):
def getPatterns(self, filename):
"""returns a list of pattern names found in a PAT file"""
patterns = []
if os.path.exists(filename):

View File

@@ -58,31 +58,27 @@ class Label(DraftAnnotation):
properties = obj.PropertiesList
if "TargetPoint" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"The position of the tip of the leader "
"line.\n"
"This point can be decorated "
"with an arrow or another symbol.")
obj.addProperty("App::PropertyVector",
"TargetPoint",
"Target",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"The position of the tip of the leader "
"line.\n"
"This point can be decorated "
"with an arrow or another symbol.",
)
obj.addProperty("App::PropertyVector", "TargetPoint", "Target", _tip, locked=True)
obj.TargetPoint = App.Vector(2, -1, 0)
if "Target" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"Object, and optionally subelement, "
"whose properties will be displayed\n"
"as 'Text', depending on 'Label Type'.\n"
"\n"
"'Target' won't be used "
"if 'Label Type' is set to 'Custom'.")
obj.addProperty("App::PropertyLinkSub",
"Target",
"Target",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"Object, and optionally subelement, "
"whose properties will be displayed\n"
"as 'Text', depending on 'Label Type'.\n"
"\n"
"'Target' won't be used "
"if 'Label Type' is set to 'Custom'.",
)
obj.addProperty("App::PropertyLinkSub", "Target", "Target", _tip, locked=True)
obj.Target = None
def set_leader_properties(self, obj):
@@ -90,65 +86,63 @@ class Label(DraftAnnotation):
properties = obj.PropertiesList
if "Points" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"The list of points defining the leader "
"line; normally a list of three points.\n"
"\n"
"The first point should be the position "
"of the text, that is, the 'Placement',\n"
"and the last point should be "
"the tip of the line, that is, "
"the 'Target Point'.\n"
"The middle point is calculated "
"automatically depending on the chosen\n"
"'Straight Direction' "
"and the 'Straight Distance' value "
"and sign.\n"
"\n"
"If 'Straight Direction' is set to "
"'Custom', the 'Points' property\n"
"can be set as a list "
"of arbitrary points.")
obj.addProperty("App::PropertyVectorList",
"Points",
"Leader",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"The list of points defining the leader "
"line; normally a list of three points.\n"
"\n"
"The first point should be the position "
"of the text, that is, the 'Placement',\n"
"and the last point should be "
"the tip of the line, that is, "
"the 'Target Point'.\n"
"The middle point is calculated "
"automatically depending on the chosen\n"
"'Straight Direction' "
"and the 'Straight Distance' value "
"and sign.\n"
"\n"
"If 'Straight Direction' is set to "
"'Custom', the 'Points' property\n"
"can be set as a list "
"of arbitrary points.",
)
obj.addProperty("App::PropertyVectorList", "Points", "Leader", _tip, locked=True)
obj.Points = []
if "StraightDirection" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"The direction of the straight segment "
"of the leader line.\n"
"\n"
"If 'Custom' is chosen, the points "
"of the leader can be specified by\n"
"assigning a custom list "
"to the 'Points' attribute.")
obj.addProperty("App::PropertyEnumeration",
"StraightDirection",
"Leader",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"The direction of the straight segment "
"of the leader line.\n"
"\n"
"If 'Custom' is chosen, the points "
"of the leader can be specified by\n"
"assigning a custom list "
"to the 'Points' attribute.",
)
obj.addProperty(
"App::PropertyEnumeration", "StraightDirection", "Leader", _tip, locked=True
)
obj.StraightDirection = ["Horizontal", "Vertical", "Custom"]
if "StraightDistance" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"The length of the straight segment "
"of the leader line.\n"
"\n"
"This is an oriented distance; "
"if it is negative, the line will "
"be drawn\n"
"to the left or below the 'Text', "
"otherwise to the right or above it,\n"
"depending on the value of "
"'Straight Direction'.")
obj.addProperty("App::PropertyDistance",
"StraightDistance",
"Leader",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"The length of the straight segment "
"of the leader line.\n"
"\n"
"This is an oriented distance; "
"if it is negative, the line will "
"be drawn\n"
"to the left or below the 'Text', "
"otherwise to the right or above it,\n"
"depending on the value of "
"'Straight Direction'.",
)
obj.addProperty(
"App::PropertyDistance", "StraightDistance", "Leader", _tip, locked=True
)
obj.StraightDistance = 1
def set_label_properties(self, obj):
@@ -156,41 +150,31 @@ class Label(DraftAnnotation):
properties = obj.PropertiesList
if "Placement" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"The placement of the 'Text' element "
"in 3D space")
obj.addProperty("App::PropertyPlacement",
"Placement",
"Label",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property", "The placement of the 'Text' element " "in 3D space"
)
obj.addProperty("App::PropertyPlacement", "Placement", "Label", _tip, locked=True)
obj.Placement = App.Placement()
if "CustomText" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"The text to display when 'Label Type' "
"is set to 'Custom'")
obj.addProperty("App::PropertyStringList",
"CustomText",
"Label",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property", "The text to display when 'Label Type' " "is set to 'Custom'"
)
obj.addProperty("App::PropertyStringList", "CustomText", "Label", _tip, locked=True)
obj.CustomText = "Label"
if "Text" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"The text displayed by this label.\n"
"\n"
"This property is read-only, as the "
"final text depends on 'Label Type',\n"
"and the object defined in 'Target'.\n"
"The 'Custom Text' is displayed only "
"if 'Label Type' is set to 'Custom'.")
obj.addProperty("App::PropertyStringList",
"Text",
"Label",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"The text displayed by this label.\n"
"\n"
"This property is read-only, as the "
"final text depends on 'Label Type',\n"
"and the object defined in 'Target'.\n"
"The 'Custom Text' is displayed only "
"if 'Label Type' is set to 'Custom'.",
)
obj.addProperty("App::PropertyStringList", "Text", "Label", _tip, locked=True)
obj.setEditorMode("Text", 1) # Read only
# TODO: maybe here we can define a second and third 'label type'
@@ -203,30 +187,28 @@ class Label(DraftAnnotation):
# This would also require updating the `return_info` function
# to handle any combination that we want.
if "LabelType" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"The type of information displayed "
"by this label.\n"
"\n"
"If 'Custom' is chosen, the contents of "
"'Custom Text' will be used.\n"
"For other types, the string will be "
"calculated automatically from the "
"object defined in 'Target'.\n"
"'Tag' and 'Material' only work "
"for objects that have these properties, "
"like BIM objects.\n"
"\n"
"For 'Position', 'Length', and 'Area' "
"these properties will be extracted "
"from the main object in 'Target',\n"
"or from the subelement "
"'VertexN', 'EdgeN', or 'FaceN', "
"respectively, if it is specified.")
obj.addProperty("App::PropertyEnumeration",
"LabelType",
"Label",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"The type of information displayed "
"by this label.\n"
"\n"
"If 'Custom' is chosen, the contents of "
"'Custom Text' will be used.\n"
"For other types, the string will be "
"calculated automatically from the "
"object defined in 'Target'.\n"
"'Tag' and 'Material' only work "
"for objects that have these properties, "
"like BIM objects.\n"
"\n"
"For 'Position', 'Length', and 'Area' "
"these properties will be extracted "
"from the main object in 'Target',\n"
"or from the subelement "
"'VertexN', 'EdgeN', or 'FaceN', "
"respectively, if it is specified.",
)
obj.addProperty("App::PropertyEnumeration", "LabelType", "Label", _tip, locked=True)
obj.LabelType = get_label_types()
def onDocumentRestored(self, obj):
@@ -327,20 +309,22 @@ DraftLabel = Label
def get_label_types():
return [QT_TRANSLATE_NOOP("Draft","Custom"),
QT_TRANSLATE_NOOP("Draft","Name"),
QT_TRANSLATE_NOOP("Draft","Label"),
QT_TRANSLATE_NOOP("Draft","Position"),
QT_TRANSLATE_NOOP("Draft","Length"),
QT_TRANSLATE_NOOP("Draft","Area"),
QT_TRANSLATE_NOOP("Draft","Volume"),
QT_TRANSLATE_NOOP("Draft","Tag"),
QT_TRANSLATE_NOOP("Draft","Material"),
QT_TRANSLATE_NOOP("Draft","Label + Position"),
QT_TRANSLATE_NOOP("Draft","Label + Length"),
QT_TRANSLATE_NOOP("Draft","Label + Area"),
QT_TRANSLATE_NOOP("Draft","Label + Volume"),
QT_TRANSLATE_NOOP("Draft","Label + Material")]
return [
QT_TRANSLATE_NOOP("Draft", "Custom"),
QT_TRANSLATE_NOOP("Draft", "Name"),
QT_TRANSLATE_NOOP("Draft", "Label"),
QT_TRANSLATE_NOOP("Draft", "Position"),
QT_TRANSLATE_NOOP("Draft", "Length"),
QT_TRANSLATE_NOOP("Draft", "Area"),
QT_TRANSLATE_NOOP("Draft", "Volume"),
QT_TRANSLATE_NOOP("Draft", "Tag"),
QT_TRANSLATE_NOOP("Draft", "Material"),
QT_TRANSLATE_NOOP("Draft", "Label + Position"),
QT_TRANSLATE_NOOP("Draft", "Label + Length"),
QT_TRANSLATE_NOOP("Draft", "Label + Area"),
QT_TRANSLATE_NOOP("Draft", "Label + Volume"),
QT_TRANSLATE_NOOP("Draft", "Label + Material"),
]
def return_info(target, typ, subelement=None):
@@ -420,7 +404,7 @@ def _get_tag(target):
def _get_material(target):
if (hasattr(target, "Material") and hasattr(target.Material, "Label")):
if hasattr(target, "Material") and hasattr(target.Material, "Label"):
return [target.Material.Label]
else:
return [translate("draft", "Material not available for object")]

View File

@@ -52,16 +52,11 @@ class Layer:
def set_properties(self, obj):
"""Set properties only if they don't exist."""
if "Group" not in obj.PropertiesList:
_tip = QT_TRANSLATE_NOOP("App::Property",
"The objects that are part of this layer")
_tip = QT_TRANSLATE_NOOP("App::Property", "The objects that are part of this layer")
# "App::PropertyLinkListHidden" instead of "App::PropertyLinkList" has 2 advantages:
# 1. No 'might break' warning when deleting an object nested in a layer.
# 2. No 'out of scope' warning for objects also nested in f.e. a Std_Part.
obj.addProperty("App::PropertyLinkListHidden",
"Group",
"Layer",
_tip,
locked=True)
obj.addProperty("App::PropertyLinkListHidden", "Group", "Layer", _tip, locked=True)
def onDocumentRestored(self, obj):
"""Execute code when the document is restored."""
@@ -93,7 +88,7 @@ class Layer:
material = App.Material() # Material with default v0.21 properties.
material.DiffuseColor = vobj.ShapeColor
material.Transparency = vobj.Transparency / 100
vobj.ShapeAppearance = (material, )
vobj.ShapeAppearance = (material,)
vobj.setPropertyStatus("ShapeColor", "Hidden")
if hasattr(vobj, "OverrideShapeColorChildren"): # v0.19 - v0.21
vobj.OverrideShapeAppearanceChildren = vobj.OverrideShapeColorChildren
@@ -214,4 +209,5 @@ def get_layer(obj):
return find
return None
## @}

View File

@@ -69,7 +69,12 @@ import lazy_loader.lazy_loader as lz
from draftutils.messages import _err, _log, _wrn
from draftutils.translate import translate
def QT_TRANSLATE_NOOP(ctx,txt): return txt
def QT_TRANSLATE_NOOP(ctx, txt):
return txt
from draftobjects.base import DraftObject
from draftobjects.draftlink import DraftLink
@@ -212,21 +217,16 @@ class PathArray(DraftLink):
def set_general_properties(self, obj, properties):
"""Set general properties only if they don't exist."""
if "Base" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property","The base object that will be duplicated")
obj.addProperty("App::PropertyLinkGlobal",
"Base",
"Objects",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property", "The base object that will be duplicated")
obj.addProperty("App::PropertyLinkGlobal", "Base", "Objects", _tip, locked=True)
obj.Base = None
if "PathObject" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property","The object along which the copies will be distributed. It must contain 'Edges'.")
obj.addProperty("App::PropertyLinkGlobal",
"PathObject",
"Objects",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"The object along which the copies will be distributed. It must contain 'Edges'.",
)
obj.addProperty("App::PropertyLinkGlobal", "PathObject", "Objects", _tip, locked=True)
obj.PathObject = None
# TODO: the 'PathSubelements' property must be changed,
@@ -237,199 +237,161 @@ class PathArray(DraftLink):
# as this property can be used to select a single object,
# or a single object with its subelements.
if "PathSubelements" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property","List of connected edges in the 'Path Object'.\nIf these are present, the copies will be created along these subelements only.\nLeave this property empty to create copies along the entire 'Path Object'.")
obj.addProperty("App::PropertyLinkSubListGlobal",
"PathSubelements",
"Objects",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"List of connected edges in the 'Path Object'.\nIf these are present, the copies will be created along these subelements only.\nLeave this property empty to create copies along the entire 'Path Object'.",
)
obj.addProperty(
"App::PropertyLinkSubListGlobal", "PathSubelements", "Objects", _tip, locked=True
)
obj.PathSubelements = []
if "Fuse" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"Specifies if the copies "
"should be fused together "
"if they touch each other (slower)")
obj.addProperty("App::PropertyBool",
"Fuse",
"Objects",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"Specifies if the copies "
"should be fused together "
"if they touch each other (slower)",
)
obj.addProperty("App::PropertyBool", "Fuse", "Objects", _tip, locked=True)
obj.Fuse = False
if self.use_link and "ExpandArray" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property","Show the individual array elements (only for Link arrays)")
obj.addProperty("App::PropertyBool",
"ExpandArray",
"Objects",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property", "Show the individual array elements (only for Link arrays)"
)
obj.addProperty("App::PropertyBool", "ExpandArray", "Objects", _tip, locked=True)
obj.ExpandArray = False
obj.setPropertyStatus('Shape', 'Transient')
obj.setPropertyStatus("Shape", "Transient")
if not self.use_link:
if "PlacementList" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"The placement for each array element")
obj.addProperty("App::PropertyPlacementList",
"PlacementList",
"Objects",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property", "The placement for each array element")
obj.addProperty(
"App::PropertyPlacementList", "PlacementList", "Objects", _tip, locked=True
)
obj.PlacementList = []
def set_align_properties(self, obj, properties):
"""Set general properties only if they don't exist."""
if "ExtraTranslation" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property","Additional translation that will be applied to each copy.\nThis is useful to adjust for the difference between shape centre and shape reference point.")
obj.addProperty("App::PropertyVectorDistance",
"ExtraTranslation",
"Alignment",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"Additional translation that will be applied to each copy.\nThis is useful to adjust for the difference between shape centre and shape reference point.",
)
obj.addProperty(
"App::PropertyVectorDistance", "ExtraTranslation", "Alignment", _tip, locked=True
)
obj.ExtraTranslation = App.Vector(0, 0, 0)
if "TangentVector" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property","Alignment vector for 'Tangent' mode")
obj.addProperty("App::PropertyVector",
"TangentVector",
"Alignment",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property", "Alignment vector for 'Tangent' mode")
obj.addProperty("App::PropertyVector", "TangentVector", "Alignment", _tip, locked=True)
obj.TangentVector = App.Vector(1, 0, 0)
if "ForceVertical" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property","Force use of 'Vertical Vector' as local Z-direction when using 'Original' or 'Tangent' alignment mode")
obj.addProperty("App::PropertyBool",
"ForceVertical",
"Alignment",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"Force use of 'Vertical Vector' as local Z-direction when using 'Original' or 'Tangent' alignment mode",
)
obj.addProperty("App::PropertyBool", "ForceVertical", "Alignment", _tip, locked=True)
obj.ForceVertical = False
if "VerticalVector" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property","Direction of the local Z axis when 'Force Vertical' is true")
obj.addProperty("App::PropertyVector",
"VerticalVector",
"Alignment",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property", "Direction of the local Z axis when 'Force Vertical' is true"
)
obj.addProperty("App::PropertyVector", "VerticalVector", "Alignment", _tip, locked=True)
obj.VerticalVector = App.Vector(0, 0, 1)
if "AlignMode" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property","Method to orient the copies along the path.\n- Original: X is curve tangent, Y is normal, and Z is the cross product.\n- Frenet: aligns the object following the local coordinate system along the path.\n- Tangent: similar to 'Original' but the local X axis is pre-aligned to 'Tangent Vector'.\n\nTo get better results with 'Original' or 'Tangent' you may have to set 'Force Vertical' to true.")
obj.addProperty("App::PropertyEnumeration",
"AlignMode",
"Alignment",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"Method to orient the copies along the path.\n- Original: X is curve tangent, Y is normal, and Z is the cross product.\n- Frenet: aligns the object following the local coordinate system along the path.\n- Tangent: similar to 'Original' but the local X axis is pre-aligned to 'Tangent Vector'.\n\nTo get better results with 'Original' or 'Tangent' you may have to set 'Force Vertical' to true.",
)
obj.addProperty("App::PropertyEnumeration", "AlignMode", "Alignment", _tip, locked=True)
obj.AlignMode = ["Original", "Frenet", "Tangent"]
obj.AlignMode = "Original"
if "ReversePath" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property","Walk the path backwards.")
obj.addProperty("App::PropertyBool",
"ReversePath",
"Alignment",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property", "Walk the path backwards.")
obj.addProperty("App::PropertyBool", "ReversePath", "Alignment", _tip, locked=True)
obj.ReversePath = False
# The Align property must be attached after other align properties
# so that onChanged works properly
if "Align" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property","Orient the copies along the path depending on the 'Align Mode'.\nOtherwise the copies will have the same orientation as the original Base object.")
obj.addProperty("App::PropertyBool",
"Align",
"Alignment",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"Orient the copies along the path depending on the 'Align Mode'.\nOtherwise the copies will have the same orientation as the original Base object.",
)
obj.addProperty("App::PropertyBool", "Align", "Alignment", _tip, locked=True)
obj.Align = False
def set_spacing_properties(self, obj, properties):
if "Count" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property","Number of copies to create")
obj.addProperty("App::PropertyInteger",
"Count",
"Spacing",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property", "Number of copies to create")
obj.addProperty("App::PropertyInteger", "Count", "Spacing", _tip, locked=True)
obj.Count = 4
if "SpacingMode" not in properties:
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"How copies are spaced.\n" +
" - Fixed count: available path length (minus start and end offsets) is evenly divided into n.\n" +
" - Fixed spacing: start at \"Start offset\" and place new copies after traveling a fixed distance along the path.\n" +
" - Fixed count and spacing: same as \"Fixed spacing\", but also stop at given number of copies."
)
obj.addProperty("App::PropertyEnumeration",
"SpacingMode",
"Spacing",
_tip,
locked=True)
"How copies are spaced.\n"
+ " - Fixed count: available path length (minus start and end offsets) is evenly divided into n.\n"
+ ' - Fixed spacing: start at "Start offset" and place new copies after traveling a fixed distance along the path.\n'
+ ' - Fixed count and spacing: same as "Fixed spacing", but also stop at given number of copies.',
)
obj.addProperty("App::PropertyEnumeration", "SpacingMode", "Spacing", _tip, locked=True)
obj.SpacingMode = ["Fixed count", "Fixed spacing", "Fixed count and spacing"]
obj.SpacingMode = "Fixed count"
if "SpacingUnit" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property","Base fixed distance between elements.")
obj.addProperty("App::PropertyLength",
"SpacingUnit",
"Spacing",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property", "Base fixed distance between elements.")
obj.addProperty("App::PropertyLength", "SpacingUnit", "Spacing", _tip, locked=True)
obj.SpacingUnit = 20.0
obj.setPropertyStatus("SpacingUnit", "Hidden")
if "UseSpacingPattern" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property","Use repeating spacing patterns instead of uniform spacing.")
obj.addProperty("App::PropertyBool",
"UseSpacingPattern",
"Spacing",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property", "Use repeating spacing patterns instead of uniform spacing."
)
obj.addProperty("App::PropertyBool", "UseSpacingPattern", "Spacing", _tip, locked=True)
obj.UseSpacingPattern = False
if "SpacingPattern" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property","Spacing is multiplied by a corresponding number in this sequence.")
obj.addProperty("App::PropertyFloatList",
"SpacingPattern",
"Spacing",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property", "Spacing is multiplied by a corresponding number in this sequence."
)
obj.addProperty(
"App::PropertyFloatList", "SpacingPattern", "Spacing", _tip, locked=True
)
obj.SpacingPattern = [1, 2]
obj.setPropertyStatus("SpacingPattern", "Hidden")
if "StartOffset" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property","Length from the start of the path to the first copy.")
obj.addProperty("App::PropertyLength",
"StartOffset",
"Spacing",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property", "Length from the start of the path to the first copy."
)
obj.addProperty("App::PropertyLength", "StartOffset", "Spacing", _tip, locked=True)
obj.StartOffset = 0.0
if "EndOffset" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property","Length from the end of the path to the last copy.")
obj.addProperty("App::PropertyLength",
"EndOffset",
"Spacing",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property", "Length from the end of the path to the last copy."
)
obj.addProperty("App::PropertyLength", "EndOffset", "Spacing", _tip, locked=True)
obj.EndOffset = 0.0
def linkSetup(self, obj):
"""Set up the object as a link object."""
super().linkSetup(obj)
obj.configLinkProperty(ElementCount='Count')
obj.configLinkProperty(ElementCount="Count")
def execute(self, obj):
"""Execute when the object is created or recomputed."""
if self.props_changed_placement_only(obj) \
or not obj.Base \
or not obj.PathObject:
if self.props_changed_placement_only(obj) or not obj.Base or not obj.PathObject:
self.props_changed_clear()
return
@@ -438,15 +400,13 @@ class PathArray(DraftLink):
w = self.get_wires(obj.PathObject, obj.PathSubelements)
if not w:
_err(obj.PathObject.Label
+ translate("draft",", path object does not have 'Edges'."))
_err(obj.PathObject.Label + translate("draft", ", path object does not have 'Edges'."))
return
base_rotation = obj.Base.Shape.Placement.Rotation
final_rotation = base_rotation
if (obj.Align and obj.AlignMode == "Tangent"
and hasattr(obj, "TangentVector")):
if obj.Align and obj.AlignMode == "Tangent" and hasattr(obj, "TangentVector"):
Xaxis = App.Vector(1.0, 0.0, 0.0) # default TangentVector
if not DraftVecUtils.equals(Xaxis, obj.TangentVector):
@@ -454,30 +414,33 @@ class PathArray(DraftLink):
pre_rotation = App.Rotation(obj.TangentVector, Xaxis)
final_rotation = base_rotation.multiply(pre_rotation)
copy_placements = placements_on_path(final_rotation,
w, obj.Count,
obj.ExtraTranslation,
obj.Align, obj.AlignMode,
obj.ForceVertical,
obj.VerticalVector,
obj.StartOffset.Value,
obj.EndOffset.Value,
obj.ReversePath,
obj.SpacingMode,
obj.SpacingUnit.Value,
obj.UseSpacingPattern,
obj.SpacingPattern)
copy_placements = placements_on_path(
final_rotation,
w,
obj.Count,
obj.ExtraTranslation,
obj.Align,
obj.AlignMode,
obj.ForceVertical,
obj.VerticalVector,
obj.StartOffset.Value,
obj.EndOffset.Value,
obj.ReversePath,
obj.SpacingMode,
obj.SpacingUnit.Value,
obj.UseSpacingPattern,
obj.SpacingPattern,
)
self.buildShape(obj, array_placement, copy_placements)
self.props_changed_clear()
return (not self.use_link)
return not self.use_link
def get_wires(self, path_object, subelements):
"""Get wires from the path object."""
if subelements:
w = self.get_wire_from_subelements(subelements)
elif (hasattr(path_object.Shape, 'Wires')
and path_object.Shape.Wires):
elif hasattr(path_object.Shape, "Wires") and path_object.Shape.Wires:
w = path_object.Shape.Wires[0]
elif path_object.Shape.Edges:
w = Part.Wire(path_object.Shape.Edges)
@@ -511,10 +474,7 @@ class PathArray(DraftLink):
if prop == "SpacingMode":
# Check if all referenced properties are available:
for pr in ("SpacingMode",
"SpacingUnit",
"UseSpacingPattern",
"SpacingPattern"):
for pr in ("SpacingMode", "SpacingUnit", "UseSpacingPattern", "SpacingPattern"):
if not hasattr(obj, pr):
return
@@ -544,8 +504,7 @@ class PathArray(DraftLink):
if prop in ("Align", "AlignMode"):
# Check if all referenced properties are available:
for pr in ("Align", "AlignMode", "ForceVertical",
"VerticalVector", "TangentVector"):
for pr in ("Align", "AlignMode", "ForceVertical", "VerticalVector", "TangentVector"):
if not hasattr(obj, pr):
return
@@ -565,8 +524,7 @@ class PathArray(DraftLink):
obj.setPropertyStatus("TangentVector", "Hidden")
else:
for pr in ("AlignMode", "ForceVertical",
"VerticalVector", "TangentVector"):
for pr in ("AlignMode", "ForceVertical", "VerticalVector", "TangentVector"):
obj.setPropertyStatus(pr, "Hidden")
def onDocumentRestored(self, obj):
@@ -609,22 +567,30 @@ class PathArray(DraftLink):
if hasattr(obj, "Xlate"):
obj.ExtraTranslation = obj.Xlate
obj.removeProperty("Xlate")
self.execute(obj) # Required to update PlacementList.
self.execute(obj) # Required to update PlacementList.
# Alias for compatibility with v0.18 and earlier
_PathArray = PathArray
def placements_on_path(shapeRotation, pathwire, count, xlate, align,
mode="Original", forceNormal=False,
normalOverride=None,
startOffset=0.0, endOffset=0.0,
reversePath=False,
spacingMode="Fixed count",
spacingUnit=20.0,
useSpacingPattern=False,
spacingPattern=[1, 1, 1, 1]):
def placements_on_path(
shapeRotation,
pathwire,
count,
xlate,
align,
mode="Original",
forceNormal=False,
normalOverride=None,
startOffset=0.0,
endOffset=0.0,
reversePath=False,
spacingMode="Fixed count",
spacingUnit=20.0,
useSpacingPattern=False,
spacingPattern=[1, 1, 1, 1],
):
"""Calculate the placements of a shape along a given path.
Copies will be distributed according to spacing mode - evenly or in fixed offsets.
@@ -658,12 +624,7 @@ def placements_on_path(shapeRotation, pathwire, count, xlate, align,
if startOffset > (totalDist - minLength):
if startOffset != 0:
_wrn(
translate(
"draft",
"Start Offset too large for path length. Using 0 instead."
)
)
_wrn(translate("draft", "Start Offset too large for path length. Using 0 instead."))
startOffset = 0
if endOffset > (totalDist - startOffset - minLength):
@@ -671,7 +632,7 @@ def placements_on_path(shapeRotation, pathwire, count, xlate, align,
_wrn(
translate(
"draft",
"End Offset too large for path length minus Start Offset. Using 0 instead."
"End Offset too large for path length minus Start Offset. Using 0 instead.",
)
)
endOffset = 0
@@ -728,7 +689,6 @@ def placements_on_path(shapeRotation, pathwire, count, xlate, align,
# Each interval will be the same:
steps = [spacingUnit]
remains = 0
travel = startOffset
endTravel = startOffset + totalDist
@@ -750,18 +710,27 @@ def placements_on_path(shapeRotation, pathwire, count, xlate, align,
# place shape at proper spot on proper edge
pt = path[iend].valueAt(get_parameter_from_v0(path[iend], offset))
place = calculate_placement(shapeRotation,
path[iend], offset,
pt, xlate, align, normal,
mode, forceNormal,
reversePath)
place = calculate_placement(
shapeRotation,
path[iend],
offset,
pt,
xlate,
align,
normal,
mode,
forceNormal,
reversePath,
)
placements.append(place)
travel += steps[i % len(steps)]
i = i + 1
# End conditions:
if stopAfterDistance and travel > endTravel: break
if stopAfterCount and i >= count: break
if stopAfterDistance and travel > endTravel:
break
if stopAfterCount and i >= count:
break
# Failsafe:
if i > 10_000:
@@ -774,11 +743,18 @@ def placements_on_path(shapeRotation, pathwire, count, xlate, align,
calculatePlacementsOnPath = placements_on_path
def calculate_placement(globalRotation,
edge, offset, RefPt, xlate, align,
normal=App.Vector(0.0, 0.0, 1.0),
mode="Original", overrideNormal=False,
reversePath=False):
def calculate_placement(
globalRotation,
edge,
offset,
RefPt,
xlate,
align,
normal=App.Vector(0.0, 0.0, 1.0),
mode="Original",
overrideNormal=False,
reversePath=False,
):
"""Orient shape in the local coordinate system at parameter offset.
http://en.wikipedia.org/wiki/Euler_angles (previous version)
@@ -792,7 +768,7 @@ def calculate_placement(globalRotation,
if not align:
return placement
tol = 1e-6 # App.Rotation() tolerance is 1e-7. Shorter vectors are ignored.
tol = 1e-6 # App.Rotation() tolerance is 1e-7. Shorter vectors are ignored.
nullv = App.Vector()
t = edge.tangentAt(get_parameter_from_v0(edge, offset))
@@ -821,19 +797,28 @@ def calculate_placement(globalRotation,
n_nor = n.normalize()
t_nor = t.normalize()
if n_nor.isEqual(t_nor, tol) or n_nor.isEqual(t_nor.negative(), tol):
_wrn(translate("draft", "Tangent and normal vectors are parallel. Normal replaced by a default axis."))
_wrn(
translate(
"draft",
"Tangent and normal vectors are parallel. Normal replaced by a default axis.",
)
)
n = t
if overrideNormal:
onPathRotation = App.Rotation(t, nullv, n, "XZY") # priority = "XZY"
onPathRotation = App.Rotation(t, nullv, n, "XZY") # priority = "XZY"
else:
onPathRotation = App.Rotation(t, n, nullv, "XYZ") # priority = "XYZ"
onPathRotation = App.Rotation(t, n, nullv, "XYZ") # priority = "XYZ"
elif mode == "Frenet":
try:
n = edge.normalAt(get_parameter_from_v0(edge, offset))
except App.Base.FreeCADError: # no/infinite normals here
_wrn(translate("draft", "Cannot calculate normal vector. Using the default normal instead."))
except App.Base.FreeCADError: # no/infinite normals here
_wrn(
translate(
"draft", "Cannot calculate normal vector. Using the default normal instead."
)
)
n = normal
if n.isEqual(nullv, tol):
@@ -843,10 +828,15 @@ def calculate_placement(globalRotation,
n_nor = n.normalize()
t_nor = t.normalize()
if n_nor.isEqual(t_nor, tol) or n_nor.isEqual(t_nor.negative(), tol):
_wrn(translate("draft", "Tangent and normal vectors are parallel. Normal replaced by a default axis."))
_wrn(
translate(
"draft",
"Tangent and normal vectors are parallel. Normal replaced by a default axis.",
)
)
n = t
onPathRotation = App.Rotation(t, n, nullv, "XYZ") # priority = "XYZ"
onPathRotation = App.Rotation(t, n, nullv, "XYZ") # priority = "XYZ"
else:
_err(translate("draft", "AlignMode {} is not implemented").format(mode))
@@ -860,6 +850,7 @@ def calculate_placement(globalRotation,
calculatePlacement = calculate_placement
def get_parameter_from_v0(edge, offset):
"""Return parameter at distance offset from edge.Vertexes[0].

View File

@@ -49,7 +49,12 @@ object in the Arch Workbench.
import draftgeoutils.geo_arrays as geo
from draftutils.messages import _log
def QT_TRANSLATE_NOOP(ctx,txt): return txt
def QT_TRANSLATE_NOOP(ctx, txt):
return txt
from draftobjects.draftlink import DraftLink
## \addtogroup draftobjects
@@ -80,73 +85,83 @@ class PathTwistedArray(DraftLink):
properties = []
if "Base" not in properties:
obj.addProperty("App::PropertyLink",
"Base",
"Objects",
QT_TRANSLATE_NOOP("App::Property","The base object that will be duplicated."),
locked=True)
obj.addProperty(
"App::PropertyLink",
"Base",
"Objects",
QT_TRANSLATE_NOOP("App::Property", "The base object that will be duplicated."),
locked=True,
)
obj.Base = None
if "PathObject" not in properties:
obj.addProperty("App::PropertyLink",
"PathObject",
"Objects",
QT_TRANSLATE_NOOP("App::Property","The object along which the copies will be distributed. It must contain 'Edges'."),
locked=True)
obj.addProperty(
"App::PropertyLink",
"PathObject",
"Objects",
QT_TRANSLATE_NOOP(
"App::Property",
"The object along which the copies will be distributed. It must contain 'Edges'.",
),
locked=True,
)
obj.PathObject = None
if "Fuse" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"Specifies if the copies "
"should be fused together "
"if they touch each other (slower)")
obj.addProperty("App::PropertyBool",
"Fuse",
"Objects",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"Specifies if the copies "
"should be fused together "
"if they touch each other (slower)",
)
obj.addProperty("App::PropertyBool", "Fuse", "Objects", _tip, locked=True)
obj.Fuse = False
if "Count" not in properties:
obj.addProperty("App::PropertyInteger",
"Count",
"Objects",
QT_TRANSLATE_NOOP("App::Property","Number of copies to create."),
locked=True)
obj.addProperty(
"App::PropertyInteger",
"Count",
"Objects",
QT_TRANSLATE_NOOP("App::Property", "Number of copies to create."),
locked=True,
)
obj.Count = 15
if "RotationFactor" not in properties:
obj.addProperty("App::PropertyFloat",
"RotationFactor",
"Objects",
QT_TRANSLATE_NOOP("App::Property","Rotation factor of the twisted array."),
locked=True)
obj.addProperty(
"App::PropertyFloat",
"RotationFactor",
"Objects",
QT_TRANSLATE_NOOP("App::Property", "Rotation factor of the twisted array."),
locked=True,
)
obj.RotationFactor = 0.25
if self.use_link and "ExpandArray" not in properties:
obj.addProperty("App::PropertyBool",
"ExpandArray",
"Objects",
QT_TRANSLATE_NOOP("App::Property","Show the individual array elements (only for Link arrays)"),
locked=True)
obj.addProperty(
"App::PropertyBool",
"ExpandArray",
"Objects",
QT_TRANSLATE_NOOP(
"App::Property", "Show the individual array elements (only for Link arrays)"
),
locked=True,
)
obj.ExpandArray = False
obj.setPropertyStatus('Shape', 'Transient')
obj.setPropertyStatus("Shape", "Transient")
if not self.use_link:
if "PlacementList" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"The placement for each array element")
obj.addProperty("App::PropertyPlacementList",
"PlacementList",
"Objects",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property", "The placement for each array element")
obj.addProperty(
"App::PropertyPlacementList", "PlacementList", "Objects", _tip, locked=True
)
obj.PlacementList = []
def linkSetup(self, obj):
"""Set up the object as a link object."""
super().linkSetup(obj)
obj.configLinkProperty(ElementCount='Count')
obj.configLinkProperty(ElementCount="Count")
def onDocumentRestored(self, obj):
super().onDocumentRestored(obj)
@@ -161,13 +176,11 @@ class PathTwistedArray(DraftLink):
_log("v1.1, " + obj.Name + ", added hidden property 'PlacementList'")
self.set_properties(obj)
self.execute(obj) # Required to update PlacementList.
self.execute(obj) # Required to update PlacementList.
def execute(self, obj):
"""Execute when the object is created or recomputed."""
if self.props_changed_placement_only(obj) \
or not obj.Base \
or not obj.PathObject:
if self.props_changed_placement_only(obj) or not obj.Base or not obj.PathObject:
self.props_changed_clear()
return
@@ -178,12 +191,11 @@ class PathTwistedArray(DraftLink):
count = obj.Count
rot_factor = obj.RotationFactor
copy_placements, _ = geo.get_twisted_placements(path,
count=count,
rot_factor=rot_factor)
copy_placements, _ = geo.get_twisted_placements(path, count=count, rot_factor=rot_factor)
self.buildShape(obj, array_placement, copy_placements)
self.props_changed_clear()
return (not self.use_link)
return not self.use_link
## @}

View File

@@ -54,7 +54,7 @@ class Point(DraftObject):
obj.Y = y
obj.Z = z
obj.setPropertyStatus('Placement', 'Hidden')
obj.setPropertyStatus("Placement", "Hidden")
def onDocumentRestored(self, obj):
super().onDocumentRestored(obj)
@@ -73,6 +73,7 @@ class Point(DraftObject):
return
import Part
obj.Shape = Part.Vertex(App.Vector(0, 0, 0))
if base != xyz_vec:
obj.Placement.Base = xyz_vec

View File

@@ -22,8 +22,7 @@
# * USA *
# * *
# ***************************************************************************
"""Provides the object code for the PointArray object.
"""
"""Provides the object code for the PointArray object."""
## @package pointarray
# \ingroup draftobjects
# \brief Provides the object code for the PointArray object.
@@ -56,7 +55,7 @@ class PointArray(DraftLink):
def linkSetup(self, obj):
"""Set up the object as a link object."""
super().linkSetup(obj)
obj.configLinkProperty(ElementCount='Count')
obj.configLinkProperty(ElementCount="Count")
def set_properties(self, obj):
"""Set properties only if they don't exist."""
@@ -64,78 +63,63 @@ class PointArray(DraftLink):
if "Base" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property", "Base object that will be duplicated")
obj.addProperty("App::PropertyLink",
"Base",
"Objects",
_tip,
locked=True)
obj.addProperty("App::PropertyLink", "Base", "Objects", _tip, locked=True)
obj.Base = None
if "PointObject" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property", "Object containing points used to distribute the copies.")
obj.addProperty("App::PropertyLink",
"PointObject",
"Objects",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property", "Object containing points used to distribute the copies."
)
obj.addProperty("App::PropertyLink", "PointObject", "Objects", _tip, locked=True)
obj.PointObject = None
if "Fuse" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"Specifies if the copies "
"should be fused together "
"if they touch each other (slower)")
obj.addProperty("App::PropertyBool",
"Fuse",
"Objects",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"Specifies if the copies "
"should be fused together "
"if they touch each other (slower)",
)
obj.addProperty("App::PropertyBool", "Fuse", "Objects", _tip, locked=True)
obj.Fuse = False
if "Count" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property", "Number of copies in the array.\nThis property is read-only, as the number depends on the points in 'Point Object'.")
obj.addProperty("App::PropertyInteger",
"Count",
"Objects",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"Number of copies in the array.\nThis property is read-only, as the number depends on the points in 'Point Object'.",
)
obj.addProperty("App::PropertyInteger", "Count", "Objects", _tip, locked=True)
obj.Count = 0
obj.setEditorMode("Count", 1) # Read only
if "ExtraPlacement" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property", "Additional placement, shift and rotation, that will be applied to each copy")
obj.addProperty("App::PropertyPlacement",
"ExtraPlacement",
"Objects",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"Additional placement, shift and rotation, that will be applied to each copy",
)
obj.addProperty(
"App::PropertyPlacement", "ExtraPlacement", "Objects", _tip, locked=True
)
obj.ExtraPlacement = App.Placement()
if self.use_link and "ExpandArray" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property", "Show the individual array elements (only for Link arrays)")
obj.addProperty("App::PropertyBool",
"ExpandArray",
"Objects",
_tip,
locked=True)
obj.setPropertyStatus('Shape', 'Transient')
_tip = QT_TRANSLATE_NOOP(
"App::Property", "Show the individual array elements (only for Link arrays)"
)
obj.addProperty("App::PropertyBool", "ExpandArray", "Objects", _tip, locked=True)
obj.setPropertyStatus("Shape", "Transient")
if not self.use_link:
if "PlacementList" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"The placement for each array element")
obj.addProperty("App::PropertyPlacementList",
"PlacementList",
"Objects",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property", "The placement for each array element")
obj.addProperty(
"App::PropertyPlacementList", "PlacementList", "Objects", _tip, locked=True
)
obj.PlacementList = []
def execute(self, obj):
"""Run when the object is created or recomputed."""
if self.props_changed_placement_only(obj) \
or not obj.Base \
or not obj.PointObject:
if self.props_changed_placement_only(obj) or not obj.Base or not obj.PointObject:
self.props_changed_clear()
return
@@ -145,7 +129,7 @@ class PointArray(DraftLink):
self.buildShape(obj, obj.Placement, pls)
self.props_changed_clear()
return (not self.use_link)
return not self.use_link
def onDocumentRestored(self, obj):
super().onDocumentRestored(obj)
@@ -167,9 +151,10 @@ class PointArray(DraftLink):
if hasattr(obj, "PointList"):
obj.PointObject = obj.PointList
obj.removeProperty("PointList")
self.execute(obj) # Required to update PlacementList.
self.execute(obj) # Required to update PlacementList.
def remove_equal_vecs (vec_list):
def remove_equal_vecs(vec_list):
"""Remove equal vectors from a list.
Parameters
@@ -189,6 +174,7 @@ def remove_equal_vecs (vec_list):
res_list.append(vec)
return res_list
def get_point_list(point_object):
"""Extract a list of points from a point object.
@@ -205,7 +191,7 @@ def get_point_list(point_object):
if hasattr(point_object, "Shape") and hasattr(point_object.Shape, "Vertexes"):
pt_list = [v.Point for v in point_object.Shape.Vertexes]
# For compatibility with previous versions: add all points from sketch (including construction geometry):
if hasattr(point_object, 'Geometry'):
if hasattr(point_object, "Geometry"):
place = point_object.Placement
for geo in point_object.Geometry:
if geo.TypeId == "Part::GeomPoint":
@@ -219,6 +205,7 @@ def get_point_list(point_object):
return remove_equal_vecs(pt_list)
def build_placements(base_object, pt_list=None, placement=App.Placement()):
"""Build a placements from the base object and list of points.
@@ -227,9 +214,12 @@ def build_placements(base_object, pt_list=None, placement=App.Placement()):
list of App.Placements
"""
if not pt_list:
_err(translate("Draft",
"Point object does not have a discrete point, "
"it cannot be used for an array"))
_err(
translate(
"Draft",
"Point object does not have a discrete point, " "it cannot be used for an array",
)
)
return []
pls = list()

View File

@@ -43,36 +43,31 @@ class Polygon(DraftObject):
def __init__(self, obj):
super().__init__(obj, "Polygon")
_tip = QT_TRANSLATE_NOOP("App::Property",
"Number of faces")
_tip = QT_TRANSLATE_NOOP("App::Property", "Number of faces")
obj.addProperty("App::PropertyInteger", "FacesNumber", "Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property",
"Radius of the control circle")
_tip = QT_TRANSLATE_NOOP("App::Property", "Radius of the control circle")
obj.addProperty("App::PropertyLength", "Radius", "Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property",
"How the polygon must be drawn from the control circle")
_tip = QT_TRANSLATE_NOOP(
"App::Property", "How the polygon must be drawn from the control circle"
)
obj.addProperty("App::PropertyEnumeration", "DrawMode", "Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property",
"Radius to use to fillet the corners")
_tip = QT_TRANSLATE_NOOP("App::Property", "Radius to use to fillet the corners")
obj.addProperty("App::PropertyLength", "FilletRadius", "Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property",
"Size of the chamfer to give to the corners")
_tip = QT_TRANSLATE_NOOP("App::Property", "Size of the chamfer to give to the corners")
obj.addProperty("App::PropertyLength", "ChamferSize", "Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property",
"Create a face")
_tip = QT_TRANSLATE_NOOP("App::Property", "Create a face")
obj.addProperty("App::PropertyBool", "MakeFace", "Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property",
"The area of this object")
_tip = QT_TRANSLATE_NOOP("App::Property", "The area of this object")
obj.addProperty("App::PropertyArea", "Area", "Draft", _tip, locked=True)
obj.MakeFace = params.get_param("MakeFaceMode")
obj.DrawMode = ['inscribed','circumscribed']
obj.DrawMode = ["inscribed", "circumscribed"]
obj.FacesNumber = 0
obj.Radius = 1
@@ -88,33 +83,30 @@ class Polygon(DraftObject):
if (obj.FacesNumber >= 3) and (obj.Radius.Value > 0):
import Part
plm = obj.Placement
angle = (math.pi * 2) / obj.FacesNumber
if obj.DrawMode == 'inscribed':
if obj.DrawMode == "inscribed":
delta = obj.Radius.Value
else:
delta = obj.Radius.Value / math.cos(angle / 2.0)
pts = [App.Vector(delta, 0, 0)]
for i in range(obj.FacesNumber - 1):
ang = (i + 1) * angle
pts.append(App.Vector(delta * math.cos(ang),
delta*math.sin(ang),
0))
pts.append(App.Vector(delta * math.cos(ang), delta * math.sin(ang), 0))
pts.append(pts[0])
shape = Part.makePolygon(pts)
if "ChamferSize" in obj.PropertiesList:
if obj.ChamferSize.Value != 0:
w = DraftGeomUtils.filletWire(shape,obj.ChamferSize.Value,
chamfer=True)
w = DraftGeomUtils.filletWire(shape, obj.ChamferSize.Value, chamfer=True)
if w:
shape = w
if "FilletRadius" in obj.PropertiesList:
if obj.FilletRadius.Value != 0:
w = DraftGeomUtils.filletWire(shape,
obj.FilletRadius.Value)
w = DraftGeomUtils.filletWire(shape, obj.FilletRadius.Value)
if w:
shape = w
if hasattr(obj,"MakeFace"):
if hasattr(obj, "MakeFace"):
if obj.MakeFace:
shape = Part.Face(shape)
else:

View File

@@ -67,10 +67,10 @@ class Rectangle(DraftObject):
obj.addProperty("App::PropertyArea", "Area", "Draft", _tip, locked=True)
obj.MakeFace = params.get_param("MakeFaceMode")
obj.Length=1
obj.Height=1
obj.Rows=1
obj.Columns=1
obj.Length = 1
obj.Height = 1
obj.Rows = 1
obj.Columns = 1
def onDocumentRestored(self, obj):
super().onDocumentRestored(obj)
@@ -95,7 +95,7 @@ class Rectangle(DraftObject):
shape = None
if hasattr(obj,"Rows") and hasattr(obj,"Columns"):
if hasattr(obj, "Rows") and hasattr(obj, "Columns"):
# TODO: verify if this is needed:
if obj.Rows > 1:
rows = obj.Rows
@@ -109,29 +109,28 @@ class Rectangle(DraftObject):
if (rows > 1) or (columns > 1):
shapes = []
l = obj.Length.Value/columns
h = obj.Height.Value/rows
l = obj.Length.Value / columns
h = obj.Height.Value / rows
for i in range(columns):
for j in range(rows):
p1 = App.Vector(i*l,j*h,0)
p2 = App.Vector(p1.x+l,p1.y,p1.z)
p3 = App.Vector(p1.x+l,p1.y+h,p1.z)
p4 = App.Vector(p1.x,p1.y+h,p1.z)
p = Part.makePolygon([p1,p2,p3,p4,p1])
p1 = App.Vector(i * l, j * h, 0)
p2 = App.Vector(p1.x + l, p1.y, p1.z)
p3 = App.Vector(p1.x + l, p1.y + h, p1.z)
p4 = App.Vector(p1.x, p1.y + h, p1.z)
p = Part.makePolygon([p1, p2, p3, p4, p1])
if "ChamferSize" in obj.PropertiesList:
if obj.ChamferSize.Value != 0:
w = DraftGeomUtils.filletWire(p,
obj.ChamferSize.Value,
chamfer=True)
w = DraftGeomUtils.filletWire(
p, obj.ChamferSize.Value, chamfer=True
)
if w:
p = w
if "FilletRadius" in obj.PropertiesList:
if obj.FilletRadius.Value != 0:
w = DraftGeomUtils.filletWire(p,
obj.FilletRadius.Value)
w = DraftGeomUtils.filletWire(p, obj.FilletRadius.Value)
if w:
p = w
if hasattr(obj,"MakeFace"):
if hasattr(obj, "MakeFace"):
if obj.MakeFace:
p = Part.Face(p)
shapes.append(p)
@@ -139,31 +138,22 @@ class Rectangle(DraftObject):
shape = Part.makeCompound(shapes)
if not shape:
p1 = App.Vector(0,0,0)
p2 = App.Vector(p1.x+obj.Length.Value,
p1.y,
p1.z)
p3 = App.Vector(p1.x+obj.Length.Value,
p1.y+obj.Height.Value,
p1.z)
p4 = App.Vector(p1.x,
p1.y+obj.Height.Value,
p1.z)
p1 = App.Vector(0, 0, 0)
p2 = App.Vector(p1.x + obj.Length.Value, p1.y, p1.z)
p3 = App.Vector(p1.x + obj.Length.Value, p1.y + obj.Height.Value, p1.z)
p4 = App.Vector(p1.x, p1.y + obj.Height.Value, p1.z)
shape = Part.makePolygon([p1, p2, p3, p4, p1])
if "ChamferSize" in obj.PropertiesList:
if obj.ChamferSize.Value != 0:
w = DraftGeomUtils.filletWire(shape,
obj.ChamferSize.Value,
chamfer=True)
w = DraftGeomUtils.filletWire(shape, obj.ChamferSize.Value, chamfer=True)
if w:
shape = w
if "FilletRadius" in obj.PropertiesList:
if obj.FilletRadius.Value != 0:
w = DraftGeomUtils.filletWire(shape,
obj.FilletRadius.Value)
w = DraftGeomUtils.filletWire(shape, obj.FilletRadius.Value)
if w:
shape = w
if hasattr(obj,"MakeFace"):
if hasattr(obj, "MakeFace"):
if obj.MakeFace:
shape = Part.Face(shape)
else:
@@ -171,7 +161,7 @@ class Rectangle(DraftObject):
obj.Shape = shape
if hasattr(obj,"Area") and hasattr(shape,"Area"):
if hasattr(obj, "Area") and hasattr(shape, "Area"):
obj.Area = shape.Area
obj.Placement = plm

View File

@@ -41,7 +41,7 @@ from draftutils.translate import translate
class Shape2DView(DraftObject):
"""The Shape2DView object"""
def __init__(self,obj):
def __init__(self, obj):
self.setProperties(obj)
super().__init__(obj, "Shape2DView")
@@ -53,101 +53,108 @@ class Shape2DView(DraftObject):
obj, vp_module="view_base", vp_class="ViewProviderDraftAlt", format=False
)
def setProperties(self,obj):
def setProperties(self, obj):
pl = obj.PropertiesList
if not "Base" in pl:
_tip = QT_TRANSLATE_NOOP("App::Property",
"The base object this 2D view must represent")
obj.addProperty("App::PropertyLink", "Base",
"Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property", "The base object this 2D view must represent")
obj.addProperty("App::PropertyLink", "Base", "Draft", _tip, locked=True)
if not "Projection" in pl:
_tip = QT_TRANSLATE_NOOP("App::Property",
"The projection vector of this object")
obj.addProperty("App::PropertyVector", "Projection",
"Draft", _tip, locked=True)
obj.Projection = App.Vector(0,0,1)
_tip = QT_TRANSLATE_NOOP("App::Property", "The projection vector of this object")
obj.addProperty("App::PropertyVector", "Projection", "Draft", _tip, locked=True)
obj.Projection = App.Vector(0, 0, 1)
if not "ProjectionMode" in pl:
_tip = QT_TRANSLATE_NOOP("App::Property",
"The way the viewed object must be projected")
obj.addProperty("App::PropertyEnumeration", "ProjectionMode",
"Draft", _tip, locked=True)
obj.ProjectionMode = ["Solid", "Individual Faces",
"Cutlines", "Cutfaces","Solid faces"]
_tip = QT_TRANSLATE_NOOP("App::Property", "The way the viewed object must be projected")
obj.addProperty(
"App::PropertyEnumeration", "ProjectionMode", "Draft", _tip, locked=True
)
obj.ProjectionMode = [
"Solid",
"Individual Faces",
"Cutlines",
"Cutfaces",
"Solid faces",
]
if not "FaceNumbers" in pl:
_tip = QT_TRANSLATE_NOOP("App::Property",
"The indices of the faces to be projected in Individual Faces mode")
obj.addProperty("App::PropertyIntegerList", "FaceNumbers",
"Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property", "The indices of the faces to be projected in Individual Faces mode"
)
obj.addProperty("App::PropertyIntegerList", "FaceNumbers", "Draft", _tip, locked=True)
if not "HiddenLines" in pl:
_tip = QT_TRANSLATE_NOOP("App::Property",
"Show hidden lines")
obj.addProperty("App::PropertyBool", "HiddenLines",
"Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property", "Show hidden lines")
obj.addProperty("App::PropertyBool", "HiddenLines", "Draft", _tip, locked=True)
obj.HiddenLines = False
if not "FuseArch" in pl:
_tip = QT_TRANSLATE_NOOP("App::Property",
"Fuse wall and structure objects of same type and material")
obj.addProperty("App::PropertyBool", "FuseArch",
"Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property", "Fuse wall and structure objects of same type and material"
)
obj.addProperty("App::PropertyBool", "FuseArch", "Draft", _tip, locked=True)
if not "Tessellation" in pl:
_tip = QT_TRANSLATE_NOOP("App::Property",
"Tessellate Ellipses and B-splines into line segments")
obj.addProperty("App::PropertyBool", "Tessellation",
"Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property", "Tessellate Ellipses and B-splines into line segments"
)
obj.addProperty("App::PropertyBool", "Tessellation", "Draft", _tip, locked=True)
obj.Tessellation = False
if not "InPlace" in pl:
_tip = QT_TRANSLATE_NOOP("App::Property",
"For Cutlines and Cutfaces modes, this leaves the faces at the cut location")
obj.addProperty("App::PropertyBool", "InPlace",
"Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"For Cutlines and Cutfaces modes, this leaves the faces at the cut location",
)
obj.addProperty("App::PropertyBool", "InPlace", "Draft", _tip, locked=True)
obj.InPlace = True
if not "SegmentLength" in pl:
_tip = QT_TRANSLATE_NOOP("App::Property",
"Length of line segments if tessellating Ellipses or B-splines into line segments")
obj.addProperty("App::PropertyFloat", "SegmentLength",
"Draft", _tip, locked=True)
obj.SegmentLength = .05
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"Length of line segments if tessellating Ellipses or B-splines into line segments",
)
obj.addProperty("App::PropertyFloat", "SegmentLength", "Draft", _tip, locked=True)
obj.SegmentLength = 0.05
if not "VisibleOnly" in pl:
_tip = QT_TRANSLATE_NOOP("App::Property",
"If this is True, this object will include only visible objects")
obj.addProperty("App::PropertyBool", "VisibleOnly",
"Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property", "If this is True, this object will include only visible objects"
)
obj.addProperty("App::PropertyBool", "VisibleOnly", "Draft", _tip, locked=True)
obj.VisibleOnly = False
if not "ExclusionPoints" in pl:
_tip = QT_TRANSLATE_NOOP("App::Property",
"A list of exclusion points. Any edge touching any of those points will not be drawn.")
obj.addProperty("App::PropertyVectorList", "ExclusionPoints",
"Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"A list of exclusion points. Any edge touching any of those points will not be drawn.",
)
obj.addProperty(
"App::PropertyVectorList", "ExclusionPoints", "Draft", _tip, locked=True
)
if not "ExclusionNames" in pl:
_tip = QT_TRANSLATE_NOOP("App::Property",
"A list of exclusion object names. Any object viewed that matches a name from the list will not be drawn.")
obj.addProperty("App::PropertyStringList", "ExclusionNames",
"Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"A list of exclusion object names. Any object viewed that matches a name from the list will not be drawn.",
)
obj.addProperty("App::PropertyStringList", "ExclusionNames", "Draft", _tip, locked=True)
if not "OnlySolids" in pl:
_tip = QT_TRANSLATE_NOOP("App::Property",
"If this is True, only solid geometry is handled. This overrides the base object's Only Solids property")
obj.addProperty("App::PropertyBool", "OnlySolids",
"Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"If this is True, only solid geometry is handled. This overrides the base object's Only Solids property",
)
obj.addProperty("App::PropertyBool", "OnlySolids", "Draft", _tip, locked=True)
if not "Clip" in pl:
_tip = QT_TRANSLATE_NOOP("App::Property",
"If this is True, the contents are clipped to the borders of the section plane, if applicable. This overrides the base object's Clip property")
obj.addProperty("App::PropertyBool", "Clip",
"Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"If this is True, the contents are clipped to the borders of the section plane, if applicable. This overrides the base object's Clip property",
)
obj.addProperty("App::PropertyBool", "Clip", "Draft", _tip, locked=True)
if not "AutoUpdate" in pl:
_tip = QT_TRANSLATE_NOOP("App::Property",
"This object will be recomputed only if this is True.")
obj.addProperty("App::PropertyBool", "AutoUpdate",
"Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property", "This object will be recomputed only if this is True."
)
obj.addProperty("App::PropertyBool", "AutoUpdate", "Draft", _tip, locked=True)
obj.AutoUpdate = True
def getProjected(self,obj,shape,direction):
def getProjected(self, obj, shape, direction):
"returns projected edges from a shape and a direction"
import Part
import TechDraw
import DraftGeomUtils
edges = []
_groups = TechDraw.projectEx(shape, direction)
for g in _groups[0:5]:
@@ -157,22 +164,22 @@ class Shape2DView(DraftObject):
for g in _groups[5:]:
if not g.isNull():
edges.append(g)
edges = self.cleanExcluded(obj,edges)
edges = self.cleanExcluded(obj, edges)
if getattr(obj, "Tessellation", False):
return DraftGeomUtils.cleanProjection(Part.makeCompound(edges),
obj.Tessellation,
obj.SegmentLength)
return DraftGeomUtils.cleanProjection(
Part.makeCompound(edges), obj.Tessellation, obj.SegmentLength
)
else:
return Part.makeCompound(edges)
def cleanExcluded(self,obj,shapes):
def cleanExcluded(self, obj, shapes):
"""removes any edge touching exclusion points"""
import Part
MAXDIST = 0.0001
if (not hasattr(obj,"ExclusionPoints")) or (not obj.ExclusionPoints):
if (not hasattr(obj, "ExclusionPoints")) or (not obj.ExclusionPoints):
return shapes
#verts = [Part.Vertex(obj.Placement.multVec(p)) for p in obj.ExclusionPoints]
# verts = [Part.Vertex(obj.Placement.multVec(p)) for p in obj.ExclusionPoints]
verts = [Part.Vertex(p) for p in obj.ExclusionPoints]
nedges = []
for s in shapes:
@@ -183,14 +190,16 @@ class Shape2DView(DraftObject):
if d and (d[0] <= MAXDIST):
break
except RuntimeError:
print("FIXME: shape2dview: distance unavailable for edge",e,"in",obj.Label)
print(
"FIXME: shape2dview: distance unavailable for edge", e, "in", obj.Label
)
else:
nedges.append(e)
return nedges
def excludeNames(self,obj,objs):
if hasattr(obj,"ExclusionNames"):
objs = [o for o in objs if not(o.Name in obj.ExclusionNames)]
def excludeNames(self, obj, objs):
if hasattr(obj, "ExclusionNames"):
objs = [o for o in objs if not (o.Name in obj.ExclusionNames)]
return objs
def _get_shapes(self, shape, onlysolids=False):
@@ -203,39 +212,39 @@ class Shape2DView(DraftObject):
return [shape.copy()]
def execute(self, obj):
if self.props_changed_placement_only(obj) \
or not getattr(obj, "AutoUpdate", True):
if self.props_changed_placement_only(obj) or not getattr(obj, "AutoUpdate", True):
obj.positionBySupport()
self.props_changed_clear()
return
import Part
import DraftGeomUtils
pl = obj.Placement
if obj.Base:
if utils.get_type(obj.Base) in ["BuildingPart","SectionPlane","IfcAnnotation"]:
if utils.get_type(obj.Base) in ["BuildingPart", "SectionPlane", "IfcAnnotation"]:
objs = []
if utils.get_type(obj.Base) == "SectionPlane":
objs = self.excludeNames(obj,obj.Base.Objects)
objs = self.excludeNames(obj, obj.Base.Objects)
cutplane = obj.Base.Shape
elif utils.get_type(obj.Base) == "IfcAnnotation":
# this is a NativeIFC section plane
objs, cutplane = obj.Base.Proxy.get_section_data(obj.Base)
objs = self.excludeNames(obj, objs)
else:
objs = self.excludeNames(obj,obj.Base.Group)
objs = self.excludeNames(obj, obj.Base.Group)
cutplane = Part.makePlane(1000, 1000, App.Vector(-500, -500, 0))
m = 1
if obj.Base.ViewObject and hasattr(obj.Base.ViewObject,"CutMargin"):
if obj.Base.ViewObject and hasattr(obj.Base.ViewObject, "CutMargin"):
m = obj.Base.ViewObject.CutMargin.Value
cutplane.translate(App.Vector(0,0,m))
cutplane.translate(App.Vector(0, 0, m))
cutplane.Placement = cutplane.Placement.multiply(obj.Base.Placement)
if objs:
onlysolids = True
# TODO Fix this : 2025.1.26, why test obj.Base.OnlySolids if override by obj.OnlySolids
if hasattr(obj.Base,"OnlySolids"):
if hasattr(obj.Base, "OnlySolids"):
onlysolids = obj.Base.OnlySolids
if hasattr(obj,"OnlySolids"): # override base object
if hasattr(obj, "OnlySolids"): # override base object
onlysolids = obj.OnlySolids
try:
import Arch
@@ -243,17 +252,20 @@ class Shape2DView(DraftObject):
print("Shape2DView: BIM not present, unable to recompute")
return
objs = groups.get_group_contents(objs, walls=True)
if getattr(obj,"VisibleOnly",True):
if getattr(obj, "VisibleOnly", True):
objs = gui_utils.remove_hidden(objs)
shapes = []
if getattr(obj,"FuseArch", False):
if getattr(obj, "FuseArch", False):
shtypes = {}
for o in objs:
if utils.get_type(o) in ["Wall","Structure"]:
if utils.get_type(o) in ["Wall", "Structure"]:
shtypes.setdefault(
o.Material.Name
if (hasattr(o,"Material") and o.Material) else "None",
[]
(
o.Material.Name
if (hasattr(o, "Material") and o.Material)
else "None"
),
[],
).extend(self._get_shapes(o.Shape, onlysolids))
elif hasattr(o, "Shape"):
shapes.extend(self._get_shapes(o.Shape, onlysolids))
@@ -281,18 +293,18 @@ class Shape2DView(DraftObject):
shapes.extend(self._get_shapes(o.Shape, onlysolids))
clip = False
# TODO Fix this : 2025.1.26, why test obj.Base.Clip if override by obj.Clip
if hasattr(obj.Base,"Clip"):
if hasattr(obj.Base, "Clip"):
clip = obj.Base.Clip
if hasattr(obj,"Clip"): #override base object
if hasattr(obj, "Clip"): # override base object
clip = obj.Clip
depth = None
if hasattr(obj.Base,"Depth"):
if hasattr(obj.Base, "Depth"):
depth = obj.Base.Depth.Value
cutp, cutv, iv = Arch.getCutVolume(cutplane, shapes, clip, depth)
cuts = []
opl = App.Placement(obj.Base.Placement)
proj = opl.Rotation.multVec(App.Vector(0, 0, 1))
if obj.ProjectionMode in ["Solid","Solid faces"]:
if obj.ProjectionMode in ["Solid", "Solid faces"]:
shapes_to_cut = shapes
if obj.ProjectionMode == "Solid faces":
shapes_to_cut = []
@@ -302,9 +314,9 @@ class Shape2DView(DraftObject):
if cutv and (not cutv.isNull()) and (not sh.isNull()):
if sh.Volume < 0:
sh.reverse()
#if cutv.BoundBox.intersect(sh.BoundBox):
# if cutv.BoundBox.intersect(sh.BoundBox):
# c = sh.cut(cutv)
#else:
# else:
# c = sh.copy()
try:
c = sh.cut(cutv)
@@ -316,7 +328,7 @@ class Shape2DView(DraftObject):
else:
cuts.extend(self._get_shapes(sh, onlysolids))
comp = Part.makeCompound(cuts)
obj.Shape = self.getProjected(obj,comp,proj)
obj.Shape = self.getProjected(obj, comp, proj)
elif obj.ProjectionMode in ["Cutlines", "Cutfaces"]:
if not cutp: # Cutfaces and Cutlines needs cutp
obj.Shape = Part.Shape()
@@ -332,7 +344,7 @@ class Shape2DView(DraftObject):
facesOrg = sc.Faces
if not facesOrg:
continue
if hasattr(obj,"InPlace"):
if hasattr(obj, "InPlace"):
if obj.InPlace:
faces = facesOrg
# Alternative approach in https://forum.freecad.org/viewtopic.php?p=807314#p807314, not adopted
@@ -340,7 +352,7 @@ class Shape2DView(DraftObject):
for faceOrg in facesOrg:
if len(faceOrg.Wires) == 1:
wireProj = self.getProjected(obj, faceOrg, proj)
#return Compound
# return Compound
wireProjWire = Part.Wire(wireProj.Edges)
faceProj = Part.Face(wireProjWire)
elif len(faceOrg.Wires) == 2:
@@ -349,22 +361,28 @@ class Shape2DView(DraftObject):
if not w.isEqual(wireClosedOuter):
wireClosedInner = w
break
wireProjOuter = self.getProjected(obj, wireClosedOuter, proj)
#return Compound
wireProjOuter = self.getProjected(
obj, wireClosedOuter, proj
)
# return Compound
wireProjOuterWire = Part.Wire(wireProjOuter.Edges)
faceProj = Part.Face(wireProjOuterWire)
wireProjInner = self.getProjected(obj, wireClosedInner, proj)
#return Compound
wireProjInner = self.getProjected(
obj, wireClosedInner, proj
)
# return Compound
wireProjInnerWire = Part.Wire(wireProjInner.Edges)
faceProj.cutHoles([wireProjInnerWire]) # (list of wires)
faceProj.cutHoles(
[wireProjInnerWire]
) # (list of wires)
faces.append(faceProj)
else:
c = sh.section(cutp)
if hasattr(obj,"InPlace"):
if hasattr(obj, "InPlace"):
if not obj.InPlace:
c = self.getProjected(obj, c, proj)
#faces = []
#if (obj.ProjectionMode == "Cutfaces") and (sh.ShapeType == "Solid"):
# faces = []
# if (obj.ProjectionMode == "Cutfaces") and (sh.ShapeType == "Solid"):
# wires = DraftGeomUtils.findWires(c.Edges)
# for w in wires:
# if w.isClosed():
@@ -381,21 +399,23 @@ class Shape2DView(DraftObject):
elif obj.Base.isDerivedFrom("App::DocumentObjectGroup"):
shapes = []
objs = self.excludeNames(obj,groups.get_group_contents(obj.Base))
objs = self.excludeNames(obj, groups.get_group_contents(obj.Base))
for o in objs:
if hasattr(o, "Shape"):
shapes.extend(self._get_shapes(o.Shape))
if shapes:
import Part
comp = Part.makeCompound(shapes)
obj.Shape = self.getProjected(obj,comp,obj.Projection)
obj.Shape = self.getProjected(obj, comp, obj.Projection)
elif hasattr(obj.Base, "Shape"):
if not DraftVecUtils.isNull(obj.Projection):
if obj.ProjectionMode == "Solid":
obj.Shape = self.getProjected(obj,obj.Base.Shape,obj.Projection)
obj.Shape = self.getProjected(obj, obj.Base.Shape, obj.Projection)
elif obj.ProjectionMode == "Individual Faces":
import Part
if obj.FaceNumbers:
faces = []
for i in obj.FaceNumbers:
@@ -403,11 +423,11 @@ class Shape2DView(DraftObject):
faces.append(obj.Base.Shape.Faces[i])
views = []
for f in faces:
views.append(self.getProjected(obj,f,obj.Projection))
views.append(self.getProjected(obj, f, obj.Projection))
if views:
obj.Shape = Part.makeCompound(views)
else:
App.Console.PrintWarning(obj.ProjectionMode+" mode not implemented\n")
App.Console.PrintWarning(obj.ProjectionMode + " mode not implemented\n")
obj.Placement = pl
obj.positionBySupport()

View File

@@ -66,24 +66,41 @@ class ShapeString(DraftObject):
if "Justification" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property", "Horizontal and vertical alignment")
obj.addProperty("App::PropertyEnumeration", "Justification", "Draft", _tip, locked=True)
obj.Justification = ["Top-Left", "Top-Center", "Top-Right",
"Middle-Left", "Middle-Center", "Middle-Right",
"Bottom-Left", "Bottom-Center", "Bottom-Right"]
obj.Justification = [
"Top-Left",
"Top-Center",
"Top-Right",
"Middle-Left",
"Middle-Center",
"Middle-Right",
"Bottom-Left",
"Bottom-Center",
"Bottom-Right",
]
obj.Justification = "Bottom-Left"
if "JustificationReference" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property", "Height reference used for justification")
obj.addProperty("App::PropertyEnumeration", "JustificationReference", "Draft", _tip, locked=True)
obj.addProperty(
"App::PropertyEnumeration", "JustificationReference", "Draft", _tip, locked=True
)
obj.JustificationReference = ["Cap Height", "Shape Height"]
obj.JustificationReference = "Cap Height"
if "KeepLeftMargin" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property", "Keep left margin and leading white space when justification is left")
obj.addProperty("App::PropertyBool", "KeepLeftMargin", "Draft", _tip, locked=True).KeepLeftMargin = False
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"Keep left margin and leading white space when justification is left",
)
obj.addProperty(
"App::PropertyBool", "KeepLeftMargin", "Draft", _tip, locked=True
).KeepLeftMargin = False
if "ScaleToSize" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property", "Scale to ensure cap height is equal to size")
obj.addProperty("App::PropertyBool", "ScaleToSize", "Draft", _tip, locked=True).ScaleToSize = True
obj.addProperty(
"App::PropertyBool", "ScaleToSize", "Draft", _tip, locked=True
).ScaleToSize = True
if "Tracking" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property", "Inter-character spacing")
@@ -95,10 +112,15 @@ class ShapeString(DraftObject):
if "MakeFace" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property", "Fill letters with faces")
obj.addProperty("App::PropertyBool", "MakeFace", "Draft", _tip, locked=True).MakeFace = True
obj.addProperty(
"App::PropertyBool", "MakeFace", "Draft", _tip, locked=True
).MakeFace = True
if "Fuse" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property", "Fuse faces if faces overlap, usually not required (can be very slow)")
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"Fuse faces if faces overlap, usually not required (can be very slow)",
)
obj.addProperty("App::PropertyBool", "Fuse", "Draft", _tip, locked=True).Fuse = False
def onDocumentRestored(self, obj):
@@ -106,12 +128,12 @@ class ShapeString(DraftObject):
gui_utils.restore_view_object(
obj, vp_module="view_shapestring", vp_class="ViewProviderShapeString"
)
if not hasattr(obj, "ObliqueAngle"): # several more properties were added
if not hasattr(obj, "ObliqueAngle"): # several more properties were added
self.update_properties_1v0(obj)
def update_properties_1v0(self, obj):
"""Update view properties."""
old_tracking = obj.Tracking # no need for obj.getTypeIdOfProperty("Tracking")
old_tracking = obj.Tracking # no need for obj.getTypeIdOfProperty("Tracking")
obj.removeProperty("Tracking")
self.set_properties(obj)
obj.KeepLeftMargin = True
@@ -123,13 +145,11 @@ class ShapeString(DraftObject):
+ ", "
+ "added 'Fuse', 'Justification', 'JustificationReference', 'KeepLeftMargin', "
+ "'ObliqueAngle' and 'ScaleToSize' properties"
)
)
_log("v1.0, " + obj.Name + ", changed 'Tracking' property type")
def execute(self, obj):
if self.props_changed_placement_only() \
or not obj.String \
or not obj.FontFile:
if self.props_changed_placement_only() or not obj.String or not obj.FontFile:
obj.positionBySupport()
self.props_changed_clear()
return
@@ -174,10 +194,11 @@ class ShapeString(DraftObject):
# https://github.com/FreeCAD/FreeCAD/issues/21501
char_comp = Part.Compound(char)
factor = 1 / char_comp.BoundBox.YLength
fill = sum([shape.Area for shape in shapes]) > (0.03 / factor ** 2) \
and math.isclose(char_comp.BoundBox.DiagonalLength,
Part.Compound(shapes).BoundBox.DiagonalLength,
rel_tol=1e-7)
fill = sum([shape.Area for shape in shapes]) > (0.03 / factor**2) and math.isclose(
char_comp.BoundBox.DiagonalLength,
Part.Compound(shapes).BoundBox.DiagonalLength,
rel_tol=1e-7,
)
chars = Part.makeWireString(obj.String, font_file, obj.Size, obj.Tracking)
shapes = []
@@ -208,13 +229,21 @@ class ShapeString(DraftObject):
mtx.A12 = math.tan(math.radians(obj.ObliqueAngle))
ss_shape = ss_shape.transformGeometry(mtx)
else:
wrn = translate("draft", "ShapeString: oblique angle must be in the -80 to +80 degree range") + "\n"
wrn = (
translate(
"draft",
"ShapeString: oblique angle must be in the -80 to +80 degree range",
)
+ "\n"
)
App.Console.PrintWarning(wrn)
just_vec = self.justification_vector(ss_shape,
cap_height,
obj.Justification,
obj.JustificationReference,
obj.KeepLeftMargin)
just_vec = self.justification_vector(
ss_shape,
cap_height,
obj.Justification,
obj.JustificationReference,
obj.KeepLeftMargin,
)
shapes = ss_shape.SubShapes
for shape in shapes:
shape.translate(just_vec)
@@ -229,13 +258,17 @@ class ShapeString(DraftObject):
def onChanged(self, obj, prop):
self.props_changed_store(prop)
def justification_vector(self, ss_shape, cap_height, just, just_ref, keep_left_margin): # ss_shape is a compound
def justification_vector(
self, ss_shape, cap_height, just, just_ref, keep_left_margin
): # ss_shape is a compound
box = ss_shape.optimalBoundingBox()
if keep_left_margin is True and "Left" in just:
vec = App.Vector(0, 0, 0)
else:
vec = App.Vector(-box.XMin, 0, 0) # remove left margin caused by kerning and white space characters
width = box.XLength
vec = App.Vector(
-box.XMin, 0, 0
) # remove left margin caused by kerning and white space characters
width = box.XLength
if "Shape" in just_ref:
vec = vec + App.Vector(0, -box.YMin, 0)
height = box.YLength
@@ -244,11 +277,11 @@ class ShapeString(DraftObject):
if "Top" in just:
vec = vec + App.Vector(0, -height, 0)
elif "Middle" in just:
vec = vec + App.Vector(0, -height/2, 0)
vec = vec + App.Vector(0, -height / 2, 0)
if "Right" in just:
vec = vec + App.Vector(-width, 0, 0)
elif "Center" in just:
vec = vec + App.Vector(-width/2, 0, 0)
vec = vec + App.Vector(-width / 2, 0, 0)
return vec
def make_faces(self, wireChar):
@@ -307,7 +340,7 @@ class ShapeString(DraftObject):
for face in faces:
try:
# some fonts fail here
if face.normalAt(0, 0).z < 0: # Does not seem to occur for FaceMakerBullseye.
if face.normalAt(0, 0).z < 0: # Does not seem to occur for FaceMakerBullseye.
face.reverse()
except Exception:
pass

View File

@@ -49,30 +49,24 @@ class Text(DraftAnnotation):
properties = obj.PropertiesList
if "Placement" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"The placement of the base point "
"of the first line")
obj.addProperty("App::PropertyPlacement",
"Placement",
"Base",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property", "The placement of the base point " "of the first line"
)
obj.addProperty("App::PropertyPlacement", "Placement", "Base", _tip, locked=True)
obj.Placement = App.Placement()
if "Text" not in properties:
_tip = QT_TRANSLATE_NOOP("App::Property",
"The text displayed by this object.\n"
"It is a list of strings; each element "
"in the list will be displayed "
"in its own line.")
obj.addProperty("App::PropertyStringList",
"Text",
"Base",
_tip,
locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property",
"The text displayed by this object.\n"
"It is a list of strings; each element "
"in the list will be displayed "
"in its own line.",
)
obj.addProperty("App::PropertyStringList", "Text", "Base", _tip, locked=True)
obj.Text = []
def onDocumentRestored(self,obj):
def onDocumentRestored(self, obj):
"""Execute code when the document is restored."""
super().onDocumentRestored(obj)
gui_utils.restore_view_object(obj, vp_module="view_text", vp_class="ViewProviderText")

View File

@@ -45,53 +45,45 @@ class Wire(DraftObject):
def __init__(self, obj):
super().__init__(obj, "Wire")
_tip = QT_TRANSLATE_NOOP("App::Property",
"The vertices of the wire")
obj.addProperty("App::PropertyVectorList","Points", "Draft",_tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property", "The vertices of the wire")
obj.addProperty("App::PropertyVectorList", "Points", "Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property",
"If the wire is closed or not")
obj.addProperty("App::PropertyBool","Closed", "Draft",_tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property", "If the wire is closed or not")
obj.addProperty("App::PropertyBool", "Closed", "Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property",
"The base object is the wire, it's formed from 2 objects")
obj.addProperty("App::PropertyLink","Base", "Draft",_tip, locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property", "The base object is the wire, it's formed from 2 objects"
)
obj.addProperty("App::PropertyLink", "Base", "Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property",
"The tool object is the wire, it's formed from 2 objects")
obj.addProperty("App::PropertyLink","Tool", "Draft",_tip, locked=True)
_tip = QT_TRANSLATE_NOOP(
"App::Property", "The tool object is the wire, it's formed from 2 objects"
)
obj.addProperty("App::PropertyLink", "Tool", "Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property",
"The start point of this line")
obj.addProperty("App::PropertyVectorDistance","Start", "Draft",_tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property", "The start point of this line")
obj.addProperty("App::PropertyVectorDistance", "Start", "Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property",
"The end point of this line")
obj.addProperty("App::PropertyVectorDistance","End", "Draft",_tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property", "The end point of this line")
obj.addProperty("App::PropertyVectorDistance", "End", "Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property",
"The length of this line")
obj.addProperty("App::PropertyLength","Length", "Draft",_tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property", "The length of this line")
obj.addProperty("App::PropertyLength", "Length", "Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property",
"Radius to use to fillet the corners")
obj.addProperty("App::PropertyLength","FilletRadius", "Draft",_tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property", "Radius to use to fillet the corners")
obj.addProperty("App::PropertyLength", "FilletRadius", "Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property",
"Size of the chamfer to give to the corners")
obj.addProperty("App::PropertyLength","ChamferSize", "Draft",_tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property", "Size of the chamfer to give to the corners")
obj.addProperty("App::PropertyLength", "ChamferSize", "Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property",
"Create a face if this object is closed")
obj.addProperty("App::PropertyBool","MakeFace", "Draft",_tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property", "Create a face if this object is closed")
obj.addProperty("App::PropertyBool", "MakeFace", "Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property",
"The number of subdivisions of each edge")
obj.addProperty("App::PropertyInteger","Subdivisions", "Draft",_tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property", "The number of subdivisions of each edge")
obj.addProperty("App::PropertyInteger", "Subdivisions", "Draft", _tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property",
"The area of this object")
obj.addProperty("App::PropertyArea","Area", "Draft",_tip, locked=True)
_tip = QT_TRANSLATE_NOOP("App::Property", "The area of this object")
obj.addProperty("App::PropertyArea", "Area", "Draft", _tip, locked=True)
obj.MakeFace = params.get_param("MakeFaceMode")
obj.Closed = False
@@ -126,23 +118,26 @@ class Wire(DraftObject):
_log("v1.1, " + obj.Name + ", migrated view properties")
def execute(self, obj):
if self.props_changed_placement_only(obj): # Supplying obj is required because of `Base` and `Tool`.
if self.props_changed_placement_only(
obj
): # Supplying obj is required because of `Base` and `Tool`.
obj.positionBySupport()
self.update_start_end(obj)
self.props_changed_clear()
return
import Part
plm = obj.Placement
if obj.Base and (not obj.Tool):
if obj.Base.isDerivedFrom("Sketcher::SketchObject"):
shape = obj.Base.Shape.copy()
if obj.Base.Shape.isClosed():
if getattr(obj,"MakeFace",True):
if getattr(obj, "MakeFace", True):
shape = Part.Face(shape)
obj.Shape = shape
elif obj.Base and obj.Tool:
if hasattr(obj.Base,'Shape') and hasattr(obj.Tool,'Shape'):
if hasattr(obj.Base, "Shape") and hasattr(obj.Tool, "Shape"):
if (not obj.Base.Shape.isNull()) and (not obj.Tool.Shape.isNull()):
sh1 = obj.Base.Shape.copy()
sh2 = obj.Tool.Shape.copy()
@@ -151,41 +146,44 @@ class Wire(DraftObject):
shape = DraftGeomUtils.concatenate(shape)
obj.Shape = shape
p = []
for v in shape.Vertexes: p.append(v.Point)
if obj.Points != p: obj.Points = p
for v in shape.Vertexes:
p.append(v.Point)
if obj.Points != p:
obj.Points = p
elif obj.Points:
if obj.Points[0] == obj.Points[-1]:
if not obj.Closed: obj.Closed = True
if not obj.Closed:
obj.Closed = True
obj.Points.pop()
if obj.Closed and (len(obj.Points) > 2):
pts = obj.Points
if getattr(obj,"Subdivisions",0) > 0:
if getattr(obj, "Subdivisions", 0) > 0:
npts = []
for i in range(len(pts)):
p1 = pts[i]
npts.append(pts[i])
if i == len(pts)-1:
if i == len(pts) - 1:
p2 = pts[0]
else:
p2 = pts[i+1]
p2 = pts[i + 1]
v = p2.sub(p1)
v = DraftVecUtils.scaleTo(v,v.Length/(obj.Subdivisions+1))
v = DraftVecUtils.scaleTo(v, v.Length / (obj.Subdivisions + 1))
for j in range(obj.Subdivisions):
npts.append(p1.add(App.Vector(v).multiply(j+1)))
npts.append(p1.add(App.Vector(v).multiply(j + 1)))
pts = npts
shape = Part.makePolygon(pts+[pts[0]])
shape = Part.makePolygon(pts + [pts[0]])
if "ChamferSize" in obj.PropertiesList:
if obj.ChamferSize.Value != 0:
w = DraftGeomUtils.filletWire(shape,obj.ChamferSize.Value,chamfer=True)
w = DraftGeomUtils.filletWire(shape, obj.ChamferSize.Value, chamfer=True)
if w:
shape = w
if "FilletRadius" in obj.PropertiesList:
if obj.FilletRadius.Value != 0:
w = DraftGeomUtils.filletWire(shape,obj.FilletRadius.Value)
w = DraftGeomUtils.filletWire(shape, obj.FilletRadius.Value)
if w:
shape = w
try:
if getattr(obj,"MakeFace",True):
if getattr(obj, "MakeFace", True):
shape = Part.Face(shape)
except Part.OCCError:
pass
@@ -194,18 +192,18 @@ class Wire(DraftObject):
pts = obj.Points[1:]
lp = obj.Points[0]
for p in pts:
if not DraftVecUtils.equals(lp,p):
if getattr(obj,"Subdivisions",0) > 0:
if not DraftVecUtils.equals(lp, p):
if getattr(obj, "Subdivisions", 0) > 0:
npts = []
v = p.sub(lp)
v = DraftVecUtils.scaleTo(v,v.Length/(obj.Subdivisions+1))
edges.append(Part.LineSegment(lp,lp.add(v)).toShape())
v = DraftVecUtils.scaleTo(v, v.Length / (obj.Subdivisions + 1))
edges.append(Part.LineSegment(lp, lp.add(v)).toShape())
lv = lp.add(v)
for j in range(obj.Subdivisions):
edges.append(Part.LineSegment(lv,lv.add(v)).toShape())
edges.append(Part.LineSegment(lv, lv.add(v)).toShape())
lv = lv.add(v)
else:
edges.append(Part.LineSegment(lp,p).toShape())
edges.append(Part.LineSegment(lp, p).toShape())
lp = p
try:
shape = Part.Wire(edges)
@@ -214,19 +212,19 @@ class Wire(DraftObject):
shape = None
if "ChamferSize" in obj.PropertiesList:
if obj.ChamferSize.Value != 0:
w = DraftGeomUtils.filletWire(shape,obj.ChamferSize.Value,chamfer=True)
w = DraftGeomUtils.filletWire(shape, obj.ChamferSize.Value, chamfer=True)
if w:
shape = w
if "FilletRadius" in obj.PropertiesList:
if obj.FilletRadius.Value != 0:
w = DraftGeomUtils.filletWire(shape,obj.FilletRadius.Value)
w = DraftGeomUtils.filletWire(shape, obj.FilletRadius.Value)
if w:
shape = w
if shape:
obj.Shape = shape
if hasattr(obj,"Area") and hasattr(shape,"Area"):
if hasattr(obj, "Area") and hasattr(shape, "Area"):
obj.Area = shape.Area
if hasattr(obj,"Length"):
if hasattr(obj, "Length"):
obj.Length = shape.Length
obj.Placement = plm

View File

@@ -36,13 +36,13 @@ from draftutils import gui_utils
class WorkingPlaneProxy:
"""The Draft working plane proxy object"""
def __init__(self,obj):
def __init__(self, obj):
obj.Proxy = self
_tip = QT_TRANSLATE_NOOP("App::Property", "The placement of this object")
obj.addProperty("App::PropertyPlacement", "Placement", "Base", _tip, locked=True)
obj.addProperty("Part::PropertyPartShape","Shape","Base","", locked=True)
obj.addProperty("Part::PropertyPartShape", "Shape", "Base", "", locked=True)
obj.addExtension("Part::AttachExtensionPython")
obj.changeAttacherType("Attacher::AttachEnginePlane")
@@ -54,33 +54,32 @@ class WorkingPlaneProxy:
obj, vp_module="view_wpproxy", vp_class="ViewProviderWorkingPlaneProxy", format=False
)
def execute(self,obj):
def execute(self, obj):
import Part
l = 1
if obj.ViewObject:
if hasattr(obj.ViewObject,"DisplaySize"):
if hasattr(obj.ViewObject, "DisplaySize"):
l = obj.ViewObject.DisplaySize.Value
p = Part.makePlane(l,
l,
App.Vector(l/2, -l/2, 0),
App.Vector(0, 0, -1))
p = Part.makePlane(l, l, App.Vector(l / 2, -l / 2, 0), App.Vector(0, 0, -1))
# make sure the normal direction is pointing outwards, you never know what OCC will decide...
if p.normalAt(0,0).getAngle(obj.Placement.Rotation.multVec(App.Vector(0,0,1))) > 1:
if p.normalAt(0, 0).getAngle(obj.Placement.Rotation.multVec(App.Vector(0, 0, 1))) > 1:
p.reverse()
p.Placement = obj.Placement
obj.Shape = p
def onChanged(self,obj,prop):
def onChanged(self, obj, prop):
pass
def getNormal(self,obj):
return obj.Shape.Faces[0].normalAt(0,0)
def getNormal(self, obj):
return obj.Shape.Faces[0].normalAt(0, 0)
def dumps(self):
return self.Type
def loads(self,state):
def loads(self, state):
if state:
self.Type = state
## @}