示例#1
1
        private List<Poly2Tri.DelaunayTriangle> GetTriangleListFromClipperSolution(ClipperLib.PolyTree solution)
        {
            Func<ClipperLib.IntPoint, Poly2Tri.PolygonPoint> xfToPolygonPoint = (p) => new Poly2Tri.PolygonPoint(p.X, p.Y);
            Poly2Tri.PolygonSet polygonSet = new Poly2Tri.PolygonSet();

            ClipperLib.PolyNode node = solution.GetFirst();
            while (node != null)
            {
                // Only interested in closed paths
                if (!node.IsOpen)
                {
                    if (node.IsHole)
                    {
                        if (polygonSet.Polygons.Count() > 0)
                        {
                            // Add hole to last polygon entered
                            var polyPoints = node.Contour.Select(xfToPolygonPoint).ToArray();
                            Poly2Tri.Polygon hole = new Poly2Tri.Polygon(polyPoints);

                            Poly2Tri.Polygon polygon = polygonSet.Polygons.Last();
                            polygon.AddHole(hole);
                        }
                    }
                    else
                    {
                        // Add a new polygon to the set
                        var polyPoints = node.Contour.Select(xfToPolygonPoint).ToList();
                        Poly2Tri.Polygon polygon = new Poly2Tri.Polygon(polyPoints);
                        polygonSet.Add(polygon);
                    }
                }
                node = node.GetNext();
            }

            // Now triangulate the whole set
            Poly2Tri.P2T.Triangulate(polygonSet);

            // Combine all the triangles into one list
            List<Poly2Tri.DelaunayTriangle> triangles = new List<Poly2Tri.DelaunayTriangle>();
            foreach (var polygon in polygonSet.Polygons)
            {
                triangles.AddRange(polygon.Triangles);
            }

            return triangles;
        }
示例#2
0
        static GlyphFitOutline TessWithPolyTri(List <GlyphContour> contours)
        {
            List <Poly2Tri.TriangulationPoint> points = new List <Poly2Tri.TriangulationPoint>();
            int          cntCount = contours.Count;
            GlyphContour cnt      = contours[0];

            Poly2Tri.Polygon polygon  = CreatePolygon2(contours[0]);//first contour
            bool             isHoleIf = !cnt.IsClockwise;

            //if (cntCount > 0)
            //{
            //    //debug only
            for (int n = 1; n < cntCount; ++n)
            {
                cnt = contours[n];
                //IsHole is correct after we Analyze() the glyph contour
                polygon.AddHole(CreatePolygon2(cnt));
                //if (cnt.IsClockwise == isHoleIf)
                //{
                //     polygon.AddHole(CreatePolygon2(cnt));
                //}
                //else
                //{
                //    //eg i
                //    //the is a complete separate dot  (i head) over i body
                //}
            }
            //}

            //------------------------------------------
            Poly2Tri.P2T.Triangulate(polygon); //that poly is triangulated
            GlyphFitOutline glyphFitOutline = new GlyphFitOutline(polygon, contours);

            glyphFitOutline.Analyze();
            //------------------------------------------
#if DEBUG
            List <GlyphTriangle> triAngles = glyphFitOutline.dbugGetTriangles();
            int triangleCount = triAngles.Count;

            for (int i = 0; i < triangleCount; ++i)
            {
                //---------------
                GlyphTriangle tri = triAngles[i];
                AssignPointEdgeInvolvement(tri.e0);
                AssignPointEdgeInvolvement(tri.e1);
                AssignPointEdgeInvolvement(tri.e2);
            }
#endif
            return(glyphFitOutline);
        }
示例#3
0
        private List <Poly2Tri.DelaunayTriangle> GetTriangleListFromClipperSolution(ClipperLib.PolyTree solution)
        {
            Func <ClipperLib.IntPoint, Poly2Tri.PolygonPoint> xfToPolygonPoint = (p) => new Poly2Tri.PolygonPoint(p.X, p.Y);

            Poly2Tri.PolygonSet polygonSet = new Poly2Tri.PolygonSet();

            ClipperLib.PolyNode node = solution.GetFirst();
            while (node != null)
            {
                // Only interested in closed paths
                if (!node.IsOpen)
                {
                    if (node.IsHole)
                    {
                        if (polygonSet.Polygons.Count() > 0)
                        {
                            // Add hole to last polygon entered
                            var polyPoints        = node.Contour.Select(xfToPolygonPoint).ToArray();
                            Poly2Tri.Polygon hole = new Poly2Tri.Polygon(polyPoints);

                            Poly2Tri.Polygon polygon = polygonSet.Polygons.Last();
                            polygon.AddHole(hole);
                        }
                    }
                    else
                    {
                        // Add a new polygon to the set
                        var polyPoints           = node.Contour.Select(xfToPolygonPoint).ToList();
                        Poly2Tri.Polygon polygon = new Poly2Tri.Polygon(polyPoints);
                        polygonSet.Add(polygon);
                    }
                }
                node = node.GetNext();
            }

            // Now triangulate the whole set
            Poly2Tri.P2T.Triangulate(polygonSet);

            // Combine all the triangles into one list
            List <Poly2Tri.DelaunayTriangle> triangles = new List <Poly2Tri.DelaunayTriangle>();

            foreach (var polygon in polygonSet.Polygons)
            {
                triangles.AddRange(polygon.Triangles);
            }

            return(triangles);
        }
示例#4
0
        public static List <Polygon> concaveToConvex(Polygon concave)
        {
            List <Polygon> result = new List <Polygon>();

            IVector3d normal = concave.vertices[0].normal.clone();

            bool cw = !Extrude.isCCW(concave);

            Poly2Tri.Polygon p = fromCSGPolygon(concave);

            Poly2Tri.Poly2Tri.triangulate(p);

            List <Poly2Tri.DelaunayTriangle> triangles = p.getTriangles();

            List <Vertex> triPoints = new List <Vertex>();

            foreach (Poly2Tri.DelaunayTriangle t in triangles)
            {
                int counter = 0;
                foreach (Poly2Tri.TriangulationPoint tp in t.points)
                {
                    triPoints.Add(new Vertex(
                                      Vector3d.xyz(tp.getX(), tp.getY(), tp.getZ()),
                                      normal));

                    if (counter == 2)
                    {
                        if (!cw)
                        {
                            triPoints.Reverse();
                        }
                        Polygon poly =
                            new Polygon(
                                triPoints, concave.getStorage());
                        result.Add(poly);
                        counter   = 0;
                        triPoints = new List <Vertex>();
                    }
                    else
                    {
                        counter++;
                    }
                }
            }

            return(result);
        }
示例#5
0
        void DrawSimpleRectExample(Painter painter)
        {
            Poly2Tri.TriangulationPoint[] points = new Poly2Tri.TriangulationPoint[]
            {
                new Poly2Tri.TriangulationPoint(10, 10),
                new Poly2Tri.TriangulationPoint(40, 10),
                new Poly2Tri.TriangulationPoint(40, 40),
                new Poly2Tri.TriangulationPoint(10, 40)
            };

            Poly2Tri.Polygon polygon = new Poly2Tri.Polygon(points);
            Poly2Tri.P2T.Triangulate(polygon);


            painter.StrokeColor = Color.Black;

            DrawPoly2TriPolygon(painter, new List <Poly2Tri.Polygon>()
            {
                polygon
            });
        }
示例#6
0
        void DrawVxsArrowHoleExample(Painter painter)
        {
            //1. background box
            Poly2Tri.TriangulationPoint[] box = new Poly2Tri.TriangulationPoint[]
            {
                new Poly2Tri.TriangulationPoint(5, 5),
                new Poly2Tri.TriangulationPoint(200, 5),
                new Poly2Tri.TriangulationPoint(200, 200),
                new Poly2Tri.TriangulationPoint(5, 200)
            };

            Poly2Tri.Polygon bgBoxPolygon = new Poly2Tri.Polygon(box);

            //2. arrow-shape hole
            VertexStore vxs = BuildArrow(true);

            using (Poly2TriTool.Borrow(out var p23tool))
            {
                p23tool.YAxisPointDown = true; //since our vxs is create from Y axis point down world

                List <Poly2Tri.Polygon> polygons = new List <Poly2Tri.Polygon>();
                p23tool.PreparePolygons(vxs, polygons);

                foreach (Poly2Tri.Polygon polygon in polygons)
                {
                    //arrow-shape hole
                    bgBoxPolygon.AddHole(polygon);
                }

                Poly2Tri.P2T.Triangulate(bgBoxPolygon);

                painter.StrokeColor = Color.Black;
                DrawPoly2TriPolygon(painter, new List <Poly2Tri.Polygon>()
                {
                    bgBoxPolygon
                });
            }
        }
示例#7
0
		public static Poly2Tri.Polygon GetTriangles(PolygonClosedD2D polygons)
		{
			var mainPolygon = new Poly2Tri.Polygon(polygons.Points.Select(pt => new Poly2Tri.PolygonPoint(pt.X, pt.Y)));
			Poly2Tri.P2T.Triangulate(mainPolygon);
			return mainPolygon;
		}
        /// <summary>
        /// create GlyphDynamicOutline from flatten contours
        /// </summary>
        /// <param name="flattenContours"></param>
        /// <returns></returns>
        GlyphDynamicOutline CreateDynamicOutline(List <GlyphContour> flattenContours)
        {
            //--------------------------
            //TODO: review here, add hole or not
            // more than 1 contours, no hole => eg.  i, j, ;,  etc
            // more than 1 contours, with hole => eg.  a,e ,   etc

            //closewise => not hole
            waitingHoles.Clear();
            int cntCount = flattenContours.Count;

            Poly2Tri.Polygon mainPolygon = null;
            //
            //this version if it is a hole=> we add it to main polygon
            //TODO: add to more proper polygon ***
            //eg i
            //--------------------------
            List <Poly2Tri.Polygon> otherPolygons = null;

            for (int n = 0; n < cntCount; ++n)
            {
                GlyphContour cnt = flattenContours[n];
                if (cnt.IsClosewise())
                {
                    //not a hole
                    if (mainPolygon == null)
                    {
                        //if we don't have mainPolygon before
                        //this is main polygon
                        mainPolygon = CreatePolygon(cnt.flattenPoints);

                        if (waitingHoles.Count > 0)
                        {
                            //flush all waiting holes to the main polygon
                            int j = waitingHoles.Count;
                            for (int i = 0; i < j; ++i)
                            {
                                mainPolygon.AddHole(waitingHoles[i]);
                            }
                            waitingHoles.Clear();
                        }
                    }
                    else
                    {
                        //if we already have a main polygon
                        //then this is another sub polygon
                        //IsHole is correct after we Analyze() the glyph contour
                        Poly2Tri.Polygon subPolygon = CreatePolygon(cnt.flattenPoints);
                        if (otherPolygons == null)
                        {
                            otherPolygons = new List <Poly2Tri.Polygon>();
                        }
                        otherPolygons.Add(subPolygon);
                    }
                }
                else
                {
                    //this is a hole
                    Poly2Tri.Polygon subPolygon = CreatePolygon(cnt.flattenPoints);
                    if (mainPolygon == null)
                    {
                        //add to waiting polygon
                        waitingHoles.Add(subPolygon);
                    }
                    else
                    {
                        //add to mainPolygon
                        mainPolygon.AddHole(subPolygon);
                    }
                }
            }
            if (waitingHoles.Count > 0)
            {
                throw new NotSupportedException();
            }
            //------------------------------------------
            //2. tri angulate
            Poly2Tri.P2T.Triangulate(mainPolygon); //that poly is triangulated

            Poly2Tri.Polygon[] subPolygons = (otherPolygons != null) ? otherPolygons.ToArray() : null;
            if (subPolygons != null)
            {
                for (int i = subPolygons.Length - 1; i >= 0; --i)
                {
                    Poly2Tri.P2T.Triangulate(subPolygons[i]);
                }
            }

            //3. intermediate outline is used inside this lib
            //and then convert intermediate outline to dynamic outline
            return(new GlyphDynamicOutline(
                       new GlyphIntermediateOutline(flattenContours, mainPolygon, subPolygons)));
        }
        public static Poly2Tri.Polygon Triangulate(float[] polygon1, int[] contourEndIndices)
        {
            //create
            List <GlyphContour> flattenContours = CreateGlyphContours(polygon1, contourEndIndices);

            //--------------------------
            //TODO: review here, add hole or not
            // more than 1 contours, no hole => eg.  i, j, ;,  etc
            // more than 1 contours, with hole => eg.  a,e ,   etc

            //clockwise => not hole
            _waitingHoles.Clear();

            int cntCount = flattenContours.Count;

            Poly2Tri.Polygon mainPolygon = null;
            //
            //this version if it is a hole=> we add it to main polygon
            //TODO: add to more proper polygon ***
            //eg i
            //--------------------------
            List <Poly2Tri.Polygon> otherPolygons = null;

            for (int n = 0; n < cntCount; ++n)
            {
                GlyphContour cnt = flattenContours[n];
                if (cnt.IsClockwise())
                {
                    //not a hole
                    if (mainPolygon == null)
                    {
                        //if we don't have mainPolygon before
                        //this is main polygon
                        mainPolygon = CreatePolygon(cnt.flattenPoints);

                        if (_waitingHoles.Count > 0)
                        {
                            //flush all waiting holes to the main polygon
                            int j = _waitingHoles.Count;
                            for (int i = 0; i < j; ++i)
                            {
                                mainPolygon.AddHole(_waitingHoles[i]);
                            }
                            _waitingHoles.Clear();
                        }
                    }
                    else
                    {
                        //if we already have a main polygon
                        //then this is another sub polygon
                        //IsHole is correct after we Analyze() the glyph contour
                        Poly2Tri.Polygon subPolygon = CreatePolygon(cnt.flattenPoints);
                        if (otherPolygons == null)
                        {
                            otherPolygons = new List <Poly2Tri.Polygon>();
                        }
                        otherPolygons.Add(subPolygon);
                    }
                }
                else
                {
                    //this is a hole
                    Poly2Tri.Polygon subPolygon = CreatePolygon(cnt.flattenPoints);
                    if (mainPolygon == null)
                    {
                        //add to waiting polygon
                        _waitingHoles.Add(subPolygon);
                    }
                    else
                    {
                        //add to mainPolygon
                        mainPolygon.AddHole(subPolygon);
                    }
                }
            }
            if (_waitingHoles.Count > 0)
            {
                throw new NotSupportedException();
            }
            //------------------------------------------
            //2. tri angulate
            Poly2Tri.P2T.Triangulate(mainPolygon); //that poly is triangulated

            Poly2Tri.Polygon[] subPolygons = (otherPolygons != null) ? otherPolygons.ToArray() : null;
            if (subPolygons != null)
            {
                for (int i = subPolygons.Length - 1; i >= 0; --i)
                {
                    Poly2Tri.P2T.Triangulate(subPolygons[i]);
                }
            }

            if (mainPolygon == null)
            {
            }

            return(mainPolygon);
        }
