C#:判断点是否在多边形内

原理:

奇偶规则射线法:多边形内任意一点,向任意方向射线,相交数必然为奇数。

接着我们就可以利用线段到线段的相交数,求出想要的结果。

cs 复制代码
using System.Collections.Generic;
using System;
using UnityEngine;
using System.Drawing;



public class TestTools : MonoBehaviour
{

    public List<Transform> tranPos = new List<Transform>();

    // Start is called once before the first execution of Update after the MonoBehaviour is created
    void Start()
    {
      
    }


    Point GetNode(Transform _t)
    {
        var _nod = new Point(_t.position.x, _t.position.z);
        return _nod;
    }

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.A)) IsIn();
    }





    void IsIn()
    {
        var polygon = new List<Point>();
        polygon.Add(GetNode(tranPos[0]));
        polygon.Add(GetNode(tranPos[1]));
        polygon.Add(GetNode(tranPos[2]));
        polygon.Add(GetNode(tranPos[3]));


        Point point = GetNode(tranPos[4]);
        Point _pEnd = new Point(100,point.Y) ;

        int _num = 0;//相交数量
        for (var _i = 0; _i < polygon.Count; _i++)
        {
            var _p1 = polygon[_i];
            Point _p2 = polygon[0];
            if (_i < polygon.Count - 1) _p2 = polygon[_i + 1];

            Debug.Log("~~~~~~~~!!!");
            Debug.Log(_p1.X + "   " + _p1.Y + "   " + _p2.X + "   " + _p2.Y);

            var intersect = AreSegmentsIntersecting(point, _pEnd, _p1, _p2);
            Debug.Log(intersect);
            if (intersect) _num++;
        }
        Debug.LogError("相交数" + _num);
        var _get = _num % 2 != 0;
        Debug.Log(_get ? "在多边形内" : "不在多边形内");

    }

    // 定义点结构
    public struct Point
    {
        public double X, Y;

        public Point(double x, double y)
        {
            X = x;
            Y = y;
        }
    }

    // 计算两个向量的叉积 (P2 - P1) × (P3 - P1)
    private static double CrossProduct(Point p1, Point p2, Point p3)
    {
        return (p2.X - p1.X) * (p3.Y - p1.Y) - (p2.Y - p1.Y) * (p3.X - p1.X);
    }

    // 判断点p是否在a和b之间(用于共线情况下判断是否有重叠)
    private static bool IsPointOnSegment(Point p, Point a, Point b)
    {
        return Math.Min(a.X, b.X) <= p.X && p.X <= Math.Max(a.X, b.X) &&
               Math.Min(a.Y, b.Y) <= p.Y && p.Y <= Math.Max(a.Y, b.Y);
    }

    // 判断两条线段 (p1, p2) 和 (p3, p4) 是否相交
    public static bool AreSegmentsIntersecting(Point p1, Point p2, Point p3, Point p4)
    {
        double d1 = CrossProduct(p3, p4, p1);
        double d2 = CrossProduct(p3, p4, p2);
        double d3 = CrossProduct(p1, p2, p3);
        double d4 = CrossProduct(p1, p2, p4);

        // 检查叉积是否满足线段相交条件
        if (d1 * d2 < 0 && d3 * d4 < 0)
        {
            return true;
        }

        // 检查是否共线且重叠
        if (d1 == 0 && IsPointOnSegment(p1, p3, p4)) return true;
        if (d2 == 0 && IsPointOnSegment(p2, p3, p4)) return true;
        if (d3 == 0 && IsPointOnSegment(p3, p1, p2)) return true;
        if (d4 == 0 && IsPointOnSegment(p4, p1, p2)) return true;

        return false;
    }

    public static void Main()
    {
        Point p1 = new Point(0, 0);
        Point p2 = new Point(2, 2);
        Point p3 = new Point(0, 2);
        Point p4 = new Point(2, 0);

        bool intersecting = AreSegmentsIntersecting(p1, p2, p3, p4);
        Console.WriteLine("Are the segments intersecting? " + (intersecting ? "Yes" : "No"));
    }


}

简化函数为:

