Find the arc of the intersection between circle and rectangle

末鹿安然 提交于 2020-01-24 21:08:44

问题


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:


  1. Shift all coordinates to make circle zero-centered (box.left = box.left - circlecenter.x etc) for simplicity
  2. 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
  3. 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!