当前位置:网站首页>GeoTools:WKT、GeoJson、Feature、FeatureCollection相互转换常用工具
GeoTools:WKT、GeoJson、Feature、FeatureCollection相互转换常用工具
2022-06-30 01:24:00 【liuccn】
参考文章:
GeoTools:WKT、GeoJson、Feature、FeatureCollection相互转换
转换工具类
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import org.geotools.data.DataUtilities;
import org.geotools.data.collection.ListFeatureCollection;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.geojson.GeoJSONUtil;
import org.geotools.geojson.feature.FeatureJSON;
import org.geotools.geojson.geom.GeometryJSON;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryCollection;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.io.WKTReader;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import java.io.IOException;
import java.io.Reader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
/** * <p> * 空间处理工具 * </p> * **/
public class GeoTools {
private static final WKTReader READER = new WKTReader();
/** * 要素集合根节点 */
private static final String[] COLLECTION_TYPE = new String[]{
"FeatureCollection"};
/** * 地理要素类型 */
private static final String[] FEATURES_TYPE = new String[]{
"Feature"};
/** * 地理数据类型 * 点、线、面、几何集合 */
private static final String[] GEO_TYPE = new String[]{
"Geometry", "Point", "LineString", "Polygon", "MultiPoint", "MultiLineString", "MultiPolygon", "GeometryCollection"};
/** * 获取 Geo 几何类型 * @param wktStr WKT 字符串 * @return Geo 几何类型 */
public static String getGeometryType(String wktStr) {
String type = null;
if (StrUtil.isNotEmpty(wktStr)) {
try {
Geometry read = READER.read(wktStr);
type = read.getGeometryType();
}catch (Exception e) {
System.out.println("非规范 WKT 字符串:"+ e);
e.printStackTrace();
}
}
return type;
}
/** * 是规范的 WKT * @param wktStr WKT 字符串 * @return 是、否 */
public static boolean isWkt(String wktStr) {
for (String s : GEO_TYPE) {
if (wktStr.toLowerCase().startsWith(s.toLowerCase())) {
return true;
}
}
return false;
}
/** * 不是规范的 WKT * @param wktStr WKT 字符串 * @return 是、否 */
public static boolean isNotWkt(String wktStr) {
return !isWkt(wktStr);
}
/** * 是规范的 GeoJson * @param geoJsonStr GeoJson 字符串 * @return 是、否 */
public static boolean isGeoJson(String geoJsonStr) {
try {
JSONObject jsonObject = JSONUtil.parseObj(geoJsonStr);
return isGeoJson(jsonObject);
}catch (Exception e) {
return false;
}
}
/** * 不是规范的 GeoJson * @param geoJsonStr GeoJson 字符串 * @return 是、否 */
public static boolean isNotGeoJson(String geoJsonStr) {
return !isGeoJson(geoJsonStr);
}
/** * 是规范的 GeoJson * @param geoJson GeoJson 对象 * @return 是、否 */
public static boolean isGeoJson(JSONObject geoJson) {
String type = geoJson.getStr("type");
boolean mark = false;
// 判断根节点
if (ArrayUtil.containsIgnoreCase(COLLECTION_TYPE, type)) {
JSONArray jsonArray = geoJson.get("features", JSONArray.class);
for (Object jsonStr : jsonArray) {
JSONObject jsonObject = JSONUtil.parseObj(jsonStr);
type = jsonObject.getStr("type");
// 判断地理要素
if (ArrayUtil.containsIgnoreCase(FEATURES_TYPE, type)) {
type = jsonObject.get("geometry", JSONObject.class).getStr("type");
// 判断几何要素
mark = ArrayUtil.containsIgnoreCase(GEO_TYPE, type);
}
if (!mark) {
return false;
}
}
}else {
// 判断地理要素
if (ArrayUtil.containsIgnoreCase(FEATURES_TYPE, type)) {
type = geoJson.get("geometry", JSONObject.class).getStr("type");
}
// 数据是几何数据
mark = ArrayUtil.containsIgnoreCase(GEO_TYPE, type);
}
return mark;
}
/** * 不是规范的 GeoJson * @param geoJson GeoJson 对象 * @return 是、否 */
public static boolean isNotGeoJson(JSONObject geoJson) {
return !isGeoJson(geoJson);
}
/** * GeoJson 转 WKT * @param geoJson GeoJson 对象 * @return WKT 字符串 */
public static String geoJsonToWkt(JSONObject geoJson) {
String wkt = null;
GeometryJSON gJson = new GeometryJSON();
try {
if(isGeoJson(geoJson)){
String type = geoJson.getStr("type");
// 判断是否根节点
if (ArrayUtil.containsIgnoreCase(COLLECTION_TYPE, type)) {
JSONArray geometriesArray = geoJson.get("features", JSONArray.class);
// 定义一个数组装图形对象
int size = geometriesArray.size();
Geometry[] geometries = new Geometry[size];
for (int i = 0; i < size; i++){
String str = JSONUtil.parseObj(geometriesArray.get(i)).getStr("geometry");
// 使用 GeoUtil 去读取 str
Reader reader = GeoJSONUtil.toReader(str);
Geometry geometry = gJson.read(reader);
geometries[i] = geometry;
}
GeometryCollection geometryCollection = new GeometryCollection(geometries, new GeometryFactory());
wkt = geometryCollection.toText();
}else {
String geoStr = geoJson.toString();
// 判断是否地理要素节点
if (ArrayUtil.containsIgnoreCase(FEATURES_TYPE, type)) {
geoStr = geoJson.getStr("geometry");
}
Reader reader = GeoJSONUtil.toReader(geoStr);
Geometry read = gJson.read(reader);
wkt = read.toText();
}
}
} catch (IOException e){
System.out.println("GeoJson 转 WKT 出现异常:"+ e);
e.printStackTrace();
}
return wkt;
}
/** * WKT 转 GeoJson * @param wktStr WKT 字符串 * @return GeoJson 对象 */
public static JSONObject wktToGeoJson(String wktStr) {
JSONObject jsonObject = new JSONObject();
try {
Geometry geometry = READER.read(wktStr);
StringWriter writer = new StringWriter();
GeometryJSON geometryJson = new GeometryJSON();
geometryJson.write(geometry, writer);
jsonObject = JSONUtil.parseObj(writer.toString());
} catch (Exception e) {
System.out.println("WKT 转 GeoJson 出现异常:"+ e);
e.printStackTrace();
}
return jsonObject;
}
/** * WKT 转 Feature * @param wktStr WKT 字符串 * @return Feature JSON 对象 */
public static JSONObject wktToFeature(String wktStr) {
JSONObject jsonObject = new JSONObject();
try {
SimpleFeatureType type = DataUtilities.createType("Link", "geometry:"+getGeometryType(wktStr));
SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(type);
// 按照TYPE中声明的顺序为属性赋值就可以,其他方法我暂未尝试
featureBuilder.add(READER.read(wktStr));
SimpleFeature feature = featureBuilder.buildFeature(null);
StringWriter writer = new StringWriter();
FeatureJSON fJson = new FeatureJSON();
fJson.writeFeature(feature, writer);
jsonObject = JSONUtil.parseObj(writer.toString());
}catch (Exception e) {
System.out.println("WKT 转 Feature 出现异常:"+ e);
e.printStackTrace();
}
return jsonObject;
}
/** * WKT 转 FeatureCollection * @param wktStr WKT 字符串 * @return FeatureCollection JSON 对象 */
public static JSONObject wktToFeatureCollection(String wktStr) {
JSONObject jsonObject = new JSONObject();
try {
String geometryType = getGeometryType(wktStr);
if (StrUtil.isNotEmpty(geometryType)) {
SimpleFeatureType type = DataUtilities.createType("Link", "geometry:" + geometryType);
SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(type);
List<SimpleFeature> features = new ArrayList<>();
SimpleFeatureCollection collection = new ListFeatureCollection(type, features);
featureBuilder.add(READER.read(wktStr));
SimpleFeature feature = featureBuilder.buildFeature(null);
features.add(feature);
StringWriter writer = new StringWriter();
FeatureJSON fJson = new FeatureJSON();
fJson.writeFeatureCollection(collection, writer);
jsonObject = JSONUtil.parseObj(writer.toString());
}
}catch (Exception e) {
System.out.println("WKT 转 FeatureCollection 出现异常:"+ e);
e.printStackTrace();
}
return jsonObject;
}
}
测试
import cn.hutool.json.JSONUtil;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class GeoToolsTest {
String geoJsonStr = "{\n" +
" \"type\":\"Point\",\n" +
" \"coordinates\":[105.380859375,31.57853542647338]\n" +
" }";
String geoJsonStr2 = "{\"type\":\"Feature\",\n" +
" \"properties\":{},\n" +
" \"geometry\":{\n" +
" \"type\":\"Point\",\n" +
" \"coordinates\":[105.380859375,31.57853542647338]\n" +
" }\n" +
" }";
String geoJsonStr3 = "{\n" +
" \"type\": \"FeatureCollection\",\n" +
" \"features\": [\n" +
" {\"type\":\"Feature\",\n" +
" \"properties\":{},\n" +
" \"geometry\":{\n" +
" \"type\":\"Point\",\n" +
" \"coordinates\":[105.380859375,31.57853542647338]\n" +
" }\n" +
" },\n" +
"\t\t{\"type\":\"Feature\",\n" +
" \"properties\":{},\n" +
" \"geometry\":{\n" +
" \"type\":\"Point\",\n" +
" \"coordinates\":[105.380859375,31.57853542647338]\n" +
" }\n" +
" }\n" +
" ]\n" +
"}";
String[] wktStr = new String[]{
"POINT(6 10)", "LINESTRING(3 4,10 50,20 25)", "POLYGON((1 1,5 1,5 5,1 5,1 1),(2 2,2 3,3 3,3 2,2 2))",
"MULTIPOINT(3.5 5.6, 4.8 10.5)", "MULTILINESTRING((3 4,10 50,20 25),(-5 -8,-10 -8,-15 -4))", "MULTIPOLYGON(((1 1,5 1,5 5,1 5,1 1),(2 2,2 3,3 3,3 2,2 2)),((6 3,9 2,9 4,6 3)))",
"GEOMETRYCOLLECTION(POINT(4 6),LINESTRING(4 6,7 10))", "POINT ZM (1 1 5 60)", "POINT M (1 1 80)"};
@Test
void getGeometryType() {
for (String s : wktStr) {
System.out.println("Geo 几何类型:" + GeoTools.getGeometryType(s));
}
}
@Test
void isWkt() {
for (String s : wktStr) {
System.out.println("是规范的 WKT:" + GeoTools.isWkt(s));
}
}
@Test
void isNotWkt() {
for (String s : wktStr) {
System.out.println("不是规范的 WKT:" + GeoTools.isNotWkt(geoJsonStr2));
}
}
@Test
void isGeoJson() {
System.out.println("是规范的 GeoJson:" + GeoTools.isGeoJson(geoJsonStr3));
}
@Test
void isNotGeoJson() {
System.out.println("不是规范的 GeoJson:" + GeoTools.isNotGeoJson(geoJsonStr3));
}
@Test
void geoJsonToWkt() {
System.out.println("GeoJson 转 WKT:" + GeoTools.geoJsonToWkt(JSONUtil.parseObj(geoJsonStr)));
System.out.println("GeoJson 转 WKT:" + GeoTools.geoJsonToWkt(JSONUtil.parseObj(geoJsonStr2)));
System.out.println("GeoJson 转 WKT:" + GeoTools.geoJsonToWkt(JSONUtil.parseObj(geoJsonStr3)));
}
@Test
void wktToGeoJson() {
for (String s : wktStr) {
System.out.println("WKT 转 GeoJson:" + GeoTools.wktToGeoJson(s));
}
}
@Test
void wktToFeature() {
for (String s : wktStr) {
System.out.println("WKT 转 Feature:" + GeoTools.wktToFeature(s));
}
}
@Test
void wktToFeatureCollection() {
for (String s : wktStr) {
System.out.println("WKT 转 FeatureCollection:" + GeoTools.wktToFeatureCollection(s));
}
}
}
边栏推荐
- Online sql to CSV tool
- Sentinel source code analysis Part 6 - sentinel adapter module Chapter 4 zuul2 gateway
- Mysql 监控
- Unity编辑器随机生成物体,更换场景之后物体丢失问题解决
- Stimulsoft Reports报告工具,Stimulsoft创建和构建报告
- How to refuse the useless final review? Ape tutoring: it is important to find a suitable review method
- HC32M0+ GPIO
- How to deal with occasional bugs?
- 传统微服务框架如何无缝过渡到服务网格 ASM
- Tetris game based on STM32F103
猜你喜欢