示例#10
0
        private void CutPoly(List <NavmeshCut> InNavmeshCuts, Int3[] verts, int[] tris, ref Int3[] outVertsArr, ref int[] outTrisArr, out int outVCount, out int outTCount, Int3[] extraShape, Int3 cuttingOffset, Bounds realBounds, MyTileHandler.CutMode mode, int perturbate = 0)
        {
            if (verts.Length == 0 || tris.Length == 0)
            {
                outVCount   = 0;
                outTCount   = 0;
                outTrisArr  = new int[0];
                outVertsArr = new Int3[0];
                return;
            }
            List <IntPoint> list = null;

            if (extraShape == null && (mode & MyTileHandler.CutMode.CutExtra) != 0)
            {
                throw new Exception("extraShape is null and the CutMode specifies that it should be used. Cannot use null shape.");
            }
            if ((mode & MyTileHandler.CutMode.CutExtra) != 0)
            {
                list = new List <IntPoint>(extraShape.Length);
                for (int i = 0; i < extraShape.Length; i++)
                {
                    list.Add(new IntPoint((long)(extraShape[i].x + cuttingOffset.x), (long)(extraShape[i].z + cuttingOffset.z)));
                }
            }
            List <IntPoint> list2 = new List <IntPoint>(5);
            Dictionary <TriangulationPoint, int> dictionary = new Dictionary <TriangulationPoint, int>();
            List <PolygonPoint> list3 = new List <PolygonPoint>();
            IntRect             b     = new IntRect(verts[0].x, verts[0].z, verts[0].x, verts[0].z);

            for (int j = 0; j < verts.Length; j++)
            {
                b = b.ExpandToContain(verts[j].x, verts[j].z);
            }
            List <Int3> list4 = ListPool <Int3> .Claim(verts.Length * 2);

            List <int> list5 = ListPool <int> .Claim(tris.Length);

            PolyTree polyTree = new PolyTree();
            List <List <IntPoint> >  list6 = new List <List <IntPoint> >();
            Stack <Poly2Tri.Polygon> stack = new Stack <Poly2Tri.Polygon>();

            if (this.clipper == null)
            {
                this.clipper = new Clipper(0);
            }
            this.clipper.ReverseSolution = true;
            this.clipper.StrictlySimple  = true;
            List <NavmeshCut> listView;

            if (mode == MyTileHandler.CutMode.CutExtra)
            {
                listView = new List <NavmeshCut>();
            }
            else
            {
                listView = new List <NavmeshCut>(InNavmeshCuts);
            }
            List <int> list7 = ListPool <int> .Claim();

            List <IntRect> list8 = ListPool <IntRect> .Claim();

            List <Int2> list9 = ListPool <Int2> .Claim();

            List <List <IntPoint> > list10 = new List <List <IntPoint> >();
            List <bool>             list11 = ListPool <bool> .Claim();

            List <bool> list12 = ListPool <bool> .Claim();

            if (perturbate > 10)
            {
                Debug.LogError("Too many perturbations aborting : " + mode);
                Debug.Break();
                outVCount   = verts.Length;
                outTCount   = tris.Length;
                outTrisArr  = tris;
                outVertsArr = verts;
                return;
            }
            System.Random random = null;
            if (perturbate > 0)
            {
                random = new System.Random();
            }
            for (int k = 0; k < listView.Count; k++)
            {
                Bounds  bounds = listView[k].GetBounds();
                Int3    vInt   = (Int3)bounds.min + cuttingOffset;
                Int3    vInt2  = (Int3)bounds.max + cuttingOffset;
                IntRect a      = new IntRect(vInt.x, vInt.z, vInt2.x, vInt2.z);
                if (IntRect.Intersects(a, b))
                {
                    Int2 vInt3 = new Int2(0, 0);
                    if (perturbate > 0)
                    {
                        vInt3.x = random.Next() % 6 * perturbate - 3 * perturbate;
                        if (vInt3.x >= 0)
                        {
                            vInt3.x++;
                        }
                        vInt3.y = random.Next() % 6 * perturbate - 3 * perturbate;
                        if (vInt3.y >= 0)
                        {
                            vInt3.y++;
                        }
                    }
                    int count = list10.Count;
                    listView[k].GetContour(list10);
                    for (int l = count; l < list10.Count; l++)
                    {
                        List <IntPoint> list13 = list10[l];
                        if (list13.Count == 0)
                        {
                            Debug.LogError("Zero Length Contour");
                            list8.Add(default(IntRect));
                            list9.Add(new Int2(0, 0));
                        }
                        else
                        {
                            IntRect intRect = new IntRect((int)list13[0].X + cuttingOffset.x, (int)list13[0].Y + cuttingOffset.y, (int)list13[0].X + cuttingOffset.x, (int)list13[0].Y + cuttingOffset.y);
                            for (int m = 0; m < list13.Count; m++)
                            {
                                IntPoint intPoint = list13[m];
                                intPoint.X += (long)cuttingOffset.x;
                                intPoint.Y += (long)cuttingOffset.z;
                                if (perturbate > 0)
                                {
                                    intPoint.X += (long)vInt3.x;
                                    intPoint.Y += (long)vInt3.y;
                                }
                                list13[m] = intPoint;
                                intRect   = intRect.ExpandToContain((int)intPoint.X, (int)intPoint.Y);
                            }
                            list9.Add(new Int2(vInt.y, vInt2.y));
                            list8.Add(intRect);
                            list11.Add(listView[k].isDual);
                            list12.Add(listView[k].cutsAddedGeom);
                        }
                    }
                }
            }
            List <NavmeshAdd> listView2 = new List <NavmeshAdd>();

            Int3[] array  = verts;
            int[]  array2 = tris;
            int    num    = -1;
            int    n      = -3;

            Int3[] array3 = null;
            Int3[] array4 = null;
            Int3   vInt4  = Int3.zero;

            if (listView2.Count > 0)
            {
                array3 = new Int3[7];
                array4 = new Int3[7];
                vInt4  = (Int3)realBounds.extents;
            }
            while (true)
            {
                n += 3;
                while (n >= array2.Length)
                {
                    num++;
                    n = 0;
                    if (num >= listView2.Count)
                    {
                        array = null;
                        break;
                    }
                    if (array == verts)
                    {
                        array = null;
                    }
                    listView2[num].GetMesh(cuttingOffset, ref array, out array2);
                }
                if (array == null)
                {
                    break;
                }
                Int3    vInt5 = array[array2[n]];
                Int3    vInt6 = array[array2[n + 1]];
                Int3    vInt7 = array[array2[n + 2]];
                IntRect a2    = new IntRect(vInt5.x, vInt5.z, vInt5.x, vInt5.z);
                a2 = a2.ExpandToContain(vInt6.x, vInt6.z);
                a2 = a2.ExpandToContain(vInt7.x, vInt7.z);
                int num2 = Math.Min(vInt5.y, Math.Min(vInt6.y, vInt7.y));
                int num3 = Math.Max(vInt5.y, Math.Max(vInt6.y, vInt7.y));
                list7.Clear();
                bool flag = false;
                for (int num4 = 0; num4 < list10.Count; num4++)
                {
                    int x = list9[num4].x;
                    int y = list9[num4].y;
                    if (IntRect.Intersects(a2, list8[num4]) && y >= num2 && x <= num3 && (list12[num4] || num == -1))
                    {
                        Int3 vInt8 = vInt5;
                        vInt8.y = x;
                        Int3 vInt9 = vInt5;
                        vInt9.y = y;
                        list7.Add(num4);
                        flag |= list11[num4];
                    }
                }
                if (list7.Count == 0 && (mode & MyTileHandler.CutMode.CutExtra) == 0 && (mode & MyTileHandler.CutMode.CutAll) != 0 && num == -1)
                {
                    list5.Add(list4.Count);
                    list5.Add(list4.Count + 1);
                    list5.Add(list4.Count + 2);
                    list4.Add(vInt5);
                    list4.Add(vInt6);
                    list4.Add(vInt7);
                }
                else
                {
                    list2.Clear();
                    if (num == -1)
                    {
                        list2.Add(new IntPoint((long)vInt5.x, (long)vInt5.z));
                        list2.Add(new IntPoint((long)vInt6.x, (long)vInt6.z));
                        list2.Add(new IntPoint((long)vInt7.x, (long)vInt7.z));
                    }
                    else
                    {
                        array3[0] = vInt5;
                        array3[1] = vInt6;
                        array3[2] = vInt7;
                        int num5 = Utility.ClipPolygon(array3, 3, array4, 1, 0, 0);
                        if (num5 == 0)
                        {
                            continue;
                        }
                        num5 = Utility.ClipPolygon(array4, num5, array3, -1, 2 * vInt4.x, 0);
                        if (num5 == 0)
                        {
                            continue;
                        }
                        num5 = Utility.ClipPolygon(array3, num5, array4, 1, 0, 2);
                        if (num5 == 0)
                        {
                            continue;
                        }
                        num5 = Utility.ClipPolygon(array4, num5, array3, -1, 2 * vInt4.z, 2);
                        if (num5 == 0)
                        {
                            continue;
                        }
                        for (int num6 = 0; num6 < num5; num6++)
                        {
                            list2.Add(new IntPoint((long)array3[num6].x, (long)array3[num6].z));
                        }
                    }
                    dictionary.Clear();
                    Int3 vInt10 = vInt6 - vInt5;
                    Int3 vInt11 = vInt7 - vInt5;
                    Int3 vInt12 = vInt10;
                    Int3 vInt13 = vInt11;
                    vInt12.y = 0;
                    vInt13.y = 0;
                    for (int num7 = 0; num7 < 16; num7++)
                    {
                        if (((int)mode >> (num7 & 31) & (int)MyTileHandler.CutMode.CutAll) != 0)
                        {
                            if (1 << num7 == 1)
                            {
                                this.clipper.Clear();
                                this.clipper.AddPolygon(list2, 0);
                                for (int num8 = 0; num8 < list7.Count; num8++)
                                {
                                    this.clipper.AddPolygon(list10[list7[num8]], PolyType.ptClip);
                                }
                                polyTree.Clear();
                                this.clipper.Execute(ClipType.ctDifference, polyTree, 0, PolyFillType.pftNonZero);
                            }
                            else if (1 << num7 == 2)
                            {
                                if (!flag)
                                {
                                    goto IL_1173;
                                }
                                this.clipper.Clear();
                                this.clipper.AddPolygon(list2, 0);
                                for (int num9 = 0; num9 < list7.Count; num9++)
                                {
                                    if (list11[list7[num9]])
                                    {
                                        this.clipper.AddPolygon(list10[list7[num9]], PolyType.ptClip);
                                    }
                                }
                                list6.Clear();
                                this.clipper.Execute(0, list6, 0, PolyFillType.pftNonZero);
                                this.clipper.Clear();
                                for (int num10 = 0; num10 < list6.Count; num10++)
                                {
                                    this.clipper.AddPolygon(list6[num10], (PolyType)((!Clipper.Orientation(list6[num10])) ? 0 : 1));
                                }
                                for (int num11 = 0; num11 < list7.Count; num11++)
                                {
                                    if (!list11[list7[num11]])
                                    {
                                        this.clipper.AddPolygon(list10[list7[num11]], PolyType.ptClip);
                                    }
                                }
                                polyTree.Clear();
                                this.clipper.Execute(ClipType.ctDifference, polyTree, 0, PolyFillType.pftNonZero);
                            }
                            else if (1 << num7 == 4)
                            {
                                this.clipper.Clear();
                                this.clipper.AddPolygon(list2, 0);
                                this.clipper.AddPolygon(list, PolyType.ptClip);
                                polyTree.Clear();
                                this.clipper.Execute(0, polyTree, 0, PolyFillType.pftNonZero);
                            }
                            for (int num12 = 0; num12 < polyTree.ChildCount; num12++)
                            {
                                PolyNode        polyNode = polyTree.Childs[num12];
                                List <IntPoint> contour  = polyNode.Contour;
                                List <PolyNode> childs   = polyNode.Childs;
                                if (childs.Count == 0 && contour.Count == 3 && num == -1)
                                {
                                    for (int num13 = 0; num13 < contour.Count; num13++)
                                    {
                                        Int3   vInt14 = new Int3((int)contour[num13].X, 0, (int)contour[num13].Y);
                                        double num14  = (double)(vInt6.z - vInt7.z) * (double)(vInt5.x - vInt7.x) + (double)(vInt7.x - vInt6.x) * (double)(vInt5.z - vInt7.z);
                                        if (num14 == 0.0)
                                        {
                                            Debug.LogWarning("Degenerate triangle");
                                        }
                                        else
                                        {
                                            double num15 = ((double)(vInt6.z - vInt7.z) * (double)(vInt14.x - vInt7.x) + (double)(vInt7.x - vInt6.x) * (double)(vInt14.z - vInt7.z)) / num14;
                                            double num16 = ((double)(vInt7.z - vInt5.z) * (double)(vInt14.x - vInt7.x) + (double)(vInt5.x - vInt7.x) * (double)(vInt14.z - vInt7.z)) / num14;
                                            vInt14.y = (int)Math.Round(num15 * (double)vInt5.y + num16 * (double)vInt6.y + (1.0 - num15 - num16) * (double)vInt7.y);
                                            list5.Add(list4.Count);
                                            list4.Add(vInt14);
                                        }
                                    }
                                }
                                else
                                {
                                    Poly2Tri.Polygon polygon = null;
                                    int num17 = -1;
                                    for (List <IntPoint> list14 = contour; list14 != null; list14 = ((num17 >= childs.Count) ? null : childs[num17].Contour))
                                    {
                                        list3.Clear();
                                        for (int num18 = 0; num18 < list14.Count; num18++)
                                        {
                                            PolygonPoint polygonPoint = new PolygonPoint((double)list14[num18].X, (double)list14[num18].Y);
                                            list3.Add(polygonPoint);
                                            Int3   vInt15 = new Int3((int)list14[num18].X, 0, (int)list14[num18].Y);
                                            double num19  = (double)(vInt6.z - vInt7.z) * (double)(vInt5.x - vInt7.x) + (double)(vInt7.x - vInt6.x) * (double)(vInt5.z - vInt7.z);
                                            if (num19 == 0.0)
                                            {
                                                Debug.LogWarning("Degenerate triangle");
                                            }
                                            else
                                            {
                                                double num20 = ((double)(vInt6.z - vInt7.z) * (double)(vInt15.x - vInt7.x) + (double)(vInt7.x - vInt6.x) * (double)(vInt15.z - vInt7.z)) / num19;
                                                double num21 = ((double)(vInt7.z - vInt5.z) * (double)(vInt15.x - vInt7.x) + (double)(vInt5.x - vInt7.x) * (double)(vInt15.z - vInt7.z)) / num19;
                                                vInt15.y = (int)Math.Round(num20 * (double)vInt5.y + num21 * (double)vInt6.y + (1.0 - num20 - num21) * (double)vInt7.y);
                                                dictionary[polygonPoint] = list4.Count;
                                                list4.Add(vInt15);
                                            }
                                        }
                                        Poly2Tri.Polygon polygon2;
                                        if (stack.Count > 0)
                                        {
                                            polygon2 = stack.Pop();
                                            polygon2.AddPoints(list3);
                                        }
                                        else
                                        {
                                            polygon2 = new Poly2Tri.Polygon(list3);
                                        }
                                        if (polygon == null)
                                        {
                                            polygon = polygon2;
                                        }
                                        else
                                        {
                                            polygon.AddHole(polygon2);
                                        }
                                        num17++;
                                    }
                                    try
                                    {
                                        P2T.Triangulate(polygon);
                                    }
                                    catch (PointOnEdgeException)
                                    {
                                        Debug.LogWarning(string.Concat(new object[]
                                        {
                                            "PointOnEdgeException, perturbating vertices slightly ( at ",
                                            num7,
                                            " in ",
                                            mode,
                                            ")"
                                        }));
                                        this.CutPoly(InNavmeshCuts, verts, tris, ref outVertsArr, ref outTrisArr, out outVCount, out outTCount, extraShape, cuttingOffset, realBounds, mode, perturbate + 1);
                                        return;
                                    }
                                    for (int num22 = 0; num22 < polygon.Triangles.Count; num22++)
                                    {
                                        DelaunayTriangle delaunayTriangle = polygon.Triangles[num22];
                                        list5.Add(dictionary[delaunayTriangle.Points._0]);
                                        list5.Add(dictionary[delaunayTriangle.Points._1]);
                                        list5.Add(dictionary[delaunayTriangle.Points._2]);
                                    }
                                    if (polygon.Holes != null)
                                    {
                                        for (int num23 = 0; num23 < polygon.Holes.Count; num23++)
                                        {
                                            polygon.Holes[num23].Points.Clear();
                                            polygon.Holes[num23].ClearTriangles();
                                            if (polygon.Holes[num23].Holes != null)
                                            {
                                                polygon.Holes[num23].Holes.Clear();
                                            }
                                            stack.Push(polygon.Holes[num23]);
                                        }
                                    }
                                    polygon.ClearTriangles();
                                    if (polygon.Holes != null)
                                    {
                                        polygon.Holes.Clear();
                                    }
                                    polygon.Points.Clear();
                                    stack.Push(polygon);
                                }
                            }
                        }
                        IL_1173 :;
                    }
                }
            }
            Dictionary <Int3, int> dictionary2 = this.cached_Int3_int_dict;

            dictionary2.Clear();
            if (this.cached_int_array.Length < list4.Count)
            {
                this.cached_int_array = new int[Math.Max(this.cached_int_array.Length * 2, list4.Count)];
            }
            int[] array5 = this.cached_int_array;
            int   num24  = 0;

            for (int num25 = 0; num25 < list4.Count; num25++)
            {
                int num26;
                if (!dictionary2.TryGetValue(list4[num25], out num26))
                {
                    dictionary2.Add(list4[num25], num24);
                    array5[num25] = num24;
                    list4[num24]  = list4[num25];
                    num24++;
                }
                else
                {
                    array5[num25] = num26;
                }
            }
            outTCount = list5.Count;
            if (outTrisArr == null || outTrisArr.Length < outTCount)
            {
                outTrisArr = new int[outTCount];
            }
            for (int num27 = 0; num27 < outTCount; num27++)
            {
                outTrisArr[num27] = array5[list5[num27]];
            }
            outVCount = num24;
            if (outVertsArr == null || outVertsArr.Length < outVCount)
            {
                outVertsArr = new Int3[outVCount];
            }
            for (int num28 = 0; num28 < outVCount; num28++)
            {
                outVertsArr[num28] = list4[num28];
            }
            for (int num29 = 0; num29 < listView.Count; num29++)
            {
                listView[num29].UsedForCut();
            }
            ListPool <Int3> .Release(list4);

            ListPool <int> .Release(list5);

            ListPool <int> .Release(list7);

            ListPool <Int2> .Release(list9);

            ListPool <bool> .Release(list11);

            ListPool <bool> .Release(list12);

            ListPool <IntRect> .Release(list8);
        }
