編譯 geotools

首先先切換到 webapps/geoserver/WEB-INF/lib 目錄底下確認版本

接著下載該版本的 geotools 並客製化 geotools 內的 java source code

切換至 geotools 目錄內,以 gt-render 編譯為例

mvn install -rf :gt-render package -Dmaven.test.skip=true

編譯完成後複製 gt-render-21.x 丟到 webapps/geoserver/WEB-INF/lib 目錄底下即可

 

 

Cesium Terrain 建置

參考文件

https://github.com/geo-data/cesium-terrain-builder

https://hub.docker.com/r/homme/cesium-terrain-builder/

https://github.com/tum-gis/cesium-terrain-builder-docker

我在 ubuntu 上面編譯好多次都失敗,最後不得不妥協使用 docker

要特別注意的是他有分新舊版本,舊版是不能 work 的,雷的很痛苦

舊版

docker pull homme/cesium-terrain-builder

新版

sudo docker pull tumgis/ctb-quantized-mesh

接著我們必須去下載 SRTM 資料集,因為全球的檔案太大我先下載台灣部分區塊測試

SRTM 90m Digital Elevation Data

看網路上這篇說明,需要把 float 轉為 int,並且把 no_data 補成 0 不然會發佈失敗,不過他這篇是 ArcGIS 做出來的,窮人只好用 gdal。

gdal_translate -of GTiff -ot Int32 -a_nodata 0 D:\srtm_61_08\srtm_61_08.tif D:\srtm_61_08\srtm_61_08_new.tif

轉換完畢後執行 docker 開始計算 terrain 這個步驟會非常久

sudo docker run -it -v /home/gg/test_terrain:/data tumgis/ctb-quantized-mesh
ctb-tile -f Mesh -C -N -o ./tw ./srtm_61_08_new.tif

最後就是新版才有的 -l 參數,他會生成一個 layer.json,一定要有這個 json 檔 Cesium 才可以讀取到 terrain 的結構

ctb-tile -f Mesh -C -N -o ./tw -l ./srtm_61_08_new.tif

接著需要寫一些 C# 的 code 並且把編譯完成的 dll 放在需要佈署的網站的 bin 目錄裡面,這個地方是最關鍵的,卡了很久,可以參考這篇說明 (如果照著他的設定 web.config 會錯誤)。

最主要的原理就是任何 web server 在接收 request 為 terrain 檔時需要在 header 加上 Content-Encoding gzip

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;

namespace AddZipHeaderModule
{
    public class ZipHeaderModule : IHttpModule
    {
        public void Dispose()
        {
            //do nothing
            //throw new NotImplementedException();
        }

        public void Init(HttpApplication context)
        {
            context.EndRequest += Context_EndRequest;
        }

        private void Context_EndRequest(object sender, EventArgs e)
        {
            var context = sender as HttpApplication;
            string fileExtension = context.Request.CurrentExecutionFilePathExtension;
            if (fileExtension.Length >= 8)
            {
                if (fileExtension.Substring(0, 8) == ".terrain")
                {
                    context.Response.AddHeader("Content-Encoding", "gzip");
                }
            }
            
        }
    }
}

