zoukankan      html  css  js  c++  java
  • 一种3D空间的柱状多边形检测实现

    最近无意中拓展出这个东西,基于之前写的2D多边形检测:

    http://www.cnblogs.com/hont/p/6105997.html

    而判断两条线相交的方法替换成了我后来写的差乘判断:

    http://www.cnblogs.com/hont/p/6106043.html

    应用还是比较广泛的,特别是多边形选区和地形处理上

    代码实现:

    using UnityEngine;
    
    public class Test : MonoBehaviour
    {
        public Transform testComparePoint;
        public Transform[] pointsArray;
        public float height = 4;
    
    
        public bool IsInRange(Vector3 comparePoint)
        {
            var localComparePoint = transform.worldToLocalMatrix.MultiplyPoint3x4(comparePoint);
    
            var flag = true;
            flag &= localComparePoint.y <= height;
            flag &= localComparePoint.y >= -height;
            flag &= IsConcaveContain2D(pointsArray, localComparePoint);
    
            if (flag)
                return true;
    
            return false;
        }
    
        public bool IsConcaveContain2D(Transform[] points, Vector3 compare)
        {
            const float VIRTUAL_RAYCAST_LEN = 100000;
    
            var comparePoint = (points[1].localPosition + points[0].localPosition) * 0.5f;
            var originPoint = compare;
            comparePoint += (comparePoint - originPoint).normalized * VIRTUAL_RAYCAST_LEN;
    
            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 = IsLineSegmentIntersection(a.localPosition, b.localPosition, originPoint, comparePoint);
    
                if (r) count++;
            }
    
            return count % 2 == 1;
        }
    
        public bool IsLineSegmentIntersection(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;
        }
    
        void OnDrawGizmos()
        {
            if (pointsArray == null) return;
    
            if (testComparePoint != null)
            {
                var comparePoint = testComparePoint.transform.position;
                if (IsInRange(comparePoint))
                {
                    Gizmos.color = Color.red;
                }
            }
    
            var cacheMatrix = Gizmos.matrix;
            Gizmos.matrix = transform.localToWorldMatrix;
    
            for (int i = 0; i < pointsArray.Length; i++)
            {
                var a = pointsArray[i];
                var b = pointsArray[(i + 1) % pointsArray.Length];
    
                if (a == null) continue;
                if (b == null) continue;
    
                var minA = a.localPosition;
                var minB = b.localPosition;
    
                var maxA = a.localPosition;
                var maxB = b.localPosition;
    
                minA.y = -height;
                minB.y = -height;
    
                maxA.y = height;
                maxB.y = height;
    
                Gizmos.DrawLine(minA, minB);
                Gizmos.DrawLine(maxA, maxB);
    
                Gizmos.DrawLine(minA, maxA);
                Gizmos.DrawLine(minB, maxB);
            }
    
            Gizmos.color = Color.clear;
    
            Gizmos.matrix = cacheMatrix;
        }
    }
  • 相关阅读:
    Windows 2003,XP安装Windows Phone 7 狼人:
    Android实例剖析笔记(六) 狼人:
    Android实例剖析笔记(一) 狼人:
    Android NDK带来什么 狼人:
    Windows Phone 7常用资源大集合 狼人:
    Android实例剖析笔记(七) 狼人:
    JDK环境变量配置
    jQuery去掉字符串起始和结尾的空格
    结构型设计模式
    主题:hibernate生成tree(基于注解方式)
  • 原文地址:https://www.cnblogs.com/hont/p/6915323.html
Copyright © 2011-2022 走看看