/// <summary>
        /// 擬似半平面の作成
        /// </summary>
        public ConvexPolygon Execute(Line line, Vector2 exsample)
        {
            //lineと各境界線の交差を調べる
            Vector2 p1 = Vector2.zero;
            bool    i1 = border1.GetIntersectionPoint(line, ref p1);
            Vector2 p2 = Vector2.zero;
            bool    i2 = border2.GetIntersectionPoint(line, ref p2);
            Vector2 p3 = Vector2.zero;
            bool    i3 = border3.GetIntersectionPoint(line, ref p3);

            List <Vector2> vertices = new List <Vector2>();

            //lineが境界線1及び2と交差する場合
            if (i1 && i2 && Vector2.Distance(p1, p2) >= distanceThreshold)
            {
                //lineが境界線1及び2と交差する場合
                if (GeomUtil.CCW(p1, boundary2, p2) * GeomUtil.CCW(p1, exsample, p2) > 0f)
                {
                    //境界線2とexsampleがlineから見て同じ側にあるなら
                    //境界点2を含む方の切断後頂点リストを生成
                    AddVertices(vertices, p1, boundary2, p2);
                }
                else
                {
                    //境界点2を含まない方の切断後頂点リストを生成
                    AddVertices(vertices, p1, p2, boundary3, boundary1);
                }
            }
            else if (i2 && i3 && Vector2.Distance(p2, p3) >= distanceThreshold)
            {
                //lineが境界線2及び3と交差する場合
                if (GeomUtil.CCW(p2, boundary3, p3) * GeomUtil.CCW(p2, exsample, p3) > 0f)
                {
                    AddVertices(vertices, p2, boundary3, p3);
                }
                else
                {
                    AddVertices(vertices, p2, p3, boundary1, boundary2);
                }
            }
            else if (i3 && i1 && Vector2.Distance(p3, p1) >= distanceThreshold)
            {
                //lineが境界線3及び1と交差する場合
                if (GeomUtil.CCW(p3, boundary1, p1) * GeomUtil.CCW(p3, exsample, p1) > 0f)
                {
                    AddVertices(vertices, p3, boundary1, p1);
                }
                else
                {
                    AddVertices(vertices, p3, p1, boundary2, boundary3);
                }
            }
            else
            {
                throw new ArgumentException();
            }

            //頂点リストから凸多角形を生成して返す
            return(new ConvexPolygon(vertices));
        }
Esempio n. 2
0
        /// <summary>
        /// 初期化
        /// </summary>
        private void Initialize(List <Vector2> points)
        {
            int size = points.Count;

            //角数が3未満の場合はエラー
            if (size < 3)
            {
                throw new ArgumentException();
            }
            this.vertices = points;

            //凸性判定
            float baseCCW = 0f;

            for (int i = 0; i < size; ++i)
            {
                Vector2 p0 = points[i];
                Vector2 p1 = points[(i + 1) % size];
                Vector2 p2 = points[(i + 2) % size];

                //CCW値の計算
                float ccw = GeomUtil.CCW(p0, p1, p2);
                if (baseCCW == 0f && ccw != 0f)
                {
                    baseCCW = ccw;
                }
                if (ccw * baseCCW < 0)
                {
                    throw new ArgumentException("Polygon is not convex.");
                }
            }
            if (baseCCW > 0f)
            {
                rotation = Rotation.CCW;
            }
            else
            {
                rotation = Rotation.CW;
            }

            //線分の登録
            edges = new List <LineSegment>();
            for (int i = 0; i < size; ++i)
            {
                Vector2 p1 = points[i];
                Vector2 p2 = points[(i + 1) % size];                 //p1の次の頂点

                //2つ頂点から辺の線分を作成して登録
                edges.Add(new LineSegment(p1, p2));
            }
        }