示例#11
0
        public static Mesh Retriangulate(VoxelizationInput input, Mesh mesh, out List <List <Edge> > debugLoops)
        {
            debugLoops = new List <List <Edge> >();

            try
            {
                Triangle[] triangles = Triangle.ToTriangleArray(mesh.Indicies, mesh.Vertices);

                Debug.WriteLine("Sorting triangles based on plane.");

                List <PolygonTriangles> planeLookup = SortTrianglesIntoPlanes(triangles);

                Debug.WriteLine("Triangles sorted by planes: Done.");

                List <Vector4> processedVerticies = new List <Vector4>();
                List <int>     processedIndicies  = new List <int>();

                foreach (PolygonTriangles polygon in planeLookup)
                {
#if DEBUGGING_TJUNCTIONS
                    if (!Vector3Ex.AlmostEquals(polygon.Plane.Normal, Vector3.UnitY))
                    {
                        continue;
                    }
#endif

                    // Before we can begin margining edges we need to ensure that all shared collinear edges
                    // have a mate, one thing that can prevent this is the presence of T-Junctions, so first
                    // we need to fix them by splitting polygons that produce them.
                    polygon.Triangles = FindAndFixTJuntions(input, polygon.Triangles);

                    // We build a list of distinctive edges because a distinctive edge is either part of the inner loop
                    // or the outer loop of a group of polygons, because if two polygons share an edge that are co-planer
                    // that edge can't be on the inside or the outside of the plane.
                    List <Edge> distinctEdges = FindDistinctiveEdges(input, polygon.Triangles);
                    debugLoops.Add(distinctEdges.ToList());

                    // Merge the edges together that are collinear.
                    List <List <Edge> > outterLoops = FindOuterLoops(distinctEdges);
                    //allLoops.AddRange(outterLoops);

                    Vector3 right = Vector3Ex.GetRight(polygon.Plane.Normal);
                    Vector3 U, V;
                    Vector3Ex.GetBasisVectors(polygon.Plane.Normal, right, out U, out V);

                    Vector3 planeOrigin = polygon.Plane.PointOnPlane;

                    foreach (List <Edge> outterEdgeLoop in outterLoops)
                    {
                        List <Vector2> outerLoopTransformed = new List <Vector2>();
                        for (int i = 0; i < outterEdgeLoop.Count; i++)
                        {
                            Edge e = outterEdgeLoop[i];

                            Vector2 uv = Vector3Ex.Calc2DPoint(e.v0, U, V);

                            outerLoopTransformed.Add(uv);
                        }

                        //Debug.Assert(outerLoopTransformed.Count > 2);
                        if (outerLoopTransformed.Count > 2)
                        {
                            List <Poly2Tri.PolygonPoint> polyPoints = new List <Poly2Tri.PolygonPoint>();
                            foreach (var pt in outerLoopTransformed)
                            {
                                polyPoints.Add(new Poly2Tri.PolygonPoint(pt.X, pt.Y));
                            }
                            Poly2Tri.Polygon p = new Poly2Tri.Polygon(polyPoints);
                            Poly2Tri.P2T.Triangulate(Poly2Tri.TriangulationAlgorithm.DTSweep, p);

                            int currentVerticies = processedVerticies.Count;
                            foreach (var dt in p.Triangles)
                            {
                                processedIndicies.Add((currentVerticies + 0));
                                processedIndicies.Add((currentVerticies + 1));
                                processedIndicies.Add((currentVerticies + 2));

                                Vector3 pt0 = (((float)dt.Points._0.X * U) + ((float)dt.Points._0.Y * V)) - planeOrigin;
                                Vector3 pt1 = (((float)dt.Points._1.X * U) + ((float)dt.Points._1.Y * V)) - planeOrigin;
                                Vector3 pt2 = (((float)dt.Points._2.X * U) + ((float)dt.Points._2.Y * V)) - planeOrigin;
                                processedVerticies.Add(new Vector4(pt0, 1));
                                processedVerticies.Add(new Vector4(pt1, 1));
                                processedVerticies.Add(new Vector4(pt2, 1));

                                currentVerticies += 3;
                            }
                        }
                        else
                        {
                            Debug.WriteLine("outer loop problem!");
                        }
                    }

                    Debug.WriteLine("Distinct Edges " + processedIndicies.Count / 3);
                }

                Mesh retriangulatedMesh = new Mesh();
                retriangulatedMesh.Vertices = processedVerticies.ToArray();
                retriangulatedMesh.Indicies = processedIndicies.ToArray();

                return(retriangulatedMesh);
            }
            catch (Exception)
            {
                return(null);
            }
        }
