Esempio n. 1
0
        /// <summary>
        /// Generate Colliders based on Tile Collisions
        /// </summary>
        /// <param name="isTrigger">True for Trigger Collider, false otherwise</param>
        /// <param name="zDepth">Z Depth of the collider.</param>
        /// <param name="colliderWidth">Width of the collider, in Units</param>
        /// <param name="used2DColider">True to generate a 2D collider, false to generate a 3D collider.</param>
        /// <param name="innerCollision">If true, calculate normals facing the anchor of the collider (inside collisions), else, outside collisions.</param>
        /// <returns>A GameObject containing all generated colliders</returns>
        public GameObject GenerateTileCollisions(bool used2DColider = true, bool isTrigger = false, float zDepth = 0, float colliderWidth = 1, bool innerCollision = false)
        {
            GameObject tileColisions = new GameObject("Tile Collisions");
            tileColisions.transform.parent = MapObject.transform;
            tileColisions.transform.localPosition = Vector3.zero;

            ClipperLib.Clipper clipper = new ClipperLib.Clipper();
            List<List<ClipperLib.IntPoint>> pathsList = new List<List<ClipperLib.IntPoint>>();
            List<List<ClipperLib.IntPoint>> solution = new List<List<ClipperLib.IntPoint>>();
            // Iterate over each Tile Layer, grab all TileObjects inside this layer and use their Paths with ClipperLib to generate one polygon collider
            foreach (var layer in Layers)
            {
                if (layer is TileLayer)
                {
                    clipper.Clear();
                    solution.Clear();
                    pathsList.Clear();
                    TileLayer tileLayer = layer as TileLayer;
                    for (int x = 0; x < tileLayer.Tiles.Width; x++)
                    {
                        for (int y = 0; y < tileLayer.Tiles.Height; y++)
                        {
                            Tile t = tileLayer.Tiles[x, y];
                            if (t == null || t.TileSet == null || t.TileSet.TilesObjects == null)
                                continue;
                            if (t.TileSet.TilesObjects.ContainsKey(t.OriginalID))
                            {
                                List<TileObject> tileObjs = t.TileSet.TilesObjects[t.OriginalID];
                                foreach (var tileObj in tileObjs)
                                {
                                    pathsList.Add(tileObj.GetPath(x, y, t.SpriteEffects, _tileObjectEllipsePrecision));
                                }
                            }
                        }
                    }
                    // Add the paths to be merged to ClipperLib
                    clipper.AddPaths(pathsList, ClipperLib.PolyType.ptSubject, true);
                    // Merge it!
                    //clipper.PreserveCollinear = false;
                    //clipper.ReverseSolution = true;
                    clipper.StrictlySimple = _simpleTileObjectCalculation;
                    if (!clipper.Execute(ClipperLib.ClipType.ctUnion, solution))
                        continue;
                    clipper.Execute(ClipperLib.ClipType.ctUnion, solution);
                    // Now solution should contain all vertices of the collision object, but they are still multiplied by TileObject.ClipperScale!

                    #region Implementation of increase and decrease offset polygon.
                    if(_simpleTileObjectCalculation == false) {
                        // Link of the example of ClipperLib:
                        // http://www.angusj.com/delphi/clipper/documentation/Docs/Units/ClipperLib/Classes/ClipperOffset/_Body.htm

                        ClipperLib.ClipperOffset co = new ClipperLib.ClipperOffset(_clipperMiterLimit,_clipperArcTolerance);
                        foreach(List<ClipperLib.IntPoint> item in solution) {
                            co.AddPath(item, _clipperJoinType,_clipperEndType);
                        }
                        solution.Clear();
                        co.Execute(ref solution, _clipperDeltaOffset*TileObject.ClipperScale);
                    }
                    #endregion

                    // Generate this path's collision
                    GameObject newCollider = new GameObject("Tile Collisions " + layer.Name);
                    newCollider.transform.parent = tileColisions.transform;
                    newCollider.transform.localPosition = new Vector3(0, 0, zDepth);

                    // Finally, generate the edge collider
                    int counter = 0;

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

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

                        for (int j = 0; j < solution[i].Count; j++)
                        {
                            points.Add(
                                new Vector2(
                                    solution[i][j].X / (float)TileObject.ClipperScale,
                                    solution[i][j].Y / (float)TileObject.ClipperScale
                                )
                            );
                        }

                        if (used2DColider)
                            Generate2DTileCollision(tileLayer, counter, newCollider.transform, points, isTrigger, zDepth);
                        else
                            Generate3DTileCollision(tileLayer, counter, newCollider.transform, points, isTrigger, zDepth, colliderWidth, innerCollision);

                        counter++;
                    }

                    newCollider.isStatic = true;
                }
            }

            return tileColisions;
        }
        public static List<List<Vector2>> GenerateClipperPathPoints(TileLayer tileLayer,
			bool simpleTileObjectCalculation = true,
			double clipperArcTolerance = 0.25, double clipperMiterLimit = 2.0,
			ClipperLib.JoinType clipperJoinType = ClipperLib.JoinType.jtRound,
			ClipperLib.EndType clipperEndType = ClipperLib.EndType.etClosedPolygon,
			float clipperDeltaOffset = 0)
        {
            ClipperLib.Clipper clipper = new ClipperLib.Clipper();
            List<List<ClipperLib.IntPoint>> pathsList = new List<List<ClipperLib.IntPoint>>();
            List<List<ClipperLib.IntPoint>> solution = new List<List<ClipperLib.IntPoint>>();
            List<List<Vector2>> points = new List<List<Vector2>>();

            for (int x = 0; x < tileLayer.Tiles.Width; x++)
            {
                for (int y = 0; y < tileLayer.Tiles.Height; y++)
                {
                    Tile t = tileLayer.Tiles[x, y];
                    if (t == null || t.TileSet == null || t.TileSet.TilesObjects == null)
                        continue;
                    if (t.TileSet.TilesObjects.ContainsKey(t.OriginalID))
                    {
                        List<TileObject> tileObjs = t.TileSet.TilesObjects[t.OriginalID];
                        foreach (var tileObj in tileObjs)
                        {
                            pathsList.Add(tileObj.GetPath(x, y, t.SpriteEffects, tileLayer.BaseMap.MapRenderParameter.TileWidth, tileLayer.BaseMap.MapRenderParameter.TileHeight));
                        }
                    }
                }
            }
            // Add the paths to be merged to ClipperLib
            clipper.AddPaths(pathsList, ClipperLib.PolyType.ptSubject, true);
            // Merge it!
            //clipper.PreserveCollinear = false;
            //clipper.ReverseSolution = true;
            clipper.StrictlySimple = simpleTileObjectCalculation;
            if (!clipper.Execute(ClipperLib.ClipType.ctUnion, solution))
                return points;
            clipper.Execute(ClipperLib.ClipType.ctUnion, solution);
            // Now solution should contain all vertices of the collision object, but they are still multiplied by TileObject.ClipperScale!

            #region Implementation of increase and decrease offset polygon.
            if (simpleTileObjectCalculation == false)
            {
                // Link of the example of ClipperLib:
                // http://www.angusj.com/delphi/clipper/documentation/Docs/Units/ClipperLib/Classes/ClipperOffset/_Body.htm

                ClipperLib.ClipperOffset co = new ClipperLib.ClipperOffset(clipperMiterLimit, clipperArcTolerance);
                foreach (List<ClipperLib.IntPoint> item in solution)
                {
                    co.AddPath(item, clipperJoinType, clipperEndType);
                }
                solution.Clear();
                co.Execute(ref solution, clipperDeltaOffset * TileObject.ClipperScale);
            }
            #endregion

            for (int i = 0; i < solution.Count; i++)
            {
                if (solution[i].Count < 1)
                    continue;
                points.Add(new List<Vector2>());
                for (int j = 0; j < solution[i].Count; j++)
                {
                    points[i].Add(
                        new Vector2(
                            solution[i][j].X / (float)TileObject.ClipperScale,
                            solution[i][j].Y / (float)TileObject.ClipperScale
                        )
                    );
                }
            }

            return points;
        }
