通过GeoServer发布ArcGIS Server切片/CesiumLab切片

首先吐槽下GeoServer(其实是GeoWebCache)的切片保存路径竟然如此奇葩,且不可配置,即不能迁移到其他系统,也不能发布其他系统生产的切片(虽然GeoWebCache有对ArcGIS Server切片的插件,但那个东西却无法和GeoServer集成)。这种情况似乎将在下个版本(GeoServer2.17/GeoWebCache1.17)中有所改善,加入了对TMS切片的支持,其切片路径是我们熟悉的{z}/{x}/{y},但这并不能满足我们的需求,首先它是TMS切片,与WMTS切片在y方向相反;其次我们想要的就是随心所欲。

看来短时间内指望GeoServer在这方面有所改观是不太可能了,于是,只好自己来写一个扩展吧,希望可以让GeoServer实现通过配置路径模板的方式来适应其他类型切片,如ArcGIS或者Cesiumlab。

1、首先下载插件(今天才发现,简书竟然不能上传文件,先上传到百度云吧)

链接:https://pan.baidu.com/s/16R5yIxh5Jz32fyi08qCixA

提取码:rn1p

将下载到的custom-filestroe-1.0-SNAPSHOT.jar,放到<geoserver>\webapps\geoserver\WEB-INF\lib中,重启geoserver。

2、配置BlobStore,在Add  new BlobStore页面选择Custom FileStore,页面如下。


通过设置路径模板参数来匹配切片路径,如ArcGIS Server的切片路径是这样的:LayerName\L03\R00000002\C00000005.png,那么这里需要这样填写:{layer}\L{level:%02d}\R{row:%08x}\C{col:%08x}

而Cesiumlab切片路径是这样的:LayerName\{z}\{x}\{y}.png,则这里需要这样赶写:{layer}\{level:%d}\{col:%d}\{row:%d}

3、发布切片。在geoserver中的geowebcache.xml文件中添加一个wmsLayer:

<wmsLayer>

      <blobStoreId>arcgis</blobStoreId>

      <enabled>true</enabled>

      <name>33</name>

      <mimeFormats>

        <string>image/jpeg</string>

      </mimeFormats>

      <gridSubsets>

        <gridSubset>

          <gridSetName>EPSG:900913</gridSetName>

          <extent>

            <coords>

              <double>8176078.237521</double>

              <double>704818.027536</double>

              <double>1.5037685885628E7</double>

              <double>7086873.419584</double>

            </coords>

          </extent>

        </gridSubset>

      </gridSubsets>

      <wmsUrl>

        <string>http://localhost:8081/geoserver/wms?</string>

      </wmsUrl>

    </wmsLayer>

其中,blobStoreId是第二步中所配置的BlobStore的Identifier;name为图层名称;mimeFormats为切片的mineType;gridSubsets配置EPSG和对应的坐标范围。

4、浏览。在GeoServer的Tile Layers页面找到刚刚配置的图层。


在PreView下拉列表中选择对应的EPSG/mineType,跳转到预览页面,如下:


此插件应该能自动匹配大多数切片路径,但像GeoServer这样奇葩的路径,这里不!兼!容!

5、核心代码 :该插件代码非常简单,简单到不好意思将其作为一个项目开源出来,就把其核心代码贴到下面吧:

public File tilePath(TileObject tile, MimeType mimeType) {

final long[] tileIndex = tile.getXYZ();

long x = tileIndex[0];

int z = (int) tileIndex[2];

long y =0;

try {

y = getY(tile.getLayerName(), tile.getGridSetId(), x, tileIndex[1], z);

}catch (GeoWebCacheException e) {

e.printStackTrace();

return null;

}

StringBuilder path =new StringBuilder(256);

String fileExtension = mimeType.getFileExtension();

path.append(cacheRoot);

path.append(File.separatorChar);

String layer = tile.getLayerName();

String[] wl = layer.split(":");

String templatePath ="";

if(wl.length ==2){

templatePath =template.replace("{workspace}",wl[0]);

templatePath =template.replace("{layer}",wl[1]);

}

else{

templatePath =template.replace("{workspace}","");

templatePath =template.replace("{layer}",layer);

}

templatePath = templatePath.replace("{gridset}", tile.getGridSetId());

long shift = z /2;

long half =2 << shift;

int digits =1;

if (half >10) {

digits = (int) (Math.log10(half)) +1;

}

long halfx = x / half;

long halfy = y / half;

templatePath = templatePath.replace("{halfx}",zeroPadder(halfx, digits));

templatePath = templatePath.replace("{halfy}",zeroPadder(halfy, digits));

String levelPattern ="\\{level:([^}]*)\\}";

String levelTemplate = getString(templatePath,levelPattern);

String rowPattern ="\\{row:([^}]*)\\}";

String rowTemplate = getString(templatePath,rowPattern);

String colPattern ="\\{col:([^}]*)\\}";

String colTemplate = getString(templatePath,colPattern);

String level = String.format(levelTemplate, z);

templatePath = templatePath.replace(levelTemplate, level.substring(7,level.length() -1));

String row = String.format(rowTemplate, y);

templatePath = templatePath.replace(rowTemplate, row.substring(5,row.length() -1));

String col = String.format(colTemplate, x);

templatePath = templatePath.replace(colTemplate, col.substring(5,col.length() -1));

path.append(templatePath);

path.append('.');

path.append(fileExtension);

File tileFile =new File(path.toString());

if(!tileFile.exists()){

if(fileExtension.toLowerCase() =="jpeg"){

tileFile =new File(path.toString().replace("jpeg","jpg"));

}

}

return tileFile;

}

本想基于GeoServer2.17版本开发,但2.17版本在BlobStore方面做了比较大的修改,因此只好基于现有版本GeoServer2.16开发。

谨以此篇为自己2019年的工作画一个句号,并恭祝大家2020年万事如意!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容