예제 #1
0
        /// <summary>
        /// Generate the 3D model and assign it to the Geometry property
        /// </summary>
        /// <param name="points">a list of points representing a polygon</param>
        /// <param name="triangles">a list of triangles representing the polygon shape</param>
        /// <param name="scale">the scale of our object</param>
        /// <param name="height">the height of the model</param>
        private void AssembleModel(List <PointF> points, List <Triangle> triangles, float scale, float height)
        {
            var mesh = new MeshGeometry3D();
            Point3DCollection pointsCollection = new Point3DCollection();
            Int32Collection   triangleIndices  = new Int32Collection();

            for (int i = 0; i < points.Count; i++)
            {
                // Add the points
                pointsCollection.Add(new Point3D((points[i].X / Scale /* + WorldPosition.X*/) * scale, (points[i].Y / Scale /* + WorldPosition.Y*/) * scale, 0));
                pointsCollection.Add(new Point3D((points[i].X / Scale /* + WorldPosition.X*/) * scale, (points[i].Y / Scale /* + WorldPosition.Y*/) * scale, height));


                var previousBottomIndex = CustomTriangulator.CirculateIndex(i - 1, points.Count) * 2;
                var previousTopIndex    = previousBottomIndex + 1;
                var currentBottomIndex  = i * 2;
                var currentTopIndex     = i * 2 + 1;

                //Add the triangles
                triangleIndices.Add(currentTopIndex);
                triangleIndices.Add(currentBottomIndex);
                triangleIndices.Add(previousBottomIndex);

                triangleIndices.Add(previousTopIndex);
                triangleIndices.Add(currentTopIndex);
                triangleIndices.Add(previousBottomIndex);
            }
            for (int i = 0; i < triangles.Count; i++)
            {
                var p1Index = points.IndexOf(triangles[i].Point1) * 2;
                var p2Index = points.IndexOf(triangles[i].MiddlePoint) * 2;
                var p3Index = points.IndexOf(triangles[i].Point2) * 2;

                // Bottom Face triangle
                triangleIndices.Add(p1Index);
                triangleIndices.Add(p2Index);
                triangleIndices.Add(p3Index);

                // Top Face triangle
                triangleIndices.Add(p3Index + 1);
                triangleIndices.Add(p2Index + 1);
                triangleIndices.Add(p1Index + 1);
            }

            mesh.Positions       = pointsCollection;
            mesh.TriangleIndices = triangleIndices;

            // Add children on the main thread, otherwise wpf throws an error
            dispatcher.Invoke(() =>
            {
                Area.Children.Add(new GeometryModel3D
                {
                    Geometry = mesh
                });
            });
        }
예제 #2
0
        /// <summary>
        /// Interpret the MultiPolygon object and start processing it to create a 3D model
        /// </summary>
        /// <param name="multiPolygon">the multipolygon to process</param>
        /// <param name="scale">the scale of the 3d object</param>
        /// <param name="height">the height of the model</param>
        private void GenerateModelFromMultiPolygon(MultiPolygon multiPolygon, float scale, float height)
        {
            int side = 400;

            float maxX = 0;
            float maxY = 0;
            float minX = float.MaxValue;
            float minY = float.MaxValue;

            // Get the extreme points, these will be used for normalization
            foreach (Polygon p in multiPolygon.Coordinates)
            {
                foreach (LineString lstring in p.Coordinates)
                {
                    var maxX2 = lstring.Coordinates.Select(position => GetPointFromCoordinates(side, side, position).X).Max();
                    var maxY2 = lstring.Coordinates.Select(position => GetPointFromCoordinates(side, side, position).Y).Max();
                    var minX2 = lstring.Coordinates.Select(position => GetPointFromCoordinates(side, side, position).X).Min();
                    var minY2 = lstring.Coordinates.Select(position => GetPointFromCoordinates(side, side, position).Y).Min();
                    if (maxX2 > maxX)
                    {
                        maxX = maxX2;
                    }
                    if (maxY2 > maxY)
                    {
                        maxY = maxY2;
                    }
                    if (minX2 < minX)
                    {
                        minX = minX2;
                    }
                    if (minY2 < minY)
                    {
                        minY = minY2;
                    }
                }
            }

            WorldPosition = new PointF(minX, minY);
            var o = multiPolygon.Coordinates.OrderBy(coords => coords.Coordinates.Select(coordinate => coordinate.Coordinates.Count).Max());

            for (int i = 0; i < o.Count(); i++)
            {
                System.Diagnostics.Debug.WriteLine("Holecount: " + (o.ElementAt(i).Coordinates.Count - 1));

                List <List <PointF> > normalizedPolygon = new List <List <PointF> >();

                foreach (LineString lstring in o.ElementAt(i).Coordinates)
                {
                    List <PointF> points = new List <PointF>();
                    // Loop over the points, rescale them and add them to the list
                    foreach (IPosition point in lstring.Coordinates)
                    {
                        var xy = GetPointFromCoordinates(side, side, point);

                        var normalizedPoint = NormalizePoint(xy, minX, minY, maxX, maxY, side);

                        points.Add(normalizedPoint);
                    }

                    // Use Peucker to eliminate points
                    List <PointF> scarcePoints = EliminatePoints(points);
                    // The algorithm requires the polygon to be in the first index and all holes to follow, we assume that the longest sequence of points is the polygon and all others are holes
                    if (lstring.Coordinates.Count == o.ElementAt(i).Coordinates.Select(coordinate => coordinate.Coordinates.Count).Max())
                    {
                        normalizedPolygon.Insert(0, scarcePoints);
                    }
                    else
                    {
                        normalizedPolygon.Add(scarcePoints);
                    }
                }
                // Create a single polygon of the polygon and all it's holes
                List <PointF> compositePolygon = CustomHoleTriangulator.ConstructPolygon(normalizedPolygon);
                // Triangulate the polygon
                List <Triangle> triangles = CustomTriangulator.Triangulate(compositePolygon);
                // Generate the model
                AssembleModel(compositePolygon, triangles, scale, height);
            }
        }