예제 #1
0
        private TriangulationList <Vector3> CreateScaleBar(float modelSize4326, float modelSizeProjected, float radius = 10f)
        {
            int          nSteps    = 4;
            ScaleBarInfo scaleInfo = GetScaleBarWidth(modelSize4326, modelSizeProjected, scaleBarSizeRelativeToModel: 0.5f, nSteps);

            Vector3 currentPosition = Vector3.Zero;
            TriangulationList <Vector3> triangulation = new TriangulationList <Vector3>();

            for (int i = 0; i < nSteps; i++)
            {
                currentPosition.Z = scaleInfo.StepSizeProjected * i;

                triangulation += _meshService.CreateCylinder(currentPosition, radius, scaleInfo.StepSizeProjected
                                                             , color: i % 2 == 0 ? VectorsExtensions.CreateColor(0, 0, 0) : VectorsExtensions.CreateColor(255, 255, 255));
            }

            // scale units (m or km ?)
            string scaleLabel = (scaleInfo.TotalSize / 1000f > 1) ? $"{scaleInfo.TotalSize / 1000:F0} km" : $"{scaleInfo.TotalSize} m";

            triangulation += CreateText(scaleLabel, color: VectorsExtensions.CreateColor(255, 255, 255))
                             .Scale(radius / 5)
                             .RotateY((float)Math.PI / 2)
                             .RotateZ((float)Math.PI / 2)
                             .Translate(new Vector3(radius * 5, -radius, scaleInfo.TotalSizeProjected / 2));

            return(triangulation);
        }
예제 #2
0
 public static TriangulationList <Vector3> Transform(this TriangulationList <Vector3> triangulation, Matrix4x4 matrix4x4)
 {
     for (int i = 0; i < triangulation.NumPositions; i++)
     {
         triangulation.Positions[i] = Vector3.Transform(triangulation.Positions[i], matrix4x4);
     }
     return(triangulation);
 }
예제 #3
0
 public static TriangulationList <Vector3> ToGlTFSpace(this TriangulationList <Vector3> triangulation)
 {
     for (int i = 0; i < triangulation.NumPositions; i++)
     {
         triangulation.Positions[i] = triangulation.Positions[i].ToGlTFSpace();
     }
     return(triangulation);
 }
예제 #4
0
        public TriangulationList <Vector3> CreateText(string text, Vector4 color)
        {
            List <Polygon <Vector3> >   letterPolygons = GetTextPolygons(text);
            TriangulationList <Vector3> triangulation  = _meshService.Extrude(letterPolygons);

            triangulation.Colors = triangulation.Positions.Select(p => color).ToList();
            triangulation        = triangulation.CenterOnOrigin();
            return(triangulation);
        }
예제 #5
0
 public static TriangulationList <Vector3> ZScale(this TriangulationList <Vector3> triangulation, float zScale)
 {
     for (int i = 0; i < triangulation.NumPositions; i++)
     {
         Vector3 pos = triangulation.Positions[i];
         pos.Z *= zScale;
         triangulation.Positions[i] = pos;
     }
     return(triangulation);
 }
예제 #6
0
        public static TriangulationList <Vector3> CenterOnOrigin(this TriangulationList <Vector3> triangulation, Vector3 origin)
        {
            Matrix4x4 translate = Matrix4x4.CreateTranslation((float)-origin.X, (float)-origin.Y, -origin.Z);

            for (int i = 0; i < triangulation.NumPositions; i++)
            {
                triangulation.Positions[i] = Vector3.Transform(triangulation.Positions[i], translate);
            }

            return(triangulation);
        }
