示例#1
0
 public static void Triangulate(PointSet ps)
 {
     Triangulate(_defaultAlgorithm, ps);
 }
    public void Generate()
    {
        generationMessage = "Generating points...";

        //Generate some points...
        List<Point> generationPoints = new List<Point>();

        for(int i = 0; i < numberOfPoints; i++) {
            Point randomPoint = new Point(Random.Range(-levelRadius, levelRadius), Random.Range(-levelRadius, levelRadius));
            randomPoint = new Point( (randomPoint.x * delaunayPointSnap) / delaunayPointSnap, (randomPoint.y * delaunayPointSnap) / delaunayPointSnap);
            if(!generationPoints.Contains(randomPoint)) {
                generationPoints.Add(randomPoint);
            }
        }

        //Clean up duplicates

        generationMessage = "Triangulating...";
        //Generate a delaunay triangulation of the points
        Poly2Tri.PointSet ps = new Poly2Tri.PointSet(generationPoints.Select(d=>(Poly2Tri.TriangulationPoint)d).ToList());
        Poly2Tri.P2T.Triangulate (ps);
        List<Poly2Tri.DelaunayTriangle> delaunayTriangles = ps.Triangles.ToList();

        generationMessage = "Performing Brownian Walk through triangulation...";
        //Brownian Walk through the triangles.
        Poly2TriDelaunayTriangulationWalker walker = new Poly2TriDelaunayTriangulationWalker (delaunayTriangles);
        List<Poly2Tri.DelaunayTriangle> levelTriangleSet = new List<Poly2Tri.DelaunayTriangle>();

        for (int i = 0; i < numberOfStepsForBrownianWalk; i++) {
            Poly2Tri.DelaunayTriangle nextTriangle = walker.Next();
            if(!levelTriangleSet.Contains(nextTriangle)) {
                levelTriangleSet.Add(nextTriangle);
            }
        }

        generationMessage = "Performing Tendril Walks...";
        for (int i = 0; i < numberOfTendrilWalksToComplete; i++) {
            generationMessage = "Performing Tendril Walk: " + i;
            walker.SetCurrentTriangleIndex(delaunayTriangles.IndexOf(levelTriangleSet[Mathf.FloorToInt(Random.value * levelTriangleSet.Count)]));
            for (int j = 0; j < numberOfStepsForBrownianWalk; j++) {
                Poly2Tri.DelaunayTriangle nextTriangle = walker.Next();
                if(!levelTriangleSet.Contains(nextTriangle)) {
                    levelTriangleSet.Add(nextTriangle);
                }
            }
        }

        generationMessage = "Getting level boolean...";
        //List<Poly2Tri.DelaunayTriangle> booleanFromLevelSet = delaunayTriangles.Where (x => !levelTriangleSet.Contains (x)).ToList ();

        /* Debugging delaunay triangulation
        foreach (Poly2Tri.DelaunayTriangle tri in booleanFromLevelSet) {
            Gizmos.DrawLine(new Vector2(tri.Points[0].Xf, tri.Points[0].Yf), new Vector2(tri.Points[1].Xf, tri.Points[1].Yf));
            Gizmos.DrawLine(new Vector2(tri.Points[1].Xf, tri.Points[1].Yf), new Vector2(tri.Points[2].Xf, tri.Points[2].Yf));
            Gizmos.DrawLine(new Vector2(tri.Points[2].Xf, tri.Points[2].Yf), new Vector2(tri.Points[0].Xf, tri.Points[0].Yf));
        }
        */

        //Generate colliders...
        ClipperLib.Clipper clipper = new ClipperLib.Clipper ();
        foreach(Poly2Tri.DelaunayTriangle tri in levelTriangleSet) {
            Polygon trianglePoints = new Polygon();
            for(int i = 0; i < 3; i++) {
                trianglePoints.points.Add(tri.Points[i]);
            }
            clipper.AddPath(trianglePoints, ClipperLib.PolyType.ptSubject, true);

        }

        List<List<ClipperLib.IntPoint>> solution = new List<List<ClipperLib.IntPoint>> ();
        clipper.Execute (ClipperLib.ClipType.ctUnion, solution, ClipperLib.PolyFillType.pftPositive, ClipperLib.PolyFillType.pftPositive);

        generationMessage = "Generating mesh from boolean...";
        DestructibleLevel level = GetComponent<DestructibleLevel> ();
        if (level == null) {
            level = gameObject.AddComponent<DestructibleLevel>();
        }

        foreach (List<ClipperLib.IntPoint> polygon in solution) {
            level.booleanPolygons.Add(new Tinkerbox.Geometry.Polygon(polygon));
        }

        level.UpdateMesh();

        generationMessage = "Calling Callback..";
        OnFinishedGeneration();
        GameObject[] players = GameObject.FindGameObjectsWithTag ("Player");
        Poly2Tri.DelaunayTriangle spawnTriangle = levelTriangleSet [Mathf.FloorToInt (Random.value * levelTriangleSet.Count)];

        generationMessage = "Spawning Players...";
        Vector2 spawnPoint = new Vector2 (spawnTriangle.Centroid ().Xf, spawnTriangle.Centroid ().Yf);

        foreach (GameObject player in players) {
            player.transform.position = spawnPoint + Random.insideUnitCircle;

        }

        generationMessage = "Spawning Decorations...";
        for (int i = 0; i < decorationsToSpawn; i++) {
            GameObject decoration = (GameObject) Instantiate(decorations[Mathf.FloorToInt(Random.value * decorations.Length)]);
            Poly2Tri.DelaunayTriangle decorSpawnTriangle = levelTriangleSet [Mathf.FloorToInt (Random.value * levelTriangleSet.Count)];
            Point decorSpawnPoint = decorSpawnTriangle.Centroid();
            decoration.transform.position = decorSpawnPoint + Random.insideUnitCircle;
        }

        //yield return 0;
    }
