c# - Given bounding rectangle, starting angle, and sweep angle, how to determine points of the arc endpoints -
given bounding rectangle, starting angle , sweep angle, how determine points of each end of arc?
private void mypaint(object sender, painteventargs e) { graphics g = e.graphics; rectangle rc = new rectangle(242, 299, 200, 300); pen penred = new pen(color.red, 1); g.drawarc(penred, rc, 18, -108); // todo - determine point of each end of arc // point pt1 = ??? // point pt2 = ??? }
using equation of ellipse excellent mathematics answer can calculate start , end points of ellipse, given start angle , sweep.
first, need center of bounding box, know how shift coordinates. that's simply
rectangle rc = new rectangle(242, 299, 200, 300); int cx = (rc.left + rc.right) / 2; int cy = (rc.bottom + rc.top) / 2; // debugging purposes, let's mark point. g.fillrectangle(brushes.yellow, rectangle.fromltrb(cx - 3, cy - 3, cx + 3, cy + 3));
we need convert angles degrees radians, , change clockwise angle counter-clockwise angle so:
double mintheta = (math.pi / 180) * (360 - start); double maxtheta = (math.pi / 180) * (360 - (start + sweep));
we'll define 2 helper functions, first normalize angle (map arbitrary angles range 0-360) , second adjust calculated (x, y) coordinates correct quadrant. (given positive y down on form)
public double normalizeangle(double angle) { while (angle >= 360) angle -= 360; while (angle < 0) angle += 360; return angle; } public void adjustcoordinatesforangle(double angle, ref double x, ref double y) { if (angle > 0 && angle <= 90) { x *= 1; y *= 1; } else if (angle >= 90 && angle < 180) { x *= -1; y *= 1; } else if (angle >= 180 && angle < 270) { x *= -1; y *= -1; } else if (angle >= 270 && angle < 360) { x *= 1; y *= -1; } }
we have enough information calculate start , end points.
double mintheta = (math.pi / 180) * (360 - start); double maxtheta = (math.pi / 180) * (360 - (start + sweep)); double = width / 2.0; double b = height / 2.0; double denom = math.pow(a, 2) * math.pow(math.tan(mintheta), 2); denom = denom / math.pow(b, 2); denom = math.sqrt(denom + 1); double x = math.abs(a / denom); double y = math.abs((a * math.tan(mintheta)) / denom); start = normalizeangle(start); this.adjustcoordinatesforangle(start, ref x, ref y);
those coordinates relative bounding box's center, offset using center point calculated above:
x += cx; y += cy;
we can draw point:
g.fillrectangle(brushes.purple, new rectangle((int)x - 3, (int)y - 3, 6, 6));
all paint function looks this:
private void mypaint(object sender, painteventargs e) { double start = 18; double sweep = -108; graphics g = e.graphics; g.clear(color.black); rectangle rc = new rectangle(200, 10, 200, 300); int cx = (rc.left + rc.right) / 2; int cy = (rc.bottom + rc.top) / 2; g.fillrectangle(brushes.yellow, rectangle.fromltrb(cx - 3, cy - 3, cx + 3, cy + 3)); int width = rc.width; int height = rc.height; if (start >= 360) start -= 360; double mintheta = (math.pi / 180) * (360 - start); double maxtheta = (math.pi / 180) * (360 - (start + sweep)); double = width / 2.0; double b = height / 2.0; double denom = math.pow(a, 2) * math.pow(math.tan(mintheta), 2); denom = denom / math.pow(b, 2); denom = math.sqrt(denom + 1); double x = math.abs(a / denom); double y = math.abs((a * math.tan(mintheta)) / denom); start = normalizeangle(start); this.adjustcoordinatesforangle(start, ref x, ref y); x += cx; y += cy; g.fillrectangle(brushes.purple, new rectangle((int)x - 3, (int)y - 3, 6, 6)); denom = math.pow(a, 2) * math.pow(math.tan(maxtheta), 2); denom = denom / math.pow(b, 2); denom = math.sqrt(denom + 1); x = math.abs(a / denom); y = math.abs((a * math.tan(maxtheta)) / denom); double endangle = (start + sweep); endangle = normalizeangle(endangle); this.adjustcoordinatesforangle(endangle, ref x, ref y); x += cx; y += cy; g.fillrectangle(brushes.blue, new rectangle((int)x - 3, (int)y - 3, 6, 6)); pen penred = new pen(color.red, 1); g.drawrectangle(pens.green, rc); g.drawarc(penred, rc, (float)start, (float)sweep); }
i painted window background black make boxes , lines stand out better, , left in additional drawing elements, easier see what's happening in calculations above.
placing code form, , associating form's paint event produces result:
one final note, due rounding, start , end points may off pixel or two. if want more accuracy, you'd have draw arc yourself.
Comments
Post a Comment