搞定後要設定 web.config 如下,最後就大功告成了

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
		<validation validateIntegratedModeConfiguration="false" />
		<modules runAllManagedModulesForAllRequests="true">
			<add name="AddZipHeaderModule" type="AddZipHeaderModule.ZipHeaderModule" />
		</modules>
        <httpProtocol>
            <customHeaders>
                <remove name="Access-Control-Allwo-Origin" />
                <add name="Access-Control-Allow-Origin" value="*" />
            </customHeaders>
        </httpProtocol>
    <staticContent>
      <remove fileExtension=".czml" />
      <mimeMap fileExtension=".czml" mimeType="application/json" />
      <remove fileExtension=".glsl" />
      <mimeMap fileExtension=".glsl" mimeType="text/plain" />
      <remove fileExtension=".b3dm" />
      <mimeMap fileExtension=".b3dm" mimeType="application/octet-stream" />
      <remove fileExtension=".pnts" />
      <mimeMap fileExtension=".pnts" mimeType="application/octet-stream" />
      <remove fileExtension=".i3dm" />
      <mimeMap fileExtension=".i3dm" mimeType="application/octet-stream" />
      <remove fileExtension=".cmpt" />
      <mimeMap fileExtension=".cmpt" mimeType="application/octet-stream" />
      <remove fileExtension=".gltf" />
      <mimeMap fileExtension=".gltf" mimeType="model/gltf+json" />
      <remove fileExtension=".bgltf" />
      <mimeMap fileExtension=".bgltf" mimeType="model/gltf-binary" />
      <remove fileExtension=".glb" />
      <mimeMap fileExtension=".glb" mimeType="model/gltf-binary" />
      <remove fileExtension=".json" />
      <mimeMap fileExtension=".json" mimeType="application/json" />
      <remove fileExtension=".geojson" />
      <mimeMap fileExtension=".geojson" mimeType="application/json" />
      <remove fileExtension=".topojson" />
      <mimeMap fileExtension=".topojson" mimeType="application/json" />
      <remove fileExtension=".woff" />
      <mimeMap fileExtension=".woff" mimeType="application/font-woff" />
      <remove fileExtension=".woff2" />
      <mimeMap fileExtension=".woff2" mimeType="application/font-woff2" />
      <remove fileExtension=".kml" />
      <mimeMap fileExtension=".kml" mimeType="application/vnd.google-earth.kml+xml" />
      <remove fileExtension=".kmz" />
      <mimeMap fileExtension=".kmz" mimeType="application/vnd.google-earth.kmz" />
      <remove fileExtension=".svg" />
      <mimeMap fileExtension=".svg" mimeType="image/svg+xml" />
      <remove fileExtension=".terrain" />
      <mimeMap fileExtension=".terrain" mimeType="application/vnd.quantized-mesh" />
      <remove fileExtension=".ktx" />
      <mimeMap fileExtension=".ktx" mimeType="image/ktx" />
      <remove fileExtension=".crn" />
      <mimeMap fileExtension=".crn" mimeType="image/crn" />
      <remove fileExtension=".webm" />
      <mimeMap fileExtension=".webm" mimeType="video/webm" />
    </staticContent>
    </system.webServer>
</configuration>

後記

有種相見恨晚的感覺

http://sunhongyi.com/

定義 sld 樣式 使用 NCL color table

接續之前的 sld 燙手山芋,需要定義多組 raster 的樣式,所幸 NCL 官方有提供非常多組色表可以下載。載回來後是一個 .rgb 的纇 csv 檔案,我用 csharp 的 console 寫了一個轉換程式好讓其變成 16 進位的表,詳細過程早就忘光光等腦子清楚再寫。