示例#3
0
        ////////


        public static PointSet LoadDatPointSet(string filename, bool xflip, bool yflip, bool displayFlipX, bool displayFlipY, float rotateAngleInDegrees)
        {
            var points = new List<TriangulationPoint>();
            List<List<TriangulationPoint>> constrainedPoints = new List<List<TriangulationPoint>>();
            List<string> constrainedPointSetNames = new List<string>();
            List<TriangulationPoint> bounds = new List<TriangulationPoint>();
            List<TriangulationPoint> currentList = points;
            double precision = TriangulationPoint.kVertexCodeDefaultPrecision;
            int lineNum = 0;
            bool skipLine = false;
            foreach (var line_ in File.ReadAllLines(filename))
            {
                ++lineNum;
                string line = line_.Trim();
                if (string.IsNullOrEmpty(line) ||
                    line.StartsWith("//") ||
                    line.StartsWith("#") ||
                    line.StartsWith(";"))
                {
                    continue;
                }
                if (!skipLine && line.StartsWith("/*"))
                {
                    skipLine = true;
                    continue;
                }
                else if (skipLine)
                {
                    if( line.StartsWith("*/"))
                    {
                        skipLine = false;
                    }
                    continue;
                }
                if (line.StartsWith("Precision", StringComparison.InvariantCultureIgnoreCase))
                {
                    if (line.Length > 9)
                    {
                        string precisionStr = line.Substring(9).Trim();
                        if (!double.TryParse(precisionStr, NumberStyles.Float, CultureInfo.InvariantCulture, out precision))
                        {
                            Console.WriteLine("Invalid Precision '" + precisionStr + "' in file " + filename + ", line " + lineNum.ToString() + ".  Setting to " + TriangulationPoint.kVertexCodeDefaultPrecision.ToString());
                            precision = TriangulationPoint.kVertexCodeDefaultPrecision;
                        }
                    }
                }
                else if (line.StartsWith("Set", StringComparison.InvariantCultureIgnoreCase))
                {
                    if (line.StartsWith("SetBegin"))
                    {
                        string[] setParts = line.Split(new[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
                        if (setParts.Length < 2)
                        {
                            continue;
                        }
                        //if (setParts[1].Equals("Constrained", StringComparison.InvariantCultureIgnoreCase))
                        if (setParts[1].Equals("Constrained", StringComparison.InvariantCultureIgnoreCase) ||
                            setParts[1].Equals("Unconstrained", StringComparison.InvariantCultureIgnoreCase))
                        {
                            currentList = new List<TriangulationPoint>();
                            constrainedPoints.Add(currentList);
                            if( setParts.Length>2)
                            {
                                constrainedPointSetNames.Add(setParts[2]);
                            }
                            else
                            {
                                constrainedPointSetNames.Add("");
                            }
                        }
                        else if (bounds.Count == 0 && setParts[1].Equals("Bounds", StringComparison.InvariantCultureIgnoreCase))
                        {
                            currentList = bounds;
                        }
                        else
                        {
                            currentList = points;
                        }
                    }
                    else
                    {
                        currentList = points;
                    }
                }
                else
                {
                    var xy = line.Split(new[] { ' ', ',' }, StringSplitOptions.RemoveEmptyEntries);
                    double x, y;
                    if (xy != null &&
                        xy.Length >= 2 &&
                        double.TryParse(xy[0], NumberStyles.Float, CultureInfo.InvariantCulture, out x) &&
                        double.TryParse(xy[1], NumberStyles.Float, CultureInfo.InvariantCulture, out y))
                    {
                        currentList.Add(new PolygonPoint((xflip ? -1.0 : 1.0) * x, (yflip ? -1.0 : 1.0) * y));
                    }
                    else
                    {
                        Console.WriteLine("Invalid Input '" + line + "' in file " + filename + ", line " + lineNum.ToString());
                    }
                }
            }

            PointSet ps = null;
            if (constrainedPoints.Count > 0)
            {
                ConstrainedPointSet cps = null;
                if (bounds.Count < 3)
                {
                    points.AddRange(bounds);
                    cps = new ConstrainedPointSet(points);
                }
                else
                {
                    cps = new ConstrainedPointSet(bounds);
                    cps.AddRange(points);
                }
                int numConstrainedPointSets = constrainedPoints.Count;
                for( int i = 0; i < numConstrainedPointSets; ++i)
                {
                    List<TriangulationPoint> hole = constrainedPoints[i];
                    if (hole.Count < 3)
                    {
                        cps.AddRange(hole);
                    }
                    else
                    {
                        cps.AddHole(hole, constrainedPointSetNames[i]);
                    }
                }
                ps = cps;
            }
            else
            {
                if (bounds.Count < 3)
                {
                    points.AddRange(bounds);
                    ps = new PointSet(points);
                }
                else
                {
                    ps = new PointSet(bounds);
                    ps.AddRange(points);
                }
            }

            ps.FileName = filename;
            ps.DisplayFlipX = displayFlipX;
            ps.DisplayFlipY = displayFlipY;
            ps.DisplayRotate = rotateAngleInDegrees;
            ps.Precision = precision;

            return ps;
        }
示例#4
0
        public Bitmap ReconstructImage(SampledImage sampledImage)
        {
            int width = sampledImage.Width;
            int height = sampledImage.Height;
            Bitmap image = new Bitmap(width, height);

            Progress.ReportProgress(0);

            Stopwatch stopwatch = Stopwatch.StartNew();

            // use cached triangulation if possible
            PointSet triMesh =
                (TriangulationCachingEnabled && sampledImage.Equals(previousSampledImage)) ?
                    previousTriMesh : voronoiHelper.MakeDelaunayTriangulation(sampledImage);

            stopwatch.Stop();
            Progress.TimeReport["delaunay"] = stopwatch.ElapsedMilliseconds;

            previousTriMesh = triMesh;
            previousSampledImage = sampledImage;

            Progress.ReportProgress(25);

            stopwatch.Reset();
            stopwatch.Start();

            using (Graphics graphics = Graphics.FromImage(image))
            {
                // fill with black background
                //graphics.FillRectangle(Brushes.White, 0, 0, width, height);

                graphics.SmoothingMode = AntiAliasingEnabled ?
                    System.Drawing.Drawing2D.SmoothingMode.AntiAlias :
                    System.Drawing.Drawing2D.SmoothingMode.None;

                if (VoronoiCellsEnabled)
                {
                    DrawVoronoiCells(triMesh, graphics, sampledImage);
                }

                Progress.ReportProgress(50);

                if (DelaunayTrianglesEnabled)
                {
                    DrawDelaunayTriangles(triMesh, graphics);
                }

                Progress.ReportProgress(75);

                DrawAdditionalFeatures(width, height, triMesh, graphics, image);

                Progress.ReportProgress(100);
            }
            Progress.TimeReport["visualizer"] = stopwatch.ElapsedMilliseconds;

            return image;
        }
示例#5
0
文件: P2T.cs 项目: xtaci/poly2tri.cs
 public static void Triangulate(PointSet ps)
 {
     Triangulate(_defaultAlgorithm, ps);
 }
示例#6
0
        private void DrawVoronoiCells(PointSet triMesh, Graphics graphics, SampledImage sampledImage)
        {
            int samplePercent = 4 * triMesh.Triangles.Count / 100;
            int trianglesDone = 0;
            int percentDone = 0;

            // Voronoi cell which have already been drawn onto the image
            HashSet<Vector2> drawnVoronoiCells = new HashSet<Vector2>();

            foreach (DelaunayTriangle triangle in triMesh.Triangles)
            {
                // draw Voronoi cells, one around each Delaunay triangle vertex
                foreach (TriangulationPoint triVertex in triangle.Points)
                {
                    // each cell corresponds to a triangulation vertex
                    Vector2 point = triVertex.ToVector2();
                    if (drawnVoronoiCells.Contains(point))
                    {
                        // this Voronoi cell was already drawn
                        continue;
                    }
                    drawnVoronoiCells.Add(point);
                    IList<DelaunayTriangle> surroundingTriangles =
                        VoronoiHelper.GetSurroundingTriangles(triangle, triVertex);
                    if (surroundingTriangles.Count < 3)
                    {
                        // there are not enough vertices to make a polygon
                        continue;
                    }
                    // TODO: the computation of the circumference could
                    // be cached since the voronoi vertices are usually
                    // share among multiple triangles
                    IEnumerable<Vector2> voronoiCellVertices = surroundingTriangles.Select(
                        (DelaunayTriangle tri) => VoronoiHelper.GetCircumcenter(tri));
                    PointF[] voronoiCellPolygon = voronoiCellVertices.Select(
                        (Vector2 vertex) => vertex.ToPointF()).ToArray();

                    //Color sampleColor = GetRandomColor();
                    ImageSample imageSample;
                    Color sampleColor = Color.Pink;  // DEBUG
                    if (sampledImage.SampleMap.TryGetValue((int)triVertex.Y * sampledImage.Width + (int)triVertex.X, out imageSample))
                    {
                        sampleColor = imageSample.color;
                    }
                    graphics.FillPolygon(new SolidBrush(sampleColor), voronoiCellPolygon);
                    if (VoronoiCellBordersEnabled)
                    {
                        graphics.DrawPolygon(Pens.Gray, voronoiCellPolygon);
                    }
                }
                trianglesDone++;
                if ((samplePercent > 500) && (trianglesDone % samplePercent == 0))
                {
                    percentDone++;
                    Progress.ReportProgress(25 + percentDone);
                }
            }
        }
示例#7
0
        private void DrawDelaunayTriangles(PointSet triMesh, Graphics graphics)
        {
            int samplePercent = 4 * triMesh.Triangles.Count / 100;
            int trianglesDone = 0;
            int percentDone = 0;

            foreach (DelaunayTriangle triangle in triMesh.Triangles)
            {
                // draw Delaunay triangulation
                PointF[] points = triangle.ToPointFArray();
                graphics.DrawPolygon(Pens.Black, points);

                trianglesDone++;
                if ((samplePercent > 500) && (trianglesDone % samplePercent == 0))
                {
                    percentDone++;
                    Progress.ReportProgress(50 + percentDone);
                }
            }
        }
示例#8
0
        private void DrawAdditionalFeatures(int width, int height, PointSet triMesh, Graphics graphics, Bitmap image)
        {
            int samplePercent = 4 * triMesh.Triangles.Count / 100;
            int trianglesDone = 0;
            int percentDone = 0;

            if (VoronoiVerticesEnabled || DelaunayCircumcirclesEnabled)
            {
                foreach (DelaunayTriangle triangle in triMesh.Triangles)
                {

                    Vector2 voronoiVertex = VoronoiHelper.GetCircumcenter(triangle);
                    if (VoronoiVerticesEnabled)
                    {
                        DrawVoronoiVertex(width, height, voronoiVertex, graphics, image);
                    }
                    if (DelaunayCircumcirclesEnabled)
                    {
                        DrawDelaunayCircumcircles(triangle, voronoiVertex, graphics);
                    }

                    trianglesDone++;
                    if ((samplePercent > 500) && (trianglesDone % samplePercent == 0))
                    {
                        percentDone++;
                        Progress.ReportProgress(75 + percentDone);
                    }
                }
            }
        }
示例#9
0
        public PointSet MakeDelaunayTriangulation(List<TriangulationPoint> points)
        {
            PointSet polygon = new PointSet(points);
            try
            {
                Stopwatch stopwatch = Stopwatch.StartNew();

                P2T.Triangulate(polygon);

                stopwatch.Stop();
                progress.TimeReport["delaunay"] = stopwatch.ElapsedMilliseconds;
            }
            catch (NotImplementedException ex)
            {
                Console.WriteLine("Delaunay triangulation - exception: {0}", ex.Message);
            }
            //catch (NullReferenceException ex)
            //{
            //    Console.WriteLine("Delaunay triangulation - exception: {0}", ex.Message);
            //}
            return polygon;
        }
示例#10
0
        ////////


        public static PointSet LoadDatPointSet(string filename, bool xflip, bool yflip, bool displayFlipX, bool displayFlipY, float rotateAngleInDegrees)
        {
            var points = new List <TriangulationPoint>();
            List <List <TriangulationPoint> > constrainedPoints = new List <List <TriangulationPoint> >();
            List <string>             constrainedPointSetNames  = new List <string>();
            List <TriangulationPoint> bounds      = new List <TriangulationPoint>();
            List <TriangulationPoint> currentList = points;
            double precision = TriangulationPoint.kVertexCodeDefaultPrecision;
            int    lineNum   = 0;
            bool   skipLine  = false;

            foreach (var line_ in File.ReadAllLines(filename))
            {
                ++lineNum;
                string line = line_.Trim();
                if (string.IsNullOrEmpty(line) ||
                    line.StartsWith("//") ||
                    line.StartsWith("#") ||
                    line.StartsWith(";"))
                {
                    continue;
                }
                if (!skipLine && line.StartsWith("/*"))
                {
                    skipLine = true;
                    continue;
                }
                else if (skipLine)
                {
                    if (line.StartsWith("*/"))
                    {
                        skipLine = false;
                    }
                    continue;
                }
                if (line.StartsWith("Precision", StringComparison.InvariantCultureIgnoreCase))
                {
                    if (line.Length > 9)
                    {
                        string precisionStr = line.Substring(9).Trim();
                        if (!double.TryParse(precisionStr, NumberStyles.Float, CultureInfo.InvariantCulture, out precision))
                        {
                            Console.WriteLine("Invalid Precision '" + precisionStr + "' in file " + filename + ", line " + lineNum.ToString() + ".  Setting to " + TriangulationPoint.kVertexCodeDefaultPrecision.ToString());
                            precision = TriangulationPoint.kVertexCodeDefaultPrecision;
                        }
                    }
                }
                else if (line.StartsWith("Set", StringComparison.InvariantCultureIgnoreCase))
                {
                    if (line.StartsWith("SetBegin"))
                    {
                        string[] setParts = line.Split(new[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
                        if (setParts.Length < 2)
                        {
                            continue;
                        }
                        //if (setParts[1].Equals("Constrained", StringComparison.InvariantCultureIgnoreCase))
                        if (setParts[1].Equals("Constrained", StringComparison.InvariantCultureIgnoreCase) ||
                            setParts[1].Equals("Unconstrained", StringComparison.InvariantCultureIgnoreCase))
                        {
                            currentList = new List <TriangulationPoint>();
                            constrainedPoints.Add(currentList);
                            if (setParts.Length > 2)
                            {
                                constrainedPointSetNames.Add(setParts[2]);
                            }
                            else
                            {
                                constrainedPointSetNames.Add("");
                            }
                        }
                        else if (bounds.Count == 0 && setParts[1].Equals("Bounds", StringComparison.InvariantCultureIgnoreCase))
                        {
                            currentList = bounds;
                        }
                        else
                        {
                            currentList = points;
                        }
                    }
                    else
                    {
                        currentList = points;
                    }
                }
                else
                {
                    var    xy = line.Split(new[] { ' ', ',' }, StringSplitOptions.RemoveEmptyEntries);
                    double x, y;
                    if (xy != null &&
                        xy.Length >= 2 &&
                        double.TryParse(xy[0], NumberStyles.Float, CultureInfo.InvariantCulture, out x) &&
                        double.TryParse(xy[1], NumberStyles.Float, CultureInfo.InvariantCulture, out y))
                    {
                        currentList.Add(new PolygonPoint((xflip ? -1.0 : 1.0) * x, (yflip ? -1.0 : 1.0) * y));
                    }
                    else
                    {
                        Console.WriteLine("Invalid Input '" + line + "' in file " + filename + ", line " + lineNum.ToString());
                    }
                }
            }

            PointSet ps = null;

            if (constrainedPoints.Count > 0)
            {
                ConstrainedPointSet cps = null;
                if (bounds.Count < 3)
                {
                    points.AddRange(bounds);
                    cps = new ConstrainedPointSet(points);
                }
                else
                {
                    cps = new ConstrainedPointSet(bounds);
                    cps.AddRange(points);
                }
                int numConstrainedPointSets = constrainedPoints.Count;
                for (int i = 0; i < numConstrainedPointSets; ++i)
                {
                    List <TriangulationPoint> hole = constrainedPoints[i];
                    if (hole.Count < 3)
                    {
                        cps.AddRange(hole);
                    }
                    else
                    {
                        cps.AddHole(hole, constrainedPointSetNames[i]);
                    }
                }
                ps = cps;
            }
            else
            {
                if (bounds.Count < 3)
                {
                    points.AddRange(bounds);
                    ps = new PointSet(points);
                }
                else
                {
                    ps = new PointSet(bounds);
                    ps.AddRange(points);
                }
            }

            ps.FileName      = filename;
            ps.DisplayFlipX  = displayFlipX;
            ps.DisplayFlipY  = displayFlipY;
            ps.DisplayRotate = rotateAngleInDegrees;
            ps.Precision     = precision;

            return(ps);
        }