0

I am trying to create a system to convert arc parameters between 2D rendering formats (namely, Direct2D to GDI+). In Direct2D, arcs are defined by a start point, an end point, radii, rotation angle, sweep direction, and arc sweep size (above or below 180). In GDI+, they are defined by the bounding box, start angle, and ending angle (around the horizontal axis).

I need to convert from the Direct2D format into the GDI+ format. So far, I've been able to generate the bounding box but the angles are off. Below are images of what I should be getting (the Direct2D version) and what I am getting (in GDI+).

Expected:

img

Actual:

img

The code:

RectangleF bounds = GetBoundingBoxOfEllipse(startPoint, EndPoint, ArcRadii, RotationAngle);

PointF ctr = new PointF(bounds.Left + (bounds.Width / 2.0f), bounds.Top + (bounds.Height / 2.0f));

//I originally had +90 per the formula, but it was still wrong (too far the other way instead)
double ang1 = Math.Atan2(ctr.X - startPoint.X, ctr.Y - startPoint.Y) * (180.0 / Math.PI);
if (ang1 < 0)
    ang1 += 360.0;
double ang2 = Math.Atan2(ctr.X - EndPoint.X, ctr.Y - EndPoint.Y) * (180.0 / Math.PI);
if (ang2 < 0)
    ang2 += 360.0;

//Accounting for user options
double diffAng = Math.Abs(diffHeading(ang1, ang2));
if (ArcSize == ID2D1PathGeometry.Figure.ArcSegment.ArcSizeEnum.ArcSize_Large && diffAng < 180.0f)
    diffAng += 180.0;

if (SweepDirection == ID2D1PathGeometry.Figure.ArcSegment.SweepDirectionEnum.SweepDirection_Clockwise)
    diffAng *= -1.0;

path.AddArc(new RectangleF(bounds.X, bounds.Y, bounds.Width, bounds.Height), (float)ang1, (float)diffAng);                                                                

Any help would be greatly appreciated. I am pulling my hair out arbitrarily rotating these shapes. Thanks in advance!

Edit For ease, I've also included the function for getting the ellipse bounding box.

RectangleF GetBoundingBoxOfEllipse(PointF startPoint, PointF endPoint, SizeF radii, float rotAngle)
{

    PointF v = new PointF((startPoint.X - endPoint.X) / 2.0f, (startPoint.Y - endPoint.Y) / 2.0f);
    //rotate if needed later
    double x1p = v.X;
    double y1p = v.Y;

    double rx = Math.Abs(radii.Width);
    double ry = Math.Abs(radii.Height);

    double lam = (Math.Pow(x1p, 2.0) / Math.Pow(rx, 2.0)) + (Math.Pow(y1p, 2.0) / Math.Pow(ry, 2.0));
    if(lam > 1)
    {
        rx = Math.Sqrt(lam) * rx;
        ry = Math.Sqrt(lam) * ry;
    }

    double sign = 1; //const sign = fa === fs ? -1 : 1;

    double div = (rx * rx * ry * ry - rx * rx * y1p * y1p - ry * ry * x1p * x1p) /
                 (rx * rx * y1p * y1p + ry * ry * x1p * x1p);

    double co = sign * Math.Sqrt(Math.Abs(div));

    v = new PointF((float)(((rx * y1p) / ry) * co), (float)(((-ry * x1p) / rx) * co));           
    v.X += (startPoint.X + endPoint.X) / 2.0f;
    v.Y += (startPoint.Y + endPoint.Y) / 2.0f;

    return new RectangleF(v.X - (radii.Width), v.Y - (radii.Height), radii.Width * 2.0f, radii.Height * 2.0f);
}
Spektre
  • 49,595
  • 11
  • 110
  • 380
  • [Perhaps useful](https://stackoverflow.com/questions/9017100/calculate-center-of-svg-arc/12329083#12329083) – MBo Feb 02 '21 at 07:10
  • sounds like SVG arc... see: these: https://stackoverflow.com/a/41544540/2521214 and https://stackoverflow.com/a/59300224/2521214 – Spektre Feb 02 '21 at 07:58

0 Answers0