Esempio n. 1
0
        List <List <IntPoint> > PolygonsFromRoadOutline(float extensionDistance)
        {
            var polygons = new List <List <IntPoint> >();
            var rnd      = Parameters.roadNetworkDescription;

            foreach (var road in rnd.AllRoads)
            {
                var points = GeometrySampling.BuildSamplesFromRoadOutlineWithExtensionDistance(
                    road, 0.5f, extensionDistance, Parameters.outermostLaneType);
                var path = new List <IntPoint>(points.Length);
                foreach (var point in points)
                {
                    path.Add(new IntPoint(
                                 point.pose.pos.x * PlacementUtility.UpScaleFactor,
                                 point.pose.pos.z * PlacementUtility.UpScaleFactor));
                }

                if (!Clipper.Orientation(path))
                {
                    path.Reverse();
                }

                polygons.Add(path);

                points.Dispose();
            }

            return(polygons);
        }
Esempio n. 2
0
        //------------------------------------------------------------------------------

        private void FixOrientations()
        {
            //fixup orientations of all closed paths if the orientation of the
            //closed path with the lowermost vertex is wrong ...
            if (m_lowest.X >= 0 &&
                !Clipper.Orientation(m_polyNodes.Childs[(int)m_lowest.X].m_polygon))
            {
                for (int i = 0; i < m_polyNodes.ChildCount; i++)
                {
                    PolyNode node = m_polyNodes.Childs[i];
                    if (node.m_endtype == EndType.etClosedPolygon ||
                        (node.m_endtype == EndType.etClosedLine &&
                         Clipper.Orientation(node.m_polygon)))
                    {
                        node.m_polygon.Reverse();
                    }
                }
            }
            else
            {
                for (int i = 0; i < m_polyNodes.ChildCount; i++)
                {
                    PolyNode node = m_polyNodes.Childs[i];
                    if (node.m_endtype == EndType.etClosedLine &&
                        !Clipper.Orientation(node.m_polygon))
                    {
                        node.m_polygon.Reverse();
                    }
                }
            }
        }
Esempio n. 3
0
 private void CutDual(List <IntPoint> poly, List <int> tmpIntersectingCuts, List <TileHandler.Cut> cuts, bool hasDual, List <List <IntPoint> > intermediateResult, PolyTree result)
 {
     this.clipper.Clear();
     this.clipper.AddPolygon(poly, PolyType.ptSubject);
     for (int i = 0; i < tmpIntersectingCuts.Count; i++)
     {
         if (cuts[tmpIntersectingCuts[i]].isDual)
         {
             this.clipper.AddPolygon(cuts[tmpIntersectingCuts[i]].contour, PolyType.ptClip);
         }
     }
     this.clipper.Execute(ClipType.ctIntersection, intermediateResult, PolyFillType.pftEvenOdd, PolyFillType.pftNonZero);
     this.clipper.Clear();
     if (intermediateResult != null)
     {
         for (int j = 0; j < intermediateResult.Count; j++)
         {
             this.clipper.AddPolygon(intermediateResult[j], (!Clipper.Orientation(intermediateResult[j])) ? PolyType.ptSubject : PolyType.ptClip);
         }
     }
     for (int k = 0; k < tmpIntersectingCuts.Count; k++)
     {
         if (!cuts[tmpIntersectingCuts[k]].isDual)
         {
             this.clipper.AddPolygon(cuts[tmpIntersectingCuts[k]].contour, PolyType.ptClip);
         }
     }
     result.Clear();
     this.clipper.Execute(ClipType.ctDifference, result, PolyFillType.pftEvenOdd, PolyFillType.pftNonZero);
 }
Esempio n. 4
0
        private static List <XPolygon> FromPolyTree(PolyNode results, PathOrientation subjectOrientation, double scaleBy = 1000)
        {
            List <XPolygon> polygons = new List <XPolygon>();

            foreach (PolyNode child in results.Childs)
            {
                PathOrientation orientation = Clipper.Orientation(child.Contour) == true ? PathOrientation.Anticlockwise : PathOrientation.Clockwise;
                XPolygon        polygon     = FromPath(child.Contour, scaleBy);
                polygons.Add(polygon);

                foreach (PolyNode childNode in child.Childs)
                {
                    //polygon.InnerPaths.Add(FromPath(childNode.Contour, scaleBy));
                    //List<SimplePolygon> childPolygons = FromPolyTree(childNode, subjectOrientation, scaleBy);
                    //polygons.AddRange(childPolygons);
                }
                if (orientation != subjectOrientation)
                {
                    polygon.Reverse();
                }
                //polygon.MakeLines();
            }

            return(polygons);
        }
Esempio n. 5
0
        public override IReadOnlyList <Vector2> Apply(Func <double> random, INamedDataCollection metadata, IReadOnlyList <Vector2> footprint, IReadOnlyList <Vector2> basis, IReadOnlyList <Vector2> lot)
        {
            var c = new Clipper();

            const int SCALE = 1000;

            c.AddPath(footprint.Select(a => new IntPoint((int)(a.X * SCALE), (int)(a.Y * SCALE))).ToList(), PolyType.ptSubject, true);

            var clip = _lot ? lot : basis;

            c.AddPath(clip.Select(a => new IntPoint((int)(a.X * SCALE), (int)(a.Y * SCALE))).ToList(), PolyType.ptClip, true);

            var solutions = new List <List <IntPoint> >();

            c.Execute(ClipType.ctIntersection, solutions);

            var clipperSolution = solutions.Single();

            Contract.Assume(clipperSolution != null);

            if (Clipper.Orientation(clipperSolution))
            {
                clipperSolution.Reverse();
            }

            return(clipperSolution.Select(a => new Vector2(a.X / (float)SCALE, a.Y / (float)SCALE)).ToArray());
        }
Esempio n. 6
0
        private static Polygon ClprPathsToPolygon(Paths polygons)
        {
            Polygon result = null;

            if (polygons.Count <= 0)
            {
                return(null);
            }

            result = new Polygon(polygons.Count);
            for (int j = 0; j < polygons.Count; ++j)
            {
                bool         hole    = !Clipper.Orientation(polygons[j]);
                List <Vec2d> contour = new List <Vec2d>(polygons[j].Count);
                for (int i = 0; i < polygons[j].Count; ++i)
                {
                    IntPoint p = polygons[j][i];
                    double   x = p.X / PrecisionScale;
                    double   y = p.Y / PrecisionScale;
                    contour.Add(new Vec2d(x, y));
                }
                result.SetContourAndHole(j, contour, hole);
            }
            return(result);
        }
Esempio n. 7
0
        /// <summary>
        /// Offsets a polygon by the given distance. Counter-clockwise polygons will expand while clockwise polygons
        /// will contract.
        /// </summary>
        public static List <NativeArray <RigidTransform> > OffsetPolygon(
            NativeArray <RigidTransform> samples, float distance, Allocator allocator)
        {
            var solution = new List <List <IntPoint> >();
            var polygon  = FromSamplesToClipper(samples);

            // Clipper uses Even-Odd polygon boolean operations to calculate offsets, so offsetting a clockwise path
            // will result in an expanded offset path rather than a contracted path we're looking for. The offset
            // direction is reversed here to ensure that the orientation of the polygon determines the offset direction.
            var orientation = Clipper.Orientation(polygon);

            if (!orientation)
            {
                distance *= -1;
            }

            var clipperOffset = new ClipperOffset();

            clipperOffset.AddPath(polygon, JoinType.jtRound, EndType.etClosedPolygon);
            clipperOffset.Execute(ref solution, distance * UpScaleFactor);

            if (!orientation)
            {
                for (var i = 0; i < solution.Count; i++)
                {
                    solution[i].Reverse();
                }
            }

            return(ConvertToSamples(solution, allocator));
        }
