private void button10_Click(object sender, EventArgs e) { // Calculate Header Info LLBoundingBox bb = new LLBoundingBox(173, -44, 174, -43, false); // Double Alt = 0; var v1 = MapUtil.LatLonToEcef(bb.South, bb.West, 0); listBox1.Items.Add($"WS Meters:{v1.X} , {v1.Y}"); var v2 = MapUtil.LatLonToEcef(bb.North, bb.East, 0); listBox1.Items.Add($"EN Meters:{v2.X} , {v2.Y}"); var v3 = MapUtil.LatLonToEcef(-43.5, 173.5, 0); listBox1.Items.Add($"EN Meters:{v3.X} , {v3.Y}"); //var midpt = MapUtil.MidPointLL(new MapPoint(bb.West, bb.South), new MapPoint(bb.East, bb.North)); // listBox1.Items.Add($"Midpoint:{MapUtil.Rad2Deg(midpt.Longitude)} , {MapUtil.Rad2Deg(midpt.Latitude)}"); //var v4 = MapUtil.LatLonToEcef(MapUtil.Rad2Deg(midpt.Latitude), MapUtil.Rad2Deg(midpt.Longitude), 0); //listBox1.Items.Add($"Midpoint Meters:{v4.X} , {v4.Y}"); }
public async override Task <ElevationData> GetDemLL(double minLon, double minLat, double maxLon, double maxLat) { var rect = new LLBoundingBox(new MapPoint(minLon, minLat), new MapPoint(maxLon, maxLat)); return(MakeTileDEM(rect)); }
private void btnDistance_Click(object sender, EventArgs e) { // Winner is MapUtil.GetDistance for pole to pole listBox1.Items.Add(""); var bb = new LLBoundingBox(0, 0, 0, 0, false); bb.West = -180.0; bb.East = -179.0; bb.South = 0.0; bb.North = 0.0; var d1 = MapUtil.GetDistance(bb.West, bb.South, bb.East, bb.North); listBox1.Items.Add($"Distance1:{d1}, (W,S - E,N) ,({bb.West} , {bb.South}) - ({bb.East} , {bb.North})"); Char myChar = 'K'; var d2 = MapUtil.Distance3(bb.West, bb.South, bb.East, bb.South, myChar); listBox1.Items.Add($"Distance2:{d2}, (W,S - E,N) ,({bb.West} , {bb.South}) - ({bb.East} , {bb.North})"); var d3 = MapUtil.DistanceTo(bb.West, bb.South, bb.East, bb.South, myChar); listBox1.Items.Add($"Distance3:{d3}, (W,S - E,N) ,({bb.West} , {bb.South}) - ({bb.East} , {bb.North})"); bb.West = -180.0; bb.East = -179.0; bb.South = -45.0; bb.North = -45.0; d1 = MapUtil.GetDistance(bb.West, bb.South, bb.East, bb.North); listBox1.Items.Add($"Distance1:{Math.Round(d1,6)}, (W,S - E,N) ,({bb.West} , {bb.South}) - ({bb.East} , {bb.North})"); d2 = MapUtil.Distance3(bb.West, bb.South, bb.East, bb.South, myChar); listBox1.Items.Add($"Distance2:{Math.Round(d2,6)}, (W,S - E,N) ,({bb.West} , {bb.South}) - ({bb.East} , {bb.North})"); d3 = MapUtil.DistanceTo(bb.West, bb.South, bb.East, bb.South, myChar); listBox1.Items.Add($"Distance3:{Math.Round(d3,6)}, (W,S - E,N) ,({bb.West} , {bb.South}) - ({bb.East} , {bb.North})"); bb.West = 0.0; bb.East = 1.0; bb.South = 0.0; bb.North = 0.0; d1 = MapUtil.GetDistance(bb.West, bb.South, bb.East, bb.North); listBox1.Items.Add($"Distance1:{Math.Round(d1, 6)}, (W,S - E,N) ,({bb.West} , {bb.South}) - ({bb.East} , {bb.North})"); d2 = MapUtil.Distance3(bb.West, bb.South, bb.East, bb.South, myChar); listBox1.Items.Add($"Distance2:{Math.Round(d2, 6)}, (W,S - E,N) ,({bb.West} , {bb.South}) - ({bb.East} , {bb.North})"); d3 = MapUtil.DistanceTo(bb.West, bb.South, bb.East, bb.South, myChar); listBox1.Items.Add($"Distance3:{Math.Round(d3, 6)}, (W,S - E,N) ,({bb.West} , {bb.South}) - ({bb.East} , {bb.North})"); bb.West = -179.0; bb.East = 170.0; bb.South = 0.0; bb.North = 0.0; d1 = MapUtil.GetDistance(bb.West, bb.South, bb.East, bb.North); listBox1.Items.Add($"Distance1:{Math.Round(d1, 6)}, (W,S - E,N) ,({bb.West} , {bb.South}) - ({bb.East} , {bb.North})"); d2 = MapUtil.Distance3(bb.West, bb.South, bb.East, bb.South, myChar); listBox1.Items.Add($"Distance2:{Math.Round(d2, 6)}, (W,S - E,N) ,({bb.West} , {bb.South}) - ({bb.East} , {bb.North})"); d3 = MapUtil.DistanceTo(bb.West, bb.South, bb.East, bb.South, myChar); listBox1.Items.Add($"Distance3:{Math.Round(d3, 6)}, (W,S - E,N) ,({bb.West} , {bb.South}) - ({bb.East} , {bb.North})"); bb.West = -90.0; bb.East = 90.0; bb.South = 0.0; bb.North = 0.0; d1 = MapUtil.GetDistance(bb.West, bb.South, bb.East, bb.North); listBox1.Items.Add($"Distance1:{Math.Round(d1, 6)}, (W,S - E,N) ,({bb.West} , {bb.South}) - ({bb.East} , {bb.North})"); d2 = MapUtil.Distance3(bb.West, bb.South, bb.East, bb.South, myChar); listBox1.Items.Add($"Distance2:{Math.Round(d2, 6)}, (W,S - E,N) ,({bb.West} , {bb.South}) - ({bb.East} , {bb.North})"); d3 = MapUtil.DistanceTo(bb.West, bb.South, bb.East, bb.South, myChar); listBox1.Items.Add($"Distance3:{Math.Round(d3, 6)}, (W,S - E,N) ,({bb.West} , {bb.South}) - ({bb.East} , {bb.North})"); bb.West = 1.0; bb.East = 1.1; bb.South = 0.0; bb.North = 1.0; d1 = MapUtil.GetDistance(bb.West, bb.South, bb.East, bb.North); listBox1.Items.Add($"Distance1:{Math.Round(d1, 6)}, (W,S - E,N) ,({bb.West} , {bb.South}) - ({bb.East} , {bb.North})"); d2 = MapUtil.Distance3(bb.West, bb.South, bb.East, bb.South, myChar); listBox1.Items.Add($"Distance2:{Math.Round(d2, 6)}, (W,S - E,N) ,({bb.West} , {bb.South}) - ({bb.East} , {bb.North})"); d3 = MapUtil.DistanceTo(bb.West, bb.South, bb.East, bb.South, myChar); listBox1.Items.Add($"Distance3:{Math.Round(d3, 6)}, (W,S - E,N) ,({bb.West} , {bb.South}) - ({bb.East} , {bb.North})"); }
public void MakeDemoTile(LLBoundingBox boundary) { MaximumHeight = float.NegativeInfinity; MinimumHeight = float.PositiveInfinity; if (GridSize != QMConstants.DemoResolutionGridSize) { GridSize = QMConstants.DemoResolutionGridSize; Array.Resize(ref ElevGrid, GridSize * GridSize); Array.Resize(ref EcefPoints, GridSize * GridSize); } var step = 20.0F / (GridSize - 1); var XStep = (boundary.East - boundary.West) / (GridSize - 1); var YStep = (boundary.North - boundary.South) / (GridSize - 1); float hgt; int pos = 0; double XPos; double YPos = boundary.South; for (int y = 0; y < GridSize; y++) { hgt = QMConstants.DemoBaseHgt; XPos = boundary.West; for (int x = 0; x < GridSize; x++) { // height ElevGrid[pos] = hgt; if (hgt < MinimumHeight) { MinimumHeight = hgt; } if (hgt > MaximumHeight) { MaximumHeight = hgt; } hgt = hgt + step; // ECEF EcefPoints[pos] = CoordinateUtils.geo_to_ecef(new Vector3() { X = MapUtils.Deg2Rad(XPos), Y = MapUtils.Deg2Rad(YPos), Z = hgt }); XPos = XPos + XStep; pos++; } YPos = YPos + YStep; // increase y } HasData = true; East = boundary.East; West = boundary.West; North = boundary.North; South = boundary.South; }
private void btnCenter_Click(object sender, EventArgs e) { LLBoundingBox bb = new LLBoundingBox(170, -43, 180, -44, false); var t1 = bb.GetCenter(); listBox1.Items.Add($"BB Center Test1 Not Radians {t1.Longitude} , {t1.Latitude}"); LLBoundingBox bb2 = new LLBoundingBox(MapUtil.Deg2Rad(170), MapUtil.Deg2Rad(-43), MapUtil.Deg2Rad(180), MapUtil.Deg2Rad(-44)); var t2 = bb2.GetCenter(); listBox1.Items.Add($"BB Center Test2 Not Radians {MapUtil.Rad2Deg( t2.Longitude)} , {MapUtil.Rad2Deg(t2.Latitude)}"); var t3 = MapUtil.MidPointRad(new MapPoint(MapUtil.Deg2Rad(170.0), MapUtil.Deg2Rad(-43)), new MapPoint(MapUtil.Deg2Rad(180.0), MapUtil.Deg2Rad(-44.0))); listBox1.Items.Add($"BB Center Test3 Not Radians {MapUtil.Rad2Deg(t3.Longitude)} , {MapUtil.Rad2Deg(t3.Latitude)}"); }
public void TileBuilder_BuildTile() { LLBoundingBox TileBoundaryLL = MapGeo.TileXYZToRectLL(0, 0, 20, out var yFlip); ElevationData elevData = new ElevationData(0, 5); elevData.MakeEmptyTile(TileBoundaryLL, false); QMTileBuilder tileBuilder = new QMTileBuilder() { TileData = elevData, GridSize = elevData.GridSize }; var res = tileBuilder.BuildQuantizedMeshTile(); res.Should().Be(true); tileBuilder.QuantizedMeshTile.Should().HaveCountGreaterOrEqualTo(162); tileBuilder.QuantizedMeshTile.Should().HaveCountLessOrEqualTo(164); }
public void MakeEmptyTile(LLBoundingBox boundary, bool hasLighting) { HasLighting = hasLighting; if (GridSize != QMConstants.FlatResolutionGridSize) { GridSize = QMConstants.FlatResolutionGridSize; Array.Resize(ref ElevGrid, GridSize * GridSize); Array.Resize(ref EcefPoints, GridSize * GridSize); if (hasLighting) { VertexNormals = new byte[GridSize * GridSize * 2]; Triangles = new Triangle[(GridSize - 1) * (GridSize - 1) * 2]; } } Clear(); HasData = false; East = boundary.East; West = boundary.West; North = boundary.North; South = boundary.South; MaximumHeight = LowestElevation; MinimumHeight = LowestElevation; EcefPoints[0] = CoordinateUtils.geo_to_ecef(new Vector3() { X = MapUtils.Deg2Rad(East), Y = MapUtils.Deg2Rad(South), Z = LowestElevation }); EcefPoints[1] = CoordinateUtils.geo_to_ecef(new Vector3() { X = MapUtils.Deg2Rad(West), Y = MapUtils.Deg2Rad(South), Z = LowestElevation }); EcefPoints[2] = CoordinateUtils.geo_to_ecef(new Vector3() { X = MapUtils.Deg2Rad(East), Y = MapUtils.Deg2Rad(North), Z = LowestElevation }); EcefPoints[3] = CoordinateUtils.geo_to_ecef(new Vector3() { X = MapUtils.Deg2Rad(West), Y = MapUtils.Deg2Rad(North), Z = LowestElevation }); }
/// <summary> /// /// </summary> /// <param name="bbox"></param> /// <returns></returns> private ElevationData MakeTileDEM(LLBoundingBox bbox) { // Steps // Using bounding box get elevation data for tile // Calculate header info Vector3[] ecefPoints; ElevationData ed = GetData(bbox, out ecefPoints); // Work out bounding sphere TileInfo tileInfo = new TileInfo(); var hdr = tileInfo.CalculateHeaderInfo(ref ecefPoints, false); ed.CenterX = hdr.CenterX; ed.CenterY = hdr.CenterY; ed.CenterZ = hdr.CenterZ; ed.BoundingSphereCenterX = hdr.CenterX; ed.BoundingSphereCenterY = hdr.CenterY; ed.BoundingSphereCenterZ = hdr.CenterZ; ed.BoundingSphereRadius = hdr.BoundingSphereRadius; // Work out HorizonOcclusionPoint var hop = HorizonOcclusionPoint.FromPoints(ecefPoints, tileInfo.BoundingSphere); ed.HorizonOcclusionPointX = hop.X; ed.HorizonOcclusionPointY = hop.Y; ed.HorizonOcclusionPointZ = hop.Z; /* Quicker cheat method untested * ed.HorizonOcclusionPointX = hdr.CenterX; * ed.HorizonOcclusionPointY = hdr.CenterY; * ed.HorizonOcclusionPointZ = maxElev; */ // todo lighting return(ed); }
private ElevationData GetData(LLBoundingBox bbox, out Vector3[] ecefPoints) { //todo get data from TRex //Boolean dataAvailable = true; // if ((lat >= -43.548006 & lat <= -43.547679) & (lon >= 172.632951 & lon <= 172.633542)) ElevationData ed; LLBoundingBox data = new LLBoundingBox(172.632951, -43.548006, 172.633542, -43.547679); bool dataAvailable = data.East >= bbox.West && data.West <= bbox.East && data.North >= bbox.South && data.South <= bbox.North; LLBoundingBox data2 = new LLBoundingBox(-0.124629, 51.500745, 1.0, 51.6); bool dataAvailable2 = data2.East >= bbox.West && data2.West <= bbox.East && data2.North >= bbox.South && data2.South <= bbox.North; int _gridSize; if (dataAvailable | dataAvailable2) { _gridSize = GridSize; } else { _gridSize = 2; } ed = new ElevationData(_gridSize); ecefPoints = new Vector3[_gridSize * _gridSize]; int PixelCount = _gridSize - 1; var yRange = bbox.North - bbox.South; var xRange = bbox.East - bbox.West; var xStep = xRange / PixelCount; var yStep = yRange / PixelCount; float minElev = float.PositiveInfinity; float maxElev = float.NegativeInfinity; Random rnd = new Random(); int i = 0; float hgt = 0; var HgtMode = 2; for (int y = 0; y < GridSize; y++) { for (int x = 0; x < GridSize; x++) { var lat = bbox.South + (y * yStep); var lon = bbox.West + (x * xStep); if (HgtMode == 1) { ed.Elev[i] = rnd.Next(1, 8000); } else if (HgtMode == 2) { if ((lat >= -43.548006 & lat <= -43.547679) & (lon >= 172.632951 & lon <= 172.633542)) { ed.Elev[i] = (float)10.0; } else if ((lat >= 51.500745 & lat <= 51.6) & (lon >= -0.124629 & lon <= 1.0)) { ed.Elev[i] = rnd.Next(1, 10); } else { ed.Elev[i] = 0; } } if (ed.Elev[i] < minElev) { minElev = ed.Elev[i]; } if (ed.Elev[i] > maxElev) { maxElev = ed.Elev[i]; } // Make ecef point list for later header calculations ecefPoints[i] = Coord.geo_to_ecef(new Vector3() { X = MapUtil.Deg2Rad(lon), Y = MapUtil.Deg2Rad(lat), Z = ed.Elev[i] }); i++; } } ed.MaximumHeight = maxElev; ed.MinimumHeight = minElev; return(ed); }
/* * https://cesium.com/blog/2013/05/09/computing-the-horizon-occlusion-point/ * private computeMagnitude(ellipsoid, position, scaledSpaceDirectionToPoint) * { * var scaledSpacePosition = ellipsoid.transformPositionToScaledSpace(position); * var magnitudeSquared = scaledSpacePosition.magnitudeSquared(); * var magnitude = Math.sqrt(magnitudeSquared); * var direction = scaledSpacePosition.divideByScalar(magnitude); * * // For the purpose of this computation, points below the ellipsoid * // are considered to be on it instead. * magnitudeSquared = Math.max(1.0, magnitudeSquared); * magnitude = Math.max(1.0, magnitude); * * var cosAlpha = direction.dot(scaledSpaceDirectionToPoint); * var sinAlpha = direction.cross(scaledSpaceDirectionToPoint).magnitude(); * var cosBeta = 1.0 / magnitude; * var sinBeta = Math.sqrt(magnitudeSquared - 1.0) * cosBeta; * * return 1.0 / (cosAlpha * cosBeta - sinAlpha * sinBeta); * } */ /// <summary> /// By LatLon /// </summary> /// <param name="bb"></param> /// <returns></returns> private ElevationData MakeTileDEM(LLBoundingBox bb) { // todo we also need to comput header info for the quantized mesh Vector2 v; v.X = 0; v.Y = 0; int x2 = 0; int y2 = 0; int PixelCount = GridSize - 1; var DoRandom = false; int HgtMode = 2; float minElev = float.PositiveInfinity; float maxElev = float.NegativeInfinity; Random rnd = new Random(); ElevationData ed = new ElevationData(GridSize); var midPt = bb.GetCenter(); // var pt2 = Coord.geo_to_ecef(new Vector3( MapUtil.Deg2Rad(midPt.Longitude), MapUtil.Deg2Rad(midPt.Latitude),0)); // zero elevation for now var pt = MapUtil.LatLonToEcef(midPt.Latitude, midPt.Longitude, 0); // zero elevation for now Vector3[] ecefPoints = new Vector3[GridSize * GridSize]; try { // we are going to walk up from sw to ne for returning dem in latlon coordinates var yRange = bb.North - bb.South; var xRange = bb.East - bb.West; var xStep = xRange / PixelCount; var yStep = yRange / PixelCount; int i = 0; float hgt = 0; for (int y = 0; y < GridSize; y++) { for (int x = 0; x < GridSize; x++) { var lat = bb.South + (y * yStep); var lon = bb.West + (x * xStep); v = MapProject(lat, lon); // MapProject is lat long if (v.X >= Width) { v.X = Width - 1; } if (v.Y >= Depth) { v.Y = Depth - 1; } if (v.X < 0) { v.X = 0; } if (v.Y < 0) { v.Y = 0; } x2 = (int)v.X; y2 = (int)v.Y; //hgt = 0; // if (i == 4) // hgt = 100; if (HgtMode == 1) { ed.Elev[i] = rnd.Next(1, 8000); } else if (HgtMode == 2) { ed.Elev[i] = 0; if (lat >= -43.548006 & lat <= -43.547679) { if (lon >= 172.632951 & lon <= 172.633542) { ed.Elev[i] = (float)10.0; } } } else { hgt = Map.GetPixel(x2, y2).GetBrightness(); // 0=black, 1= white ed.Elev[i] = MapUtil.Lerp(0, 1, ElevMin, ElevMax, hgt); } if (ed.Elev[i] < minElev) { minElev = ed.Elev[i]; } if (ed.Elev[i] > maxElev) { maxElev = ed.Elev[i]; } // Make ecef point list for later calculations ecefPoints[i] = Coord.geo_to_ecef(new Vector3() { X = MapUtil.Deg2Rad(lon), Y = MapUtil.Deg2Rad(lat), Z = ed.Elev[i] }); i++; } } } catch (Exception ex) { #if DEBUG System.Diagnostics.Debug.WriteLine($"**** MakeTileDEM Exception ****:{ex} v:{v} x2{x2} y2{y2} "); // file writer System.Diagnostics.Trace.WriteLine($"**** MakeTileDEM Exception *********:{ex} v:{v} x2{x2} y2{y2} "); #endif } // todo now make a ecfc array to calculate header info TileInfo tileInfo = new TileInfo(); var hdr = tileInfo.CalculateHeaderInfo(ref ecefPoints, false); ed.CenterX = hdr.CenterX; ed.CenterY = hdr.CenterY; ed.CenterZ = hdr.CenterZ; ed.BoundingSphereCenterX = hdr.CenterX; ed.BoundingSphereCenterY = hdr.CenterY; ed.BoundingSphereCenterZ = hdr.CenterZ; ed.BoundingSphereRadius = hdr.BoundingSphereRadius; ed.MaximumHeight = maxElev; ed.MinimumHeight = minElev; var hop = HorizonOcclusionPoint.FromPoints(ecefPoints, tileInfo.BoundingSphere); ed.HorizonOcclusionPointX = hop.X; ed.HorizonOcclusionPointY = hop.Y; ed.HorizonOcclusionPointZ = hop.Z; /* * // FIXME: is there a better choice for a horizon occlusion point? * // Currently it's the center of tile elevated to bbox's max Z * header.horizon_occlusion = c; * header.horizon_occlusion.z = bbox.max.z; * * * ed.HorizonOcclusionPointX = hdr.CenterX; * ed.HorizonOcclusionPointY = hdr.CenterY; * ed.HorizonOcclusionPointZ = maxElev; */ return(ed); }
/// <summary> /// Executor that implements requesting and rendering grid information to create the grid rows /// </summary> /// <returns></returns> public async Task <bool> ExecuteAsync() { // Get the lat lon boundary from xyz tile request TileBoundaryLL = MapGeo.TileXYZToRectLL(TileX, TileY, TileZ, out var yFlip); _log.LogInformation($"#Tile#.({TileX},{TileY}) Execute Start. DMode:{DisplayMode}, HasLighting:{HasLighting}, Zoom:{TileZ} FlipY:{yFlip}. TileBoundary:{TileBoundaryLL.ToDisplay()}, DataModel:{DataModelUid}"); if (TileZ == 0) // Send back default root tile { MakeRootTile(); return(true); } SiteModel = DIContext.Obtain <ISiteModels>().GetSiteModel(DataModelUid); if (SiteModel == null) { ResultStatus = RequestErrorStatus.NoSuchDataModel; _log.LogError($"Tile.({TileX},{TileY}) Failed to obtain site model for {DataModelUid}"); return(false); } var siteModelExtentWithSurveyedSurfaces = SiteModel.GetAdjustedDataModelSpatialExtents(null); _log.LogDebug($"Tile.({TileX},{TileY}) Site model extents are {siteModelExtentWithSurveyedSurfaces}. TileBoundary:{TileBoundaryLL.ToDisplay()}"); if (!siteModelExtentWithSurveyedSurfaces.IsValidPlanExtent) // No data return empty tile { return(BuildEmptyTile()); } // We will draw all missing data just below lowest elevation for site LowestElevation = (float)siteModelExtentWithSurveyedSurfaces.MinZ - 1F; Initialise(); // setup tile requirements if (TileGridSize == QMConstants.FlatResolutionGridSize) // Too far out to see detail so return empty tile { return(BuildEmptyTile()); } if (DisplayMode == QMConstants.DisplayModeDemo) // development use only { return(BuildDemoTile()); } try { var setupResult = await SetupPipelineTask(siteModelExtentWithSurveyedSurfaces, SiteModel.CellSize); if (!setupResult) { if (ResultStatus != RequestErrorStatus.InvalidCoordinateRange) { _log.LogError($"Tile.({TileX},{TileY}) Unable to setup pipelinetask."); } return(BuildEmptyTile()); } processor.Process(); if (GriddedElevationsResponse.ResultStatus != RequestErrorStatus.OK) { _log.LogError($"Tile.({TileX},{TileY}) Unable to obtain data for gridded data. GriddedElevationRequestResponse: {GriddedElevationsResponse.ResultStatus.ToString()}"); return(BuildEmptyTile()); } ElevData.HasData = !float.IsPositiveInfinity(task.MinElevation); // check for data // Developer Debugging Only if (ElevData.HasData) { OutputDebugTile("Raw"); } if (!ElevData.HasData) { return(BuildEmptyTile()); } _log.LogInformation($"#Tile#.({TileX},{TileY}) Data successfully sampled. GridSize:{TileGridSize} Min:{task.MinElevation}, Max:{task.MaxElevation} FirstElev:{GriddedElevDataArray[0, 0].Elevation}, LastElev:{GriddedElevDataArray[TileGridSize - 1, TileGridSize - 1].Elevation}"); ElevData.HasLighting = HasLighting; // Transform gridded data into a format the mesh builder can use ConvertGridToDEM(task.MinElevation, task.MaxElevation); // Build a quantized mesh from sampled elevations QMTileBuilder tileBuilder = new QMTileBuilder() { TileData = ElevData, GridSize = TileGridSize }; _log.LogInformation($"Tile.({TileX},{TileY}) BuildQuantizedMeshTile. GridSize:{TileGridSize} Min:{ElevData.MinimumHeight}, Max:{ElevData.MaximumHeight}"); if (!tileBuilder.BuildQuantizedMeshTile()) { _log.LogError($"Tile.({TileX},{TileY}) BuildQuantizedMeshTile returned false with error code: {tileBuilder.BuildTileFaultCode}"); return(false); } QMTileResponse.data = tileBuilder.QuantizedMeshTile; // Make tile from mesh ResultStatus = RequestErrorStatus.OK; QMTileResponse.ResultStatus = ResultStatus; _log.LogDebug($"#Tile#.({TileX},{TileY}) Execute End. Returning production tile. CesiumY:{yFlip}, Zoom:{TileZ}, GridSize:{TileGridSize}"); return(true); } catch (Exception ex) { _log.LogError(ex, $"#Tile#.({TileX},{TileY}). Exception building QuantizedMesh tile: "); return(false); } }