Beispiel #1
0
        /// <summary>
        /// Rebuild the input geometry.
        /// </summary>
        private InputGeometry Rebuild()
        {
            InputGeometry geometry = new InputGeometry(mesh.vertices.Count);

            foreach (var vertex in mesh.vertices.Values)
            {
                geometry.AddPoint(vertex.x, vertex.y, vertex.mark);
            }

            foreach (var segment in mesh.subsegs.Values)
            {
                geometry.AddSegment(segment.P0, segment.P1, segment.Boundary);
            }

            foreach (var hole in mesh.holes)
            {
                geometry.AddHole(hole.x, hole.y);
            }

            foreach (var region in mesh.regions)
            {
                geometry.AddRegion(region.point.x, region.point.y, region.id);
            }

            return(geometry);
        }
Beispiel #2
0
    /// <summary>
    /// Add a polygon ring to the geometry and make it a hole.
    /// </summary>
    /// <remarks>
    /// WARNING: This works for convex polygons, but not for non-convex regions in general.
    /// </remarks>
    /// <param name="points">List of points which make up the hole.</param>
    /// <param name="mark">Common boundary mark for all segments of the hole.</param>
    public static void AddRingAsHole(this InputGeometry geometry,
                                     IEnumerable <Point> points, int mark = 0)
    {
        // Save the current number of points.
        int N = geometry.Count;

        // Hole coordinates
        float x = 0.0f;
        float y = 0.0f;

        int m = 0;

        foreach (var pt in points)
        {
            x += pt.X;
            y += pt.Y;

            geometry.AddPoint(pt.X, pt.Y, pt.Boundary, pt.Attributes);
            m++;
        }

        for (int i = 0; i < m; i++)
        {
            geometry.AddSegment(N + i, N + ((i + 1) % m), mark);
        }

        geometry.AddHole(x / m, y / m);
    }
Beispiel #3
0
        public override InputGeometry Generate(double param0, double param1, double param2)
        {
            // Number of points on the outer circle
            int n = GetParamValueInt(0, param0);
            int count, npoints;

            double radius = GetParamValueInt(1, param1);

            // Step size on the outer circle
            double h = 2 * Math.PI * radius / n;

            // Current radius and step size
            double r, dphi;

            InputGeometry input = new InputGeometry(n + 1);

            // Inner cirlce (radius = 1)
            r       = 1;
            npoints = (int)(2 * Math.PI * r / h);
            dphi    = 2 * Math.PI / npoints;
            for (int i = 0; i < npoints; i++)
            {
                input.AddPoint(r * Math.Cos(i * dphi), r * Math.Sin(i * dphi), 1);
                input.AddSegment(i, (i + 1) % npoints, 1);
            }

            count = input.Count;

            // Center cirlce
            r       = (radius + 1) / 2.0;
            npoints = (int)(2 * Math.PI * r / h);
            dphi    = 2 * Math.PI / npoints;
            for (int i = 0; i < npoints; i++)
            {
                input.AddPoint(r * Math.Cos(i * dphi), r * Math.Sin(i * dphi), 2);
                input.AddSegment(count + i, count + (i + 1) % npoints, 2);
            }

            count = input.Count;

            // Outer cirlce
            r       = radius;
            npoints = (int)(2 * Math.PI * r / h);
            dphi    = 2 * Math.PI / npoints;
            for (int i = 0; i < npoints; i++)
            {
                input.AddPoint(r * Math.Cos(i * dphi), r * Math.Sin(i * dphi), 3);
                input.AddSegment(count + i, count + (i + 1) % npoints, 3);
            }

            input.AddHole(0, 0);

            // Regions: |++++++|++++++|---|
            //          r             1   0

            input.AddRegion((r + 3.0) / 4.0, 0, 1);
            input.AddRegion((3 * r + 1.0) / 4.0, 0, 2);

            return(input);
        }