Esempio n. 8
0
 private void FixOrientations()
 {
     if (m_lowest.X >= 0 && !Clipper.Orientation(m_polyNodes.Childs[(int)m_lowest.X].m_polygon))
     {
         for (int i = 0; i < m_polyNodes.ChildCount; i++)
         {
             PolyNode polyNode = m_polyNodes.Childs[i];
             if (polyNode.m_endtype == EndType.etClosedPolygon || (polyNode.m_endtype == EndType.etClosedLine && Clipper.Orientation(polyNode.m_polygon)))
             {
                 polyNode.m_polygon.Reverse();
             }
         }
     }
     else
     {
         for (int j = 0; j < m_polyNodes.ChildCount; j++)
         {
             PolyNode polyNode2 = m_polyNodes.Childs[j];
             if (polyNode2.m_endtype == EndType.etClosedLine && !Clipper.Orientation(polyNode2.m_polygon))
             {
                 polyNode2.m_polygon.Reverse();
             }
         }
     }
 }
        /// <summary>
        /// Clean up a proposed corridor shape (primarily removing holes, which are invalid in a floorplan)
        /// </summary>
        /// <param name="clipper"></param>
        /// <param name="outline"></param>
        /// <param name="corridor"></param>
        /// <param name="width"></param>
        /// <returns></returns>
        public static List <List <IntPoint> > CleanCorridorPolygon(Clipper clipper, List <IntPoint> outline, IEnumerable <Vector2> corridor, float width)
        {
            //Clean up after the previous run, just in case
            clipper.Clear();

            //Clip this spanning tree to the footprint of the floorplan (to create a polytree)
            var result = new List <List <IntPoint> >();

            clipper.AddPath(outline, PolyType.ptClip, true);
            clipper.AddPath(corridor.Select(ToPoint).ToList(), PolyType.ptSubject, true);
            clipper.Execute(ClipType.ctIntersection, result);

            //Clean up after self, to be polite
            clipper.Clear();

            //Keep simplifying, and removing holes until nothing happens
            do
            {
                //merge together vertices which are very close
                result = Clipper.CleanPolygons(result, width / 8);

                //Remove holes from the result
                var holes = result.RemoveAll(r => !Clipper.Orientation(r));

                //Once we have one single polygon, or removing holes did nothing we've finished!
                if (result.Count == 1 || holes == 0)
                {
                    return(result);
                }
            } while (result.Count > 0);

            //This shouldn't ever happen unless we simplify away to nothing
            return(result);
        }
Esempio n. 10
0
 private static List <IntPoint> UnifyClipper(List <IntPoint> path)
 {
     if (!Clipper.Orientation(path))
     {
         path.Reverse();
     }
     return(path);
 }
Esempio n. 11
0
        public void assertCCW()
        {
            Path path = getPathFromCurve();

            if (!Clipper.Orientation(path))
            {
                parametricObject.curve.Reverse();
            }
        }
Esempio n. 12
0
 public void CheckIfHole()
 {
     if (Clipper.Orientation(this.toPolygon()))
     {
         Hole = false;
     }
     else
     {
         Hole = true;
     }
 }
Esempio n. 13
0
        protected override void OnUpdate()
        {
            var polygons = PolygonsFromRoadOutline(Parameters.extensionDistance);

            var clipper = new Clipper();

            foreach (var polygon in polygons)
            {
                if (!Clipper.Orientation(polygon))
                {
                    polygon.Reverse();
                }
                if (Clipper.Area(polygon) > 0)
                {
                    clipper.AddPath(polygon, PolyType.ptSubject, true);
                }
            }

            var solution = new List <List <IntPoint> >();

            clipper.Execute(ClipType.ctUnion, solution, PolyFillType.pftNonZero, PolyFillType.pftNonZero);

            solution.RemoveAll(IsSmallerThanMinimumArea);

            if (solution.Count == 0 && polygons.Count != 0)
            {
                throw new Exception($"Unable to create a polygon from " +
                                    $"{Parameters.roadNetworkDescription.name}");
            }

            foreach (var polygon in solution)
            {
                var pathEntity = EntityManager.CreateEntity(m_SamplesArchetype);

                var orientation = Clipper.Orientation(polygon)
                    ? PolygonOrientation.Outside
                    : PolygonOrientation.Inside;

                var pathSamplesBuffer    = EntityManager.GetBuffer <PointSampleGlobal>(pathEntity).Reinterpret <RigidTransform>();
                var placementPathSamples = PlacementUtility.IntPointsToRigidTransforms(polygon, true, Allocator.TempJob);
                pathSamplesBuffer.AddRange(placementPathSamples);
                placementPathSamples.Dispose();

                EntityManager.SetComponentData(pathEntity, new PolygonOrientationComponent
                {
                    Orientation = orientation
                });
            }
        }
        private IReadOnlyList <IReadOnlyList <Vector2> > ShapesForRoom(IEnumerable <Vector2> roomFootprint, bool split = false)
        {
            Contract.Requires(roomFootprint != null);

            //Winding check
            var clipperRoomFootprint = roomFootprint.Select(ToPoint).ToList();

            if (Clipper.Orientation(clipperRoomFootprint))
            {
                clipperRoomFootprint.Reverse();
            }

            //Contain within floor outer edge
            var solution = ClipToFloor(clipperRoomFootprint, split);

            if (solution == null)
            {
                return(null);
            }

            //Clip against other rooms
            if (_rooms.Count > 0)
            {
                var clips = solution.Select(a => ClipToRooms(a, split));

                solution = clips.SelectMany(a => a).ToList();
                if (solution.Count > 1 && !split)
                {
                    return(null);
                }
            }

            //Ensure shapes are still clockwise wound (mutate in place to reverse)
            foreach (var shape in solution.Where(Clipper.Orientation))
            {
                shape.Reverse();
            }

            //Convert back to vectors and apply SAFE_DISTANCE shrink (all rooms are shrunk by this distance)
            return(solution
                   .Select(shape =>
                           shape
                           .Select(ToVector2)
                           .Shrink(SAFE_DISTANCE)
                           .ToArray()
                           ).ToArray());
        }
Esempio n. 15
0
        public static List <XPolygon> Clip(ClipType clipType, List <XPolygon> subjects, List <XPolygon> clips, double scaleBy = 1000)
        {
            List <XPolygon> results = new List <XPolygon>();

            Paths subjPaths = ToPaths(subjects, scaleBy);
            Paths clipPaths = ToPaths(clips, scaleBy);

            Clipper clipper = new Clipper();

            clipper.AddPaths(clipPaths, PolyType.ptSubject, closed: true);
            clipper.AddPaths(subjPaths, PolyType.ptClip, closed: true);
            PolyTree result = new PolyTree();

            clipper.Execute(clipType, result, PolyFillType.pftEvenOdd, PolyFillType.pftEvenOdd);
            PathOrientation orientation = Clipper.Orientation(subjPaths.First()) == true ? PathOrientation.Anticlockwise : PathOrientation.Clockwise;

            return(FromPolyTree(result, orientation, scaleBy));
        }
