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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
public static TriangulationList <Vector3> Scale(this TriangulationList <Vector3> triangulation, Vector3 scales) { return(triangulation.Transform(Matrix4x4.CreateScale(scales))); }
public static TriangulationList <Vector3> Scale(this TriangulationList <Vector3> triangulation, float factor) { return(triangulation.Transform(Matrix4x4.CreateScale(factor))); }
public static TriangulationList <Vector3> Translate(this TriangulationList <Vector3> triangulation, Vector3 vector) { Matrix4x4 translate = Matrix4x4.CreateTranslation(vector); return(Transform(triangulation, translate)); }
public static TriangulationList <Vector3> RotateZ(this TriangulationList <Vector3> triangulation, float radians) => Transform(triangulation, Matrix4x4.CreateRotationZ(radians));
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()); }
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);
public static TriangulationList <Vector3> CenterOnOrigin(this TriangulationList <Vector3> triangulation) { return(triangulation.CenterOnOrigin(triangulation.GetBoundingBox(), true)); }