zoukankan      html  css  js  c++  java
  • 经纬度计算是否在圆形内,是否在矩形内,是否在多边形内方法

    class 点面关系
    {
    static void Main(string[] args)
    {
    //Vector2D point1 = new Vector2D(39.909209536859834, 116.3225715637207);//in
    Vector2D point1 = new Vector2D(39.901045, 116.415596);//out
    Vector2D cPoint = new Vector2D(39.909209536859834, 116.3225715637207); 
    Console.WriteLine("点是否在圆内:" + 点是否在圆内(cPoint, 8000, point1));
    Console.WriteLine("点是否在圆内:" + 点是否在圆内(cPoint, new Vector2D(39.901045, 116.415596), point1));


    //Vector2D point2 = new Vector2D(39.924745, 116.379204);//in
    Vector2D point2 = new Vector2D(39.928695, 116.546059);//out
    Vector2D pointA = new Vector2D(39.913423004886866, 116.36890411376953);
    Vector2D pointB = new Vector2D(39.93450133090293, 116.38727188110351); 
    Console.WriteLine("点是否在矩形内:" + 点是否在矩形内(pointA, pointB, point2));


    Vector2D point3 = new Vector2D(39.957649, 116.376801);//in
    //Vector2D point3 = new Vector2D(39.919216, 116.2817);//out
    List<Vector2D> polygon = new List<Vector2D>();
    polygon.Add(new Vector2D(39.909209536859834, 116.3225715637207));
    polygon.Add(new Vector2D(39.95920953685983, 116.3725715637207));
    polygon.Add(new Vector2D(39.95920953685983, 116.42257156372072));
    polygon.Add(new Vector2D(39.909209536859834, 116.4725715637207));
    polygon.Add(new Vector2D(39.85920953685984, 116.42257156372072));
    polygon.Add(new Vector2D(39.85920953685984, 116.3725715637207)); 
    Console.WriteLine("点是否在多边形内:" + 点是否在多边形内(point3, polygon));

    Console.ReadLine();
    }

    /// <summary>
    /// 点是否在圆内(在边上也认为在圆内)
    /// </summary>
    /// <param name="cPoint">圆心坐标</param>
    /// <param name="cRadius">圆半径</param>
    /// <param name="point">当前点</param>
    /// <returns></returns>
    public static bool 点是否在圆内(Vector2D cPoint, double cRadius, Vector2D point)
    {
    var d1 = Distance(cPoint.Lat, cPoint.Lon, point.Lat, point.Lon);
    double distance = Math.Sqrt(Math.Pow(Math.Abs(point.X - cPoint.X), 2) + Math.Pow(Math.Abs(point.Y - cPoint.Y), 2));
    return distance <= cRadius;
    }

    private static double Distance(double lon1, double lat1, double lon2, double lat2)
    {
    double R = 6378137; //地球半径
    lat1 = lat1 * Math.PI / 180.0;
    lat2 = lat2 * Math.PI / 180.0; 
    double sa2 = Math.Sin((lat1 - lat2) / 2.0);
    double sb2 = Math.Sin(((lon1 - lon2) * Math.PI / 180.0) / 2.0);
    return 2 * R * Math.Asin(Math.Sqrt(sa2 * sa2 + Math.Cos(lat1) * Math.Cos(lat2) * sb2 * sb2));
    }

    /// <summary>
    /// 点是否在圆内(在边上也认为在圆内)
    /// </summary>
    /// <param name="cPoint">圆心坐标</param>
    /// <param name="onPoint">圆边上坐标</param>
    /// <param name="point">当前点</param>
    /// <returns></returns>
    public static bool 点是否在圆内(Vector2D cPoint, Vector2D onPoint, Vector2D point)
    {
    double cRadius = Distance(cPoint.Lat, cPoint.Lon, onPoint.Lat, onPoint.Lon);
    double distance = Distance(cPoint.Lat, cPoint.Lon, point.Lat, point.Lon);
    return distance <= cRadius;
    }

    /// <summary>
    /// 点是否在多边形内(在边上也认为在多边形内)
    /// </summary>
    /// <param name="point">当前点</param>
    /// <param name="polygon">多边形点</param>
    /// <returns></returns>
    public static bool 点是否在多边形内(Vector2D point, List<Vector2D> polygon)
    {
    var res = SMath.CalcPointPolygonRelation(point, polygon);
    return res != PointPolygonRelation.OutOfPolygon;
    }

    /// <summary>
    /// 点是否在矩形内
    /// </summary>
    /// <param name="pointA">对角上点A</param>
    /// <param name="pointB">对角上点B</param>
    /// <param name="point">当前点</param>
    /// <returns></returns>
    public static bool 点是否在矩形内(Vector2D pointA, Vector2D pointB, Vector2D point)
    {
    List<Vector2D> polygon = new List<Vector2D>();
    polygon.Add(pointA);
    polygon.Add(new Vector2D(pointA.X, pointB.Y));
    polygon.Add(pointB); 
    polygon.Add(new Vector2D(pointB.X, pointA.Y));
    var res = SMath.CalcPointPolygonRelation(point, polygon);
    return res != PointPolygonRelation.OutOfPolygon;
    }
    }

    ******************

    public static PointPolygonRelation CalcPointPolygonRelation(double x, double y, IList polygon)
    {
    if(polygon.Count < 3) return PointPolygonRelation.OutOfPolygon;
    IVector start = (IVector)polygon[polygon.Count - 2];
    if(start == null) return PointPolygonRelation.OutOfPolygon;
    IVector middle = (IVector)polygon[polygon.Count - 1];
    IVector end;
    PointPolygonRelation result = PointPolygonRelation.OutOfPolygon;
    int num = 0;
    double minX, minY, maxX, maxY;
    for(int i = 0; i < polygon.Count; i++, start = middle, middle = end)
    {
    end = (IVector)polygon[i];
    //如果点刚好在顶点上,则直接返回
    if((x == start.X && y == start.Y) || (x == middle.X && y == middle.Y) || (x == end.X && y == end.Y))
    {
    result = PointPolygonRelation.OnPolygonVertex;
    goto Return;
    }
    if(middle.X == end.X && middle.Y == end.Y)
    {
    continue;
    }
    minX = Math.Min(middle.X, end.X);
    maxX = Math.Max(middle.X, end.X);
    //如果X不落在最大X值和最小X值之间,则跳过
    if(x > maxX || x < minX) continue;

    minY = Math.Min(middle.Y, end.Y);
    maxY = Math.Max(middle.Y, end.Y);
    //如果Y大于最大Y值则跳过,因为向上做射线不可能相交
    if(y > maxY) continue;
    if(minX == maxX)//需要判断相交的线段为Y轴平行线
    {
    if(y > minY && y < maxY)
    {
    result = PointPolygonRelation.OnPolygonBorder;
    goto Return;
    }
    else if(y < minY)//如果在最小的Y之下,因为目标线段为Y轴平行线,所以记为1次
    {
    num++;
    }
    }
    else
    {
    double k = (middle.Y - end.Y) / (middle.X - end.X);
    double b = middle.Y - k * middle.X;

    double crossY = k * x + b;

    if(crossY < y) continue;//如果交点小于y则跳过,因为我们是向上做射线

    if(crossY == y)
    {
    result = PointPolygonRelation.OnPolygonBorder;
    goto Return;
    }

    if(x == maxX || x == minX)
    {
    if((start.X > middle.X && end.X < middle.X) || (start.X < middle.X && end.X > middle.X))
    num++;
    }
    else
    {
    num++;
    }
    }
    }

    if(num % 2 != 0) result = PointPolygonRelation.InPolygon;
    Return:

    return result;
    }

    /// <summary>
    /// 计算点和面的关系
    /// </summary>
    /// <param name="point"></param>
    /// <param name="polygon"></param>
    /// <returns></returns>
    public static PointPolygonRelation CalcPointPolygonRelation(IVector point, IList polygon)
    {
    return CalcPointPolygonRelation(point.X, point.Y, polygon);
    }

    _____________

    public enum PointPolygonRelation
    {
    /// <summary>
    /// 点在面内
    /// </summary>
    InPolygon,
    /// <summary>
    /// 点在边上
    /// </summary>
    OnPolygonBorder,
    /// <summary>
    /// 点在面外
    /// </summary>
    OutOfPolygon,
    /// <summary>
    /// 点在面的拐点上
    /// </summary>
    OnPolygonVertex
    }

  • 相关阅读:
    Leetcode Binary Tree Preorder Traversal
    Leetcode Minimum Depth of Binary Tree
    Leetcode 148. Sort List
    Leetcode 61. Rotate List
    Leetcode 86. Partition List
    Leetcode 21. Merge Two Sorted Lists
    Leetcode 143. Reorder List
    J2EE项目应用开发过程中的易错点
    JNDI初认识
    奔腾的代码
  • 原文地址:https://www.cnblogs.com/xiaoan-one/p/3736329.html
Copyright © 2011-2022 走看看