Esempio n. 16
0
        public bool isInside(float i, float j)
        {
            Paths boundingSolids = P_Plan.getTransformedSubjPaths();
            Paths boundingHoles  = P_Plan.getTransformedHolePaths();

            bool pointIsInside = false;

            IntPoint ip = new IntPoint(i * AXGeometryTools.Utilities.IntPointPrecision, j * AXGeometryTools.Utilities.IntPointPrecision);

            if (boundingSolids != null)
            {
                if (boundingSolids != null)
                {
                    foreach (Path path in boundingSolids)
                    {
                        if (Clipper.PointInPolygon(ip, path) == 1 && Clipper.Orientation(path))
                        {
                            pointIsInside = true;
                            break;
                        }
                    }
                }

                if (boundingHoles != null)
                {
                    foreach (Path hole in boundingHoles)
                    {
                        if (Clipper.PointInPolygon(ip, hole) == 1)
                        {
                            pointIsInside = false;
                            break;
                        }
                    }
                }
            }


            //exclude = (boundingIsVoid) ? ! exclude : exclude;

            //if (pointIsInside)
            //continue;

            return(pointIsInside);
        }
Esempio n. 17
0
        public bool isInside(float i, float j, Paths boundingSolids, Paths boundingHoles)
        {
            bool pointIsInside = false;

            IntPoint ip = new IntPoint(i * AXGeometryTools.Utilities.IntPointPrecision, j * AXGeometryTools.Utilities.IntPointPrecision);

            //Debug.Log(ip.X+", "+ip.Y);

            if (boundingSolids != null)
            {
                if (boundingSolids != null)
                {
                    foreach (Path path in boundingSolids)
                    {
                        //Pather.printPath(path);
                        if (Clipper.PointInPolygon(ip, path) == 1 && Clipper.Orientation(path))
                        {
                            pointIsInside = true;
                            break;
                        }
                    }
                }

                if (boundingHoles != null)
                {
                    foreach (Path hole in boundingHoles)
                    {
                        if (Clipper.PointInPolygon(ip, hole) == 1)
                        {
                            pointIsInside = false;
                            break;
                        }
                    }
                }
            }


            //exclude = (boundingIsVoid) ? ! exclude : exclude;

            //if (pointIsInside)
            //continue;

            return(pointIsInside);
        }
Esempio n. 18
0
        public static NativeArray <RigidTransform> OffsetPath(
            NativeArray <RigidTransform> samples,
            float distance,
            bool looped,
            Allocator allocator)
        {
            var solution = new List <List <IntPoint> >();
            var polygon  = FromSamplesToClipper(samples);

            if (!Clipper.Orientation(polygon))
            {
                distance *= -1;
            }

            var clipperOffset = new ClipperOffset();

            clipperOffset.AddPath(polygon, JoinType.jtRound, EndType.etOpenButt);
            clipperOffset.Execute(ref solution, distance * UpScaleFactor);

            return(IntPointsToRigidTransforms(solution[0], looped, allocator));
        }
Esempio n. 19
0
        public void Draw(Color color)
        {
            if (points == null)
            {
                return;
            }

            var realColor = color;

            for (int i = 0, count = points.Count; i < count; ++i)
            {
                Gizmos.color = color;
                var path = points[i];
                color.a = realColor.a * (Clipper.Orientation(path) ? 1.0f : 0.5f);

                for (int j = 0, pathCount = path.Count; j < pathCount; ++j)
                {
                    Gizmos.DrawLine(path[j].ToVector2D(), path[(j + 1) % pathCount].ToVector2D());
                }
            }
        }
Esempio n. 20
0
        private static Paths PolygonToClprPaths(Polygon polygon)
        {
            Paths result = new List <List <IntPoint> >(polygon.NumContours);

            for (int j = 0; j < polygon.NumContours; ++j)
            {
                result.Add(new List <IntPoint>(polygon[j].Count));
                for (int i = 0; i < polygon[j].Count; ++i)
                {
                    Vec2d    v = polygon[j][i];
                    IntPoint p;
                    p.X = (Int32)(v.X * PrecisionScale);
                    p.Y = (Int32)(v.Y * PrecisionScale);
                    result[j].Add(p);
                }
                if (Clipper.Orientation(result[j]) == polygon.IsHole(j))
                {
                    result[j].Reverse();
                }
            }
            return(result);
        }
Esempio n. 21
0
        /// <summary>
        /// cws requires the project boundary to be counter clockwise.
        ///   returns true if reversed
        /// </summary>
        public static string MakeCounterClockwise(string polygonWkt, out bool hasBeenReversed)
        {
            hasBeenReversed = false;
            var resultPolygonWkt = polygonWkt;
            var points           = ConvertAndValidatePolygon(polygonWkt);

            var polygon     = ClipperPolygon(points);
            var orientation = Clipper.Orientation(polygon);

            // "On Y-axis positive upward displays, Orientation will return true if the polygon's orientation is counter-clockwise"
            if (orientation == false)
            {
                var polygons = new List <List <IntPoint> > {
                    polygon
                };
                Clipper.ReversePolygons(new List <List <IntPoint> >(polygons));
                hasBeenReversed = true;
                var polygonList = FromClipperPolygon(polygons[0]);
                resultPolygonWkt = polygonList.ToPolygonWKT();
            }

            return(resultPolygonWkt);
        }
Esempio n. 22
0
        /// <summary>
        /// "sichere" Flächen erzeugen (ev. aufteilen)
        /// </summary>
        /// <param name="area"></param>
        /// <param name="maxsize">max. "quadratisches" Umgrenzung in MapUnits</param>
        /// <returns></returns>
        static List <DetailMap.Poly> MakeSafeAreas(DetailMap.Poly area, int maxsize)
        {
            List <DetailMap.Poly> lst = new List <DetailMap.Poly>();

            ClipperPath p = MapUnitPointList2ClipperPath(area.GetMapUnitPoints());
            bool        counterclockwise = Clipper.Orientation(p);

            ClipperPaths newpolys = SplitClipperPath(MapUnitPointList2ClipperPath(area.GetMapUnitPoints()), maxsize);

            for (int i = 0; i < newpolys.Count; i++)
            {
                if (Clipper.Orientation(newpolys[i]) != counterclockwise)
                {
                    newpolys[i].Reverse();
                }
            }

            if (newpolys.Count > 1) // es ist eine Teilung erfolgt
            {
                foreach (var newpoly in newpolys)
                {
                    DetailMap.Poly newarea = new DetailMap.Poly(area);
                    newarea.Clear();
                    foreach (var pt in newpoly)
                    {
                        newarea.AddPoint(new MapUnitPoint((int)pt.X, (int)pt.Y), false);
                    }
                    lst.Add(newarea);
                }
            }
            else
            {
                lst.Add(area);
            }

            return(lst);
        }
