private void MeshCleanReq( DelaunayTriangle triangle ) {
			if (triangle != null && !triangle.IsInterior) {
				triangle.IsInterior = true;
				Triangulatable.AddTriangle(triangle);

				for (int i = 0; i < 3; i++)
				if (!triangle.EdgeIsConstrained[i])
				{
					MeshCleanReq(triangle.Neighbors[i]);
				}
			}
		}
		public void RemoveFromList( DelaunayTriangle triangle ) {
			Triangles.Remove(triangle);
			// TODO: remove all neighbor pointers to this triangle
			//        for( int i=0; i<3; i++ )
			//        {
			//            if( triangle.neighbors[i] != null )
			//            {
			//                triangle.neighbors[i].clearNeighbor( triangle );
			//            }
			//        }
			//        triangle.clearNeighbors();
		}
Пример #3
0
 public void MeshClean(DelaunayTriangle triangle)
 {
     MeshCleanReq(triangle);
 }
Пример #4
0
        private static void FlipEdgeEvent(DTSweepContext tcx, TriangulationPoint ep, TriangulationPoint eq,
                                          DelaunayTriangle t, TriangulationPoint p)
        {
            TriangulationPoint op, newP;
            DelaunayTriangle ot;
            bool inScanArea;

            ot = t.NeighborAcross(p);
            op = ot.OppositePoint(t, p);

            if (ot == null)
            {
                // If we want to integrate the fillEdgeEvent do it here
                // With current implementation we should never get here
                throw new InvalidOperationException("[BUG:FIXME] FLIP failed due to missing triangle");
            }

            inScanArea = TriangulationUtil.InScanArea(p, t.PointCCW(p), t.PointCW(p), op);
            if (inScanArea)
            {
                // Lets rotate shared edge one vertex CW
                RotateTrianglePair(t, p, ot, op);
                tcx.MapTriangleToNodes(t);
                tcx.MapTriangleToNodes(ot);

                if (p == eq && op == ep)
                {
                    if (eq == tcx.EdgeEvent.ConstrainedEdge.Q
                        && ep == tcx.EdgeEvent.ConstrainedEdge.P)
                    {
                        if (tcx.IsDebugEnabled)
                        {
            #if NETFX_CORE
                            Debug.WriteLine("[FLIP] - constrained edge done");
            #else
                            Console.WriteLine("[FLIP] - constrained edge done"); // TODO: remove
            #endif
                        }
                        t.MarkConstrainedEdge(ep, eq);
                        ot.MarkConstrainedEdge(ep, eq);
                        Legalize(tcx, t);
                        Legalize(tcx, ot);
                    }
                    else
                    {
                        if (tcx.IsDebugEnabled)
            #if NETFX_CORE
                          Debug.WriteLine("[FLIP] - subedge done"); // TODO: remove
            #else
                         Console.WriteLine("[FLIP] - subedge done"); // TODO: remove
            #endif
                        // XXX: I think one of the triangles should be legalized here?
                    }
                }
                else
                {
                    if (tcx.IsDebugEnabled)
            #if NETFX_CORE
                        Debug.WriteLine("[FLIP] - flipping and continuing with triangle still crossing edge"); // TODO: remove
            #else
                         Console.WriteLine("[FLIP] - flipping and continuing with triangle still crossing edge"); // TODO: remove
            #endif
                            // TODO: remove
                    Orientation o = TriangulationUtil.Orient2d(eq, op, ep);
                    t = NextFlipTriangle(tcx, o, t, ot, p, op);
                    FlipEdgeEvent(tcx, ep, eq, t, p);
                }
            }
            else
            {
                newP = NextFlipPoint(ep, eq, ot, op);
                FlipScanEdgeEvent(tcx, ep, eq, t, ot, newP);
                EdgeEvent(tcx, ep, eq, t, p);
            }
        }
Пример #5
0
        /// <summary>
        /// After a flip we have two triangles and know that only one will still be
        /// intersecting the edge. So decide which to contiune with and legalize the other
        /// </summary>
        /// <param name="tcx"></param>
        /// <param name="o">should be the result of an TriangulationUtil.orient2d( eq, op, ep )</param>
        /// <param name="t">triangle 1</param>
        /// <param name="ot">triangle 2</param>
        /// <param name="p">a point shared by both triangles</param>
        /// <param name="op">another point shared by both triangles</param>
        /// <returns>returns the triangle still intersecting the edge</returns>
        private static DelaunayTriangle NextFlipTriangle(DTSweepContext tcx, Orientation o, DelaunayTriangle t, DelaunayTriangle ot, TriangulationPoint p, TriangulationPoint op)
        {
            int edgeIndex;

            if (o == Orientation.CCW)
            {
                // ot is not crossing edge after flip
                edgeIndex = ot.EdgeIndex(p, op);
                ot.EdgeIsDelaunay[edgeIndex] = true;
                Legalize(tcx, ot);
                ot.EdgeIsDelaunay.Clear();
                return(t);
            }
            // t is not crossing edge after flip
            edgeIndex = t.EdgeIndex(p, op);
            t.EdgeIsDelaunay[edgeIndex] = true;
            Legalize(tcx, t);
            t.EdgeIsDelaunay.Clear();
            return(ot);
        }
Пример #6
0
        /// <summary>
        /// When we need to traverse from one triangle to the next we need
        /// the point in current triangle that is the opposite point to the next
        /// triangle.
        /// </summary>
        private static bool NextFlipPoint(TriangulationPoint ep, TriangulationPoint eq, DelaunayTriangle ot, TriangulationPoint op, out TriangulationPoint newP)
        {
            newP = null;
            Orientation o2d = TriangulationUtil.Orient2d(eq, op, ep);

            switch (o2d)
            {
            case Orientation.CW:
                newP = ot.PointCCWFrom(op);
                return(true);

            case Orientation.CCW:
                newP = ot.PointCWFrom(op);
                return(true);

            case Orientation.Collinear:
                // TODO: implement support for point on constraint edge
                //throw new PointOnEdgeException("Point on constrained edge not supported yet", eq, op, ep);
                return(false);

            default:
                throw new NotImplementedException("Orientation not handled");
            }
        }
Пример #7
0
        /// <summary>
        /// Returns true if triangle was legalized
        /// </summary>
        private static bool Legalize(DTSweepContext tcx, DelaunayTriangle t)
        {
            // To legalize a triangle we start by finding if any of the three edges
            // violate the Delaunay condition
            for (int i = 0; i < 3; i++)
            {
                // TODO: fix so that cEdge is always valid when creating new triangles then we can check it here
                //       instead of below with ot
                if (t.EdgeIsDelaunay[i])
                {
                    continue;
                }

                DelaunayTriangle ot = t.Neighbors[i];
                if (ot != null)
                {
                    TriangulationPoint p = t.Points[i];
                    TriangulationPoint op = ot.OppositePoint(t, p);
                    int oi = ot.IndexOf(op);
                    // If this is a Constrained Edge or a Delaunay Edge(only during recursive legalization)
                    // then we should not try to legalize
                    if (ot.EdgeIsConstrained[oi] || ot.EdgeIsDelaunay[oi])
                    {
                        t.EdgeIsConstrained[i] = ot.EdgeIsConstrained[oi];
                        // XXX: have no good way of setting this property when creating new triangles so lets set it here
                        continue;
                    }

                    bool inside = TriangulationUtil.SmartIncircle(p, t.PointCCW(p), t.PointCW(p), op);

                    if (inside)
                    {
                        // Lets mark this shared edge as Delaunay
                        t.EdgeIsDelaunay[i] = true;
                        ot.EdgeIsDelaunay[oi] = true;

                        // Lets rotate shared edge one vertex CW to legalize it
                        RotateTrianglePair(t, p, ot, op);

                        // We now got one valid Delaunay Edge shared by two triangles
                        // This gives us 4 new edges to check for Delaunay

                        // Make sure that triangle to node mapping is done only one time for a specific triangle
                        bool notLegalized = !Legalize(tcx, t);

                        if (notLegalized)
                        {
                            tcx.MapTriangleToNodes(t);
                        }
                        notLegalized = !Legalize(tcx, ot);
                        if (notLegalized)
                        {
                            tcx.MapTriangleToNodes(ot);
                        }

                        // Reset the Delaunay edges, since they only are valid Delaunay edges
                        // until we add a new triangle or point.
                        // XXX: need to think about this. Can these edges be tried after we
                        //      return to previous recursive level?
                        t.EdgeIsDelaunay[i] = false;
                        ot.EdgeIsDelaunay[oi] = false;

                        // If triangle have been legalized no need to check the other edges since
                        // the recursive legalization will handles those so we can end here.
                        return true;
                    }
                }
            }
            return false;
        }
Пример #8
0
        /// <summary>
        /// Adds a triangle to the advancing front to fill a hole.
        /// </summary>
        /// <param name="tcx"></param>
        /// <param name="node">middle node, that is the bottom of the hole</param>
        private static void Fill(DTSweepContext tcx, AdvancingFrontNode node)
        {
            DelaunayTriangle triangle = new DelaunayTriangle(node.Prev.Point, node.Point, node.Next.Point);
            // TODO: should copy the cEdge value from neighbor triangles
            //       for now cEdge values are copied during the legalize
            triangle.MarkNeighbor(node.Prev.Triangle);
            triangle.MarkNeighbor(node.Triangle);
            tcx.Triangles.Add(triangle);

            // Update the advancing front
            node.Prev.Next = node.Next;
            node.Next.Prev = node.Prev;
            tcx.RemoveNode(node);

            // If it was legalized the triangle has already been mapped
            if (!Legalize(tcx, triangle))
            {
                tcx.MapTriangleToNodes(triangle);
            }
        }
Пример #9
0
        GameObject GenerateCountryRegionSurface(int countryIndex, int regionIndex, Material material, bool drawOutline)
        {
            Country country = countries[countryIndex];
            Region  region  = country.regions [regionIndex];

            Polygon poly = new Polygon(region.latlon);

            double maxTriangleSize = 10.0f;

            if (countryIndex == 6)               // Antarctica
            {
                maxTriangleSize = 9.0f;
            }
            if (Mathf.Abs(region.minMaxLat.x - region.minMaxLat.y) > maxTriangleSize ||
                Mathf.Abs(region.minMaxLon.x - region.minMaxLon.y) > maxTriangleSize)                // special case; needs steiner points to reduce the size of triangles
            {
                double step = maxTriangleSize / 2;
                List <TriangulationPoint> steinerPoints = new List <TriangulationPoint>();
                for (double x = region.minMaxLat.x + step / 2; x < region.minMaxLat.y - step / 2; x += step)
                {
                    for (double y = region.minMaxLon.x + step / 2; y < region.minMaxLon.y - step / 2; y += step)
                    {
                        if (ContainsPoint2D(region.latlon, x, y))
                        {
                            steinerPoints.Add(new TriangulationPoint(x, y));
                        }
                    }
                }
                poly.AddSteinerPoints(steinerPoints);
            }

            P2T.Triangulate(poly);

            int flip1, flip2;

            flip1 = 1; flip2 = 2;
            Vector3[] revisedSurfPoints = new Vector3[poly.Triangles.Count * 3];
            for (int k = 0; k < poly.Triangles.Count; k++)
            {
                DelaunayTriangle dt = poly.Triangles[k];
                revisedSurfPoints[k * 3]         = GetSpherePointFromLatLon2(dt.Points[0].X, dt.Points[0].Y);
                revisedSurfPoints[k * 3 + flip1] = GetSpherePointFromLatLon2(dt.Points[1].X, dt.Points[1].Y);
                revisedSurfPoints[k * 3 + flip2] = GetSpherePointFromLatLon2(dt.Points[2].X, dt.Points[2].Y);
            }
            int revIndex = revisedSurfPoints.Length - 1;

            // Generate surface mesh
            int       cacheIndex    = GetCacheIndexForCountryRegion(countryIndex, regionIndex);
            string    cacheIndexSTR = cacheIndex.ToString();
            Transform t             = surfacesLayer.transform.FindChild(cacheIndexSTR);

            if (t != null)
            {
                DestroyImmediate(t.gameObject);
            }
            GameObject surf = Drawing.CreateSurface(cacheIndexSTR, revisedSurfPoints, revIndex, material);

            surf.transform.SetParent(surfacesLayer.transform, false);
            surf.transform.localPosition = MiscVector.Vector3zero;
            surf.transform.localRotation = Quaternion.Euler(MiscVector.Vector3zero);
            if (surfaces.ContainsKey(cacheIndex))
            {
                surfaces.Remove(cacheIndex);
            }
            surfaces.Add(cacheIndex, surf);

            // draw outline
            if (drawOutline)
            {
                DrawCountryRegionOutline(region, surf);
            }
            return(surf);
        }
Пример #10
0
 public void AddTriangle(DelaunayTriangle t)
 {
     throw new NotImplementedException("PolyHole.AddTriangle should never get called");
 }
