判断矩形和圆交

一.算法

        方法一:先判断矩形是否在圆内(矩形的四个顶点是否在圆内),若是则不相交,否则再判断圆心到矩形四条边的最短距离(点到线段的最短距离)是否存在小于半径的,若是则相交(认为矩形包括圆是不相交的,已经先排除了)。方法二:圆分平面为四部分,

        方法二:圆分平面四部分,不相交的情况分了几种:长方形在圆形上面,长方形在圆形下面,长方形在圆形左边,长方形在圆形右边,长方形在圆形内部,圆形在长方形内部。

        方法三:矩形分平面九部分,用矩形的四个边,把空间划分成为9个区域,判定圆心的位置在那个区域当中,如果在矩形的内部,则必然的相交,如果位于上下左右四个边区域当中,检测圆心到边的距离,判定是否相交,如果位于四个角点对应的区域,只要检测矩形的四个角是否在圆的内部就是了。

        错误做法:

  • 圆在矩形内或者矩形在圆内都不算相交,假设对角线是左下角和右上角(目测是这样,不是也没关系),若圆心不在横纵坐标范围内那么肯定不交,这种想法错误,想想矩形在圆右下角,看下图。

  • 这样判断矩形在圆内不对,看下图
p.y+r>ymax&&p.y-r>ymin&&p.x-r>xmin&&p.x+r>xmax

 

        不得不说做这道题收获不小……

二.算法实现

        以HDU1221为例,直接去AC吧。

import java.util.Scanner;
//AC了
public class W {
  public static void main(String[] args) {
    int T;
    double x,y;
    double r;
    Scanner sc = new Scanner(System.in);
    T = sc.nextInt();
    while(T-->0) {
      x = sc.nextDouble();
      y = sc.nextDouble();
      //圆心
      PointW p = new PointW(x,y);
      r = sc.nextDouble();
      x = sc.nextDouble();
      y = sc.nextDouble();
      PointW p1 = new PointW(x,y);
      x = sc.nextDouble();
      y = sc.nextDouble();
      PointW p2 = new PointW(x,y);
      boolean tag = go(p,r,p1,p2);
      if(tag) {
        System.out.println("YES");
      }else {
        System.out.println("NO");
      }
    }
  }
  private static boolean go(PointW p, double r, PointW p1, PointW p2) {
    /*
     * 为节省内存也可以只用两个点,不要Point类,x1,y1存储xy小值,然后排列组合就得到四个点了
     */
    double xmin = Math.min(p1.x,p2.x);
    double xmax = p1.x + p2.x - xmin;
    double ymin = Math.min(p1.y,p2.y);
    double ymax = p1.y + p2.y - ymin;
    //矩形四点;从左下角向上、向右,再向下
    PointW q1 = new PointW(xmin,ymin);
    PointW q2 = new PointW(xmin,ymax);
    PointW q3 = new PointW(xmax,ymax);
    PointW q4 = new PointW(xmax,ymin);
    boolean i = Double.compare(distance(p, q1), r)<0;
    boolean j = Double.compare(distance(p, q2), r)<0;
    boolean k = Double.compare(distance(p, q3), r)<0;
    boolean t = Double.compare(distance(p, q4), r)<0;
    //在圆内可以这样算,在圆外不能简单地把小于0改成大于0,考虑矩形贯穿圆
    if(xmax<p.x-r||ymin>p.y+r||xmin>p.x+r||ymax<p.y-r) {
      return false;
    }else if(i&&j&&k&&t) {
      return false;
    }else if(p.y+r<ymax&&p.y-r>ymin&&p.x-r>xmin&&p.x+r<xmax){//在矩形内
        return false;
    }else {
      return true;
    }
  }
  private static double distance(PointW p, PointW p1) {
    return Math.hypot(p.x-p1.x, p.y-p1.y);
  }
}
class PointW {
  double x;
  double y;
  public PointW() {
    this.x = 0;
    this.y = 0;
  }
  public PointW(double x, double y) {
    this.x = x;
    this.y = y;
  }
}

        下面的wa了,路过的给瞧一瞧。

