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:
@@ -63,52 +63,65 @@ def array(objectslist, arg1, arg2, arg3, arg4=None, arg5=None, arg6=None):
|
||||
if arg6:
|
||||
rectArray2(objectslist, arg1, arg2, arg3, arg4, arg5, arg6)
|
||||
elif arg4:
|
||||
rectArray(objectslist, arg1,arg2, arg3, arg4)
|
||||
rectArray(objectslist, arg1, arg2, arg3, arg4)
|
||||
else:
|
||||
polarArray(objectslist, arg1, arg2, arg3)
|
||||
|
||||
|
||||
def rectArray(objectslist,xvector,yvector,xnum,ynum):
|
||||
utils.type_check([(xvector, App.Vector),
|
||||
(yvector, App.Vector),
|
||||
(xnum,int), (ynum,int)],
|
||||
"rectArray")
|
||||
if not isinstance(objectslist,list): objectslist = [objectslist]
|
||||
def rectArray(objectslist, xvector, yvector, xnum, ynum):
|
||||
utils.type_check(
|
||||
[(xvector, App.Vector), (yvector, App.Vector), (xnum, int), (ynum, int)], "rectArray"
|
||||
)
|
||||
if not isinstance(objectslist, list):
|
||||
objectslist = [objectslist]
|
||||
for xcount in range(xnum):
|
||||
currentxvector=App.Vector(xvector).multiply(xcount)
|
||||
if not xcount==0:
|
||||
move.move(objectslist,currentxvector,True)
|
||||
currentxvector = App.Vector(xvector).multiply(xcount)
|
||||
if not xcount == 0:
|
||||
move.move(objectslist, currentxvector, True)
|
||||
for ycount in range(ynum):
|
||||
currentxvector=App.Vector(currentxvector)
|
||||
currentyvector=currentxvector.add(App.Vector(yvector).multiply(ycount))
|
||||
if not ycount==0:
|
||||
move.move(objectslist,currentyvector,True)
|
||||
currentxvector = App.Vector(currentxvector)
|
||||
currentyvector = currentxvector.add(App.Vector(yvector).multiply(ycount))
|
||||
if not ycount == 0:
|
||||
move.move(objectslist, currentyvector, True)
|
||||
|
||||
|
||||
def rectArray2(objectslist,xvector,yvector,zvector,xnum,ynum,znum):
|
||||
utils.type_check([(xvector,App.Vector), (yvector,App.Vector), (zvector,App.Vector),(xnum,int), (ynum,int),(znum,int)], "rectArray2")
|
||||
if not isinstance(objectslist,list): objectslist = [objectslist]
|
||||
def rectArray2(objectslist, xvector, yvector, zvector, xnum, ynum, znum):
|
||||
utils.type_check(
|
||||
[
|
||||
(xvector, App.Vector),
|
||||
(yvector, App.Vector),
|
||||
(zvector, App.Vector),
|
||||
(xnum, int),
|
||||
(ynum, int),
|
||||
(znum, int),
|
||||
],
|
||||
"rectArray2",
|
||||
)
|
||||
if not isinstance(objectslist, list):
|
||||
objectslist = [objectslist]
|
||||
for xcount in range(xnum):
|
||||
currentxvector=App.Vector(xvector).multiply(xcount)
|
||||
if not xcount==0:
|
||||
move.move(objectslist,currentxvector,True)
|
||||
currentxvector = App.Vector(xvector).multiply(xcount)
|
||||
if not xcount == 0:
|
||||
move.move(objectslist, currentxvector, True)
|
||||
for ycount in range(ynum):
|
||||
currentxvector=App.Vector(currentxvector)
|
||||
currentyvector=currentxvector.add(App.Vector(yvector).multiply(ycount))
|
||||
if not ycount==0:
|
||||
move.move(objectslist,currentyvector,True)
|
||||
currentxvector = App.Vector(currentxvector)
|
||||
currentyvector = currentxvector.add(App.Vector(yvector).multiply(ycount))
|
||||
if not ycount == 0:
|
||||
move.move(objectslist, currentyvector, True)
|
||||
for zcount in range(znum):
|
||||
currentzvector=currentyvector.add(App.Vector(zvector).multiply(zcount))
|
||||
if not zcount==0:
|
||||
move.move(objectslist,currentzvector,True)
|
||||
currentzvector = currentyvector.add(App.Vector(zvector).multiply(zcount))
|
||||
if not zcount == 0:
|
||||
move.move(objectslist, currentzvector, True)
|
||||
|
||||
|
||||
def polarArray(objectslist,center,angle,num):
|
||||
utils.type_check([(center,App.Vector), (num,int)], "polarArray")
|
||||
if not isinstance(objectslist,list): objectslist = [objectslist]
|
||||
fraction = float(angle)/num
|
||||
def polarArray(objectslist, center, angle, num):
|
||||
utils.type_check([(center, App.Vector), (num, int)], "polarArray")
|
||||
if not isinstance(objectslist, list):
|
||||
objectslist = [objectslist]
|
||||
fraction = float(angle) / num
|
||||
for i in range(num):
|
||||
currangle = fraction + (i*fraction)
|
||||
rotate.rotate(objectslist,currangle,center,copy=True)
|
||||
currangle = fraction + (i * fraction)
|
||||
rotate.rotate(objectslist, currangle, center, copy=True)
|
||||
|
||||
|
||||
## @}
|
||||
|
||||
@@ -54,7 +54,7 @@ def cut(object1, object2):
|
||||
If there is a problem and the new object can't be created.
|
||||
"""
|
||||
if not App.activeDocument():
|
||||
_err(translate("draft","No active document. Aborting."))
|
||||
_err(translate("draft", "No active document. Aborting."))
|
||||
return
|
||||
|
||||
obj = App.activeDocument().addObject("Part::Cut", "Cut")
|
||||
@@ -69,4 +69,5 @@ def cut(object1, object2):
|
||||
|
||||
return obj
|
||||
|
||||
|
||||
## @}
|
||||
|
||||
@@ -247,7 +247,6 @@ def downgrade(objects, delete=False, force=None):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
# helper functions (same as in upgrade.py)
|
||||
|
||||
def get_parent(obj):
|
||||
@@ -311,7 +310,6 @@ def downgrade(objects, delete=False, force=None):
|
||||
for newobj in new_list:
|
||||
gui_utils.format_object(newobj, obj, ignore_construction=True)
|
||||
|
||||
|
||||
doc = App.ActiveDocument
|
||||
add_list = []
|
||||
delete_list = []
|
||||
@@ -347,15 +345,15 @@ def downgrade(objects, delete=False, force=None):
|
||||
|
||||
elif force:
|
||||
# functions that work on a single object:
|
||||
single_funcs = {"explode": explode,
|
||||
"getWire": getWire,
|
||||
"shapify": _shapify}
|
||||
single_funcs = {"explode": explode, "getWire": getWire, "shapify": _shapify}
|
||||
# functions that work on multiple objects:
|
||||
multi_funcs = {"cut2": cut2,
|
||||
"splitCompounds": splitCompounds,
|
||||
"splitFaces": splitFaces,
|
||||
"splitWires": splitWires,
|
||||
"subtr": subtr}
|
||||
multi_funcs = {
|
||||
"cut2": cut2,
|
||||
"splitCompounds": splitCompounds,
|
||||
"splitFaces": splitFaces,
|
||||
"splitWires": splitWires,
|
||||
"subtr": subtr,
|
||||
}
|
||||
if force in single_funcs:
|
||||
result = any([single_funcs[force](obj) for obj in objects])
|
||||
elif force in multi_funcs:
|
||||
@@ -388,21 +386,21 @@ def downgrade(objects, delete=False, force=None):
|
||||
_msg(translate("draft", "Found 1 array: exploding it"))
|
||||
|
||||
# special case, we have one parametric object: we "de-parametrize" it
|
||||
elif len(objects) == 1 \
|
||||
and hasattr(objects[0], "Shape") \
|
||||
and (
|
||||
hasattr(objects[0], "Base")
|
||||
or hasattr(objects[0], "Profile")
|
||||
or hasattr(objects[0], "Sections")
|
||||
):
|
||||
elif (
|
||||
len(objects) == 1
|
||||
and hasattr(objects[0], "Shape")
|
||||
and (
|
||||
hasattr(objects[0], "Base")
|
||||
or hasattr(objects[0], "Profile")
|
||||
or hasattr(objects[0], "Sections")
|
||||
)
|
||||
):
|
||||
result = _shapify(objects[0])
|
||||
if result:
|
||||
_msg(translate("draft", "Found 1 parametric object: breaking its dependencies"))
|
||||
|
||||
# we have one multi-solids compound object: extract its solids
|
||||
elif len(objects) == 1 \
|
||||
and hasattr(objects[0], "Shape") \
|
||||
and len(solids) > 1:
|
||||
elif len(objects) == 1 and hasattr(objects[0], "Shape") and len(solids) > 1:
|
||||
result = splitCompounds(objects)
|
||||
if result:
|
||||
_msg(translate("draft", "Found 1 multi-solids compound: exploding it"))
|
||||
@@ -423,7 +421,11 @@ def downgrade(objects, delete=False, force=None):
|
||||
elif same_parent and same_parent_type != "PartDesign::Body":
|
||||
result = subtr(objects)
|
||||
if result:
|
||||
_msg(translate("draft", "Found several faces: subtracting them from the first one"))
|
||||
_msg(
|
||||
translate(
|
||||
"draft", "Found several faces: subtracting them from the first one"
|
||||
)
|
||||
)
|
||||
|
||||
# only one face: we extract its wires
|
||||
elif len(faces) > 0:
|
||||
@@ -448,4 +450,5 @@ def downgrade(objects, delete=False, force=None):
|
||||
gui_utils.select(add_list)
|
||||
return add_list, delete_list
|
||||
|
||||
|
||||
## @}
|
||||
|
||||
@@ -43,6 +43,7 @@ import draftmake.make_arc_3points as make_arc_3points
|
||||
Part = lz.LazyLoader("Part", globals(), "Part")
|
||||
DraftGeomUtils = lz.LazyLoader("DraftGeomUtils", globals(), "DraftGeomUtils")
|
||||
|
||||
|
||||
def draftify(objectslist, makeblock=False, delete=True):
|
||||
"""draftify(objectslist,[makeblock],[delete])
|
||||
|
||||
@@ -62,11 +63,11 @@ def draftify(objectslist, makeblock=False, delete=True):
|
||||
If delete = False, old objects are not deleted
|
||||
"""
|
||||
|
||||
if not isinstance(objectslist,list):
|
||||
if not isinstance(objectslist, list):
|
||||
objectslist = [objectslist]
|
||||
newobjlist = []
|
||||
for obj in objectslist:
|
||||
if hasattr(obj,'Shape'):
|
||||
if hasattr(obj, "Shape"):
|
||||
for cluster in Part.sortEdges(obj.Shape.Edges):
|
||||
w = Part.Wire(cluster)
|
||||
nobj = draftify_shape(w)
|
||||
@@ -88,11 +89,12 @@ def draftify(objectslist, makeblock=False, delete=True):
|
||||
return newobjlist[0]
|
||||
return newobjlist
|
||||
|
||||
|
||||
def draftify_shape(shape):
|
||||
|
||||
nobj = None
|
||||
if DraftGeomUtils.hasCurves(shape):
|
||||
if (len(shape.Edges) == 1):
|
||||
if len(shape.Edges) == 1:
|
||||
edge = shape.Edges[0]
|
||||
edge_type = DraftGeomUtils.geomType(edge)
|
||||
if edge_type == "Circle":
|
||||
@@ -101,21 +103,24 @@ def draftify_shape(shape):
|
||||
else:
|
||||
first_parameter = edge.FirstParameter
|
||||
last_parameter = edge.LastParameter
|
||||
points = [edge.Curve.value(first_parameter),
|
||||
edge.Curve.value((first_parameter + last_parameter)/2),
|
||||
edge.Curve.value(last_parameter)]
|
||||
points = [
|
||||
edge.Curve.value(first_parameter),
|
||||
edge.Curve.value((first_parameter + last_parameter) / 2),
|
||||
edge.Curve.value(last_parameter),
|
||||
]
|
||||
nobj = make_arc_3points.make_arc_3points(points)
|
||||
# TODO: take into consideration trimmed curves and capture the specific
|
||||
# type of BSpline and Bezier that can be converted to a draft object.
|
||||
# elif edge_type == "BSplineCurve":
|
||||
# knots = [edge.Curve.value(p) for p in edge.Curve.getKnots()]
|
||||
# nobj = make_bspline.make_bspline(knots, closed=edge.isClosed())
|
||||
# elif edge_type == "BezierCurve":
|
||||
# nobj = make_bezcurve.make_bezcurve(edge.Curve.getPoles(),
|
||||
# closed=edge.isClosed())
|
||||
# TODO: take into consideration trimmed curves and capture the specific
|
||||
# type of BSpline and Bezier that can be converted to a draft object.
|
||||
# elif edge_type == "BSplineCurve":
|
||||
# knots = [edge.Curve.value(p) for p in edge.Curve.getKnots()]
|
||||
# nobj = make_bspline.make_bspline(knots, closed=edge.isClosed())
|
||||
# elif edge_type == "BezierCurve":
|
||||
# nobj = make_bezcurve.make_bezcurve(edge.Curve.getPoles(),
|
||||
# closed=edge.isClosed())
|
||||
else:
|
||||
nobj = make_wire.make_wire(shape)
|
||||
|
||||
return nobj
|
||||
|
||||
|
||||
## @}
|
||||
|
||||
@@ -20,8 +20,7 @@
|
||||
# * USA *
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
"""Provides functions to return the DXF representation of various shapes.
|
||||
"""
|
||||
"""Provides functions to return the DXF representation of various shapes."""
|
||||
## @package dxf
|
||||
# \ingroup draftfunctions
|
||||
# \brief Provides functions to return the DXF representation of shapes.
|
||||
@@ -44,6 +43,7 @@ TechDraw = lz.LazyLoader("TechDraw", globals(), "TechDraw")
|
||||
## \addtogroup draftfunctions
|
||||
# @{
|
||||
|
||||
|
||||
def _get_proj(vec, plane=None):
|
||||
"""Get a projection of the vector in the plane's u and v directions.
|
||||
|
||||
@@ -85,9 +85,9 @@ def get_dxf(obj, direction=None):
|
||||
p2 = _get_proj(obj.End, plane=plane)
|
||||
p3 = _get_proj(obj.Dimline, plane=plane)
|
||||
result += "0\nDIMENSION\n8\n0\n62\n0\n3\nStandard\n70\n1\n"
|
||||
result += "10\n"+str(p3.x)+"\n20\n"+str(p3.y)+"\n30\n"+str(p3.z)+"\n"
|
||||
result += "13\n"+str(p1.x)+"\n23\n"+str(p1.y)+"\n33\n"+str(p1.z)+"\n"
|
||||
result += "14\n"+str(p2.x)+"\n24\n"+str(p2.y)+"\n34\n"+str(p2.z)+"\n"
|
||||
result += "10\n" + str(p3.x) + "\n20\n" + str(p3.y) + "\n30\n" + str(p3.z) + "\n"
|
||||
result += "13\n" + str(p1.x) + "\n23\n" + str(p1.y) + "\n33\n" + str(p1.z) + "\n"
|
||||
result += "14\n" + str(p2.x) + "\n24\n" + str(p2.y) + "\n34\n" + str(p2.z) + "\n"
|
||||
|
||||
elif utils.get_type(obj) == "Annotation":
|
||||
# Only for App::Annotation
|
||||
@@ -104,7 +104,7 @@ def get_dxf(obj, direction=None):
|
||||
result += "7\nSTANDARD\n"
|
||||
count += 1
|
||||
|
||||
elif hasattr(obj, 'Shape'):
|
||||
elif hasattr(obj, "Shape"):
|
||||
# TODO do this the Draft way, for ex. using polylines and rectangles
|
||||
if not direction:
|
||||
direction = App.Vector(0, 0, -1)
|
||||
@@ -117,8 +117,7 @@ def get_dxf(obj, direction=None):
|
||||
except Exception:
|
||||
# TODO: trap only specific exception.
|
||||
# Impossible to generate DXF from Shape? Which exception is throw?
|
||||
_wrn("get_dxf: "
|
||||
"unable to project '{}' to {}".format(obj.Label, direction))
|
||||
_wrn("get_dxf: " "unable to project '{}' to {}".format(obj.Label, direction))
|
||||
else:
|
||||
result += d
|
||||
else:
|
||||
@@ -127,11 +126,10 @@ def get_dxf(obj, direction=None):
|
||||
return result
|
||||
|
||||
|
||||
def getDXF(obj,
|
||||
direction=None):
|
||||
def getDXF(obj, direction=None):
|
||||
"""Return DXF string of the object. DEPRECATED. Use 'get_dxf'."""
|
||||
utils.use_instead("get_dxf")
|
||||
return get_dxf(obj,
|
||||
direction=direction)
|
||||
return get_dxf(obj, direction=direction)
|
||||
|
||||
|
||||
## @}
|
||||
|
||||
@@ -55,9 +55,10 @@ def extrude(obj, vector, solid=False):
|
||||
newobj.Solid = solid
|
||||
if App.GuiUp:
|
||||
obj.ViewObject.Visibility = False
|
||||
gui_utils.format_object(newobj,obj)
|
||||
gui_utils.format_object(newobj, obj)
|
||||
gui_utils.select(newobj)
|
||||
|
||||
return newobj
|
||||
|
||||
|
||||
## @}
|
||||
|
||||
@@ -49,6 +49,7 @@ def fuse(object1, object2):
|
||||
return
|
||||
import Part
|
||||
import DraftGeomUtils
|
||||
|
||||
# testing if we have holes:
|
||||
holes = False
|
||||
fshape = object1.Shape.fuse(object2.Shape)
|
||||
@@ -74,9 +75,10 @@ def fuse(object1, object2):
|
||||
if App.GuiUp:
|
||||
object1.ViewObject.Visibility = False
|
||||
object2.ViewObject.Visibility = False
|
||||
gui_utils.format_object(obj,object1)
|
||||
gui_utils.format_object(obj, object1)
|
||||
gui_utils.select(obj)
|
||||
|
||||
return obj
|
||||
|
||||
|
||||
## @}
|
||||
|
||||
@@ -61,7 +61,7 @@ def heal(objlist=None, delete=True, reparent=True):
|
||||
else:
|
||||
print("Manual mode: Force-healing selected objects…")
|
||||
|
||||
if not isinstance(objlist,list):
|
||||
if not isinstance(objlist, list):
|
||||
objlist = [objlist]
|
||||
|
||||
dellist = []
|
||||
@@ -70,34 +70,34 @@ def heal(objlist=None, delete=True, reparent=True):
|
||||
for obj in objlist:
|
||||
dtype = utils.get_type(obj)
|
||||
ftype = obj.TypeId
|
||||
if ftype in ["Part::FeaturePython","App::FeaturePython","Part::Part2DObjectPython"]:
|
||||
if ftype in ["Part::FeaturePython", "App::FeaturePython", "Part::Part2DObjectPython"]:
|
||||
proxy = obj.Proxy
|
||||
if hasattr(obj,"ViewObject"):
|
||||
if hasattr(obj.ViewObject,"Proxy"):
|
||||
if hasattr(obj, "ViewObject"):
|
||||
if hasattr(obj.ViewObject, "Proxy"):
|
||||
proxy = obj.ViewObject.Proxy
|
||||
if (proxy == 1) or (dtype in ["Unknown","Part"]) or (not auto):
|
||||
if (proxy == 1) or (dtype in ["Unknown", "Part"]) or (not auto):
|
||||
got = True
|
||||
dellist.append(obj.Name)
|
||||
props = obj.PropertiesList
|
||||
if ("Dimline" in props) and ("Start" in props):
|
||||
print("Healing " + obj.Name + " of type Dimension")
|
||||
nobj = make_copy(obj,force="Dimension",reparent=reparent)
|
||||
nobj = make_copy(obj, force="Dimension", reparent=reparent)
|
||||
elif ("Height" in props) and ("Length" in props):
|
||||
print("Healing " + obj.Name + " of type Rectangle")
|
||||
nobj = make_copy(obj,force="Rectangle",reparent=reparent)
|
||||
nobj = make_copy(obj, force="Rectangle", reparent=reparent)
|
||||
elif ("Points" in props) and ("Closed" in props):
|
||||
if "BSpline" in obj.Name:
|
||||
print("Healing " + obj.Name + " of type BSpline")
|
||||
nobj = make_copy(obj,force="BSpline",reparent=reparent)
|
||||
nobj = make_copy(obj, force="BSpline", reparent=reparent)
|
||||
else:
|
||||
print("Healing " + obj.Name + " of type Wire")
|
||||
nobj = make_copy(obj,force="Wire",reparent=reparent)
|
||||
nobj = make_copy(obj, force="Wire", reparent=reparent)
|
||||
elif ("Radius" in props) and ("FirstAngle" in props):
|
||||
print("Healing " + obj.Name + " of type Circle")
|
||||
nobj = make_copy(obj,force="Circle",reparent=reparent)
|
||||
nobj = make_copy(obj, force="Circle", reparent=reparent)
|
||||
elif ("DrawMode" in props) and ("FacesNumber" in props):
|
||||
print("Healing " + obj.Name + " of type Polygon")
|
||||
nobj = make_copy(obj,force="Polygon",reparent=reparent)
|
||||
nobj = make_copy(obj, force="Polygon", reparent=reparent)
|
||||
else:
|
||||
dellist.pop()
|
||||
print("Object " + obj.Name + " is not healable")
|
||||
@@ -105,10 +105,11 @@ def heal(objlist=None, delete=True, reparent=True):
|
||||
if not got:
|
||||
print("No object seems to need healing")
|
||||
else:
|
||||
print("Healed ",len(dellist)," objects")
|
||||
print("Healed ", len(dellist), " objects")
|
||||
|
||||
if dellist and delete:
|
||||
for n in dellist:
|
||||
App.ActiveDocument.removeObject(n)
|
||||
|
||||
|
||||
## @}
|
||||
|
||||
@@ -31,7 +31,7 @@ import FreeCAD as App
|
||||
import DraftVecUtils
|
||||
|
||||
|
||||
def join_wires(wires, joinAttempts = 0):
|
||||
def join_wires(wires, joinAttempts=0):
|
||||
"""join_wires(objects): merges a set of wires where possible, if any of those
|
||||
wires have a coincident start and end point"""
|
||||
wires = list(wires)
|
||||
@@ -58,10 +58,13 @@ def join_two_wires(wire1, wire2):
|
||||
"""
|
||||
wire1AbsPoints = [wire1.Placement.multVec(point) for point in wire1.Points]
|
||||
wire2AbsPoints = [wire2.Placement.multVec(point) for point in wire2.Points]
|
||||
if ((DraftVecUtils.equals(wire1AbsPoints[0], wire2AbsPoints[-1])
|
||||
and DraftVecUtils.equals(wire1AbsPoints[-1], wire2AbsPoints[0]))
|
||||
or (DraftVecUtils.equals(wire1AbsPoints[0], wire2AbsPoints[0])
|
||||
and DraftVecUtils.equals(wire1AbsPoints[-1], wire2AbsPoints[-1]))):
|
||||
if (
|
||||
DraftVecUtils.equals(wire1AbsPoints[0], wire2AbsPoints[-1])
|
||||
and DraftVecUtils.equals(wire1AbsPoints[-1], wire2AbsPoints[0])
|
||||
) or (
|
||||
DraftVecUtils.equals(wire1AbsPoints[0], wire2AbsPoints[0])
|
||||
and DraftVecUtils.equals(wire1AbsPoints[-1], wire2AbsPoints[-1])
|
||||
):
|
||||
wire2AbsPoints.pop()
|
||||
wire1.Closed = True
|
||||
elif DraftVecUtils.equals(wire1AbsPoints[0], wire2AbsPoints[0]):
|
||||
@@ -76,10 +79,9 @@ def join_two_wires(wire1, wire2):
|
||||
else:
|
||||
return False
|
||||
wire2AbsPoints.pop(0)
|
||||
wire1.Points = ([wire1.Placement.inverse().multVec(point)
|
||||
for point in wire1AbsPoints] +
|
||||
[wire1.Placement.inverse().multVec(point)
|
||||
for point in wire2AbsPoints])
|
||||
wire1.Points = [wire1.Placement.inverse().multVec(point) for point in wire1AbsPoints] + [
|
||||
wire1.Placement.inverse().multVec(point) for point in wire2AbsPoints
|
||||
]
|
||||
App.ActiveDocument.removeObject(wire2.Name)
|
||||
return True
|
||||
|
||||
|
||||
@@ -80,11 +80,11 @@ def mirror(objlist, p1, p2):
|
||||
"""
|
||||
|
||||
if not objlist:
|
||||
_err(translate("draft","No object given"))
|
||||
_err(translate("draft", "No object given"))
|
||||
return
|
||||
|
||||
if p1 == p2:
|
||||
_err(translate("draft","The two points are coincident"))
|
||||
_err(translate("draft", "The two points are coincident"))
|
||||
return
|
||||
|
||||
if not isinstance(objlist, list):
|
||||
@@ -110,4 +110,5 @@ def mirror(objlist, p1, p2):
|
||||
|
||||
return result
|
||||
|
||||
|
||||
## @}
|
||||
|
||||
@@ -92,7 +92,9 @@ def move(selection, vector, copy=False, subelements=False):
|
||||
if copy:
|
||||
for obj in objs:
|
||||
if obj.isDerivedFrom("App::DocumentObjectGroup") and obj.Name not in newgroups:
|
||||
newgroups[obj.Name] = obj.Document.addObject(obj.TypeId, utils.get_real_name(obj.Name))
|
||||
newgroups[obj.Name] = obj.Document.addObject(
|
||||
obj.TypeId, utils.get_real_name(obj.Name)
|
||||
)
|
||||
|
||||
for idx, obj in enumerate(objs):
|
||||
newobj = None
|
||||
@@ -217,7 +219,7 @@ def move_edge(obj, edge_idx, vector, global_place=None):
|
||||
if utils.is_closed_edge(edge_idx, obj):
|
||||
move_vertex(obj, 0, vector, global_place)
|
||||
else:
|
||||
move_vertex(obj, edge_idx+1, vector, global_place)
|
||||
move_vertex(obj, edge_idx + 1, vector, global_place)
|
||||
|
||||
|
||||
def copy_moved_edge(obj, edge_idx, vector, global_place=None):
|
||||
@@ -233,9 +235,10 @@ def copy_moved_edge(obj, edge_idx, vector, global_place=None):
|
||||
if utils.is_closed_edge(edge_idx, obj):
|
||||
vertex2 = glp.multVec(obj.Points[0]).add(vector)
|
||||
else:
|
||||
vertex2 = glp.multVec(obj.Points[edge_idx+1]).add(vector)
|
||||
vertex2 = glp.multVec(obj.Points[edge_idx + 1]).add(vector)
|
||||
newobj = make_line.make_line(vertex1, vertex2)
|
||||
gui_utils.format_object(newobj, obj)
|
||||
return newobj
|
||||
|
||||
|
||||
## @}
|
||||
|
||||
@@ -70,43 +70,51 @@ def offset(obj, delta, copy=False, bind=False, sym=False, occ=False):
|
||||
"""
|
||||
import Part
|
||||
import DraftGeomUtils
|
||||
|
||||
newwire = None
|
||||
delete = None
|
||||
|
||||
if (copy is False
|
||||
and (utils.get_type(obj).startswith("Sketcher::")
|
||||
or utils.get_type(obj).startswith("Part::")
|
||||
or utils.get_type(obj).startswith("PartDesign::"))): # For PartDesign_SubShapeBinders which can reference sketches.
|
||||
print("the offset tool is currently unable to offset a non-Draft object directly - Creating a copy")
|
||||
if copy is False and (
|
||||
utils.get_type(obj).startswith("Sketcher::")
|
||||
or utils.get_type(obj).startswith("Part::")
|
||||
or utils.get_type(obj).startswith("PartDesign::")
|
||||
): # For PartDesign_SubShapeBinders which can reference sketches.
|
||||
print(
|
||||
"the offset tool is currently unable to offset a non-Draft object directly - Creating a copy"
|
||||
)
|
||||
copy = True
|
||||
|
||||
def getRect(p,obj):
|
||||
def getRect(p, obj):
|
||||
"""returns length,height,placement"""
|
||||
pl = obj.Placement.copy()
|
||||
pl.Base = p[0]
|
||||
diag = p[2].sub(p[0])
|
||||
bb = p[1].sub(p[0])
|
||||
bh = p[3].sub(p[0])
|
||||
nb = DraftVecUtils.project(diag,bb)
|
||||
nh = DraftVecUtils.project(diag,bh)
|
||||
if obj.Length.Value < 0: l = -nb.Length
|
||||
else: l = nb.Length
|
||||
if obj.Height.Value < 0: h = -nh.Length
|
||||
else: h = nh.Length
|
||||
return l,h,pl
|
||||
nb = DraftVecUtils.project(diag, bb)
|
||||
nh = DraftVecUtils.project(diag, bh)
|
||||
if obj.Length.Value < 0:
|
||||
l = -nb.Length
|
||||
else:
|
||||
l = nb.Length
|
||||
if obj.Height.Value < 0:
|
||||
h = -nh.Length
|
||||
else:
|
||||
h = nh.Length
|
||||
return l, h, pl
|
||||
|
||||
def getRadius(obj,delta):
|
||||
def getRadius(obj, delta):
|
||||
"""returns a new radius for a regular polygon"""
|
||||
an = math.pi/obj.FacesNumber
|
||||
nr = DraftVecUtils.rotate(delta,-an)
|
||||
nr.multiply(1/math.cos(an))
|
||||
an = math.pi / obj.FacesNumber
|
||||
nr = DraftVecUtils.rotate(delta, -an)
|
||||
nr.multiply(1 / math.cos(an))
|
||||
nr = obj.Shape.Vertexes[0].Point.add(nr)
|
||||
nr = nr.sub(obj.Placement.Base)
|
||||
nr = nr.Length
|
||||
if obj.DrawMode == "inscribed":
|
||||
return nr
|
||||
else:
|
||||
return nr * math.cos(math.pi/obj.FacesNumber)
|
||||
return nr * math.cos(math.pi / obj.FacesNumber)
|
||||
|
||||
newwire = None
|
||||
if utils.get_type(obj) == "Circle":
|
||||
@@ -117,27 +125,29 @@ def offset(obj, delta, copy=False, bind=False, sym=False, occ=False):
|
||||
if sym:
|
||||
d1 = App.Vector(delta).multiply(0.5)
|
||||
d2 = d1.negative()
|
||||
n1 = DraftGeomUtils.offsetWire(obj.Shape,d1)
|
||||
n2 = DraftGeomUtils.offsetWire(obj.Shape,d2)
|
||||
n1 = DraftGeomUtils.offsetWire(obj.Shape, d1)
|
||||
n2 = DraftGeomUtils.offsetWire(obj.Shape, d2)
|
||||
else:
|
||||
if isinstance(delta,float) and (len(obj.Shape.Edges) == 1):
|
||||
if isinstance(delta, float) and (len(obj.Shape.Edges) == 1):
|
||||
# circle
|
||||
c = obj.Shape.Edges[0].Curve
|
||||
nc = Part.Circle(c.Center,c.Axis,delta)
|
||||
nc = Part.Circle(c.Center, c.Axis, delta)
|
||||
if len(obj.Shape.Vertexes) > 1:
|
||||
nc = Part.ArcOfCircle(nc,obj.Shape.Edges[0].FirstParameter,obj.Shape.Edges[0].LastParameter)
|
||||
nc = Part.ArcOfCircle(
|
||||
nc, obj.Shape.Edges[0].FirstParameter, obj.Shape.Edges[0].LastParameter
|
||||
)
|
||||
newwire = Part.Wire(nc.toShape())
|
||||
p = []
|
||||
else:
|
||||
newwire = DraftGeomUtils.offsetWire(obj.Shape,delta)
|
||||
newwire = DraftGeomUtils.offsetWire(obj.Shape, delta)
|
||||
if DraftGeomUtils.hasCurves(newwire) and copy:
|
||||
p = []
|
||||
else:
|
||||
p = DraftGeomUtils.getVerts(newwire)
|
||||
if occ:
|
||||
newobj = App.ActiveDocument.addObject("Part::Feature","Offset")
|
||||
newobj.Shape = DraftGeomUtils.offsetWire(obj.Shape,delta,occ=True)
|
||||
gui_utils.formatObject(newobj,obj)
|
||||
newobj = App.ActiveDocument.addObject("Part::Feature", "Offset")
|
||||
newobj.Shape = DraftGeomUtils.offsetWire(obj.Shape, delta, occ=True)
|
||||
gui_utils.formatObject(newobj, obj)
|
||||
if not copy:
|
||||
delete = obj.Name
|
||||
elif bind:
|
||||
@@ -151,35 +161,36 @@ def offset(obj, delta, copy=False, bind=False, sym=False, occ=False):
|
||||
if s1 and s2:
|
||||
w1 = s1.Edges
|
||||
w2 = s2.Edges
|
||||
w3 = Part.LineSegment(s1.Vertexes[0].Point,s2.Vertexes[0].Point).toShape()
|
||||
w4 = Part.LineSegment(s1.Vertexes[-1].Point,s2.Vertexes[-1].Point).toShape()
|
||||
newobj = App.ActiveDocument.addObject("Part::Feature","Offset")
|
||||
newobj.Shape = Part.Face(Part.Wire(w1+[w3]+w2+[w4]))
|
||||
w3 = Part.LineSegment(s1.Vertexes[0].Point, s2.Vertexes[0].Point).toShape()
|
||||
w4 = Part.LineSegment(s1.Vertexes[-1].Point, s2.Vertexes[-1].Point).toShape()
|
||||
newobj = App.ActiveDocument.addObject("Part::Feature", "Offset")
|
||||
newobj.Shape = Part.Face(Part.Wire(w1 + [w3] + w2 + [w4]))
|
||||
else:
|
||||
print("Draft.offset: Unable to bind wires")
|
||||
else:
|
||||
newobj = App.ActiveDocument.addObject("Part::Feature","Offset")
|
||||
newobj = App.ActiveDocument.addObject("Part::Feature", "Offset")
|
||||
newobj.Shape = Part.Face(obj.Shape.Wires[0])
|
||||
if not copy:
|
||||
delete = obj.Name
|
||||
elif copy:
|
||||
newobj = None
|
||||
if sym: return None
|
||||
if sym:
|
||||
return None
|
||||
if utils.get_type(obj) == "Wire":
|
||||
if p:
|
||||
newobj = make_wire(p)
|
||||
newobj.Closed = obj.Closed
|
||||
elif newwire:
|
||||
newobj = App.ActiveDocument.addObject("Part::Feature","Offset")
|
||||
newobj = App.ActiveDocument.addObject("Part::Feature", "Offset")
|
||||
newobj.Shape = newwire
|
||||
else:
|
||||
print("Draft.offset: Unable to duplicate this object")
|
||||
elif utils.get_type(obj) == "Rectangle":
|
||||
if p:
|
||||
length,height,plac = getRect(p,obj)
|
||||
newobj = make_rectangle(length,height,plac)
|
||||
length, height, plac = getRect(p, obj)
|
||||
newobj = make_rectangle(length, height, plac)
|
||||
elif newwire:
|
||||
newobj = App.ActiveDocument.addObject("Part::Feature","Offset")
|
||||
newobj = App.ActiveDocument.addObject("Part::Feature", "Offset")
|
||||
newobj.Shape = newwire
|
||||
else:
|
||||
print("Draft.offset: Unable to duplicate this object")
|
||||
@@ -192,7 +203,7 @@ def offset(obj, delta, copy=False, bind=False, sym=False, occ=False):
|
||||
elif utils.get_type(obj) == "Polygon":
|
||||
pl = obj.Placement
|
||||
newobj = make_polygon(obj.FacesNumber)
|
||||
newobj.Radius = getRadius(obj,delta)
|
||||
newobj.Radius = getRadius(obj, delta)
|
||||
newobj.DrawMode = obj.DrawMode
|
||||
newobj.Placement = pl
|
||||
elif utils.get_type(obj) == "BSpline":
|
||||
@@ -207,37 +218,38 @@ def offset(obj, delta, copy=False, bind=False, sym=False, occ=False):
|
||||
except Part.OCCError:
|
||||
pass
|
||||
if (not newobj) and newwire:
|
||||
newobj = App.ActiveDocument.addObject("Part::Feature","Offset")
|
||||
newobj = App.ActiveDocument.addObject("Part::Feature", "Offset")
|
||||
newobj.Shape = newwire
|
||||
if not newobj:
|
||||
print("Draft.offset: Unable to create an offset")
|
||||
if newobj:
|
||||
gui_utils.formatObject(newobj,obj)
|
||||
gui_utils.formatObject(newobj, obj)
|
||||
else:
|
||||
newobj = None
|
||||
if sym: return None
|
||||
if sym:
|
||||
return None
|
||||
if utils.get_type(obj) == "Wire":
|
||||
if obj.Base or obj.Tool:
|
||||
App.Console.PrintWarning("Warning: object history removed\n")
|
||||
obj.Base = None
|
||||
obj.Tool = None
|
||||
obj.Placement = App.Placement() # p points are in the global coordinate system
|
||||
obj.Placement = App.Placement() # p points are in the global coordinate system
|
||||
obj.Points = p
|
||||
elif utils.get_type(obj) == "BSpline":
|
||||
#print(delta)
|
||||
# print(delta)
|
||||
obj.Points = delta
|
||||
#print("done")
|
||||
# print("done")
|
||||
elif utils.get_type(obj) == "Rectangle":
|
||||
length,height,plac = getRect(p,obj)
|
||||
length, height, plac = getRect(p, obj)
|
||||
obj.Placement = plac
|
||||
obj.Length = length
|
||||
obj.Height = height
|
||||
elif utils.get_type(obj) == "Circle":
|
||||
obj.Radius = delta
|
||||
elif utils.get_type(obj) == "Polygon":
|
||||
obj.Radius = getRadius(obj,delta)
|
||||
elif utils.get_type(obj) == 'Part':
|
||||
print("unsupported object") # TODO
|
||||
obj.Radius = getRadius(obj, delta)
|
||||
elif utils.get_type(obj) == "Part":
|
||||
print("unsupported object") # TODO
|
||||
newobj = obj
|
||||
if copy and params.get_param("selectBaseObjects"):
|
||||
gui_utils.select(obj)
|
||||
@@ -247,4 +259,5 @@ def offset(obj, delta, copy=False, bind=False, sym=False, occ=False):
|
||||
App.ActiveDocument.removeObject(delete)
|
||||
return newobj
|
||||
|
||||
|
||||
## @}
|
||||
|
||||
@@ -42,8 +42,14 @@ from draftutils import params
|
||||
from draftutils import utils
|
||||
|
||||
|
||||
def rotate(selection, angle, center=App.Vector(0, 0, 0),
|
||||
axis=App.Vector(0, 0, 1), copy=False, subelements=False):
|
||||
def rotate(
|
||||
selection,
|
||||
angle,
|
||||
center=App.Vector(0, 0, 0),
|
||||
axis=App.Vector(0, 0, 1),
|
||||
copy=False,
|
||||
subelements=False,
|
||||
):
|
||||
"""rotate(selection, angle, [center], [axis], [copy], [subelements])
|
||||
|
||||
Rotates or copies selected objects.
|
||||
@@ -80,8 +86,16 @@ def rotate(selection, angle, center=App.Vector(0, 0, 0),
|
||||
single object / list with 2 or more objects / empty list
|
||||
The objects (or their copies).
|
||||
"""
|
||||
utils.type_check([(angle, (float, int)), (center, App.Vector),
|
||||
(axis, App.Vector), (copy, bool), (subelements, bool)], "rotate")
|
||||
utils.type_check(
|
||||
[
|
||||
(angle, (float, int)),
|
||||
(center, App.Vector),
|
||||
(axis, App.Vector),
|
||||
(copy, bool),
|
||||
(subelements, bool),
|
||||
],
|
||||
"rotate",
|
||||
)
|
||||
if not isinstance(selection, list):
|
||||
selection = [selection]
|
||||
if not selection:
|
||||
@@ -106,7 +120,9 @@ def rotate(selection, angle, center=App.Vector(0, 0, 0),
|
||||
if copy:
|
||||
for obj in objs:
|
||||
if obj.isDerivedFrom("App::DocumentObjectGroup") and obj.Name not in newgroups:
|
||||
newgroups[obj.Name] = obj.Document.addObject(obj.TypeId, utils.get_real_name(obj.Name))
|
||||
newgroups[obj.Name] = obj.Document.addObject(
|
||||
obj.TypeId, utils.get_real_name(obj.Name)
|
||||
)
|
||||
|
||||
for idx, obj in enumerate(objs):
|
||||
newobj = None
|
||||
@@ -230,9 +246,8 @@ def rotate_vertex(obj, vert_idx, angle, center, axis, global_place=None):
|
||||
glp = global_place
|
||||
points = obj.Points
|
||||
points[vert_idx] = glp.inverse().multVec(
|
||||
rotate_vector_from_center(
|
||||
glp.multVec(points[vert_idx]),
|
||||
angle, axis, center))
|
||||
rotate_vector_from_center(glp.multVec(points[vert_idx]), angle, axis, center)
|
||||
)
|
||||
obj.Points = points
|
||||
|
||||
|
||||
@@ -245,7 +260,7 @@ def rotate_edge(obj, edge_idx, angle, center, axis, global_place=None):
|
||||
if utils.is_closed_edge(edge_idx, obj):
|
||||
rotate_vertex(obj, 0, angle, center, axis, global_place)
|
||||
else:
|
||||
rotate_vertex(obj, edge_idx+1, angle, center, axis, global_place)
|
||||
rotate_vertex(obj, edge_idx + 1, angle, center, axis, global_place)
|
||||
|
||||
|
||||
def copy_rotated_edge(obj, edge_idx, angle, center, axis, global_place=None):
|
||||
@@ -257,19 +272,16 @@ def copy_rotated_edge(obj, edge_idx, angle, center, axis, global_place=None):
|
||||
glp = obj.getGlobalPlacement()
|
||||
else:
|
||||
glp = global_place
|
||||
vertex1 = rotate_vector_from_center(
|
||||
glp.multVec(obj.Points[edge_idx]),
|
||||
angle, axis, center)
|
||||
vertex1 = rotate_vector_from_center(glp.multVec(obj.Points[edge_idx]), angle, axis, center)
|
||||
if utils.is_closed_edge(edge_idx, obj):
|
||||
vertex2 = rotate_vector_from_center(
|
||||
glp.multVec(obj.Points[0]),
|
||||
angle, axis, center)
|
||||
vertex2 = rotate_vector_from_center(glp.multVec(obj.Points[0]), angle, axis, center)
|
||||
else:
|
||||
vertex2 = rotate_vector_from_center(
|
||||
glp.multVec(obj.Points[edge_idx+1]),
|
||||
angle, axis, center)
|
||||
glp.multVec(obj.Points[edge_idx + 1]), angle, axis, center
|
||||
)
|
||||
newobj = make_line.make_line(vertex1, vertex2)
|
||||
gui_utils.format_object(newobj, obj)
|
||||
return newobj
|
||||
|
||||
|
||||
## @}
|
||||
|
||||
@@ -43,8 +43,7 @@ from draftutils import params
|
||||
from draftutils import utils
|
||||
|
||||
|
||||
def scale(selection, scale, center=App.Vector(0, 0, 0),
|
||||
copy=False, clone=False, subelements=False):
|
||||
def scale(selection, scale, center=App.Vector(0, 0, 0), copy=False, clone=False, subelements=False):
|
||||
"""scale(selection, scale, [center], [copy], [clone], [subelements])
|
||||
|
||||
Scales or copies selected objects.
|
||||
@@ -82,8 +81,16 @@ def scale(selection, scale, center=App.Vector(0, 0, 0),
|
||||
single object / list with 2 or more objects / empty list
|
||||
The objects (or their copies).
|
||||
"""
|
||||
utils.type_check([(scale, App.Vector), (center, App.Vector),
|
||||
(copy, bool), (clone, bool), (subelements, bool)], "scale")
|
||||
utils.type_check(
|
||||
[
|
||||
(scale, App.Vector),
|
||||
(center, App.Vector),
|
||||
(copy, bool),
|
||||
(clone, bool),
|
||||
(subelements, bool),
|
||||
],
|
||||
"scale",
|
||||
)
|
||||
sx, sy, sz = scale
|
||||
if sx * sy * sz == 0:
|
||||
raise ValueError("Zero component in scale vector")
|
||||
@@ -98,9 +105,13 @@ def scale(selection, scale, center=App.Vector(0, 0, 0),
|
||||
if subelements:
|
||||
return _scale_subelements(selection, scale, center, copy)
|
||||
else:
|
||||
objs, parent_places, sel_info = utils._modifiers_process_selection(selection, (copy or clone), scale=True)
|
||||
objs, parent_places, sel_info = utils._modifiers_process_selection(
|
||||
selection, (copy or clone), scale=True
|
||||
)
|
||||
else:
|
||||
objs = utils._modifiers_filter_objects(utils._modifiers_get_group_contents(selection), (copy or clone), scale=True)
|
||||
objs = utils._modifiers_filter_objects(
|
||||
utils._modifiers_get_group_contents(selection), (copy or clone), scale=True
|
||||
)
|
||||
parent_places = None
|
||||
sel_info = None
|
||||
|
||||
@@ -113,7 +124,9 @@ def scale(selection, scale, center=App.Vector(0, 0, 0),
|
||||
if copy or clone:
|
||||
for obj in objs:
|
||||
if obj.isDerivedFrom("App::DocumentObjectGroup") and obj.Name not in newgroups:
|
||||
newgroups[obj.Name] = obj.Document.addObject(obj.TypeId, utils.get_real_name(obj.Name))
|
||||
newgroups[obj.Name] = obj.Document.addObject(
|
||||
obj.TypeId, utils.get_real_name(obj.Name)
|
||||
)
|
||||
|
||||
for idx, obj in enumerate(objs):
|
||||
newobj = None
|
||||
@@ -174,7 +187,9 @@ def scale(selection, scale, center=App.Vector(0, 0, 0),
|
||||
continue
|
||||
if sx == sy == sz:
|
||||
newobj = make_clone.make_clone(obj, forcedraft=True)
|
||||
newobj.Placement.Base = scale_vector_from_center(newobj.Placement.Base, scale, center)
|
||||
newobj.Placement.Base = scale_vector_from_center(
|
||||
newobj.Placement.Base, scale, center
|
||||
)
|
||||
newobj.Scale = scale
|
||||
else:
|
||||
if parent_place.isIdentity():
|
||||
@@ -221,10 +236,10 @@ def scale(selection, scale, center=App.Vector(0, 0, 0),
|
||||
else:
|
||||
pla = parent_place * obj.Placement
|
||||
pts = [
|
||||
App.Vector (0.0, 0.0, 0.0),
|
||||
App.Vector (obj.Length.Value, 0.0, 0.0),
|
||||
App.Vector (obj.Length.Value, obj.Height.Value, 0.0),
|
||||
App.Vector (0.0, obj.Height.Value, 0.0)
|
||||
App.Vector(0.0, 0.0, 0.0),
|
||||
App.Vector(obj.Length.Value, 0.0, 0.0),
|
||||
App.Vector(obj.Length.Value, obj.Height.Value, 0.0),
|
||||
App.Vector(0.0, obj.Height.Value, 0.0),
|
||||
]
|
||||
pts = [pla.multVec(p) for p in pts]
|
||||
pts = [scale_vector_from_center(p, scale, center) for p in pts]
|
||||
@@ -232,7 +247,7 @@ def scale(selection, scale, center=App.Vector(0, 0, 0),
|
||||
x_vec = pts[1] - pts[0]
|
||||
y_vec = pts[3] - pts[0]
|
||||
ang = x_vec.getAngle(y_vec)
|
||||
if math.isclose(ang % math.pi/2, math.pi/4, abs_tol=1e-6):
|
||||
if math.isclose(ang % math.pi / 2, math.pi / 4, abs_tol=1e-6):
|
||||
if copy:
|
||||
newobj = make_copy.make_copy(obj)
|
||||
newobj.Placement = pla
|
||||
@@ -275,6 +290,7 @@ def scale(selection, scale, center=App.Vector(0, 0, 0),
|
||||
|
||||
if create_non_parametric:
|
||||
import Part
|
||||
|
||||
if parent_place.isIdentity():
|
||||
pla = obj.Placement
|
||||
else:
|
||||
@@ -288,6 +304,7 @@ def scale(selection, scale, center=App.Vector(0, 0, 0),
|
||||
if App.GuiUp:
|
||||
if utils.get_type(obj) in ("Circle", "Ellipse"):
|
||||
from draftviewproviders.view_base import ViewProviderDraft
|
||||
|
||||
ViewProviderDraft(newobj.ViewObject)
|
||||
else:
|
||||
newobj.ViewObject.Proxy = 0
|
||||
@@ -384,7 +401,7 @@ def scale_edge(obj, edge_idx, scale, center, global_place=None):
|
||||
if utils.is_closed_edge(edge_idx, obj):
|
||||
scale_vertex(obj, 0, scale, center, global_place)
|
||||
else:
|
||||
scale_vertex(obj, edge_idx+1, scale, center, global_place)
|
||||
scale_vertex(obj, edge_idx + 1, scale, center, global_place)
|
||||
|
||||
|
||||
def copy_scaled_edge(obj, edge_idx, scale, center, global_place=None):
|
||||
@@ -400,9 +417,10 @@ def copy_scaled_edge(obj, edge_idx, scale, center, global_place=None):
|
||||
if utils.is_closed_edge(edge_idx, obj):
|
||||
vertex2 = scale_vector_from_center(glp.multVec(obj.Points[0]), scale, center)
|
||||
else:
|
||||
vertex2 = scale_vector_from_center(glp.multVec(obj.Points[edge_idx+1]), scale, center)
|
||||
vertex2 = scale_vector_from_center(glp.multVec(obj.Points[edge_idx + 1]), scale, center)
|
||||
newobj = make_line.make_line(vertex1, vertex2)
|
||||
gui_utils.format_object(newobj, obj)
|
||||
return newobj
|
||||
|
||||
|
||||
## @}
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
from draftmake import make_copy
|
||||
from draftutils import utils
|
||||
|
||||
|
||||
def split(wire, newPoint, edgeIndex):
|
||||
if utils.get_type(wire) != "Wire":
|
||||
return None
|
||||
@@ -44,8 +45,10 @@ def split_closed_wire(wire, edgeIndex):
|
||||
if edgeIndex == len(wire.Points):
|
||||
new.Points = [wire.Points[0], wire.Points[-1]]
|
||||
else:
|
||||
new.Points = [wire.Points[edgeIndex-1], wire.Points[edgeIndex]]
|
||||
wire.Points = list(reversed(wire.Points[0:edgeIndex])) + list(reversed(wire.Points[edgeIndex:]))
|
||||
new.Points = [wire.Points[edgeIndex - 1], wire.Points[edgeIndex]]
|
||||
wire.Points = list(reversed(wire.Points[0:edgeIndex])) + list(
|
||||
reversed(wire.Points[edgeIndex:])
|
||||
)
|
||||
return new
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -21,8 +21,7 @@
|
||||
# * USA *
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
"""Provides functions to return the SVG representation of some shapes.
|
||||
"""
|
||||
"""Provides functions to return the SVG representation of some shapes."""
|
||||
## @package svgshapes
|
||||
# \ingroup draftfunctions
|
||||
# \brief Provides functions to return the SVG representation of some shapes.
|
||||
@@ -95,21 +94,21 @@ def get_discretized(edge, plane):
|
||||
if pieces == 0:
|
||||
pieces = 10
|
||||
|
||||
d = int(edge.Length/pieces)
|
||||
d = int(edge.Length / pieces)
|
||||
if d == 0:
|
||||
d = 1
|
||||
|
||||
edata = ""
|
||||
for i in range(d + 1):
|
||||
_length = edge.LastParameter - edge.FirstParameter
|
||||
_point = edge.FirstParameter + float(i)/d * _length
|
||||
_point = edge.FirstParameter + float(i) / d * _length
|
||||
_vec = edge.valueAt(_point)
|
||||
v = get_proj(_vec, plane)
|
||||
|
||||
if not edata:
|
||||
edata += 'M ' + str(v.x) + ' ' + str(v.y) + ' '
|
||||
edata += "M " + str(v.x) + " " + str(v.y) + " "
|
||||
else:
|
||||
edata += 'L ' + str(v.x) + ' ' + str(v.y) + ' '
|
||||
edata += "L " + str(v.x) + " " + str(v.y) + " "
|
||||
|
||||
return edata
|
||||
|
||||
@@ -120,9 +119,9 @@ def getDiscretized(edge, plane):
|
||||
return get_discretized(edge, plane)
|
||||
|
||||
|
||||
def _get_path_circ_ellipse(plane, edge, verts, edata,
|
||||
iscircle, isellipse,
|
||||
fill, stroke, linewidth, lstyle):
|
||||
def _get_path_circ_ellipse(
|
||||
plane, edge, verts, edata, iscircle, isellipse, fill, stroke, linewidth, lstyle
|
||||
):
|
||||
"""Get the edge data from a path that is a circle or ellipse."""
|
||||
if plane:
|
||||
drawing_plane_normal = plane.axis
|
||||
@@ -166,9 +165,7 @@ def _get_path_circ_ellipse(plane, edge, verts, edata,
|
||||
if not done:
|
||||
if len(edge.Vertexes) == 1 and iscircle:
|
||||
# Complete circle not only arc
|
||||
svg = get_circle(plane,
|
||||
fill, stroke, linewidth, lstyle,
|
||||
edge)
|
||||
svg = get_circle(plane, fill, stroke, linewidth, lstyle, edge)
|
||||
# If it's a circle we will return the final SVG string,
|
||||
# otherwise it will process the `edata` further
|
||||
return "svg", svg
|
||||
@@ -180,9 +177,8 @@ def _get_path_circ_ellipse(plane, edge, verts, edata,
|
||||
# return svg
|
||||
|
||||
# Difference in angles
|
||||
_diff = (center.LastParameter - center.FirstParameter)/2.0
|
||||
endpoints = [get_proj(center.value(_diff), plane),
|
||||
get_proj(verts[-1].Point, plane)]
|
||||
_diff = (center.LastParameter - center.FirstParameter) / 2.0
|
||||
endpoints = [get_proj(center.value(_diff), plane), get_proj(verts[-1].Point, plane)]
|
||||
else:
|
||||
endpoints = [get_proj(verts[-1].Point, plane)]
|
||||
|
||||
@@ -213,16 +209,15 @@ def _get_path_circ_ellipse(plane, edge, verts, edata,
|
||||
# between tangents
|
||||
_diff = edge.LastParameter - edge.FirstParameter
|
||||
t1 = edge.tangentAt(edge.FirstParameter)
|
||||
t2 = edge.tangentAt(edge.FirstParameter + _diff/10)
|
||||
t2 = edge.tangentAt(edge.FirstParameter + _diff / 10)
|
||||
flag_sweep = DraftVecUtils.angle(t1, t2, drawing_plane_normal) < 0
|
||||
|
||||
for v in endpoints:
|
||||
edata += ('A {} {} {} '
|
||||
'{} {} '
|
||||
'{} {} '.format(rx, ry, rot,
|
||||
int(flag_large_arc),
|
||||
int(flag_sweep),
|
||||
v.x, v.y))
|
||||
edata += (
|
||||
"A {} {} {} "
|
||||
"{} {} "
|
||||
"{} {} ".format(rx, ry, rot, int(flag_large_arc), int(flag_sweep), v.x, v.y)
|
||||
)
|
||||
|
||||
return "edata", edata
|
||||
|
||||
@@ -232,7 +227,7 @@ def _get_path_bspline(plane, edge, edata):
|
||||
bspline = edge.Curve.toBSpline(edge.FirstParameter, edge.LastParameter)
|
||||
if bspline.Degree > 3 or bspline.isRational():
|
||||
try:
|
||||
bspline = bspline.approximateBSpline(0.05, 50, 3, 'C0')
|
||||
bspline = bspline.approximateBSpline(0.05, 50, 3, "C0")
|
||||
except RuntimeError:
|
||||
_wrn("Debug: unable to approximate bspline from edge")
|
||||
|
||||
@@ -242,30 +237,30 @@ def _get_path_bspline(plane, edge, edata):
|
||||
_wrn("Bezier segment of degree > 3")
|
||||
raise AssertionError
|
||||
elif bezierseg.Degree == 1:
|
||||
edata += 'L '
|
||||
edata += "L "
|
||||
elif bezierseg.Degree == 2:
|
||||
edata += 'Q '
|
||||
edata += "Q "
|
||||
elif bezierseg.Degree == 3:
|
||||
edata += 'C '
|
||||
edata += "C "
|
||||
|
||||
for pole in bezierseg.getPoles()[1:]:
|
||||
v = get_proj(pole, plane)
|
||||
edata += '{} {} '.format(v.x, v.y)
|
||||
edata += "{} {} ".format(v.x, v.y)
|
||||
else:
|
||||
_msg("Debug: one edge (hash {}) "
|
||||
"has been discretized "
|
||||
"with parameter 0.1".format(edge.hashCode()))
|
||||
_msg(
|
||||
"Debug: one edge (hash {}) "
|
||||
"has been discretized "
|
||||
"with parameter 0.1".format(edge.hashCode())
|
||||
)
|
||||
|
||||
for linepoint in bspline.discretize(0.1)[1:]:
|
||||
v = get_proj(linepoint, plane)
|
||||
edata += 'L {} {} '.format(v.x, v.y)
|
||||
edata += "L {} {} ".format(v.x, v.y)
|
||||
|
||||
return edata
|
||||
|
||||
|
||||
def get_circle(plane,
|
||||
fill, stroke, linewidth, lstyle,
|
||||
edge):
|
||||
def get_circle(plane, fill, stroke, linewidth, lstyle, edge):
|
||||
"""Get the SVG representation from a circular edge."""
|
||||
cen = get_proj(edge.Curve.Center, plane)
|
||||
rad = edge.Curve.Radius
|
||||
@@ -277,7 +272,7 @@ def get_circle(plane,
|
||||
|
||||
if round(edge.Curve.Axis.getAngle(drawing_plane_normal), 2) in [0, 3.14]:
|
||||
# Perpendicular projection: circle
|
||||
svg = '<circle '
|
||||
svg = "<circle "
|
||||
svg += 'cx="{}" cy="{}" r="{}" '.format(cen.x, cen.y, rad)
|
||||
else:
|
||||
# Any other projection: ellipse
|
||||
@@ -288,57 +283,60 @@ def get_circle(plane,
|
||||
# for the generated SVG?
|
||||
svg += 'stroke-width="{} px" '.format(linewidth)
|
||||
svg += 'style="'
|
||||
svg += 'stroke-width:{};'.format(linewidth)
|
||||
svg += 'stroke-miterlimit:4;'
|
||||
svg += 'stroke-dasharray:{};'.format(lstyle)
|
||||
svg += 'stroke-linecap:square;'
|
||||
svg += 'fill:{}'.format(fill) + '"'
|
||||
svg += '/>\n'
|
||||
svg += "stroke-width:{};".format(linewidth)
|
||||
svg += "stroke-miterlimit:4;"
|
||||
svg += "stroke-dasharray:{};".format(lstyle)
|
||||
svg += "stroke-linecap:square;"
|
||||
svg += "fill:{}".format(fill) + '"'
|
||||
svg += "/>\n"
|
||||
return svg
|
||||
|
||||
|
||||
def getCircle(plane,
|
||||
fill, stroke, linewidth, lstyle,
|
||||
edge):
|
||||
def getCircle(plane, fill, stroke, linewidth, lstyle, edge):
|
||||
"""Get the SVG representation from a circular edge."""
|
||||
utils.use_instead("get_circle")
|
||||
return get_circle(plane, fill, stroke, linewidth, lstyle, edge)
|
||||
|
||||
|
||||
def get_ellipse(plane,
|
||||
fill, stroke, linewidth, lstyle,
|
||||
edge):
|
||||
def get_ellipse(plane, fill, stroke, linewidth, lstyle, edge):
|
||||
"""Get the SVG representation from an elliptical edge."""
|
||||
cen = get_proj(edge.Curve.Center, plane)
|
||||
mir = edge.Curve.MinorRadius
|
||||
mar = edge.Curve.MajorRadius
|
||||
svg = '<ellipse '
|
||||
svg = "<ellipse "
|
||||
svg += 'cx="{}" cy="{}" '.format(cen.x, cen.y)
|
||||
svg += 'rx="{}" ry="{}" '.format(mar, mir)
|
||||
svg += 'stroke="{}" '.format(stroke)
|
||||
svg += 'stroke-width="{} px" '.format(linewidth)
|
||||
svg += 'style="'
|
||||
svg += 'stroke-width:{};'.format(linewidth)
|
||||
svg += 'stroke-miterlimit:4;'
|
||||
svg += 'stroke-dasharray:{};'.format(lstyle)
|
||||
svg += 'stroke-linecap:square;'
|
||||
svg += 'fill:{}'.format(fill) + '"'
|
||||
svg += '/>\n'
|
||||
svg += "stroke-width:{};".format(linewidth)
|
||||
svg += "stroke-miterlimit:4;"
|
||||
svg += "stroke-dasharray:{};".format(lstyle)
|
||||
svg += "stroke-linecap:square;"
|
||||
svg += "fill:{}".format(fill) + '"'
|
||||
svg += "/>\n"
|
||||
return svg
|
||||
|
||||
|
||||
def getEllipse(plane,
|
||||
fill, stroke, linewidth, lstyle,
|
||||
edge):
|
||||
def getEllipse(plane, fill, stroke, linewidth, lstyle, edge):
|
||||
"""Get the SVG representation from an elliptical edge. DEPRECATED."""
|
||||
utils.use_instead("get_ellipse")
|
||||
return get_ellipse(plane, fill, stroke, linewidth, lstyle, edge)
|
||||
|
||||
|
||||
def get_path(obj, plane,
|
||||
fill, pathdata, stroke, linewidth, lstyle,
|
||||
fill_opacity=None,
|
||||
edges=[], wires=[], pathname=None):
|
||||
def get_path(
|
||||
obj,
|
||||
plane,
|
||||
fill,
|
||||
pathdata,
|
||||
stroke,
|
||||
linewidth,
|
||||
lstyle,
|
||||
fill_opacity=None,
|
||||
edges=[],
|
||||
wires=[],
|
||||
pathname=None,
|
||||
):
|
||||
"""Get the SVG representation from an object's edges or wires.
|
||||
|
||||
TODO: the `edges` and `wires` must not default to empty list `[]`
|
||||
@@ -382,28 +380,27 @@ def get_path(obj, plane,
|
||||
if len(_edges) > 1:
|
||||
last_pt = verts[-1].Point
|
||||
nextverts = _edges[1].Vertexes
|
||||
if (last_pt - nextverts[0].Point).Length > 1e-6 \
|
||||
and (last_pt - nextverts[-1].Point).Length > 1e-6:
|
||||
if (last_pt - nextverts[0].Point).Length > 1e-6 and (
|
||||
last_pt - nextverts[-1].Point
|
||||
).Length > 1e-6:
|
||||
verts.reverse()
|
||||
v = get_proj(verts[0].Point, plane)
|
||||
edata += 'M {} {} '.format(v.x, v.y)
|
||||
edata += "M {} {} ".format(v.x, v.y)
|
||||
else:
|
||||
previousverts = verts
|
||||
verts = edge.Vertexes
|
||||
if (verts[0].Point - previousverts[-1].Point).Length > 1e-6:
|
||||
verts.reverse()
|
||||
if (verts[0].Point - previousverts[-1].Point).Length > 1e-6:
|
||||
raise ValueError('edges not ordered')
|
||||
raise ValueError("edges not ordered")
|
||||
|
||||
iscircle = DraftGeomUtils.geomType(edge) == "Circle"
|
||||
isellipse = DraftGeomUtils.geomType(edge) == "Ellipse"
|
||||
|
||||
if iscircle or isellipse:
|
||||
_type, data = _get_path_circ_ellipse(plane, edge, verts,
|
||||
edata,
|
||||
iscircle, isellipse,
|
||||
fill, stroke,
|
||||
linewidth, lstyle)
|
||||
_type, data = _get_path_circ_ellipse(
|
||||
plane, edge, verts, edata, iscircle, isellipse, fill, stroke, linewidth, lstyle
|
||||
)
|
||||
if _type == "svg":
|
||||
# final svg string already calculated, so just return it
|
||||
return data
|
||||
@@ -412,14 +409,14 @@ def get_path(obj, plane,
|
||||
edata = data
|
||||
elif DraftGeomUtils.geomType(edge) == "Line":
|
||||
v = get_proj(verts[-1].Point, plane)
|
||||
edata += 'L {} {} '.format(v.x, v.y)
|
||||
edata += "L {} {} ".format(v.x, v.y)
|
||||
else:
|
||||
# If it's not a circle nor ellipse nor straight line
|
||||
# convert the curve to BSpline
|
||||
edata = _get_path_bspline(plane, edge, edata)
|
||||
|
||||
if fill != 'none':
|
||||
edata += 'Z '
|
||||
if fill != "none":
|
||||
edata += "Z "
|
||||
|
||||
if edata in pathdata:
|
||||
# do not draw a path on another identical path
|
||||
@@ -432,29 +429,48 @@ def get_path(obj, plane,
|
||||
svg += 'stroke="{}" '.format(stroke)
|
||||
svg += 'stroke-width="{} px" '.format(linewidth)
|
||||
svg += 'style="'
|
||||
svg += 'stroke-width:{};'.format(linewidth)
|
||||
svg += 'stroke-miterlimit:4;'
|
||||
svg += 'stroke-dasharray:{};'.format(lstyle)
|
||||
svg += 'stroke-linecap:square;'
|
||||
svg += 'fill:{};'.format(fill)
|
||||
svg += "stroke-width:{};".format(linewidth)
|
||||
svg += "stroke-miterlimit:4;"
|
||||
svg += "stroke-dasharray:{};".format(lstyle)
|
||||
svg += "stroke-linecap:square;"
|
||||
svg += "fill:{};".format(fill)
|
||||
# fill_opacity must be a number, but if it's `None` it is omitted
|
||||
if fill_opacity is not None:
|
||||
svg += 'fill-opacity:{};'.format(fill_opacity)
|
||||
svg += "fill-opacity:{};".format(fill_opacity)
|
||||
|
||||
svg += 'fill-rule: evenodd"'
|
||||
svg += '/>\n'
|
||||
svg += "/>\n"
|
||||
return svg
|
||||
|
||||
|
||||
def getPath(obj, plane,
|
||||
fill, pathdata, stroke, linewidth, lstyle,
|
||||
fill_opacity,
|
||||
edges=[], wires=[], pathname=None):
|
||||
def getPath(
|
||||
obj,
|
||||
plane,
|
||||
fill,
|
||||
pathdata,
|
||||
stroke,
|
||||
linewidth,
|
||||
lstyle,
|
||||
fill_opacity,
|
||||
edges=[],
|
||||
wires=[],
|
||||
pathname=None,
|
||||
):
|
||||
"""Get the SVG representation from a path. DEPRECATED."""
|
||||
utils.use_instead("get_path")
|
||||
return get_path(obj, plane,
|
||||
fill, pathdata, stroke, linewidth, lstyle,
|
||||
fill_opacity,
|
||||
edges=edges, wires=wires, pathname=pathname)
|
||||
return get_path(
|
||||
obj,
|
||||
plane,
|
||||
fill,
|
||||
pathdata,
|
||||
stroke,
|
||||
linewidth,
|
||||
lstyle,
|
||||
fill_opacity,
|
||||
edges=edges,
|
||||
wires=wires,
|
||||
pathname=pathname,
|
||||
)
|
||||
|
||||
|
||||
## @}
|
||||
|
||||
@@ -36,9 +36,7 @@ import draftutils.utils as utils
|
||||
# @{
|
||||
|
||||
|
||||
def _get_text_techdraw(text, tcolor, fontsize, anchor,
|
||||
align, fontname, angle, base,
|
||||
linespacing):
|
||||
def _get_text_techdraw(text, tcolor, fontsize, anchor, align, fontname, angle, base, linespacing):
|
||||
"""Return the SVG representation of text for TechDraw display.
|
||||
|
||||
`text` is a list of textual elements; they are iterated, styled,
|
||||
@@ -56,28 +54,23 @@ def _get_text_techdraw(text, tcolor, fontsize, anchor,
|
||||
_t = _t.replace("<", "<")
|
||||
t = _t.replace(">", ">")
|
||||
|
||||
svg += '<text '
|
||||
svg += "<text "
|
||||
svg += 'stroke-width="0" stroke="{}" '.format(tcolor)
|
||||
svg += 'fill="{}" font-size="{}" '.format(tcolor, fontsize)
|
||||
svg += 'style="text-anchor:{};text-align:{};'.format(anchor,
|
||||
align.lower())
|
||||
svg += 'style="text-anchor:{};text-align:{};'.format(anchor, align.lower())
|
||||
svg += 'font-family:{}" '.format(fontname)
|
||||
svg += 'transform="'
|
||||
svg += 'rotate({},{},{}) '.format(math.degrees(angle),
|
||||
point.x,
|
||||
point.y)
|
||||
svg += 'translate({},{}) '.format(point.x,
|
||||
point.y)
|
||||
svg += "rotate({},{},{}) ".format(math.degrees(angle), point.x, point.y)
|
||||
svg += "translate({},{}) ".format(point.x, point.y)
|
||||
svg += 'scale(1,-1)"'
|
||||
# svg += 'freecad:skip="1"'
|
||||
svg += '>\n'
|
||||
svg += ">\n"
|
||||
svg += t
|
||||
svg += '</text>\n'
|
||||
svg += "</text>\n"
|
||||
return svg
|
||||
|
||||
|
||||
def _get_text_header(tcolor, fontsize, anchor, align,
|
||||
fontname, angle, base, flip):
|
||||
def _get_text_header(tcolor, fontsize, anchor, align, fontname, angle, base, flip):
|
||||
"""Return the initial <text> tag with style options.
|
||||
|
||||
The text must be added after this tag, and then must be closed.
|
||||
@@ -86,37 +79,43 @@ def _get_text_header(tcolor, fontsize, anchor, align,
|
||||
...
|
||||
</text>
|
||||
"""
|
||||
svg = '<text '
|
||||
svg = "<text "
|
||||
svg += 'stroke-width="0" stroke="{}" '.format(tcolor)
|
||||
svg += 'fill="{}" font-size="{}" '.format(tcolor, fontsize)
|
||||
svg += 'style="text-anchor:{};text-align:{};'.format(anchor,
|
||||
align.lower())
|
||||
svg += 'style="text-anchor:{};text-align:{};'.format(anchor, align.lower())
|
||||
svg += 'font-family:{}" '.format(fontname)
|
||||
svg += 'transform="'
|
||||
svg += 'rotate({},{},{}) '.format(math.degrees(angle),
|
||||
base.x,
|
||||
base.y)
|
||||
svg += "rotate({},{},{}) ".format(math.degrees(angle), base.x, base.y)
|
||||
if flip:
|
||||
svg += 'translate({},{}) '.format(base.x, base.y)
|
||||
svg += "translate({},{}) ".format(base.x, base.y)
|
||||
else:
|
||||
svg += 'translate({},{}) '.format(base.x, -base.y)
|
||||
svg += "translate({},{}) ".format(base.x, -base.y)
|
||||
# svg += 'scale({},-{}) '.format(tmod/2000, tmod/2000)
|
||||
|
||||
if flip:
|
||||
svg += 'scale(1,-1) '
|
||||
svg += "scale(1,-1) "
|
||||
else:
|
||||
svg += 'scale(1,1) '
|
||||
svg += "scale(1,1) "
|
||||
|
||||
svg += '" '
|
||||
svg += 'freecad:skip="1"'
|
||||
svg += '>\n'
|
||||
svg += ">\n"
|
||||
return svg
|
||||
|
||||
|
||||
def get_text(plane, techdraw,
|
||||
tcolor, fontsize, fontname,
|
||||
angle, base, text,
|
||||
linespacing=0.5, align="center", flip=True):
|
||||
def get_text(
|
||||
plane,
|
||||
techdraw,
|
||||
tcolor,
|
||||
fontsize,
|
||||
fontname,
|
||||
angle,
|
||||
base,
|
||||
text,
|
||||
linespacing=0.5,
|
||||
align="center",
|
||||
flip=True,
|
||||
):
|
||||
"""Get the SVG representation of a textual element."""
|
||||
if isinstance(angle, App.Rotation):
|
||||
if not plane:
|
||||
@@ -129,14 +128,14 @@ def get_text(plane, techdraw,
|
||||
angle = -angle.Angle
|
||||
else:
|
||||
angle = angle.Angle
|
||||
elif abs(plane.axis.getAngle(angle.Axis) - math.pi/2) < 0.001:
|
||||
elif abs(plane.axis.getAngle(angle.Axis) - math.pi / 2) < 0.001:
|
||||
# text is perpendicular to view, so it shouldn't appear
|
||||
return ""
|
||||
else:
|
||||
# Compute an X vector
|
||||
vec = App.Vector(1,0,0)
|
||||
vec = angle.multVec(App.Vector(1,0,0))
|
||||
angle = DraftVecUtils.angle(vec,plane.u)
|
||||
vec = App.Vector(1, 0, 0)
|
||||
vec = angle.multVec(App.Vector(1, 0, 0))
|
||||
angle = DraftVecUtils.angle(vec, plane.u)
|
||||
|
||||
# text should be a list of strings separated by a newline
|
||||
if not isinstance(text, list):
|
||||
@@ -154,9 +153,9 @@ def get_text(plane, techdraw,
|
||||
# in an individual tag.
|
||||
# <text ...> text[0] </text>
|
||||
# <text ...> text[1] </text>
|
||||
svg = _get_text_techdraw(text, tcolor, fontsize, anchor,
|
||||
align, fontname, angle, base,
|
||||
linespacing)
|
||||
svg = _get_text_techdraw(
|
||||
text, tcolor, fontsize, anchor, align, fontname, angle, base, linespacing
|
||||
)
|
||||
else:
|
||||
# If the SVG is not for TechDraw, and there is a single item
|
||||
# in the text list, place it in a single tag.
|
||||
@@ -167,8 +166,7 @@ def get_text(plane, techdraw,
|
||||
# <tspan>text[0]</tspan>
|
||||
# <tspan>text[1]</tspan>
|
||||
# </text>
|
||||
svg = _get_text_header(tcolor, fontsize, anchor, align,
|
||||
fontname, angle, base, flip)
|
||||
svg = _get_text_header(tcolor, fontsize, anchor, align, fontname, angle, base, flip)
|
||||
|
||||
if len(text) == 1:
|
||||
_t = text[0].replace("&", "&").replace("<", "<")
|
||||
@@ -176,25 +174,34 @@ def get_text(plane, techdraw,
|
||||
else:
|
||||
for i in range(len(text)):
|
||||
if i == 0:
|
||||
svg += '<tspan>'
|
||||
svg += "<tspan>"
|
||||
else:
|
||||
svg += '<tspan x="0" dy="{}">'.format(linespacing)
|
||||
_t = text[i].replace("&", "&").replace("<", "<")
|
||||
svg += _t.replace(">", ">")
|
||||
svg += '</tspan>\n'
|
||||
svg += '</text>\n'
|
||||
svg += "</tspan>\n"
|
||||
svg += "</text>\n"
|
||||
return svg
|
||||
|
||||
|
||||
def getText(plane, techdraw,
|
||||
tcolor, fontsize, fontname,
|
||||
angle, base, text,
|
||||
linespacing=0.5, align="center", flip=True):
|
||||
def getText(
|
||||
plane,
|
||||
techdraw,
|
||||
tcolor,
|
||||
fontsize,
|
||||
fontname,
|
||||
angle,
|
||||
base,
|
||||
text,
|
||||
linespacing=0.5,
|
||||
align="center",
|
||||
flip=True,
|
||||
):
|
||||
"""Get the SVG representation of a textual element. DEPRECATED."""
|
||||
utils.use_instead("get_text")
|
||||
return get_text(plane, techdraw,
|
||||
tcolor, fontsize, fontname,
|
||||
angle, base, text,
|
||||
linespacing, align, flip)
|
||||
return get_text(
|
||||
plane, techdraw, tcolor, fontsize, fontname, angle, base, text, linespacing, align, flip
|
||||
)
|
||||
|
||||
|
||||
## @}
|
||||
|
||||
@@ -220,8 +220,9 @@ def upgrade(objects, delete=False, force=None):
|
||||
new_area = new_face.Area
|
||||
new_cen = new_face.CenterOfMass
|
||||
for old_area, old_cen, old_color in old_data:
|
||||
if math.isclose(new_area, old_area, abs_tol=1e-7) \
|
||||
and new_cen.isEqual(old_cen, 1e-7):
|
||||
if math.isclose(new_area, old_area, abs_tol=1e-7) and new_cen.isEqual(
|
||||
old_cen, 1e-7
|
||||
):
|
||||
new_colors.append(old_color)
|
||||
break
|
||||
newobj.ViewObject.DiffuseColor = new_colors
|
||||
@@ -316,8 +317,11 @@ def upgrade(objects, delete=False, force=None):
|
||||
for cluster in sorted_edges:
|
||||
for edge in cluster:
|
||||
print("Curve: {}".format(edge.Curve))
|
||||
print("first: {}, last: {}".format(edge.Vertexes[0].Point,
|
||||
edge.Vertexes[-1].Point))
|
||||
print(
|
||||
"first: {}, last: {}".format(
|
||||
edge.Vertexes[0].Point, edge.Vertexes[-1].Point
|
||||
)
|
||||
)
|
||||
wires = [Part.Wire(cluster) for cluster in sorted_edges]
|
||||
except Part.OCCError:
|
||||
return False
|
||||
@@ -349,7 +353,6 @@ def upgrade(objects, delete=False, force=None):
|
||||
delete_list.append(obj)
|
||||
return True
|
||||
|
||||
|
||||
# helper functions (same as in downgrade.py)
|
||||
|
||||
def get_parent(obj):
|
||||
@@ -413,7 +416,6 @@ def upgrade(objects, delete=False, force=None):
|
||||
for newobj in new_list:
|
||||
gui_utils.format_object(newobj, obj, ignore_construction=True)
|
||||
|
||||
|
||||
doc = App.ActiveDocument
|
||||
add_list = []
|
||||
delete_list = []
|
||||
@@ -476,17 +478,21 @@ def upgrade(objects, delete=False, force=None):
|
||||
result = turnToParts(meshes)
|
||||
else:
|
||||
# functions that work on a single object:
|
||||
single_funcs = {"closeWire": closeWire,
|
||||
"draftify": _draftify,
|
||||
"makeSketchFace": makeSketchFace,
|
||||
"makeSolid": makeSolid}
|
||||
single_funcs = {
|
||||
"closeWire": closeWire,
|
||||
"draftify": _draftify,
|
||||
"makeSketchFace": makeSketchFace,
|
||||
"makeSolid": makeSolid,
|
||||
}
|
||||
# functions that work on multiple objects:
|
||||
multi_funcs = {"joinFaces": joinFaces,
|
||||
"makeCompound": makeCompound,
|
||||
"makeFaces": makeFaces,
|
||||
"makeFusion": makeFusion,
|
||||
"makeShell": makeShell,
|
||||
"makeWires": makeWires}
|
||||
multi_funcs = {
|
||||
"joinFaces": joinFaces,
|
||||
"makeCompound": makeCompound,
|
||||
"makeFaces": makeFaces,
|
||||
"makeFusion": makeFusion,
|
||||
"makeShell": makeShell,
|
||||
"makeWires": makeWires,
|
||||
}
|
||||
if force in single_funcs:
|
||||
result = any([single_funcs[force](obj) for obj in objects])
|
||||
elif force in multi_funcs:
|
||||
@@ -536,39 +542,55 @@ def upgrade(objects, delete=False, force=None):
|
||||
_msg(translate("draft", "Found 1 solidifiable object: solidifying it"))
|
||||
|
||||
# we have exactly 2 objects: we fuse them
|
||||
elif len(objects) == 2 \
|
||||
and not faces_coplanarity \
|
||||
and same_parent \
|
||||
and same_parent_type != "PartDesign::Body":
|
||||
elif (
|
||||
len(objects) == 2
|
||||
and not faces_coplanarity
|
||||
and same_parent
|
||||
and same_parent_type != "PartDesign::Body"
|
||||
):
|
||||
result = makeFusion(objects)
|
||||
if result:
|
||||
_msg(translate("draft", "Found 2 objects: fusing them"))
|
||||
|
||||
# we have many separate faces: we try to make a shell or compound
|
||||
elif len(objects) > 1 \
|
||||
and len(faces) > 1 \
|
||||
and same_parent \
|
||||
and same_parent_type != "PartDesign::Body":
|
||||
elif (
|
||||
len(objects) > 1
|
||||
and len(faces) > 1
|
||||
and same_parent
|
||||
and same_parent_type != "PartDesign::Body"
|
||||
):
|
||||
result = makeShell(objects)
|
||||
if result:
|
||||
_msg(translate(
|
||||
"draft",
|
||||
"Found several objects: creating a " + result.Shape.ShapeType
|
||||
))
|
||||
_msg(
|
||||
translate(
|
||||
"draft", "Found several objects: creating a " + result.Shape.ShapeType
|
||||
)
|
||||
)
|
||||
|
||||
# we have faces: we try to join them if they are coplanar
|
||||
elif len(objects) == 1 and len(faces) > 1 and faces_coplanarity:
|
||||
result = joinFaces(objects)
|
||||
if result:
|
||||
_msg(translate("draft", "Found object with several coplanar faces: refining them"))
|
||||
_msg(
|
||||
translate(
|
||||
"draft", "Found object with several coplanar faces: refining them"
|
||||
)
|
||||
)
|
||||
|
||||
# only one object: if not parametric, we "draftify" it
|
||||
elif len(objects) == 1 \
|
||||
and not objects[0].isDerivedFrom("Part::Part2DObjectPython") \
|
||||
and not utils.get_type(objects[0]) in ["BezCurve", "BSpline", "Wire"]:
|
||||
elif (
|
||||
len(objects) == 1
|
||||
and not objects[0].isDerivedFrom("Part::Part2DObjectPython")
|
||||
and not utils.get_type(objects[0]) in ["BezCurve", "BSpline", "Wire"]
|
||||
):
|
||||
result = _draftify(objects[0])
|
||||
if result:
|
||||
_msg(translate("draft", "Found 1 non-parametric object: replacing it with a Draft object"))
|
||||
_msg(
|
||||
translate(
|
||||
"draft",
|
||||
"Found 1 non-parametric object: replacing it with a Draft object",
|
||||
)
|
||||
)
|
||||
|
||||
# in the following cases there are no faces
|
||||
elif not faces:
|
||||
@@ -579,7 +601,11 @@ def upgrade(objects, delete=False, force=None):
|
||||
if len(objects) == 1 and objects[0].isDerivedFrom("Sketcher::SketchObject"):
|
||||
result = makeSketchFace(objects[0])
|
||||
if result:
|
||||
_msg(translate("draft", "Found 1 closed sketch object: creating a face from it"))
|
||||
_msg(
|
||||
translate(
|
||||
"draft", "Found 1 closed sketch object: creating a face from it"
|
||||
)
|
||||
)
|
||||
# only closed wires
|
||||
else:
|
||||
result = makeFaces(objects)
|
||||
@@ -594,7 +620,11 @@ def upgrade(objects, delete=False, force=None):
|
||||
else:
|
||||
result = makeCompound(objects)
|
||||
if result:
|
||||
_msg(translate("draft", "Found several non-treatable objects: creating compound"))
|
||||
_msg(
|
||||
translate(
|
||||
"draft", "Found several non-treatable objects: creating compound"
|
||||
)
|
||||
)
|
||||
|
||||
# special case, we have only one open wire. We close it, unless it has only 1 edge!
|
||||
elif len(objects) == 1 and len(openwires) == 1:
|
||||
@@ -603,16 +633,23 @@ def upgrade(objects, delete=False, force=None):
|
||||
_msg(translate("draft", "Found 1 open wire: closing it"))
|
||||
|
||||
# only one object: if not parametric, we "draftify" it
|
||||
elif len(objects) == 1 \
|
||||
and len(edges) == 1 \
|
||||
and not objects[0].isDerivedFrom("Part::Part2DObjectPython") \
|
||||
and not utils.get_type(objects[0]) in ["BezCurve", "BSpline", "Wire"]:
|
||||
elif (
|
||||
len(objects) == 1
|
||||
and len(edges) == 1
|
||||
and not objects[0].isDerivedFrom("Part::Part2DObjectPython")
|
||||
and not utils.get_type(objects[0]) in ["BezCurve", "BSpline", "Wire"]
|
||||
):
|
||||
edge_type = DraftGeomUtils.geomType(objects[0].Shape.Edges[0])
|
||||
# currently only support Line and Circle
|
||||
if edge_type in ("Line", "Circle"):
|
||||
result = _draftify(objects[0])
|
||||
if result:
|
||||
_msg(translate("draft", "Found 1 non-parametric object: replacing it with a Draft object"))
|
||||
_msg(
|
||||
translate(
|
||||
"draft",
|
||||
"Found 1 non-parametric object: replacing it with a Draft object",
|
||||
)
|
||||
)
|
||||
|
||||
# only points, no edges
|
||||
elif not edges and len(objects) > 1:
|
||||
@@ -637,4 +674,5 @@ def upgrade(objects, delete=False, force=None):
|
||||
gui_utils.select(add_list)
|
||||
return add_list, delete_list
|
||||
|
||||
|
||||
## @}
|
||||
|
||||
Reference in New Issue
Block a user