Esempio n. 23
0
        public void redraw()
        {
            canvas.Children.Clear();

            if (rooms.Count == 0 && decoration.Count == 0)
            {
                return;
            }

            c.Clear();
            Polygons outline = new Polygons();

            c.AddPolygons(rooms, PolyType.ptSubject);
            c.AddPolygons(decoration, PolyType.ptSubject);
            c.Execute(ClipType.ctUnion, outline, PolyFillType.pftNonZero, PolyFillType.pftNonZero);
            outline = Clipper.OffsetPolygons(outline, 10, JoinType.jtMiter);

            // Bevel inside corners of the outline
            foreach (Polygon p in outline)
            {
                // Skip holes
                if (!Clipper.Orientation(p))
                {
                    continue;
                }

                // Find the inside corners
                List <bool> corners = new List <bool>();
                for (int j = 0; j < p.Count; ++j)
                {
                    int i = (j + p.Count - 1) % p.Count;
                    int k = (j + 1) % p.Count;

                    IntPoint e1 = new IntPoint(p[j].X - p[i].X, p[j].Y - p[i].Y);
                    IntPoint e2 = new IntPoint(p[j].X - p[k].X, p[j].Y - p[k].Y);

                    int a = (int)(e1.X * e2.Y - e2.X * e1.Y);

                    corners.Add(a > 0);
                }

                // Bevel them to the midpoints of the original lines
                for (int j = 0; j < p.Count; ++j)
                {
                    int i = (j + p.Count - 1) % p.Count;
                    int k = (j + 1) % p.Count;

                    if (corners[j])
                    {
                        if (!corners[i])
                        {
                            corners.Insert(j, true);
                            p.Insert(j, new IntPoint((p[i].X + p[j].X) / 2, (p[i].Y + p[j].Y) / 2));

                            ++j; ++k;
                        }

                        p[j] = new IntPoint((p[j].X + p[k].X) / 2, (p[j].Y + p[k].Y) / 2);
                    }
                }
            }

            foreach (Polygon p in rooms)
            {
                canvas.Children.Add(ToSystemPolygon(p));
            }

            foreach (Polygon p in outline)
            {
                canvas.Children.Add(ToSystemPolygon(p, Brushes.Yellow));
            }

            UpdateLayout();
        }