cs 复制代码
 public bool IsInPolygon(Point _p, List<Point> _polygon)
 {
     // 计算两个向量的叉积 (P2 - P1) × (P3 - P1)
     double CrossProduct(Point p1, Point p2, Point p3)
     {
         return (p2.X - p1.X) * (p3.Y - p1.Y) - (p2.Y - p1.Y) * (p3.X - p1.X);
     }

     // 判断点p是否在a和b之间(用于共线情况下判断是否有重叠)
    bool IsPointOnSegment(Point p, Point a, Point b)
     {
         return Math.Min(a.X, b.X) <= p.X && p.X <= Math.Max(a.X, b.X) &&
                Math.Min(a.Y, b.Y) <= p.Y && p.Y <= Math.Max(a.Y, b.Y);
     }

     // 判断两条线段 (p1, p2) 和 (p3, p4) 是否相交
     bool AreSegmentsIntersecting(Point p1, Point p2, Point p3, Point p4)
     {
         double d1 = CrossProduct(p3, p4, p1);
         double d2 = CrossProduct(p3, p4, p2);
         double d3 = CrossProduct(p1, p2, p3);
         double d4 = CrossProduct(p1, p2, p4);

         // 检查叉积是否满足线段相交条件
         if (d1 * d2 < 0 && d3 * d4 < 0)
         {
             return true;
         }

         // 检查是否共线且重叠
         if (d1 == 0 && IsPointOnSegment(p1, p3, p4)) return true;
         if (d2 == 0 && IsPointOnSegment(p2, p3, p4)) return true;
         if (d3 == 0 && IsPointOnSegment(p3, p1, p2)) return true;
         if (d4 == 0 && IsPointOnSegment(p4, p1, p2)) return true;

         return false;
     }

     Point _pEnd = new Point(float.MaxValue, _p.Y);

     int _num = 0;//相交数量
     for (var _i = 0; _i < _polygon.Count; _i++)
     {
         var _p1 = _polygon[_i];
         Point _p2 = _polygon[0];
         if (_i < _polygon.Count - 1) _p2 = _polygon[_i + 1];

         Debug.Log("~~~~~~~~!!!");
         Debug.Log(_p1.X + "   " + _p1.Y + "   " + _p2.X + "   " + _p2.Y);

         var intersect = AreSegmentsIntersecting(_p, _pEnd, _p1, _p2);
         Debug.Log(intersect);
         if (intersect) _num++;
     }
     Debug.LogError("相交数" + _num);
     var _get = _num % 2 != 0;
     Debug.Log(_get ? "在多边形内" : "不在多边形内");
     return _get;


 }


 // 定义点结构
 public struct Point
 {
     public double X, Y;

     public Point(double x, double y)
     {
         X = x;
         Y = y;
     }
 }

除了顶点照顾不到,基本也够用了。

相关推荐
weixin_3077791310 分钟前
在Linux服务器上使用Jenkins和Poetry实现Python项目自动化
linux·开发语言·python·自动化·jenkins
润 下10 分钟前
C语言——深入解析C语言指针:从基础到实践从入门到精通(四)
c语言·开发语言·人工智能·经验分享·笔记·程序人生·其他
Empty_77714 分钟前
Python编程之常用模块
开发语言·网络·python
小火柴12318 分钟前
利用R绘制箱线图
开发语言·r语言
wheeldown28 分钟前
【Linux】Linux 进程通信:System V 共享内存(最快方案)C++ 封装实战 + 通信案例,4 类经典 Bug 快速修复
linux·运维·服务器·开发语言
小年糕是糕手38 分钟前
【数据结构】双向链表“0”基础知识讲解 + 实战演练
c语言·开发语言·数据结构·c++·学习·算法·链表
将车24443 分钟前
C++实现二叉树搜索树
开发语言·数据结构·c++·笔记·学习
梵得儿SHI1 小时前
Java 反射机制核心类详解:Class、Constructor、Method、Field
java·开发语言·反射·class·constructor·java反射·java反射机制
hbqjzx1 小时前
记录一个自动学习的脚本开发过程
开发语言·javascript·学习
Sirens.2 小时前
Java核心概念:抽象类、接口、Object类深度剖析
java·开发语言·github