示例#12
0
        static void TriangulateConstrainedDelaunay(List <List <Vector3> > listlistPointsConstrainedDelaunay, List <List <int> > listlistHashValuesConstrainedDelaunay, bool bForceVertexSoup, FracturedObject fracturedComponent,
                                                   bool bConnectivityPostprocess, MeshFaceConnectivity faceConnectivityPos, MeshFaceConnectivity faceConnectivityNeg, MeshDataConnectivity meshConnectivityPos, MeshDataConnectivity meshConnectivityNeg, int nForceMeshConnectivityHash,
                                                   int nSplitCloseSubMesh, Matrix4x4 mtxPlane, Matrix4x4 mtxToLocalPos, Matrix4x4 mtxToLocalNeg, Vector3 v3CenterPos, Vector3 v3CenterNeg,
                                                   List <int>[] aListIndicesPosInOut, List <VertexData> listVertexDataPosInOut, List <int>[] aListIndicesNegInOut, List <VertexData> listVertexDataNegInOut)
        {
            // Pass to two dimensional plane:

            Matrix4x4 mtxPlaneInverse = mtxPlane.inverse;
            List <List <Poly2Tri.Point2D> >      listlistCapPoints        = new List <List <Poly2Tri.Point2D> >();
            List <List <Poly2Tri.PolygonPoint> > listlistCapPolygonPoints = new List <List <Poly2Tri.PolygonPoint> >();
            List <Poly2Tri.Polygon> listCapPolygons = new List <Poly2Tri.Polygon>();

            for (int i = 0; i < listlistPointsConstrainedDelaunay.Count; i++)
            {
                List <Poly2Tri.Point2D>      listCapPoints         = new List <Poly2Tri.Point2D>();
                List <Poly2Tri.PolygonPoint> listCapPolygonsPoints = new List <Poly2Tri.PolygonPoint>();

                foreach (Vector3 v3Vertex in listlistPointsConstrainedDelaunay[i])
                {
                    Vector3 v3VertexInPlane = mtxPlaneInverse.MultiplyPoint3x4(v3Vertex);
                    listCapPoints.Add(new Poly2Tri.Point2D(v3VertexInPlane.x, v3VertexInPlane.z));
                    listCapPolygonsPoints.Add(new Poly2Tri.PolygonPoint(v3VertexInPlane.x, v3VertexInPlane.z));
                }

                listlistCapPoints.Add(listCapPoints);
                listlistCapPolygonPoints.Add(listCapPolygonsPoints);
                listCapPolygons.Add(new Poly2Tri.Polygon(listCapPolygonsPoints));
            }

            // Remove close vertices

            float fPrecisionFix = Mathf.Max(Parameters.EPSILONCAPPRECISIONMIN, fracturedComponent.CapPrecisionFix);

            if (fPrecisionFix > 0.0f)
            {
                for (int nCap = 0; nCap < listlistCapPolygonPoints.Count; nCap++)
                {
                    double lastX = listlistCapPolygonPoints[nCap][listlistCapPolygonPoints[nCap].Count - 1].X;
                    double lastY = listlistCapPolygonPoints[nCap][listlistCapPolygonPoints[nCap].Count - 1].Y;

                    bool bDeleteCap = false;

                    for (int nVertex = 0; nVertex < listlistCapPolygonPoints[nCap].Count; nVertex++)
                    {
                        double vecX = listlistCapPolygonPoints[nCap][nVertex].X - lastX;
                        double vecY = listlistCapPolygonPoints[nCap][nVertex].Y - lastY;

                        if (System.Math.Sqrt(vecX * vecX + vecY * vecY) < fPrecisionFix)
                        {
                            listlistCapPolygonPoints[nCap].RemoveAt(nVertex);
                            nVertex--;

                            if (listlistCapPolygonPoints[nCap].Count < 3)
                            {
                                bDeleteCap = true;
                                break;
                            }
                        }
                        else
                        {
                            lastX = listlistCapPolygonPoints[nCap][nVertex].X;
                            lastY = listlistCapPolygonPoints[nCap][nVertex].Y;
                        }
                    }

                    if (bDeleteCap)
                    {
                        listlistCapPolygonPoints.RemoveAt(nCap);
                        nCap--;
                    }
                }
            }

            if (listlistCapPolygonPoints.Count == 0)
            {
                return;
            }

            // Search if one of the caps is contained in the other. If this happens we will mark the big one as the polygon and the rest as holes

            int nSuperPolygon = -1;

            Poly2Tri.Polygon polygonContainer = null;

            if (bForceVertexSoup == false)
            {
                for (int i = 0; i < listlistCapPolygonPoints.Count; i++)
                {
                    for (int j = 0; j < listlistCapPolygonPoints.Count; j++)
                    {
                        if (i != j && listlistCapPoints[i].Count >= 3 && listlistCapPoints[j].Count >= 3)
                        {
                            if (Poly2Tri.PolygonUtil.PolygonContainsPolygon(listlistCapPoints[i], listCapPolygons[i].Bounds, listlistCapPoints[j], listCapPolygons[j].Bounds, true))
                            {
                                nSuperPolygon = i;
                                break;
                            }
                            else if (Poly2Tri.PolygonUtil.PolygonContainsPolygon(listlistCapPoints[j], listCapPolygons[j].Bounds, listlistCapPoints[i], listCapPolygons[i].Bounds, true))
                            {
                                nSuperPolygon = j;
                                break;
                            }
                        }
                    }
                }

                // Add holes if this is a cap with holes

                if (nSuperPolygon != -1)
                {
                    polygonContainer = listCapPolygons[nSuperPolygon];

                    for (int i = 0; i < listlistCapPolygonPoints.Count; i++)
                    {
                        if (i != nSuperPolygon && listCapPolygons[i].Count >= 3)
                        {
                            polygonContainer.AddHole(listCapPolygons[i]);
                        }
                    }
                }
            }

            // Triangulate

            bool bTriangulatedWithHoles = false;

            if (polygonContainer != null && bForceVertexSoup == false)
            {
                // Polygon with holes

                try
                {
                    Poly2Tri.P2T.Triangulate(polygonContainer);

                    if (polygonContainer.Triangles != null)
                    {
                        List <Vector3> listMeshVertices = new List <Vector3>();
                        List <int>     listMeshIndices  = new List <int>();

                        CreateIndexedMesh(polygonContainer.Triangles, listMeshVertices, listMeshIndices, mtxPlane, true);

                        Triangulate(listMeshVertices, listMeshIndices, fracturedComponent, listlistPointsConstrainedDelaunay, listlistHashValuesConstrainedDelaunay,
                                    bConnectivityPostprocess, faceConnectivityPos, faceConnectivityNeg, meshConnectivityPos, meshConnectivityNeg, nForceMeshConnectivityHash,
                                    nSplitCloseSubMesh, mtxPlane, mtxToLocalPos, mtxToLocalNeg, v3CenterPos, v3CenterNeg,
                                    aListIndicesPosInOut, listVertexDataPosInOut, aListIndicesNegInOut, listVertexDataNegInOut);
                    }

                    bTriangulatedWithHoles = true;
                }
                catch (System.Exception e)
                {
                    if (fracturedComponent.Verbose)
                    {
                        Debug.LogWarning("Exception (" + e.GetType() + ") using hole triangulation (holes = " + listlistCapPolygonPoints.Count + "). Trying to use constrained delaunay.");
                    }
                    bTriangulatedWithHoles = false;
                }
            }

            if (bTriangulatedWithHoles == false)
            {
                if (bForceVertexSoup)
                {
                    // Vertex soup

                    List <Poly2Tri.TriangulationPoint> listPoints = new List <Poly2Tri.TriangulationPoint>();

                    if (listlistCapPolygonPoints.Count > 0)
                    {
                        foreach (Poly2Tri.PolygonPoint polyPoint in listlistCapPolygonPoints[0])
                        {
                            listPoints.Add(polyPoint);
                        }

                        try
                        {
                            if (listPoints.Count >= 3)
                            {
                                Poly2Tri.PointSet ps = new Poly2Tri.PointSet(listPoints);
                                Poly2Tri.P2T.Triangulate(ps);

                                if (ps.Triangles != null)
                                {
                                    List <Vector3> listMeshVertices = new List <Vector3>();
                                    List <int>     listMeshIndices  = new List <int>();

                                    CreateIndexedMesh(ps.Triangles, listMeshVertices, listMeshIndices, mtxPlane, true);

                                    Triangulate(listMeshVertices, listMeshIndices, fracturedComponent, listlistPointsConstrainedDelaunay, listlistHashValuesConstrainedDelaunay,
                                                bConnectivityPostprocess, faceConnectivityPos, faceConnectivityNeg, meshConnectivityPos, meshConnectivityNeg, nForceMeshConnectivityHash,
                                                nSplitCloseSubMesh, mtxPlane, mtxToLocalPos, mtxToLocalNeg, v3CenterPos, v3CenterNeg,
                                                aListIndicesPosInOut, listVertexDataPosInOut, aListIndicesNegInOut, listVertexDataNegInOut);
                                }
                            }
                        }
                        catch (System.Exception e)
                        {
                            if (fracturedComponent.Verbose)
                            {
                                Debug.LogWarning("Exception (" + e.GetType() + ") using vertex soup triangulation.");
                            }
                        }
                    }
                }
                else
                {
                    // Use constrained delaunay triangulation

                    int nPoly = 0;

                    foreach (List <Poly2Tri.PolygonPoint> listPolyPoints in listlistCapPolygonPoints)
                    {
                        IList <Poly2Tri.DelaunayTriangle> listTriangles = null;

                        Poly2Tri.Polygon polygon = null;

                        try
                        {
                            if (listPolyPoints.Count >= 3)
                            {
                                polygon = new Poly2Tri.Polygon(listPolyPoints);
                                Poly2Tri.P2T.Triangulate(polygon);
                                listTriangles = polygon.Triangles;
                            }
                        }
                        catch (System.Exception e)
                        {
                            if (fracturedComponent.Verbose)
                            {
                                Debug.LogWarning("Exception (" + e.GetType() + ") using polygon triangulation of cap polygon " + nPoly + ". Trying to use non constrained");
                            }
                            listTriangles = null;
                        }

                        if (listTriangles == null)
                        {
                            List <Poly2Tri.TriangulationPoint> listPoints = new List <Poly2Tri.TriangulationPoint>();

                            foreach (Poly2Tri.PolygonPoint polyPoint in listPolyPoints)
                            {
                                listPoints.Add(polyPoint);
                            }

                            try
                            {
                                if (listPoints.Count >= 3)
                                {
                                    Poly2Tri.PointSet ps = new Poly2Tri.PointSet(listPoints);
                                    Poly2Tri.P2T.Triangulate(ps);
                                    listTriangles = ps.Triangles;
                                }
                            }
                            catch (System.Exception e)
                            {
                                if (fracturedComponent.Verbose)
                                {
                                    Debug.LogWarning("Exception (" + e.GetType() + ") using non constrained triangulation of cap polygon " + nPoly + ". Skipping");
                                }
                            }
                        }

                        if (listTriangles != null)
                        {
                            List <Vector3> listMeshVertices = new List <Vector3>();
                            List <int>     listMeshIndices  = new List <int>();

                            CreateIndexedMesh(listTriangles, listMeshVertices, listMeshIndices, mtxPlane, true);

                            Triangulate(listMeshVertices, listMeshIndices, fracturedComponent, listlistPointsConstrainedDelaunay, listlistHashValuesConstrainedDelaunay,
                                        bConnectivityPostprocess, faceConnectivityPos, faceConnectivityNeg, meshConnectivityPos, meshConnectivityNeg, nForceMeshConnectivityHash,
                                        nSplitCloseSubMesh, mtxPlane, mtxToLocalPos, mtxToLocalNeg, v3CenterPos, v3CenterNeg,
                                        aListIndicesPosInOut, listVertexDataPosInOut, aListIndicesNegInOut, listVertexDataNegInOut);
                        }

                        nPoly++;
                    }
                }
            }
        }