Esempio n. 3
0
        public static List <PointLatLngAlt> CreateRotary(List <PointLatLngAlt> polygon, double altitude, double distance, double spacing, double angle, double overshoot1, double overshoot2, StartPosition startpos, bool shutter, float minLaneSeparation, float leadin, PointLatLngAlt HomeLocation)
        {
            spacing = 0;

            if (distance < 0.1)
            {
                distance = 0.1;
            }

            if (polygon.Count == 0)
            {
                return(new List <PointLatLngAlt>());
            }

            List <utmpos> ans = new List <utmpos>();

            // utm zone distance calcs will be done in
            int utmzone = polygon[0].GetUTMZone();

            // utm position list
            List <utmpos> utmpositions = utmpos.ToList(PointLatLngAlt.ToUTM(utmzone, polygon), utmzone);

            // close the loop if its not already
            if (utmpositions[0] != utmpositions[utmpositions.Count - 1])
            {
                utmpositions.Add(utmpositions[0]); // make a full loop
            }
            var maxlane = 200;                     // (Centroid(utmpositions).GetDistance(utmpositions[0]) / distance);

            ClipperLib.ClipperOffset clipperOffset = new ClipperLib.ClipperOffset();

            clipperOffset.AddPath(utmpositions.Select(a => { return(new ClipperLib.IntPoint(a.x * 1000.0, a.y * 1000.0)); }).ToList(), ClipperLib.JoinType.jtMiter, ClipperLib.EndType.etClosedPolygon);

            for (int lane = 0; lane < maxlane; lane++)
            {
                List <utmpos> ans1 = new List <utmpos>();

                ClipperLib.PolyTree tree = new ClipperLib.PolyTree();
                clipperOffset.Execute(ref tree, (Int64)(distance * 1000.0 * -lane));

                if (tree.ChildCount == 0)
                {
                    break;
                }

                foreach (var treeChild in tree.Childs)
                {
                    ans1 = treeChild.Contour.Select(a => new utmpos(a.X / 1000.0, a.Y / 1000.0, utmzone))
                           .ToList();

                    if (ans.Count() > 2)
                    {
                        var start1 = ans[ans.Count() - 1];
                        var end1   = ans[ans.Count() - 2];

                        var start2 = ans1[0];
                        var end2   = ans1[ans1.Count() - 1];
                    }

                    ans.AddRange(ans1);
                }
            }

            // set the altitude on all points
            return(ans.Select(plla => { var a = plla.ToLLA(); a.Alt = altitude; a.Tag = "S"; return a; }).ToList());
        }
