Exemple #1
0
 public void CanCalculateZoomLevel()
 {
     Assert.Equal(1, TileServiceUtils.CalculateZoomLevel(Math.PI / 2, Math.PI));
     Assert.Equal(11, TileServiceUtils.CalculateZoomLevel(Math.PI / 2000, Math.PI / 1000));
     Assert.Equal(21, TileServiceUtils.CalculateZoomLevel(Math.PI / 2000000, Math.PI / 1000000));
     Assert.Equal(24, TileServiceUtils.CalculateZoomLevel(Math.PI / 2000000000, Math.PI / 1000000000));
 }
Exemple #2
0
        public void RoundingZoomLevelTest()
        {
            double diff1 = 0.000365585907798893;
            double diff2 = 0.000766990393942846;

            double diff1_1 = 0.000365339467977011;
            double diff2_1 = 0.000766990393942818;

            var res1 = TileServiceUtils.CalculateZoomLevel(diff1, diff2);
            var res2 = TileServiceUtils.CalculateZoomLevel(diff1_1, diff2_1);

            Assert.Equal(res1, res2);
            Assert.Equal(13, res1);
        }
Exemple #3
0
        /// <summary>
        /// Get the map parameters for the report tile
        /// </summary>
        public MapParameters GetMapParameters(string bbox, int width, int height, bool addMargin, bool adjustBoundingBox)
        {
            log.LogDebug($"GetMapParameters: bbox={bbox}, width={width}, height={height}, addMargin={addMargin}, adjustBoundingBox={adjustBoundingBox}");

            var            bboxRadians = boundingBoxHelper.GetBoundingBox(bbox);
            MapBoundingBox mapBox      = new MapBoundingBox
            {
                minLat = bboxRadians.BottomLeftLat,
                minLng = bboxRadians.BottomLeftLon,
                maxLat = bboxRadians.TopRightLat,
                maxLng = bboxRadians.TopRightLon
            };

            int  zoomLevel = TileServiceUtils.CalculateZoomLevel(mapBox.maxLat - mapBox.minLat, mapBox.maxLng - mapBox.minLng);
            long numTiles  = TileServiceUtils.NumberOfTiles(zoomLevel);

            MapParameters parameters = new MapParameters
            {
                bbox      = mapBox,
                zoomLevel = zoomLevel,
                numTiles  = numTiles,
                mapWidth  = width,
                mapHeight = height,
                addMargin = addMargin
            };

            if (adjustBoundingBox)
            {
                boundingBoxService.AdjustBoundingBoxToFit(parameters);
            }

            parameters.pixelTopLeft = TileServiceUtils.LatLngToPixel(mapBox.maxLat, mapBox.minLng, parameters.numTiles);
            log.LogDebug("MapParameters: " + JsonConvert.SerializeObject(parameters));

            return(parameters);
        }