예제 #7
0
        public TriangulationList <Vector3> CreateModelAdornments(DEMDataSet dataset, ImageryProvider imageryProvider, BoundingBox bboxDemSpace, BoundingBox bboxModelSpace)
        {
            var width = (float)new GeoPoint(latitude: bboxDemSpace.Center[1],
                                            longitude: bboxDemSpace.Center[0] - bboxDemSpace.Width / 2f)
                        .DistanceTo(
                new GeoPoint(latitude: bboxDemSpace.Center[1],
                             longitude: bboxDemSpace.Center[0] + bboxDemSpace.Width / 2f)
                );

            // bbox size
            float projHeight      = (float)bboxModelSpace.Height;
            float arrowSizeFactor = projHeight / 3f;
            float zCenter         = (float)bboxModelSpace.Center[2];
            float projWidth       = (float)bboxModelSpace.Width;
            //
            float PI = (float)Math.PI;

            // Arrow
            TriangulationList <Vector3> adornments = _meshService.CreateArrow().ToGlTFSpace()
                                                     .Scale(arrowSizeFactor)
                                                     .Translate(new Vector3(-projWidth * 0.55f, 0, zCenter));

            // North text 'N'
            adornments += this.CreateText("N", VectorsExtensions.CreateColor(255, 255, 255)).ToGlTFSpace()
                          .Scale(projHeight / 200f / 5f)
                          .RotateX(-PI / 2)
                          .Translate(new Vector3(-projWidth * 0.55f, arrowSizeFactor * 1.1f, zCenter));

            // Scale bar
            var scaleBar     = this.CreateScaleBar(width, projWidth, radius: projHeight / 200f).ToGlTFSpace();
            var scaleBarSize = scaleBar.GetBoundingBox().Height;

            adornments += scaleBar
                          .RotateZ(PI / 2f)
                          .Translate(new Vector3(projWidth / 2, -projHeight / 2 - projHeight * 0.05f, zCenter));

            var text = $"{dataset.Attribution.Subject}: {dataset.Attribution.Text}";

            if (imageryProvider != null)
            {
                text = string.Concat(text, $"{Environment.NewLine}{imageryProvider.Attribution.Subject}: {imageryProvider.Attribution.Text}");
            }
            var text3D    = this.CreateText(text, VectorsExtensions.CreateColor(255, 255, 255)).ToGlTFSpace();
            var textWidth = (float)text3D.GetBoundingBox().Width;
            var scale     = (float)(((projWidth - scaleBarSize) * 0.9f) / textWidth);

            text3D = text3D.Scale((float)scale)
                     .RotateX(-PI / 2)
                     .Translate(new Vector3((-projWidth + textWidth * scale) / 2f, -projHeight * 0.55f, zCenter));
            adornments += text3D;

            return(adornments);
        }
예제 #8
0
        public static TriangulationList <Vector3> CenterOnOrigin(this TriangulationList <Vector3> triangulation, BoundingBox bbox, bool centerOnZ = false)
        {
            //Logger.Info("CenterOnOrigin...");
            double xOriginOffset = bbox.xMax - (bbox.xMax - bbox.xMin) / 2d;
            double yOriginOffset = bbox.yMax - (bbox.yMax - bbox.yMin) / 2d;

            Matrix4x4 translate = Matrix4x4.CreateTranslation((float)-xOriginOffset, (float)-yOriginOffset, centerOnZ ? (float)-bbox.zMin : 0);

            for (int i = 0; i < triangulation.NumPositions; i++)
            {
                triangulation.Positions[i] = Vector3.Transform(triangulation.Positions[i], translate);
            }

            return(triangulation);
        }
예제 #9
0
        public static BoundingBox GetBoundingBox(this TriangulationList <Vector3> triangulation)
        {
            var bbox = new BoundingBox()
            {
                zMin = double.MaxValue, zMax = double.MinValue
            };

            for (int i = 0; i < triangulation.NumPositions; i++)
            {
                bbox.xMin = Math.Min(bbox.xMin, triangulation.Positions[i].X);
                bbox.xMax = Math.Max(bbox.xMax, triangulation.Positions[i].X);
                bbox.yMin = Math.Min(bbox.yMin, triangulation.Positions[i].Y);
                bbox.yMax = Math.Max(bbox.yMax, triangulation.Positions[i].Y);
                bbox.zMin = Math.Min(bbox.zMin, triangulation.Positions[i].Z);
                bbox.zMax = Math.Max(bbox.zMax, triangulation.Positions[i].Z);
            }

            return(bbox);
        }