示例#13
0
        void DrawOutput()
        {
            if (_g == null)
            {
                return;
            }

            //-----------
            //for GDI+ only
            bool drawInvert = chkInvert.Checked;
            int  viewHeight = this.panel1.Height;

            //-----------
            //show tess
            _g.Clear(Color.White);
            int[]   contourEndIndices;
            float[] polygon1 = GetPolygonData(out contourEndIndices);
            if (polygon1 == null)
            {
                return;
            }
            //
            if (drawInvert)
            {
                var transformMat = new System.Drawing.Drawing2D.Matrix();
                transformMat.Scale(1, -1);
                transformMat.Translate(0, -viewHeight);
                //
                polygon1 = TransformPoints(polygon1, transformMat);
            }


            using (Pen pen1 = new Pen(Color.LightGray, 6))
            {
                int    nn = polygon1.Length;
                int    a  = 0;
                PointF p0;
                PointF p1;

                int contourCount = contourEndIndices.Length;
                int startAt      = 3;
                for (int cnt_index = 0; cnt_index < contourCount; ++cnt_index)
                {
                    int endAt = contourEndIndices[cnt_index];
                    for (int m = startAt; m <= endAt;)
                    {
                        p0 = new PointF(polygon1[m - 3], polygon1[m - 2]);
                        p1 = new PointF(polygon1[m - 1], polygon1[m]);
                        _g.DrawLine(pen1, p0, p1);
                        _g.DrawString(a.ToString(), this.Font, Brushes.Black, p0);
                        m += 2;
                        a++;
                    }
                    //close contour

                    p0 = new PointF(polygon1[endAt - 1], polygon1[endAt]);
                    p1 = new PointF(polygon1[startAt - 3], polygon1[startAt - 2]);
                    _g.DrawLine(pen1, p0, p1);
                    _g.DrawString(a.ToString(), this.Font, Brushes.Black, p0);
                    //
                    startAt = (endAt + 1) + 3;
                }
            }
            //----------------------------------------------------------------------------

            //tess
            if (rdoTessSGI.Checked)
            {
                //SGI Tess Lib

                if (!_tessTool.TessPolygon(polygon1, _contourEnds))
                {
                    return;
                }

                //1.
                List <ushort> indexList = _tessTool.TessIndexList;
                //2.
                List <TessVertex2d> tempVertexList = _tessTool.TempVertexList;
                //3.
                int vertexCount = indexList.Count;
                //-----------------------------
                int     orgVertexCount = polygon1.Length / 2;
                float[] vtx            = new float[vertexCount * 2];//***
                int     n = 0;

                for (int p = 0; p < vertexCount; ++p)
                {
                    ushort index = indexList[p];
                    if (index >= orgVertexCount)
                    {
                        //extra coord (newly created)
                        TessVertex2d extraVertex = tempVertexList[index - orgVertexCount];
                        vtx[n]     = (float)extraVertex.x;
                        vtx[n + 1] = (float)extraVertex.y;
                    }
                    else
                    {
                        //original corrd
                        vtx[n]     = (float)polygon1[index * 2];
                        vtx[n + 1] = (float)polygon1[(index * 2) + 1];
                    }
                    n += 2;
                }
                //-----------------------------
                //draw tess result
                int j = vtx.Length;
                for (int i = 0; i < j;)
                {
                    var p0 = new PointF(vtx[i], vtx[i + 1]);
                    var p1 = new PointF(vtx[i + 2], vtx[i + 3]);
                    var p2 = new PointF(vtx[i + 4], vtx[i + 5]);

                    _g.DrawLine(Pens.Red, p0, p1);
                    _g.DrawLine(Pens.Red, p1, p2);
                    _g.DrawLine(Pens.Red, p2, p0);

                    i += 6;
                }
            }
            else
            {
                Poly2Tri.Polygon mainPolygon = Poly2TriExampleHelper.Triangulate(polygon1, contourEndIndices);
                foreach (Poly2Tri.DelaunayTriangle tri in mainPolygon.Triangles)
                {
                    Poly2Tri.TriangulationPoint p0 = tri.P0;
                    Poly2Tri.TriangulationPoint p1 = tri.P1;
                    Poly2Tri.TriangulationPoint p2 = tri.P2;

                    _g.DrawLine(Pens.Red, (float)p0.X, (float)p0.Y, (float)p1.X, (float)p1.Y);
                    _g.DrawLine(Pens.Red, (float)p1.X, (float)p1.Y, (float)p2.X, (float)p2.Y);
                    _g.DrawLine(Pens.Red, (float)p2.X, (float)p2.Y, (float)p0.X, (float)p0.Y);
                }
            }
        }
        public static GameObject GenerateShapeUVedWithWalls_Balanced(this Poly2Tri.Polygon shape, OSMType type, string Id, string other, string tag, string MaterialName = "Building", float WallHeight = 5, float MaximumHeight = 12, bool GenerateColliders = true)
        {
            GameObject gameObject = new GameObject(type + "|" + ((int)type) + "|" + Id + (!string.IsNullOrEmpty(other) ? "|" + other : ""));

            gameObject.tag = tag;
            if (shape.Triangles == null)
            {
                return(gameObject);
            }
            if (shape.Triangles.Count == 0)
            {
                return(gameObject);
            }
            List <Vector3> vertices = new List <Vector3>();

            for (int i = 0; i < shape.Triangles.Count; i++)
            {
                vertices.AddRange(shape.Triangles[i].Points.Select(s => new Vector3((float)s.X, WallHeight, (float)s.Y)).Reverse());
            }

            // This is the starting index in the vertex list that belongs to the walls.
            // We use this to distinguish between roof UVs and wall UVs.
            int            WallStartIndex = vertices.Count;
            List <Vector2> UVs            = new List <Vector2>();
            var            minXRoof       = vertices.GetRange(0, WallStartIndex).Select(i => i.x).Min();
            var            minZRoof       = vertices.GetRange(0, WallStartIndex).Select(i => i.z).Min();
            var            maxXRoof       = vertices.GetRange(0, WallStartIndex).Select(i => i.x).Max();
            var            maxZRoof       = vertices.GetRange(0, WallStartIndex).Select(i => i.z).Max();

            // for (int i = 0; i < UVs.Length; i++)
            for (int i = 0; i < WallStartIndex; i++)
            {
                UVs.Add(new Vector2(
                            linear(vertices[i].x, minXRoof, maxXRoof, 0, 1),
                            linear(vertices[i].z, minZRoof, maxZRoof, 0, 0.5f)
                            ));
            }


            Vector2[] UVRef = new Vector2[]
            {
                new Vector2(0, 0.5f),                                     // top left
                new Vector2(1, 0.5f),                                     // top right
                new Vector2(0, 0.5f + 0.5f * WallHeight / MaximumHeight), // bottom left
                new Vector2(1, 0.5f + 0.5f * WallHeight / MaximumHeight)  // bottom right
                // new Vector2(0,1), // bottom left
                // new Vector2(1,1) // bottom right
            };
            #region Outer wall
            Vector3   HeightVector     = new Vector3(0, WallHeight, 0);
            Vector3[] OriginalVertices = shape.Points.Select(s => new Vector3((float)s.X, WallHeight, (float)s.Y)).ToArray();


            // Generating Walls - Total: (OriginalVertices.Length)*4*3
            for (int i = 0; i < OriginalVertices.Length - 1; i++)
            {
                Vector3 v1   = OriginalVertices[i];
                Vector3 v2   = OriginalVertices[i + 1];
                var     dist = Vector3.Distance(v1, v2);

                //Debug.Log("Distance: "+dist);
                dist = dist.Clamp(0, 5);
                var UVratioTopRight    = new Vector2(dist / 5, UVRef[1].y);
                var UVratioBottomRight = new Vector2(dist / 5, UVRef[3].y);

                Vector3 v3 = OriginalVertices[i] - HeightVector;
                Vector3 v4 = OriginalVertices[i + 1] - HeightVector;
                vertices.AddRange(new Vector3[] { v1, v2, v3 });
                UVs.Add(UVRef[0]);
                UVs.Add(UVratioTopRight); //UVs.Add(UVRef[1]);
                UVs.Add(UVRef[2]);
                vertices.AddRange(new Vector3[] { v3, v2, v4 });
                UVs.Add(UVRef[2]);
                UVs.Add(UVratioTopRight);    //UVs.Add(UVRef[1]);
                UVs.Add(UVratioBottomRight); //UVs.Add(UVRef[3]);
                // Reverse
                vertices.AddRange(new Vector3[] { v1, v3, v2 });
                UVs.Add(UVRef[0]);
                UVs.Add(UVRef[2]);
                UVs.Add(UVratioTopRight); //UVs.Add(UVRef[1]);
                vertices.AddRange(new Vector3[] { v3, v4, v2 });
                UVs.Add(UVRef[2]);
                UVs.Add(UVratioBottomRight); //UVs.Add(UVRef[3]);
                UVs.Add(UVratioTopRight);    //UVs.Add(UVRef[1]);
            }

            // Last Wall - Total: 4*3
            Vector3 lv1    = OriginalVertices[OriginalVertices.Length - 1];
            Vector3 lv2    = OriginalVertices[0];
            var     distlw = Vector3.Distance(lv1, lv2);
            //Debug.Log("Distance: "+distlw);
            distlw = distlw.Clamp(0, 5);
            var     UVratioTopRightlw    = new Vector2(distlw / 5, UVRef[1].y);
            var     UVratioBottomRightlw = new Vector2(distlw / 5, UVRef[3].y);
            Vector3 lv3 = OriginalVertices[OriginalVertices.Length - 1] - HeightVector;
            Vector3 lv4 = OriginalVertices[0] - HeightVector;
            vertices.AddRange(new Vector3[] { lv1, lv2, lv3 });
            UVs.Add(UVRef[0]);
            UVs.Add(UVratioTopRightlw); //UVs.Add(UVRef[1]);
            UVs.Add(UVRef[2]);
            vertices.AddRange(new Vector3[] { lv3, lv2, lv4 });
            UVs.Add(UVRef[2]);
            UVs.Add(UVratioTopRightlw);    //UVs.Add(UVRef[1]);
            UVs.Add(UVratioBottomRightlw); //UVs.Add(UVRef[3]);
            // Reverse
            vertices.AddRange(new Vector3[] { lv1, lv3, lv2 });
            UVs.Add(UVRef[0]);
            UVs.Add(UVRef[2]);
            UVs.Add(UVratioTopRightlw); //UVs.Add(UVRef[1]);
            vertices.AddRange(new Vector3[] { lv3, lv4, lv2 });
            UVs.Add(UVRef[2]);
            UVs.Add(UVratioBottomRightlw); //UVs.Add(UVRef[3]);
            UVs.Add(UVratioTopRightlw);    //UVs.Add(UVRef[1]);

            #endregion

            #region Inner walls
            List <Vector3[]> OriginalInnerVertices = new List <Vector3[]>();
            if (shape.Holes != null)
            {
                for (int i = 0; i < shape.Holes.Count; i++)
                {
                    OriginalInnerVertices.Add(shape.Holes[i].Points.Select(s => new Vector3((float)s.X, WallHeight, (float)s.Y)).ToArray());
                }

                for (int holeidx = 0; holeidx < shape.Holes.Count; holeidx++)
                {
                    // Generating Walls - Total: (OriginalInnerVertices.Length)*4*3
                    for (int i = 0; i < OriginalInnerVertices[holeidx].Length - 1; i++)
                    {
                        Vector3 v1   = OriginalInnerVertices[holeidx][i];
                        Vector3 v2   = OriginalInnerVertices[holeidx][i + 1];
                        var     dist = Vector3.Distance(v1, v2);

                        //Debug.Log("Distance: "+dist);
                        dist = dist.Clamp(0, 5);
                        var UVratioTopRight    = new Vector2(dist / 5, UVRef[1].y);
                        var UVratioBottomRight = new Vector2(dist / 5, UVRef[3].y);

                        Vector3 v3 = OriginalInnerVertices[holeidx][i] - HeightVector;
                        Vector3 v4 = OriginalInnerVertices[holeidx][i + 1] - HeightVector;
                        vertices.AddRange(new Vector3[] { v1, v2, v3 });
                        UVs.Add(UVRef[0]);
                        UVs.Add(UVratioTopRight); //UVs.Add(UVRef[1]);
                        UVs.Add(UVRef[2]);
                        vertices.AddRange(new Vector3[] { v3, v2, v4 });
                        UVs.Add(UVRef[2]);
                        UVs.Add(UVratioTopRight);    //UVs.Add(UVRef[1]);
                        UVs.Add(UVratioBottomRight); //UVs.Add(UVRef[3]);
                        // Reverse
                        vertices.AddRange(new Vector3[] { v1, v3, v2 });
                        UVs.Add(UVRef[0]);
                        UVs.Add(UVRef[2]);
                        UVs.Add(UVratioTopRight); //UVs.Add(UVRef[1]);
                        vertices.AddRange(new Vector3[] { v3, v4, v2 });
                        UVs.Add(UVRef[2]);
                        UVs.Add(UVratioBottomRight); //UVs.Add(UVRef[3]);
                        UVs.Add(UVratioTopRight);    //UVs.Add(UVRef[1]);
                    }

                    // Last Wall - Total: 4*3
                    Vector3 lv1_hole    = OriginalInnerVertices[holeidx][OriginalInnerVertices[holeidx].Length - 1];
                    Vector3 lv2_hole    = OriginalInnerVertices[holeidx][0];
                    var     distlw_hole = Vector3.Distance(lv1_hole, lv2_hole);
                    //Debug.Log("Distance: "+distlw_hole);
                    distlw_hole = distlw_hole.Clamp(0, 5);
                    var     UVratioTopRightlw_hole    = new Vector2(distlw_hole / 5, UVRef[1].y);
                    var     UVratioBottomRightlw_hole = new Vector2(distlw_hole / 5, UVRef[3].y);
                    Vector3 lv3_hole = OriginalInnerVertices[holeidx][OriginalInnerVertices[holeidx].Length - 1] - HeightVector;
                    Vector3 lv4_hole = OriginalInnerVertices[holeidx][0] - HeightVector;
                    vertices.AddRange(new Vector3[] { lv1_hole, lv2_hole, lv3_hole });
                    UVs.Add(UVRef[0]);
                    UVs.Add(UVratioTopRightlw_hole); //UVs.Add(UVRef[1]);
                    UVs.Add(UVRef[2]);
                    vertices.AddRange(new Vector3[] { lv3_hole, lv2_hole, lv4_hole });
                    UVs.Add(UVRef[2]);
                    UVs.Add(UVratioTopRightlw_hole);    //UVs.Add(UVRef[1]);
                    UVs.Add(UVratioBottomRightlw_hole); //UVs.Add(UVRef[3]);
                    // Reverse
                    vertices.AddRange(new Vector3[] { lv1_hole, lv3_hole, lv2_hole });
                    UVs.Add(UVRef[0]);
                    UVs.Add(UVRef[2]);
                    UVs.Add(UVratioTopRightlw_hole); //UVs.Add(UVRef[1]);
                    vertices.AddRange(new Vector3[] { lv3_hole, lv4_hole, lv2_hole });
                    UVs.Add(UVRef[2]);
                    UVs.Add(UVratioBottomRightlw_hole); //UVs.Add(UVRef[3]);
                    UVs.Add(UVratioTopRightlw_hole);    //UVs.Add(UVRef[1]);
                }
            }
            #endregion

            // int[] tris = new int[shape.Triangles.Count * 3 + (OriginalVertices.Length - 1) * 4 * 3 + 4 * 3];
            int innerTriCount = 0;
            for (int i = 0; i < OriginalInnerVertices.Count; i++)
            {
                innerTriCount += (OriginalInnerVertices[i].Length - 1) * 4 * 3 + 4 * 3;
            }
            int[] tris = new int[shape.Triangles.Count * 3 + (OriginalVertices.Length - 1) * 4 * 3 + 4 * 3 + innerTriCount];
            for (int i = 0; i < tris.Length; i++)
            {
                tris[i] = i;
            }

            gameObject.position = CoordinateConvertor.ChangePivot(ref vertices, CoordinateConvertor.PivotLocation.ZeroBottomCenter);
            gameObject.mesh     = Rebuild(vertices.ToArray(), tris, UVs.ToArray());
            gameObject.material = new Material(MaterialName);

            return(gameObject);
        }
