package com.se.simu.helper;
|
|
import cn.hutool.core.io.FileUtil;
|
import cn.hutool.json.JSONArray;
|
import cn.hutool.json.JSONObject;
|
import com.se.simu.domain.dto.GeField;
|
import com.se.simu.domain.dto.GeLayer;
|
import lombok.extern.slf4j.Slf4j;
|
import org.gdal.gdal.Dataset;
|
import org.gdal.gdal.gdal;
|
import org.gdal.gdalconst.gdalconst;
|
import org.gdal.ogr.*;
|
import org.gdal.osr.SpatialReference;
|
|
import java.sql.Timestamp;
|
import java.time.LocalDateTime;
|
import java.util.List;
|
import java.util.Map;
|
import java.util.Vector;
|
|
@Slf4j
|
@SuppressWarnings("ALL")
|
public class ShpHelper {
|
private static Vector<String> options;
|
|
public static Vector<String> getOptions() {
|
if (null == options) {
|
options = new Vector<>();
|
options.add("ENCODING=UTF-8");
|
}
|
|
return options;
|
}
|
|
public static boolean createShp(String filePath, Map<String, Object> map, SpatialReference sr, Double minx, Double miny, Double maxx, Double maxy) {
|
Driver driver = null;
|
DataSource dataSource = null;
|
Layer layer = null;
|
try {
|
driver = ogr.GetDriverByName("ESRI shapefile");
|
if (null == driver) return false;
|
|
dataSource = driver.CreateDataSource(filePath, null);
|
if (null == dataSource) return false;
|
|
layer = dataSource.CreateLayer(FileUtil.getName(filePath), sr, ogr.wkbPolygon, getOptions());
|
if (null == layer) return false;
|
|
if (null != map) createFields(layer, map);
|
|
Feature f = new Feature(layer.GetLayerDefn());
|
Geometry g = createPolygon(sr, minx, miny, maxx, maxy);
|
f.SetGeometry(g);
|
if (null != map) setValues(f, map);
|
|
layer.CreateFeature(f);
|
|
return true;
|
} catch (Exception ex) {
|
log.error(ex.getMessage(), ex);
|
return false;
|
} finally {
|
GdalHelper.delete(layer, dataSource, driver);
|
}
|
}
|
|
private static void createFields(Layer layer, Map<String, Object> map) {
|
for (String key : map.keySet()) {
|
Object val = map.get(key);
|
switch (val.getClass().getTypeName()) {
|
//case "java.math.BigDecimal":
|
case "java.lang.Double":
|
case "double":
|
layer.CreateField(new FieldDefn(key, ogr.OFTReal));
|
break;
|
case "java.lang.Long":
|
case "long":
|
layer.CreateField(new FieldDefn(key, ogr.OFTInteger64));
|
break;
|
case "java.lang.Integer":
|
case "int":
|
layer.CreateField(new FieldDefn(key, ogr.OFTInteger));
|
break;
|
//case "java.sql.Timestamp":
|
//case "java.time.LocalDate":
|
// layer.CreateField(new FieldDefn(key, ogr.OFTDateTime));
|
// break;
|
default:
|
layer.CreateField(new FieldDefn(key, ogr.OFTString));
|
break;
|
}
|
}
|
}
|
|
private static void setValues(Feature f, Map<String, Object> map) {
|
for (String key : map.keySet()) {
|
Object val = map.get(key);
|
switch (val.getClass().getTypeName()) {
|
case "java.lang.Double":
|
case "double":
|
f.SetField(key, Double.parseDouble(val.toString()));
|
break;
|
case "java.lang.Long":
|
case "long":
|
f.SetField(key, Long.parseLong(val.toString()));
|
break;
|
case "java.lang.Integer":
|
case "int":
|
f.SetField(key, Integer.parseInt(val.toString()));
|
break;
|
default:
|
f.SetField(key, val.toString());
|
break;
|
}
|
}
|
}
|
|
public static Geometry createPolygon(SpatialReference sr, Double minx, Double miny, Double maxx, Double maxy) {
|
String epsg = sr.GetAuthorityCode(null);
|
if (!("4326".equals(epsg) || "4490".equals(epsg))) {
|
double[] dmin = GdalHelper.fromWgs84(sr, minx, miny);
|
double[] dmax = GdalHelper.fromWgs84(sr, maxx, maxy);
|
minx = dmin[0];
|
miny = dmin[1];
|
maxx = dmax[0];
|
maxy = dmax[1];
|
}
|
|
Geometry ring = new Geometry(ogr.wkbLinearRing);
|
ring.AddPoint_2D(minx, maxy);
|
ring.AddPoint_2D(maxx, maxy);
|
ring.AddPoint_2D(maxx, miny);
|
ring.AddPoint_2D(minx, miny);
|
ring.AddPoint_2D(minx, maxy);
|
|
Geometry poly = new Geometry(ogr.wkbPolygon);
|
poly.AddGeometry(ring);
|
poly.AssignSpatialReference(sr);
|
|
return poly;
|
}
|
|
public static boolean createShp(String filePath, GeLayer geLayer) {
|
Driver driver = null;
|
DataSource dataSource = null;
|
Layer layer = null;
|
try {
|
driver = ogr.GetDriverByName("ESRI shapefile");
|
if (null == driver) return false;
|
|
dataSource = driver.CreateDataSource(filePath, null);
|
if (null == dataSource) return false;
|
|
int geoType = getGeometryType(geLayer.getQueryType());
|
layer = dataSource.CreateLayer(FileUtil.getName(filePath), geLayer.getDb().getSpatialReference(), geoType, getOptions());
|
if (null == layer) return false;
|
|
createLayerFields(layer, geLayer.getFields());
|
|
FeatureDefn featureDefn = layer.GetLayerDefn();
|
for (int i = 0, c = geLayer.getData().size(); i < c; i++) {
|
Feature f = new Feature(featureDefn);
|
JSONObject data = geLayer.getData().getJSONObject(i).getJSONObject("properties");
|
setFeatureData(f, geLayer.getFields(), data);
|
|
JSONObject geom = geLayer.getData().getJSONObject(i).getJSONObject("geometry");
|
Geometry g = createGeometry(geLayer, geom);
|
f.SetGeometry(g);
|
|
layer.CreateFeature(f);
|
}
|
|
return true;
|
} catch (Exception ex) {
|
log.error(ex.getMessage(), ex);
|
return false;
|
} finally {
|
GdalHelper.delete(layer, dataSource, driver);
|
}
|
}
|
|
private static void setFeatureData(Feature f, List<GeField> fields, JSONObject data) {
|
for (int i = 0, c = fields.size(); i < c; i++) {
|
GeField geField = fields.get(i);
|
switch (geField.getType()) {
|
case "int":
|
f.SetField(i, data.getInt(geField.getName()));
|
break;
|
case "long":
|
f.SetField(i, data.getLong(geField.getName()));
|
break;
|
case "double":
|
f.SetField(i, data.getDouble(geField.getName()));
|
break;
|
case "datetime":
|
long date = data.getLong(geField.getName());
|
Timestamp time = new Timestamp(date);
|
setTimestamp(f, i, time);
|
break;
|
default:
|
f.SetField(i, data.getStr(geField.getName()));
|
break;
|
}
|
}
|
}
|
|
private static void setTimestamp(Feature f, int i, Timestamp time) {
|
if (null == time) return;
|
|
LocalDateTime local = time.toLocalDateTime();
|
f.SetField(i, local.getYear(), local.getMonthValue(), local.getDayOfMonth(), local.getHour(), local.getMinute(), local.getSecond(), 8);
|
}
|
|
public static Geometry createGeometry(GeLayer geLayer, JSONObject geom) {
|
String type = geom.getStr("type");
|
JSONArray cs = geom.getJSONArray("coordinates");
|
|
Geometry g = null;
|
switch (type) {
|
case "Point":
|
g = new Geometry(ogr.wkbPoint);
|
g.AddPoint_2D(cs.getDouble(0), cs.getDouble(1));
|
break;
|
case "MultiLineString":
|
g = new Geometry(ogr.wkbMultiLineString);
|
for (int i = 0, c = cs.size(); i < c; i++) {
|
Geometry line = new Geometry(ogr.wkbLineString);
|
JSONArray lineArr = cs.getJSONArray(i);
|
for (int j = 0, d = lineArr.size(); j < d; j++) {
|
JSONArray arr = lineArr.getJSONArray(j);
|
line.AddPoint_2D(arr.getDouble(0), arr.getDouble(1));
|
}
|
g.AddGeometry(line);
|
}
|
break;
|
case "MultiPolygon":
|
g = new Geometry(ogr.wkbMultiPolygon);
|
for (int i = 0, c = cs.size(); i < c; i++) {
|
Geometry poly = new Geometry(ogr.wkbPolygon);
|
JSONArray polyArr = cs.getJSONArray(i);
|
for (int j = 0, d = polyArr.size(); j < d; j++) {
|
Geometry ring = new Geometry(ogr.wkbLinearRing);
|
JSONArray ringArr = polyArr.getJSONArray(j);
|
for (int k = 0, e = ringArr.size(); k < e; k++) {
|
JSONArray arr = ringArr.getJSONArray(k);
|
ring.AddPoint_2D(arr.getDouble(0), arr.getDouble(1));
|
}
|
poly.AddGeometry(ring);
|
}
|
g.AddGeometry(poly);
|
}
|
break;
|
}
|
return g;
|
}
|
|
private static int getGeometryType(String type) {
|
switch (type) {
|
case "point":
|
return ogr.wkbPoint;
|
case "polyline":
|
return ogr.wkbMultiLineString;
|
case "polygon":
|
return ogr.wkbMultiPolygon;
|
default:
|
return ogr.wkbUnknown;
|
}
|
}
|
|
private static void createLayerFields(Layer layer, List<GeField> fields) {
|
for (int i = 0, c = fields.size(); i < c; i++) {
|
GeField f = fields.get(i);
|
FieldDefn fd = new FieldDefn(f.getName(), getFieldType(f));
|
|
layer.CreateField(fd, i);
|
}
|
}
|
|
private static Integer getFieldType(GeField f) {
|
switch (f.getType()) {
|
case "int":
|
return ogr.OFTInteger;
|
case "long":
|
return ogr.OFTInteger64;
|
case "double":
|
return ogr.OFTReal;
|
case "datetime":
|
return ogr.OFTDateTime;
|
default:
|
return ogr.OFTString;
|
}
|
}
|
|
private String getEpsg(SpatialReference sr) {
|
return sr.GetAuthorityCode(null);
|
}
|
|
public static boolean polygonize2Shp(Dataset ds, String filePath) {
|
Driver driver = null;
|
DataSource dataSource = null;
|
Layer layer = null;
|
try {
|
driver = ogr.GetDriverByName("ESRI shapefile");
|
if (null == driver) return false;
|
|
dataSource = driver.CreateDataSource(filePath, null);
|
if (null == dataSource) return false;
|
|
layer = dataSource.CreateLayer(FileUtil.getName(filePath), ds.GetSpatialRef(), ogr.wkbPolygon, getOptions());
|
if (null == layer) return false;
|
|
layer.CreateField(new FieldDefn("val", ogr.OFTReal));
|
|
gdal.Polygonize(ds.GetRasterBand(1), ds.GetRasterBand(1).GetMaskBand(), layer, 0);
|
|
return true;
|
} catch (Exception ex) {
|
log.error(ex.getMessage(), ex);
|
return false;
|
} finally {
|
GdalHelper.delete(layer, dataSource, driver);
|
}
|
}
|
|
public static boolean polygonize2Geojson(Dataset ds, String filePath) {
|
Driver driver = null;
|
DataSource dataSource = null;
|
Layer layer = null;
|
try {
|
driver = ogr.GetDriverByName("GeoJSON");
|
if (null == driver) return false;
|
|
dataSource = driver.CreateDataSource(filePath, null);
|
if (null == dataSource) return false;
|
|
layer = dataSource.CreateLayer(FileUtil.getName(filePath), ds.GetSpatialRef(), ogr.wkbPolygon);
|
if (null == layer) return false;
|
|
layer.CreateField(new FieldDefn("val", ogr.OFTReal));
|
|
gdal.Polygonize(ds.GetRasterBand(1), ds.GetRasterBand(1).GetMaskBand(), layer, 0);
|
|
return true;
|
} catch (Exception ex) {
|
log.error(ex.getMessage(), ex);
|
return false;
|
} finally {
|
GdalHelper.delete(layer, dataSource, driver);
|
}
|
}
|
|
public static void test() {
|
String path = "D:\\simu\\out\\20241010095328\\waters\\1730217635000\\";
|
|
Dataset ds = gdal.Open(path + "water.tif", gdalconst.GA_ReadOnly);
|
ds.SetSpatialRef(GdalHelper.createSpatialReference(4548));
|
polygonize2Geojson(ds, path + "water.geojson");
|
}
|
}
|