Beispiel #4
0
        static void SearchTree(InputGeometry inputGeometry, ref int pointIndex, PolyNode node)
        {
            foreach (PolyNode childNode in node.Childs)
            {
                int startIndex = pointIndex;

                foreach (Vector2 point in childNode.Contour)
                {
                    inputGeometry.AddPoint(point.X, point.Y);
                    if (pointIndex > startIndex)
                    {
                        inputGeometry.AddSegment(pointIndex - 1, pointIndex);
                    }
                    pointIndex++;
                }
                inputGeometry.AddSegment(pointIndex - 1, startIndex);

                if (childNode.IsHole)
                {
                    for (int i = 0, j = childNode.Contour.Count - 1, k = childNode.Contour.Count - 2; i < childNode.Contour.Count; k = j, j = i, i++)
                    {
                        Vector2 a1 = childNode.Contour[k];
                        Vector2 a2 = childNode.Contour[j];
                        Vector2 a3 = childNode.Contour[i];

                        if (Vector2.VectorProduct(a2 - a1, a3 - a1) < 0)
                        {
                            Vector2 c = (a1 + a3) / 2;
                            Vector2 d = a2 - c;
                            float   x = c.Length * 2;
                            Vector2 hole;
                            do
                            {
                                x   /= 2;
                                hole = c + (1 - x) * d;
                            } while (!IsInside(childNode, hole));
                            x   /= 512;
                            hole = c + (1 - x) * d;
                            inputGeometry.AddHole(hole.X, hole.Y);
                            break;
                        }
                    }
                }

                SearchTree(inputGeometry, ref pointIndex, childNode);
            }
        }
Beispiel #5
0
        public void Triangulate()
        {
            indices.Clear();

            if (texVertices.Count >= 3)
            {
                InputGeometry inputGeometry = new InputGeometry(texVertices.Count);

                for (int i = 0; i < texVertices.Count; ++i)
                {
                    Vector2 vertex = texVertices[i].vertex;
                    inputGeometry.AddPoint(vertex.x, vertex.y);
                }

                for (int i = 0; i < edges.Count; ++i)
                {
                    Edge edge = edges[i];
                    inputGeometry.AddSegment(texVertices.IndexOf(edge.vertex1),
                                             texVertices.IndexOf(edge.vertex2));
                }

                for (int i = 0; i < holes.Count; ++i)
                {
                    Vector2 hole = holes[i].vertex;
                    inputGeometry.AddHole(hole.x, hole.y);
                }

                TriangleNet.Mesh trangleMesh = new TriangleNet.Mesh();

                trangleMesh.Triangulate(inputGeometry);


                foreach (TriangleNet.Data.Triangle triangle in trangleMesh.Triangles)
                {
                    if (triangle.P0 >= 0 && triangle.P0 < texVertices.Count &&
                        triangle.P0 >= 0 && triangle.P1 < texVertices.Count &&
                        triangle.P0 >= 0 && triangle.P2 < texVertices.Count)
                    {
                        indices.Add(triangle.P0);
                        indices.Add(triangle.P2);
                        indices.Add(triangle.P1);
                    }
                }
            }

            isDirty = true;
        }
Beispiel #6
0
        private void ReadHoles(InputGeometry geometry, ArrayList holes)
        {
            int n = holes.Count;

            if (n % 2 != 0)
            {
                throw new Exception("JSON format error (holes).");
            }

            for (int i = 0; i < n; i += 2)
            {
                geometry.AddHole(
                    double.Parse(holes[i].ToString(), Util.Nfi),
                    double.Parse(holes[i + 1].ToString(), Util.Nfi)
                    );
            }
        }
        void SearchTree(InputGeometry inputGeometry, ref int pointIndex, PolyNode node)
        {
            foreach (PolyNode childNode in node.Childs)
            {
                int startIndex = pointIndex;

                foreach (ControlPoint point in childNode.Contour)
                {
                    inputGeometry.AddPoint(point.X, point.Y);
                    if (pointIndex > startIndex)
                    {
                        inputGeometry.AddSegment(pointIndex - 1, pointIndex);
                    }
                    pointIndex++;
                }
                inputGeometry.AddSegment(pointIndex - 1, startIndex);

                if (childNode.IsHole)
                {
                    for (int i = 0, j = childNode.Contour.Count - 1, k = childNode.Contour.Count - 2; i < childNode.Contour.Count; k = j, j = i, i++)
                    {
                        ControlPoint a1 = childNode.Contour[k];
                        ControlPoint a2 = childNode.Contour[j];
                        ControlPoint a3 = childNode.Contour[i];

                        if (ControlPoint.VectorProduct(a2 - a1, a3 - a1) < 0)
                        {
                            ControlPoint c = ((a1 + a3) / 2) - a2;
                            double       x = 2;
                            ControlPoint hole;
                            do
                            {
                                x   /= 2;
                                hole = a2 + (c * x);
                            } while (!IsInside(childNode, hole));

                            inputGeometry.AddHole(hole.X, hole.Y);
                            break;
                        }
                    }
                }

                SearchTree(inputGeometry, ref pointIndex, childNode);
            }
        }
        public static void Triangulate(List <Vector2> vertices, List <IndexedEdge> edges, List <Hole> holes,
                                       ref List <int> indices)
        {
            indices.Clear();

            if (vertices.Count >= 3)
            {
                InputGeometry inputGeometry = new InputGeometry(vertices.Count);

                for (int i = 0; i < vertices.Count; ++i)
                {
                    Vector2 position = vertices[i];
                    inputGeometry.AddPoint(position.x, position.y);
                }

                for (int i = 0; i < edges.Count; ++i)
                {
                    IndexedEdge edge = edges[i];
                    inputGeometry.AddSegment(edge.index1, edge.index2);
                }

                for (int i = 0; i < holes.Count; ++i)
                {
                    Vector2 hole = holes[i].vertex;
                    inputGeometry.AddHole(hole.x, hole.y);
                }

                TriangleNet.Mesh triangleMesh = new TriangleNet.Mesh();

                triangleMesh.Triangulate(inputGeometry);

                foreach (TriangleNet.Data.Triangle triangle in triangleMesh.Triangles)
                {
                    if (triangle.P0 >= 0 && triangle.P0 < vertices.Count &&
                        triangle.P0 >= 0 && triangle.P1 < vertices.Count &&
                        triangle.P0 >= 0 && triangle.P2 < vertices.Count)
                    {
                        indices.Add(triangle.P0);
                        indices.Add(triangle.P2);
                        indices.Add(triangle.P1);
                    }
                }
            }
        }
