S
@Th69 : du hast mir aber den Anstoß andere Suchbegriffe zu verwenden, und PAAAM
[https://mortoray.com/2017/02/16/rendering-an-svg-elliptical-arc-as-bezier-curves/](Link Adresse)
da gibt source code den ich noch in c# protieren musste:
class ArcHelper
{
/**
Perform the endpoint to center arc parameter conversion as detailed in the SVG 1.1 spec.
F.6.5 Conversion from endpoint to center parameterization
@param r must be a ref in case it needs to be scaled up, as per the SVG spec
*/
public static void EndpointToCenterArcParams(Point p1, Point p2, ref Point r_, float xAngle,
bool flagA, bool flagS, out Point c, out Point angles)
{
double rX = Math.Abs(r_.X);
double rY = Math.Abs(r_.Y);
//(F.6.5.1)
double dx2 = (p1.X - p2.X) / 2.0;
double dy2 = (p1.Y - p2.Y) / 2.0;
double x1p = Math.Cos(xAngle) * dx2 + Math.Sin(xAngle) * dy2;
double y1p = -Math.Sin(xAngle) * dx2 + Math.Cos(xAngle) * dy2;
//(F.6.5.2)
double rxs = rX * rX;
double rys = rY * rY;
double x1ps = x1p * x1p;
double y1ps = y1p * y1p;
// check if the radius is too small `pq < 0`, when `dq > rxs * rys` (see below)
// cr is the ratio (dq : rxs * rys)
double cr = x1ps / rxs + y1ps / rys;
if (cr > 1)
{
//scale up rX,rY equally so cr == 1
var s = Math.Sqrt(cr);
rX = s * rX;
rY = s * rY;
rxs = rX * rX;
rys = rY * rY;
}
double dq = (rxs * y1ps + rys * x1ps);
double pq = (rxs * rys - dq) / dq;
double q = Math.Sqrt(Math.Max(0, pq)); //use Max to account for float precision
if (flagA == flagS)
q = -q;
double cxp = q * rX * y1p / rY;
double cyp = -q * rY * x1p / rX;
//(F.6.5.3)
double cx = Math.Cos(xAngle) * cxp - Math.Sin(xAngle) * cyp + (p1.X + p2.X) / 2;
double cy = Math.Sin(xAngle) * cxp + Math.Cos(xAngle) * cyp + (p1.Y + p2.Y) / 2;
//(F.6.5.5)
double theta = svgAngle(1, 0, (x1p - cxp) / rX, (y1p - cyp) / rY);
//(F.6.5.6)
double delta = svgAngle(
(x1p - cxp) / rX, (y1p - cyp) / rY,
(-x1p - cxp) / rX, (-y1p - cyp) / rY);
//delta = Math.Mod(delta, Math.PI * 2);
delta = delta % (Math.PI * 2);
if (!flagS)
delta -= 2 * Math.PI;
r_ =new Point((float)rX, (float)rY);
c = new Point((float)cx, (float)cy);
angles = new Point((float)theta, (float)delta);
}
public static T Clamp<T>(T val, T min, T max) where T : IComparable<T>
{
if (val.CompareTo(min) < 0) return min;
else if (val.CompareTo(max) > 0) return max;
else return val;
}
static double svgAngle(double ux, double uy, double vx, double vy)
{
var u = new Vector((float)ux, (float)uy);
var v = new Vector((float)vx, (float)vy);
//(F.6.5.4)
var dot = u * v;
//var dot = Vector.Dot(u, v);
var len = u.Length * v.Length;
// var len = Vector.Length(u) * Vector.Length(v);
var ang = Math.Acos(Clamp(dot / len, -1, 1)); //floating point precision, slightly over values appear
if ((u.X * v.Y - u.Y * v.X) < 0)
ang = -ang;
return ang;
}
}
klappt einwandfrei;)