Example #1
0
        // find the type of a specific vertex in a polygon, either Concave or Convex.
        public PolygonType VertexType(int vertexNo)
        {
            PolygonData triangle;

            if (vertexNo == 0)
            {
                triangle = new PolygonData(new List <PointF> {
                    PtList[PtList.Count - 2], PtList[0], PtList[1]
                });                                                                                               // the polygon is always closed so the last point is the same as the first
            }
            else
            {
                triangle = new PolygonData(new List <PointF> {
                    PtList[vertexNo - 1], PtList[vertexNo], PtList[vertexNo + 1]
                });
            }

            if (Math.Sign(triangle.Area) == Math.Sign(this.Area))
            {
                return(PolygonType.Convex);
            }
            else
            {
                return(PolygonType.Concave);
            }
        }
        // From Wikipedia:
        // One way to triangulate a simple polygon is by using the assertion that any simple polygon
        // without holes has at least two so called 'ears'. An ear is a triangle with two sides on the edge
        // of the polygon and the other one completely inside it. The algorithm then consists of finding
        // such an ear, removing it from the polygon (which results in a new polygon that still meets
        // the conditions) and repeating until there is only one triangle left.

        // the algorithm here aims for simplicity over performance. there are other, more performant
        // algorithms that are much more complex.

        // convert a triangle to a list of triangles. each triangle is represented by a PointF array of length 3.
        public static List<PointF[]> Triangulate(PolygonData poly) {
            List<PointF[]> triangles = new List<PointF[]>();  // accumulate the triangles here
            // keep clipping ears off of poly until only one triangle remains
            while (poly.PtListOpen.Count > 3)  // if only 3 points are left, we have the final triangle
            {
                int midvertex = FindEar(poly);  // find the middle vertex of the next "ear"
                triangles.Add(new PointF[] { poly.PtList[midvertex - 1], poly.PtList[midvertex], poly.PtList[midvertex + 1] });
                // create a new polygon that clips off the ear; i.e., all vertices but midvertex
                List<PointF> newPts = new List<PointF>(poly.PtList);
                newPts.RemoveAt(midvertex);  // clip off the ear
                poly = new PolygonData(newPts);  // poly now has one less point
            }
            // only a single triangle remains, so add it to the triangle list
            triangles.Add(poly.PtListOpen.ToArray());
            return triangles;
        }
 // find an ear (always a triangle) of the polygon and return the index of the middle (second) vertex in the ear
 public static int FindEar(PolygonData poly) {
     for (int i = 0; i < poly.PtList.Count - 2; i++) {
         if (poly.VertexType(i + 1) == PolygonType.Convex) {
             // get the three points of the triangle we are about to test
             PointF a = poly.PtList[i];
             PointF b = poly.PtList[i + 1];
             PointF c = poly.PtList[i + 2];
             bool foundAPointInTheTriangle = false;  // see if any of the other points in the polygon are in this triangle
             for (int j = 0; j < poly.PtListOpen.Count; j++)  // don't check the last point, which is a duplicate of the first
             {
                 if (j != i && j != i + 1 && j != i + 2 && PointInTriangle(poly.PtList[j], a, b, c)) foundAPointInTheTriangle = true;
             }
             if (!foundAPointInTheTriangle)  // the middle point of this triangle is convex and none of the other points in the polygon are in this triangle, so it is an ear
                 return i + 1;  // EXITING HERE!
         }
     }
     throw new ApplicationException("Improperly formed polygon");
 }
Example #4
0
        /// <summary>
        /// This method returns a 3D representation of this area
        /// </summary>
        /// <param name="nodesDict">List of all the nodes on the map</param>
        /// <param name="map">bounds of the map</param>
        /// <param name="brush">Color of this area</param>
        /// <returns>ModelUIElement3D of this area</returns>
        public virtual ModelUIElement3D get3DSurface(Dictionary<long, OsmSharp.Osm.Node> nodesDict, Map map, System.Windows.Media.SolidColorBrush brush) {
            List<PointF> ptlist = getScaledPointsSurface(nodesDict, map);

            // Divide the polygons in triangles, this is code (and these two classes) are from: https://polygontriangulation.codeplex.com/
            PolygonData poly = new PolygonData(ptlist);
            List<PointF[]> triangles = Triangulation2D.Triangulate(poly);

            // Surrounding tags of the mesh
            ModelUIElement3D model = new ModelUIElement3D();
            GeometryModel3D geometryModel = new GeometryModel3D();

            // Mesh and his his properties
            MeshGeometry3D mesh = new MeshGeometry3D();
            DiffuseMaterial material = new DiffuseMaterial((System.Windows.Media.Brush)brush);
            Point3DCollection positions = new Point3DCollection();
            Int32Collection indices = new Int32Collection();

            // Add points and indices to their collection
            foreach (PointF[] points in triangles) {
                foreach (PointF point in points) {
                    positions.Add(new Point3D(point.X, point.Y, height));
                }

                int count = positions.Count;
                indices.Add(count - 3);
                indices.Add(count - 2);
                indices.Add(count - 1);
            }

            // Add these collections to the mesh
            mesh.Positions = positions;
            mesh.TriangleIndices = indices;

            // Set the color of front and back of the triangle
            geometryModel.Material = material;
            geometryModel.BackMaterial = material;

            // Add the mesh to the model
            geometryModel.Geometry = mesh;
            model.Model = geometryModel;

            return model;
        }
        // find the type of a specific vertex in a polygon, either Concave or Convex.
        public PolygonType VertexType(int vertexNo) {
            PolygonData triangle;
            if (vertexNo == 0) {
                triangle = new PolygonData(new List<PointF> { PtList[PtList.Count - 2], PtList[0], PtList[1] });  // the polygon is always closed so the last point is the same as the first
            } else {
                triangle = new PolygonData(new List<PointF> { PtList[vertexNo - 1], PtList[vertexNo], PtList[vertexNo + 1] });
            }

            if (Math.Sign(triangle.Area) == Math.Sign(this.Area))
                return PolygonType.Convex;
            else
                return PolygonType.Concave;
        }