Beispiel #9
0
        public override InputGeometry Generate(double param0, double param1, double param2)
        {
            int n = GetParamValueInt(0, param0);
            int m = n / 2;

            InputGeometry input = new InputGeometry(n + 1);

            double ro, r = 10;
            double step = 2 * Math.PI / m;

            // Inner ring
            for (int i = 0; i < m; i++)
            {
                input.AddPoint(r * Math.Cos(i * step), r * Math.Sin(i * step));
                input.AddSegment(i, (i + 1) % m);
            }

            r = 1.5 * r;


            step = 2 * Math.PI / n;
            double offset = step / 2;

            // Outer ring
            for (int i = 0; i < n; i++)
            {
                ro = r;

                if (i % 2 == 0)
                {
                    ro = r + r * Util.Random.NextDouble() * (param1 / 100);
                }

                input.AddPoint(ro * Math.Cos(i * step + offset), ro * Math.Sin(i * step + offset));
                input.AddSegment(m + i, m + ((i + 1) % n));
            }

            input.AddHole(0, 0);

            return(input);
        }
        private InputGeometry Rebuild()
        {
            InputGeometry inputGeometry = new InputGeometry(this.mesh.vertices.Count);

            foreach (Vertex value in this.mesh.vertices.Values)
            {
                inputGeometry.AddPoint(value.x, value.y, value.mark);
            }
            foreach (Segment segment in this.mesh.subsegs.Values)
            {
                inputGeometry.AddSegment(segment.P0, segment.P1, segment.Boundary);
            }
            foreach (Point hole in this.mesh.holes)
            {
                inputGeometry.AddHole(hole.x, hole.y);
            }
            foreach (RegionPointer region in this.mesh.regions)
            {
                inputGeometry.AddRegion(region.point.x, region.point.y, region.id);
            }
            return(inputGeometry);
        }
Beispiel #11
0
        public static void Tessellate(List <Vector2> vertices, List <IndexedEdge> indexedEdges, List <Hole> holes, List <int> indices, float tessellationAmount)
        {
            if (tessellationAmount <= 0f)
            {
                return;
            }

            indices.Clear();

            if (vertices.Count >= 3)
            {
                InputGeometry inputGeometry = new InputGeometry(vertices.Count);

                for (int i = 0; i < vertices.Count; ++i)
                {
                    Vector2 vertex = vertices[i];
                    inputGeometry.AddPoint(vertex.x, vertex.y);
                }

                for (int i = 0; i < indexedEdges.Count; ++i)
                {
                    IndexedEdge edge = indexedEdges[i];
                    inputGeometry.AddSegment(edge.index1, edge.index2);
                }

                for (int i = 0; i < holes.Count; ++i)
                {
                    Vector2 hole = holes[i].vertex;
                    inputGeometry.AddHole(hole.x, hole.y);
                }

                TriangleNet.Mesh            triangleMesh = new TriangleNet.Mesh();
                TriangleNet.Tools.Statistic statistic    = new TriangleNet.Tools.Statistic();

                triangleMesh.Triangulate(inputGeometry);

                triangleMesh.Behavior.MinAngle      = 20.0;
                triangleMesh.Behavior.SteinerPoints = -1;
                triangleMesh.Refine(true);

                statistic.Update(triangleMesh, 1);

                triangleMesh.Refine(statistic.LargestArea / tessellationAmount);
                triangleMesh.Renumber();

                vertices.Clear();
                indexedEdges.Clear();

                foreach (TriangleNet.Data.Vertex vertex in triangleMesh.Vertices)
                {
                    vertices.Add(new Vector2((float)vertex.X, (float)vertex.Y));
                }

                foreach (TriangleNet.Data.Segment segment in triangleMesh.Segments)
                {
                    indexedEdges.Add(new IndexedEdge(segment.P0, segment.P1));
                }

                foreach (TriangleNet.Data.Triangle triangle in triangleMesh.Triangles)
                {
                    if (triangle.P0 >= 0 && triangle.P0 < vertices.Count &&
                        triangle.P0 >= 0 && triangle.P1 < vertices.Count &&
                        triangle.P0 >= 0 && triangle.P2 < vertices.Count)
                    {
                        indices.Add(triangle.P0);
                        indices.Add(triangle.P2);
                        indices.Add(triangle.P1);
                    }
                }
            }
        }
