|
@@ -0,0 +1,360 @@
|
|
|
+package com.onemap.spatial.util;
|
|
|
+
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
+import org.geotools.data.DataStore;
|
|
|
+import org.geotools.data.DataStoreFinder;
|
|
|
+import org.geotools.data.FeatureSource;
|
|
|
+import org.geotools.data.shapefile.ShapefileDataStore;
|
|
|
+import org.geotools.data.store.ContentFeatureCollection;
|
|
|
+import org.geotools.data.store.ContentFeatureSource;
|
|
|
+import org.geotools.feature.FeatureCollection;
|
|
|
+import org.geotools.feature.FeatureIterator;
|
|
|
+import org.geotools.geometry.jts.ReferencedEnvelope;
|
|
|
+import org.geotools.referencing.CRS;
|
|
|
+import org.locationtech.jts.geom.Envelope;
|
|
|
+import org.locationtech.jts.geom.Geometry;
|
|
|
+import org.opengis.feature.GeometryAttribute;
|
|
|
+import org.opengis.feature.Property;
|
|
|
+import org.opengis.feature.simple.SimpleFeature;
|
|
|
+import org.opengis.feature.simple.SimpleFeatureType;
|
|
|
+import org.opengis.filter.Filter;
|
|
|
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
|
|
|
+
|
|
|
+import java.io.File;
|
|
|
+import java.io.IOException;
|
|
|
+import java.net.MalformedURLException;
|
|
|
+import java.nio.charset.Charset;
|
|
|
+import java.nio.charset.StandardCharsets;
|
|
|
+import java.util.*;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+public class ShapeFileUtil {
|
|
|
+ /**
|
|
|
+ * convert shpFileType to db field type
|
|
|
+ * 备注:目前arcgis的字段类型有:短整型 长整型 浮点型 双精度 文本 日期
|
|
|
+ *
|
|
|
+ * @param value
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public static String convertShpFieldType2H2GISOrPG(Class value) throws Exception {
|
|
|
+ if (value == String.class) {//文本
|
|
|
+ return "varchar";
|
|
|
+ }
|
|
|
+ if (value == Integer.class) {//短整型
|
|
|
+ return "int";
|
|
|
+ }
|
|
|
+ if (value == Long.class) {//长整型
|
|
|
+ return "bigint";
|
|
|
+ }
|
|
|
+ if (value == Double.class || value == Float.class) {//浮点型 双精度 保留精度,比如在金币上运算更安全
|
|
|
+ return "numeric";
|
|
|
+ }
|
|
|
+ if (value == Date.class) {
|
|
|
+ return "TIMESTAMP WITH TIME ZONE ";//日期, 使用包含时区的来处理
|
|
|
+ }
|
|
|
+ if (Geometry.class.isAssignableFrom(value)) {
|
|
|
+ return "geometry";
|
|
|
+ }
|
|
|
+ //除了上述,真不知道还会有啥了。除非arcgis的shp又增加了新类型?!那无能为力了,抛出异常吧
|
|
|
+ throw new Exception("不支持的类型!" + value.getName());
|
|
|
+ //
|
|
|
+// if (value.getSuperclass().getName().equals(String.class))
|
|
|
+
|
|
|
+// return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 读取shp的bbox并返回
|
|
|
+ *
|
|
|
+ * @param filePaths
|
|
|
+ * @return GeomAttrWrapper.bboxMap属性中存储每个shp对应的bbox
|
|
|
+ * @throws IOException
|
|
|
+ */
|
|
|
+ public static GeomAttrWrapper readBboxFromFile(List<String> filePaths) throws IOException {
|
|
|
+ Map<String, Envelope> bboxMap = new HashMap<>();
|
|
|
+ for (String filePath : filePaths) {
|
|
|
+ if (!filePath.endsWith(".shp")) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ File file = new File(filePath);
|
|
|
+ Map<String, Object> map = new HashMap<>();
|
|
|
+ map.put("url", file.toURI().toURL());
|
|
|
+
|
|
|
+ ShapefileDataStore dataStore = new ShapefileDataStore(file.toURI().toURL());//DataStoreFinder.getDataStore(map);
|
|
|
+ dataStore.setCharset(Charset.forName("GBK"));
|
|
|
+ String typeName = dataStore.getTypeNames()[0];
|
|
|
+
|
|
|
+ FeatureSource<SimpleFeatureType, SimpleFeature> source =
|
|
|
+ dataStore.getFeatureSource(typeName);
|
|
|
+ Filter filter = Filter.INCLUDE; // ECQL.toFilter("BBOX(THE_GEOM, 10,20,30,40)")
|
|
|
+ FeatureCollection<SimpleFeatureType, SimpleFeature> collection = source.getFeatures(filter);
|
|
|
+ bboxMap.put(filePath, collection.getBounds());
|
|
|
+// final CoordinateReferenceSystem coordinateReferenceSystem = collection.getBounds().getCoordinateReferenceSystem();
|
|
|
+// final String crsCode = CRS.toSRS(coordinateReferenceSystem, true);
|
|
|
+ dataStore.dispose();
|
|
|
+ }
|
|
|
+
|
|
|
+ return new GeomAttrWrapper(null, null, bboxMap);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 从shp文件中读取geometry和属性字段数据
|
|
|
+ *
|
|
|
+ * @param filePaths shp文件在磁盘下的绝对路径
|
|
|
+ * @param returnAllAttrs 若为true,则返回全部的属性;若为false,则提取filterAttrs中指定的属性和geometry;filterAttrs为null或者空,则只提取geometry
|
|
|
+ * @param filterAttrs 用于过滤出希望返回的属性
|
|
|
+ * @return GeomAttrWrapper
|
|
|
+ * @throws Exception
|
|
|
+ */
|
|
|
+ public static GeomAttrWrapper readShapeAndFieldsFromFile(List<String> filePaths, boolean returnAllAttrs, Set<String> filterAttrs) throws Exception {
|
|
|
+ Map<String, List<ShpGeomWithAttr>> geoMap = new HashMap<>();
|
|
|
+ Map<String, Envelope> bboxMap = new HashMap<>();
|
|
|
+ boolean getExpectedAttrs = filterAttrs != null && filterAttrs.size() > 0 ? true : false;
|
|
|
+ Map<String, Class> attrTypes = new HashMap<>();
|
|
|
+ for (String filePath : filePaths) {
|
|
|
+ if (!filePath.endsWith(".shp")) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ List<ShpGeomWithAttr> geometries = new ArrayList<>();
|
|
|
+ File file = new File(filePath);
|
|
|
+ Map<String, Object> map = new HashMap<>();
|
|
|
+ map.put("url", file.toURI().toURL());
|
|
|
+
|
|
|
+ ShapefileDataStore dataStore = new ShapefileDataStore(file.toURI().toURL());//DataStoreFinder.getDataStore(map);
|
|
|
+ dataStore.setCharset(Charset.forName("UTF-8"));
|
|
|
+ String typeName = dataStore.getTypeNames()[0];
|
|
|
+
|
|
|
+ FeatureSource<SimpleFeatureType, SimpleFeature> source =
|
|
|
+ dataStore.getFeatureSource(typeName);
|
|
|
+ Filter filter = Filter.INCLUDE; // ECQL.toFilter("BBOX(THE_GEOM, 10,20,30,40)")
|
|
|
+ FeatureCollection<SimpleFeatureType, SimpleFeature> collection = source.getFeatures(filter);
|
|
|
+ bboxMap.put(filePath, collection.getBounds());
|
|
|
+ final CoordinateReferenceSystem coordinateReferenceSystem = collection.getBounds().getCoordinateReferenceSystem();
|
|
|
+ final String crsCode = CRS.toSRS(coordinateReferenceSystem, true);
|
|
|
+ int srid = 0;
|
|
|
+ try {
|
|
|
+ srid = Integer.parseInt(crsCode);
|
|
|
+ } catch (NumberFormatException e) {//有时候,prj文件中没有出现’AUTHORITY["EPSG",4326]‘,就会解不了srid的int出来,就会报错,此时就不管它了,没办法
|
|
|
+// e.printStackTrace();
|
|
|
+ }
|
|
|
+ try (FeatureIterator<SimpleFeature> features = collection.features()) {
|
|
|
+ while (features.hasNext()) {
|
|
|
+ SimpleFeature feature = features.next();
|
|
|
+ final GeometryAttribute geometryProperty = feature.getDefaultGeometryProperty();
|
|
|
+ Object value = geometryProperty.getValue();
|
|
|
+ if (value instanceof Geometry) {
|
|
|
+ Geometry geometry = (Geometry) value;
|
|
|
+ geometry.setSRID(srid);
|
|
|
+ Map<String, Object> properties = null;
|
|
|
+ if (returnAllAttrs) {// 全都返回,则直接全都返回
|
|
|
+ final Collection<Property> prps = feature.getProperties();
|
|
|
+ properties = new HashMap<>(prps.size());
|
|
|
+ for (Property prp : prps) {
|
|
|
+ final String name = prp.getName().getLocalPart().toLowerCase(Locale.ROOT);
|
|
|
+ properties.put(name, prp.getValue());
|
|
|
+ final Class type = attrTypes.get(name);
|
|
|
+ if (type == null) {
|
|
|
+ attrTypes.put(name, prp.getType().getBinding());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else if (getExpectedAttrs) {
|
|
|
+ properties = new HashMap<>(filterAttrs.size());
|
|
|
+ final Collection<Property> prps = feature.getProperties();
|
|
|
+ for (Property prp : prps) {
|
|
|
+ final String name = prp.getName().getLocalPart().toLowerCase(Locale.ROOT);
|
|
|
+ if (filterAttrs.contains(name)) {
|
|
|
+ properties.put(name, prp.getValue());
|
|
|
+ final Class type = attrTypes.get(name);
|
|
|
+ if (type == null) {
|
|
|
+ attrTypes.put(name, prp.getType().getBinding());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ShpGeomWithAttr shpGeomWithAttr = new ShpGeomWithAttr(geometry, properties);
|
|
|
+ geometries.add(shpGeomWithAttr);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ //do nothing...
|
|
|
+ }
|
|
|
+ dataStore.dispose();
|
|
|
+ geoMap.put(filePath, geometries);
|
|
|
+ }
|
|
|
+
|
|
|
+ return new GeomAttrWrapper(geoMap, attrTypes, bboxMap);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 从shp文件中读取geometry数据
|
|
|
+ *
|
|
|
+ * @param filePaths shp文件在磁盘下的绝对路径
|
|
|
+ * @return
|
|
|
+ * @throws Exception
|
|
|
+ */
|
|
|
+ public static Map<String, List<Geometry>> readShapeFromFile(List<String> filePaths) throws Exception {
|
|
|
+ Map<String, List<Geometry>> geoMap = new HashMap<>();
|
|
|
+ for (String filePath : filePaths) {
|
|
|
+ if (!filePath.endsWith(".shp")) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ List<Geometry> geometries = new ArrayList<>();
|
|
|
+ File file = new File(filePath);
|
|
|
+ Map<String, Object> map = new HashMap<>();
|
|
|
+ map.put("url", file.toURI().toURL());
|
|
|
+
|
|
|
+ DataStore dataStore = DataStoreFinder.getDataStore(map);
|
|
|
+ String typeName = dataStore.getTypeNames()[0];
|
|
|
+
|
|
|
+ FeatureSource<SimpleFeatureType, SimpleFeature> source =
|
|
|
+ dataStore.getFeatureSource(typeName);
|
|
|
+ Filter filter = Filter.INCLUDE; // ECQL.toFilter("BBOX(THE_GEOM, 10,20,30,40)")
|
|
|
+
|
|
|
+ FeatureCollection<SimpleFeatureType, SimpleFeature> collection = source.getFeatures(filter);
|
|
|
+ final CoordinateReferenceSystem coordinateReferenceSystem = collection.getBounds().getCoordinateReferenceSystem();
|
|
|
+ final String crsCode = CRS.toSRS(coordinateReferenceSystem, true);
|
|
|
+ int srid = 0;
|
|
|
+ try {
|
|
|
+ srid = Integer.parseInt(crsCode);
|
|
|
+ } catch (NumberFormatException e) {//有时候,prj文件中没有出现’AUTHORITY["EPSG",4326]‘,就会解不了srid的int出来,就会报错,此时就不管它了,没办法
|
|
|
+// e.printStackTrace();
|
|
|
+ }
|
|
|
+
|
|
|
+ try (FeatureIterator<SimpleFeature> features = collection.features()) {
|
|
|
+ while (features.hasNext()) {
|
|
|
+ SimpleFeature feature = features.next();
|
|
|
+// final Collection<Property> properties = feature.getProperties();
|
|
|
+// final Property name = feature.getProperty("Name");
|
|
|
+// final List<Object> attributes = feature.getAttributes();
|
|
|
+// final Object name1 = feature.getAttribute("Name");//value本身
|
|
|
+// Property name.getType().getBinding().getName();//可以获取类型
|
|
|
+ //name.getName();//获取字段名称
|
|
|
+ //name.getValue();//获取值
|
|
|
+ final GeometryAttribute geometryProperty = feature.getDefaultGeometryProperty();
|
|
|
+ Object value = geometryProperty.getValue();
|
|
|
+ if (value instanceof Geometry) {
|
|
|
+ Geometry geometry = (Geometry) value;
|
|
|
+ geometry.setSRID(srid);
|
|
|
+ geometries.add(geometry);
|
|
|
+// Envelope geomEnvelope = geometry.getEnvelopeInternal();
|
|
|
+// envelope.expandToInclude(geomEnvelope);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ dataStore.dispose();
|
|
|
+
|
|
|
+ geoMap.put(filePath, geometries);
|
|
|
+ }
|
|
|
+
|
|
|
+ return geoMap;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @param baseDir shp文件(夹)的绝对路径
|
|
|
+ * @return 返回该文件(夹)的所有的shp的绝对路径
|
|
|
+ */
|
|
|
+ public static List<String> getShpFilePaths(String baseDir) {
|
|
|
+ if (baseDir.endsWith(".shp")) {
|
|
|
+ return new ArrayList<String>() {{
|
|
|
+ add(baseDir);
|
|
|
+ }};
|
|
|
+ }
|
|
|
+
|
|
|
+ File fileDir = new File(baseDir);
|
|
|
+ if (!fileDir.exists()) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ List<String> shpList = new ArrayList<>();
|
|
|
+ List<String> dirs = new ArrayList() {{
|
|
|
+ add(baseDir);
|
|
|
+ }};
|
|
|
+ while (true) {
|
|
|
+ List<String> newDirs = null;
|
|
|
+ if (dirs != null && dirs.size() > 0) {
|
|
|
+ for (String dir : dirs) {
|
|
|
+ File file = new File(dir);
|
|
|
+ final File[] files = file.listFiles();
|
|
|
+ if (files != null && files.length > 0) {
|
|
|
+ for (File aFile : files) {
|
|
|
+ if (aFile.getName().endsWith(".shp")) {
|
|
|
+ shpList.add(aFile.getAbsolutePath());
|
|
|
+ } else if (aFile.isDirectory()) {
|
|
|
+ newDirs = newDirs == null ? new ArrayList<>() : newDirs;
|
|
|
+ newDirs.add(aFile.getAbsolutePath());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ dirs = newDirs;
|
|
|
+ } else {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return shpList;
|
|
|
+ }
|
|
|
+
|
|
|
+ public static class ShpGeomWithAttr {
|
|
|
+ private Geometry geometry;
|
|
|
+ private Map<String, Object> properties;
|
|
|
+
|
|
|
+ public ShpGeomWithAttr(Geometry geometry, Map<String, Object> properties) {
|
|
|
+ this.geometry = geometry;
|
|
|
+ this.properties = properties;
|
|
|
+ }
|
|
|
+
|
|
|
+ public Geometry getGeometry() {
|
|
|
+ return geometry;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void setGeometry(Geometry geometry) {
|
|
|
+ this.geometry = geometry;
|
|
|
+ }
|
|
|
+
|
|
|
+ public Map<String, Object> getProperties() {
|
|
|
+ return properties;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void setProperties(Map<String, Object> properties) {
|
|
|
+ this.properties = properties;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public static class GeomAttrWrapper {
|
|
|
+ private Map<String, List<ShpGeomWithAttr>> geoMap;
|
|
|
+ private Map<String, Class> attrTypeMap;
|
|
|
+ private Map<String, Envelope> bboxMap;
|
|
|
+
|
|
|
+ public GeomAttrWrapper(Map<String, List<ShpGeomWithAttr>> geoMap, Map<String, Class> attrTypeMap, Map<String, Envelope> bboxMap) {
|
|
|
+ this.geoMap = geoMap;
|
|
|
+ this.attrTypeMap = attrTypeMap;
|
|
|
+ this.bboxMap = bboxMap;
|
|
|
+ }
|
|
|
+
|
|
|
+ public Map<String, List<ShpGeomWithAttr>> getGeoMap() {
|
|
|
+ return geoMap;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void setGeoMap(Map<String, List<ShpGeomWithAttr>> geoMap) {
|
|
|
+ this.geoMap = geoMap;
|
|
|
+ }
|
|
|
+
|
|
|
+ public Map<String, Class> getAttrTypeMap() {
|
|
|
+ return attrTypeMap;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void setAttrTypeMap(Map<String, Class> attrTypeMap) {
|
|
|
+ this.attrTypeMap = attrTypeMap;
|
|
|
+ }
|
|
|
+
|
|
|
+ public Map<String, Envelope> getBboxMap() {
|
|
|
+ return bboxMap;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void setBboxMap(Map<String, Envelope> bboxMap) {
|
|
|
+ this.bboxMap = bboxMap;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+}
|