diff --git a/src/Mod/Draft/CMakeLists.txt b/src/Mod/Draft/CMakeLists.txt
index 45aa204568..b684d6f33d 100644
--- a/src/Mod/Draft/CMakeLists.txt
+++ b/src/Mod/Draft/CMakeLists.txt
@@ -98,6 +98,7 @@ SET(Draft_functions
draftfunctions/scale.py
draftfunctions/split.py
draftfunctions/svg.py
+ draftfunctions/svgshapes.py
draftfunctions/svgtext.py
draftfunctions/upgrade.py
draftfunctions/README.md
diff --git a/src/Mod/Draft/draftfunctions/svg.py b/src/Mod/Draft/draftfunctions/svg.py
index 3ceb6e5216..ca617e202f 100644
--- a/src/Mod/Draft/draftfunctions/svg.py
+++ b/src/Mod/Draft/draftfunctions/svg.py
@@ -41,13 +41,14 @@ import WorkingPlane
import draftutils.utils as utils
import draftfunctions.svgtext as svgtext
+from draftfunctions.svgshapes import get_proj, get_circle, get_path
from draftutils.utils import param
-from draftutils.messages import _msg, _wrn
+from draftutils.messages import _wrn
# Delay import of module until first use because it is heavy
Part = lz.LazyLoader("Part", globals(), "Part")
DraftGeomUtils = lz.LazyLoader("DraftGeomUtils", globals(), "DraftGeomUtils")
-Drawing = lz.LazyLoader("Drawing", globals(), "Drawing")
+# Drawing = lz.LazyLoader("Drawing", globals(), "Drawing")
## \addtogroup draftfuctions
@@ -90,80 +91,6 @@ def getLineStyle(linestyle, scale):
return get_line_style(linestyle, scale)
-def get_proj(vec, plane=None):
- """Get a projection of the vector in the plane's u and v directions.
-
- TODO: check if the same function for SVG and DXF projection can be used
- so that this function is not just duplicated code.
- This function may also be present elsewhere, like `WorkingPlane`
- or `DraftGeomUtils`, so we should avoid code duplication.
-
- Parameters
- ----------
- vec: Base::Vector3
- An arbitrary vector that will be projected on the U and V directions.
-
- plane: WorkingPlane.Plane
- An object of type `WorkingPlane`.
- """
- if not plane:
- return vec
-
- nx = DraftVecUtils.project(vec, plane.u)
- lx = nx.Length
-
- if abs(nx.getAngle(plane.u)) > 0.1:
- lx = -lx
-
- ny = DraftVecUtils.project(vec, plane.v)
- ly = ny.Length
-
- if abs(ny.getAngle(plane.v)) > 0.1:
- ly = -ly
-
- # if techdraw: buggy - we now simply do it at the end
- # ly = -ly
- return App.Vector(lx, ly, 0)
-
-
-def getProj(vec, plane=None):
- """Get a projection of a vector. DEPRECATED."""
- utils.use_instead("get_proj")
- return get_proj(vec, plane)
-
-
-def get_discretized(edge, plane):
- """Get a discretized edge on a plane."""
- pieces = param.GetFloat("svgDiscretization", 10.0)
-
- if pieces == 0:
- pieces = 10
-
- 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
- _vec = edge.valueAt(_point)
- v = get_proj(_vec, plane)
-
- if not edata:
- edata += 'M ' + str(v.x) + ' ' + str(v.y) + ' '
- else:
- edata += 'L ' + str(v.x) + ' ' + str(v.y) + ' '
-
- return edata
-
-
-def getDiscretized(edge, plane):
- """Get a discretized edge on a plane. DEPRECATED."""
- utils.use_instead("get_discretized")
- return get_discretized(edge, plane)
-
-
def get_pattern(pat):
"""Get an SVG pattern."""
patterns = utils.svg_patterns()
@@ -179,79 +106,6 @@ def getPattern(pat):
return get_pattern(pat)
-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
-
- if hasattr(App, "DraftWorkingPlane"):
- drawing_plane_normal = App.DraftWorkingPlane.axis
- else:
- drawing_plane_normal = App.Vector(0, 0, 1)
-
- if plane:
- drawing_plane_normal = plane.axis
-
- if round(edge.Curve.Axis.getAngle(drawing_plane_normal), 2) in [0, 3.14]:
- # Perpendicular projection: circle
- svg = '\n'
- return svg
-
-
-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):
- """Get the SVG representation from an elliptical edge."""
- cen = get_proj(edge.Curve.Center, plane)
- mir = edge.Curve.MinorRadius
- mar = edge.Curve.MajorRadius
- svg = '\n'
- return svg
-
-
-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_arrow(obj,
arrowtype, point, arrowsize, color, linewidth, angle=0):
"""Get the SVG representation from an arrow."""
@@ -359,270 +213,6 @@ def format_point(coords, action='L'):
return "{action}{x},{y}".format(x=coords.x, y=coords.y, action=action)
-def _get_path_circ_ellipse(plane, edge, vertex, edata,
- iscircle, isellipse,
- fill, stroke, linewidth, lstyle):
- """Get the edge data from a path that is a circle or ellipse."""
- if hasattr(App, "DraftWorkingPlane"):
- drawing_plane_normal = App.DraftWorkingPlane.axis
- else:
- drawing_plane_normal = App.Vector(0, 0, 1)
-
- if plane:
- drawing_plane_normal = plane.axis
-
- center = edge.Curve
- ax = center.Axis
-
- # The angle between the curve axis and the plane is not 0 nor 180 degrees
- _angle = math.degrees(ax.getAngle(drawing_plane_normal))
- if round(_angle, 2) not in (0, 180):
- edata += get_discretized(edge, plane)
- return "edata", edata
-
- # The angle is 0 or 180, coplanar
- occversion = Part.OCC_VERSION.split(".")
- done = False
- if int(occversion[0]) >= 7 and int(occversion[1]) >= 1:
- # if using occ >= 7.1, use HLR algorithm
- snip = Drawing.projectToSVG(edge, drawing_plane_normal)
-
- if snip:
- try:
- _a = snip.split('path d="')[1]
- _a = _a.split('"')[0]
- _a = _a.split("A")[1]
- A = "A " + _a
- except IndexError:
- # TODO: trap only specific exception.
- # Check the problem. Split didn't produce a two element list?
- _wrn("Circle or ellipse: "
- "cannot split the projection snip "
- "obtained by 'projectToSVG', "
- "continue manually.")
- else:
- edata += A
- done = True
-
- if not done:
- if len(edge.Vertexes) == 1 and iscircle:
- # Complete circle not only arc
- 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
- elif len(edge.Vertexes) == 1 and isellipse:
- # Complete ellipse not only arc
- # svg = get_ellipse(plane,
- # fill, stroke, linewidth,
- # lstyle, edge)
- # return svg
-
- # Difference in angles
- _diff = (center.LastParameter - center.FirstParameter)/2.0
- endpoints = [get_proj(center.value(_diff), plane),
- get_proj(vertex[-1].Point, plane)]
- else:
- endpoints = [get_proj(vertex[-1].Point, plane)]
-
- # Arc with more than one vertex
- if iscircle:
- rx = ry = center.Radius
- rot = 0
- else: # ellipse
- rx = center.MajorRadius
- ry = center.MinorRadius
- _rot = center.AngleXU * center.Axis * App.Vector(0, 0, 1)
- rot = math.degrees(_rot)
- if rot > 90:
- rot -= 180
- if rot < -90:
- rot += 180
-
- # Be careful with the sweep flag
- _diff = edge.ParameterRange[1] - edge.ParameterRange[0]
- _diff = _diff / math.pi
- flag_large_arc = (_diff % 2) > 1
-
- # flag_sweep = (center.Axis * drawing_plane_normal >= 0) \
- # == (edge.LastParameter > edge.FirstParameter)
- # == (edge.Orientation == "Forward")
-
- # Another method: check the direction of the angle
- # between tangents
- _diff = edge.LastParameter - edge.FirstParameter
- t1 = edge.tangentAt(edge.FirstParameter)
- 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))
-
- return "edata", edata
-
-
-def _get_path_bspline(plane, edge, edata):
- """Convert the edge to a BSpline and discretize it."""
- bspline = edge.Curve.toBSpline(edge.FirstParameter, edge.LastParameter)
- if bspline.Degree > 3 or bspline.isRational():
- try:
- bspline = bspline.approximateBSpline(0.05, 50, 3, 'C0')
- except RuntimeError:
- _wrn("Debug: unable to approximate bspline from edge")
-
- if bspline.Degree <= 3 and not bspline.isRational():
- for bezierseg in bspline.toBezier():
- if bezierseg.Degree > 3: # should not happen
- _wrn("Bezier segment of degree > 3")
- raise AssertionError
- elif bezierseg.Degree == 1:
- edata += 'L '
- elif bezierseg.Degree == 2:
- edata += 'Q '
- elif bezierseg.Degree == 3:
- edata += 'C '
-
- for pole in bezierseg.getPoles()[1:]:
- v = get_proj(pole, plane)
- edata += '{} {} '.format(v.x, v.y)
- else:
- _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)
-
- return edata
-
-
-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 `[]`
- but to `None`. Verify that the code doesn't break with this change.
-
- `edges` and `wires` are mutually exclusive. If no `wires` are provided,
- sort the `edges`, and use them. If `wires` are provided, sort the edges
- in these `wires`, and use them.
- """
- svg = " 1e-6:
- vertex.reverse()
-
- if edgeindex == 0:
- v = get_proj(vertex[0].Point, plane)
- edata += 'M {} {} '.format(v.x, v.y)
- else:
- if (vertex[0].Point - previousvs[-1].Point).Length > 1e-6:
- 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, vertex,
- edata,
- iscircle, isellipse,
- fill, stroke,
- linewidth, lstyle)
- if _type == "svg":
- # final svg string already calculated, so just return it
- return data
-
- # else the `edata` was properly augmented, so re-assing it
- edata = data
- elif DraftGeomUtils.geomType(edge) == "Line":
- v = get_proj(vertex[-1].Point, plane)
- 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 edata in pathdata:
- # do not draw a path on another identical path
- return ""
- else:
- svg += edata
- pathdata.append(edata)
-
- svg += '" '
- 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 += '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-rule: evenodd"'
- svg += '/>\n'
- return svg
-
-
-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)
-
-
def get_svg(obj,
scale=1, linewidth=0.35, fontsize=12,
fillstyle="shape color", direction=None, linestyle=None,
diff --git a/src/Mod/Draft/draftfunctions/svgshapes.py b/src/Mod/Draft/draftfunctions/svgshapes.py
new file mode 100644
index 0000000000..9ecf2c9f36
--- /dev/null
+++ b/src/Mod/Draft/draftfunctions/svgshapes.py
@@ -0,0 +1,464 @@
+# -*- coding: utf8 -*-
+# ***************************************************************************
+# * Copyright (c) 2009 Yorik van Havre *
+# * Copyright (c) 2018 George Shuklin (amarao) *
+# * Copyright (c) 2020 Eliud Cabrera Castillo *
+# * *
+# * 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 *
+# * *
+# ***************************************************************************
+"""Provides functions to return the SVG representation of some shapes.
+
+Warning: this still uses the `Drawing.projectToSVG` method to provide
+the SVG representation of certain objects.
+Therefore, even if the Drawing Workbench is obsolete, the `Drawing` module
+may not be removed completely yet. This must be checked.
+"""
+## @package svgshapes
+# \ingroup draftfuctions
+# \brief Provides functions to return the SVG representation of some shapes.
+
+import math
+import lazy_loader.lazy_loader as lz
+
+import FreeCAD as App
+import DraftVecUtils
+import draftutils.utils as utils
+
+from draftutils.utils import param
+from draftutils.messages import _msg, _wrn
+
+# Delay import of module until first use because it is heavy
+Part = lz.LazyLoader("Part", globals(), "Part")
+DraftGeomUtils = lz.LazyLoader("DraftGeomUtils", globals(), "DraftGeomUtils")
+Drawing = lz.LazyLoader("Drawing", globals(), "Drawing")
+
+## \addtogroup draftfuctions
+# @{
+
+
+def get_proj(vec, plane=None):
+ """Get a projection of the vector in the plane's u and v directions.
+
+ TODO: check if the same function for SVG and DXF projection can be used
+ so that this function is not just duplicated code.
+ This function may also be present elsewhere, like `WorkingPlane`
+ or `DraftGeomUtils`, so we should avoid code duplication.
+
+ Parameters
+ ----------
+ vec: Base::Vector3
+ An arbitrary vector that will be projected on the U and V directions.
+
+ plane: WorkingPlane.Plane
+ An object of type `WorkingPlane`.
+ """
+ if not plane:
+ return vec
+
+ nx = DraftVecUtils.project(vec, plane.u)
+ lx = nx.Length
+
+ if abs(nx.getAngle(plane.u)) > 0.1:
+ lx = -lx
+
+ ny = DraftVecUtils.project(vec, plane.v)
+ ly = ny.Length
+
+ if abs(ny.getAngle(plane.v)) > 0.1:
+ ly = -ly
+
+ # if techdraw: buggy - we now simply do it at the end
+ # ly = -ly
+ return App.Vector(lx, ly, 0)
+
+
+def getProj(vec, plane=None):
+ """Get a projection of a vector. DEPRECATED."""
+ utils.use_instead("get_proj")
+ return get_proj(vec, plane)
+
+
+def get_discretized(edge, plane):
+ """Get a discretized edge on a plane."""
+ pieces = param.GetFloat("svgDiscretization", 10.0)
+
+ if pieces == 0:
+ pieces = 10
+
+ 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
+ _vec = edge.valueAt(_point)
+ v = get_proj(_vec, plane)
+
+ if not edata:
+ edata += 'M ' + str(v.x) + ' ' + str(v.y) + ' '
+ else:
+ edata += 'L ' + str(v.x) + ' ' + str(v.y) + ' '
+
+ return edata
+
+
+def getDiscretized(edge, plane):
+ """Get a discretized edge on a plane. DEPRECATED."""
+ utils.use_instead("get_discretized")
+ return get_discretized(edge, plane)
+
+
+def _get_path_circ_ellipse(plane, edge, vertex, edata,
+ iscircle, isellipse,
+ fill, stroke, linewidth, lstyle):
+ """Get the edge data from a path that is a circle or ellipse."""
+ if hasattr(App, "DraftWorkingPlane"):
+ drawing_plane_normal = App.DraftWorkingPlane.axis
+ else:
+ drawing_plane_normal = App.Vector(0, 0, 1)
+
+ if plane:
+ drawing_plane_normal = plane.axis
+
+ center = edge.Curve
+ ax = center.Axis
+
+ # The angle between the curve axis and the plane is not 0 nor 180 degrees
+ _angle = math.degrees(ax.getAngle(drawing_plane_normal))
+ if round(_angle, 2) not in (0, 180):
+ edata += get_discretized(edge, plane)
+ return "edata", edata
+
+ # The angle is 0 or 180, coplanar
+ occversion = Part.OCC_VERSION.split(".")
+ done = False
+ if int(occversion[0]) >= 7 and int(occversion[1]) >= 1:
+ # if using occ >= 7.1, use HLR algorithm
+ snip = Drawing.projectToSVG(edge, drawing_plane_normal)
+
+ if snip:
+ try:
+ _a = snip.split('path d="')[1]
+ _a = _a.split('"')[0]
+ _a = _a.split("A")[1]
+ A = "A " + _a
+ except IndexError:
+ # TODO: trap only specific exception.
+ # Check the problem. Split didn't produce a two element list?
+ _wrn("Circle or ellipse: "
+ "cannot split the projection snip "
+ "obtained by 'projectToSVG', "
+ "continue manually.")
+ else:
+ edata += A
+ done = True
+
+ if not done:
+ if len(edge.Vertexes) == 1 and iscircle:
+ # Complete circle not only arc
+ 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
+ elif len(edge.Vertexes) == 1 and isellipse:
+ # Complete ellipse not only arc
+ # svg = get_ellipse(plane,
+ # fill, stroke, linewidth,
+ # lstyle, edge)
+ # return svg
+
+ # Difference in angles
+ _diff = (center.LastParameter - center.FirstParameter)/2.0
+ endpoints = [get_proj(center.value(_diff), plane),
+ get_proj(vertex[-1].Point, plane)]
+ else:
+ endpoints = [get_proj(vertex[-1].Point, plane)]
+
+ # Arc with more than one vertex
+ if iscircle:
+ rx = ry = center.Radius
+ rot = 0
+ else: # ellipse
+ rx = center.MajorRadius
+ ry = center.MinorRadius
+ _rot = center.AngleXU * center.Axis * App.Vector(0, 0, 1)
+ rot = math.degrees(_rot)
+ if rot > 90:
+ rot -= 180
+ if rot < -90:
+ rot += 180
+
+ # Be careful with the sweep flag
+ _diff = edge.ParameterRange[1] - edge.ParameterRange[0]
+ _diff = _diff / math.pi
+ flag_large_arc = (_diff % 2) > 1
+
+ # flag_sweep = (center.Axis * drawing_plane_normal >= 0) \
+ # == (edge.LastParameter > edge.FirstParameter)
+ # == (edge.Orientation == "Forward")
+
+ # Another method: check the direction of the angle
+ # between tangents
+ _diff = edge.LastParameter - edge.FirstParameter
+ t1 = edge.tangentAt(edge.FirstParameter)
+ 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))
+
+ return "edata", edata
+
+
+def _get_path_bspline(plane, edge, edata):
+ """Convert the edge to a BSpline and discretize it."""
+ bspline = edge.Curve.toBSpline(edge.FirstParameter, edge.LastParameter)
+ if bspline.Degree > 3 or bspline.isRational():
+ try:
+ bspline = bspline.approximateBSpline(0.05, 50, 3, 'C0')
+ except RuntimeError:
+ _wrn("Debug: unable to approximate bspline from edge")
+
+ if bspline.Degree <= 3 and not bspline.isRational():
+ for bezierseg in bspline.toBezier():
+ if bezierseg.Degree > 3: # should not happen
+ _wrn("Bezier segment of degree > 3")
+ raise AssertionError
+ elif bezierseg.Degree == 1:
+ edata += 'L '
+ elif bezierseg.Degree == 2:
+ edata += 'Q '
+ elif bezierseg.Degree == 3:
+ edata += 'C '
+
+ for pole in bezierseg.getPoles()[1:]:
+ v = get_proj(pole, plane)
+ edata += '{} {} '.format(v.x, v.y)
+ else:
+ _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)
+
+ return edata
+
+
+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
+
+ if hasattr(App, "DraftWorkingPlane"):
+ drawing_plane_normal = App.DraftWorkingPlane.axis
+ else:
+ drawing_plane_normal = App.Vector(0, 0, 1)
+
+ if plane:
+ drawing_plane_normal = plane.axis
+
+ if round(edge.Curve.Axis.getAngle(drawing_plane_normal), 2) in [0, 3.14]:
+ # Perpendicular projection: circle
+ svg = '\n'
+ return svg
+
+
+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):
+ """Get the SVG representation from an elliptical edge."""
+ cen = get_proj(edge.Curve.Center, plane)
+ mir = edge.Curve.MinorRadius
+ mar = edge.Curve.MajorRadius
+ svg = '\n'
+ return svg
+
+
+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):
+ """Get the SVG representation from an object's edges or wires.
+
+ TODO: the `edges` and `wires` must not default to empty list `[]`
+ but to `None`. Verify that the code doesn't break with this change.
+
+ `edges` and `wires` are mutually exclusive. If no `wires` are provided,
+ sort the `edges`, and use them. If `wires` are provided, sort the edges
+ in these `wires`, and use them.
+ """
+ svg = " 1e-6:
+ vertex.reverse()
+
+ if edgeindex == 0:
+ v = get_proj(vertex[0].Point, plane)
+ edata += 'M {} {} '.format(v.x, v.y)
+ else:
+ if (vertex[0].Point - previousvs[-1].Point).Length > 1e-6:
+ 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, vertex,
+ edata,
+ iscircle, isellipse,
+ fill, stroke,
+ linewidth, lstyle)
+ if _type == "svg":
+ # final svg string already calculated, so just return it
+ return data
+
+ # else the `edata` was properly augmented, so re-assing it
+ edata = data
+ elif DraftGeomUtils.geomType(edge) == "Line":
+ v = get_proj(vertex[-1].Point, plane)
+ 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 edata in pathdata:
+ # do not draw a path on another identical path
+ return ""
+ else:
+ svg += edata
+ pathdata.append(edata)
+
+ svg += '" '
+ 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 += '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-rule: evenodd"'
+ svg += '/>\n'
+ return svg
+
+
+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)
+
+## @}