示例#15
0
        public void PreparePolygons(float[] flattenPolygonXYs, int[] contourEndIndices, List <Poly2Tri.Polygon> outputPolygons)
        {
            _waitingHoles.Clear();
            _flattenContours.Clear();
            _otherPolygons.Clear();

            //
            SeparateToFlattenContourList(flattenPolygonXYs, contourEndIndices, _flattenContours);
            //--------------------------
            //TODO: review here, add hole or not
            // more than 1 contours, no hole => eg.  i, j, ;,  etc
            // more than 1 contours, with hole => eg.  a,e ,   etc

            //clockwise => not hole

            int cntCount = _flattenContours.Count;

            Poly2Tri.Polygon mainPolygon = null;
            //
            //this version if it is a hole=> we add it to main polygon
            //TODO: add to more proper polygon ***
            //eg i
            //--------------------------

            for (int n = 0; n < cntCount; ++n)
            {
                FlattenContour cnt = _flattenContours[n];

                bool cntIsMainPolygon = YAxisPointDown ? !cnt.IsClockwise : cnt.IsClockwise;

                if (cntIsMainPolygon)
                {
                    //main polygon
                    //not a hole
                    if (mainPolygon == null)
                    {
                        //if we don't have mainPolygon before
                        //this is main polygon
                        mainPolygon = CreatePolygon(cnt);

                        if (_waitingHoles.Count > 0)
                        {
                            //flush all waiting holes to the main polygon
                            int j = _waitingHoles.Count;
                            for (int i = 0; i < j; ++i)
                            {
                                mainPolygon.AddHole(_waitingHoles[i]);
                            }
                            _waitingHoles.Clear();
                        }
                    }
                    else
                    {
                        //if we already have a main polygon
                        //then this is another sub polygon
                        //IsHole is correct after we Analyze() the glyph contour
                        _otherPolygons.Add(CreatePolygon(cnt));
                    }
                }
                else
                {
                    //this is a hole
                    Poly2Tri.Polygon subPolygon = CreatePolygon(cnt);
                    if (mainPolygon == null)
                    {
                        //add to waiting polygon
                        _waitingHoles.Add(subPolygon);
                    }
                    else
                    {
                        //add to mainPolygon
                        mainPolygon.AddHole(subPolygon);
                    }
                }
            }
            if (_waitingHoles.Count > 0)
            {
                throw new NotSupportedException();
            }

            outputPolygons.Add(mainPolygon);
            if (_otherPolygons.Count > 0)
            {
                outputPolygons.AddRange(_otherPolygons);
            }


            _waitingHoles.Clear();
            _flattenContours.Clear();
            _otherPolygons.Clear();
        }
示例#16
0
        //-------
        public void Triangulate <T>(IList <T> contours, List <Poly2Tri.Polygon> outputPolygons)
            where T : IContour
        {
            _waitingHoles.Clear();
            _flattenContours.Clear();

            //--------------------------
            //TODO: review here, add hole or not
            // more than 1 contours, no hole => eg.  i, j, ;,  etc
            // more than 1 contours, with hole => eg.  a,e ,   etc

            //clockwise => not hole

            int cntCount = contours.Count;

            Poly2Tri.Polygon mainPolygon = null;
            //
            //this version if it is a hole=> we add it to main polygon
            //TODO: add to more proper polygon ***
            //eg i
            //--------------------------
            List <Poly2Tri.Polygon> otherPolygons = null;

            for (int n = 0; n < cntCount; ++n)
            {
                IContour cnt = contours[n];

                bool cntIsMainPolygon = cnt.IsClockwise;

                //if (yAxisFlipped)
                //{
                //    cntIsMainPolygon = !cntIsMainPolygon;
                //}

                if (cntIsMainPolygon)
                {
                    //main polygon
                    //not a hole
                    if (mainPolygon == null)
                    {
                        //if we don't have mainPolygon before
                        //this is main polygon
                        mainPolygon = CreatePolygon(cnt);

                        if (_waitingHoles.Count > 0)
                        {
                            //flush all waiting holes to the main polygon
                            int j = _waitingHoles.Count;
                            for (int i = 0; i < j; ++i)
                            {
                                mainPolygon.AddHole(_waitingHoles[i]);
                            }
                            _waitingHoles.Clear();
                        }
                    }
                    else
                    {
                        //if we already have a main polygon
                        //then this is another sub polygon
                        //IsHole is correct after we Analyze() the glyph contour
                        Poly2Tri.Polygon subPolygon = CreatePolygon(cnt);
                        if (otherPolygons == null)
                        {
                            otherPolygons = new List <Poly2Tri.Polygon>();
                        }
                        otherPolygons.Add(subPolygon);
                    }
                }
                else
                {
                    //this is a hole
                    Poly2Tri.Polygon subPolygon = CreatePolygon(cnt);
                    if (mainPolygon == null)
                    {
                        //add to waiting polygon
                        _waitingHoles.Add(subPolygon);
                    }
                    else
                    {
                        //add to mainPolygon
                        mainPolygon.AddHole(subPolygon);
                    }
                }
            }
            if (_waitingHoles.Count > 0)
            {
                throw new NotSupportedException();
            }
            //------------------------------------------
            //2. tri angulate
            Poly2Tri.P2T.Triangulate(mainPolygon); //that poly is triangulated
            outputPolygons.Add(mainPolygon);

            if (otherPolygons != null)
            {
                outputPolygons.AddRange(otherPolygons);
                for (int i = otherPolygons.Count - 1; i >= 0; --i)
                {
                    Poly2Tri.P2T.Triangulate(otherPolygons[i]);
                }
            }
            //------------------------------------------
            _waitingHoles.Clear();
            _flattenContours.Clear();
        }
示例#17
0
        /// <summary>
        /// create polygon from flatten curve outline point
        /// </summary>
        /// <param name="cnt"></param>
        /// <returns></returns>
        static Poly2Tri.Polygon CreatePolygon2(GlyphContour cnt)
        {
            List <Poly2Tri.TriangulationPoint> points = new List <Poly2Tri.TriangulationPoint>();
            List <GlyphPart> allParts = cnt.parts;
            //---------------------------------------
            //merge all generated points
            //also remove duplicated point too!
            List <GlyphPoint2D> mergedPoints = new List <GlyphPoint2D>();

            cnt.mergedPoints = mergedPoints;
            //---------------------------------------
            {
                int tt = 0;
                int j  = allParts.Count;

                for (int i = 0; i < j; ++i)
                {
                    GlyphPart p = allParts[i];

                    List <GlyphPoint2D> fpoints = p.GetFlattenPoints();
                    if (tt == 0)
                    {
                        int n = fpoints.Count;
                        for (int m = 0; m < n; ++m)
                        {
                            //GlyphPoint2D fp = fpoints[m];
                            mergedPoints.Add(fpoints[m]);
                            //allPoints.Add((float)fp.x);
                            //allPoints.Add((float)fp.y);
                        }
                        tt++;
                    }
                    else
                    {
                        //except first point
                        int n = fpoints.Count;
                        for (int m = 1; m < n; ++m)
                        {
                            //GlyphPoint2D fp = fpoints[m];
                            mergedPoints.Add(fpoints[m]);
                            //allPoints.Add((float)fp.x);
                            //allPoints.Add((float)fp.y);
                        }
                    }
                }
            }
            //---------------------------------------
            {
                //check last (x,y) and first (x,y)
                int lim = mergedPoints.Count - 1;
                {
                    if (mergedPoints[lim].IsEqualValues(mergedPoints[0]))
                    {
                        //remove last (x,y)
                        mergedPoints.RemoveAt(lim);
                        lim -= 1;
                    }
                }

                //limitation: poly tri not accept duplicated points!
                double prevX = 0;
                double prevY = 0;
                Dictionary <TmpPoint, bool> tmpPoints = new Dictionary <TmpPoint, bool>();
                lim = mergedPoints.Count;

                for (int i = 0; i < lim; ++i)
                {
                    GlyphPoint2D p = mergedPoints[i];
                    double       x = p.x;
                    double       y = p.y;

                    if (x == prevX && y == prevY)
                    {
                        if (i > 0)
                        {
                            throw new NotSupportedException();
                        }
                    }
                    else
                    {
                        TmpPoint tmp_point = new TmpPoint(x, y);
                        if (!tmpPoints.ContainsKey(tmp_point))
                        {
                            //ensure no duplicated point
                            tmpPoints.Add(tmp_point, true);
                            var userTriangulationPoint = new Poly2Tri.TriangulationPoint(x, y)
                            {
                                userData = p
                            };
                            p.triangulationPoint = userTriangulationPoint;
                            points.Add(userTriangulationPoint);
                        }
                        else
                        {
                            throw new NotSupportedException();
                        }

                        prevX = x;
                        prevY = y;
                    }
                }

                Poly2Tri.Polygon polygon = new Poly2Tri.Polygon(points.ToArray());
                return(polygon);
            }
        }