import java.util.Scanner;
//wa
public class HDU1221 {
  public static void main(String[] args) {
    int T;
    double x,y;
    double r;
    Scanner sc = new Scanner(System.in);
    T = sc.nextInt();
    while(T-->0) {
      x = sc.nextDouble();
      y = sc.nextDouble();
      //圆心
      Point p = new Point(x,y);
      r = sc.nextDouble();
      x = sc.nextDouble();
      y = sc.nextDouble();
      Point p1 = new Point(x,y);
      x = sc.nextDouble();
      y = sc.nextDouble();
      Point p2 = new Point(x,y);
      boolean tag = go(p,r,p1,p2);
      if(tag) {
        System.out.println("YES");
      }else {
        System.out.println("NO");
      }
    }
  }
  private static boolean go(Point p, double r, Point p1, Point p2) {
    double xmin = Math.min(p1.x,p2.x);
    double xmax = p1.x + p2.x - xmin;
    double ymin = Math.min(p1.y,p2.y);
    //原来ymin写成了xmin
    double ymax = p1.y + p2.y - ymin;
    //矩形四点;从左下角向上、向右,再向下
    Point q1 = new Point(xmin,ymin);
    Point q2 = new Point(xmin,ymax);
    Point q3 = new Point(xmax,ymax);
    Point q4 = new Point(xmax,ymin);
    boolean i = Double.compare(distance(p, q1), r)<0;
    boolean j = Double.compare(distance(p, q2), r)<0;
    boolean k = Double.compare(distance(p, q3), r)<0;
    boolean t = Double.compare(distance(p, q4), r)<0;
    if(i&&j&&k&&t) {//先排除在圆内情况,采用if else
      return false;
    }else {
      //等于0表示相切(tangent)
      i = Double.compare(pointToLine(q1,q2,p), r)<=0;
      j = Double.compare(pointToLine(q2,q3,p), r)<=0;
      k = Double.compare(pointToLine(q3,q4,p), r)<=0;
      t = Double.compare(pointToLine(q4,q1,p), r)<=0;
      if(i||j||k||t) {
        return true;
      }else {
        return false;
      }
    }
  }
  private static double distance(Point p, Point p1) {
    return Math.hypot(p.x-p1.x, p.y-p1.y);
  }
  //点到线段的最短距离,x0,y0是圆心
  private static double pointToLine(Point p1,Point p2, Point p) {
    double ans = 0;
    double a, b, c;
    a = distance(p1, p2);
    b = distance(p1, p);
    c = distance(p2, p);
    if (c+b==a) {//点在线段上
      ans = 0;
      return ans;
    }
    if (a<=1e-8) {//不是线段,是一个点
      ans = b;
      return ans;
    }
    if (c*c >= a*a + b*b) { //组成直角三角形或钝角三角形,p1为直角或钝角
      ans = b;
      return ans;
    }
    if (b * b >= a * a + c * c) {// 组成直角三角形或钝角三角形,p2为直角或钝角
      ans = c;
      return ans;
    }
    // 组成锐角三角形,则求三角形的高
    double p0 = (a + b + c) / 2;// 半周长
    double s = Math.sqrt(p0 * (p0 - a) * (p0 - b) * (p0 - c));// 海伦公式求面积
    ans = 2*s / a;// 返回点到线的距离(利用三角形面积公式求高)
    return ans;
  }
}
class Point {
  double x;
  double y;
  public Point() {
    this.x = 0;
    this.y = 0;
  }
  public Point(double x, double y) {
    this.x = x;
    this.y = y;
  }
}
时间: 2024-09-29 15:54:14

判断矩形和圆交的相关文章

矩形和圆 位置关系-如何用C++写出:判断矩形和圆的位置关系?

问题描述 如何用C++写出:判断矩形和圆的位置关系? 我知道有四种关系,相交,包含(两种),相离. 圆包含矩形的情况可以 检测圆的四个坐标轴方向点的坐标是否在矩形内或在矩形上 矩形包含圆的情况可以 检测矩形的四点是否在圆中 但是矩形和圆相交相离就不知道怎么判断了....

矢量图 矩形区域-VB矢量图 判断矩形区域内包含的图形(对象)

问题描述 VB矢量图 判断矩形区域内包含的图形(对象) 在VB做的矢量图中,自己定义一个矩形区域,如何确定在这个矩形区域内是否存在图像对象

控件-IntersectsWith判断矩形交集,当矩形参数带负数不能判断