static void Main(string[] args)
        {
            //讀取color文字檔
            //name , r , g , b
            //轉換 rgb 為 hex
            var files = Directory.EnumerateFiles(@"D:\rgb\", "*.rgb");
            
            foreach (var file in files)
            {
                
                var fileName = Path.GetFileNameWithoutExtension(file);
                

                var lines = File.ReadAllLines(@"D:\rgb\" + fileName + ".rgb");
                List<string> colorList = new List<string>();



                //寫入檔案
                var flag = false;
                var skipColorCount = 0;
                List<string> hexs = new List<string>();

                int skip = 2;
                int counter = 1;
                foreach (var line in lines)
                {
                    if (counter <= skip)
                    {
                        counter++;
                        continue;
                    }

                    flag = !flag;
                    if (flag == false)
                    {
                        continue;
                    }


                    //skipColorCount++;
                    //if (skipColorCount % 16 != 0)
                    //{
                    //    continue;
                    //}


                    var lineResult = line.Split(' ');
                    //string name = lineResult[0];
                    int r = Convert.ToInt32(Convert.ToDouble(lineResult[0]) * 255.0);
                    int g = Convert.ToInt32(Convert.ToDouble(lineResult[1]) * 255.0);
                    int b = Convert.ToInt32(Convert.ToDouble(lineResult[2]) * 255.0);
                    Color color = Color.FromArgb(r, g, b);

                    string hex = color.R.ToString("X2") + color.G.ToString("X2") + color.B.ToString("X2");


                    hexs.Add(hex);

                    //writer.WriteLine("#{0}", hex);

                    //writer.WriteLine(string.Format("<option value='{0}' style='background: #{1};'>{0}</option>", name, hex));


                    

                }


                using (StreamWriter writer = new StreamWriter(@"D:\rgb\" + fileName + ".txt"))
                {
                    foreach (var hex in hexs)
                    {
                        writer.WriteLine("#{0}", hex);
                    }
                }

                hexs.Reverse();
                using (StreamWriter writer = new StreamWriter(@"D:\rgb\" + fileName + "-inv.txt"))
                {
                    foreach (var hex in hexs)
                    {
                        writer.WriteLine("#{0}", hex);
                    }
                }
            }


        }

以下提供一些現成的 64 色 colormap ,可以直接套在 ncWMS 或 GeoServer 使用

Rainbow

#7E03FF
#7510FF
#6E1CFF
#6529FE
#5E35FE
#5541FD
#4E4DFC
#4559FB
#3D65FA
#376DF9
#2D7BF7
#2884F6
#1D91F3
#1898F2
#0DA5EF
#08ACEE
#03B7EB
#0AC0E8
#12C8E6
#1BCFE3
#22D6E0
#2BDDDD
#32E3DA
#3BE8D6
#42EDD3
#4BF2CF
#52F5CB
#5BF8C8
#63FBC4
#6AFDC0
#73FEBB
#7AFFB7
#83FFB3
#8AFEAE
#93FDA9
#9AFBA5
#A3F9A0
#AAF69B
#B2F396
#BBEE91
#C2EA8C
#CBE486
#D2DE81
#DBD87B
#E2D176
#EBCA70
#F2C26B
#FBB965
#FFB05F
#FFA759
#FF9D53
#FF934D
#FF8947
#FF7E41
#FF733B
#FF6835
#FF5C2F
#FF5029
#FF4422
#FF381C
#FF2C16
#FF1F10
#FF1309
#FF0603

Jet

#000084
#000096
#0000A8
#0000BB
#0000CD
#0000DF
#0000F1
#0000FF
#0004FF
#0011FF
#0024FF
#0030FF
#0044FF
#0050FF
#0065FF
#0070FF
#0085FF
#0095FF
#00A4FF
#00B4FF
#00C4FF
#00D4FF
#00E4F8
#0CF5EB
#19FFDE
#26FFD1
#33FFC4
#40FFB7
#4DFFAA
#5AFF9D
#66FF90
#73FF83
#80FF77
#8DFF6A
#9AFF5D
#A7FF50
#B4FF43
#C1FF36
#CEFF29
#DBFF1C
#E7FF0F
#F4F802
#FFEA00
#FFDB00
#FFCC00
#FFBD00
#FFAE00
#FF9F00
#FF9100
#FF8200
#FF7300
#FF6400
#FF5500
#FF4700
#FF3800
#FF2900
#FF1A00
#F60B00
#E40000
#D10000
#BF0000
#AD0000
#9B0000
#890000

Ocean

#007E01
#007805
#007209
#006C0D
#006611
#006015
#005A19
#00541D
#004E21
#004924
#004229
#003D2C
#003631
#003234
#002A39
#00263C
#001E41
#001845
#001249
#000C4D
#000651
#000055
#000659
#000C5D
#001261
#001865
#001E69
#00246D
#002A71
#003075
#003679
#003C7D
#004281
#004885
#004E89
#00548D
#005A91
#006095
#006699
#006C9D
#0072A1
#0078A5
#007EA9
#0984AD
#158AB1
#2190B5
#2D96B9
#399CBD
#45A2C1
#51A8C5
#5DAEC9
#69B4CD
#75BAD1
#81C0D5
#8DC6D9
#99CCDD
#A5D2E1
#B1D8E5
#BDDEE9
#C9E4ED
#D5EAF1
#E1F0F5
#EDF6F9
#F9FCFD

 

CoolWarm

#3C4EC2
#4055C8
#455CCE
#4A63D3
#4F69D9
#5470DE
#5977E3
#5E7DE7
#6384EB
#6788EE
#6E90F2
#7295F4
#799CF8
#7DA0F9
#84A7FC
#88ABFD
#8FB1FE
#94B6FF
#9ABBFF
#9FBFFF
#A5C3FE
#AAC7FD
#AFCAFC
#B5CDFA
#BAD0F8
#BFD3F6
#C4D5F3
#C9D7F0
#CDD9EC
#D2DBE8
#D6DCE4
#DADCE0
#DEDCDB
#E2DAD5
#E6D7CF
#EAD5C9
#EDD2C3
#EFCEBD
#F2CBB7
#F3C7B1
#F5C2AA
#F6BEA4
#F7B99E
#F7B497
#F7AF91
#F7A98B
#F6A385
#F59D7E
#F39778
#F29072
#F08A6C
#ED8366
#EA7B60
#E7745B
#E36C55
#E0654F
#DC5D4A
#D75445
#D24B40
#CD423B
#C83836
#C32E31
#BD1F2D
#B70D28

 

 

sld 初探

因為接了燙手山芋共有大概有 N 百種以上的資料來源,然後每個資料來源又區分 N 種樣式,所以必須要自己定義 sld 這鬼玩兒,不然預設的 raster 樣式看起來會黑嚕嚕一片,定義過的則比較像是人在看的。

經過一翻偷懶可以先用 QGIS 開起來吸取顏色,之後再貼到 raster 的 template 裡面就可以算大功告成。比較重要的參數大概就是 color 跟 quantity 依照資料的數值去對應到顏色的漸層,此外 sld 還有許的的 function 及技巧但太過燒腦,後續想到再寫。

<?xml version="1.0" encoding="ISO-8859-1"?>
<StyledLayerDescriptor version="1.0.0" 
    xsi:schemaLocation="http://www.opengis.net/sld StyledLayerDescriptor.xsd" 
    xmlns="http://www.opengis.net/sld" 
    xmlns:ogc="http://www.opengis.net/ogc" 
    xmlns:xlink="http://www.w3.org/1999/xlink" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <NamedLayer>
    <Name>Two color gradient</Name>
    <UserStyle>
      <Title>SLD Cook Book: Two color gradient</Title>
      <FeatureTypeStyle>
        <Rule>
          <RasterSymbolizer>
            <ColorMap type="ramp">
        <ColorMapEntry color="#ca0020" quantity="0" label="label" opacity="1"/>
        <ColorMapEntry color="#f4a582" quantity="0.5" label="values" opacity="1"/>
        <ColorMapEntry color="#f7f7f7" quantity="1" label="label" opacity="1"/>
        <ColorMapEntry color="#92c5de" quantity="2" label="label" opacity="1"/>
        <ColorMapEntry color="#0571b0" quantity="3" label="label" opacity="1"/>

</ColorMap>
          </RasterSymbolizer>
        </Rule>
      </FeatureTypeStyle>
    </UserStyle>
  </NamedLayer>
</StyledLayerDescriptor>

prismjs 踩雷

為了要學習 wordpress 及記錄過去踩的雷坑,在貼程式碼上面造成了困擾,後來發現了 prismjs 這神器。可以將語法貼得很漂亮,不過在我貼程式碼時會出現討人厭的換行因此需要把 <pre><code> 融合作為一行才可以正常運作。要合為一行可以使用 TexttoOneLine 線上工具。

另外就是我的 WordPress 為 5 以上的版本,安裝了 Prism 的外掛根本不啟用,以致張貼時都要自己手 key ,後來安裝了舊版的編輯文章外掛就搞定了。