cookie加密11

Online sql to CSV tool

ES6 one line code for array de duplication

首届·技术播客月开播在即

cookie加密9

第八届“互联网+”大赛 | 云原生赛道邀你来挑战

Analysis of natural frequency and buckling load of cylinder by finite element method

画画水族馆的应用特色及功能

81. search rotation sort array II

2022-06-29: x = {a, B, C, D}, y = {e, F, G, H}, the length of the two small arrays X and Y is 4. If yes: a + e = B + F = C + G = D + H
随机推荐
英伟达Jetson Nano的初步了解
ctfshow 大赛原题 680-695
【Games101】Transformation
我,33岁,字节跳动测试开发,揭开北京“测试岗”的真实收入
【推荐系统】基于用户的协同过滤简明原理与代码实现
cookie加密9
2022-06-29:x = { a, b, c, d }, y = { e, f, g, h }, x、y两个小数组长度都是4。 如果有: a + e = b + f = c + g = d + h
STC89C52 single chip microcomputer simple calculator design and code demonstration
JS prototype and prototype chain (Lantern Festival meal)
[deep learning compilation] operator compilation IR conversion
Wechat applet - requestsubscribemessage:fail can only be invoked by user tap gesture
田口实验法
Varnish 基础概览2
R language linear regression model fitting diagnosis outliers analysis of domestic gas consumption and calorie examples with self-test questions
[proteus simulation] 8-bit port detection 8 independent keys
眼底出血术后需注意事项//每天必看
Varnish 基础概览1
Mysql 监控3
Cantilever beam calculation [matlab code]
Varnish 基础概览10