问题描述 IntersectsWith判断矩形交集,当矩形参数带负数不能判断 在窗口界面用画一个矩形选框,通过和控件的bouds矩形做交集来判断是否接触,当从左上角向右下方的时候好使,但是当画的矩形参数带负数,比如从右下到左上时就不能判断了,求大虾支招.有什么办法可以更好的判断,或是把画的矩形转成正参数,求教 解决方案 好吧,我不该太懒这都懒得想,自己附上答案. if (MouseRect.Width < 0) { MouseRect.X = MouseRect.X + MouseRect.Wi

C++判断矩形相交的方法_C 语言

本文实例讲述了C++判断矩形相交的方法.分享给大家供大家参考.具体如下: 已知2矩形原点和宽高,判断2矩形相交,相交矩形 相交判断原理: 假定矩形是用一对点表达的(minx, miny) (maxx, maxy),那么两个矩形     rect1{(minx1, miny1)(maxx1, maxy1)}     rect2{(minx2, miny2)(maxx2, maxy2)}  相交的结果一定是个矩形,构成这个相交矩形rect{(minx, miny) (maxx, maxy)}的点对坐

3.请使用C#作为编程语言,编写一段程序,判断平面上一个矩形和一个圆形是否有重叠。

问题描述 需自行给出矩形和圆形的类声明,不要使用.NETframework提供的基础类. 解决方案 解决方案二:判断五个Point圆的Point和半径r计算矩形的四个角坐标是否有任意一个与圆Point的直线距离在r以内,就是有重叠,相等的看判断标准,大于r的,就不重叠,两个坐标点算直线距离总会吧,直角三角形解决方案三:明目张胆的不劳而获解决方案四:没有重叠....结贴解决方案五:假设圆形是a,矩形是b,首先,要计算出a的外接矩形c(通过a的原点坐标加减半径),然后判断b和c的相交部分(如果存在的

第12周-任务4-点类与圆类

[题目]点类与圆类(1)先建立一个Point(点)类,包含数据成员x,y(坐标点):(2)以Point为基类,派生出一个Circle(圆)类,增加数据成员(半径),基类的成员表示圆心:(3)编写上述两类中的构造.析构函数及必要的输入输出函数(4)定义友元函数int locate,判断点p在圆c上.圆c内或圆c外,返回值<0圆内,==0圆上,>0 圆外:(5)重载关系运算符(6种)运算符,使之能够按圆的面积比较两个圆的大小:(6)给定一点p,求出该点与圆心相连成的直线与圆的两个交点并输出下面给出

Photoshop制作标准椭圆矩形的三种方法

椭圆矩形介于圆和圆角矩形中间的形状,主题图标绘制最流行的形状之一;有一些新人和身边朋友问我怎么制作这形状,所以,分享一下我的绘制方法. 最终效果 准备工作: 打开Photoshop,新建600 * 600的画布,其它参数默认,点确定. 方法1: 鼠标移至左侧工具栏矩形工具上,点击三角箭头切换成多边形工具.鼠标移至选项栏设置边:4,点击设置图标(齿轮),按下展开,勾选平滑拐角. 按住Shift,按住鼠标左键在画布中央绘制就可以了. 放大之后发现它的边缘是虚的像素,为了更加精确的显示,要让边缘对齐像

PS制作标准的椭圆矩形

  椭圆矩形介于圆和圆角矩形中间的形状,主题图标绘制最流行的形状之一;有一些新人和身边朋友问我怎么制作这形状,所以,分享一下我的绘制方法. 最终效果 准备工作: 打开Photoshop,新建600 * 600的画布,其它参数默认,点确定. 方法1: 鼠标移至左侧工具栏矩形工具上,点击三角箭头切换成多边形工具.鼠标移至选项栏设置边:4,点击设置图标(齿轮),按下展开,勾选平滑拐角. 按住Shift,按住鼠标左键在画布中央绘制就可以了. 放大之后发现它的边缘是虚的像素,为了更加精确的显示,要让边缘对

图像处理-一个图像识别的问题(判断物体是否在范围内)

问题描述 一个图像识别的问题(判断物体是否在范围内) 最近做一个项目涉及到一个人因的可视性问题,前面的不说了,得到一个图像,判断零件是否在一个圆内,请问大神这个判断怎么实现 解决方案 首先要看看你的零件的轮廓.给轮廓设n个点,判断这n个点是否在圆内就可以了,具体判断方法数学里面有的,如何判断点在圆内... 解决方案二: 把轮廓识别出来,判断就是数学的问题了.