Esempio n. 4
0
        public static List <PointLatLngAlt> CreateRotary(List <PointLatLngAlt> polygon, double altitude, double distance, double spacing, double angle, double overshoot1, double overshoot2, StartPosition startpos, bool shutter, float minLaneSeparation, float leadin, PointLatLngAlt HomeLocation, int clockwise_laps, bool match_spiral_perimeter, int laps)
        {
            spacing = 0;

            if (distance < 0.1)
            {
                distance = 0.1;
            }

            if (polygon.Count == 0)
            {
                return(new List <PointLatLngAlt>());
            }

            List <utmpos> ans = new List <utmpos>();

            // utm zone distance calcs will be done in
            int utmzone = polygon[0].GetUTMZone();

            // utm position list
            List <utmpos> utmpositions = utmpos.ToList(PointLatLngAlt.ToUTM(utmzone, polygon), utmzone);

            // close the loop if its not already
            if (utmpositions[0] != utmpositions[utmpositions.Count - 1])
            {
                utmpositions.Add(utmpositions[0]); // make a full loop
            }
            var maxlane = laps;                    // (Centroid(utmpositions).GetDistance(utmpositions[0]) / distance);

            ClipperLib.ClipperOffset clipperOffset = new ClipperLib.ClipperOffset();

            clipperOffset.AddPath(utmpositions.Select(a => { return(new ClipperLib.IntPoint(a.x * 1000.0, a.y * 1000.0)); }).ToList(), ClipperLib.JoinType.jtMiter, ClipperLib.EndType.etClosedPolygon);

            for (int lane = 0; lane < maxlane; lane++)
            {
                List <utmpos> ans1 = new List <utmpos>();

                ClipperLib.PolyTree tree = new ClipperLib.PolyTree();
                clipperOffset.Execute(ref tree, (Int64)(distance * 1000.0 * -lane));

                if (tree.ChildCount == 0)
                {
                    break;
                }

                if (lane < clockwise_laps || clockwise_laps < 0)
                {
                    ClipperLib.Clipper.ReversePaths(ClipperLib.Clipper.PolyTreeToPaths(tree));
                }

                foreach (var treeChild in tree.Childs)
                {
                    ans1 = treeChild.Contour.Select(a => new utmpos(a.X / 1000.0, a.Y / 1000.0, utmzone))
                           .ToList();

                    if (lane == 0 && clockwise_laps != 1 && match_spiral_perimeter)
                    {
                        ans1.Insert(0, ans1.Last <utmpos>());   // start at the last point of the first calculated lap
                                                                // to make a closed polygon on the first trip around
                    }


                    if (lane == clockwise_laps - 1)
                    {
                        ans1.Add(ans1.First <utmpos>());  // revisit the first waypoint on this lap to cleanly exit the CW pattern
                    }

                    if (ans.Count() > 2)
                    {
                        var start1 = ans[ans.Count() - 1];
                        var end1   = ans[ans.Count() - 2];

                        var start2 = ans1[0];
                        var end2   = ans1[ans1.Count() - 1];
                    }

                    ans.AddRange(ans1);
                }
            }

            // set the altitude on all points
            return(ans.Select(plla => { var a = plla.ToLLA(); a.Alt = altitude; a.Tag = "S"; return a; }).ToList());
        }