判断一个点是否在一个不规则图形内

项目中遇到的问题,这里粘贴老总写的方法.学习一下...以备以后遇到时使用.

 

package com.vanda.economic.common.utils;

import java.util.List;

public class SpatialRelationUtil {
  private SpatialRelationUtil() {}


  public static class Point {

    public Point(int a, int b) {
      x = a;
      y = b;
    }

    public double x;
    public double y;
  }

  /**
   * 返回一个点是否在一个多边形区域内
   * 
   * @param mPoints 多边形坐标点列表
   * @param point 待判断点
   * @return true 多边形包含这个点,false 多边形未包含这个点。
   */
  public static boolean isPolygonContainsPoint(List<Point> mPoints, Point point) {
    int nCross = 0;
    for (int i = 0; i < mPoints.size(); i++) {
      Point p1 = mPoints.get(i);
      Point p2 = mPoints.get((i + 1) % mPoints.size());
      // 取多边形任意一个边,做点point的水平延长线,求解与当前边的交点个数
      // p1p2是水平线段,要么没有交点,要么有无限个交点
      if (p1.y == p2.y) continue;
      // point 在p1p2 底部 --> 无交点
      if (point.y < Math.min(p1.y, p2.y)) continue;
      // point 在p1p2 顶部 --> 无交点
      if (point.y >= Math.max(p1.y, p2.y)) continue;
      // 求解 point点水平线与当前p1p2边的交点的 X 坐标 通过前面几个if条件筛选,这里的如果求出来有交点一定在p1p2连接线上,而不是延长线上.
      double x = (point.y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y) + p1.x;
      if (x > point.x) // 当x=point.x时,说明point在p1p2线段上
        nCross++; // 只统计单边交点
    }
    // 单边交点为偶数,点在多边形之外 ---
    return (nCross % 2 == 1);
  }

  /**
   * 返回一个点是否在一个多边形边界上
   * 
   * @param mPoints 多边形坐标点列表
   * @param point 待判断点
   * @return true 点在多边形边上,false 点不在多边形边上。
   */
  public static boolean isPointInPolygonBoundary(List<Point> mPoints, Point point) {
    for (int i = 0; i < mPoints.size(); i++) {
      Point p1 = mPoints.get(i);
      Point p2 = mPoints.get((i + 1) % mPoints.size());
      // 取多边形任意一个边,做点point的水平延长线,求解与当前边的交点个数

      // point 在p1p2 底部 --> 无交点
      if (point.y < Math.min(p1.y, p2.y)) continue;
      // point 在p1p2 顶部 --> 无交点
      if (point.y > Math.max(p1.y, p2.y)) continue;

      // p1p2是水平线段,要么没有交点,要么有无限个交点
      if (p1.y == p2.y) {
        double minX = Math.min(p1.x, p2.x);
        double maxX = Math.max(p1.x, p2.x);
        // point在水平线段p1p2上,直接return true
        if ((point.y == p1.y) && (point.x >= minX && point.x <= maxX)) {
          return true;
        }
      } else { // 求解交点
        double x = (point.y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y) + p1.x;
        if (x == point.x) // 当x=point.x时,说明point在p1p2线段上
          return true;
      }
    }
    return false;
  }
}

PS: 这里有几个问题...因为学的数学知识已经全部还给老师了,所以有个地方还是没有懂,就是为什么isPolygonContainsPoint方法里面交点为偶数就是在图像外???

判断一个点是否不规则图形内,可以使用射线法和包围盒法相结合的方法。 具体做法如下: 1. 首先根据所有的坐标,计算得到一个包围盒,即最小矩形框,该包围盒的左上角坐标为`(x_min, y_min)`,右下角坐标为`(x_max, y_max)`。 2. 判断是否在包围盒内,如果不在,直接返回False。 3. 对于包围盒内的,向右射出一条射线,并计算该射线与不规则图形的边相交的次数。 4. 如果相交的次数为奇数,说明不规则图形内部;如果相交的次数为偶数,说明不规则图形外部。 需要注意的是,如果射线与不规则图形的边重合或者与顶重合,也需要计算在内,因为这也表示相交次数增加了。 以下是一个示例代码: ```python def is_point_in_irregular_polygon(x, y, points): # 计算包围盒 x_min = min([p[0] for p in points]) x_max = max([p[0] for p in points]) y_min = min([p[1] for p in points]) y_max = max([p[1] for p in points]) # 判断是否在包围盒内 if x < x_min or x > x_max or y < y_min or y > y_max: return False # 计算交数量 num_intersections = 0 for i in range(len(points)): x1, y1 = points[i] x2, y2 = points[(i + 1) % len(points)] if ((y1 <= y < y2) or (y2 <= y < y1)) and (x < max(x1, x2)): # 计算交的 x 坐标 x_inter = (y - y1) * (x2 - x1) / (y2 - y1) + x1 if (x_inter == x): # 如果交和顶重合,也需要计算在内 return True if (x_inter > x): # 如果交在右侧,计数加一 num_intersections += 1 # 判断数量的奇偶性 return (num_intersections % 2 == 1) ``` 这个示例代码只适用于简单的不规则多边形,如果是复杂的不规则图形,需要使用更复杂的算法,例如扫描线算法等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值