Esempio n. 3
0
        /// <summary>
        /// 初期化
        /// </summary>
        private void Initialize(List <Vector2> points)
        {
            int size = points.Count;

            //角数が3未満の場合はエラー
            if (size < 3)
            {
                throw new ArgumentException();
            }

            //最も遠い座標のインデックスを求める
            int   index       = 0;
            float maxDistance = 0f;
            float distance    = 0f;

            for (int i = 0; i < size; ++i)
            {
                distance = points[i].magnitude;
                if (distance > maxDistance)
                {
                    maxDistance = distance;
                    index       = i;
                }
            }
            mostFarIndex = index;

            //最も遠い座標の外積を求める
            Vector2 p0 = points[(index + (size - 1)) % size];
            Vector2 p1 = points[index];
            Vector2 p2 = points[(index + 1) % size];

            mostFarCross = GeomUtil.CCW(p0, p1, p2);

            //頂点リストの作成
            vertices = new List <PolygonVertex>();
            for (int i = 0; i < size; ++i)
            {
                p0 = points[(i + (size - 1)) % size];
                p1 = points[i];
                p2 = points[(i + 1) % size];

                float cross = GeomUtil.CCW(p0, p1, p2);
                float angle = GeomUtil.TwoVectorAngle(p1, p0, p2);
                if (cross * mostFarCross < 0f)
                {
                    angle = 360f - angle;
                }
                vertices.Add(new PolygonVertex(p1, angle, i));
            }
        }
Esempio n. 4
0
    private void UpdateLine()
    {
        if (line == null)
        {
            return;
        }

        int size = vertices.Count;

        if (size < 3)
        {
            return;
        }

        line.SetVertexCount(vertices.Count + 1);

        float baseCCW   = GeomUtil.CCW(vertices [0].position, vertices [1].position, vertices [2].position);
        bool  notConvex = false;

        for (int i = 0; i < size; ++i)
        {
            line.SetPosition(i, vertices [i].position);

            //凸性判定
            Vector2 p1  = vertices [i].position;
            Vector2 p2  = vertices [(i + 1) % size].position;
            Vector2 p3  = vertices [(i + 2) % size].position;
            float   ccw = GeomUtil.CCW(p1, p2, p3);
            if (baseCCW * ccw <= 0)
            {
                notConvex = true;
            }
        }
        line.SetPosition(size, vertices [0].position);

        if (notConvex)
        {
            line.SetColors(Color.red, Color.red);
        }
        else
        {
            line.SetColors(Color.white, Color.white);
        }
    }
Esempio n. 5
0
    private void Update()
    {
        float ccw = GeomUtil.CCW(p1.position, p2.position, p3.position);

        //Line Color
        Color c = Color.white;

        if (ccw < 0)
        {
            c = Color.blue;
        }
        else if (ccw > 0)
        {
            c = Color.red;
        }
        line.SetColors(c, c);

        //Draw Line
        line.SetVertexCount(3);
        line.SetPosition(0, p1.position);
        line.SetPosition(1, p2.position);
        line.SetPosition(2, p3.position);
    }
Esempio n. 6
0
        /// <summary>
        /// 簡易メッシュ変換
        /// </summary>
        public EasyMesh ToEasyMesh(Color color)
        {
            int size = vertices.Count;

            Vector3[] verts   = new Vector3[size];
            Color[]   colors  = new Color[size];
            int[]     indices = new int[(size - 2) * 3];

            //一時データと準備
            List <PolygonVertex> temp = new List <PolygonVertex>();

            for (int i = 0; i < size; ++i)
            {
                temp.Add(new PolygonVertex(vertices[i]));
                verts[i]  = vertices[i].point;
                colors[i] = color;
            }

            //頂点処理ループ
            int     index = mostFarIndex;
            int     indicesCount = 0;
            Vector2 p0, p1, p2;
            int     i0, i1, i2;
            int     processNum    = 0;
            int     maxProcessNum = temp.Count * 2;

            while (temp.Count > 3 && processNum < maxProcessNum)
            {
                size = temp.Count;

                i0 = (index + size - 1) % size;
                p0 = temp[i0].point;
                i1 = index;
                p1 = temp[i1].point;
                i2 = (index + 1) % size;
                p2 = temp[i2].point;

                //外積の向きを調べる
                float cross = GeomUtil.CCW(p0, p1, p2);
                if (cross * mostFarCross >= 0f)
                {
                    //三角形の中に他の頂点が混じってないか確認
                    bool contains = false;
                    for (int i = 2; i < size - 1; ++i)
                    {
                        int j = (index + i) % size;

                        if (GeomUtil.TriangleInPoint(p0, p1, p2, temp[j].point))
                        {
                            contains = true;
                            break;
                        }
                    }
                    //インデックスの追加
                    if (!contains)
                    {
                        //回転方向によってポリゴンの順序が反転する
                        if (mostFarCross > 0f)
                        {
                            indices[indicesCount + 0] = temp[i0].index;
                            indices[indicesCount + 1] = temp[i2].index;
                            indices[indicesCount + 2] = temp[i1].index;
                        }
                        else
                        {
                            indices[indicesCount + 0] = temp[i0].index;
                            indices[indicesCount + 1] = temp[i1].index;
                            indices[indicesCount + 2] = temp[i2].index;
                        }
                        indicesCount += 3;
                        temp.RemoveAt(i1);
                        size--;
                    }
                }

                index = (index + 1) % size;
                ++processNum;
            }

            if (processNum >= maxProcessNum)
            {
                throw new ArgumentException("Not Create Mesh.");
            }

            //最後の3点を加える
            indices[indicesCount + 0] = temp[0].index;
            indices[indicesCount + 1] = temp[2].index;
            indices[indicesCount + 2] = temp[1].index;

            return(new EasyMesh(verts, colors, indices));
        }
