From d24055b523e867c31b94767f6e2db29ca862ccac Mon Sep 17 00:00:00 2001 From: vocx-fc Date: Sat, 4 Jul 2020 17:49:53 -0500 Subject: [PATCH] Draft: improve initial code of getSVG Improve also the docstrings, and minor adjustments in PEP8 style and spacing. --- src/Mod/Draft/getSVG.py | 228 ++++++++++++++++++++++++++++------------ 1 file changed, 163 insertions(+), 65 deletions(-) diff --git a/src/Mod/Draft/getSVG.py b/src/Mod/Draft/getSVG.py index 4da99c89aa..d43d061c2f 100644 --- a/src/Mod/Draft/getSVG.py +++ b/src/Mod/Draft/getSVG.py @@ -29,6 +29,7 @@ # @{ import math import six +import lazy_loader.lazy_loader as lz import FreeCAD import DraftVecUtils @@ -37,112 +38,209 @@ import draftutils.utils as utils from FreeCAD import Vector +# Delay import of module until first use because it is heavy +Part = lz.LazyLoader("Part", globals(), "Part") +DraftGeomUtils = lz.LazyLoader("DraftGeomUtils", globals(), "DraftGeomUtils") -def getLineStyle(linestyle, scale): - "returns a linestyle" - p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft") - l = None - if linestyle == "Dashed": - l = p.GetString("svgDashedLine","0.09,0.05") - elif linestyle == "Dashdot": - l = p.GetString("svgDashdotLine","0.09,0.05,0.02,0.05") - elif linestyle == "Dotted": - l = p.GetString("svgDottedLine","0.02,0.02") - elif linestyle: - if "," in linestyle: - l = linestyle - if l: - l = l.split(",") +param = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft") + + +def get_line_style(line_style, scale): + """Return a linestyle scaled by a factor.""" + style = None + + if line_style == "Dashed": + style = param.GetString("svgDashedLine", "0.09,0.05") + elif line_style == "Dashdot": + style = param.GetString("svgDashdotLine", "0.09,0.05,0.02,0.05") + elif line_style == "Dotted": + style = param.GetString("svgDottedLine", "0.02,0.02") + elif line_style: + if "," in line_style: + style = line_style + + if style: + style = style.split(",") try: # scale dashes - l = ",".join([str(float(d)/scale) for d in l]) - #print "lstyle ",l + style = ",".join([str(float(d)/scale) for d in style]) + # print("lstyle ", style) except: return "none" else: - return l + return style + return "none" -def getProj(vec, plane): - if not plane: return vec - nx = DraftVecUtils.project(vec,plane.u) +def getLineStyle(linestyle, scale): + """Return a Line style. DEPRECATED. Use get_line_style.""" + utils.use_instead("get_line_style") + return get_line_style(linestyle, scale) + + +def getProj(vec, plane=None): + """Get a projection of the vector in the plane's u and v directions. + + 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) + + 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 + + if abs(ny.getAngle(plane.v)) > 0.1: + ly = -ly + + # if techdraw: buggy - we now simply do it at the end # ly = -ly - return Vector(lx,ly,0) + return Vector(lx, ly, 0) def getDiscretized(edge, plane): - ml = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft").GetFloat("svgDiscretization",10.0) - if ml == 0: - ml = 10 - d = int(edge.Length/ml) + """Get discretization of the edge.""" + 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): - v = getProj(edge.valueAt(edge.FirstParameter+((float(i)/d)*(edge.LastParameter-edge.FirstParameter))), plane) + for i in range(d + 1): + _length = edge.LastParameter - edge.FirstParameter + _point = edge.FirstParameter + float(i)/d * _length + _vec = edge.valueAt(_point) + v = getProj(_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 def getPattern(pat): + """Get an SVG pattern.""" if pat in utils.svg_patterns(): return utils.svg_patterns()[pat][0] return '' -def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direction=None,linestyle=None,color=None,linespacing=None,techdraw=False,rotation=0,fillSpaces=False,override=True): - '''getSVG(object,[scale], [linewidth],[fontsize],[fillstyle],[direction],[linestyle],[color],[linespacing]): - returns a string containing a SVG representation of the given object, - with the given linewidth and fontsize (used if the given object contains - any text). You can also supply an arbitrary projection vector. the - scale parameter allows to scale linewidths down, so they are resolution-independant.''' +def getSVG(obj, + scale=1, linewidth=0.35, fontsize=12, + fillstyle="shape color", direction=None, linestyle=None, + color=None, linespacing=None, techdraw=False, rotation=0, + fillSpaces=False, override=True): + """Return a string containing an SVG representation of the object. - import Part, DraftGeomUtils + Paramaeters + ----------- + scale: float, optional + It defaults to 1. + It allows scaling line widths down, so they are resolution-independent. - # if this is a group, gather all the svg views of its children - if hasattr(obj,"isDerivedFrom"): - if obj.isDerivedFrom("App::DocumentObjectGroup") or utils.get_type(obj) == "Layer": + linewidth: float, optional + It defaults to 0.35. + + fontsize: float, optional + It defaults to 12, which is interpreted as `pt` unit (points). + It is used if the given object contains any text. + + fillstyle: str, optional + It defaults to 'shape color'. + + direction: Base::Vector3, optional + It defaults to `None`. + It is an arbitrary projection vector or a `WorkingPlane.Plane` + instance. + + linestyle: optional + It defaults to `None`. + + color: optional + It defaults to `None`. + + linespacing: float, optional + It defaults to `None`. + + techdraw: bool, optional + It defaults to `False`. + If it is `True`, it sets some options for generating SVG strings + for displaying inside TechDraw. + + rotation: float, optional + It defaults to 0. + + fillSpaces: bool, optional + It defaults to `False`. + + override: bool, optional + It defaults to `True`. + """ + # If this is a group, recursively call this function to gather + # all the SVG strings from the contents of the group + if hasattr(obj, "isDerivedFrom"): + if (obj.isDerivedFrom("App::DocumentObjectGroup") + or utils.get_type(obj) == "Layer"): svg = "" for child in obj.Group: - svg += getSVG(child,scale,linewidth,fontsize,fillstyle,direction,linestyle,color,linespacing,techdraw,rotation,fillSpaces,override) + svg += getSVG(child, + scale, linewidth, fontsize, + fillstyle, direction, linestyle, + color, linespacing, techdraw, + rotation, fillSpaces, override) return svg pathdata = [] svg = "" linewidth = float(linewidth)/scale if not override: - if hasattr(obj,"ViewObject"): - if hasattr(obj.ViewObject,"LineWidth"): - if hasattr(obj.ViewObject.LineWidth,"Value"): - lw = obj.ViewObject.LineWidth.Value - else: - lw = obj.ViewObject.LineWidth - linewidth = lw*linewidth + if hasattr(obj, "ViewObject") and hasattr(obj.ViewObject, "LineWidth"): + if hasattr(obj.ViewObject.LineWidth, "Value"): + lw = obj.ViewObject.LineWidth.Value + else: + lw = obj.ViewObject.LineWidth + linewidth = lw * linewidth + fontsize = (float(fontsize)/scale)/2 if linespacing: linespacing = float(linespacing)/scale else: linespacing = 0.5 - #print obj.Label," line spacing ",linespacing,"scale ",scale - pointratio = .75 # the number of times the dots are smaller than the arrow size + + # print(obj.Label, "line spacing", linespacing, "scale", scale) + + # The number of times the dots are smaller than the arrow size + pointratio = 0.75 plane = None + if direction: - if isinstance(direction,FreeCAD.Vector): - if direction != Vector(0,0,0): + if isinstance(direction, FreeCAD.Vector): + if direction != Vector(0, 0, 0): plane = WorkingPlane.plane() - plane.alignToPointAndAxis_SVG(Vector(0,0,0),direction.negative().negative(),0) - elif isinstance(direction,WorkingPlane.plane): + plane.alignToPointAndAxis_SVG(Vector(0, 0, 0), + direction.negative().negative(), + 0) + elif isinstance(direction, WorkingPlane.plane): plane = direction + stroke = "#000000" if color and override: if "#" in color: @@ -150,18 +248,18 @@ def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direct else: stroke = utils.get_rgb(color) elif FreeCAD.GuiUp: - if hasattr(obj,"ViewObject"): - if hasattr(obj.ViewObject,"LineColor"): + if hasattr(obj, "ViewObject"): + if hasattr(obj.ViewObject, "LineColor"): stroke = utils.get_rgb(obj.ViewObject.LineColor) - elif hasattr(obj.ViewObject,"TextColor"): + elif hasattr(obj.ViewObject, "TextColor"): stroke = utils.get_rgb(obj.ViewObject.TextColor) + lstyle = "none" if override: - lstyle = getLineStyle(linestyle, scale) + lstyle = get_line_style(linestyle, scale) else: - if hasattr(obj,"ViewObject"): - if hasattr(obj.ViewObject,"DrawStyle"): - lstyle = getLineStyle(obj.ViewObject.DrawStyle, scale) + if hasattr(obj, "ViewObject") and hasattr(obj.ViewObject, "DrawStyle"): + lstyle = get_line_style(obj.ViewObject.DrawStyle, scale) def getPath(edges=[],wires=[],pathname=None):