Пример #11
0
        private void CutPoly(Int3[] verts, int[] tris, ref Int3[] outVertsArr, ref int[] outTrisArr, out int outVCount, out int outTCount, Int3[] extraShape, Int3 cuttingOffset, Bounds realBounds, TileHandler.CutMode mode = TileHandler.CutMode.CutAll | TileHandler.CutMode.CutDual, int perturbate = -1)
        {
            if (verts.Length == 0 || tris.Length == 0)
            {
                outVCount   = 0;
                outTCount   = 0;
                outTrisArr  = new int[0];
                outVertsArr = new Int3[0];
                return;
            }
            if (perturbate > 10)
            {
                Debug.LogError("Too many perturbations aborting.\nThis may cause a tile in the navmesh to become empty. Try to see see if any of your NavmeshCut or NavmeshAdd components use invalid custom meshes.");
                outVCount   = verts.Length;
                outTCount   = tris.Length;
                outTrisArr  = tris;
                outVertsArr = verts;
                return;
            }
            List <IntPoint> list = null;

            if (extraShape == null && (mode & TileHandler.CutMode.CutExtra) != (TileHandler.CutMode) 0)
            {
                throw new Exception("extraShape is null and the CutMode specifies that it should be used. Cannot use null shape.");
            }
            if ((mode & TileHandler.CutMode.CutExtra) != (TileHandler.CutMode) 0)
            {
                list = ListPool <IntPoint> .Claim(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)));
                }
            }
            IntRect bounds = new IntRect(verts[0].x, verts[0].z, verts[0].x, verts[0].z);

            for (int j = 0; j < verts.Length; j++)
            {
                bounds = bounds.ExpandToContain(verts[j].x, verts[j].z);
            }
            List <NavmeshCut> list2;

            if (mode == TileHandler.CutMode.CutExtra)
            {
                list2 = ListPool <NavmeshCut> .Claim();
            }
            else
            {
                list2 = NavmeshCut.GetAllInRange(realBounds);
            }
            List <NavmeshAdd> allInRange = NavmeshAdd.GetAllInRange(realBounds);
            List <int>        list3      = ListPool <int> .Claim();

            List <TileHandler.Cut> list4 = TileHandler.PrepareNavmeshCutsForCutting(list2, cuttingOffset, bounds, perturbate, allInRange.Count > 0);
            List <Int3>            list5 = ListPool <Int3> .Claim(verts.Length * 2);

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

            Int3[] array  = verts;
            int[]  array2 = tris;
            if (list2.Count == 0 && allInRange.Count == 0 && (mode & ~(TileHandler.CutMode.CutAll | TileHandler.CutMode.CutDual)) == (TileHandler.CutMode) 0 && (mode & TileHandler.CutMode.CutAll) != (TileHandler.CutMode) 0)
            {
                this.CopyMesh(array, array2, list5, list6);
            }
            else
            {
                List <IntPoint> list7 = ListPool <IntPoint> .Claim();

                Dictionary <TriangulationPoint, int> dictionary = new Dictionary <TriangulationPoint, int>();
                List <PolygonPoint> list8 = ListPool <PolygonPoint> .Claim();

                PolyTree polyTree = new PolyTree();
                List <List <IntPoint> > intermediateResult = new List <List <IntPoint> >();
                Stack <Polygon>         stack = new Stack <Polygon>();
                this.clipper.StrictlySimple  = (perturbate > -1);
                this.clipper.ReverseSolution = true;
                Int3[] array3  = null;
                Int3[] clipOut = null;
                Int2   @int    = default(Int2);
                if (allInRange.Count > 0)
                {
                    array3  = new Int3[7];
                    clipOut = new Int3[7];
                    @int    = new Int2(((Int3)realBounds.extents).x, ((Int3)realBounds.extents).z);
                }
                int num = -1;
                int k   = -3;
                for (;;)
                {
                    k += 3;
                    while (k >= array2.Length)
                    {
                        num++;
                        k = 0;
                        if (num >= allInRange.Count)
                        {
                            array = null;
                            break;
                        }
                        if (array == verts)
                        {
                            array = null;
                        }
                        allInRange[num].GetMesh(cuttingOffset, ref array, out array2);
                    }
                    if (array == null)
                    {
                        break;
                    }
                    Int3 int2 = array[array2[k]];
                    Int3 int3 = array[array2[k + 1]];
                    Int3 int4 = array[array2[k + 2]];
                    if (VectorMath.IsColinearXZ(int2, int3, int4))
                    {
                        Debug.LogWarning("Skipping degenerate triangle.");
                    }
                    else
                    {
                        IntRect a = new IntRect(int2.x, int2.z, int2.x, int2.z);
                        a = a.ExpandToContain(int3.x, int3.z);
                        a = a.ExpandToContain(int4.x, int4.z);
                        int num2 = Math.Min(int2.y, Math.Min(int3.y, int4.y));
                        int num3 = Math.Max(int2.y, Math.Max(int3.y, int4.y));
                        list3.Clear();
                        bool flag = false;
                        for (int l = 0; l < list4.Count; l++)
                        {
                            int x = list4[l].boundsY.x;
                            int y = list4[l].boundsY.y;
                            if (IntRect.Intersects(a, list4[l].bounds) && y >= num2 && x <= num3 && (list4[l].cutsAddedGeom || num == -1))
                            {
                                Int3 int5 = int2;
                                int5.y = x;
                                Int3 int6 = int2;
                                int6.y = y;
                                list3.Add(l);
                                flag |= list4[l].isDual;
                            }
                        }
                        if (list3.Count == 0 && (mode & TileHandler.CutMode.CutExtra) == (TileHandler.CutMode) 0 && (mode & TileHandler.CutMode.CutAll) != (TileHandler.CutMode) 0 && num == -1)
                        {
                            list6.Add(list5.Count);
                            list6.Add(list5.Count + 1);
                            list6.Add(list5.Count + 2);
                            list5.Add(int2);
                            list5.Add(int3);
                            list5.Add(int4);
                        }
                        else
                        {
                            list7.Clear();
                            if (num == -1)
                            {
                                list7.Add(new IntPoint((long)int2.x, (long)int2.z));
                                list7.Add(new IntPoint((long)int3.x, (long)int3.z));
                                list7.Add(new IntPoint((long)int4.x, (long)int4.z));
                            }
                            else
                            {
                                array3[0] = int2;
                                array3[1] = int3;
                                array3[2] = int4;
                                int num4 = this.ClipAgainstRectangle(array3, clipOut, new Int2(@int.x * 2, @int.y * 2));
                                if (num4 == 0)
                                {
                                    continue;
                                }
                                for (int m = 0; m < num4; m++)
                                {
                                    list7.Add(new IntPoint((long)array3[m].x, (long)array3[m].z));
                                }
                            }
                            dictionary.Clear();
                            for (int n = 0; n < 16; n++)
                            {
                                if ((mode >> (n & 31) & TileHandler.CutMode.CutAll) != (TileHandler.CutMode) 0)
                                {
                                    if (1 << n == 1)
                                    {
                                        this.CutAll(list7, list3, list4, polyTree);
                                    }
                                    else if (1 << n == 2)
                                    {
                                        if (!flag)
                                        {
                                            goto IL_9A0;
                                        }
                                        this.CutDual(list7, list3, list4, flag, intermediateResult, polyTree);
                                    }
                                    else if (1 << n == 4)
                                    {
                                        this.CutExtra(list7, list, polyTree);
                                    }
                                    for (int num5 = 0; num5 < polyTree.ChildCount; num5++)
                                    {
                                        PolyNode        polyNode = polyTree.Childs[num5];
                                        List <IntPoint> contour  = polyNode.Contour;
                                        List <PolyNode> childs   = polyNode.Childs;
                                        if (childs.Count == 0 && contour.Count == 3 && num == -1)
                                        {
                                            for (int num6 = 0; num6 < 3; num6++)
                                            {
                                                Int3 int7 = new Int3((int)contour[num6].X, 0, (int)contour[num6].Y);
                                                int7.y = TileHandler.SampleYCoordinateInTriangle(int2, int3, int4, int7);
                                                list6.Add(list5.Count);
                                                list5.Add(int7);
                                            }
                                        }
                                        else
                                        {
                                            Polygon polygon = null;
                                            int     num7    = -1;
                                            for (List <IntPoint> list9 = contour; list9 != null; list9 = ((num7 >= childs.Count) ? null : childs[num7].Contour))
                                            {
                                                list8.Clear();
                                                for (int num8 = 0; num8 < list9.Count; num8++)
                                                {
                                                    PolygonPoint polygonPoint = new PolygonPoint((double)list9[num8].X, (double)list9[num8].Y);
                                                    list8.Add(polygonPoint);
                                                    Int3 int8 = new Int3((int)list9[num8].X, 0, (int)list9[num8].Y);
                                                    int8.y = TileHandler.SampleYCoordinateInTriangle(int2, int3, int4, int8);
                                                    dictionary[polygonPoint] = list5.Count;
                                                    list5.Add(int8);
                                                }
                                                Polygon polygon2;
                                                if (stack.Count > 0)
                                                {
                                                    polygon2 = stack.Pop();
                                                    polygon2.AddPoints(list8);
                                                }
                                                else
                                                {
                                                    polygon2 = new Polygon(list8);
                                                }
                                                if (num7 == -1)
                                                {
                                                    polygon = polygon2;
                                                }
                                                else
                                                {
                                                    polygon.AddHole(polygon2);
                                                }
                                                num7++;
                                            }
                                            try
                                            {
                                                P2T.Triangulate(polygon);
                                            }
                                            catch (PointOnEdgeException)
                                            {
                                                Debug.LogWarning("PointOnEdgeException, perturbating vertices slightly.\nThis is usually fine. It happens sometimes because of rounding errors. Cutting will be retried a few more times.");
                                                this.CutPoly(verts, tris, ref outVertsArr, ref outTrisArr, out outVCount, out outTCount, extraShape, cuttingOffset, realBounds, mode, perturbate + 1);
                                                return;
                                            }
                                            try
                                            {
                                                for (int num9 = 0; num9 < polygon.Triangles.Count; num9++)
                                                {
                                                    DelaunayTriangle delaunayTriangle = polygon.Triangles[num9];
                                                    list6.Add(dictionary[delaunayTriangle.Points._0]);
                                                    list6.Add(dictionary[delaunayTriangle.Points._1]);
                                                    list6.Add(dictionary[delaunayTriangle.Points._2]);
                                                }
                                            }
                                            catch (KeyNotFoundException)
                                            {
                                                Debug.LogWarning("KeyNotFoundException, perturbating vertices slightly.\nThis is usually fine. It happens sometimes because of rounding errors. Cutting will be retried a few more times.");
                                                this.CutPoly(verts, tris, ref outVertsArr, ref outTrisArr, out outVCount, out outTCount, extraShape, cuttingOffset, realBounds, mode, perturbate + 1);
                                                return;
                                            }
                                            TileHandler.PoolPolygon(polygon, stack);
                                        }
                                    }
                                }
                                IL_9A0 :;
                            }
                        }
                    }
                }
                ListPool <IntPoint> .Release(list7);

                ListPool <PolygonPoint> .Release(list8);
            }
            this.CompressMesh(list5, list6, ref outVertsArr, ref outTrisArr, out outVCount, out outTCount);
            for (int num10 = 0; num10 < list2.Count; num10++)
            {
                list2[num10].UsedForCut();
            }
            ListPool <Int3> .Release(list5);

            ListPool <int> .Release(list6);

            ListPool <int> .Release(list3);

            for (int num11 = 0; num11 < list4.Count; num11++)
            {
                ListPool <IntPoint> .Release(list4[num11].contour);
            }
            ListPool <TileHandler.Cut> .Release(list4);

            ListPool <NavmeshCut> .Release(list2);
        }
Пример #12
0
        GameObject GenerateProvinceRegionSurface(int provinceIndex, int regionIndex, Material material)
        {
            if (provinceIndex < 0 || provinceIndex >= provinces.Length)
            {
                return(null);
            }
            if (provinces[provinceIndex].regions == null)
            {
                ReadProvincePackedString(provinces[provinceIndex]);
            }
            if (provinces[provinceIndex].regions == null || regionIndex < 0 || regionIndex >= provinces[provinceIndex].regions.Count)
            {
                return(null);
            }

            Province province = provinces[provinceIndex];
            Region   region   = province.regions [regionIndex];

            // Triangulate to get the polygon vertex indices
            Poly2Tri.Polygon poly = new Poly2Tri.Polygon(region.latlon);

            if (_enableProvinceEnclaves && regionIndex == province.mainRegionIndex)
            {
                ProvinceSubstractProvinceEnclaves(provinceIndex, region, poly);
            }


            // Antarctica, Saskatchewan (Canada), British Columbia (Canada), Krasnoyarsk (Russia) - special cases due to its geometry
            float step = _frontiersDetail == FRONTIERS_DETAIL.High ? 2f: 5f;
            List <TriangulationPoint> steinerPoints = new List <TriangulationPoint>();
            float x0 = region.latlonRect2D.min.x + step / 2f;
            float x1 = region.latlonRect2D.max.x - step / 2f;
            float y0 = region.latlonRect2D.min.y + step / 2f;
            float y1 = region.latlonRect2D.max.y - step / 2f;

            for (float x = x0; x < x1; x += step)
            {
                for (float y = y0; y < y1; y += step)
                {
                    float xp = x + UnityEngine.Random.Range(-0.0001f, 0.0001f);
                    float yp = y + UnityEngine.Random.Range(-0.0001f, 0.0001f);
                    if (region.Contains(xp, yp))
                    {
                        steinerPoints.Add(new TriangulationPoint(xp, yp));
                        //						GameObject obj = GameObject.CreatePrimitive(PrimitiveType.Sphere);
                        //						obj.transform.SetParent(WorldMapGlobe.instance.transform, false);
                        //						obj.transform.localScale = Vector3.one * 0.01f;
                        //						obj.transform.localPosition = Conversion.GetSpherePointFromLatLon(new Vector2(x,y)) * 1.01f;
                    }
                }
            }
            if (steinerPoints.Count > 0)
            {
                poly.AddSteinerPoints(steinerPoints);
            }
            P2T.Triangulate(poly);

            int flip1, flip2;

            if (_earthInvertedMode)
            {
                flip1 = 2; flip2 = 1;
            }
            else
            {
                flip1 = 1; flip2 = 2;
            }
            int triCount = poly.Triangles.Count;

            Vector3[] revisedSurfPoints = new Vector3[triCount * 3];
            for (int k = 0; k < triCount; k++)
            {
                DelaunayTriangle dt = poly.Triangles[k];
                revisedSurfPoints[k * 3]         = Conversion.GetSpherePointFromLatLon(dt.Points[0].X, dt.Points[0].Y);
                revisedSurfPoints[k * 3 + flip1] = Conversion.GetSpherePointFromLatLon(dt.Points[1].X, dt.Points[1].Y);
                revisedSurfPoints[k * 3 + flip2] = Conversion.GetSpherePointFromLatLon(dt.Points[2].X, dt.Points[2].Y);
            }

            int revIndex = revisedSurfPoints.Length - 1;

            // Generate surface mesh
            int    cacheIndex    = GetCacheIndexForProvinceRegion(provinceIndex, regionIndex);
            string cacheIndexSTR = cacheIndex.ToString();
            // Deletes potential residual surface
            Transform t = surfacesLayer.transform.Find(cacheIndexSTR);

            if (t != null)
            {
                DestroyImmediate(t.gameObject);
            }
            GameObject surf = Drawing.CreateSurface(cacheIndexSTR, revisedSurfPoints, revIndex, material);

//			Rect rect = new Rect(0,0,0,0);
//			GameObject surf = Drawing.CreateSurface (cacheIndexSTR, poly, material, rect, Vector2.zero, Vector2.zero, 0);
            surf.transform.SetParent(surfacesLayer.transform, false);
            surf.transform.localPosition = Misc.Vector3zero;
            if (_earthInvertedMode)
            {
                surf.transform.localScale = Misc.Vector3one * 0.998f;
            }
            if (surfaces.ContainsKey(cacheIndex))
            {
                surfaces.Remove(cacheIndex);
            }
            surfaces.Add(cacheIndex, surf);
            return(surf);
        }
