diff --git a/src/Mod/Draft/draftfunctions/svg.py b/src/Mod/Draft/draftfunctions/svg.py index d83d584b4e..bbb90cb463 100644 --- a/src/Mod/Draft/draftfunctions/svg.py +++ b/src/Mod/Draft/draftfunctions/svg.py @@ -547,9 +547,9 @@ 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, e, edata, iscircle, - fill, stroke, linewidth, lstyle, - isellipse, vs): +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 @@ -559,96 +559,99 @@ def _get_path_circ_ellipse(plane, e, edata, iscircle, if plane: drawing_plane_normal = plane.axis - c = e.Curve - ax = c.Axis - if round(ax.getAngle(drawing_plane_normal), 2) in [0, 3.14]: - 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(e, drawing_plane_normal) + center = edge.Curve + ax = center.Axis - 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; - # what is the problem? - # split didn't produce a two element list? - _wrn("Circle or ellipse: " - "not possible to split the projection " - "snip obtained by Drawing.projectToSVG, " - "continue manually.") - else: - edata += A - done = True + # 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 - if not done: - if len(e.Vertexes) == 1 and iscircle: - # Complete circle not only arc - svg = get_circle(plane, - fill, stroke, linewidth, lstyle, - e) - # If it's a circle we will return the final SVG string, - # otherwise it will process the `edata` further - return "svg", svg - elif len(e.Vertexes) == 1 and isellipse: - # Complete ellipse not only arc - # svg = get_ellipse(plane, - # fill, stroke, linewidth, - # lstyle, edge) - # return svg + # 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) - # Difference in angles - _diff = (c.LastParameter - c.FirstParameter)/2.0 - endpoints = [get_proj(c.value(_diff), plane), - get_proj(vs[-1].Point, plane)] + 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: - endpoints = [get_proj(vs[-1].Point, plane)] + edata += A + done = True - # Arc with more than one vertex - if iscircle: - rx = ry = c.Radius - rot = 0 - else: # ellipse - rx = c.MajorRadius - ry = c.MinorRadius - rot = math.degrees(c.AngleXU - * c.Axis * App.Vector(0, 0, 1)) - if rot > 90: - rot -= 180 - if rot < -90: - rot += 180 + 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 - # Be careful with the sweep flag - _diff = e.ParameterRange[1] - e.ParameterRange[0] - _diff = _diff / math.pi - flag_large_arc = (_diff % 2) > 1 + # 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)] - # flag_sweep = (c.Axis * drawing_plane_normal >= 0) \ - # == (e.LastParameter > e.FirstParameter) - # == (e.Orientation == "Forward") + # 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 - # Another method: check the direction of the angle - # between tangents - _diff = e.LastParameter - e.FirstParameter - t1 = e.tangentAt(e.FirstParameter) - t2 = e.tangentAt(e.FirstParameter + _diff/10) - flag_sweep = DraftVecUtils.angle(t1, t2, - drawing_plane_normal) < 0 + # Be careful with the sweep flag + _diff = edge.ParameterRange[1] - edge.ParameterRange[0] + _diff = _diff / math.pi + flag_large_arc = (_diff % 2) > 1 - for v in endpoints: - edata += ('A {} {} {} ' - '{} {} ' - '{} {} '.format(rx, ry, rot, - int(flag_large_arc), - int(flag_sweep), - v.x, v.y)) - else: - edata += get_discretized(e, plane) + # 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 @@ -714,9 +717,11 @@ def get_path(obj, plane, isellipse = DraftGeomUtils.geomType(e) == "Ellipse" if iscircle or isellipse: - _type, data = _get_path_circ_ellipse(plane, e, edata, iscircle, - fill, stroke, linewidth, - lstyle, isellipse, vs) + _type, data = _get_path_circ_ellipse(plane, e, vs, + edata, + iscircle, isellipse, + fill, stroke, + linewidth, lstyle) if _type == "svg": # final svg string already calculated, so just return it return data