//-------------------------------------------------------------------------------------------------- bool _AddEllipicalArcSegment(SketchSegmentEllipticalArc arcSegment, Pnt2d start, Pnt2d end) { var parameters = new double[2]; var ellipse = arcSegment.GetEllipse(_Sketch.Points, parameters); if (ellipse == null) { return(false); } double rotAngle = ellipse.XAxis().Angle(new Ax2d(ellipse.Location(), Dir2d.DX)); double length = parameters[1] - parameters[0]; var size = length < Math.PI ? SvgArcSize.Small : SvgArcSize.Large; var sense = ellipse.Axis().Sense() > 0; if (start == _Sketch.Points[arcSegment.EndPoint]) { sense = !sense; // Sense was inverted by interchanged start/end point } var sweep = sense ? SvgArcSweep.Positive : SvgArcSweep.Negative; var svgSegment = new SvgPathSegArc(start, ellipse.MajorRadius(), ellipse.MinorRadius(), rotAngle.ToDeg(), size, sweep, end); _CurrentPath.Segments.Add(svgSegment); return(true); }
public static IEnumerable <SvgPathSegment> Create(SvgPathSegment lastSegment, string commandString, SvgConverter conv) { if (!conv.TrySplitValues(commandString.Substring(1), out var values, false)) { yield break; } int valuePos = 0; while (valuePos < values.Length) { var start = new Pnt2d(); if (lastSegment != null) { start = lastSegment.End; } double rx = values[0] * conv.Scale; double ry = values[1] * conv.Scale; double angle = values[2]; SvgArcSize size = values[3] == 0 ? SvgArcSize.Small : SvgArcSize.Large; SvgArcSweep sweep = values[4] == 0 ? SvgArcSweep.Negative : SvgArcSweep.Positive; Pnt2d end = new Pnt2d(values[5] * conv.Scale, values[6] * conv.Scale); if (char.IsLower(commandString[0])) { end += start; } valuePos += 7; lastSegment = new SvgPathSegArc(start, rx, ry, angle, size, sweep, end); yield return(lastSegment); } }
//-------------------------------------------------------------------------------------------------- void _ImportArcSegment(SvgPathSegArc svgSegment, ref int startPoint) { var radiusX = svgSegment.RadiusX; var radiusY = svgSegment.RadiusY; var rotation = -svgSegment.Angle.ToRad(); var startPnt2d = svgSegment.Start; var endPnt2d = svgSegment.End; var centerPnt2d = Geom2dUtils.FindEllipseCenterFromEndpoints( startPnt2d, endPnt2d, radiusX, radiusY, rotation, (int)svgSegment.Size != (int)svgSegment.Sweep); // Do we have a circle arc? if (Math.Abs(radiusX - radiusY) < 0.0001) { var axis = Ax2d.OX.Rotated(Pnt2d.Origin, rotation).Translated(centerPnt2d.ToVec()); var circ = new gp_Circ2d(axis, radiusX, svgSegment.Sweep != SvgArcSweep.Positive); //Debug.WriteLine("StartParam: {0} - EndParam: {1}", ElCLib.Parameter(circ, startPnt2d), ElCLib.Parameter(circ, endPnt2d)); var startParam = ElCLib.Parameter(circ, startPnt2d); var endParam = ElCLib.Parameter(circ, endPnt2d); if (endParam < startParam) { endParam += 2 * Math.PI; } var rimPnt2d = ElCLib.Value(startParam + (endParam - startParam) / 2, circ); var endPoint = _AddPoint(endPnt2d); _Segments.Add(new SketchSegmentArc(startPoint, endPoint, _AddPoint(rimPnt2d))); startPoint = endPoint; } else { // No, we have a elliptical arc // Construct ellipse, convert to bezier var axis = Ax2d.OX.Rotated(Pnt2d.Origin, rotation).Translated(centerPnt2d.ToVec()); var ellipse = new gp_Elips2d(axis, radiusX, radiusY, svgSegment.Sweep != SvgArcSweep.Positive); var startParam = ElCLib.Parameter(ellipse, startPnt2d); var endParam = ElCLib.Parameter(ellipse, endPnt2d); if (double.IsNaN(startParam) || double.IsNaN(endParam)) { Messages.Warning("Invalid elliptical arc found in SVG file."); return; } var bezierPointArray = Geom2dUtils.EllipticalArcToBezier(ellipse, startParam, endParam); foreach (var bezierPoints in bezierPointArray) { var endPoint = _AddPoint(bezierPoints.p2); _Segments.Add(new SketchSegmentBezier(startPoint, _AddPoint(bezierPoints.c1), _AddPoint(bezierPoints.c2), endPoint)); startPoint = endPoint; } } }
//-------------------------------------------------------------------------------------------------- bool _AddArcSegment(SketchSegmentArc arcSegment, Pnt2d start, Pnt2d end) { var parameters = new double[2]; var circle = arcSegment.GetCircle(_Sketch.Points, parameters); if (circle == null) { return(false); } double length = parameters[1] - parameters[0]; var size = length < Math.PI ? SvgArcSize.Small : SvgArcSize.Large; var sweep = circle.Position().Sense() > 0 ? SvgArcSweep.Positive : SvgArcSweep.Negative; var svgSegment = new SvgPathSegArc(start, circle.Radius(), circle.Radius(), 0, size, sweep, end); _CurrentPath.Segments.Add(svgSegment); return(true); }
//-------------------------------------------------------------------------------------------------- internal static IEnumerable <SvgPathSegment> Create(string pathString, SvgConverter conv) { SvgPathSegment lastSegment = null; SvgPathSegment firstSegment = null; int next = 0; while (next < pathString.Length) { int start = next; next = pathString.IndexOfAny(_PathCommands, start + 1); if (next == -1) { next = pathString.Length; } IEnumerable <SvgPathSegment> newSegments = null; var commandString = pathString.Substring(start, next - start); switch (char.ToLower(commandString[0])) { case 'm': newSegments = SvgPathSegMoveto.Create(lastSegment, commandString, conv); break; case 'l': case 'h': case 'v': newSegments = SvgPathSegLineto.Create(lastSegment, commandString, conv); break; case 'c': case 's': newSegments = SvgPathSegCurvetoCubic.Create(lastSegment, commandString, conv); break; case 'q': case 't': newSegments = SvgPathSegCurvetoQuadratic.Create(lastSegment, commandString, conv); break; case 'a': newSegments = SvgPathSegArc.Create(lastSegment, commandString, conv); break; case 'z': lastSegment = SvgPathSegClosePath.Create(firstSegment, lastSegment); yield return(lastSegment); firstSegment = null; continue; } if (newSegments == null) { continue; } foreach (var segment in newSegments) { if (firstSegment == null) { firstSegment = segment; } lastSegment = segment; yield return(segment); } } }