Пример #13
0
        /// <summary>
        /// Generate a set of mesh faces that represent a delaunay triangulation in the XY plane of the
        /// specified set of vertices.
        /// Based on the algorithm described here: http://paulbourke.net/papers/triangulate/
        /// </summary>
        /// <param name="vertices">The vertices to mesh between</param>
        /// <param name="faces">Optional.  The face collection to which to add the triangles.
        /// If null or ommitted, a new MeshFaceCollection will be created.</param>
        /// <param name="bounds">The bounding box that contains the triangulation.  Should encompass all vertices
        /// and, for later voronoi generation, any bounding geometry.  If null, the bounding box of the vertices
        /// themselves will be used.</param>
        /// <param name="clean">Clean up construction Super Triangle.  If true, any remaining fragments of the
        /// initial generating supertriangle will be removed from the output face list.  Set this to false
        /// if planning on using this mesh for subsequent voronoi generation so that the edge cells can be extended.</param>
        /// <param name="outerVerts">Optional.  If input and non-null, this collection will be populated with the exterior vertices - those connected
        /// to the original supertriangle.  If 'clean' is false, this will instead return the supertriangle vertices.</param>
        public static MeshFaceCollection DelaunayTriangulationXY(VertexCollection vertices,
                                                                 MeshFaceCollection faces = null, BoundingBox bounds = null, bool clean = true, VertexCollection outerVerts = null)
        {
            List <Vertex> vertexList = vertices.ToList();

            vertexList.Sort();

            if (faces == null)
            {
                faces = new MeshFaceCollection();
            }

            if (bounds == null)
            {
                bounds = new BoundingBox(vertexList);
            }
            else
            {
                bounds = new BoundingBox(bounds);
            }

            bounds.Scale(5); //Provide a little wriggle room!

            // Meshing starts with one 'super triangle' that encloses all vertices.
            // This will be removed at the end
            MeshFace superTriangle = DelaunayTriangle.GenerateSuperTriangleXY(bounds);

            faces.Add(superTriangle);



            // Include each vertex in the meshing one at a time
            foreach (Vertex v in vertexList)
            {
                //for (int k = 0; k < 8; k++)
                //{
                //    Vertex v = vertexList[k];
                //    if (k == 7)
                //    {
                //        bool bum = true;
                //    }

                IList <MeshEdge> edges = new List <MeshEdge>(); //The edges of replaced triangles

                for (int i = faces.Count - 1; i >= 0; i--)
                {
                    MeshFace face = faces[i];

                    if (face.XYCircumcircleContainmentQuickCheck(v)) //The vertex lies within the circumcircle of this face
                    {
                        //The edges of the triangle are added to the current edge set...
                        for (int j = 0; j < face.Count; j++)
                        {
                            edges.Add(face.GetEdge(j));
                        }
                        //...and the triangle is removed.
                        faces.RemoveAt(i);
                    }
                }

                //Remove duplicate edges to retain only the convex hull of edges.
                //edges.RemoveDuplicates();

                //Replaced with bespoke version
                for (int i = edges.Count - 2; i >= 0; i--)
                {
                    MeshEdge itemA = edges[i];
                    for (int j = edges.Count - 1; j > i; j--)
                    {
                        if (itemA.Equals(edges[j]))
                        {
                            edges.RemoveAt(j);
                            edges.RemoveAt(i);
                            j--;
                            continue;
                        }
                    }
                }

                // Add triangle fan between all remaining edges and the new vertex
                foreach (MeshEdge edge in edges)
                {
                    faces.Add(new DelaunayTriangle(edge, v));
                }
            }

            // Extract outer vertices
            if (outerVerts != null)
            {
                if (clean)
                {
                    var outerFaces = faces.AllWithVertices(new VertexCollection(superTriangle));
                    foreach (Vertex v in outerFaces.ExtractVertices())
                    {
                        outerVerts.Add(v);
                    }
                }
                else
                {
                    foreach (Vertex v in superTriangle)
                    {
                        outerVerts.Add(v);
                    }
                }
            }

            // Remove the super triangle and any triangles still attached to it
            if (clean)
            {
                faces.RemoveAllWithVertices(new VertexCollection(superTriangle));
            }

            return(faces);
        }
Пример #14
0
 /// <summary>
 ///     Adds the triangle using the specified t
 /// </summary>
 /// <param name="t">The </param>
 public void AddTriangle(DelaunayTriangle t)
 {
     TrianglesPrivate.Add(t);
 }
Пример #15
0
		public override void Clear()
		{
			this.PrimaryTriangle = null;
			this.SecondaryTriangle = null;
			this.ActivePoint = null;
			this.ActiveNode = null;
			this.ActiveConstraint = null;
		}
Пример #16
0
        /// <summary>
        /// Rotates a triangle pair one vertex CW
        ///       n2                    n2
        ///  P +-----+             P +-----+
        ///    | t  /|               |\  t |  
        ///    |   / |               | \   |
        ///  n1|  /  |n3           n1|  \  |n3
        ///    | /   |    after CW   |   \ |
        ///    |/ oT |               | oT \|
        ///    +-----+ oP            +-----+
        ///       n4                    n4
        /// </summary>
        private static void RotateTrianglePair(DelaunayTriangle t, TriangulationPoint p, DelaunayTriangle ot, TriangulationPoint op)
        {
            DelaunayTriangle n1 = t.NeighborCCW(p);
            DelaunayTriangle n2 = t.NeighborCW(p);
            DelaunayTriangle n3 = ot.NeighborCCW(op);
            DelaunayTriangle n4 = ot.NeighborCW(op);

            bool ce1 = t.GetConstrainedEdgeCCW(p);
            bool ce2 = t.GetConstrainedEdgeCW(p);
            bool ce3 = ot.GetConstrainedEdgeCCW(op);
            bool ce4 = ot.GetConstrainedEdgeCW(op);

            bool de1 = t.GetDelaunayEdgeCCW(p);
            bool de2 = t.GetDelaunayEdgeCW(p);
            bool de3 = ot.GetDelaunayEdgeCCW(op);
            bool de4 = ot.GetDelaunayEdgeCW(op);

            t.Legalize(p, op);
            ot.Legalize(op, p);

            // Remap dEdge
            ot.SetDelaunayEdgeCCW(p, de1);
            t.SetDelaunayEdgeCW(p, de2);
            t.SetDelaunayEdgeCCW(op, de3);
            ot.SetDelaunayEdgeCW(op, de4);

            // Remap cEdge
            ot.SetConstrainedEdgeCCW(p, ce1);
            t.SetConstrainedEdgeCW(p, ce2);
            t.SetConstrainedEdgeCCW(op, ce3);
            ot.SetConstrainedEdgeCW(op, ce4);

            // Remap neighbors
            // XXX: might optimize the markNeighbor by keeping track of
            //      what side should be assigned to what neighbor after the
            //      rotation. Now mark neighbor does lots of testing to find
            //      the right side.
            t.Neighbors.Clear();
            ot.Neighbors.Clear();
            if (n1 != null) ot.MarkNeighbor(n1);
            if (n2 != null) t.MarkNeighbor(n2);
            if (n3 != null) t.MarkNeighbor(n3);
            if (n4 != null) ot.MarkNeighbor(n4);
            t.MarkNeighbor(ot);
        }