예제 #10
0
        public static TriangulationList <Vector3> ReprojectTo(this TriangulationList <Vector3> triangulation, int sourceEpsgCode, int destinationEpsgCode)
        {
            if (sourceEpsgCode == destinationEpsgCode)
            {
                return(triangulation);
            }


            // Defines the starting coordiante system
            ProjectionInfo pSource = ProjectionInfo.FromEpsgCode(sourceEpsgCode);
            // Defines the starting coordiante system
            ProjectionInfo pTarget = ProjectionInfo.FromEpsgCode(destinationEpsgCode);


            double[] inputPoints = triangulation.Positions.SelectMany(pt => new double[] { pt.X, pt.Y }).ToArray();
            Reproject.ReprojectPoints(inputPoints, null, pSource, pTarget, 0, triangulation.NumPositions);

            for (int i = 0; i < triangulation.NumPositions; i++)
            {
                triangulation.Positions[i] = new Vector3((float)inputPoints[2 * i], (float)inputPoints[2 * i + 1], triangulation.Positions[i].Z);
            }
            return(triangulation);
        }
예제 #11
0
 public static TriangulationList <Vector3> Scale(this TriangulationList <Vector3> triangulation, Vector3 scales)
 {
     return(triangulation.Transform(Matrix4x4.CreateScale(scales)));
 }
예제 #12
0
 public static TriangulationList <Vector3> Scale(this TriangulationList <Vector3> triangulation, float factor)
 {
     return(triangulation.Transform(Matrix4x4.CreateScale(factor)));
 }
예제 #13
0
        public static TriangulationList <Vector3> Translate(this TriangulationList <Vector3> triangulation, Vector3 vector)
        {
            Matrix4x4 translate = Matrix4x4.CreateTranslation(vector);

            return(Transform(triangulation, translate));
        }
예제 #14
0
 public static TriangulationList <Vector3> RotateZ(this TriangulationList <Vector3> triangulation, float radians) => Transform(triangulation, Matrix4x4.CreateRotationZ(radians));
예제 #15
0
        public List <Polygon <Vector3> > GetTextPolygons(string text)
        {
            Dictionary <int, Polygon <Vector3> > letterPolygons = new Dictionary <int, Polygon <Vector3> >();

            using (Bitmap bmp = new Bitmap(400, 400))
                using (GraphicsPath gp = new GraphicsPath())
                    using (Graphics g = Graphics.FromImage(bmp))
                        using (Font f = new Font("Calibri", 40f))
                        {
                            //g.ScaleTransform(4, 4);
                            gp.AddString(text, f.FontFamily, 0, 40f, new Point(0, 0), StringFormat.GenericDefault);
                            g.DrawPath(Pens.Gray, gp);
                            gp.Flatten(new Matrix(), 0.1f); // <<== *
                            //g.DrawPath(Pens.DarkSlateBlue, gp);
                            //gp.SetMarkers();

                            using (GraphicsPathIterator gpi = new GraphicsPathIterator(gp))
                            {
                                gpi.Rewind();

                                var triangulation = new TriangulationList <Vector3>();
                                using (GraphicsPath gsubPath = new GraphicsPath())
                                {
                                    // Read all subpaths and their properties
                                    for (int i = 0; i < gpi.SubpathCount; i++)
                                    {
                                        gpi.NextSubpath(gsubPath, out bool bClosedCurve);
                                        if (!bClosedCurve)
                                        {
                                            _logger.LogWarning("Unclosed text shape. Skipping.");
                                            continue;
                                        }
                                        //Debug.Assert(bClosedCurve, "Unclosed character. That's not possible");

                                        var currentRing = gsubPath.PathPoints.Select(p => new Vector3(p.X, p.Y, 0)).ToList();

                                        List <int> childs  = GetIncludedPolygons(currentRing, letterPolygons);
                                        List <int> parents = GetContainerPolygons(currentRing, letterPolygons);
                                        // contains other polygon ?
                                        if (childs.Any())
                                        {
                                            Polygon <Vector3> newPoly = new Polygon <Vector3>(currentRing);
                                            foreach (var key in childs)
                                            {
                                                var child = letterPolygons[key];
                                                letterPolygons.Remove(key);
                                                newPoly.InteriorRings.Add(child.ExteriorRing);
                                            }
                                            letterPolygons.Add(i, newPoly);
                                        }
                                        else if (parents.Any())
                                        {
                                            Debug.Assert(parents.Count == 1);
                                            letterPolygons[parents.First()].InteriorRings.Add(currentRing);
                                        }
                                        else
                                        {
                                            letterPolygons.Add(i, new Polygon <Vector3>(currentRing));
                                        }

                                        // triangulation += _meshService.Tesselate(currentLetterPoints, currentLetterPointsInt);

                                        gsubPath.Reset();
                                    }
                                }
                            }
                        }

            return(letterPolygons.Values.ToList());
        }
