關閉
標題:dem grd hdr 轉 tiff mapserver 發地形圖- 圓滑版 -- 這版不好
內容:
<?php
// grd_to_tif.php
function my_pathinfo($path)
{
$dirname = '';
$basename = '';
$extension = '';
$filename = '';
$pos = strrpos($path, '/');
if($pos !== false) {
$dirname = substr($path, 0, strrpos($path, '/'));
$basename = substr($path, strrpos($path, '/') + 1);
} else {
$basename = $path;
}
$ext = strrchr($path, '.');
if($ext !== false) {
$extension = substr($ext, 1);
}
$filename = $basename;
$pos = strrpos($basename, '.');
if($pos !== false) {
$filename = substr($basename, 0, $pos);
}
return array (
'dirname' => $dirname,
'basename' => $basename,
'extension' => $extension,
'filename' => $filename
);
}
function subname($fname){
//$pathinfo=pathinfo($fname);
//$pathinfo['extension'];
$m=explode(".",$fname);
return end($m);
}
function mainname($fname){
$pathinfo=my_pathinfo($fname);
//print_r($pathinfo);
//exit();
return $pathinfo['filename'];
}
$EPSG = "EPSG:3826";
$DX = 20; $DY = 20;
$NODATA = -32768; // 你原本用的 nodata
$RADIUS = 30; // 20m DEM 建議 20~30
$fp = glob("*.grd");
$max_k = count($fp);
foreach($fp as $k => $v){
$bn = basename($v);
$mn = mainname($v);
// 1) grd -> csv(逐行轉,避免空白/多欄位)
$csv = "{$mn}.csv";
if(!is_file($csv)){
$in = fopen($v, "rb");
$out = fopen($csv, "wb");
fwrite($out, "X,Y,Z\n");
while(!feof($in)){
$line = fgets($in);
if($line===false) break;
$line = trim(str_replace("\r","", $line));
if($line==="") continue;
$parts = preg_split('/\s+/', $line);
if(count($parts) < 3) continue;
fwrite($out, $parts[0].",".$parts[1].",".$parts[2]."\n");
}
fclose($in); fclose($out);
}
// 2) csv -> OGRVRT (強制幾何 + 指定 SrcLayer)
// CSV 的 layer 名通常就是檔名(不含副檔名)
$vrt = "{$mn}.vrt";
if(!is_file($vrt)){
$vrt_xml = <<<EOF
<OGRVRTDataSource>
<OGRVRTLayer name="dem">
<SrcDataSource relativeToVRT="1">{$mn}.csv</SrcDataSource>
<SrcLayer>{$mn}</SrcLayer>
<GeometryType>wkbPoint</GeometryType>
<LayerSRS>{$EPSG}</LayerSRS>
<GeometryField encoding="PointFromColumns" x="X" y="Y" z="Z"/>
</OGRVRTLayer>
</OGRVRTDataSource>
EOF;
file_put_contents($vrt, $vrt_xml);
}
// 3) 掃 min/max 範圍(用來給 gdal_grid 的 -txe/-tye/-outsize)
// 這一步可以省略,但你要格網正確,最好做
$xmin=$ymin=null; $xmax=$ymax=null;
$fh = fopen($v, "rb");
while(!feof($fh)){
$line = fgets($fh);
if($line===false) break;
$line = trim(str_replace("\r","",$line));
if($line==="") continue;
$p = preg_split('/\s+/', $line);
if(count($p) < 3) continue;
$x = floatval($p[0]); $y = floatval($p[1]);
if($xmin===null){ $xmin=$xmax=$x; $ymin=$ymax=$y; }
else{
if($x<$xmin) $xmin=$x;
if($x>$xmax) $xmax=$x;
if($y<$ymin) $ymin=$y;
if($y>$ymax) $ymax=$y;
}
}
fclose($fh);
// 4) extent 對齊 20m 格點(避免像素變 19.x)
$xmin = floor($xmin/$DX)*$DX;
$ymin = floor($ymin/$DY)*$DY;
$xmax = ceil($xmax/$DX)*$DX;
$ymax = ceil($ymax/$DY)*$DY;
$cols = (int)(($xmax-$xmin)/$DX) + 1;
$rows = (int)(($ymax-$ymin)/$DY) + 1;
// 5) gdal_grid 產 tif(這才是正確的 XYZ->raster)
$tif = "{$mn}.tif";
if(!is_file($tif)){
// 注意:-tye 要 ymax ymin,才能確保 PixelSize Y 為負
$CMD = "gdal_grid -a_srs {$EPSG} -of GTiff -zfield Z ".
"-a nearest:radius1={$RADIUS}:radius2={$RADIUS}:nodata={$NODATA} ".
"-txe {$xmin} {$xmax} -tye {$ymax} {$ymin} -outsize {$cols} {$rows} ".
"\"{$vrt}\" \"{$tif}\"";
echo $CMD, "\n";
`$CMD`;
}
// 6) warp 統一到 20m 格網(tap),順便把 nodata 固定好
$fix = "{$mn}_fix.tif";
if(!is_file($fix)){
$CMD = "gdalwarp -overwrite -r near -tr 20 20 -tap ".
"-srcnodata {$NODATA} -dstnodata {$NODATA} ".
"\"{$tif}\" \"{$fix}\"";
echo $CMD, "\n";
`$CMD`;
}
// 7) 平滑(cubic)一定要帶 src/dst nodata,否則邊界會抹出怪值
$smooth = "{$mn}_smooth.tif";
if(!is_file($smooth)){
$CMD = "gdalwarp -overwrite -r cubic ".
"-srcnodata {$NODATA} -dstnodata {$NODATA} ".
"\"{$fix}\" \"{$smooth}\"";
echo $CMD, "\n";
`$CMD`;
}
echo sprintf("%d / %d ...\n", ($k+1), $max_k);
}
// Windows 才有 dir /b;若在 Linux 要改成 ls
`dir /b *_fix.tif > list.txt`;
`gdalbuildvrt -input_file_list list.txt all.vrt`;
// 先整張統一(避免縫)
`gdalwarp -overwrite -r near -tr 20 20 -tap -srcnodata -32768 -dstnodata -32768 all.vrt all_aligned.tif`;
// 想圓滑:整張做一次 cubic(比每片做更不容易放大接縫)
`gdalwarp -overwrite -r cubic -srcnodata -32768 -dstnodata -32768 all_aligned.tif all_smooth.tif`;
// 等高線(10m)
`gdal_contour -i 10 -a elev all_smooth.tif contour_10m.gpkg`;
// 匯出 SQLite,幾何欄位 GEOMETRY
`ogr2ogr -f SQLITE 8429.db contour_10m.gpkg -s_srs EPSG:3826 -t_srs EPSG:4326 -nln 8429 -lco GEOMETRY_NAME=GEOMETRY`;