Пример #17
0
        // Token: 0x06002959 RID: 10585 RVA: 0x001BCF00 File Offset: 0x001BB100
        private TileHandler.CuttingResult CutPoly(Int3[] verts, int[] tris, Int3[] extraShape, GraphTransform graphTransform, IntRect tiles, TileHandler.CutMode mode = TileHandler.CutMode.CutAll | TileHandler.CutMode.CutDual, int perturbate = -1)
        {
            if (verts.Length == 0 || tris.Length == 0)
            {
                TileHandler.CuttingResult result = new TileHandler.CuttingResult
                {
                    verts = ArrayPool <Int3> .Claim(0),
                    tris  = ArrayPool <int> .Claim(0)
                };
                return(result);
            }
            if (perturbate > 10)
            {
                Debug.LogError("Too many perturbations aborting.\nThis may cause a tile in the navmesh to become empty. Try to see see if any of your NavmeshCut or NavmeshAdd components use invalid custom meshes.");
                TileHandler.CuttingResult result = new TileHandler.CuttingResult
                {
                    verts = verts,
                    tris  = tris
                };
                return(result);
            }
            List <IntPoint> list = null;

            if (extraShape == null && (mode & TileHandler.CutMode.CutExtra) != (TileHandler.CutMode) 0)
            {
                throw new Exception("extraShape is null and the CutMode specifies that it should be used. Cannot use null shape.");
            }
            Bounds         tileBoundsInGraphSpace = this.graph.GetTileBoundsInGraphSpace(tiles);
            Vector3        min             = tileBoundsInGraphSpace.min;
            GraphTransform graphTransform2 = graphTransform * Matrix4x4.TRS(min, Quaternion.identity, Vector3.one);
            Vector2        v = new Vector2(tileBoundsInGraphSpace.size.x, tileBoundsInGraphSpace.size.z);

            if ((mode & TileHandler.CutMode.CutExtra) != (TileHandler.CutMode) 0)
            {
                list = ListPool <IntPoint> .Claim(extraShape.Length);

                for (int i = 0; i < extraShape.Length; i++)
                {
                    Int3 @int = graphTransform2.InverseTransform(extraShape[i]);
                    list.Add(new IntPoint((long)@int.x, (long)@int.z));
                }
            }
            IntRect cutSpaceBounds = new IntRect(verts[0].x, verts[0].z, verts[0].x, verts[0].z);

            for (int j = 0; j < verts.Length; j++)
            {
                cutSpaceBounds = cutSpaceBounds.ExpandToContain(verts[j].x, verts[j].z);
            }
            List <NavmeshCut> list2;

            if (mode == TileHandler.CutMode.CutExtra)
            {
                list2 = ListPool <NavmeshCut> .Claim();
            }
            else
            {
                list2 = this.cuts.QueryRect <NavmeshCut>(tiles);
            }
            List <NavmeshAdd> list3 = this.cuts.QueryRect <NavmeshAdd>(tiles);
            List <int>        list4 = ListPool <int> .Claim();

            List <TileHandler.Cut> list5 = TileHandler.PrepareNavmeshCutsForCutting(list2, graphTransform2, cutSpaceBounds, perturbate, list3.Count > 0);
            List <Int3>            list6 = ListPool <Int3> .Claim(verts.Length * 2);

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

            if (list2.Count == 0 && list3.Count == 0 && (mode & ~(TileHandler.CutMode.CutAll | TileHandler.CutMode.CutDual)) == (TileHandler.CutMode) 0 && (mode & TileHandler.CutMode.CutAll) != (TileHandler.CutMode) 0)
            {
                TileHandler.CopyMesh(verts, tris, list6, list7);
            }
            else
            {
                List <IntPoint> list8 = ListPool <IntPoint> .Claim();

                Dictionary <TriangulationPoint, int> dictionary = new Dictionary <TriangulationPoint, int>();
                List <PolygonPoint> list9 = ListPool <PolygonPoint> .Claim();

                PolyTree polyTree = new PolyTree();
                List <List <IntPoint> > intermediateResult = ListPool <List <IntPoint> > .Claim();

                Stack <Polygon> stack = StackPool <Polygon> .Claim();

                this.clipper.StrictlySimple  = (perturbate > -1);
                this.clipper.ReverseSolution = true;
                Int3[] array   = null;
                Int3[] clipOut = null;
                Int2   size    = default(Int2);
                if (list3.Count > 0)
                {
                    array   = new Int3[7];
                    clipOut = new Int3[7];
                    size    = new Int2(((Int3)v).x, ((Int3)v).y);
                }
                Int3[] array2 = null;
                for (int k = -1; k < list3.Count; k++)
                {
                    Int3[] array3;
                    int[]  array4;
                    if (k == -1)
                    {
                        array3 = verts;
                        array4 = tris;
                    }
                    else
                    {
                        list3[k].GetMesh(ref array2, out array4, graphTransform2);
                        array3 = array2;
                    }
                    for (int l = 0; l < array4.Length; l += 3)
                    {
                        Int3 int2 = array3[array4[l]];
                        Int3 int3 = array3[array4[l + 1]];
                        Int3 int4 = array3[array4[l + 2]];
                        if (VectorMath.IsColinearXZ(int2, int3, int4))
                        {
                            Debug.LogWarning("Skipping degenerate triangle.");
                        }
                        else
                        {
                            IntRect a = new IntRect(int2.x, int2.z, int2.x, int2.z);
                            a = a.ExpandToContain(int3.x, int3.z);
                            a = a.ExpandToContain(int4.x, int4.z);
                            int num  = Math.Min(int2.y, Math.Min(int3.y, int4.y));
                            int num2 = Math.Max(int2.y, Math.Max(int3.y, int4.y));
                            list4.Clear();
                            bool flag = false;
                            for (int m = 0; m < list5.Count; m++)
                            {
                                int x = list5[m].boundsY.x;
                                int y = list5[m].boundsY.y;
                                if (IntRect.Intersects(a, list5[m].bounds) && y >= num && x <= num2 && (list5[m].cutsAddedGeom || k == -1))
                                {
                                    Int3 int5 = int2;
                                    int5.y = x;
                                    Int3 int6 = int2;
                                    int6.y = y;
                                    list4.Add(m);
                                    flag |= list5[m].isDual;
                                }
                            }
                            if (list4.Count == 0 && (mode & TileHandler.CutMode.CutExtra) == (TileHandler.CutMode) 0 && (mode & TileHandler.CutMode.CutAll) != (TileHandler.CutMode) 0 && k == -1)
                            {
                                list7.Add(list6.Count);
                                list7.Add(list6.Count + 1);
                                list7.Add(list6.Count + 2);
                                list6.Add(int2);
                                list6.Add(int3);
                                list6.Add(int4);
                            }
                            else
                            {
                                list8.Clear();
                                if (k == -1)
                                {
                                    list8.Add(new IntPoint((long)int2.x, (long)int2.z));
                                    list8.Add(new IntPoint((long)int3.x, (long)int3.z));
                                    list8.Add(new IntPoint((long)int4.x, (long)int4.z));
                                }
                                else
                                {
                                    array[0] = int2;
                                    array[1] = int3;
                                    array[2] = int4;
                                    int num3 = this.ClipAgainstRectangle(array, clipOut, size);
                                    if (num3 == 0)
                                    {
                                        goto IL_8D1;
                                    }
                                    for (int n = 0; n < num3; n++)
                                    {
                                        list8.Add(new IntPoint((long)array[n].x, (long)array[n].z));
                                    }
                                }
                                dictionary.Clear();
                                for (int num4 = 0; num4 < 16; num4++)
                                {
                                    if ((mode >> (num4 & 31) & TileHandler.CutMode.CutAll) != (TileHandler.CutMode) 0)
                                    {
                                        if (1 << num4 == 1)
                                        {
                                            this.CutAll(list8, list4, list5, polyTree);
                                        }
                                        else if (1 << num4 == 2)
                                        {
                                            if (!flag)
                                            {
                                                goto IL_8C2;
                                            }
                                            this.CutDual(list8, list4, list5, flag, intermediateResult, polyTree);
                                        }
                                        else if (1 << num4 == 4)
                                        {
                                            this.CutExtra(list8, list, polyTree);
                                        }
                                        for (int num5 = 0; num5 < polyTree.ChildCount; num5++)
                                        {
                                            PolyNode        polyNode = polyTree.Childs[num5];
                                            List <IntPoint> contour  = polyNode.Contour;
                                            List <PolyNode> childs   = polyNode.Childs;
                                            if (childs.Count == 0 && contour.Count == 3 && k == -1)
                                            {
                                                for (int num6 = 0; num6 < 3; num6++)
                                                {
                                                    Int3 int7 = new Int3((int)contour[num6].X, 0, (int)contour[num6].Y);
                                                    int7.y = Polygon.SampleYCoordinateInTriangle(int2, int3, int4, int7);
                                                    list7.Add(list6.Count);
                                                    list6.Add(int7);
                                                }
                                            }
                                            else
                                            {
                                                Polygon polygon = null;
                                                int     num7    = -1;
                                                for (List <IntPoint> list10 = contour; list10 != null; list10 = ((num7 < childs.Count) ? childs[num7].Contour : null))
                                                {
                                                    list9.Clear();
                                                    for (int num8 = 0; num8 < list10.Count; num8++)
                                                    {
                                                        PolygonPoint polygonPoint = new PolygonPoint((double)list10[num8].X, (double)list10[num8].Y);
                                                        list9.Add(polygonPoint);
                                                        Int3 int8 = new Int3((int)list10[num8].X, 0, (int)list10[num8].Y);
                                                        int8.y = Polygon.SampleYCoordinateInTriangle(int2, int3, int4, int8);
                                                        dictionary[polygonPoint] = list6.Count;
                                                        list6.Add(int8);
                                                    }
                                                    Polygon polygon2;
                                                    if (stack.Count > 0)
                                                    {
                                                        polygon2 = stack.Pop();
                                                        polygon2.AddPoints(list9);
                                                    }
                                                    else
                                                    {
                                                        polygon2 = new Polygon(list9);
                                                    }
                                                    if (num7 == -1)
                                                    {
                                                        polygon = polygon2;
                                                    }
                                                    else
                                                    {
                                                        polygon.AddHole(polygon2);
                                                    }
                                                    num7++;
                                                }
                                                try
                                                {
                                                    P2T.Triangulate(polygon);
                                                }
                                                catch (PointOnEdgeException)
                                                {
                                                    Debug.LogWarning("PointOnEdgeException, perturbating vertices slightly.\nThis is usually fine. It happens sometimes because of rounding errors. Cutting will be retried a few more times.");
                                                    return(this.CutPoly(verts, tris, extraShape, graphTransform, tiles, mode, perturbate + 1));
                                                }
                                                try
                                                {
                                                    for (int num9 = 0; num9 < polygon.Triangles.Count; num9++)
                                                    {
                                                        DelaunayTriangle delaunayTriangle = polygon.Triangles[num9];
                                                        list7.Add(dictionary[delaunayTriangle.Points._0]);
                                                        list7.Add(dictionary[delaunayTriangle.Points._1]);
                                                        list7.Add(dictionary[delaunayTriangle.Points._2]);
                                                    }
                                                }
                                                catch (KeyNotFoundException)
                                                {
                                                    Debug.LogWarning("KeyNotFoundException, perturbating vertices slightly.\nThis is usually fine. It happens sometimes because of rounding errors. Cutting will be retried a few more times.");
                                                    return(this.CutPoly(verts, tris, extraShape, graphTransform, tiles, mode, perturbate + 1));
                                                }
                                                TileHandler.PoolPolygon(polygon, stack);
                                            }
                                        }
                                    }
                                    IL_8C2 :;
                                }
                            }
                        }
                        IL_8D1 :;
                    }
                }
                if (array2 != null)
                {
                    ArrayPool <Int3> .Release(ref array2, false);
                }
                StackPool <Polygon> .Release(stack);

                ListPool <List <IntPoint> > .Release(ref intermediateResult);

                ListPool <IntPoint> .Release(ref list8);

                ListPool <PolygonPoint> .Release(ref list9);
            }
            TileHandler.CuttingResult result2 = default(TileHandler.CuttingResult);
            Polygon.CompressMesh(list6, list7, out result2.verts, out result2.tris);
            for (int num10 = 0; num10 < list2.Count; num10++)
            {
                list2[num10].UsedForCut();
            }
            ListPool <Int3> .Release(ref list6);

            ListPool <int> .Release(ref list7);

            ListPool <int> .Release(ref list4);

            for (int num11 = 0; num11 < list5.Count; num11++)
            {
                ListPool <IntPoint> .Release(list5[num11].contour);
            }
            ListPool <TileHandler.Cut> .Release(ref list5);

            ListPool <NavmeshCut> .Release(ref list2);

            return(result2);
        }
