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); } }
private static SvgPath ConvertArc(Arc arc) { SvgPath svgPath = new SvgPath(); SvgPathSegmentList svgPathSegmentList = new SvgPathSegmentList(); svgPathSegmentList.Add(new SvgMoveToSegment(arc.GetEndPoint(0).ConvertToPointF())); XYZ a = arc.GetEndPoint(0) - arc.Center; XYZ b = arc.GetEndPoint(1) - arc.Center; double angleAboutAxis = a.AngleOnPlaneTo(b, arc.Normal); SvgArcSweep svgArcSweep = SvgArcSweep.Positive; if (angleAboutAxis >= 180) { svgArcSweep = SvgArcSweep.Negative; } SvgArcSize svgArcSize = SvgArcSize.Small; SvgArcSegment svgArcSegment = new SvgArcSegment(svgPathSegmentList.Last.End, (float)arc.Radius, (float)arc.Radius, (float)angleAboutAxis, svgArcSize, svgArcSweep, arc.GetEndPoint(1).ConvertToPointF()); svgPathSegmentList.Add(svgArcSegment); svgPath.PathData = svgPathSegmentList; return(svgPath); }
public SvgArcSegment(PointF start, float radiusX, float radiusY, float angle, SvgArcSize size, SvgArcSweep sweep, PointF end) : base(start, end) { this.RadiusX = Math.Abs(radiusX); this.RadiusY = Math.Abs(radiusY); this.Angle = angle; this.Sweep = sweep; this.Size = size; }
public SvgArcSegment(PointF start, float radiusX, float radiusY, float angle, SvgArcSize size, SvgArcSweep sweep, PointF end) : base(start, end) { this.RadiusX = System.Math.Abs(radiusX); this.RadiusY = System.Math.Abs(radiusY); this.Angle = angle; this.Sweep = sweep; this.Size = size; }
public SvgArcSegment(float radiusX, float radiusY, float angle, SvgArcSize size, SvgArcSweep sweep, bool isRelative, PointF end) : base(isRelative, end) { RadiusX = Math.Abs(radiusX); RadiusY = Math.Abs(radiusY); Angle = angle; Sweep = sweep; Size = size; }
public SvgArcSegment(PointF start, float radiusX, float radiusY, float angle, SvgArcSize size, SvgArcSweep sweep, PointF end) : base(start, end) { RadiusX = Math.Abs(radiusX); RadiusY = Math.Abs(radiusY); Angle = angle; Sweep = sweep; Size = size; }
public SvgPathSegArc(Pnt2d start, double radiusX, double radiusY, double angle, SvgArcSize size, SvgArcSweep sweep, Pnt2d end) : base(start, end) { RadiusX = radiusX; RadiusY = radiusY; Angle = angle; Size = size; Sweep = sweep; }
public SvgArcSegment(Point start, float radiusX, float radiusY, float angle, SvgArcSize size, SvgArcSweep sweep, Point end) : base(start, end) { RadiusX = Math.Abs(radiusX); RadiusY = Math.Abs(radiusY); Angle = angle; Sweep = sweep; Size = size; }
public svgDrawArc(PointF start, float radiusX, float radiusY, float angle, SvgArcSize size, SvgArcSweep sweep, PointF end) { this.Start = start; this.End = end; this.RadiusX = Math.Abs(radiusX); this.RadiusY = Math.Abs(radiusY); this.Angle = angle; this.Sweep = sweep; this.Size = size; }
public SvgArcSegment(IPoint2F start, Single radiusX, Single radiusY, Single angle, SvgArcSize size, SvgArcSweep sweep, IPoint2F end) : base(start, end) { RadiusX = Math.Abs(radiusX); RadiusY = Math.Abs(radiusY); Angle = angle; Sweep = sweep; Size = size; }
public void Set(float startX, float startY, float radiusX, float radiusY, float angle, SvgArcSize size, SvgArcSweep sweep, float endX, float endY) { this.StartX = startX; this.StartY = startY; this.EndX = endX; this.EndY = endY; this.RadiusX = Math.Abs(radiusX); this.RadiusY = Math.Abs(radiusY); this.Angle = angle; this.Sweep = sweep; this.Size = size; }
private static SvgPath ConverPolyCurve(List <Curve> curves) { SvgPath svgPath = new SvgPath(); SvgPathSegmentList svgPathSegmentList = new SvgPathSegmentList(); svgPathSegmentList.Add(new SvgMoveToSegment(curves[0].GetEndPoint(0).ConvertToPointF())); foreach (Curve curve in curves) { if (curve is Arc) { Arc arc = (Arc)curve; XYZ a = arc.GetEndPoint(0) - arc.Center; XYZ b = arc.GetEndPoint(1) - arc.Center; double angleAboutAxis = a.AngleOnPlaneTo(b, arc.Normal); SvgArcSweep svgArcSweep = SvgArcSweep.Positive; if (angleAboutAxis >= 180) { svgArcSweep = SvgArcSweep.Negative; } SvgArcSize svgArcSize = SvgArcSize.Small; SvgArcSegment svgArcSegment = new SvgArcSegment(svgPathSegmentList.Last.End, (float)arc.Radius, (float)arc.Radius, (float)angleAboutAxis, svgArcSize, svgArcSweep, arc.GetEndPoint(1).ConvertToPointF()); svgPathSegmentList.Add(svgArcSegment); } else if (curve is Line) { SvgLineSegment svgLineSegment = new SvgLineSegment(svgPathSegmentList.Last.End, ((Line)curve).GetEndPoint(1).ConvertToPointF()); svgPathSegmentList.Add(svgLineSegment); } } svgPath.PathData = svgPathSegmentList; return(svgPath); }
protected void DrawArc(SvgDocument source, PointF center, float radius, PointF startPoint, PointF endPoint, bool largeArc = false) { SvgPath svgPath = new SvgPath() { Fill = new SvgColourServer(Color.Transparent), StrokeWidth = MandalaGenerator.StrokeWidth, Stroke = new SvgColourServer(Color.Black) }; svgPath.PathData = new SvgPathSegmentList(); SvgMoveToSegment svgStartMove = new SvgMoveToSegment(startPoint); svgPath.PathData.Add(svgStartMove); SvgArcSize size = largeArc ? SvgArcSize.Large : SvgArcSize.Small; SvgArcSegment arc = new SvgArcSegment(startPoint, radius, radius, 0, size, SvgArcSweep.Negative, endPoint); svgPath.PathData.Add(arc); source.Children.Add(svgPath); }
//--------------------------------------------------------------------- public void DrawArc(float fromX, float fromY, float endX, float endY, float xaxisRotationAngleDec, float rx, float ry, SvgArcSize arcSize, SvgArcSweep arcSweep) { //------------------ //SVG Elliptical arc ... //from Apache Batik //----------------- CenterFormArc centerFormArc = new CenterFormArc(); ComputeArc2(fromX, fromY, rx, ry, DegToRad(xaxisRotationAngleDec), arcSize == SvgArcSize.Large, arcSweep == SvgArcSweep.Negative, endX, endY, ref centerFormArc); arcTool.Init(centerFormArc.cx, centerFormArc.cy, rx, ry, centerFormArc.radStartAngle, (centerFormArc.radStartAngle + centerFormArc.radSweepDiff)); VertexStore v1 = GetFreeVxs(); bool stopLoop = false; foreach (VertexData vertexData in arcTool.GetVertexIter()) { switch (vertexData.command) { case VertexCmd.NoMore: stopLoop = true; break; default: v1.AddVertex(vertexData.x, vertexData.y, vertexData.command); //yield return vertexData; break; } //------------------------------ if (stopLoop) { break; } } double scaleRatio = 1; if (centerFormArc.scaleUp) { int vxs_count = v1.Count; double px0, py0, px_last, py_last; v1.GetVertex(0, out px0, out py0); v1.GetVertex(vxs_count - 1, out px_last, out py_last); double distance1 = Math.Sqrt((px_last - px0) * (px_last - px0) + (py_last - py0) * (py_last - py0)); double distance2 = Math.Sqrt((endX - fromX) * (endX - fromX) + (endY - fromY) * (endY - fromY)); if (distance1 < distance2) { scaleRatio = distance2 / distance1; } else { } } if (xaxisRotationAngleDec != 0) { //also rotate if (centerFormArc.scaleUp) { var mat = PixelFarm.Agg.Transform.Affine.NewMatix( new PixelFarm.Agg.Transform.AffinePlan(PixelFarm.Agg.Transform.AffineMatrixCommand.Translate, -centerFormArc.cx, -centerFormArc.cy), new PixelFarm.Agg.Transform.AffinePlan(PixelFarm.Agg.Transform.AffineMatrixCommand.Scale, scaleRatio, scaleRatio), new PixelFarm.Agg.Transform.AffinePlan(PixelFarm.Agg.Transform.AffineMatrixCommand.Rotate, DegToRad(xaxisRotationAngleDec)), new PixelFarm.Agg.Transform.AffinePlan(PixelFarm.Agg.Transform.AffineMatrixCommand.Translate, centerFormArc.cx, centerFormArc.cy)); var v2 = GetFreeVxs(); mat.TransformToVxs(v1, v2); ReleaseVxs(ref v1); v1 = v2; } else { //not scalue var mat = PixelFarm.Agg.Transform.Affine.NewMatix( new PixelFarm.Agg.Transform.AffinePlan(PixelFarm.Agg.Transform.AffineMatrixCommand.Translate, -centerFormArc.cx, -centerFormArc.cy), new PixelFarm.Agg.Transform.AffinePlan(PixelFarm.Agg.Transform.AffineMatrixCommand.Rotate, DegToRad(xaxisRotationAngleDec)), new PixelFarm.Agg.Transform.AffinePlan(PixelFarm.Agg.Transform.AffineMatrixCommand.Translate, centerFormArc.cx, centerFormArc.cy)); var v2 = GetFreeVxs(); mat.TransformToVxs(v1, v2); ReleaseVxs(ref v1); v1 = v2; } } else { //no rotate if (centerFormArc.scaleUp) { var mat = PixelFarm.Agg.Transform.Affine.NewMatix( new PixelFarm.Agg.Transform.AffinePlan(PixelFarm.Agg.Transform.AffineMatrixCommand.Translate, -centerFormArc.cx, -centerFormArc.cy), new PixelFarm.Agg.Transform.AffinePlan(PixelFarm.Agg.Transform.AffineMatrixCommand.Scale, scaleRatio, scaleRatio), new PixelFarm.Agg.Transform.AffinePlan(PixelFarm.Agg.Transform.AffineMatrixCommand.Translate, centerFormArc.cx, centerFormArc.cy)); var v2 = GetFreeVxs(); mat.TransformToVxs(v1, v2); ReleaseVxs(ref v1); v1 = v2; } } _aggStroke.Width = this.StrokeWidth; var v3 = _aggStroke.MakeVxs(v1, GetFreeVxs()); _canvas.DrawGfxPath(_canvas.StrokeColor, InternalGraphicsPath.CreateGraphicsPath(new VertexStoreSnap(v3))); ReleaseVxs(ref v3); ReleaseVxs(ref v1); }
public static void AddToPath(GraphicsPath graphicsPath, Vector2 Start, Vector2 End, float RadiusX, float RadiusY, float Angle, SvgArcSize Size, SvgArcSweep Sweep) { if (Start == End) { return; } if (RadiusX == 0.0f && RadiusY == 0.0f) { graphicsPath.AddElement(new LineElement(Start, End)); return; } var sinPhi = Math.Sin(Angle * RadiansPerDegree); var cosPhi = Math.Cos(Angle * RadiansPerDegree); var x1dash = cosPhi * (Start.X - End.X) / 2.0 + sinPhi * (Start.Y - End.Y) / 2.0; var y1dash = -sinPhi * (Start.X - End.X) / 2.0 + cosPhi * (Start.Y - End.Y) / 2.0; double root; var numerator = RadiusX * RadiusX * RadiusY * RadiusY - RadiusX * RadiusX * y1dash * y1dash - RadiusY * RadiusY * x1dash * x1dash; var rx = RadiusX; var ry = RadiusY; if (numerator < 0.0) { var s = (float)Math.Sqrt(1.0 - numerator / (RadiusX * RadiusX * RadiusY * RadiusY)); rx *= s; ry *= s; root = 0.0; } else { root = ((Size == SvgArcSize.Large && Sweep == SvgArcSweep.Positive) || (Size == SvgArcSize.Small && Sweep == SvgArcSweep.Negative) ? -1.0 : 1.0) * Math.Sqrt(numerator / (RadiusX * RadiusX * y1dash * y1dash + RadiusY * RadiusY * x1dash * x1dash)); } var cxdash = root * rx * y1dash / ry; var cydash = -root * ry * x1dash / rx; var cx = cosPhi * cxdash - sinPhi * cydash + (Start.X + End.X) / 2.0; var cy = sinPhi * cxdash + cosPhi * cydash + (Start.Y + End.Y) / 2.0; var theta1 = CalculateVectorAngle(1.0, 0.0, (x1dash - cxdash) / rx, (y1dash - cydash) / ry); var dtheta = CalculateVectorAngle((x1dash - cxdash) / rx, (y1dash - cydash) / ry, (-x1dash - cxdash) / rx, (-y1dash - cydash) / ry); if (Sweep == SvgArcSweep.Negative && dtheta > 0) { dtheta -= 2.0 * Math.PI; } else if (Sweep == SvgArcSweep.Positive && dtheta < 0) { dtheta += 2.0 * Math.PI; } var segments = (int)Math.Ceiling((double)Math.Abs(dtheta / (Math.PI / 2.0))); var delta = dtheta / segments; var t = 8.0 / 3.0 * Math.Sin(delta / 4.0) * Math.Sin(delta / 4.0) / Math.Sin(delta / 2.0); var startX = Start.X; var startY = Start.Y; for (var i = 0; i < segments; ++i) { var cosTheta1 = Math.Cos(theta1); var sinTheta1 = Math.Sin(theta1); var theta2 = theta1 + delta; var cosTheta2 = Math.Cos(theta2); var sinTheta2 = Math.Sin(theta2); var endpointX = cosPhi * rx * cosTheta2 - sinPhi * ry * sinTheta2 + cx; var endpointY = sinPhi * rx * cosTheta2 + cosPhi * ry * sinTheta2 + cy; var dx1 = t * (-cosPhi * rx * sinTheta1 - sinPhi * ry * cosTheta1); var dy1 = t * (-sinPhi * rx * sinTheta1 + cosPhi * ry * cosTheta1); var dxe = t * (cosPhi * rx * sinTheta2 + sinPhi * ry * cosTheta2); var dye = t * (sinPhi * rx * sinTheta2 - cosPhi * ry * cosTheta2); graphicsPath.AddElement(new BezierElement( startX, startY, (float)(startX + dx1), (float)(startY + dy1), (float)(endpointX + dxe), (float)(endpointY + dye), (float)endpointX, (float)endpointY)); theta1 = theta2; startX = (float)endpointX; startY = (float)endpointY; } }
public void DrawArc(float fromX, float fromY, float endX, float endY, float xaxisRotationAngleDec, float rx, float ry, SvgArcSize arcSize, SvgArcSweep arcSweep) { //------------------ //SVG Elliptical arc ... //from Apache Batik //----------------- CenterFormArc centerFormArc = new CenterFormArc(); ComputeArc2(fromX, fromY, rx, ry, DegToRad(xaxisRotationAngleDec), arcSize == SvgArcSize.Large, arcSweep == SvgArcSweep.Negative, endX, endY, ref centerFormArc); arcTool.Init(centerFormArc.cx, centerFormArc.cy, rx, ry, centerFormArc.radStartAngle, (centerFormArc.radStartAngle + centerFormArc.radSweepDiff)); VertexStore vxs = new VertexStore(); bool stopLoop = false; foreach (VertexData vertexData in arcTool.GetVertexIter()) { switch (vertexData.command) { case VertexCmd.Stop: stopLoop = true; break; default: vxs.AddVertex(vertexData.x, vertexData.y, vertexData.command); //yield return vertexData; break; } //------------------------------ if (stopLoop) { break; } } double scaleRatio = 1; if (centerFormArc.scaleUp) { int vxs_count = vxs.Count; double px0, py0, px_last, py_last; vxs.GetVertex(0, out px0, out py0); vxs.GetVertex(vxs_count - 1, out px_last, out py_last); double distance1 = Math.Sqrt((px_last - px0) * (px_last - px0) + (py_last - py0) * (py_last - py0)); double distance2 = Math.Sqrt((endX - fromX) * (endX - fromX) + (endY - fromY) * (endY - fromY)); if (distance1 < distance2) { scaleRatio = distance2 / distance1; } else { } } if (xaxisRotationAngleDec != 0) { //also rotate if (centerFormArc.scaleUp) { var mat = PixelFarm.Agg.Transform.Affine.NewMatix( new PixelFarm.Agg.Transform.AffinePlan(PixelFarm.Agg.Transform.AffineMatrixCommand.Translate, -centerFormArc.cx, -centerFormArc.cy), new PixelFarm.Agg.Transform.AffinePlan(PixelFarm.Agg.Transform.AffineMatrixCommand.Scale, scaleRatio, scaleRatio), new PixelFarm.Agg.Transform.AffinePlan(PixelFarm.Agg.Transform.AffineMatrixCommand.Rotate, DegToRad(xaxisRotationAngleDec)), new PixelFarm.Agg.Transform.AffinePlan(PixelFarm.Agg.Transform.AffineMatrixCommand.Translate, centerFormArc.cx, centerFormArc.cy)); vxs = mat.TransformToVxs(vxs); } else { //not scalue var mat = PixelFarm.Agg.Transform.Affine.NewMatix( new PixelFarm.Agg.Transform.AffinePlan(PixelFarm.Agg.Transform.AffineMatrixCommand.Translate, -centerFormArc.cx, -centerFormArc.cy), new PixelFarm.Agg.Transform.AffinePlan(PixelFarm.Agg.Transform.AffineMatrixCommand.Rotate, DegToRad(xaxisRotationAngleDec)), new PixelFarm.Agg.Transform.AffinePlan(PixelFarm.Agg.Transform.AffineMatrixCommand.Translate, centerFormArc.cx, centerFormArc.cy)); vxs = mat.TransformToVxs(vxs); } } else { //no rotate if (centerFormArc.scaleUp) { var mat = PixelFarm.Agg.Transform.Affine.NewMatix( new PixelFarm.Agg.Transform.AffinePlan(PixelFarm.Agg.Transform.AffineMatrixCommand.Translate, -centerFormArc.cx, -centerFormArc.cy), new PixelFarm.Agg.Transform.AffinePlan(PixelFarm.Agg.Transform.AffineMatrixCommand.Scale, scaleRatio, scaleRatio), new PixelFarm.Agg.Transform.AffinePlan(PixelFarm.Agg.Transform.AffineMatrixCommand.Translate, centerFormArc.cx, centerFormArc.cy)); vxs = mat.TransformToVxs(vxs); } } vxs = aggStroke.MakeVxs(vxs); sclineRas.Reset(); sclineRas.AddPath(vxs); sclineRasToGL.DrawWithColor(sclineRas, sclinePack8, this.strokeColor); }
public SvgArcSegment(PointF start, float radiusX, float radiusY, float angle, SvgArcSize size, SvgArcSweep sweep, PointF end) : this(radiusX, radiusY, angle, size, sweep, false, end) { Start = start; }
//--------------------------------------------------------------------- public void DrawArc( float fromX, float fromY, float endX, float endY, float xaxisRotationAngleDec, float rx, float ry, SvgArcSize arcSize, SvgArcSweep arcSweep) { //------------------ //SVG Elliptical arc ... //from Apache Batik //----------------- CenterFormArc centerFormArc = new CenterFormArc(); ComputeArc2(fromX, fromY, rx, ry, AggMath.deg2rad(xaxisRotationAngleDec), arcSize == SvgArcSize.Large, arcSweep == SvgArcSweep.Negative, endX, endY, ref centerFormArc); // using (VectorToolBox.Borrow(out Arc arcTool)) using (VxsTemp.Borrow(out var v1, out var v2, out var v3)) { arcTool.Init(centerFormArc.cx, centerFormArc.cy, rx, ry, centerFormArc.radStartAngle, (centerFormArc.radStartAngle + centerFormArc.radSweepDiff)); bool stopLoop = false; foreach (VertexData vertexData in arcTool.GetVertexIter()) { switch (vertexData.command) { case VertexCmd.NoMore: stopLoop = true; break; default: v1.AddVertex(vertexData.x, vertexData.y, vertexData.command); //yield return vertexData; break; } //------------------------------ if (stopLoop) { break; } } double scaleRatio = 1; if (centerFormArc.scaleUp) { int vxs_count = v1.Count; double px0, py0, px_last, py_last; v1.GetVertex(0, out px0, out py0); v1.GetVertex(vxs_count - 1, out px_last, out py_last); double distance1 = Math.Sqrt((px_last - px0) * (px_last - px0) + (py_last - py0) * (py_last - py0)); double distance2 = Math.Sqrt((endX - fromX) * (endX - fromX) + (endY - fromY) * (endY - fromY)); if (distance1 < distance2) { scaleRatio = distance2 / distance1; } else { } } if (xaxisRotationAngleDec != 0) { //also rotate if (centerFormArc.scaleUp) { //var mat = Affine.NewMatix( // new AffinePlan(AffineMatrixCommand.Translate, -centerFormArc.cx, -centerFormArc.cy), // new AffinePlan(AffineMatrixCommand.Scale, scaleRatio, scaleRatio), // new AffinePlan(AffineMatrixCommand.Rotate, DegToRad(xaxisRotationAngleDec)), // new AffinePlan(AffineMatrixCommand.Translate, centerFormArc.cx, centerFormArc.cy)); //mat1.TransformToVxs(v1, v2); //v1 = v2; AffineMat mat = AffineMat.Iden; mat.Translate(-centerFormArc.cx, -centerFormArc.cy); mat.Scale(scaleRatio); mat.RotateDeg(xaxisRotationAngleDec); mat.Translate(centerFormArc.cx, centerFormArc.cy); VertexStoreTransformExtensions.TransformToVxs(ref mat, v1, v2); v1 = v2; } else { //not scale //var mat = Affine.NewMatix( // AffinePlan.Translate(-centerFormArc.cx, -centerFormArc.cy), // AffinePlan.RotateDeg(xaxisRotationAngleDec), // AffinePlan.Translate(centerFormArc.cx, centerFormArc.cy)); //mat.TransformToVxs(v1, v2); //v1 = v2; AffineMat mat = AffineMat.Iden; mat.Translate(-centerFormArc.cx, -centerFormArc.cy); mat.RotateDeg(xaxisRotationAngleDec); mat.Translate(centerFormArc.cx, centerFormArc.cy); VertexStoreTransformExtensions.TransformToVxs(ref mat, v1, v2); v1 = v2; } } else { //no rotate if (centerFormArc.scaleUp) { //var mat = Affine.NewMatix( // new AffinePlan(AffineMatrixCommand.Translate, -centerFormArc.cx, -centerFormArc.cy), // new AffinePlan(AffineMatrixCommand.Scale, scaleRatio, scaleRatio), // new AffinePlan(AffineMatrixCommand.Translate, centerFormArc.cx, centerFormArc.cy)); //mat.TransformToVxs(v1, v2); //v1 = v2; AffineMat mat = AffineMat.Iden; mat.Translate(-centerFormArc.cx, -centerFormArc.cy); mat.RotateDeg(scaleRatio); mat.Translate(centerFormArc.cx, centerFormArc.cy); // VertexStoreTransformExtensions.TransformToVxs(ref mat, v1, v2); v1 = v2; } } //_stroke.Width = this.StrokeWidth; //_stroke.MakeVxs(v1, v3); //_pcx.DrawGfxPath(_pcx.StrokeColor, _pathRenderVxBuilder.CreatePathRenderVx(v3)); } }
internal static void MakeBezierCurveFromArc(ref PointF start, ref PointF end, float rx, float ry, float angle, SvgArcSize arcSize, SvgArcSweep arcSweep, out PointF[] bezier4Points) { double sinPhi = Math.Sin(angle * SvgPathSegArc.RAD_PER_DEG); double cosPhi = Math.Cos(angle * SvgPathSegArc.RAD_PER_DEG); double x1dash = cosPhi * (start.X - end.X) / 2.0 + sinPhi * (start.Y - end.Y) / 2.0; double y1dash = -sinPhi * (start.X - end.X) / 2.0 + cosPhi * (start.Y - end.Y) / 2.0; double root; double numerator = (rx * rx * ry * ry) - (rx * rx * y1dash * y1dash) - (ry * ry * x1dash * x1dash); if (numerator < 0.0) { float s = (float)Math.Sqrt(1.0 - numerator / (rx * rx * ry * ry)); rx *= s; ry *= s; root = 0.0; } else { root = ((arcSize == SvgArcSize.Large && arcSweep == SvgArcSweep.Positive) || (arcSize == SvgArcSize.Small && arcSweep == SvgArcSweep.Negative) ? -1.0 : 1.0) * Math.Sqrt(numerator / (rx * rx * y1dash * y1dash + ry * ry * x1dash * x1dash)); } double cxdash = root * rx * y1dash / ry; double cydash = -root * ry * x1dash / rx; double cx = cosPhi * cxdash - sinPhi * cydash + (start.X + end.X) / 2.0; double cy = sinPhi * cxdash + cosPhi * cydash + (start.Y + end.Y) / 2.0; double theta1 = SvgPathSegArc.CalculateVectorAngle(1.0, 0.0, (x1dash - cxdash) / rx, (y1dash - cydash) / ry); double dtheta = SvgPathSegArc.CalculateVectorAngle((x1dash - cxdash) / rx, (y1dash - cydash) / ry, (-x1dash - cxdash) / rx, (-y1dash - cydash) / ry); if (arcSweep == SvgArcSweep.Negative && dtheta > 0) { dtheta -= 2.0 * Math.PI; } else if (arcSweep == SvgArcSweep.Positive && dtheta < 0) { dtheta += 2.0 * Math.PI; } int nsegments = (int)Math.Ceiling((double)Math.Abs(dtheta / (Math.PI / 2.0))); double delta = dtheta / nsegments; double t = 8.0 / 3.0 * Math.Sin(delta / 4.0) * Math.Sin(delta / 4.0) / Math.Sin(delta / 2.0); double startX = start.X; double startY = start.Y; bezier4Points = new PointF[nsegments * 4]; int nn = 0; for (int n = 0; n < nsegments; ++n) { double cosTheta1 = Math.Cos(theta1); double sinTheta1 = Math.Sin(theta1); double theta2 = theta1 + delta; double cosTheta2 = Math.Cos(theta2); double sinTheta2 = Math.Sin(theta2); double endpointX = cosPhi * rx * cosTheta2 - sinPhi * ry * sinTheta2 + cx; double endpointY = sinPhi * rx * cosTheta2 + cosPhi * ry * sinTheta2 + cy; double dx1 = t * (-cosPhi * rx * sinTheta1 - sinPhi * ry * cosTheta1); double dy1 = t * (-sinPhi * rx * sinTheta1 + cosPhi * ry * cosTheta1); double dxe = t * (cosPhi * rx * sinTheta2 + sinPhi * ry * cosTheta2); double dye = t * (sinPhi * rx * sinTheta2 - cosPhi * ry * cosTheta2); bezier4Points[nn] = new PointF((float)startX, (float)startY); bezier4Points[nn + 1] = new PointF((float)(startX + dx1), (float)(startY + dy1)); bezier4Points[nn + 2] = new PointF((float)(endpointX + dxe), (float)(endpointY + dye)); bezier4Points[nn + 3] = new PointF((float)endpointX, (float)endpointY); nn += 4; theta1 = theta2; startX = (float)endpointX; startY = (float)endpointY; } }
public static void MakeBezierCurveFromArc(ref PointF start, ref PointF end, float rx, float ry, float angle, SvgArcSize arcSize, SvgArcSweep arcSweep, out PointF[] bezier4Points) { double sinPhi = Math.Sin(angle * SvgPathSegArc.RAD_PER_DEG); double cosPhi = Math.Cos(angle * SvgPathSegArc.RAD_PER_DEG); double x1dash = cosPhi * (start.X - end.X) / 2.0 + sinPhi * (start.Y - end.Y) / 2.0; double y1dash = -sinPhi * (start.X - end.X) / 2.0 + cosPhi * (start.Y - end.Y) / 2.0; double root; double numerator = (rx * rx * ry * ry) - (rx * rx * y1dash * y1dash) - (ry * ry * x1dash * x1dash); if (numerator < 0.0) { float s = (float)Math.Sqrt(1.0 - numerator / (rx * rx * ry * ry)); rx *= s; ry *= s; root = 0.0; } else { root = ((arcSize == SvgArcSize.Large && arcSweep == SvgArcSweep.Positive) || (arcSize == SvgArcSize.Small && arcSweep == SvgArcSweep.Negative) ? -1.0 : 1.0) * Math.Sqrt(numerator / (rx * rx * y1dash * y1dash + ry * ry * x1dash * x1dash)); } double cxdash = root * rx * y1dash / ry; double cydash = -root * ry * x1dash / rx; double cx = cosPhi * cxdash - sinPhi * cydash + (start.X + end.X) / 2.0; double cy = sinPhi * cxdash + cosPhi * cydash + (start.Y + end.Y) / 2.0; double theta1 = SvgPathSegArc.CalculateVectorAngle(1.0, 0.0, (x1dash - cxdash) / rx, (y1dash - cydash) / ry); double dtheta = SvgPathSegArc.CalculateVectorAngle((x1dash - cxdash) / rx, (y1dash - cydash) / ry, (-x1dash - cxdash) / rx, (-y1dash - cydash) / ry); if (arcSweep == SvgArcSweep.Negative && dtheta > 0) { dtheta -= 2.0 * Math.PI; } else if (arcSweep == SvgArcSweep.Positive && dtheta < 0) { dtheta += 2.0 * Math.PI; } int nsegments = (int)Math.Ceiling((double)Math.Abs(dtheta / (Math.PI / 2.0))); double delta = dtheta / nsegments; double t = 8.0 / 3.0 * Math.Sin(delta / 4.0) * Math.Sin(delta / 4.0) / Math.Sin(delta / 2.0); double startX = start.X; double startY = start.Y; bezier4Points = new PointF[nsegments * 4]; int nn = 0; for (int n = 0; n < nsegments; ++n) { double cosTheta1 = Math.Cos(theta1); double sinTheta1 = Math.Sin(theta1); double theta2 = theta1 + delta; double cosTheta2 = Math.Cos(theta2); double sinTheta2 = Math.Sin(theta2); double endpointX = cosPhi * rx * cosTheta2 - sinPhi * ry * sinTheta2 + cx; double endpointY = sinPhi * rx * cosTheta2 + cosPhi * ry * sinTheta2 + cy; double dx1 = t * (-cosPhi * rx * sinTheta1 - sinPhi * ry * cosTheta1); double dy1 = t * (-sinPhi * rx * sinTheta1 + cosPhi * ry * cosTheta1); double dxe = t * (cosPhi * rx * sinTheta2 + sinPhi * ry * cosTheta2); double dye = t * (sinPhi * rx * sinTheta2 - cosPhi * ry * cosTheta2); bezier4Points[nn] = new PointF((float)startX, (float)startY); bezier4Points[nn + 1] = new PointF((float)(startX + dx1), (float)(startY + dy1)); bezier4Points[nn + 2] = new PointF((float)(endpointX + dxe), (float)(endpointY + dye)); bezier4Points[nn + 3] = new PointF((float)endpointX, (float)endpointY); nn += 4; theta1 = theta2; startX = (float)endpointX; startY = (float)endpointY; } }
//--------------------------------------------------------------------- public void DrawArc(float fromX, float fromY, float endX, float endY, float xaxisRotationAngleDec, float rx, float ry, SvgArcSize arcSize, SvgArcSweep arcSweep) { //------------------ //SVG Elliptical arc ... //from Apache Batik //----------------- CenterFormArc centerFormArc = new CenterFormArc(); ComputeArc2(fromX, fromY, rx, ry, DegToRad(xaxisRotationAngleDec), arcSize == SvgArcSize.Large, arcSweep == SvgArcSweep.Negative, endX, endY, ref centerFormArc); arcTool.Init(centerFormArc.cx, centerFormArc.cy, rx, ry, centerFormArc.radStartAngle, (centerFormArc.radStartAngle + centerFormArc.radSweepDiff)); VertexStore v1 = GetFreeVxs(); bool stopLoop = false; foreach (VertexData vertexData in arcTool.GetVertexIter()) { switch (vertexData.command) { case VertexCmd.Stop: stopLoop = true; break; default: v1.AddVertex(vertexData.x, vertexData.y, vertexData.command); //yield return vertexData; break; } //------------------------------ if (stopLoop) { break; } } double scaleRatio = 1; if (centerFormArc.scaleUp) { int vxs_count = v1.Count; double px0, py0, px_last, py_last; v1.GetVertex(0, out px0, out py0); v1.GetVertex(vxs_count - 1, out px_last, out py_last); double distance1 = Math.Sqrt((px_last - px0) * (px_last - px0) + (py_last - py0) * (py_last - py0)); double distance2 = Math.Sqrt((endX - fromX) * (endX - fromX) + (endY - fromY) * (endY - fromY)); if (distance1 < distance2) { scaleRatio = distance2 / distance1; } else { } } if (xaxisRotationAngleDec != 0) { //also rotate if (centerFormArc.scaleUp) { var mat = PixelFarm.Agg.Transform.Affine.NewMatix( new PixelFarm.Agg.Transform.AffinePlan(PixelFarm.Agg.Transform.AffineMatrixCommand.Translate, -centerFormArc.cx, -centerFormArc.cy), new PixelFarm.Agg.Transform.AffinePlan(PixelFarm.Agg.Transform.AffineMatrixCommand.Scale, scaleRatio, scaleRatio), new PixelFarm.Agg.Transform.AffinePlan(PixelFarm.Agg.Transform.AffineMatrixCommand.Rotate, DegToRad(xaxisRotationAngleDec)), new PixelFarm.Agg.Transform.AffinePlan(PixelFarm.Agg.Transform.AffineMatrixCommand.Translate, centerFormArc.cx, centerFormArc.cy)); var v2 = GetFreeVxs(); mat.TransformToVxs(v1, v2); ReleaseVxs(ref v1); v1 = v2; } else { //not scalue var mat = PixelFarm.Agg.Transform.Affine.NewMatix( new PixelFarm.Agg.Transform.AffinePlan(PixelFarm.Agg.Transform.AffineMatrixCommand.Translate, -centerFormArc.cx, -centerFormArc.cy), new PixelFarm.Agg.Transform.AffinePlan(PixelFarm.Agg.Transform.AffineMatrixCommand.Rotate, DegToRad(xaxisRotationAngleDec)), new PixelFarm.Agg.Transform.AffinePlan(PixelFarm.Agg.Transform.AffineMatrixCommand.Translate, centerFormArc.cx, centerFormArc.cy)); var v2 = GetFreeVxs(); mat.TransformToVxs(v1, v2); ReleaseVxs(ref v1); v1 = v2; } } else { //no rotate if (centerFormArc.scaleUp) { var mat = PixelFarm.Agg.Transform.Affine.NewMatix( new PixelFarm.Agg.Transform.AffinePlan(PixelFarm.Agg.Transform.AffineMatrixCommand.Translate, -centerFormArc.cx, -centerFormArc.cy), new PixelFarm.Agg.Transform.AffinePlan(PixelFarm.Agg.Transform.AffineMatrixCommand.Scale, scaleRatio, scaleRatio), new PixelFarm.Agg.Transform.AffinePlan(PixelFarm.Agg.Transform.AffineMatrixCommand.Translate, centerFormArc.cx, centerFormArc.cy)); var v2 = GetFreeVxs(); mat.TransformToVxs(v1, v2); ReleaseVxs(ref v1); v1 = v2; } } _aggStroke.Width = this.StrokeWidth; var v3 = _aggStroke.MakeVxs(v1, GetFreeVxs()); _canvas.DrawGfxPath(_canvas.StrokeColor, InternalGraphicsPath.CreateGraphicsPath(new VertexStoreSnap(v3))); ReleaseVxs(ref v3); ReleaseVxs(ref v1); }