public static bool TryParseArcPath(string ArcPath, out SvgArcPath arc) { string[] strArray = ArcPath.Split(' '); if (strArray[0] == "M" && strArray[3] == "A") { double.TryParse(strArray[1], out arc.x1); //x1 double.TryParse(strArray[2], out arc.y1); //y1 double.TryParse(strArray[4], out arc.rx); //rx double.TryParse(strArray[5], out arc.ry); //ry double.TryParse(strArray[6], out arc.phi); //x-axis-rotation int.TryParse(strArray[7], out int fA); //large-arc-flag arc.fA = fA == 1; int.TryParse(strArray[8], out int fS); //sweep-flag arc.fS = fS == 1; double.TryParse(strArray[9], out arc.x2); //x2 double.TryParse(strArray[10], out arc.y2); //y2 return(true); } else if (strArray[0].StartsWith("M") && strArray[2].StartsWith("A")) { double.TryParse(strArray[0][1..], out arc.x1); //x1
//conversion_from_endpoint_to_center_parameterization //sample : svgArcToCenterParam(200,200,50,50,0,1,1,300,200) // x1 y1 rx ry φ fA fS x2 y2 private static ArcParams SvgArcToArcParam(SvgArcPath svgArc) { double cx, cy, startAngle, deltaAngle, endAngle; var PIx2 = Math.PI * 2.0; if (svgArc.rx < 0) { svgArc.rx = -svgArc.rx; } if (svgArc.ry < 0) { svgArc.ry = -svgArc.ry; } if (svgArc.rx == 0.0 || svgArc.ry == 0.0) { // invalid arguments throw new Exception("rx and ry can not be 0"); } var s_phi = Math.Sin(svgArc.phi); var c_phi = Math.Cos(svgArc.phi); var hd_x = (svgArc.x1 - svgArc.x2) / 2.0; // half diff of x var hd_y = (svgArc.y1 - svgArc.y2) / 2.0; // half diff of y var hs_x = (svgArc.x1 + svgArc.x2) / 2.0; // half sum of x var hs_y = (svgArc.y1 + svgArc.y2) / 2.0; // half sum of y // F6.5.1 var x1_ = c_phi * hd_x + s_phi * hd_y; var y1_ = c_phi * hd_y - s_phi * hd_x; // F.6.6 Correction of out-of-range radii // Step 3: Ensure radii are large enough var lambda = (x1_ * x1_) / (svgArc.rx * svgArc.rx) + (y1_ * y1_) / (svgArc.ry * svgArc.ry); if (lambda > 1) { svgArc.rx *= Math.Sqrt(lambda); svgArc.ry *= Math.Sqrt(lambda); } var rxry = svgArc.rx * svgArc.ry; var rxy1_ = svgArc.rx * y1_; var ryx1_ = svgArc.ry * x1_; var sum_of_sq = rxy1_ * rxy1_ + ryx1_ * ryx1_; // sum of square if (sum_of_sq == 0) { throw new Exception("start point can not be same as end point"); } var coe = Math.Sqrt(Math.Abs((rxry * rxry - sum_of_sq) / sum_of_sq)); if (svgArc.fA == svgArc.fS) { coe = -coe; } // F6.5.2 var cx_ = coe * rxy1_ / svgArc.ry; var cy_ = -coe * ryx1_ / svgArc.rx; // F6.5.3 cx = c_phi * cx_ - s_phi * cy_ + hs_x; cy = s_phi * cx_ + c_phi * cy_ + hs_y; var xcr1 = (x1_ - cx_) / svgArc.rx; var xcr2 = (x1_ + cx_) / svgArc.rx; var ycr1 = (y1_ - cy_) / svgArc.ry; var ycr2 = (y1_ + cy_) / svgArc.ry; // F6.5.5 startAngle = Radian(1.0, 0.0, xcr1, ycr1); // F6.5.6 deltaAngle = Radian(xcr1, ycr1, -xcr2, -ycr2); while (deltaAngle > PIx2) { deltaAngle -= PIx2; } while (deltaAngle < 0.0) { deltaAngle += PIx2; } if (!svgArc.fS) { deltaAngle -= PIx2; } endAngle = startAngle + deltaAngle; while (endAngle > PIx2) { endAngle -= PIx2; } while (endAngle < 0.0) { endAngle += PIx2; } ArcParams outputObj = new ArcParams() { /* cx, cy, startAngle, deltaAngle */ center_x = cx, center_y = cy, startAngle = startAngle * (180 / Math.PI), endAngle = endAngle * (180 / Math.PI), radius = svgArc.rx }; return(outputObj); }