예제 #16
0
        public TriangulationList <Vector3> GenerateTriangleMesh_Line(IEnumerable <GeoPoint> points, float width)
        {
            try
            {
                if (points == null)
                {
                    _logger?.LogWarning("Points are empty.");
                }
                else
                {
                    if (width <= 0)
                    {
                        throw new Exception("Line width of 0 is not supported. Please provide a with > 0.");
                    }
                    else
                    {
                        TriangulationList <Vector3> triangulation = new TriangulationList <Vector3>();

                        // https://gist.github.com/gszauer/5718441
                        // Line triangle mesh
                        List <Vector3> sections = points.Select(pt => pt.ToVector3GlTFSpace())
                                                  .FilterConsecutiveSame()
                                                  .ToList();

                        for (int i = 0; i < sections.Count - 1; i++)
                        {
                            Vector3 current = sections[i];
                            Vector3 next    = sections[i + 1];
                            Vector3 dir     = Vector3.Normalize(next - current);


                            // translate the vector to the left along its way
                            Vector3 side;
                            if (dir.Equals(Vector3.UnitY))
                            {
                                side = Vector3.UnitX * width;
                            }
                            else
                            {
                                side = Vector3.Cross(dir, Vector3.UnitY) * width;
                            }


                            Vector3 v0 = current - side; // 0
                            Vector3 v1 = current + side; // 1

                            triangulation.Positions.Add(v0);
                            triangulation.Positions.Add(v1);

                            if (i == sections.Count - 2) // add last vertices
                            {
                                v0 = next - side;        // 0
                                v1 = next + side;        // 1
                                triangulation.Positions.Add(v0);
                                triangulation.Positions.Add(v1);
                            }
                        }
                        // add last vertices


                        for (int i = 0; i < sections.Count - 1; i++)
                        {
                            int i0 = i * 2;
                            triangulation.Indices.Add(i0);
                            triangulation.Indices.Add(i0 + 1);
                            triangulation.Indices.Add(i0 + 3);

                            triangulation.Indices.Add(i0 + 0);
                            triangulation.Indices.Add(i0 + 3);
                            triangulation.Indices.Add(i0 + 2);
                        }

                        return(triangulation);
                    }
                }
            }
            catch (Exception ex)
            {
                _logger?.LogError(ex, ex.ToString());
                throw;
            }
            return(default);
예제 #17
0
 public static TriangulationList <Vector3> CenterOnOrigin(this TriangulationList <Vector3> triangulation)
 {
     return(triangulation.CenterOnOrigin(triangulation.GetBoundingBox(), true));
 }