Esempio n. 24
0
        // GENERATE GRID_REPEATER
        public override GameObject generate(bool makeGameObjects, AXParametricObject initiator_po, bool isReplica)
        {
            //Debug.Log(parametricObject.Name + " Generate");
            if (parametricObject == null || !parametricObject.isActive)
            {
                return(null);
            }

            if (repeaterToolU == null || repeaterToolV == null)
            {
                return(null);
            }

            preGenerate();


            // NODE_MESH
            AXParametricObject nodeSrc_po = null;
            GameObject         nodePlugGO = null;

            if (nodeSrc_p != null)
            {
                nodeSrc_po = nodeSrc_p.parametricObject;
                if (makeGameObjects && !parametricObject.combineMeshes)
                {
                    nodePlugGO = nodeSrc_po.generator.generate(true, initiator_po, isReplica);
                }
            }


            // CELL_MESH
            AXParametricObject cellSrc_po = null;
            GameObject         cellPlugGO = null;

            if (cellSrc_p != null)
            {
                cellSrc_po = cellSrc_p.parametricObject;
                if (makeGameObjects && !parametricObject.combineMeshes)
                {
                    cellPlugGO = cellSrc_po.generator.generate(true, initiator_po, isReplica);
                }
            }

            // BAY_SPAN_U
            AXParametricObject spanUSrc_po = null;
            GameObject         spanUPlugGO = null;

            if (spanUSrc_p != null)
            {
                spanUSrc_po = spanUSrc_p.parametricObject;
                if (makeGameObjects && !parametricObject.combineMeshes)
                {
                    spanUPlugGO = spanUSrc_po.generator.generate(true, initiator_po, isReplica);
                }
            }

            // BAY_SPAN_V
            AXParametricObject spanVSrc_po = null;
            GameObject         spanVPlugGO = null;

            if (spanVSrc_p != null)
            {
                spanVSrc_po = spanVSrc_p.parametricObject;
                if (makeGameObjects && !parametricObject.combineMeshes)
                {
                    spanVPlugGO = spanVSrc_po.generator.generate(true, initiator_po, isReplica);
                }
            }



            if (nodeSrc_po == null && cellSrc_po == null && spanUSrc_po == null && spanVSrc_po == null)
            {
                AXParameter output_p = getPreferredOutputParameter();
                if (output_p != null)
                {
                    output_p.meshes = null;
                }

                return(null);
            }


            GameObject go = null;

            if (makeGameObjects && !parametricObject.combineMeshes)
            {
                go = ArchimatixUtils.createAXGameObject(parametricObject.Name, parametricObject);
            }



            // BOUNDING_SHAPE

            Paths boundingSolids = null;
            Paths boundingHoles  = null;


            if (P_BoundingShape != null && P_BoundingShape.DependsOn != null)
            {
                AXParameter bounding_src_p = null;
                if (P_BoundingShape != null)
                {
                    bounding_src_p = P_BoundingShape.DependsOn;                               // USING SINGLE SPLINE INPUT
                }
                boundingShapeSrc_po = bounding_src_p.parametricObject;

                AXShape.thickenAndOffset(ref P_BoundingShape, bounding_src_p);
                // now boundin_p has offset and thickened polytree or paths.

                boundingSolids = P_BoundingShape.getTransformedSubjPaths();
                boundingHoles  = P_BoundingShape.getTransformedHolePaths();
            }



            List <AXMesh> ax_meshes = new List <AXMesh>();

            Matrix4x4 localPlacement_mx = Matrix4x4.identity;

            // -----------------------------------

            int max_reps = 150;

            int   cellsU     = Mathf.Clamp(repeaterToolU.cells, 1, max_reps);
            float actualBayU = repeaterToolU.actualBay;

            int   cellsV     = Mathf.Clamp(repeaterToolV.cells, 1, max_reps);
            float actualBayV = repeaterToolV.actualBay;

            shiftU = -cellsU * actualBayU / 2;
            shiftV = -cellsV * actualBayV / 2;


            // BAY SPAN
            // Spanners are meshers that get replicated and sized to fit the bay...

            // prepare mesh to iterate in each direction

            //List<AXMesh>  ax_meshes_X         = new List<AXMesh>();
            //List<AXMesh>  ax_meshes_Z         = new List<AXMesh>();



            AXMesh tmpMesh;

            if (spanUSrc_p != null)
            {
                //ax_meshes_X = spanUSrc_p.meshes;
                //ax_meshes_Z = spanUSrc_p.meshes;
            }

            /* NEED TO INTEGRATE THIS BACK IN IN THE FUTRE...
             * if (bay_span_source != null)
             * {
             *
             *      // 1. cache source object
             *      bay_span_source.cacheParameterValues();
             *
             *
             *      // Y_AXIS
             *
             *      AXParameter p_bayv = parametricObject.getParameter("actual_bay_V");
             *      AXParameter p_bayv_client = null;
             *      if (p_bayv != null)
             *      {
             *              foreach (AXRelation rel in p_bayv.relations)
             *              {
             *                      p_bayv_client = rel.getRelatedTo(p_bayv);
             *                      p_bayv_client.intiateRipple_setFloatValueFromGUIChange(abayy);
             *              }
             *      }
             *
             *
             *      AXParameter p_bayu = parametricObject.getParameter("actual_bay_U");
             *      AXParameter p_bayu_client = null;
             *
             *      // X-AXIS
             *      // For now, only set the boundaries.
             *      // Perhaps later, may want to set other like controls as in Replicant
             *
             *      // If there is a relation to actual_bay_U, propogate it
             *      if (p_bayu != null)
             *      {
             *              foreach (AXRelation rel in p_bayu.relations)
             *              {
             *                      p_bayu_client = rel.getRelatedTo(p_bayu);
             *                      p_bayu_client.intiateRipple_setFloatValueFromGUIChange(abayx);
             *              }
             *      }
             *
             *      //bay_span_source.propagateParameterByBinding(1, bayx);
             *      //bay_span_source.propagateParameterByBinding(2, bayy);
             *
             *      // 2. re_generate with temporary values set by this Replicant
             *      bay_span_source.generateOutputNow (makeGameObjects, parametricObject);
             *
             *      // 3. Now that the bay_span_source has been regergrab the meshes from the input sources and add them here
             *      AXParameter output_p = bay_span_source.getParameter("Output Mesh");
             *      foreach (AXMesh amesh in output_p.meshes)
             *              ax_meshes_X.Add (amesh.Clone(amesh.transMatrix));
             *
             *
             *
             *      // Z-AXIS
             *      // Use the bayz now to generate x
             *
             *      if (p_bayu != null)
             *      {
             *              foreach (AXRelation rel in p_bayu.relations)
             *              {
             *                      p_bayu_client = rel.getRelatedTo(p_bayu);
             *                      p_bayu_client.intiateRipple_setFloatValueFromGUIChange(abayz);
             *              }
             *      }
             *
             *      //bay_span_source.propagateParameterByBinding(1, bayz);
             *
             *
             *      // 2. re_generate with temporary values set by this Replicant
             *      bay_span_source.generateOutputNow (makeGameObjects, parametricObject);
             *
             *      // 3. Now that the bay_span_source has been regergrab the meshes from the input sources and add them here
             *      foreach (AXMesh amesh in output_p.meshes)
             *              ax_meshes_Z.Add (amesh.Clone(amesh.transMatrix));
             *
             *
             *      // 4. restore source object; as though we were never here!
             *      bay_span_source.revertParametersFromCache();
             *
             *      //Debug.Log ("HAVE BAY SPAN -- " + output_p.meshes.Count);
             *
             *
             * }
             */


            /* NEED TO INTEGRATE THIS BACK IN IN THE FUTRE...
             * if (cell_center_source != null)
             * {
             *      // Y-AXIS
             *      // For now, only set the boundaries.
             *      // Perhaps later, may want to set other like controls as in Replicant
             *      // 1. cache source object
             *      cell_center_source.cacheParameterValues();
             *
             *
             *
             *      //bay_center_source.propagateParameterByBinding(1, bayx);
             *      //bay_center_source.propagateParameterByBinding(3, bayz);
             *
             *      // 2. re_generate with temporary values set by this Replicant
             *      cell_center_source.generateOutputNow (makeGameObjects, parametricObject);
             *
             *      // 3. Now that the bay_span_source has been regenerted,  grab the meshes from the input sources and add them here
             *      AXParameter bc_output_p = cell_center_source.getParameter("Output Mesh");
             *      foreach (AXMesh amesh in bc_output_p.meshes)
             *              ax_meshes_Y.Add (amesh.Clone(amesh.transMatrix));
             *
             *      // 4. restore source object; as though we were never here!
             *      cell_center_source.revertParametersFromCache();
             *
             * }
             */



            // BOUNDING

            List <AXMesh> boundingMeshes = new List <AXMesh>();



            for (int i = 0; i <= cellsU; i++)
            {
                for (int k = 0; k <= cellsV; k++)
                {
                    bool exclude = false;

                    IntPoint ip = new IntPoint((i * actualBayU + shiftU) * AXGeometryTools.Utilities.IntPointPrecision, (k * actualBayV + shiftV) * AXGeometryTools.Utilities.IntPointPrecision);

                    if (boundingSolids != null)
                    {
                        exclude = true;

                        if (boundingSolids != null)
                        {
                            foreach (Path path in boundingSolids)
                            {
                                if (Clipper.PointInPolygon(ip, path) == 1 && Clipper.Orientation(path))
                                {
                                    exclude = false;
                                    break;
                                }
                            }
                        }

                        if (boundingHoles != null)
                        {
                            foreach (Path hole in boundingHoles)
                            {
                                if (Clipper.PointInPolygon(ip, hole) == 1)
                                {
                                    exclude = true;
                                    break;
                                }
                            }
                        }
                    }


                    exclude = (boundingIsVoid) ? !exclude : exclude;

                    if (exclude)
                    {
                        continue;
                    }


                    // NODES
                    if (nodeSrc_po != null && nodeSrc_p.meshes != null && ((i <= repeaterToolU.edgeCount || i >= cellsU - repeaterToolU.edgeCount) || (k <= repeaterToolV.edgeCount || k >= cellsV - repeaterToolV.edgeCount)))
                    {
                        string this_address = "node_" + i + "_" + k;

                        // LOCAL PLACEMENT NODE
                        localPlacement_mx = localNodeMatrixFromAddress(i, k);


                        // AX_MESHES

                        for (int mi = 0; mi < nodeSrc_p.meshes.Count; mi++)
                        {
                            AXMesh dep_amesh = nodeSrc_p.meshes [mi];
                            tmpMesh = dep_amesh.Clone(localPlacement_mx * dep_amesh.transMatrix);
                            tmpMesh.subItemAddress = this_address;
                            ax_meshes.Add(tmpMesh);
                        }



                        // BOUNDING
                        boundingMeshes.Add(new AXMesh(nodeSrc_po.boundsMesh, localPlacement_mx * nodeSrc_po.generator.localMatrix));


                        // GAME_OBJECTS

                        if (nodePlugGO != null && makeGameObjects && !parametricObject.combineMeshes)
                        {
                            Matrix4x4  mx     = localPlacement_mx * nodeSrc_po.generator.localMatrixWithAxisRotationAndAlignment;
                            GameObject copyGO = (GameObject)GameObject.Instantiate(nodePlugGO, AXUtilities.GetPosition(mx), AXUtilities.QuaternionFromMatrix(mx));

                            copyGO.transform.localScale = new Vector3(copyGO.transform.localScale.x * jitterScale.x, copyGO.transform.localScale.y * jitterScale.y, copyGO.transform.localScale.z * jitterScale.z);

                                                        #if UNITY_EDITOR
                            //if (parametricObject.model.isSelected(nodeSrc_po) && nodeSrc_po.selectedConsumerAddress == this_address)
                            //	Selection.activeGameObject = copyGO;
                                                        #endif

                            AXGameObject axgo = copyGO.GetComponent <AXGameObject>();
                            if (axgo != null)
                            {
                                axgo.consumerAddress = this_address;
                            }

                            copyGO.name             = copyGO.name + "_" + this_address;
                            copyGO.transform.parent = go.transform;
                        }
                    }                     // \NODES



                    // CELL CENTERS
                    if (cellSrc_po != null && cellSrc_p.meshes != null && i < cellsU && k < cellsV && ((i < repeaterToolU.edgeCount || i > cellsU - repeaterToolU.edgeCount - 1) || (k < repeaterToolV.edgeCount || k > cellsV - repeaterToolV.edgeCount - 1)))
                    {
                        string this_address = "cell_" + i + "_" + k;

                        // LOCAL PLACEMENT

                        localPlacement_mx = localCellMatrixFromAddress(i, k);


                        // AX_MESHES

                        for (int mi = 0; mi < cellSrc_p.meshes.Count; mi++)
                        {
                            AXMesh dep_amesh = cellSrc_p.meshes [mi];
                            tmpMesh = dep_amesh.Clone(localPlacement_mx * dep_amesh.transMatrix);
                            tmpMesh.subItemAddress = this_address;
                            ax_meshes.Add(tmpMesh);
                        }


                        // BOUNDING
                        boundingMeshes.Add(new AXMesh(cellSrc_po.boundsMesh, localPlacement_mx * cellSrc_po.generator.localMatrix));



                        // GAME_OBJECTS

                        if (cellPlugGO != null && makeGameObjects && !parametricObject.combineMeshes)
                        {
                            Matrix4x4  mx     = localPlacement_mx * cellSrc_po.generator.localMatrixWithAxisRotationAndAlignment;
                            GameObject copyGO = (GameObject)GameObject.Instantiate(cellPlugGO, AXUtilities.GetPosition(mx), AXUtilities.QuaternionFromMatrix(mx));

                            copyGO.transform.localScale = new Vector3(copyGO.transform.localScale.x * jitterScale.x, copyGO.transform.localScale.y * jitterScale.y, copyGO.transform.localScale.z * jitterScale.z);

                                                        #if UNITY_EDITOR
                            //if (parametricObject.model.isSelected(cellSrc_po) && cellSrc_po.selectedConsumerAddress == this_address)
                            //Selection.activeGameObject = copyGO;
                                                        #endif

                            AXGameObject axgo = copyGO.GetComponent <AXGameObject>();
                            if (axgo != null)
                            {
                                axgo.consumerAddress = this_address;
                            }

                            copyGO.name             = copyGO.name + "_" + this_address;
                            copyGO.transform.parent = go.transform;
                        }
                    }



                    // SPAN_U
                    if (spanUSrc_po != null && spanUSrc_p.meshes != null && i < cellsU && k <= cellsV && ((i < repeaterToolV.edgeCount || i > cellsU - repeaterToolU.edgeCount - 1) || (k <= repeaterToolV.edgeCount || k > cellsV - repeaterToolV.edgeCount - 1)))
                    {
                        string this_address = "spanU_" + i + "_" + k;

                        // LOCAL PLACEMENT SPAN_U

                        localPlacement_mx = localSpanUMatrixFromAddress(i, k);


                        // AX_MESHES

                        for (int mi = 0; mi < spanUSrc_p.meshes.Count; mi++)
                        {
                            AXMesh dep_amesh = spanUSrc_p.meshes [mi];
                            tmpMesh = dep_amesh.Clone(localPlacement_mx * dep_amesh.transMatrix);
                            tmpMesh.subItemAddress = this_address;
                            ax_meshes.Add(tmpMesh);
                        }


                        // BOUNDING
                        boundingMeshes.Add(new AXMesh(spanUSrc_po.boundsMesh, localPlacement_mx * spanUSrc_po.generator.localMatrix));



                        // GAME_OBJECTS

                        if (spanUSrc_po != null && makeGameObjects && !parametricObject.combineMeshes)
                        {
                            Matrix4x4  mx     = localPlacement_mx * spanUSrc_po.generator.localMatrixWithAxisRotationAndAlignment;
                            GameObject copyGO = (GameObject)GameObject.Instantiate(spanUPlugGO, AXUtilities.GetPosition(mx), AXUtilities.QuaternionFromMatrix(mx));


                            copyGO.transform.localScale = new Vector3(copyGO.transform.localScale.x * jitterScale.x, copyGO.transform.localScale.y * jitterScale.y, copyGO.transform.localScale.z * jitterScale.z);

                                                        #if UNITY_EDITOR
                            //if (parametricObject.model.isSelected(spanUSrc_po) && spanUSrc_po.selectedConsumerAddress == this_address)
                            //	Selection.activeGameObject = copyGO;
                                                        #endif

                            AXGameObject axgo = copyGO.GetComponent <AXGameObject>();
                            if (axgo != null)
                            {
                                axgo.consumerAddress = this_address;
                            }

                            copyGO.name             = copyGO.name + "_" + this_address;
                            copyGO.transform.parent = go.transform;
                        }
                    }

                    // SPAN_V
                    if (spanVSrc_po != null && spanVSrc_p.meshes != null && i <= cellsU && k < cellsV && ((i <= repeaterToolU.edgeCount || i > cellsU - repeaterToolU.edgeCount - 1) || (k < repeaterToolV.edgeCount || k > cellsV - repeaterToolV.edgeCount - 1)))
                    {
                        string this_address = "spanV_" + i + "_" + k;

                        // LOCAL PLACEMENT SPAN_U
                        localPlacement_mx = localSpanVMatrixFromAddress(i, k);



                        // AX_MESHES

                        for (int mi = 0; mi < spanVSrc_p.meshes.Count; mi++)
                        {
                            AXMesh dep_amesh = spanVSrc_p.meshes [mi];
                            tmpMesh = dep_amesh.Clone(localPlacement_mx * dep_amesh.transMatrix);
                            tmpMesh.subItemAddress = this_address;
                            ax_meshes.Add(tmpMesh);
                        }



                        // BOUNDING
                        boundingMeshes.Add(new AXMesh(spanVSrc_po.boundsMesh, localPlacement_mx * spanVSrc_po.generator.localMatrix));



                        // GAME_OBJECTS

                        if (spanVSrc_po != null && makeGameObjects && !parametricObject.combineMeshes)
                        {
                            Matrix4x4  mx     = localPlacement_mx * spanVSrc_po.generator.localMatrixWithAxisRotationAndAlignment;
                            GameObject copyGO = (GameObject)GameObject.Instantiate(spanVPlugGO, AXUtilities.GetPosition(mx), AXUtilities.QuaternionFromMatrix(mx));


                            copyGO.transform.localScale = new Vector3(copyGO.transform.localScale.x * jitterScale.x, copyGO.transform.localScale.y * jitterScale.y, copyGO.transform.localScale.z * jitterScale.z);

                                                        #if UNITY_EDITOR
                            //if (parametricObject.model.isSelected(spanVSrc_po) && spanVSrc_po.selectedConsumerAddress == this_address)
                            //	Selection.activeGameObject = copyGO;
                                                        #endif

                            AXGameObject axgo = copyGO.GetComponent <AXGameObject>();
                            if (axgo != null)
                            {
                                axgo.consumerAddress = this_address;
                            }

                            copyGO.name             = copyGO.name + "_" + this_address;
                            copyGO.transform.parent = go.transform;
                        }
                    }
                }         // k
            }             //i


            GameObject.DestroyImmediate(nodePlugGO);
            GameObject.DestroyImmediate(cellPlugGO);
            GameObject.DestroyImmediate(spanUPlugGO);
            GameObject.DestroyImmediate(spanVPlugGO);



            // FINISH AX_MESHES

            parametricObject.finishMultiAXMeshAndOutput(ax_meshes, isReplica);



            // FINISH BOUNDS

            CombineInstance[] boundsCombinator = new CombineInstance[boundingMeshes.Count];
            for (int bb = 0; bb < boundsCombinator.Length; bb++)
            {
                boundsCombinator[bb].mesh      = boundingMeshes[bb].mesh;
                boundsCombinator[bb].transform = boundingMeshes[bb].transMatrix;
            }
            setBoundsWithCombinator(boundsCombinator);



            // FINISH GAME_OBJECTS

            if (makeGameObjects)
            {
                if (parametricObject.combineMeshes)
                {
                    go = parametricObject.makeGameObjectsFromAXMeshes(ax_meshes, true);
                }

                Matrix4x4 tmx = parametricObject.generator.localMatrixWithAxisRotationAndAlignment;

                go.transform.rotation   = AXUtilities.QuaternionFromMatrix(tmx);
                go.transform.position   = AXUtilities.GetPosition(tmx);
                go.transform.localScale = parametricObject.getLocalScaleAxisRotated();

                return(go);
            }

            return(null);
        }
