[置顶] ArcGIS 地图切图系列之(二)JAVA实现

一、ArcGIS 地图切片原理

        详见上一篇文章内容。

二、java实现思路

      第一步:根据输入的地图要素,获取该要素的外包矩形,计算该要素所在的行列号:

public java.awt.Rectangle getOverlappingCellsESRI(Rectangle rect) {
	    int col1, col2, row1, row2;
	    
	    plottingMAXScale = 0.019035688046642241; 
	    col1 = (int)Math.floor((rect.x1 - this.x1) / 256 / plottingMAXScale ); 
	    col2 = (int)Math.floor((rect.x2 - this.x1) / 256 / plottingMAXScale); 
	    row1 = (int)Math.floor((Math.abs(rect.y1 - this.y1)) / 256 / plottingMAXScale); 
	    row2 = (int)Math.floor((Math.abs(rect.y2 - this.y1)) / 256 / plottingMAXScale);
	   
	    return new java.awt.Rectangle(col1,row2,col2-col1,row1-row2);
	  }
       其中plottingMAXScale是指的分辨率,上一篇博客已经讲述了怎么计算了,这里测试就写死了。方法返回的是该要素所在的起始行row和起始列,已经宽度和高度。

       第二步:根据行列号、宽度和高度,来进行画布的生成。

 for (Shape shape : shapes) {
              Rectangle shapeMBR = shape.getMBR();
              if (shapeMBR == null)
                continue;
              java.awt.Rectangle overlappingCells = bottomGrid.getOverlappingCellsESRI(shapeMBR); 
             
              // Iterate over levels from bottom up
              
              for (key.level = maxLevel; key.level >= minLevel; key.level--) {
                for (key.y = overlappingCells.y; key.y <= overlappingCells.y + overlappingCells.height; key.y++) {
                  for (key.x = overlappingCells.x; key.x <= overlappingCells.x + overlappingCells.width; key.x++) {
                    Canvas canvas = canvases.get(key);
                    if (canvas == null) {
                      Rectangle tileMBR = new Rectangle(); 
                      tileMBR.x1 = -400 + 256 * bottomGrid.plottingMAXScale * key.x;
                      tileMBR.x2 = -400 + 256 * bottomGrid.plottingMAXScale * (key.x + 1);
                      tileMBR.y1 =  400 - 256 * bottomGrid.plottingMAXScale * (key.y + 1);
                      tileMBR.y2 =  400 - 256 * bottomGrid.plottingMAXScale * key.y;
                      canvas = plotter.createCanvas(tileWidth, tileHeight, tileMBR); 
                      canvases.put(key.clone(), canvas);  
                    }
                    plotter.plot(canvas, shape);
                  }
                }  
                // Update overlappingCells for the higher level
                int updatedX1 = overlappingCells.x / 2;
                int updatedY1 = overlappingCells.y / 2;
                int updatedX2 = (overlappingCells.x + overlappingCells.width) / 2;
                int updatedY2 = (overlappingCells.y + overlappingCells.height) / 2;
                overlappingCells.x = updatedX1;
                overlappingCells.y = updatedY1;
                overlappingCells.width = updatedX2 - updatedX1 ;
                overlappingCells.height = updatedY2 - updatedY1 ; 
                bottomGrid.plottingMAXScale = bottomGrid.plottingMAXScale * 2;
              }
            }
        }
       画布生成过程中是从最大level开始,根据行列号来计算该要素所在切片的大小,得到canvas,然后将该要素绘制到该画布上。这里需要注意的是在计算画布外包矩形时,注意是从坐标系原点出发的,不要和Tiling scheme origin弄混淆了。

       第三步:将生成的画布绘制成图片

 // Write the tiles
      final Entry<TileIndexESRI, Canvas>[] entries =
          canvases.entrySet().toArray(new Map.Entry[canvases.size()]);
      // Clear the hash map to save memory as it is no longer needed
      canvases.clear();
      int parallelism = params.getInt("parallel",
          Runtime.getRuntime().availableProcessors());
      Parallel.forEach(entries.length, new RunnableRange<Object>() {
        @Override
        public Object run(int i1, int i2) {
          boolean output = params.getBoolean("output", true);
          try {
            Plotter plotter = plotterClass.newInstance();
            plotter.configure(params);
             
            for (int i = i1; i < i2; i++) {
              Map.Entry<TileIndexESRI, Canvas> entry = entries[i];
              TileIndexESRI key = entry.getKey();
              
              Path imagePath = new Path(outPath + "\\" + "L" + String.format("%0"+2+"d", key.level), key.getImageFileName()+extension);
              // Write this tile to an image
              DataOutputStream outFile = output? outFS.create(imagePath)
                  : new DataOutputStream(new NullOutputStream());
              plotter.writeImage(entry.getValue(), outFile, vflip);
              outFile.close();
              
              // Remove entry to allows GC to collect it
              entries[i] = null;
            }
            return null;
          } catch (InstantiationException e) {
            e.printStackTrace();
          } catch (IllegalAccessException e) {
            e.printStackTrace();
          } catch (IOException e) {
            e.printStackTrace();
          }
          return null;
        }
      }, parallelism);
    } catch (InstantiationException e) {
      throw new RuntimeException("Error creating rastierizer", e);
    } catch (IllegalAccessException e) {
      throw new RuntimeException("Error creating rastierizer", e);
    }
         以此将计算得到的canvas绘制成地图切片。以上就可以生成完美的地图切片了。我们来看下结果:
[置顶] ArcGIS 地图切图系列之(二)JAVA实现_第1张图片

       第四步:生成的访问地图切片的HTML

       这里通过ArcGIS api for JS;
 while (templateFileReader.readLine(line) > 0) {
        String lineStr = line.toString();
        
        //full extent
        lineStr = lineStr.replace("#{XMIN}", Double.toString(inputMBR.x1));
        lineStr = lineStr.replace("#{XMAX}", Double.toString(inputMBR.x2));
        lineStr = lineStr.replace("#{YMIN}", Double.toString(inputMBR.y1));
        lineStr = lineStr.replace("#{YMAX}", Double.toString(inputMBR.y2));
        // level of detals information
        lineStr = lineStr.replace("#{LODInfos}", lodInfoString);
        htmlOut.println(lineStr);
      }
       对模板进行参数修改。这里主要修改了地图范围和level of details information.看一下模板:
[置顶] ArcGIS 地图切图系列之(二)JAVA实现_第2张图片

       通过以上的步骤就可以完成地图切片,我们来看下结果吧:
[置顶] ArcGIS 地图切图系列之(二)JAVA实现_第3张图片
       那么点击index.html会出现什么呢,见证奇迹的时刻;
[置顶] ArcGIS 地图切图系列之(二)JAVA实现_第4张图片
      通过以上的测试,采用java语言,根据ArcGIS Server地图切片的原理,实现了地图数据的缓存过程。完结!

你可能感兴趣的:(java,server,地图,arcgis,arcgis,切片)