Exemple #4
0
        protected override async Task <ContractExecutionResult> ProcessAsyncEx <T>(T item)
        {
            var request = item as DxfTileRequest;

            if (request == null)
            {
                ThrowRequestTypeCastException <DxfTileRequest>();
            }

            string filespaceId = FileDescriptorExtensions.GetFileSpaceId(configStore, log);

            //Calculate zoom level
            int zoomLevel = TileServiceUtils.CalculateZoomLevel(request.bbox.TopRightLat - request.bbox.BottomLeftLat,
                                                                request.bbox.TopRightLon - request.bbox.BottomLeftLon);

            log.LogDebug("DxfTileExecutor: BBOX differences {0} {1} {2}", request.bbox.TopRightLat - request.bbox.BottomLeftLat,
                         request.bbox.TopRightLon - request.bbox.BottomLeftLon, zoomLevel);
            int   numTiles      = TileServiceUtils.NumberOfTiles(zoomLevel);
            Point topLeftLatLng = new Point(request.bbox.TopRightLat.LatRadiansToDegrees(),
                                            request.bbox.BottomLeftLon.LonRadiansToDegrees());
            Point topLeftTile = WebMercatorProjection.LatLngToTile(topLeftLatLng, numTiles);

            log.LogDebug("DxfTileExecutor: zoomLevel={0}, numTiles={1}, xtile={2}, ytile={3}", zoomLevel, numTiles,
                         topLeftTile.x, topLeftTile.y);

            log.LogDebug("DxfTileExecutor: {0} files", request.files.Count());

            //Short circuit overlaying if there no files to overlay as ForAll is an expensive operation
            if (!request.files.Any())
            {
                byte[] emptyOverlayData = null;
                using (Bitmap bitmap = new Bitmap(WebMercatorProjection.TILE_SIZE, WebMercatorProjection.TILE_SIZE))
                {
                    emptyOverlayData = bitmap.BitmapToByteArray();
                }
                return(new TileResult(emptyOverlayData));
            }

            log.LogDebug(string.Join(",", request.files.Select(f => f.Name).ToList()));

            List <byte[]> tileList = new List <byte[]>();

            var fileTasks = request.files.Select(async file =>
            {
                //foreach (var file in request.files)
                //Check file type to see if it has tiles
                if (file.ImportedFileType == ImportedFileType.Alignment ||
                    file.ImportedFileType == ImportedFileType.DesignSurface ||
                    file.ImportedFileType == ImportedFileType.Linework)
                {
                    if (zoomLevel >= file.MinZoomLevel)
                    {
                        var suffix           = FileUtils.GeneratedFileSuffix(file.ImportedFileType);
                        string generatedName = FileUtils.GeneratedFileName(file.Name, suffix, FileUtils.DXF_FILE_EXTENSION);
                        byte[] tileData      = null;
                        if (zoomLevel <= file.MaxZoomLevel || file.MaxZoomLevel == 0) //0 means not calculated
                        {
                            tileData = await GetTileAtRequestedZoom(topLeftTile, zoomLevel, file.Path, generatedName, filespaceId);
                        }
                        else if (zoomLevel - file.MaxZoomLevel <= 5) //Don't try to scale if the difference is too excessive
                        {
                            tileData = await GetTileAtHigherZoom(topLeftTile, zoomLevel, file.Path, generatedName, filespaceId,
                                                                 file.MaxZoomLevel, numTiles);
                        }
                        else
                        {
                            log.LogDebug(
                                "DxfTileExecutor: difference between requested and maximum zooms too large; not even going to try to scale tile");
                        }
                        if (tileData != null)
                        {
                            tileList.Add(tileData);
                        }
                    }
                }
            });

            await Task.WhenAll(fileTasks);

            //Overlay the tiles. Return an empty tile if none to overlay.
            log.LogDebug("DxfTileExecutor: Overlaying {0} tiles", tileList.Count);
            byte[] overlayData          = null;
            System.Drawing.Point origin = new System.Drawing.Point(0, 0);
            using (Bitmap bitmap = new Bitmap(WebMercatorProjection.TILE_SIZE, WebMercatorProjection.TILE_SIZE))
                using (Graphics g = Graphics.FromImage(bitmap))
                {
                    foreach (byte[] tileData in tileList)
                    {
                        using (var tileStream = new MemoryStream(tileData))
                        {
                            Image image = Image.FromStream(tileStream);
                            g.DrawImage(image, origin);
                        }
                    }
                    overlayData = bitmap.BitmapToByteArray();
                }

            return(new TileResult(overlayData));
        }