Пример #18
0
        /// <summary>
        /// Scan part of the FlipScan algorithm<br>
        /// When a triangle pair isn't flippable we will scan for the next 
        /// point that is inside the flip triangle scan area. When found 
        /// we generate a new flipEdgeEvent
        /// </summary>
        /// <param name="tcx"></param>
        /// <param name="ep">last point on the edge we are traversing</param>
        /// <param name="eq">first point on the edge we are traversing</param>
        /// <param name="flipTriangle">the current triangle sharing the point eq with edge</param>
        /// <param name="t"></param>
        /// <param name="p"></param>
        private static void FlipScanEdgeEvent(DTSweepContext tcx, TriangulationPoint ep, TriangulationPoint eq, DelaunayTriangle flipTriangle, DelaunayTriangle t, TriangulationPoint p)
        {
            DelaunayTriangle ot = t.NeighborAcross(p);
            TriangulationPoint op = ot.OppositePoint(t, p);

            if (ot == null)
            {
                // If we want to integrate the fillEdgeEvent do it here
                // With current implementation we should never get here
                throw new Exception("[BUG:FIXME] FLIP failed due to missing triangle");
            }

            bool inScanArea = TriangulationUtil.InScanArea(eq, flipTriangle.PointCCW(eq), flipTriangle.PointCW(eq), op);
            if (inScanArea)
            {
                // flip with new edge op->eq
                FlipEdgeEvent(tcx, eq, op, ot, op);
                // TODO: Actually I just figured out that it should be possible to
                //       improve this by getting the next ot and op before the the above
                //       flip and continue the flipScanEdgeEvent here
                // set new ot and op here and loop back to inScanArea test
                // also need to set a new flipTriangle first
                // Turns out at first glance that this is somewhat complicated
                // so it will have to wait.
            }
            else
            {
                TriangulationPoint newP = NextFlipPoint(ep, eq, ot, op);
                FlipScanEdgeEvent(tcx, ep, eq, flipTriangle, ot, newP);
            }
        }
        private void CutPoly(VInt3[] verts, int[] tris, ref VInt3[] outVertsArr, ref int[] outTrisArr, out int outVCount, out int outTCount, VInt3[] extraShape, VInt3 cuttingOffset, Bounds realBounds, TileHandler.CutMode mode = TileHandler.CutMode.CutAll, int perturbate = 0)
        {
            if (verts.Length == 0 || tris.Length == 0)
            {
                outVCount   = 0;
                outTCount   = 0;
                outTrisArr  = new int[0];
                outVertsArr = new VInt3[0];
                return;
            }
            List <IntPoint> list = null;

            if (extraShape == null && (mode & TileHandler.CutMode.CutExtra) != (TileHandler.CutMode) 0)
            {
                throw new Exception("extraShape is null and the CutMode specifies that it should be used. Cannot use null shape.");
            }
            if ((mode & TileHandler.CutMode.CutExtra) != (TileHandler.CutMode) 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 <VInt3> list4 = ListPool <VInt3> .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 <Polygon>         stack = new Stack <Polygon>();

            if (this.clipper == null)
            {
                this.clipper = new Clipper(0);
            }
            this.clipper.set_ReverseSolution(true);
            this.clipper.set_StrictlySimple(true);
            ListView <NavmeshCut> listView;

            if (mode == TileHandler.CutMode.CutExtra)
            {
                listView = new ListView <NavmeshCut>();
            }
            else
            {
                listView = NavmeshCut.GetAllInRange(realBounds);
            }
            List <int> list7 = ListPool <int> .Claim();

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

            List <VInt2> list9 = ListPool <VInt2> .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;
            }
            Random random = null;

            if (perturbate > 0)
            {
                random = new Random();
            }
            for (int k = 0; k < listView.Count; k++)
            {
                Bounds  bounds = listView[k].GetBounds();
                VInt3   vInt   = (VInt3)bounds.min + cuttingOffset;
                VInt3   vInt2  = (VInt3)bounds.max + cuttingOffset;
                IntRect a      = new IntRect(vInt.x, vInt.z, vInt2.x, vInt2.z);
                if (IntRect.Intersects(a, b))
                {
                    VInt2 vInt3 = new VInt2(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.get_Count();
                    listView[k].GetContour(list10);
                    for (int l = count; l < list10.get_Count(); l++)
                    {
                        List <IntPoint> list13 = list10.get_Item(l);
                        if (list13.get_Count() == 0)
                        {
                            Debug.LogError("Zero Length Contour");
                            list8.Add(default(IntRect));
                            list9.Add(new VInt2(0, 0));
                        }
                        else
                        {
                            IntRect intRect = new IntRect((int)list13.get_Item(0).X + cuttingOffset.x, (int)list13.get_Item(0).Y + cuttingOffset.y, (int)list13.get_Item(0).X + cuttingOffset.x, (int)list13.get_Item(0).Y + cuttingOffset.y);
                            for (int m = 0; m < list13.get_Count(); m++)
                            {
                                IntPoint intPoint = list13.get_Item(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.set_Item(m, intPoint);
                                intRect = intRect.ExpandToContain((int)intPoint.X, (int)intPoint.Y);
                            }
                            list9.Add(new VInt2(vInt.y, vInt2.y));
                            list8.Add(intRect);
                            list11.Add(listView[k].isDual);
                            list12.Add(listView[k].cutsAddedGeom);
                        }
                    }
                }
            }
            List <NavmeshAdd> allInRange = NavmeshAdd.GetAllInRange(realBounds);

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

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

            if (allInRange.get_Count() > 0)
            {
                array3 = new VInt3[7];
                array4 = new VInt3[7];
                vInt4  = (VInt3)realBounds.extents;
            }
            while (true)
            {
                n += 3;
                while (n >= array2.Length)
                {
                    num++;
                    n = 0;
                    if (num >= allInRange.get_Count())
                    {
                        array = null;
                        break;
                    }
                    if (array == verts)
                    {
                        array = null;
                    }
                    allInRange.get_Item(num).GetMesh(cuttingOffset, ref array, out array2);
                }
                if (array == null)
                {
                    break;
                }
                VInt3   vInt5 = array[array2[n]];
                VInt3   vInt6 = array[array2[n + 1]];
                VInt3   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.get_Count(); num4++)
                {
                    int x = list9.get_Item(num4).x;
                    int y = list9.get_Item(num4).y;
                    if (IntRect.Intersects(a2, list8.get_Item(num4)) && y >= num2 && x <= num3 && (list12.get_Item(num4) || num == -1))
                    {
                        VInt3 vInt8 = vInt5;
                        vInt8.y = x;
                        VInt3 vInt9 = vInt5;
                        vInt9.y = y;
                        list7.Add(num4);
                        flag |= list11.get_Item(num4);
                    }
                }
                if (list7.get_Count() == 0 && (mode & TileHandler.CutMode.CutExtra) == (TileHandler.CutMode) 0 && (mode & TileHandler.CutMode.CutAll) != (TileHandler.CutMode) 0 && num == -1)
                {
                    list5.Add(list4.get_Count());
                    list5.Add(list4.get_Count() + 1);
                    list5.Add(list4.get_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();
                    VInt3 vInt10 = vInt6 - vInt5;
                    VInt3 vInt11 = vInt7 - vInt5;
                    VInt3 vInt12 = vInt10;
                    VInt3 vInt13 = vInt11;
                    vInt12.y = 0;
                    vInt13.y = 0;
                    for (int num7 = 0; num7 < 16; num7++)
                    {
                        if ((mode >> (num7 & 31 & 31) & TileHandler.CutMode.CutAll) != (TileHandler.CutMode) 0)
                        {
                            if (1 << num7 == 1)
                            {
                                this.clipper.Clear();
                                this.clipper.AddPolygon(list2, 0);
                                for (int num8 = 0; num8 < list7.get_Count(); num8++)
                                {
                                    this.clipper.AddPolygon(list10.get_Item(list7.get_Item(num8)), 1);
                                }
                                polyTree.Clear();
                                this.clipper.Execute(2, polyTree, 0, 1);
                            }
                            else if (1 << num7 == 2)
                            {
                                if (!flag)
                                {
                                    goto IL_116B;
                                }
                                this.clipper.Clear();
                                this.clipper.AddPolygon(list2, 0);
                                for (int num9 = 0; num9 < list7.get_Count(); num9++)
                                {
                                    if (list11.get_Item(list7.get_Item(num9)))
                                    {
                                        this.clipper.AddPolygon(list10.get_Item(list7.get_Item(num9)), 1);
                                    }
                                }
                                list6.Clear();
                                this.clipper.Execute(0, list6, 0, 1);
                                this.clipper.Clear();
                                for (int num10 = 0; num10 < list6.get_Count(); num10++)
                                {
                                    this.clipper.AddPolygon(list6.get_Item(num10), Clipper.Orientation(list6.get_Item(num10)) ? 1 : 0);
                                }
                                for (int num11 = 0; num11 < list7.get_Count(); num11++)
                                {
                                    if (!list11.get_Item(list7.get_Item(num11)))
                                    {
                                        this.clipper.AddPolygon(list10.get_Item(list7.get_Item(num11)), 1);
                                    }
                                }
                                polyTree.Clear();
                                this.clipper.Execute(2, polyTree, 0, 1);
                            }
                            else if (1 << num7 == 4)
                            {
                                this.clipper.Clear();
                                this.clipper.AddPolygon(list2, 0);
                                this.clipper.AddPolygon(list, 1);
                                polyTree.Clear();
                                this.clipper.Execute(0, polyTree, 0, 1);
                            }
                            for (int num12 = 0; num12 < polyTree.get_ChildCount(); num12++)
                            {
                                PolyNode        polyNode = polyTree.get_Childs().get_Item(num12);
                                List <IntPoint> contour  = polyNode.get_Contour();
                                List <PolyNode> childs   = polyNode.get_Childs();
                                if (childs.get_Count() == 0 && contour.get_Count() == 3 && num == -1)
                                {
                                    for (int num13 = 0; num13 < contour.get_Count(); num13++)
                                    {
                                        VInt3  vInt14 = new VInt3((int)contour.get_Item(num13).X, 0, (int)contour.get_Item(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 = MMGame_Math.RoundToInt(num15 * (double)vInt5.y + num16 * (double)vInt6.y + (1.0 - num15 - num16) * (double)vInt7.y);
                                            list5.Add(list4.get_Count());
                                            list4.Add(vInt14);
                                        }
                                    }
                                }
                                else
                                {
                                    Polygon polygon = null;
                                    int     num17   = -1;
                                    for (List <IntPoint> list14 = contour; list14 != null; list14 = ((num17 < childs.get_Count()) ? childs.get_Item(num17).get_Contour() : null))
                                    {
                                        list3.Clear();
                                        for (int num18 = 0; num18 < list14.get_Count(); num18++)
                                        {
                                            PolygonPoint polygonPoint = new PolygonPoint((double)list14.get_Item(num18).X, (double)list14.get_Item(num18).Y);
                                            list3.Add(polygonPoint);
                                            VInt3  vInt15 = new VInt3((int)list14.get_Item(num18).X, 0, (int)list14.get_Item(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 = MMGame_Math.RoundToInt(num20 * (double)vInt5.y + num21 * (double)vInt6.y + (1.0 - num20 - num21) * (double)vInt7.y);
                                                dictionary.set_Item(polygonPoint, list4.get_Count());
                                                list4.Add(vInt15);
                                            }
                                        }
                                        Polygon polygon2;
                                        if (stack.get_Count() > 0)
                                        {
                                            polygon2 = stack.Pop();
                                            polygon2.AddPoints(list3);
                                        }
                                        else
                                        {
                                            polygon2 = new 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(verts, tris, ref outVertsArr, ref outTrisArr, out outVCount, out outTCount, extraShape, cuttingOffset, realBounds, mode, perturbate + 1);
                                        return;
                                    }
                                    for (int num22 = 0; num22 < polygon.get_Triangles().get_Count(); num22++)
                                    {
                                        DelaunayTriangle delaunayTriangle = polygon.get_Triangles().get_Item(num22);
                                        list5.Add(dictionary.get_Item(delaunayTriangle.Points._0));
                                        list5.Add(dictionary.get_Item(delaunayTriangle.Points._1));
                                        list5.Add(dictionary.get_Item(delaunayTriangle.Points._2));
                                    }
                                    if (polygon.get_Holes() != null)
                                    {
                                        for (int num23 = 0; num23 < polygon.get_Holes().get_Count(); num23++)
                                        {
                                            polygon.get_Holes().get_Item(num23).get_Points().Clear();
                                            polygon.get_Holes().get_Item(num23).ClearTriangles();
                                            if (polygon.get_Holes().get_Item(num23).get_Holes() != null)
                                            {
                                                polygon.get_Holes().get_Item(num23).get_Holes().Clear();
                                            }
                                            stack.Push(polygon.get_Holes().get_Item(num23));
                                        }
                                    }
                                    polygon.ClearTriangles();
                                    if (polygon.get_Holes() != null)
                                    {
                                        polygon.get_Holes().Clear();
                                    }
                                    polygon.get_Points().Clear();
                                    stack.Push(polygon);
                                }
                            }
                        }
                        IL_116B :;
                    }
                }
            }
            Dictionary <VInt3, int> dictionary2 = this.cached_Int3_int_dict;

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

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

            ListPool <int> .Release(list5);

            ListPool <int> .Release(list7);

            ListPool <VInt2> .Release(list9);

            ListPool <bool> .Release(list11);

            ListPool <bool> .Release(list12);

            ListPool <IntRect> .Release(list8);
        }
Пример #20
0
 /// <summary>
 /// When we need to traverse from one triangle to the next we need 
 /// the point in current triangle that is the opposite point to the next
 /// triangle. 
 /// </summary>
 private static TriangulationPoint NextFlipPoint(TriangulationPoint ep, TriangulationPoint eq, DelaunayTriangle ot, TriangulationPoint op)
 {
     Orientation o2d = TriangulationUtil.Orient2d(eq, op, ep);
     if (o2d == Orientation.CW)
     {
         // Right
         return ot.PointCCW(op);
     }
     else if (o2d == Orientation.CCW)
     {
         // Left
         return ot.PointCW(op);
     }
     else
     {
         // TODO: implement support for point on constraint edge
         throw new PointOnEdgeException("Point on constrained edge not supported yet");
     }
 }
Пример #21
0
        GameObject GenerateProvinceRegionSurface(int provinceIndex, int regionIndex, Material material)
        {
            Region region = provinces [provinceIndex].regions [regionIndex];

            Polygon poly = new Polygon(region.latlon);

            // Antarctica, Saskatchewan (Canada), British Columbia (Canada), Krasnoyarsk (Russia) - special cases due to its geometry
            if (provinceIndex == 218 || provinceIndex == 220 || provinceIndex == 224 || provinceIndex == 3423)
            {
                float step = 5;
                List <TriangulationPoint> steinerPoints = new List <TriangulationPoint>();
                for (double x = region.minMaxLat.x + step / 2; x < region.minMaxLat.y - step / 2; x += step)
                {
                    for (double y = region.minMaxLon.x + step / 2; y < region.minMaxLon.y - step / 2; y += step)
                    {
                        if (region.ContainsPoint(x, y))
                        {
                            steinerPoints.Add(new TriangulationPoint(x, y));
                        }
                    }
                }
                poly.AddSteinerPoints(steinerPoints);
            }
            P2T.Triangulate(poly);

            int flip1, flip2;

            if (_earthInvertedMode)
            {
                flip1 = 2; flip2 = 1;
            }
            else
            {
                flip1 = 1; flip2 = 2;
            }
            Vector3[] revisedSurfPoints = new Vector3[poly.Triangles.Count * 3];
            for (int k = 0; k < poly.Triangles.Count; k++)
            {
                DelaunayTriangle dt = poly.Triangles[k];
                revisedSurfPoints[k * 3]         = GetSpherePointFromLatLon(dt.Points[0].X, dt.Points[0].Y);
                revisedSurfPoints[k * 3 + flip1] = GetSpherePointFromLatLon(dt.Points[1].X, dt.Points[1].Y);
                revisedSurfPoints[k * 3 + flip2] = GetSpherePointFromLatLon(dt.Points[2].X, dt.Points[2].Y);
            }

            int revIndex = revisedSurfPoints.Length - 1;

            // Generate surface mesh
            int    cacheIndex    = GetCacheIndexForProvinceRegion(provinceIndex, regionIndex);
            string cacheIndexSTR = cacheIndex.ToString();
            // Deletes potential residual surface
            Transform t = surfacesLayer.transform.FindChild(cacheIndexSTR);

            if (t != null)
            {
                DestroyImmediate(t.gameObject);
            }
            GameObject surf = Drawing.CreateSurface(cacheIndexSTR, revisedSurfPoints, revIndex, material);

            surf.transform.SetParent(transform, false);
            surf.transform.localPosition = MiscVector.Vector3zero;
            if (_earthInvertedMode)
            {
                surf.transform.localScale = MiscVector.Vector3one * 0.998f;
            }
            if (surfaces.ContainsKey(cacheIndex))
            {
                surfaces.Remove(cacheIndex);
            }
            surfaces.Add(cacheIndex, surf);
            return(surf);
        }
Пример #22
0
        /// <summary>
        /// When we need to traverse from one triangle to the next we need
        /// the point in current triangle that is the opposite point to the next
        /// triangle.
        /// </summary>
        private static TriangulationPoint NextFlipPoint(TriangulationPoint ep, TriangulationPoint eq, DelaunayTriangle ot, TriangulationPoint op)
        {
            Orientation o2d = TriangulationUtil.Orient2d(eq, op, ep);

            if (o2d == Orientation.CW)
            {
                // Right
                return(ot.PointCCW(op));
            }
            else if (o2d == Orientation.CCW)
            {
                // Left
                return(ot.PointCW(op));
            }
            else
            {
                // TODO: implement support for point on constraint edge
                throw new PointOnEdgeException("Point on constrained edge not supported yet");
            }
        }
Пример #23
0
        private static void EdgeEvent( DTSweepContext tcx, TriangulationPoint ep, TriangulationPoint eq, DelaunayTriangle triangle, TriangulationPoint point )
        {
            TriangulationPoint p1, p2;

            if (tcx.IsDebugEnabled) tcx.DTDebugContext.PrimaryTriangle=triangle;

            if (IsEdgeSideOfTriangle(triangle, ep, eq)) return;

            p1 = triangle.PointCCWFrom(point);
            Orientation o1 = TriangulationUtil.Orient2d(eq, p1, ep);
            if (o1 == Orientation.Collinear) {
                // TODO: Split edge in two
                ////            splitEdge( ep, eq, p1 );
                //            edgeEvent( tcx, p1, eq, triangle, point );
                //            edgeEvent( tcx, ep, p1, triangle, p1 );
                //            return;
                throw new PointOnEdgeException("EdgeEvent - Point on constrained edge not supported yet",eq,p1,ep);
            }

            p2 = triangle.PointCWFrom(point);
            Orientation o2 = TriangulationUtil.Orient2d(eq, p2, ep);
            if (o2 == Orientation.Collinear) {
                // TODO: Split edge in two
                //            edgeEvent( tcx, p2, eq, triangle, point );
                //            edgeEvent( tcx, ep, p2, triangle, p2 );
                //            return;
                throw new PointOnEdgeException("EdgeEvent - Point on constrained edge not supported yet",eq,p2,ep);
            }

            if (o1 == o2) {
                // Need to decide if we are rotating CW or CCW to get to a triangle
                // that will cross edge
                if (o1 == Orientation.CW) {
                    triangle = triangle.NeighborCCWFrom(point);
                } else {
                    triangle = triangle.NeighborCWFrom(point);
                }
                EdgeEvent(tcx, ep, eq, triangle, point);
            } else {
                // This triangle crosses constraint so lets flippin start!
                FlipEdgeEvent(tcx, ep, eq, triangle, point);
            }
        }
Пример #24
0
        /// <summary>
        /// Scan part of the FlipScan algorithm<br>
        /// When a triangle pair isn't flippable we will scan for the next
        /// point that is inside the flip triangle scan area. When found
        /// we generate a new flipEdgeEvent
        /// </summary>
        /// <param name="tcx"></param>
        /// <param name="ep">last point on the edge we are traversing</param>
        /// <param name="eq">first point on the edge we are traversing</param>
        /// <param name="flipTriangle">the current triangle sharing the point eq with edge</param>
        /// <param name="t"></param>
        /// <param name="p"></param>
        private static void FlipScanEdgeEvent(DTSweepContext tcx, TriangulationPoint ep, TriangulationPoint eq, DelaunayTriangle flipTriangle, DelaunayTriangle t, TriangulationPoint p)
        {
            DelaunayTriangle   ot = t.NeighborAcross(p);
            TriangulationPoint op = ot.OppositePoint(t, p);

            if (ot == null)
            {
                // If we want to integrate the fillEdgeEvent do it here
                // With current implementation we should never get here
                throw new Exception("[BUG:FIXME] FLIP failed due to missing triangle");
            }

            bool inScanArea = TriangulationUtil.InScanArea(eq, flipTriangle.PointCCW(eq), flipTriangle.PointCW(eq), op);

            if (inScanArea)
            {
                // flip with new edge op->eq
                FlipEdgeEvent(tcx, eq, op, ot, op);
                // TODO: Actually I just figured out that it should be possible to
                //       improve this by getting the next ot and op before the the above
                //       flip and continue the flipScanEdgeEvent here
                // set new ot and op here and loop back to inScanArea test
                // also need to set a new flipTriangle first
                // Turns out at first glance that this is somewhat complicated
                // so it will have to wait.
            }
            else
            {
                TriangulationPoint newP = NextFlipPoint(ep, eq, ot, op);
                FlipScanEdgeEvent(tcx, ep, eq, flipTriangle, ot, newP);
            }
        }
Пример #25
0
        /// <summary>
        /// Creates a new front triangle and legalize it
        /// </summary>
        private static AdvancingFrontNode NewFrontTriangle( DTSweepContext tcx, TriangulationPoint point, AdvancingFrontNode node )
        {
            AdvancingFrontNode newNode;
            DelaunayTriangle triangle;

            triangle = new DelaunayTriangle(point, node.Point, node.Next.Point);
            triangle.MarkNeighbor(node.Triangle);
            tcx.Triangles.Add(triangle);

            newNode = new AdvancingFrontNode(point) {Next = node.Next, Prev = node};
            node.Next.Prev = newNode;
            node.Next = newNode;

            tcx.AddNode(newNode); // XXX: BST

            if (tcx.IsDebugEnabled) tcx.DTDebugContext.ActiveNode = newNode;

            if (!Legalize(tcx, triangle)) tcx.MapTriangleToNodes(triangle);

            return newNode;
        }
Пример #26
0
 /// <summary>
 /// When we need to traverse from one triangle to the next we need 
 /// the point in current triangle that is the opposite point to the next
 /// triangle. 
 /// </summary>
 private static TriangulationPoint NextFlipPoint( TriangulationPoint ep, TriangulationPoint eq, DelaunayTriangle ot, TriangulationPoint op )
 {
     Orientation o2d = TriangulationUtil.Orient2d(eq, op, ep);
     switch ( o2d ) {
     case Orientation.CW: return ot.PointCCWFrom(op);
     case Orientation.CCW: return ot.PointCWFrom(op);
     case Orientation.Collinear:
         // TODO: implement support for point on constraint edge
         throw new PointOnEdgeException("Point on constrained edge not supported yet",eq,op,ep);
     default:
         throw new NotImplementedException("Orientation not handled");
     }
 }
Пример #27
0
        public static GameObject CreateSurface(string name, Polygon poly, Material material, Rect rect, Vector2 textureScale, Vector2 textureOffset, float textureRotation, DisposalManager disposalManager)
        {
            GameObject hexa = new GameObject(name, typeof(MeshRenderer), typeof(MeshFilter));

            int triCount = poly.Triangles.Count;

            if (newPoints == null)
            {
                newPoints = new List <Vector3> (triCount * 3);
            }
            else
            {
                newPoints.Clear();
            }
            int[] triNew         = new int[triCount * 3];
            int   newPointsCount = -1;

            if (hit == null)
            {
                hit = new Dictionary <Vector3, int> (20000);
            }
            else
            {
                hit.Clear();
            }
            Vector3 p;

            p.z = 0;
            for (int k = 0; k < triCount; k++)
            {
                DelaunayTriangle dt = poly.Triangles [k];
                int ptmp;
                p.x = dt.Points [0].Xf;
                p.y = dt.Points [0].Yf;
                if (hit.TryGetValue(p, out ptmp))
                {
                    triNew [k * 3] = ptmp;
                }
                else
                {
                    newPoints.Add(p);
                    hit [p]        = ++newPointsCount;
                    triNew [k * 3] = newPointsCount;
                }
                p.x = dt.Points [2].Xf;
                p.y = dt.Points [2].Yf;
                if (hit.TryGetValue(p, out ptmp))
                {
                    triNew [k * 3 + 1] = ptmp;
                }
                else
                {
                    newPoints.Add(p);
                    hit [p]            = ++newPointsCount;
                    triNew [k * 3 + 1] = newPointsCount;
                }
                p.x = dt.Points [1].Xf;
                p.y = dt.Points [1].Yf;
                if (hit.TryGetValue(p, out ptmp))
                {
                    triNew [k * 3 + 2] = ptmp;
                }
                else
                {
                    newPoints.Add(p);
                    hit [p]            = ++newPointsCount;
                    triNew [k * 3 + 2] = newPointsCount;
                }
            }

            Mesh mesh = new Mesh();

            if (disposalManager != null)
            {
                if (disposalManager != null)
                {
                    disposalManager.MarkForDisposal(hexa);
                }
                if (disposalManager != null)
                {
                    disposalManager.MarkForDisposal(mesh);
                }
            }
            hexa.hideFlags |= HideFlags.HideInHierarchy;

            mesh.SetVertices(newPoints);
            // uv mapping
            if (material.mainTexture != null)
            {
                Vector2[] uv = new Vector2[newPoints.Count];
                for (int k = 0; k < uv.Length; k++)
                {
                    Vector2 coor = newPoints [k];
                    coor.x /= textureScale.x;
                    coor.y /= textureScale.y;
                    if (textureRotation != 0)
                    {
                        coor = RotatePoint(coor, Misc.Vector2zero, textureRotation);
                    }
                    coor    += textureOffset;
                    uv [k].x = (coor.x - rect.xMin) / rect.width;
                    uv [k].y = (coor.y - rect.yMax) / rect.height;
                }
                mesh.uv = uv;
            }
            mesh.SetTriangles(triNew, 0);
            mesh.RecalculateNormals();

            MeshFilter meshFilter = hexa.GetComponent <MeshFilter> ();

            meshFilter.mesh = mesh;

            hexa.GetComponent <MeshRenderer> ().sharedMaterial = material;
            return(hexa);
        }
Пример #28
0
 /// <summary>
 /// Try to map a node to all sides of this triangle that don't have 
 /// a neighbor.
 /// </summary>
 public void MapTriangleToNodes(DelaunayTriangle t)
 {
     AdvancingFrontNode n;
     for (int i = 0; i < 3; i++)
     {
         if (t.Neighbors[i] == null)
         {
             n = aFront.LocatePoint(t.PointCW(t.Points[i]));
             if (n != null)
             {
                 n.Triangle = t;
             }
         }
     }
 }
Пример #29
0
        private void CutPoly(Int3[] verts, int[] tris, ref Int3[] outVertsArr, ref int[] outTrisArr, out int outVCount, out int outTCount, Int3[] extraShape, Int3 cuttingOffset, Bounds realBounds, TileHandler.CutMode mode = TileHandler.CutMode.CutAll | TileHandler.CutMode.CutDual, 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 & TileHandler.CutMode.CutExtra) != (TileHandler.CutMode) 0)
            {
                throw new Exception("extraShape is null and the CutMode specifies that it should be used. Cannot use null shape.");
            }
            if ((mode & TileHandler.CutMode.CutExtra) != (TileHandler.CutMode) 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>();

            Pathfinding.IntRect b = new Pathfinding.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 <Pathfinding.Poly2Tri.Polygon> stack = new Stack <Pathfinding.Poly2Tri.Polygon>();

            this.clipper = (this.clipper ?? new Clipper(0));
            this.clipper.ReverseSolution = true;
            this.clipper.StrictlySimple  = true;
            List <NavmeshCut> list7;

            if (mode == TileHandler.CutMode.CutExtra)
            {
                list7 = ListPool <NavmeshCut> .Claim();
            }
            else
            {
                list7 = NavmeshCut.GetAllInRange(realBounds);
            }
            List <int> list8 = ListPool <int> .Claim();

            List <Pathfinding.IntRect> list9 = ListPool <Pathfinding.IntRect> .Claim();

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

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

            List <bool> list13 = 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 < list7.Count; k++)
            {
                Bounds bounds         = list7[k].GetBounds();
                Int3   @int           = (Int3)bounds.min + cuttingOffset;
                Int3   int2           = (Int3)bounds.max + cuttingOffset;
                Pathfinding.IntRect a = new Pathfinding.IntRect(@int.x, @int.z, int2.x, int2.z);
                if (Pathfinding.IntRect.Intersects(a, b))
                {
                    Int2 int3 = new Int2(0, 0);
                    if (perturbate > 0)
                    {
                        int3.x = random.Next() % 6 * perturbate - 3 * perturbate;
                        if (int3.x >= 0)
                        {
                            int3.x++;
                        }
                        int3.y = random.Next() % 6 * perturbate - 3 * perturbate;
                        if (int3.y >= 0)
                        {
                            int3.y++;
                        }
                    }
                    int count = list11.Count;
                    list7[k].GetContour(list11);
                    for (int l = count; l < list11.Count; l++)
                    {
                        List <IntPoint> list14 = list11[l];
                        if (list14.Count == 0)
                        {
                            Debug.LogError("Zero Length Contour");
                            list9.Add(default(Pathfinding.IntRect));
                            list10.Add(new Int2(0, 0));
                        }
                        else
                        {
                            Pathfinding.IntRect item = new Pathfinding.IntRect((int)list14[0].X + cuttingOffset.x, (int)list14[0].Y + cuttingOffset.y, (int)list14[0].X + cuttingOffset.x, (int)list14[0].Y + cuttingOffset.y);
                            for (int m = 0; m < list14.Count; m++)
                            {
                                IntPoint value = list14[m];
                                value.X += (long)cuttingOffset.x;
                                value.Y += (long)cuttingOffset.z;
                                if (perturbate > 0)
                                {
                                    value.X += (long)int3.x;
                                    value.Y += (long)int3.y;
                                }
                                list14[m] = value;
                                item      = item.ExpandToContain((int)value.X, (int)value.Y);
                            }
                            list10.Add(new Int2(@int.y, int2.y));
                            list9.Add(item);
                            list12.Add(list7[k].isDual);
                            list13.Add(list7[k].cutsAddedGeom);
                        }
                    }
                }
            }
            List <NavmeshAdd> allInRange = NavmeshAdd.GetAllInRange(realBounds);

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

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

            if (allInRange.Count > 0)
            {
                array3 = new Int3[7];
                array4 = new Int3[7];
                int4   = (Int3)realBounds.extents;
            }
            while (true)
            {
                n += 3;
                while (n >= array2.Length)
                {
                    num++;
                    n = 0;
                    if (num >= allInRange.Count)
                    {
                        array = null;
                        break;
                    }
                    if (array == verts)
                    {
                        array = null;
                    }
                    allInRange[num].GetMesh(cuttingOffset, ref array, out array2);
                }
                if (array == null)
                {
                    break;
                }
                Int3 int5 = array[array2[n]];
                Int3 int6 = array[array2[n + 1]];
                Int3 int7 = array[array2[n + 2]];
                Pathfinding.IntRect a2 = new Pathfinding.IntRect(int5.x, int5.z, int5.x, int5.z);
                a2 = a2.ExpandToContain(int6.x, int6.z);
                a2 = a2.ExpandToContain(int7.x, int7.z);
                int num2 = Math.Min(int5.y, Math.Min(int6.y, int7.y));
                int num3 = Math.Max(int5.y, Math.Max(int6.y, int7.y));
                list8.Clear();
                bool flag = false;
                for (int num4 = 0; num4 < list11.Count; num4++)
                {
                    int x = list10[num4].x;
                    int y = list10[num4].y;
                    if (Pathfinding.IntRect.Intersects(a2, list9[num4]) && y >= num2 && x <= num3 && (list13[num4] || num == -1))
                    {
                        Int3 int8 = int5;
                        int8.y = x;
                        Int3 int9 = int5;
                        int9.y = y;
                        list8.Add(num4);
                        flag |= list12[num4];
                    }
                }
                if (list8.Count == 0 && (mode & TileHandler.CutMode.CutExtra) == (TileHandler.CutMode) 0 && (mode & TileHandler.CutMode.CutAll) != (TileHandler.CutMode) 0 && num == -1)
                {
                    list5.Add(list4.Count);
                    list5.Add(list4.Count + 1);
                    list5.Add(list4.Count + 2);
                    list4.Add(int5);
                    list4.Add(int6);
                    list4.Add(int7);
                }
                else
                {
                    list2.Clear();
                    if (num == -1)
                    {
                        list2.Add(new IntPoint((long)int5.x, (long)int5.z));
                        list2.Add(new IntPoint((long)int6.x, (long)int6.z));
                        list2.Add(new IntPoint((long)int7.x, (long)int7.z));
                    }
                    else
                    {
                        array3[0] = int5;
                        array3[1] = int6;
                        array3[2] = int7;
                        int num5 = Utility.ClipPolygon(array3, 3, array4, 1, 0, 0);
                        if (num5 == 0)
                        {
                            continue;
                        }
                        num5 = Utility.ClipPolygon(array4, num5, array3, -1, 2 * int4.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 * int4.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 int10 = int6 - int5;
                    Int3 int11 = int7 - int5;
                    Int3 int12 = int10;
                    Int3 int13 = int11;
                    int12.y = 0;
                    int13.y = 0;
                    for (int num7 = 0; num7 < 16; num7++)
                    {
                        if ((mode >> (num7 & 31) & TileHandler.CutMode.CutAll) != (TileHandler.CutMode) 0)
                        {
                            if (1 << num7 == 1)
                            {
                                this.clipper.Clear();
                                this.clipper.AddPolygon(list2, PolyType.ptSubject);
                                for (int num8 = 0; num8 < list8.Count; num8++)
                                {
                                    this.clipper.AddPolygon(list11[list8[num8]], PolyType.ptClip);
                                }
                                polyTree.Clear();
                                this.clipper.Execute(ClipType.ctDifference, polyTree, PolyFillType.pftEvenOdd, PolyFillType.pftNonZero);
                            }
                            else if (1 << num7 == 2)
                            {
                                if (!flag)
                                {
                                    goto IL_1174;
                                }
                                this.clipper.Clear();
                                this.clipper.AddPolygon(list2, PolyType.ptSubject);
                                for (int num9 = 0; num9 < list8.Count; num9++)
                                {
                                    if (list12[list8[num9]])
                                    {
                                        this.clipper.AddPolygon(list11[list8[num9]], PolyType.ptClip);
                                    }
                                }
                                list6.Clear();
                                this.clipper.Execute(ClipType.ctIntersection, list6, PolyFillType.pftEvenOdd, PolyFillType.pftNonZero);
                                this.clipper.Clear();
                                for (int num10 = 0; num10 < list6.Count; num10++)
                                {
                                    this.clipper.AddPolygon(list6[num10], (!Clipper.Orientation(list6[num10])) ? PolyType.ptSubject : PolyType.ptClip);
                                }
                                for (int num11 = 0; num11 < list8.Count; num11++)
                                {
                                    if (!list12[list8[num11]])
                                    {
                                        this.clipper.AddPolygon(list11[list8[num11]], PolyType.ptClip);
                                    }
                                }
                                polyTree.Clear();
                                this.clipper.Execute(ClipType.ctDifference, polyTree, PolyFillType.pftEvenOdd, PolyFillType.pftNonZero);
                            }
                            else if (1 << num7 == 4)
                            {
                                this.clipper.Clear();
                                this.clipper.AddPolygon(list2, PolyType.ptSubject);
                                this.clipper.AddPolygon(list, PolyType.ptClip);
                                polyTree.Clear();
                                this.clipper.Execute(ClipType.ctIntersection, polyTree, PolyFillType.pftEvenOdd, 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   item2 = new Int3((int)contour[num13].X, 0, (int)contour[num13].Y);
                                        double num14 = (double)(int6.z - int7.z) * (double)(int5.x - int7.x) + (double)(int7.x - int6.x) * (double)(int5.z - int7.z);
                                        if (num14 == 0.0)
                                        {
                                            Debug.LogWarning("Degenerate triangle");
                                        }
                                        else
                                        {
                                            double num15 = ((double)(int6.z - int7.z) * (double)(item2.x - int7.x) + (double)(int7.x - int6.x) * (double)(item2.z - int7.z)) / num14;
                                            double num16 = ((double)(int7.z - int5.z) * (double)(item2.x - int7.x) + (double)(int5.x - int7.x) * (double)(item2.z - int7.z)) / num14;
                                            item2.y = (int)Math.Round(num15 * (double)int5.y + num16 * (double)int6.y + (1.0 - num15 - num16) * (double)int7.y);
                                            list5.Add(list4.Count);
                                            list4.Add(item2);
                                        }
                                    }
                                }
                                else
                                {
                                    Pathfinding.Poly2Tri.Polygon polygon = null;
                                    int num17 = -1;
                                    for (List <IntPoint> list15 = contour; list15 != null; list15 = ((num17 >= childs.Count) ? null : childs[num17].Contour))
                                    {
                                        list3.Clear();
                                        for (int num18 = 0; num18 < list15.Count; num18++)
                                        {
                                            PolygonPoint polygonPoint = new PolygonPoint((double)list15[num18].X, (double)list15[num18].Y);
                                            list3.Add(polygonPoint);
                                            Int3   item3 = new Int3((int)list15[num18].X, 0, (int)list15[num18].Y);
                                            double num19 = (double)(int6.z - int7.z) * (double)(int5.x - int7.x) + (double)(int7.x - int6.x) * (double)(int5.z - int7.z);
                                            if (num19 == 0.0)
                                            {
                                                Debug.LogWarning("Degenerate triangle");
                                            }
                                            else
                                            {
                                                double num20 = ((double)(int6.z - int7.z) * (double)(item3.x - int7.x) + (double)(int7.x - int6.x) * (double)(item3.z - int7.z)) / num19;
                                                double num21 = ((double)(int7.z - int5.z) * (double)(item3.x - int7.x) + (double)(int5.x - int7.x) * (double)(item3.z - int7.z)) / num19;
                                                item3.y = (int)Math.Round(num20 * (double)int5.y + num21 * (double)int6.y + (1.0 - num20 - num21) * (double)int7.y);
                                                dictionary[polygonPoint] = list4.Count;
                                                list4.Add(item3);
                                            }
                                        }
                                        Pathfinding.Poly2Tri.Polygon polygon2;
                                        if (stack.Count > 0)
                                        {
                                            polygon2 = stack.Pop();
                                            polygon2.AddPoints(list3);
                                        }
                                        else
                                        {
                                            polygon2 = new Pathfinding.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(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_1174 :;
                    }
                }
            }
            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 < list7.Count; num29++)
            {
                list7[num29].UsedForCut();
            }
            ListPool <Int3> .Release(list4);

            ListPool <int> .Release(list5);

            ListPool <int> .Release(list8);

            ListPool <Int2> .Release(list10);

            ListPool <bool> .Release(list12);

            ListPool <bool> .Release(list13);

            ListPool <Pathfinding.IntRect> .Release(list9);

            ListPool <NavmeshCut> .Release(list7);
        }
Пример #30
0
        public void CreateAdvancingFront()
        {
            AdvancingFrontNode head, tail, middle;
            // Initial triangle
            DelaunayTriangle iTriangle = new DelaunayTriangle(Points[0], Tail, Head);
            Triangles.Add(iTriangle);

            head = new AdvancingFrontNode(iTriangle.Points[1]);
            head.Triangle = iTriangle;
            middle = new AdvancingFrontNode(iTriangle.Points[0]);
            middle.Triangle = iTriangle;
            tail = new AdvancingFrontNode(iTriangle.Points[2]);

            aFront = new AdvancingFront(head, tail);
            aFront.AddNode(middle);

            // TODO: I think it would be more intuitive if head is middles next and not previous
            //       so swap head and tail
            aFront.Head.Next = middle;
            middle.Next = aFront.Tail;
            middle.Prev = aFront.Head;
            aFront.Tail.Prev = middle;
        }
Пример #31
0
 public void MeshClean(DelaunayTriangle triangle)
 {
     MeshCleanReq(triangle);
 }
 public override void Clear()
 {
     PrimaryTriangle = null;
     SecondaryTriangle = null;
     ActivePoint = null;
     ActiveNode = null;
     ActiveConstraint = null;
 }
Пример #33
0
 public void AddTriangle(DelaunayTriangle t)
 {
     _triangles.Add(t);
 }
Пример #34
0
        private static void EdgeEvent(DTSweepContext tcx, TriangulationPoint ep, TriangulationPoint eq, DelaunayTriangle triangle, TriangulationPoint point)
        {
            if (IsEdgeSideOfTriangle(triangle, ep, eq))
                return;

            TriangulationPoint p1 = triangle.PointCCW(point);
            Orientation o1 = TriangulationUtil.Orient2d(eq, p1, ep);
            if (o1 == Orientation.Collinear)
            {
                if (triangle.Contains(eq, p1))
                {
                    triangle.MarkConstrainedEdge(eq, p1);
                    // We are modifying the constraint maybe it would be better to
                    // not change the given constraint and just keep a variable for the new constraint
                    tcx.EdgeEvent.ConstrainedEdge.Q = p1;
                    triangle = triangle.NeighborAcross(point);
                    EdgeEvent(tcx, ep, p1, triangle, p1);
                }
                else
                {
                    throw new PointOnEdgeException("EdgeEvent - Point on constrained edge not supported yet");
                }
                return;
            }

            TriangulationPoint p2 = triangle.PointCW(point);
            Orientation o2 = TriangulationUtil.Orient2d(eq, p2, ep);
            if (o2 == Orientation.Collinear)
            {
                if (triangle.Contains(eq, p2))
                {
                    triangle.MarkConstrainedEdge(eq, p2);
                    // We are modifying the constraint maybe it would be better to
                    // not change the given constraint and just keep a variable for the new constraint
                    tcx.EdgeEvent.ConstrainedEdge.Q = p2;
                    triangle = triangle.NeighborAcross(point);
                    EdgeEvent(tcx, ep, p2, triangle, p2);
                }
                else
                {
                    throw new PointOnEdgeException("EdgeEvent - Point on constrained edge not supported yet");
                }
                return;
            }

            if (o1 == o2)
            {
                // Need to decide if we are rotating CW or CCW to get to a triangle
                // that will cross edge
                if (o1 == Orientation.CW)
                {
                    triangle = triangle.NeighborCCW(point);
                }
                else
                {
                    triangle = triangle.NeighborCW(point);
                }
                EdgeEvent(tcx, ep, eq, triangle, point);
            }
            else
            {
                // This triangle crosses constraint so lets flippin start!
                FlipEdgeEvent(tcx, ep, eq, triangle, point);
            }
        }
Пример #35
0
        /// <summary>
        /// Returns true if triangle was legalized
        /// </summary>
        private static bool Legalize(DTSweepContext tcx, DelaunayTriangle t)
        {
            // To legalize a triangle we start by finding if any of the three edges
            // violate the Delaunay condition
            for (int i = 0; i < 3; i++)
            {
                // TODO: fix so that cEdge is always valid when creating new triangles then we can check it here
                //       instead of below with ot
                if (t.EdgeIsDelaunay[i])
                {
                    continue;
                }

                DelaunayTriangle ot = t.Neighbors[i];
                if (ot != null)
                {
                    TriangulationPoint p  = t.Points[i];
                    TriangulationPoint op = ot.OppositePoint(t, p);
                    int oi = ot.IndexOf(op);
                    // If this is a Constrained Edge or a Delaunay Edge(only during recursive legalization)
                    // then we should not try to legalize
                    if (ot.EdgeIsConstrained[oi] || ot.EdgeIsDelaunay[oi])
                    {
                        t.EdgeIsConstrained[i] = ot.EdgeIsConstrained[oi];
                        // XXX: have no good way of setting this property when creating new triangles so lets set it here
                        continue;
                    }

                    bool inside = TriangulationUtil.SmartIncircle(p, t.PointCCW(p), t.PointCW(p), op);

                    if (inside)
                    {
                        // Lets mark this shared edge as Delaunay
                        t.EdgeIsDelaunay[i]   = true;
                        ot.EdgeIsDelaunay[oi] = true;

                        // Lets rotate shared edge one vertex CW to legalize it
                        RotateTrianglePair(t, p, ot, op);

                        // We now got one valid Delaunay Edge shared by two triangles
                        // This gives us 4 new edges to check for Delaunay

                        // Make sure that triangle to node mapping is done only one time for a specific triangle
                        bool notLegalized = !Legalize(tcx, t);

                        if (notLegalized)
                        {
                            tcx.MapTriangleToNodes(t);
                        }
                        notLegalized = !Legalize(tcx, ot);
                        if (notLegalized)
                        {
                            tcx.MapTriangleToNodes(ot);
                        }

                        // Reset the Delaunay edges, since they only are valid Delaunay edges
                        // until we add a new triangle or point.
                        // XXX: need to think about this. Can these edges be tried after we
                        //      return to previous recursive level?
                        t.EdgeIsDelaunay[i]   = false;
                        ot.EdgeIsDelaunay[oi] = false;

                        // If triangle have been legalized no need to check the other edges since
                        // the recursive legalization will handles those so we can end here.
                        return(true);
                    }
                }
            }
            return(false);
        }
Пример #36
0
        private static void FlipEdgeEvent(DTSweepContext tcx, TriangulationPoint ep, TriangulationPoint eq, DelaunayTriangle t, TriangulationPoint p)
        {
            DelaunayTriangle ot = t.NeighborAcross(p);
            TriangulationPoint op = ot.OppositePoint(t, p);

            if (ot == null)
            {
                // If we want to integrate the fillEdgeEvent do it here
                // With current implementation we should never get here
                throw new InvalidOperationException("[BUG:FIXME] FLIP failed due to missing triangle");
            }

            if (t.GetConstrainedEdgeAcross(p))
            {
                throw new Exception("Intersecting Constraints");
            }

            bool inScanArea = TriangulationUtil.InScanArea(p, t.PointCCW(p), t.PointCW(p), op);
            if (inScanArea)
            {
                // Lets rotate shared edge one vertex CW
                RotateTrianglePair(t, p, ot, op);
                tcx.MapTriangleToNodes(t);
                tcx.MapTriangleToNodes(ot);

                if (p == eq && op == ep)
                {
                    if (eq == tcx.EdgeEvent.ConstrainedEdge.Q
                        && ep == tcx.EdgeEvent.ConstrainedEdge.P)
                    {
                        t.MarkConstrainedEdge(ep, eq);
                        ot.MarkConstrainedEdge(ep, eq);
                        Legalize(tcx, t);
                        Legalize(tcx, ot);
                    }
                    else
                    {
                        // XXX: I think one of the triangles should be legalized here?
                    }
                }
                else
                {
                    // TODO: remove
                    Orientation o = TriangulationUtil.Orient2d(eq, op, ep);
                    t = NextFlipTriangle(tcx, o, t, ot, p, op);
                    FlipEdgeEvent(tcx, ep, eq, t, p);
                }
            }
            else
            {
                TriangulationPoint newP = NextFlipPoint(ep, eq, ot, op);
                FlipScanEdgeEvent(tcx, ep, eq, t, ot, newP);
                EdgeEvent(tcx, ep, eq, t, p);
            }
        }
Пример #37
0
        /// <summary>
        /// Rotates a triangle pair one vertex CW
        ///       n2                    n2
        ///  P +-----+             P +-----+
        ///    | t  /|               |\  t |
        ///    |   / |               | \   |
        ///  n1|  /  |n3           n1|  \  |n3
        ///    | /   |    after CW   |   \ |
        ///    |/ oT |               | oT \|
        ///    +-----+ oP            +-----+
        ///       n4                    n4
        /// </summary>
        private static void RotateTrianglePair(DelaunayTriangle t, TriangulationPoint p, DelaunayTriangle ot, TriangulationPoint op)
        {
            DelaunayTriangle n1 = t.NeighborCCW(p);
            DelaunayTriangle n2 = t.NeighborCW(p);
            DelaunayTriangle n3 = ot.NeighborCCW(op);
            DelaunayTriangle n4 = ot.NeighborCW(op);

            bool ce1 = t.GetConstrainedEdgeCCW(p);
            bool ce2 = t.GetConstrainedEdgeCW(p);
            bool ce3 = ot.GetConstrainedEdgeCCW(op);
            bool ce4 = ot.GetConstrainedEdgeCW(op);

            bool de1 = t.GetDelaunayEdgeCCW(p);
            bool de2 = t.GetDelaunayEdgeCW(p);
            bool de3 = ot.GetDelaunayEdgeCCW(op);
            bool de4 = ot.GetDelaunayEdgeCW(op);

            t.Legalize(p, op);
            ot.Legalize(op, p);

            // Remap dEdge
            ot.SetDelaunayEdgeCCW(p, de1);
            t.SetDelaunayEdgeCW(p, de2);
            t.SetDelaunayEdgeCCW(op, de3);
            ot.SetDelaunayEdgeCW(op, de4);

            // Remap cEdge
            ot.SetConstrainedEdgeCCW(p, ce1);
            t.SetConstrainedEdgeCW(p, ce2);
            t.SetConstrainedEdgeCCW(op, ce3);
            ot.SetConstrainedEdgeCW(op, ce4);

            // Remap neighbors
            // XXX: might optimize the markNeighbor by keeping track of
            //      what side should be assigned to what neighbor after the
            //      rotation. Now mark neighbor does lots of testing to find
            //      the right side.
            t.Neighbors.Clear();
            ot.Neighbors.Clear();
            if (n1 != null)
            {
                ot.MarkNeighbor(n1);
            }
            if (n2 != null)
            {
                t.MarkNeighbor(n2);
            }
            if (n3 != null)
            {
                t.MarkNeighbor(n3);
            }
            if (n4 != null)
            {
                ot.MarkNeighbor(n4);
            }
            t.MarkNeighbor(ot);
        }
Пример #38
0
 private static bool IsEdgeSideOfTriangle(DelaunayTriangle triangle, TriangulationPoint ep, TriangulationPoint eq)
 {
     int index = triangle.EdgeIndex(ep, eq);
     if (index != -1)
     {
         triangle.MarkConstrainedEdge(index);
         triangle = triangle.Neighbors[index];
         if (triangle != null)
         {
             triangle.MarkConstrainedEdge(ep, eq);
         }
         return true;
     }
     return false;
 }
Пример #39
0
        private static void EdgeEvent(DTSweepContext tcx, TriangulationPoint ep, TriangulationPoint eq, DelaunayTriangle triangle, TriangulationPoint point)
        {
            if (IsEdgeSideOfTriangle(triangle, ep, eq))
            {
                return;
            }

            TriangulationPoint p1 = triangle.PointCCW(point);
            Orientation        o1 = TriangulationUtil.Orient2d(eq, p1, ep);

            if (o1 == Orientation.Collinear)
            {
                if (triangle.Contains(eq, p1))
                {
                    triangle.MarkConstrainedEdge(eq, p1);
                    // We are modifying the constraint maybe it would be better to
                    // not change the given constraint and just keep a variable for the new constraint
                    tcx.EdgeEvent.ConstrainedEdge.Q = p1;
                    triangle = triangle.NeighborAcross(point);
                    EdgeEvent(tcx, ep, p1, triangle, p1);
                }
                else
                {
                    throw new PointOnEdgeException("EdgeEvent - Point on constrained edge not supported yet");
                }
                if (tcx.IsDebugEnabled)
                {
                    Debug.WriteLine("EdgeEvent - Point on constrained edge");
                }
                return;
            }

            TriangulationPoint p2 = triangle.PointCW(point);
            Orientation        o2 = TriangulationUtil.Orient2d(eq, p2, ep);

            if (o2 == Orientation.Collinear)
            {
                if (triangle.Contains(eq, p2))
                {
                    triangle.MarkConstrainedEdge(eq, p2);
                    // We are modifying the constraint maybe it would be better to
                    // not change the given constraint and just keep a variable for the new constraint
                    tcx.EdgeEvent.ConstrainedEdge.Q = p2;
                    triangle = triangle.NeighborAcross(point);
                    EdgeEvent(tcx, ep, p2, triangle, p2);
                }
                else
                {
                    throw new PointOnEdgeException("EdgeEvent - Point on constrained edge not supported yet");
                }
                if (tcx.IsDebugEnabled)
                {
                    Debug.WriteLine("EdgeEvent - Point on constrained edge");
                }
                return;
            }

            if (o1 == o2)
            {
                // Need to decide if we are rotating CW or CCW to get to a triangle
                // that will cross edge
                if (o1 == Orientation.CW)
                {
                    triangle = triangle.NeighborCCW(point);
                }
                else
                {
                    triangle = triangle.NeighborCW(point);
                }
                EdgeEvent(tcx, ep, eq, triangle, point);
            }
            else
            {
                // This triangle crosses constraint so lets flippin start!
                FlipEdgeEvent(tcx, ep, eq, triangle, point);
            }
        }
Пример #40
0
        /// <summary>
        /// Creates a new front triangle and legalize it
        /// </summary>
        private static AdvancingFrontNode NewFrontTriangle(DTSweepContext tcx, TriangulationPoint point, AdvancingFrontNode node)
        {
            DelaunayTriangle triangle = new DelaunayTriangle(point, node.Point, node.Next.Point);
            triangle.MarkNeighbor(node.Triangle);
            tcx.Triangles.Add(triangle);

            AdvancingFrontNode newNode = new AdvancingFrontNode(point);
            newNode.Next = node.Next;
            newNode.Prev = node;
            node.Next.Prev = newNode;
            node.Next = newNode;

            tcx.AddNode(newNode); // XXX: BST

            if (!Legalize(tcx, triangle))
            {
                tcx.MapTriangleToNodes(triangle);
            }

            return newNode;
        }
Пример #41
0
        private static void FlipEdgeEvent(DTSweepContext tcx, TriangulationPoint ep, TriangulationPoint eq, DelaunayTriangle t, TriangulationPoint p)
        {
            DelaunayTriangle   ot = t.NeighborAcross(p);
            TriangulationPoint op = ot.OppositePoint(t, p);

            if (ot == null)
            {
                // If we want to integrate the fillEdgeEvent do it here
                // With current implementation we should never get here
                throw new InvalidOperationException("[BUG:FIXME] FLIP failed due to missing triangle");
            }

            if (t.GetConstrainedEdgeAcross(p))
            {
                throw new Exception("Intersecting Constraints");
            }

            bool inScanArea = TriangulationUtil.InScanArea(p, t.PointCCW(p), t.PointCW(p), op);

            if (inScanArea)
            {
                // Lets rotate shared edge one vertex CW
                RotateTrianglePair(t, p, ot, op);
                tcx.MapTriangleToNodes(t);
                tcx.MapTriangleToNodes(ot);

                if (p == eq && op == ep)
                {
                    if (eq == tcx.EdgeEvent.ConstrainedEdge.Q &&
                        ep == tcx.EdgeEvent.ConstrainedEdge.P)
                    {
                        if (tcx.IsDebugEnabled)
                        {
                            Console.WriteLine("[FLIP] - constrained edge done");                     // TODO: remove
                        }
                        t.MarkConstrainedEdge(ep, eq);
                        ot.MarkConstrainedEdge(ep, eq);
                        Legalize(tcx, t);
                        Legalize(tcx, ot);
                    }
                    else
                    {
                        if (tcx.IsDebugEnabled)
                        {
                            Console.WriteLine("[FLIP] - subedge done");                     // TODO: remove
                        }
                        // XXX: I think one of the triangles should be legalized here?
                    }
                }
                else
                {
                    if (tcx.IsDebugEnabled)
                    {
                        Console.WriteLine("[FLIP] - flipping and continuing with triangle still crossing edge");
                    }
                    // TODO: remove
                    Orientation o = TriangulationUtil.Orient2d(eq, op, ep);
                    t = NextFlipTriangle(tcx, o, t, ot, p, op);
                    FlipEdgeEvent(tcx, ep, eq, t, p);
                }
            }
            else
            {
                TriangulationPoint newP = NextFlipPoint(ep, eq, ot, op);
                FlipScanEdgeEvent(tcx, ep, eq, t, ot, newP);
                EdgeEvent(tcx, ep, eq, t, p);
            }
        }
Пример #42
0
 /// <summary>
 /// After a flip we have two triangles and know that only one will still be
 /// intersecting the edge. So decide which to contiune with and legalize the other
 /// </summary>
 /// <param name="tcx"></param>
 /// <param name="o">should be the result of an TriangulationUtil.orient2d( eq, op, ep )</param>
 /// <param name="t">triangle 1</param>
 /// <param name="ot">triangle 2</param>
 /// <param name="p">a point shared by both triangles</param>
 /// <param name="op">another point shared by both triangles</param>
 /// <returns>returns the triangle still intersecting the edge</returns>
 private static DelaunayTriangle NextFlipTriangle(DTSweepContext tcx, Orientation o, DelaunayTriangle t, DelaunayTriangle ot, TriangulationPoint p, TriangulationPoint op)
 {
     int edgeIndex;
     if (o == Orientation.CCW)
     {
         // ot is not crossing edge after flip
         edgeIndex = ot.EdgeIndex(p, op);
         ot.EdgeIsDelaunay[edgeIndex] = true;
         Legalize(tcx, ot);
         ot.EdgeIsDelaunay.Clear();
         return t;
     }
     // t is not crossing edge after flip
     edgeIndex = t.EdgeIndex(p, op);
     t.EdgeIsDelaunay[edgeIndex] = true;
     Legalize(tcx, t);
     t.EdgeIsDelaunay.Clear();
     return ot;
 }
Пример #43
0
 public virtual void AddTriangle(DelaunayTriangle t)
 {
     Triangles.Add(t);
 }