示例#18
0
        /// <summary>
        /// triangulate polygon using Poly2Tri library
        /// http://code.google.com/p/poly2tri/
        /// </summary>
        /// <returns>index list of triangle points</returns>
        public List<int> Triangulate()
        {
            var p2tPoints = new List<Poly2Tri.PolygonPoint>(Points.Length);

            foreach (var point in Points)
            {
                p2tPoints.Add(new Poly2Tri.PolygonPoint(point.x, point.y));
            }

            // create p2t polygon
            var p2tPolygon = new Poly2Tri.Polygon(p2tPoints);

            // add holes
            foreach (var polygonHole in holes)
            {
                var p2tHolePoints = new List<Poly2Tri.PolygonPoint>(polygonHole.Points.Length);

                foreach (var polygonPoint in polygonHole.Points)
                {
                    p2tHolePoints.Add(new Poly2Tri.PolygonPoint(polygonPoint.x, polygonPoint.y));
                }

                p2tPolygon.AddHole(new Poly2Tri.Polygon(p2tHolePoints));
            }

            Poly2Tri.P2T.Triangulate(p2tPolygon);

            var triangles = p2tPolygon.Triangles.Count;

            var indices = new List<int>(triangles*3);
            Points = new Vector2[triangles*3];
            var j = 0;

            for (int i = 0; i < triangles; i++)
            {
                indices.Add((j + 0));
                indices.Add((j + 1));
                indices.Add((j + 2));

                Points[j + 2].x = (float)p2tPolygon.Triangles[i].Points._0.X;
                Points[j + 2].y = (float)p2tPolygon.Triangles[i].Points._0.Y;

                Points[j + 1].x = (float)p2tPolygon.Triangles[i].Points._1.X;
                Points[j + 1].y = (float)p2tPolygon.Triangles[i].Points._1.Y;

                Points[j + 0].x = (float)p2tPolygon.Triangles[i].Points._2.X;
                Points[j + 0].y = (float)p2tPolygon.Triangles[i].Points._2.Y;

                j += 3;
            }

            return indices;
        }
示例#19
0
文件: Triangulate.cs 项目: wHo2/TMC
        static void TriangulateConstrainedDelaunay( List<List<Vector3>> listlistPointsConstrainedDelaunay, List<List<int>> listlistHashValuesConstrainedDelaunay, bool bForceVertexSoup, FracturedObject fracturedComponent,
                                                    bool bConnectivityPostprocess, MeshFaceConnectivity faceConnectivityPos, MeshFaceConnectivity faceConnectivityNeg, MeshDataConnectivity meshConnectivityPos, MeshDataConnectivity meshConnectivityNeg, int nForceMeshConnectivityHash,
                                                    int nSplitCloseSubMesh, Matrix4x4 mtxPlane, Matrix4x4 mtxToLocalPos, Matrix4x4 mtxToLocalNeg, Vector3 v3CenterPos, Vector3 v3CenterNeg,
                                                    List<int>[] aListIndicesPosInOut, List<VertexData> listVertexDataPosInOut, List<int>[] aListIndicesNegInOut, List<VertexData> listVertexDataNegInOut)
        {
            // Pass to two dimensional plane:

            Matrix4x4 mtxPlaneInverse = mtxPlane.inverse;
            List<List<Poly2Tri.Point2D>>      listlistCapPoints        = new List<List<Poly2Tri.Point2D>>();
            List<List<Poly2Tri.PolygonPoint>> listlistCapPolygonPoints = new List<List<Poly2Tri.PolygonPoint>>();
            List<Poly2Tri.Polygon>            listCapPolygons          = new List<Poly2Tri.Polygon>();

            for(int i = 0; i < listlistPointsConstrainedDelaunay.Count; i++)
            {
                List<Poly2Tri.Point2D>      listCapPoints         = new List<Poly2Tri.Point2D>();
                List<Poly2Tri.PolygonPoint> listCapPolygonsPoints = new List<Poly2Tri.PolygonPoint>();

                foreach(Vector3 v3Vertex in listlistPointsConstrainedDelaunay[i])
                {
                    Vector3 v3VertexInPlane = mtxPlaneInverse.MultiplyPoint3x4(v3Vertex);
                    listCapPoints.Add        (new Poly2Tri.Point2D     (v3VertexInPlane.x, v3VertexInPlane.z));
                    listCapPolygonsPoints.Add(new Poly2Tri.PolygonPoint(v3VertexInPlane.x, v3VertexInPlane.z));
                }

                listlistCapPoints.Add(listCapPoints);
                listlistCapPolygonPoints.Add(listCapPolygonsPoints);
                listCapPolygons.Add(new Poly2Tri.Polygon(listCapPolygonsPoints));
            }

            // Remove close vertices

            float fPrecisionFix = Mathf.Max(Parameters.EPSILONCAPPRECISIONMIN, fracturedComponent.CapPrecisionFix);

            if(fPrecisionFix > 0.0f)
            {
                for(int nCap = 0; nCap < listlistCapPolygonPoints.Count; nCap++)
                {
                    double lastX = listlistCapPolygonPoints[nCap][listlistCapPolygonPoints[nCap].Count - 1].X;
                    double lastY = listlistCapPolygonPoints[nCap][listlistCapPolygonPoints[nCap].Count - 1].Y;

                    bool bDeleteCap = false;

                    for(int nVertex = 0; nVertex < listlistCapPolygonPoints[nCap].Count; nVertex++)
                    {
                        double vecX = listlistCapPolygonPoints[nCap][nVertex].X - lastX;
                        double vecY = listlistCapPolygonPoints[nCap][nVertex].Y - lastY;

                        if(System.Math.Sqrt(vecX * vecX + vecY * vecY) < fPrecisionFix)
                        {
                            listlistCapPolygonPoints[nCap].RemoveAt(nVertex);
                            nVertex--;

                            if(listlistCapPolygonPoints[nCap].Count < 3)
                            {
                                bDeleteCap = true;
                                break;
                            }
                        }
                        else
                        {
                            lastX = listlistCapPolygonPoints[nCap][nVertex].X;
                            lastY = listlistCapPolygonPoints[nCap][nVertex].Y;
                        }
                    }

                    if(bDeleteCap)
                    {
                        listlistCapPolygonPoints.RemoveAt(nCap);
                        nCap--;
                    }
                }
            }

            if(listlistCapPolygonPoints.Count == 0)
            {
                return;
            }

            // Search if one of the caps is contained in the other. If this happens we will mark the big one as the polygon and the rest as holes

            int nSuperPolygon = -1;
            Poly2Tri.Polygon polygonContainer = null;

            if(bForceVertexSoup == false)
            {
                for(int i = 0; i < listlistCapPolygonPoints.Count; i++)
                {
                    for(int j = 0; j < listlistCapPolygonPoints.Count; j++)
                    {
                        if(i != j && listlistCapPoints[i].Count >= 3 && listlistCapPoints[j].Count >= 3)
                        {
                            if(Poly2Tri.PolygonUtil.PolygonContainsPolygon(listlistCapPoints[i], listCapPolygons[i].Bounds, listlistCapPoints[j], listCapPolygons[j].Bounds, true))
                            {
                                nSuperPolygon = i;
                                break;
                            }
                            else if(Poly2Tri.PolygonUtil.PolygonContainsPolygon(listlistCapPoints[j], listCapPolygons[j].Bounds, listlistCapPoints[i], listCapPolygons[i].Bounds, true))
                            {
                                nSuperPolygon = j;
                                break;
                            }
                        }
                    }
                }

                // Add holes if this is a cap with holes

                if(nSuperPolygon != -1)
                {
                    polygonContainer = listCapPolygons[nSuperPolygon];

                    for(int i = 0; i < listlistCapPolygonPoints.Count; i++)
                    {
                        if(i != nSuperPolygon && listCapPolygons[i].Count >= 3)
                        {
                            polygonContainer.AddHole(listCapPolygons[i]);
                        }
                    }
                }
            }

            // Triangulate

            bool bTriangulatedWithHoles = false;

            if(polygonContainer != null && bForceVertexSoup == false)
            {
                // Polygon with holes

                try
                {
                    Poly2Tri.P2T.Triangulate(polygonContainer);

                    if(polygonContainer.Triangles != null)
                    {
                        List<Vector3> listMeshVertices = new List<Vector3>();
                        List<int>     listMeshIndices  = new List<int>();

                        CreateIndexedMesh(polygonContainer.Triangles, listMeshVertices, listMeshIndices, mtxPlane, true);

                        Triangulate(    listMeshVertices, listMeshIndices, fracturedComponent, listlistPointsConstrainedDelaunay, listlistHashValuesConstrainedDelaunay,
                                        bConnectivityPostprocess, faceConnectivityPos, faceConnectivityNeg, meshConnectivityPos, meshConnectivityNeg, nForceMeshConnectivityHash,
                                        nSplitCloseSubMesh, mtxPlane, mtxToLocalPos, mtxToLocalNeg, v3CenterPos, v3CenterNeg,
                                        aListIndicesPosInOut, listVertexDataPosInOut, aListIndicesNegInOut, listVertexDataNegInOut);
                    }

                    bTriangulatedWithHoles = true;
                }
                catch(System.Exception e)
                {
                    if(fracturedComponent.Verbose) Debug.LogWarning("Exception (" + e.GetType() + ") using hole triangulation (holes = " + listlistCapPolygonPoints.Count + "). Trying to use constrained delaunay.");
                    bTriangulatedWithHoles = false;
                }
            }

            if(bTriangulatedWithHoles == false)
            {
                if(bForceVertexSoup)
                {
                    // Vertex soup

                    List<Poly2Tri.TriangulationPoint> listPoints = new List<Poly2Tri.TriangulationPoint>();

                    if(listlistCapPolygonPoints.Count > 0)
                    {
                        foreach(Poly2Tri.PolygonPoint polyPoint in listlistCapPolygonPoints[0])
                        {
                            listPoints.Add(polyPoint);
                        }

                        try
                        {
                            if(listPoints.Count >= 3)
                            {
                                Poly2Tri.PointSet ps = new Poly2Tri.PointSet(listPoints);
                                Poly2Tri.P2T.Triangulate(ps);

                                if(ps.Triangles != null)
                                {
                                    List<Vector3> listMeshVertices = new List<Vector3>();
                                    List<int>     listMeshIndices  = new List<int>();

                                    CreateIndexedMesh(ps.Triangles, listMeshVertices, listMeshIndices, mtxPlane, true);

                                    Triangulate(    listMeshVertices, listMeshIndices, fracturedComponent, listlistPointsConstrainedDelaunay, listlistHashValuesConstrainedDelaunay,
                                                    bConnectivityPostprocess, faceConnectivityPos, faceConnectivityNeg, meshConnectivityPos, meshConnectivityNeg, nForceMeshConnectivityHash,
                                                    nSplitCloseSubMesh, mtxPlane, mtxToLocalPos, mtxToLocalNeg, v3CenterPos, v3CenterNeg,
                                                    aListIndicesPosInOut, listVertexDataPosInOut, aListIndicesNegInOut, listVertexDataNegInOut);
                                }
                            }
                        }
                        catch(System.Exception e)
                        {
                            if(fracturedComponent.Verbose) Debug.LogWarning("Exception (" + e.GetType() + ") using vertex soup triangulation.");
                        }
                    }
                }
                else
                {
                    // Use constrained delaunay triangulation

                    int nPoly = 0;

                    foreach(List<Poly2Tri.PolygonPoint> listPolyPoints in listlistCapPolygonPoints)
                    {
                        IList<Poly2Tri.DelaunayTriangle> listTriangles = null;

                        Poly2Tri.Polygon polygon = null;

                        try
                        {
                            if(listPolyPoints.Count >= 3)
                            {
                                polygon = new Poly2Tri.Polygon(listPolyPoints);
                                Poly2Tri.P2T.Triangulate(polygon);
                                listTriangles = polygon.Triangles;
                            }
                        }
                        catch(System.Exception e)
                        {
                            if(fracturedComponent.Verbose) Debug.LogWarning("Exception (" + e.GetType() + ") using polygon triangulation of cap polygon " + nPoly + ". Trying to use non constrained");
                            listTriangles = null;
                        }

                        if(listTriangles == null)
                        {
                            List<Poly2Tri.TriangulationPoint> listPoints = new List<Poly2Tri.TriangulationPoint>();

                            foreach(Poly2Tri.PolygonPoint polyPoint in listPolyPoints)
                            {
                                listPoints.Add(polyPoint);
                            }

                            try
                            {
                                if(listPoints.Count >= 3)
                                {
                                    Poly2Tri.PointSet ps = new Poly2Tri.PointSet(listPoints);
                                    Poly2Tri.P2T.Triangulate(ps);
                                    listTriangles = ps.Triangles;
                                }
                            }
                            catch(System.Exception e)
                            {
                                if(fracturedComponent.Verbose) Debug.LogWarning("Exception (" + e.GetType() + ") using non constrained triangulation of cap polygon " + nPoly + ". Skipping");
                            }
                        }

                        if(listTriangles != null)
                        {
                            List<Vector3> listMeshVertices = new List<Vector3>();
                            List<int>     listMeshIndices  = new List<int>();

                            CreateIndexedMesh(listTriangles, listMeshVertices, listMeshIndices, mtxPlane, true);

                            Triangulate(    listMeshVertices, listMeshIndices, fracturedComponent, listlistPointsConstrainedDelaunay, listlistHashValuesConstrainedDelaunay,
                                            bConnectivityPostprocess, faceConnectivityPos, faceConnectivityNeg, meshConnectivityPos, meshConnectivityNeg, nForceMeshConnectivityHash,
                                            nSplitCloseSubMesh, mtxPlane, mtxToLocalPos, mtxToLocalNeg, v3CenterPos, v3CenterNeg,
                                            aListIndicesPosInOut, listVertexDataPosInOut, aListIndicesNegInOut, listVertexDataNegInOut);
                        }

                        nPoly++;
                    }
                }
            }
        }