Exemple #5
0
        protected override async Task <ContractExecutionResult> ProcessAsyncEx <T>(T item)
        {
            List <FileData>     files       = null;
            int                 zoomLevel   = 0;
            Point               topLeftTile = null;
            int                 numTiles    = 0;
            BoundingBox2DLatLon bbox        = null;

            if (item is DxfTileRequest request)
            {
                files = request.files?.ToList();
                bbox  = request.bbox;

                //Calculate zoom level
                zoomLevel = TileServiceUtils.CalculateZoomLevel(request.bbox.TopRightLat - request.bbox.BottomLeftLat,
                                                                request.bbox.TopRightLon - request.bbox.BottomLeftLon);
                log.LogDebug("DxfTileExecutor: BBOX differences {0} {1} {2}", request.bbox.TopRightLat - request.bbox.BottomLeftLat,
                             request.bbox.TopRightLon - request.bbox.BottomLeftLon, zoomLevel);
                numTiles = TileServiceUtils.NumberOfTiles(zoomLevel);
                Point topLeftLatLng = new Point(request.bbox.TopRightLat.LatRadiansToDegrees(),
                                                request.bbox.BottomLeftLon.LonRadiansToDegrees());
                topLeftTile = WebMercatorProjection.LatLngToTile(topLeftLatLng, numTiles);
                log.LogDebug($"DxfTileExecutor: zoomLevel={zoomLevel}, numTiles={numTiles}, xtile={topLeftTile.x}, ytile={topLeftTile.y}");
            }
            else if (item is DxfTile3dRequest request3d)
            {
                files = request3d.files?.ToList();

                zoomLevel   = request3d.zoomLevel;
                numTiles    = TileServiceUtils.NumberOfTiles(zoomLevel);
                topLeftTile = new Point {
                    x = request3d.xTile, y = request3d.yTile
                };
            }
            else
            {
                ThrowRequestTypeCastException <DxfTileRequest>();
            }

            log.LogDebug($"DxfTileExecutor: {files?.Count ?? 0} files");

            //Short circuit overlaying if there no files to overlay as ForAll is an expensive operation
            if (files == null || !files.Any())
            {
                byte[] emptyOverlayData;
                using (var bitmap = new Image <Rgba32>(WebMercatorProjection.TILE_SIZE, WebMercatorProjection.TILE_SIZE))
                {
                    emptyOverlayData = bitmap.BitmapToByteArray();
                }

                return(new TileResult(emptyOverlayData));
            }

            log.LogDebug(string.Join(",", files.Select(f => f.Name).ToList()));

            var          tileList = new List <byte[]>();
            const string DATA_OCEAN_ROOT_FOLDER_ID_KEY = "DATA_OCEAN_ROOT_FOLDER_ID";
            var          dataOceanRootFolder           = configStore.GetValueString(DATA_OCEAN_ROOT_FOLDER_ID_KEY);

            if (string.IsNullOrEmpty(dataOceanRootFolder))
            {
                throw new ArgumentException($"Missing environment variable {DATA_OCEAN_ROOT_FOLDER_ID_KEY}");
            }

            //For GeoTIFF files, use the latest version of a file
            var geoTiffFiles = files.Where(x => x.ImportedFileType == ImportedFileType.GeoTiff).ToList();

            if (geoTiffFiles.Any())
            {
                //Find any with multiple versions and remove old ones from the list
                var latestFiles = geoTiffFiles.GroupBy(g => g.Name).Select(g => g.OrderBy(o => o.SurveyedUtc).Last()).ToList();
                foreach (var geoTiffFile in geoTiffFiles)
                {
                    if (!latestFiles.Contains(geoTiffFile))
                    {
                        files.Remove(geoTiffFile);
                    }
                }
            }

            var fileTasks = files.Select(async file =>
            {
                //foreach (var file in request.files)
                //Check file type to see if it has tiles
                if (file.ImportedFileType == ImportedFileType.Linework ||
                    file.ImportedFileType == ImportedFileType.GeoTiff)
                {
                    var fullPath = DataOceanFileUtil.DataOceanPath(dataOceanRootFolder, file.CustomerUid, file.ProjectUid);
                    var fileName = DataOceanFileUtil.DataOceanFileName(file.Name,
                                                                       file.ImportedFileType == ImportedFileType.SurveyedSurface || file.ImportedFileType == ImportedFileType.GeoTiff,
                                                                       Guid.Parse(file.ImportedFileUid), file.SurveyedUtc);
                    fileName = DataOceanFileUtil.GeneratedFileName(fileName, file.ImportedFileType);

                    if (zoomLevel >= file.MinZoomLevel)
                    {
                        byte[] tileData = null;
                        if (zoomLevel <= file.MaxZoomLevel || file.MaxZoomLevel == 0) //0 means not calculated
                        {
                            tileData = await GetTileAtRequestedZoom(topLeftTile, zoomLevel, fullPath, fileName);
                        }
                        else if (zoomLevel - file.MaxZoomLevel <= 5) //Don't try to scale if the difference is too excessive
                        {
                            tileData = await GetTileAtHigherZoom(topLeftTile, zoomLevel, fullPath, fileName,
                                                                 file.MaxZoomLevel, numTiles);
                        }
                        else
                        {
                            log.LogDebug(
                                "DxfTileExecutor: difference between requested and maximum zooms too large; not even going to try to scale tile");
                        }

                        if (tileData != null && tileData.Length > 0)
                        {
                            tileList.Add(tileData);
                        }
                    }
                }
            });

            await Task.WhenAll(fileTasks);

            log.LogDebug($"DxfTileExecutor: Overlaying {tileList.Count} tiles");
            byte[] overlayData = TileOverlay.OverlayTiles(tileList);

            return(new TileResult(overlayData));
        }