Beispiel #12
0
        public override InputGeometry Generate(double param0, double param1, double param2)
        {
            int numPoints = GetParamValueInt(1, param1);

            InputGeometry input = new InputGeometry(numPoints + 4);

            double x, y, step = 2 * Math.PI / numPoints;

            double r = GetParamValueInt(2, param2);

            // Generate circle
            for (int i = 0; i < numPoints; i++)
            {
                x = r * Math.Cos(i * step);
                y = r * Math.Sin(i * step);

                input.AddPoint(x, y, 2);
                input.AddSegment(i, (i + 1) % numPoints, 2);
            }

            numPoints = input.Count;

            int numPointsB = GetParamValueInt(0, param0);

            // Box sides are 100 units long
            step = 100.0 / numPointsB;

            // Left box boundary points
            for (int i = 0; i < numPointsB; i++)
            {
                input.AddPoint(-50, -50 + i * step, 1);
            }

            // Top box boundary points
            for (int i = 0; i < numPointsB; i++)
            {
                input.AddPoint(-50 + i * step, 50, 1);
            }

            // Right box boundary points
            for (int i = 0; i < numPointsB; i++)
            {
                input.AddPoint(50, 50 - i * step, 1);
            }

            // Bottom box boundary points
            for (int i = 0; i < numPointsB; i++)
            {
                input.AddPoint(50 - i * step, -50, 1);
            }

            // Add box segments
            for (int i = numPoints; i < input.Count - 1; i++)
            {
                input.AddSegment(i, i + 1, 1);
            }

            // Add last segments which closes the box
            input.AddSegment(input.Count - 1, numPoints, 1);

            // Add hole
            input.AddHole(0, 0);

            return(input);
        }
