问题
I need to find the largest arc created from the intersection of a circle and a rectangle. I have the center of the circle, the radius and the coordinates of the rectangle, and I need to find the angle of the intersection points with the center of the circle.
I have a code that works, but it computes the solution iterating the points of the circumference, and I was wondering if there's a more elegant way to calculate the solution using trigonometry instead of "brute force".
That's my code:
import 'dart:math';
class CircleTheSquare {
final Point _circleCenter;
final int _circleRadius;
final Rectangle _box;
CircleTheSquare(this._circleCenter, this._circleRadius, this._box);
Map<String, double> get arc {
Map res = new Map();
double angle = .0;
double angleIn;
double angleOut;
double increment = 1.0;
while (true) {
if (angle > 360.0 && angleIn == null) {
break;
}
// Finds a point of intersection (next points will be inside
// of the rectangle).
if (!_isOutside(angle) && _isOutside(angle - increment)) {
angleIn = angle;
}
// Finds next intersection (next points will be outside
// of the rectangle).
if (angleIn != null &&
_isOutside(angle + increment) && !_isOutside(angle)) {
angleOut = angle;
// Adds the arc to result only there's not a previous largest arc.
if (res["in"] == null ||
angleOut - angleIn > res["arc"]) {
res["in"] = angleIn;
res["arc"] = angleOut - angleIn;
}
angleIn = null;
angleOut = null;
}
angle += increment;
}
// If there's no intersections.
// -- For simplicity, we will assume that the
// rectangle and the circle intersect or that the circle is
// inside of the rectangle).
if (res["in"] == null) {
res = {"in" : 0.0, "arc" : 360.0};
}
return res;
}
bool _isOutside(double a) {
var res;
double cx = _circleCenter.x + (_circleRadius * cos(a * (PI / 180)));
double cy = _circleCenter.y + (_circleRadius * sin(a * (PI / 180)));
bool hOut = cx < _box.left || cx > _box.left + _box.width;
bool vOut = cy < _box.top || cy > _box.top + _box.height;
if (hOut || vOut) {
res = true;
} else {
res = false;
}
return res;
}
}
main() {
CircleTheSquare a = new CircleTheSquare(new Point(250, 250), 100,
new Rectangle(0,0,500,500));
print(a.arc); // {in: 0.0, arc: 360.0}
CircleTheSquare b = new CircleTheSquare(new Point(450, 250), 100,
new Rectangle(0,0,500,500));
print(b.arc); // {in: 60.0, arc: 240.0}
CircleTheSquare c = new CircleTheSquare(new Point(420, 420), 100,
new Rectangle(0,0,500,500));
print(c.arc); // 4 intersections, returns the largest arc:
// {in: 127.0, arc: 196.0}
}
回答1:
- Shift all coordinates to make circle zero-centered (box.left = box.left - circlecenter.x etc) for simplicity
- Find intersections of circle with sides of rectangle. For example, for left side solve (box.left)^2 + y^2 = radius^2, check that point lies on side, add intersection point to list
- Sort intersection points by angle (probably, it is automatically provided by side check order), find the largest angle interval for arcs inside the rectangle
回答2:
As you expect, there are better and more direct methods to solve this. You may want to look at e.g. http://mathworld.wolfram.com/Circle-LineIntersection.html. Split the rectangle into lines, get intersection points for each line, determine if they are within the actual line segments, then find the points that give the largest arc.
来源:https://stackoverflow.com/questions/22605134/find-the-arc-of-the-intersection-between-circle-and-rectangle