示例#20
0
		public static List<Poly2Tri.Polygon> GetTriangles(IList<PolygonClosedD2D> polygons)
		{
			var result = new List<Poly2Tri.Polygon>();

			for (int i = 0; i < polygons.Count; ++i)
			{
				if (polygons[i].IsHole)
					continue;

				var mainPolygon = new Poly2Tri.Polygon(polygons[i].Points.Select(pt => new Poly2Tri.PolygonPoint(pt.X, pt.Y)));

				// find all holes in mainPolygon
				for (int j = 0; j < polygons.Count; ++j)
				{
					if (polygons[j].IsHole && object.ReferenceEquals(polygons[j].Parent, polygons[i]))
					{
						var holePolygon = new Poly2Tri.Polygon(polygons[j].Points.Select(pt => new Poly2Tri.PolygonPoint(pt.X, pt.Y)));
						mainPolygon.AddHole(holePolygon);
					}
				}

				result.Add(mainPolygon);
			}

			foreach (var p in result)
			{
				Poly2Tri.P2T.Triangulate(p);
			}

			return result;
		}
示例#21
0
        public static GameObject OSMtoGameObject2(string OSMid, Vector3 MinPointOnMap, Bounds bounds, MapProperties properties, string connPostGreSql, OSMShape shape = OSMShape.Way)
        {
            if (rand == null)
            {
                rand = new Random((int)DateTime.Now.Ticks);
            }
            if (properties == null)
            {
                properties = Properties;
            }
            var   minmaxX       = properties.minMaxX;
            var   minmaxY       = properties.minMaxY;
            int   direction     = -1;
            float LineWidth     = properties.RoadLineThickness;
            float BuildingWidth = properties.BuildingLineThickness;
            float height        = properties.BuildingHeight;

            if (height < 4)
            {
                height = 4;
            }
            var FirstWay = OSMid;

            if (shape == OSMShape.Way)
            {
                var            w = new Way(FirstWay);
                List <OsmNode> WayNodes;
                List <Tag>     WayTags;
                using (Npgsql.NpgsqlConnection con = new Npgsql.NpgsqlConnection(connPostGreSql))
                {
                    con.Open();
                    WayNodes = w.GetNodesPostgreSQL(FirstWay, con);
                    WayTags  = w.GetTagsPostgreSQL(FirstWay, con);
                    con.Close();
                }
                if (WayTags.Where(i => i.KeyValueSQL[0].ToLower() == "landuse" || i.KeyValueSQL[0].ToLower() == "building" || i.KeyValueSQL[0].ToLower() == "highway").Count() != 0)
                {
                    var tempPoints = new Vector3[WayNodes.Count];

                    int counter = 0;
                    foreach (var node in WayNodes)
                    {
                        var result = CoordinateConvertor.SimpleInterpolation((float)node.PositionSQL.Lat, (float)node.PositionSQL.Lon, bounds, minmaxX, minmaxY);
                        // Testing the correct direction
                        tempPoints[counter] = new Vector3(direction * (float)result[0], 0, (float)result[1]) - MinPointOnMap;
                        counter++;
                    }
                    WayNodes = null;
                    var building    = WayTags.Where(i => i.KeyValueSQL[0].ToLower() == "building");
                    var highwayType = WayTags.Where(i => i.KeyValueSQL[0].ToLower() == "highway");
                    WayTags = null;
                    if (building.Count() != 0)
                    {
                        #region Buildings
                        // Check if it has overlapping start and ending points.
                        // NOTE: Replaced with the code to remove all the duplicates, not only the endpoints.
                        // Checking for duplicates:
                        tempPoints = tempPoints.ToArray().RemoveDuplicates();
                        var Skip = false;
                        if (tempPoints.Length <= 2)
                        {
                            // Buildings that are too small to show such as 76844368
                            // http://www.openstreetmap.org/browse/way/76844368
                            // "A weird building were found and ignored. FirstWay \nRelated url: http://www.openstreetmap.org/browse/way/{0}"
                            Skip = true; // continue;
                        }
                        if (!Skip)
                        {
                            var p2d = tempPoints.ToCPoint2D();
                            // TODO bug in the cpolygon, probably duplicates
                            var shp = new PolygonCuttingEar.CPolygonShape(p2d);
                            shp.CutEar();
                            p2d = null;
                            GC.Collect();
                            // TODO:
                            var randHeight         = CoordinateConvertor.linear((float)rand.NextDouble(), 0, 1, -3f, height);
                            var randMaterial       = (randHeight > height / 2f) ? "BuildingTall" : randHeight < height / 2f ? "Building2" : "Building";
                            var resultedGameObject = shp.GenerateShapeUVedWithWalls_Balanced(
                                CoordinateConvertor.OSMType.Polygon, FirstWay,
                                "Building", "Building", randMaterial,
                                height + randHeight, height + 7, true);
                            return(resultedGameObject);
                        }
                        #endregion
                    }
                    else
                    {
                        if (highwayType.Count() != 0)
                        {
                            #region Roads
                            var hwtype = highwayType.First();
                            //Console.WriteLine("Generating roads..id=" + FirstWay);
                            switch (hwtype.KeyValueSQL[1])
                            {
                            case "cycleway":
                            {
                                var resultedGameObject = CoordinateConvertor.MeshGenerationFilledCorners(tempPoints.ToSegmentedPoints(2f), properties.CyclewayWidth, CoordinateConvertor.OSMType.Line, FirstWay, hwtype.KeyValueSQL[1], "Line", properties.CycleWayMaterial.Name, -0.01f);
                                // ObjFormat.MeshToFile(resultedGameObject,System.IO.Path.Combine( exportPath , resultedGameObject.Name.Replace("|", "-") + ".obj"));

                                return(resultedGameObject);
                            }

                            case "footway":
                            case "path":
                            case "pedestrian":
                            {
                                var resultedGameObject = CoordinateConvertor.MeshGenerationFilledCorners(tempPoints.ToSegmentedPoints(4f), properties.FootwayWidth, CoordinateConvertor.OSMType.Line, FirstWay, hwtype.KeyValueSQL[1], "Line", properties.FootWayMaterial.Name, -0.01f);
                                // ObjFormat.MeshToFile(resultedGameObject,System.IO.Path.Combine( exportPath , resultedGameObject.Name.Replace("|", "-") + ".obj"));
                                return(resultedGameObject);
                            }

                            case "steps":
                            {
                                var resultedGameObject = CoordinateConvertor.MeshGenerationFilledCorners(tempPoints.ToSegmentedPoints(4f), properties.CyclewayWidth, CoordinateConvertor.OSMType.Line, FirstWay, hwtype.KeyValueSQL[1], "Line", properties.StepsMaterial.Name, -0.01f);
                                return(resultedGameObject);
                            }

                            // Miguel R.C. commented these lines.
                            // Reason: Why breaking in the case "motorway"? That results in some roads missing when generating scenarios.
                            // With these lines commented, the motorways will be generated in the default case.
                            //case "motorway":
                            //    {
                            //        break;
                            //    }

                            default:
                            {
                                var resultedGameObject = CoordinateConvertor.MeshGenerationFilledCorners(tempPoints.ToSegmentedPoints(0.5f), properties.RoadWidth, CoordinateConvertor.OSMType.Line, FirstWay, hwtype.KeyValueSQL[1], "Line", properties.RoadMaterial.Name, 0f);

                                return(resultedGameObject);
                            }
                            }
                            #endregion
                        }
                    }
                }
            }
            else if (shape == OSMShape.Relation) // It is probably a multi-polygon building defined in a relation.
            {
                List <OsmNode[]> OuterNodes;
                List <OsmNode>   OuterWay;
                List <OsmNode[]> InnerNodes;
                List <Tag>       tags;
                Relation         r = new Relation(FirstWay);
                Way w = new Way();
                using (Npgsql.NpgsqlConnection con = new Npgsql.NpgsqlConnection(connPostGreSql))
                {
                    con.Open();

                    tags = r.GetTagsPostgreSQL(con);
                    var isMultiPolygon = tags.Exists(t => t.KeyValueSQL[0] == "type" && t.KeyValueSQL[1] == "multipolygon");
                    if (isMultiPolygon)
                    {
                        var Members = r.GetMembersPostgreSQLByType(r.id, 1, con);

                        OuterNodes = Members
                                     .Where(m => m.Role.ToLower() == Member.RoleOuter)
                                     .OrderBy(o => o.order)
                                     .Select(m => w.GetNodesPostgreSQL(m.ReferenceId, connPostGreSql).ToArray()).ToList();
                        InnerNodes = Members
                                     .Where(m => m.Role.ToLower() == Member.RoleInner)
                                     .OrderBy(o => o.order)
                                     .Select(m => w.GetNodesPostgreSQL(m.ReferenceId, connPostGreSql).ToArray()).ToList();


                        OuterWay = new List <OsmNode>();
                        foreach (var nodelist in OuterNodes)
                        {
                            OuterWay.AddRange(nodelist);
                        }


                        var tempPointsOuterPoints = new Vector3[OuterWay.Count];
                        int counter = 0;
                        foreach (var node in OuterWay)
                        {
                            var result = CoordinateConvertor.SimpleInterpolation((float)node.PositionSQL.Lat, (float)node.PositionSQL.Lon, bounds, minmaxX, minmaxY);
                            // Testing the correct direction
                            tempPointsOuterPoints[counter] = new Vector3(direction * (float)result[0], 0, (float)result[1]) - MinPointOnMap;
                            counter++;
                        }

                        List <Vector3[]> holes = new List <Vector3[]>();
                        for (int i = 0; i < InnerNodes.Count; i++)
                        {
                            holes.Add(new Vector3[InnerNodes[i].Length]);

                            for (int j = 0; j < InnerNodes[i].Length; j++)
                            {
                                var result = CoordinateConvertor.SimpleInterpolation((float)InnerNodes[i][j].PositionSQL.Lat, (float)InnerNodes[i][j].PositionSQL.Lon, bounds, minmaxX, minmaxY);
                                // Testing the correct direction
                                holes[i][j] = new Vector3(direction * (float)result[0], 0, (float)result[1]) - MinPointOnMap;
                            }
                        }


                        var outerpolypoints   = tempPointsOuterPoints.Select(s => new Poly2Tri.PolygonPoint(s.x, s.z));
                        Poly2Tri.Polygon poly = new Poly2Tri.Polygon(outerpolypoints);
                        // TODO: poly.IsPointInside() check the holes against all pieces

                        var innerspolypoints = new List <Poly2Tri.PolygonPoint[]>();
                        for (int i = 0; i < holes.Count; i++)
                        {
                            var currentInner = holes[i].Select(s => new Poly2Tri.PolygonPoint(s.x, s.z)).ToArray();
                            innerspolypoints.Add(currentInner);
                            poly.AddHole(new Poly2Tri.Polygon(currentInner));
                        }
                        Poly2Tri.P2T.Triangulate(poly);

                        var randHeight         = CoordinateConvertor.linear((float)rand.NextDouble(), 0, 1, -3f, height);
                        var randMaterial       = (randHeight > height / 2f) ? "BuildingTall" : randHeight < height / 2f ? "Building2" : "Building";
                        var resultedGameObject = poly.GenerateShapeUVedWithWalls_Balanced(
                            CoordinateConvertor.OSMType.Relation, FirstWay,
                            "Building", "Building", randMaterial,
                            height + randHeight, height + 7, true);
                        return(resultedGameObject);
                    }
                    con.Close();
                }
            }
            return(null);
        }