Esempio n. 7
0
        /// <summary>
        /// 簡易メッシュ変換コルーチン
        /// </summary>
        public IEnumerator CoToEasyMesh(Color color, Action <EasyMesh> updateCallback, Action <EasyMesh> endCallback = null, float wait = 0.1f)
        {
            int size = vertices.Count;

            Vector3[] verts   = new Vector3[size];
            Color[]   colors  = new Color[size];
            int[]     indices = new int[(size - 2) * 3];

            //一時データと準備
            List <PolygonVertex> temp = new List <PolygonVertex>();

            for (int i = 0; i < size; ++i)
            {
                temp.Add(new PolygonVertex(vertices[i]));
                verts[i]  = vertices[i].point;
                colors[i] = color;
            }

            //頂点処理ループ
            int     index = mostFarIndex;
            int     indicesCount = 0;
            Vector2 p0, p1, p2;
            int     i0, i1, i2;
            int     processNum    = 0;
            int     maxProcessNum = temp.Count * 2;

            while (temp.Count > 3 && processNum < maxProcessNum)
            {
                size = temp.Count;

                i0 = (index + size - 1) % size;
                p0 = temp[i0].point;
                i1 = index;
                p1 = temp[i1].point;
                i2 = (index + 1) % size;
                p2 = temp[i2].point;

                //外積の向きを調べる
                float cross = GeomUtil.CCW(p0, p1, p2);
                if (cross * mostFarCross >= 0f)
                {
                    //三角形の中に他の頂点が混じってないか確認
                    bool contains = false;
                    for (int i = 2; i < size - 1; ++i)
                    {
                        int j = (index + i) % size;

                        if (GeomUtil.TriangleInPoint(p0, p1, p2, temp[j].point))
                        {
                            contains = true;
                            break;
                        }
                    }
                    //インデックスの追加
                    if (!contains)
                    {
                        indices[indicesCount + 0] = temp[i0].index;
                        indices[indicesCount + 1] = temp[i1].index;
                        indices[indicesCount + 2] = temp[i2].index;
                        indicesCount += 3;
                        temp.RemoveAt(i1);
                        size--;

                        yield return(new WaitForSeconds(wait));

                        //コールバック
                        if (updateCallback != null)
                        {
                            updateCallback(new EasyMesh(verts, colors, indices));
                        }
                    }
                }

                index = (index + 1) % size;
                ++processNum;
            }

            if (processNum >= maxProcessNum)
            {
                throw new ArgumentException("Not create mesh");
            }

            //最後の3点を加える
            indices[indicesCount + 0] = temp[0].index;
            indices[indicesCount + 1] = temp[1].index;
            indices[indicesCount + 2] = temp[2].index;

            yield return(new WaitForSeconds(wait));

            //コールバック
            if (endCallback != null)
            {
                endCallback(new EasyMesh(verts, colors, indices));
            }
        }