Beispiel #13
0
    // returns list of list of vertices, each one being a triangle
    public static List <List <Vector2> > MakeTriangles(List <List <Vector2> > loops)
    {
        //Debug.LogFormat("loop1 = {0}, loopL = {1}", loops[0].Count, loops[loops.Count - 1].Count);

        // first off, the loops should be sorted by area, so we can just go from the start expecting the first polygon to be the largest one and last the smallest.
        List <List <Vector2> > polygons = new List <List <Vector2> >();
        Dictionary <List <Vector2>, List <List <Vector2> > > holes = new Dictionary <List <Vector2>, List <List <Vector2> > >();

        //for (int i = loops.Count - 1; i >= 0; i--)
        for (int i = 0; i < loops.Count; i++)
        {
            List <Vector2> loop = loops[i];
            // first we check if this loop intersects any polygon. if it does, add hole to dictionary. if it doesn't, just add polygon.
            bool anyHole = false;

            for (int j = 0; j < polygons.Count; j++)
            {
                if (CheckIntersection(polygons[j], loop))
                {
                    //Debug.LogFormat("adding hole (len = {0}) to polygon (len = {1})", loop.Count, polygons[j].Count);
                    //Debug.LogFormat("polygon {0} intersects loop {1}", j, i);
                    if (!holes.ContainsKey(polygons[j]))
                    {
                        holes[polygons[j]] = new List <List <Vector2> >();
                    }
                    holes[polygons[j]].Add(((IEnumerable <Vector2>)loop).Reverse().ToList());
                    anyHole = true;
                    break;
                }
            }

            if (!anyHole)
            {
                //Debug.LogFormat("adding polygon (len = {0})", loop.Count);
                polygons.Add(loop);
            }
            //break;
        }

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

        for (int i = 0; i < polygons.Count; i++)
        {
            List <Vector2> polygon = polygons[i];

            if (polygon.Count < 3)
            {
                continue;
            }
            //Debug.LogFormat("polygon points = {0}", polygon.Count);

            InputGeometry input = new InputGeometry();
            for (int j = 0; j < polygon.Count; j++)
            {
                input.AddPoint(polygon[j].x, polygon[j].y);
            }

            // add segments
            for (int j = 0; j < polygon.Count; j++)
            {
                input.AddSegment(j, (j + 1) % polygon.Count, 0);
            }

            if (holes.ContainsKey(polygon))
            {
                for (int j = 0; j < holes[polygon].Count; j++)
                {
                    List <Vector2> hole = holes[polygon][j];

                    // add holes segments
                    int   basePt = input.points.Count;
                    float cx     = 0;
                    float cy     = 0;
                    for (int k = 0; k < hole.Count; k++)
                    {
                        input.AddPoint(hole[k].x, hole[k].y);
                        cx += hole[k].x; cy += hole[k].y;
                    }
                    cx /= hole.Count;
                    cy /= hole.Count;
                    for (int k = 0; k < hole.Count; k++)
                    {
                        input.AddSegment(basePt + k, basePt + ((k + 1) % hole.Count), j + 1);
                    }
                    input.AddHole(cx, cy);
                }
            }

            if (input.points.Count < 3)
            {
                continue;
            }

            //
            TriangleNet.Mesh mesh = new TriangleNet.Mesh();
            mesh.Triangulate(input);

            // put triangles to output
            for (int j = 0; j < mesh.Triangles.Count; j++)
            {
                Triangle       mtri     = mesh.Triangles.ElementAt(j);
                List <Vector2> triangle = new List <Vector2>();
                for (int k = 0; k < 3; k++)
                {
                    triangle.Add(new Vector2((float)mtri.vertices[k].x, (float)mtri.vertices[k].y));
                }
                output.Add(triangle);
            }
        }

        return(output);
    }
Beispiel #14
0
        /// <summary>
        /// Get a list of triangles which will fill the area described by the slice
        /// </summary>
        public IEnumerable <Triangle> Triangles()
        {
            TriangleNet.Behavior behavior = new TriangleNet.Behavior();
            behavior.ConformingDelaunay = true;

            foreach (var poly in IndividualPolygons())
            {
                PolyNode      node     = polyTree.GetFirst();
                InputGeometry geometry = new InputGeometry();
                while (node != null)
                {
                    var offset = geometry.Points.Count();
                    var index  = 0;
                    foreach (IntPoint point in node.Contour)
                    {
                        geometry.AddPoint(point.X, point.Y);
                        if (index > 0)
                        {
                            geometry.AddSegment(index - 1 + offset, index + offset);
                        }
                        index++;
                    }
                    geometry.AddSegment(index - 1 + offset, offset);

                    if (node.IsHole)
                    {
                        // To describe a hole, AddHole must be called with a location inside the hole.
                        IntPoint last         = new IntPoint(0, 0);
                        bool     lastKnown    = false;
                        double   longest      = 0;
                        IntPoint longestAlong = new IntPoint(0, 0);
                        IntPoint from         = new IntPoint(0, 0);
                        foreach (IntPoint point in node.Contour)
                        {
                            if (lastKnown)
                            {
                                IntPoint along  = new IntPoint(point.X - last.X, point.Y - last.Y);
                                double   length = Math.Sqrt(along.X * along.X + along.Y * along.Y);
                                if (length > longest)
                                {
                                    longest      = length;
                                    longestAlong = along;
                                    from         = last;
                                }
                            }
                            last      = point;
                            lastKnown = true;
                        }
                        if (longest > 0)
                        {
                            double perpendicularX = ((double)longestAlong.Y * (double)scale * 0.001d) / longest;
                            double perpendicularY = -((double)longestAlong.X * (double)scale * 0.001d) / longest;
                            geometry.AddHole(perpendicularX + from.X + longestAlong.X / 2.0d,
                                             perpendicularY + from.Y + longestAlong.Y / 2.0d);
                        }
                        else
                        {
                        }
                    }
                    node = node.GetNext();
                }

                if (geometry.Points.Count() > 0)
                {
                    var mesh = new TriangleNet.Mesh(behavior);
                    mesh.Triangulate(geometry);
                    mesh.Renumber();
                    foreach (Triangle t in this.GetMeshTriangles(mesh))
                    {
                        yield return(t);
                    }
                }
            }
        }