当前位置: 首页 > news >正文

2D空间中求一点是否在多边形内

参考自这篇博文:http://www.cnblogs.com/dabiaoge/p/4491540.html

 

一开始没仔细看做法,浪费了不少时间。下面是最终实现的效果:

 

大致流程:

1.随便选取多边形上任意一条边,以比较点和边的中心点做一条射线(这里用的伪射线)。

2.用这条射线与其他所有边判断是否相交。

3.将所有与线段相交的数量相加,如果是奇数就在多边形内。

 

特殊情况:

1.刚好在点上或者在线上。实际运用时会有点误差,但不影响。

2.必须是闭合线段,且不能存在包含的情况。但如果是一个数组生成的线段,不会有这种情况

 

代码(Unity3D):

using UnityEngine;
using System.Collections;

public class Test1 : MonoBehaviour
{
    const float RAYCAST_LEN = 100000f;
    public Transform[] points;
    public Transform compare;


    bool IsContract(Transform compare)
    {
        var comparePoint = (points[1].position + points[0].position) * 0.5f;
        var originPoint = compare.transform.position;
        comparePoint += (comparePoint - originPoint).normalized * RAYCAST_LEN;

        Debug.DrawLine(originPoint, comparePoint);

        int count = 0;
        for (int i = 0; i < points.Length; i++)
        {
            var a = points[i % points.Length];
            var b = points[(i + 1) % points.Length];

            var r = IsIntersection(a.position, b.position, originPoint, comparePoint);

            if (r) count++;
        }

        return count % 2 == 1;
    }

    void OnDrawGizmos()
    {
        if (compare == null) return;

        var oldColor = Gizmos.color;

        if (IsContract(compare))
            Gizmos.color = Color.red;

        for (int i = 0; i < points.Length; i++)
        {
            var a = points[i % points.Length];
            var b = points[(i + 1) % points.Length];

            Gizmos.DrawLine(a.position, b.position);
        }

        Gizmos.color = oldColor;
    }

    bool IsIntersection(Vector3 a, Vector3 b, Vector3 c, Vector3 d)
    {
        var crossA = Mathf.Sign(Vector3.Cross(d - c, a - c).y);
        var crossB = Mathf.Sign(Vector3.Cross(d - c, b - c).y);

        if (Mathf.Approximately(crossA, crossB)) return false;

        var crossC = Mathf.Sign(Vector3.Cross(b - a, c - a).y);
        var crossD = Mathf.Sign(Vector3.Cross(b - a, d - a).y);

        if (Mathf.Approximately(crossC, crossD)) return false;

        return true;
    }
}

 

 

另外参考的文章中没有说差乘判断两个线段是否相交的具体做法,这里说明一下

 

大致流程:

现在有线段AB和线段CB

用线段AB的方向和C,D两点分别做差乘比较。如果C,D在同侧则return跳出

用线段CD的方向和A,B两点分别做差乘比较。如果A,B在同侧则return跳出

最终返回相交

 

脚本就是上面的IsIntersection函数,最终实现效果(只适用于2D空间,如果是XY轴向要取差乘的z分量做比较):

相关文章:

  • ceph基础操作记录
  • zabbix企业应用之定时获取监控数据做报表
  • SQLSERVER之“sqlserver索引、视图、存储过程和触发器的使用”
  • 编译动态库与静态库的注意事项和方法
  • 《写给大忙人的hadoop2》读书笔记(一)大数据定义
  • Flume OG 与 Flume NG 的对比
  • Android:LinearLayout布局中Layout_weight的深刻理解
  • python 库集合
  • 建议Javascript以后都用严格模式
  • 表空间对空闲区的管理方式
  • RegExp
  • Java并发编程(五)Lock
  • 学技术怎可成为”快餐”?
  • KVM中镜像格式的选择
  • SQL server 添加字段问题
  • [译] 理解数组在 PHP 内部的实现(给PHP开发者的PHP源码-第四部分)
  • C++类的相互关联
  • CSS中外联样式表代表的含义
  • java8-模拟hadoop
  • JavaWeb(学习笔记二)
  • mac修复ab及siege安装
  • MySQL QA
  • python docx文档转html页面
  • seaborn 安装成功 + ImportError: DLL load failed: 找不到指定的模块 问题解决
  • 从零开始在ubuntu上搭建node开发环境
  • 番外篇1:在Windows环境下安装JDK
  • 使用Swoole加速Laravel(正式环境中)
  • 源码之下无秘密 ── 做最好的 Netty 源码分析教程
  • 国内唯一,阿里云入选全球区块链云服务报告,领先AWS、Google ...
  • ​软考-高级-系统架构设计师教程(清华第2版)【第15章 面向服务架构设计理论与实践(P527~554)-思维导图】​
  • #define
  • #我与Java虚拟机的故事#连载11: JVM学习之路
  • $$$$GB2312-80区位编码表$$$$
  • (delphi11最新学习资料) Object Pascal 学习笔记---第8章第5节(封闭类和Final方法)
  • (Oracle)SQL优化技巧(一):分页查询
  • (Redis使用系列) Springboot 实现Redis消息的订阅与分布 四
  • (附源码)spring boot网络空间安全实验教学示范中心网站 毕业设计 111454
  • (七)Java对象在Hibernate持久化层的状态
  • (十)【Jmeter】线程(Threads(Users))之jp@gc - Stepping Thread Group (deprecated)
  • (一)【Jmeter】JDK及Jmeter的安装部署及简单配置
  • (原創) 未来三学期想要修的课 (日記)
  • (转) Android中ViewStub组件使用
  • (转)mysql使用Navicat 导出和导入数据库
  • *Django中的Ajax 纯js的书写样式1
  • .net core 实现redis分片_基于 Redis 的分布式任务调度框架 earth-frost
  • .Net Core 中间件验签
  • .NET DevOps 接入指南 | 1. GitLab 安装
  • .Net Winform开发笔记(一)
  • .net 后台导出excel ,word
  • .NET企业级应用架构设计系列之开场白
  • .NET与java的MVC模式(2):struts2核心工作流程与原理
  • .sh 的运行
  • @RequestBody与@ModelAttribute
  • @RequestMapping处理请求异常
  • @Resource和@Autowired的区别