Esempio n. 25
0
 public static bool Orientation(this Polygon polygon)
 {
     return(Clipper.Orientation(polygon));
 }
Esempio n. 26
0
        // Token: 0x060005E2 RID: 1506 RVA: 0x000360CC File Offset: 0x000344CC
        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) 3, 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>();
            IntRect             b     = new IntRect(verts[0].x, verts[0].z, verts[0].x, verts[0].z);

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

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

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

            if (this.clipper == null)
            {
                this.clipper = new Clipper(0);
            }
            this.clipper.ReverseSolution = 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 <IntRect> list9 = ListPool <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;
                IntRect a      = new IntRect(@int.x, @int.z, int2.x, int2.z);
                if (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(IntRect));
                            list10.Add(new Int2(0, 0));
                        }
                        else
                        {
                            IntRect item = new 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;
            }
            for (;;)
            {
                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]];
                IntRect a2   = new 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 (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_1161;
                                }
                                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
                                {
                                    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);
                                            }
                                        }
                                        Polygon polygon2;
                                        if (stack.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.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_1161 :;
                    }
                }
            }
            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 <IntRect> .Release(list9);

            ListPool <NavmeshCut> .Release(list7);
        }
        /// <summary>
        /// This approach extends the idea in Job.WithCode() by manually generating batches of work with one job per batch for better load balancing.
        /// Setup is tedious, but is slightly faster (~1-2ms) than Entities.ForEach with a separate buffer. We should probably avoid this pattern due to the large overhead and brittle code.
        ///
        /// Test results:
        /// Total: 36ms
        /// Setup: 1.12ms
        /// Combine: 2.12ms
        /// </summary>
        private List <List <IntPoint> > PolygonsFromRoadOutlineIJobParallelFor(float extensionDistance, JobHandle jobHandle)
        {
            Profiler.BeginSample("PolygonsFromRoadOutlineIJobParallelFor");
            Profiler.BeginSample("PolygonsFromRoadOutlineIJobParallelFor_Setup");
            var polygons = new List <List <IntPoint> >();

            var outlineJobParams = new NativeList <OutlineJobParams>(300, Allocator.TempJob);
            var sampleCountTotal = 0;

            Entities.ForEach((int entityInQueryIndex, Entity entity, ref EcsRoad road) =>
            {
                var sampleCount = GeometrySampling.ComputeSampleCountForRoadOutline(road, .5f);
                outlineJobParams.Add(new OutlineJobParams
                {
                    entity     = entity,
                    startIndex = sampleCountTotal,
                    count      = sampleCount
                });
                sampleCountTotal += sampleCount;
            }).Run();

            var samples = new NativeArray <PointSampleGlobal>(sampleCountTotal, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);


            var ecsRoadGetter         = GetComponentDataFromEntity <EcsRoad>(true);
            var geometryGetter        = GetBufferFromEntity <Geometry>(true);
            var laneSectionGetter     = GetBufferFromEntity <EcsLaneSection>(true);
            var laneGetter            = GetBufferFromEntity <EcsLane>(true);
            var laneOffsetGetter      = GetBufferFromEntity <LaneOffset>(true);
            var laneWidthRecordGetter = GetBufferFromEntity <LaneWidthRecord>(true);

            var batchSize              = samples.Length / 64;
            var jobBatches             = new NativeList <JobHandle>(Allocator.TempJob);
            int currentBatchSize       = 0;
            int currentBatchStartIndex = 0;

            for (int i = 0; i < outlineJobParams.Length; i++)
            {
                var currentJobParams = outlineJobParams[i];
                currentBatchSize += currentJobParams.count;
                if (currentBatchSize >= batchSize || i == outlineJobParams.Length - 1)
                {
                    var job = new BuildSamplesJob()
                    {
                        extensionDistance = extensionDistance,
                        outlineJobBatch   = new OutlineJobBatch
                        {
                            startIndex = currentBatchStartIndex,
                            count      = i - currentBatchStartIndex + 1
                        },
                        outlineJobParams      = outlineJobParams,
                        ecsRoadGetter         = ecsRoadGetter,
                        geometryGetter        = geometryGetter,
                        laneSectionGetter     = laneSectionGetter,
                        laneGetter            = laneGetter,
                        laneOffsetGetter      = laneOffsetGetter,
                        laneWidthRecordGetter = laneWidthRecordGetter,
                        samples = samples
                    }.Schedule(jobHandle);
                    jobBatches.Add(job);

                    currentBatchSize       = 0;
                    currentBatchStartIndex = i + 1;
                }
            }

            Profiler.EndSample();
            Profiler.BeginSample("PolygonsFromRoadOutlineIJobParallelFor_CompleteJob");
            JobHandle.CombineDependencies(jobBatches).Complete();

            Profiler.EndSample();
            Profiler.BeginSample("PolygonsFromRoadOutlineIJobParallelFor_Combine");

            foreach (var outlineJobParam in outlineJobParams)
            {
                var sampleSlice = new NativeSlice <PointSampleGlobal>(samples, outlineJobParam.startIndex, outlineJobParam.count);
                var path        = new List <IntPoint>(sampleSlice.Length);
                foreach (var point in sampleSlice)
                {
                    path.Add(new IntPoint(
                                 point.pose.pos.x * PlacementUtility.UpScaleFactor,
                                 point.pose.pos.z * PlacementUtility.UpScaleFactor));
                }

                if (!Clipper.Orientation(path))
                {
                    path.Reverse();
                }

                polygons.Add(path);
            }

            outlineJobParams.Dispose();
            jobBatches.Dispose();
            samples.Dispose();
            Profiler.EndSample();
            Profiler.EndSample();

            return(polygons);
        }
        protected override JobHandle OnUpdate(JobHandle inputDeps)
        {
            List <List <IntPoint> > polygons;

            switch (Parameters.processingScheme)
            {
            case ProcessingScheme.JobWithCode:
                polygons = PolygonsFromRoadOutlineJobWithCode(Parameters.extensionDistance, inputDeps);
                break;

            case ProcessingScheme.IJobParallelFor:
                polygons = PolygonsFromRoadOutlineIJobParallelFor(Parameters.extensionDistance, inputDeps);
                break;

            case ProcessingScheme.EntityForEachTempDynamicArrays:
                polygons = PolygonsFromRoadOutlineEntityForEach(Parameters.extensionDistance, inputDeps);
                break;

            case ProcessingScheme.EntityForEachSeparateBuffer:
                polygons = PolygonsFromRoadOutlineEntityForEachSeparateBuffer(Parameters.extensionDistance, inputDeps);
                break;

            default:
                throw new NotSupportedException();
            }

            Profiler.BeginSample("Clipper");
            var clipper = new Clipper();

            foreach (var polygon in polygons)
            {
                if (!Clipper.Orientation(polygon))
                {
                    polygon.Reverse();
                }
                if (Clipper.Area(polygon) > 0)
                {
                    clipper.AddPath(polygon, PolyType.ptSubject, true);
                }
            }

            var solution = new List <List <IntPoint> >();

            clipper.Execute(ClipType.ctUnion, solution, PolyFillType.pftNonZero, PolyFillType.pftNonZero);

            solution.RemoveAll(IsSmallerThanMinimumArea);
            Profiler.EndSample();

            Profiler.BeginSample("Create sample entities");
            foreach (var polygon in solution)
            {
                var entity = EntityManager.CreateEntity(m_SamplesArchetype);
                EntityManager.SetComponentData(entity, new PolygonOrientationComponent
                {
                    Orientation = Clipper.Orientation(polygon)
                        ? PolygonOrientation.Outside
                        : PolygonOrientation.Inside
                });

                var buffer = EntityManager.GetBuffer <PointSampleGlobal>(entity);
                var count  = polygon.Count;
                for (var i = 0; i < polygon.Count; i++)
                {
                    var previousPoint = polygon[((i - 1) % count + count) % count];
                    var point         = polygon[i];
                    var nextPoint     = polygon[(i + 1) % polygon.Count];

                    var v1       = new float3(point.X - previousPoint.X, 0, point.Y - previousPoint.Y);
                    var v2       = new float3(nextPoint.X - point.X, 0, nextPoint.Y - point.Y);
                    var rotation = quaternion.LookRotation(v2 + v1, new float3(0, 1, 0));

                    var fromClipperToGlobal = new PointSampleGlobal(new RigidTransform
                    {
                        pos = new float3(
                            point.X * PlacementUtility.DownScaleFactor,
                            0,
                            point.Y * PlacementUtility.DownScaleFactor),
                        rot = rotation
                    });
                    buffer.Add(fromClipperToGlobal);
                }
            }
            Profiler.EndSample();

            return(inputDeps);
        }
        /// <summary>
        /// Gets the Isovist polygon.
        /// </summary>
        /// <param name="vantagePoint">The vantage point.</param>
        /// <param name="viewDepth">The view depth.</param>
        /// <param name="edges">The edges.</param>
        /// <returns>BarrierPolygons.</returns>
        public BarrierPolygon IsovistPolygon(UV vantagePoint, double viewDepth, HashSet <UVLine> edges)
        {
            /*first and expand and shrink operation is performed to merge the shadowing edges*/
            double expandShrinkFactor = Math.Pow(10.0, this.PolygonalBooleanPrecision) * UnitConversion.Convert(0.075, Length_Unit_Types.FEET, UnitType);
            //offsetting the excluded area of each edge
            INTPolygons   offsetedPolygons = new INTPolygons();
            ClipperOffset clipperOffset    = new ClipperOffset();

            foreach (UVLine edgeItem in edges)
            {
                clipperOffset.AddPath(this.excludedArea(vantagePoint, viewDepth + 1, edgeItem), ClipperLib.JoinType.jtMiter, EndType.etClosedPolygon);
                INTPolygons plygns = new INTPolygons();
                clipperOffset.Execute(ref plygns, expandShrinkFactor);
                offsetedPolygons.AddRange(plygns);
                clipperOffset.Clear();
            }
            //Unioning the expanded exclusions
            INTPolygons offsetUnioned = new INTPolygons();
            Clipper     c             = new Clipper();

            c.AddPaths(offsetedPolygons, PolyType.ptSubject, true);
            c.Execute(ClipType.ctUnion, offsetUnioned, PolyFillType.pftNonZero, PolyFillType.pftNonZero);
            //shrink the polygons to retain their original size
            INTPolygons results = new INTPolygons();

            clipperOffset.Clear();
            clipperOffset.AddPaths(offsetUnioned, JoinType.jtMiter, EndType.etClosedPolygon);
            clipperOffset.Execute(ref results, -expandShrinkFactor);
            clipperOffset.Clear();
            offsetUnioned.Clear();

            /*
             * What ever is a hole in the resulting mereged polygon is the visibility polygon
             * Now we classify the polygons based on being a hole or not
             */
            //filtering out the holes that do not include the center
            INTPolygons holesNOT             = new INTPolygons();
            INTPolygons holesIncludingCenter = new INTPolygons();
            IntPoint    iCenter = ConvertUVToIntPoint(vantagePoint);

            foreach (INTPolygon item in results)
            {
                if (!Clipper.Orientation(item))
                {
                    if (Clipper.PointInPolygon(iCenter, item) == 1)
                    {
                        holesIncludingCenter.Add(item);
                    }
                }
                else
                {
                    holesNOT.Add(item);
                }
            }
            if (holesIncludingCenter.Count == 0)
            {
                //there is no hole. The shadow polygones should clip the potential field of visibility (i.e. circle) by an subtraction operation
                INTPolygon circle = createCircle(vantagePoint, viewDepth);
                //subtraction
                c.Clear();
                c.AddPath(circle, PolyType.ptSubject, true);
                c.AddPaths(holesNOT, PolyType.ptClip, true);
                INTPolygons isovistPolygon = new INTPolygons();
                c.Execute(ClipType.ctDifference, isovistPolygon);
                //searching for a polygon that includes the center
                foreach (INTPolygon item in isovistPolygon)
                {
                    if (Clipper.PointInPolygon(iCenter, item) == 1)
                    {
                        BarrierPolygon isovist = this.ConvertINTPolygonToBarrierPolygon(item);
                        results              = null;
                        c                    = null;
                        clipperOffset        = null;
                        offsetedPolygons     = null;
                        circle               = null;
                        holesNOT             = null;
                        holesIncludingCenter = null;
                        isovistPolygon       = null;
                        return(isovist);
                    }
                }
                MessageBox.Show(string.Format("Isovist not found!\nNo hole detected\n{0} polygons can be isovist", isovistPolygon.Count.ToString()));
            }
            else if (holesIncludingCenter.Count == 1)
            {
                INTPolygons isovistPolygon = holesIncludingCenter;
                foreach (INTPolygon item in isovistPolygon)
                {
                    if (Clipper.PointInPolygon(iCenter, item) == 1)
                    {
                        item.Reverse();
                        BarrierPolygon isovist = this.ConvertINTPolygonToBarrierPolygon(item);
                        results              = null;
                        c                    = null;
                        clipperOffset        = null;
                        offsetedPolygons     = null;
                        holesNOT             = null;
                        holesIncludingCenter = null;
                        isovistPolygon       = null;
                        return(isovist);
                    }
                }
                MessageBox.Show(string.Format("Isovist not found!\nOne hole detected\n{0} polygons can be isovist", isovistPolygon.Count.ToString()));
            }
            else if (holesIncludingCenter.Count > 1)
            {
                MessageBox.Show("Isovist not found!\nMore than one hole found that can include the vantage point");
            }
            return(null);
        }
