예제 #1
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);
        }
예제 #2
0
        void DrawSimpleRectWithHoleExample(Painter painter)
        {
            Poly2Tri.TriangulationPoint[] box = new Poly2Tri.TriangulationPoint[]
            {
                new Poly2Tri.TriangulationPoint(5, 5),
                new Poly2Tri.TriangulationPoint(45, 5),
                new Poly2Tri.TriangulationPoint(45, 45),
                new Poly2Tri.TriangulationPoint(5, 45)
            };

            Poly2Tri.TriangulationPoint[] hole = 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(box);
            polygon.AddHole(new Poly2Tri.Polygon(hole));

            Poly2Tri.P2T.Triangulate(polygon);


            painter.StrokeColor = Color.Black;

            DrawPoly2TriPolygon(painter, new List <Poly2Tri.Polygon>()
            {
                polygon
            });
        }
예제 #3
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);
        }
예제 #4
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);
        }
예제 #5
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
                });
            }
        }
예제 #6
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;
		}
예제 #7
0
        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);
        }
예제 #8
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;
        }
예제 #9
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);
        }
예제 #10
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();
        }
예제 #11
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();
        }
예제 #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++;
                    }
                }
            }
        }
        /// <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)));
        }
예제 #14
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);
        }