• 判断点是否在一个任意多边形中


    using UnityEngine;
    using System.Collections.Generic;

    public class JudgePoint : MonoBehaviour
    {

    //多边形A 所有顶点
    private float[,] dingdian = new float[4, 3] { { 6, 4, 0 }, { 3, 1, 0 }, { 2, 2, 0 }, { 3, 5, 0 } };
    //P点 不确定是否在多边形内
    private float[,] P = new float[1, 3] { { 3, 2, 0 } };
    //O点 目标点
    private float[,] O = new float[1, 3] { { 7, 10, 0 } };
    //测试 不规则四边形 第一象限
    private float[,] bianbian = new float[4, 3] { { 8, 0, 8 }, { 2, 2, 0 }, { 0, 5, 0 }, { 4, 8, 0 } };
    private float[,] dian1 = new float[1, 3] { { 5, 8, 0 } };//坐标系中不在多边形内 unity测试 不在多边形内
    private float[,] dian2 = new float[1, 3] { { 5, 2, 0 } };//坐标系中 在多边形内 unity测试 在多边形内
    //测试 不规则五边形 410 260 480 770 830 第一象限
    private float[,] bianFive = new float[5, 3] { { 4, 1, 0 }, { 2, 6, 0 }, { 4, 8, 0 }, { 7, 7, 0 }, { 8, 3, 0 } };
    private float[,] dian3 = new float[1, 3] { { 2, 3, 0 } };//坐标系中 不在 unity测试 不在
    private float[,] dian4 = new float[1, 3] { { 6, 3, 0 } };//坐标系中 在 unity测试 在
    //7,8 不在 4,7在
    //测试 多边形 不在第一象限内 180 650 520 -1-10 -820 -460
    private float[,] bianSix = new float[6, 3] { { 1, 8, 0 }, { 6, 5, 0 }, { 5, 2, 0 }, { -1, -1, 0 }, { -8, 2, 0 }, { -4, 6, 0 } };
    private float[,] dian7 = new float[1, 3] { { 5, 1, 0 } }; //坐标系 不在 unity不在
    private float[,] dian8 = new float[1, 3] { { -4, -2, 0 } };//坐标系 不在 unity不在
    private float[,] dian9 = new float[1, 3] { { 4, 5, 0 } }; //坐标系 在 unity在
    //10000次 测试 不规则六边形 31毫秒
    //10000次 测试 不规则四边形 15-16毫秒

    //算法一:凹多边形测试 500 070 440 880 算法一 无法计算 凹多边形
    private float[,] bianAo = new float[4, 3] { { 5, 0, 0 }, { 0, 7, 0 }, { 4, 4, 0 }, { 8, 8, 8 } };
    private float[,] dian10 = new float[1, 3] { { 4, 5, 0 } }; //坐标系 不在 unity 不在
    private float[,] dian11 = new float[1, 3] { { 5, 4, 0 } };//坐标系 在 unity 不在
    //算法二:凹多边形测试 成功 10000次 凹四边形 15-16毫秒
    //算法二测试:凹六边形 380 450 870 700 220 060 +判断点是否在边上
    private float[,] bianAoSix = new float[6, 3] { { 3, 8, 0 }, { 4, 5, 0 }, { 8, 7, 0 }, { 6, 2, 0 }, { 2, 2, 0 }, { 0, 6, 0 } };
    private float[,] dian12 = new float[1, 3] { { 8, 1, 0 } }; // 坐标系 不在 2 :0
    private float[,] dian13 = new float[1, 3] { { 5, 6, 0 } };//坐标系 不在 3:2
    private float[,] dian14 = new float[1, 3] { { 6, 1, 0 } };//坐标系 在 1 : 1
    private float[,] dian15 = new float[1, 3] { { 3, 6, 0 } };//坐标系 在 2:3
    //继续测试
    private float[,] dian16 = new float[1, 3] { { 1, 2, 0 } };//坐标系 不在 0: 3
    private float[,] dian17 = new float[1, 3] { { 3, 1, 0 } };//坐标系 不在 0: 2
    private float[,] dian18 = new float[1, 3] { { 4, 8, 0 } };//不在 2: 0
    private float[,] dian19 = new float[1, 3] { { 4, 7, 0 } };//不在 2: 2

    //总结 算法一:适合任何凸多边形 任何象限 10000次 四边形 15-16毫秒
    // 算法二:适合任何凹多边形 任何象限 10000次 四边形 0-15-16毫秒
    // 算法二:加上判断点是否在边上 任何象限 10000次 六边形 15-16毫秒

    private float[,] dian20 = new float[1, 3] { { 4, 4, 0 } };


    void Start()
    {
    //ForJudgePoint(dingdian, P);
    //ForJudgePoint(bianbian, dian);
    //ForJudgePoint(bianFive, dian3);
    //ForJudgePoint(bianFive, dian4);
    //ForJudgePoint(bianSix, dian7);
    //ForJudgePoint(bianSix, dian8);
    //ForJudgePoint(bianSix, dian9);
    float time = System.Environment.TickCount; //计时器
    //for (int i = 0; i < 10000; i++)
    //{
    // ForJudgePoint(bianbian, dian2);
    //}

    // Debug.Log(Vector3.Angle(v1, v2));
    //ForJudgePoint(bianAo, dian10);
    //ForJudgePoint(bianAo, dian11);
    //SecondJudge(bianAo, dian11);
    for (int i = 0; i < 10000; i++)
    {
    SecondJudge(bianAo, dian10);
    }
    Debug.Log("times:" + (System.Environment.TickCount - time)); //计时器
    //ForJudgePoint(bianSix, dian7);
    //SecondJudge(bianSix, dian7);
    //ForJudgePoint(bianSix, dian9);
    //SecondJudge(bianSix, dian9);
    //SecondJudge(bianAoSix, dian12);
    //SecondJudge(bianAoSix, dian13);
    //SecondJudge(bianAoSix, dian14);
    //SecondJudge(bianAoSix, dian15);
    //SecondJudge(bianAoSix, dian16);
    //SecondJudge(bianAoSix, dian17);
    //SecondJudge(bianAoSix, dian18);
    //SecondJudge(bianAoSix, dian19);
    //SecondJudge(bianAoSix, dian20);

    }
    //算法二 凹多边形
    public void SecondJudge(float[,] dingdian, float[,] point)
    {
    int bianShu = dingdian.Length / 3;
    //bool isOnLine = JudPointOnLine(dingdian, point, bianShu);
    //if (isOnLine == true) { Debug.Log("该点在多边形边上"); return; }
    List<int> listLeft = new List<int>();
    List<int> listRight = new List<int>();
    float y = point[0, 1];
    float x = point[0, 0];
    bool isEqu = false;
    float bianX = 0;
    for (int i = 0; i < bianShu; i++)
    {
    if (dingdian[i, 1] == y)
    {
    isEqu = true;
    bianX = dingdian[i, 0];
    if (dingdian[i, 0] > x)
    {
    listRight.Add(i);
    listRight.Add(i);
    }
    else
    {
    listLeft.Add(i);
    listLeft.Add(i);
    }
    }
    }
    for (int i = 0; i < bianShu; i++)
    {
    if (i < bianShu - 1)
    {
    if (dingdian[i, 1] < y && y < dingdian[i + 1, 1])
    {
    if (dingdian[i, 0] <= x && dingdian[i + 1, 0] <= x)
    {
    listLeft.Add(i);
    }
    else if (dingdian[i, 0] >= x && dingdian[i + 1, 0] >= x)
    {
    listRight.Add(i);
    }
    else
    {
    float midX = (dingdian[i, 0] + dingdian[i + 1, 0]) / 2;
    if (x > midX)
    {
    listLeft.Add(i);
    }
    else
    {
    listRight.Add(i);
    }
    }
    }
    }
    else
    {
    if (dingdian[i, 1] < y && y < dingdian[0, 1])
    {
    if (dingdian[i, 0] <= x && dingdian[0, 0] <= x)
    {
    listLeft.Add(i);
    }
    else if (dingdian[i, 0] >= x && dingdian[0, 0] >= x)
    {
    listRight.Add(i);
    }
    else
    {
    float midX = (dingdian[i, 0] + dingdian[0, 0]) / 2;
    if (midX < x)
    {
    listLeft.Add(i);
    }
    else
    {
    listRight.Add(i);
    }
    }
    }
    }
    }
    for (int i = 0; i < bianShu; i++)
    {
    if (i < bianShu - 1)
    {
    if (dingdian[i, 1] > y && y > dingdian[i + 1, 1])
    {
    if (dingdian[i, 0] <= x && dingdian[i + 1, 0] <= x)
    {
    listLeft.Add(i);
    }
    else if (dingdian[i, 0] >= x && dingdian[i + 1, 0] >= x)
    {
    listRight.Add(i);
    }
    else
    {
    float midX = (dingdian[i, 0] + dingdian[i + 1, 0]) / 2;
    if (midX < x)
    {
    listLeft.Add(i);
    }
    else
    {
    listRight.Add(i);
    }
    }
    }
    }
    else
    {
    if (dingdian[i, 1] > y && y > dingdian[0, 1])
    {
    if (dingdian[i, 0] <= x && dingdian[0, 0] <= x)
    {
    listLeft.Add(i);
    }
    else if (dingdian[i, 0] >= x && dingdian[0, 0] >= x)
    {
    listRight.Add(i);
    }
    else
    {
    float midX = (dingdian[i, 0] + dingdian[0, 0]) / 2;
    if (midX < x)
    {
    listLeft.Add(i);
    }
    else
    {
    listRight.Add(i);
    }
    }
    }
    }
    }
    //Debug.Log(listLeft.Count + " " + listRight.Count);
    if (isEqu == false)
    {
    if (listLeft.Count % 2 == 0 || listRight.Count % 2 == 0)
    {
    //Debug.Log("==不在== 多边形内");
    }
    else
    {
    //Debug.Log("==在== 多边形内");
    }
    }
    else
    {
    if ((bianX > x && listLeft.Count % 2 == 0) || (bianX < x && listRight.Count % 2 == 0))
    {
    //Debug.Log("=不在= 多边形内");
    }
    else
    {
    //Debug.Log("=在= 多边形内");
    }
    }


    }


    //判断点是否在多边形边上
    public bool JudPointOnLine(float[,] dingdian, float[,] point, int bianshu)
    {

    for (int i = 0; i < bianshu - 1; i++)
    {
    //先判断是否在 边所在的直线上
    if ((dingdian[i, 0] - point[0, 0]) * (dingdian[i + 1, 1] - point[0, 1]) - (dingdian[i + 1, 0] - point[0, 0]) * (dingdian[i, 1] - point[0, 1]) == 0)
    {
    //判断X值 与2个点X的值
    if ((point[0, 0] > dingdian[i, 0] && point[0, 0] > dingdian[i + 1, 0]) || (point[0, 0] < dingdian[i, 0] && point[0, 0] < dingdian[i + 1, 0]))
    {
    return false;
    }
    else
    {
    return true;
    }
    }
    }
    //最后一边
    if ((dingdian[bianshu - 1, 0] - point[0, 0]) * (dingdian[0, 1] - point[0, 1]) - (dingdian[0, 0] - point[0, 0]) * (dingdian[bianshu - 1, 1] - point[0, 1]) == 0)
    {
    //判断X值 与2个点X的值
    if ((point[0, 0] > dingdian[bianshu - 1, 0] && point[0, 0] > dingdian[0, 0]) || (point[0, 0] < dingdian[bianshu - 1, 0] && point[0, 0] < dingdian[0, 0]))
    {
    return false;
    }
    else
    {
    return true;
    }
    }

    return false;

    }

    //算法一
    public void ForJudgePoint(float[,] dingdian, float[,] point)
    {
    int bianShu = dingdian.Length / 3;//三维向量 除以3 = 多边形边数
    float[] results = new float[bianShu];
    for (int i = 0; i < dingdian.Length / 3 - 1; i++)
    {
    //判断 多边形 第一个顶点到最后一个顶点 一共边数-1 条边(还剩最后顶点 到 第一个顶点 这条边)
    //多边形 第一条边 的向量
    float[,] polygonSide = { { dingdian[i, 0] - dingdian[i + 1, 0], dingdian[i, 1] - dingdian[i + 1, 1], dingdian[i, 2] - dingdian[i + 1, 2] } };
    //多边形 第一条边向量的起始点 到 点point 的向量
    float[,] pointToSide = { { dingdian[i, 0] - point[0, 0], dingdian[i, 1] - point[0, 1], dingdian[i, 2] - point[0, 2] } };
    //二维向量叉乘 Z分量 = x1*y2-x2*y1
    float res = polygonSide[0, 0] * pointToSide[0, 1] - pointToSide[0, 0] * polygonSide[0, 1];
    res = res > 0 ? res = 1 : res = -1;
    results[i] = res;
    if (i >= 1)
    {
    if (results[i] != results[i - 1])
    {
    Debug.Log("点P ==不在== 多边形中!!!");
    return;
    }
    }
    }
    //最后一条边
    float[,] polygonLastSide = { { dingdian[bianShu - 1, 0] - dingdian[0, 0], dingdian[bianShu - 1, 1] - dingdian[0, 1], dingdian[bianShu - 1, 2] - dingdian[0, 2] } };
    float[,] pointToLastSide = { { dingdian[bianShu - 1, 0] - point[0, 0], dingdian[bianShu - 1, 1] - point[0, 1], dingdian[bianShu - 1, 2] - point[0, 2] } };
    float resLast = polygonLastSide[0, 0] * pointToLastSide[0, 1] - pointToLastSide[0, 0] * polygonLastSide[0, 1];
    resLast = resLast > 0 ? resLast = 1 : resLast = -1;
    if (resLast != results[0])
    {
    Debug.Log("点P ==不在== 多边形中!!!");
    }
    else
    {
    Debug.Log("点P ==在== 多边形中!!!");
    }
    }
    }

  • 相关阅读:
    Django缓存大总结
    Django之视图 ListView
    Django中间件之加载分析
    Django启动过程之超级详细分析
    Django中间件
    RabbitMq与Celery应用示意图
    爬虫的基本原理
    RestFramework的过滤组件 和 分页组件
    python注释、输入格式化输出输出及数据类型
    编程语言的发展历史及python的初了解
  • 原文地址:https://www.cnblogs.com/cocotang/p/5809493.html
Copyright © 2020-2023  润新知