Esempio n. 30
0
        private void CutPoly(ListView <NavmeshCut> InNavmeshCuts, VInt3[] verts, int[] tris, ref VInt3[] outVertsArr, ref int[] outTrisArr, out int outVCount, out int outTCount, VInt3[] extraShape, VInt3 cuttingOffset, Bounds realBounds, SGameTileHandler.CutMode mode = (SGameTileHandler.CutMode) 3, 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 & SGameTileHandler.CutMode.CutExtra) != (SGameTileHandler.CutMode) 0)
            {
                throw new Exception("extraShape is null and the CutMode specifies that it should be used. Cannot use null shape.");
            }
            if ((mode & SGameTileHandler.CutMode.CutExtra) != (SGameTileHandler.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 == SGameTileHandler.CutMode.CutExtra)
            {
                listView = new ListView <NavmeshCut>();
            }
            else
            {
                listView = new ListView <NavmeshCut>(InNavmeshCuts);
            }
            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);
                        }
                    }
                }
            }
            ListView <NavmeshAdd> listView2 = new ListView <NavmeshAdd>();

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

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

            if (listView2.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 >= listView2.Count)
                    {
                        array = null;
                        break;
                    }
                    if (array == verts)
                    {
                        array = null;
                    }
                    listView2[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 & SGameTileHandler.CutMode.CutExtra) == (SGameTileHandler.CutMode) 0 && (mode & SGameTileHandler.CutMode.CutAll) != (SGameTileHandler.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) & SGameTileHandler.CutMode.CutAll) != (SGameTileHandler.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_1173;
                                }
                                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))) ? 0 : 1);
                                }
                                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 = (int)Math.Round(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()) ? null : childs.get_Item(num17).get_Contour()))
                                    {
                                        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 = (int)Math.Round(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(InNavmeshCuts, 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_1173 :;
                    }
                }
            }
            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);
        }