操作GIS的geometry 空间类型数据方式
Java 版本:
import java.io.IOException;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.io.WKBReader;
import org.locationtech.jts.io.WKBWriter;
import org.wololo.geojson.GeoJSON;
import org.wololo.jts2geojson.GeoJSONReader;
import org.wololo.jts2geojson.GeoJSONWriter;
import com.fasterxml.jackson.databind.ObjectMapper;
public class GISConvertUtils {
/**
* obj 转 json
*
* @param obj
* @param <T>
* @return
*/
public static <T> String obj2StringPretty(T obj) {
ObjectMapper mapper = new ObjectMapper();
if (obj == null) {
return null;
}
try {
return obj instanceof String ? (String) obj : mapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
} catch (IOException e) {
return null;
}
}
/**
* json 转 obj
*
* @param str
* @param clazz
* @param <T>
* @return
*/
public static <T> T string2Obj(String str, Class<T> clazz) {
ObjectMapper mapper = new ObjectMapper();
if (isEmpty(str) || clazz == null) {
return null;
}
try {
return clazz.equals(String.class) ? (T) str : mapper.readValue(str, clazz);
} catch (IOException e) {
return null;
}
}
/**
* 为空判断
*
* @param str
* @return
*/
private static boolean isEmpty(String str) {
return str == null || str.length() == 0;
}
/**
* geojson 转 wkt
*
* @param geojson
* @return
* @throws Exception
*/
public static String geojson2Wkt(String geojson) throws Exception {
Geometry geometry = geojson2Geometry(geojson);
return geometry2Wkt(geometry);
}
/**
* geojson 转 geometry
*
* @param geojson
* @return
* @throws Exception
*/
public static Geometry geojson2Geometry(String geojson) throws Exception {
GeoJSONReader reader = new GeoJSONReader();
Geometry geometry = reader.read(geojson);
return geometry;
}
/**
* geometry 转 wkt
*
* @param geometry
* @return
* @throws Exception
*/
public static String geometry2Wkt(Geometry geometry) throws Exception {
WKBWriter writer = new WKBWriter();
return writer.toHex(writer.write(geometry));
}
/**
* wkt 转 geojson
*
* @param wkt
* @return
* @throws Exception
*/
public static String wkt2Geojson(String wkt) throws Exception {
Geometry geometry = wkt2Geometry(wkt);
return geometry2Geojson(geometry);
}
/**
* wkt 转 geometry
*
* @param wkt
* @return
* @throws Exception
*/
public static Geometry wkt2Geometry(String wkt) throws Exception {
WKBReader reader = new WKBReader();
return reader.read(reader.hexToBytes(wkt));
}
/**
* geometry 转 geojson
*
* @param geometry
* @return
* @throws Exception
*/
public static String geometry2Geojson(Geometry geometry) throws Exception {
GeoJSONWriter writer = new GeoJSONWriter();
GeoJSON json = writer.write(geometry);
return json.toString();
}
public static void main(String[] a) throws Exception {
String json = "{\"type\":\"Polygon\",\"coordinates\":[[[117.34406948089598,31.05120600591231],[117.34029293060304,31.048852961698408],[117.33844757080078,31.045396822533544],[117.33977794647217,31.04300686567524],[117.34359741210939,31.04164640189476],[117.34973430633545,31.04138901466813],[117.35445499420166,31.04227148226229],[117.35690116882324,31.044330541502767],[117.35724449157713,31.048044089313084],[117.35509872436523,31.05006625738655],[117.35020637512208,31.05157366381521],[117.34406948089598,31.05120600591231]]]}";
String s1=geojson2Wkt(json);
System.out.println(s1);
System.out.println(wkt2Geojson(s1));
}
}
python 版本:
可以使用 :from geodaisy import converters
将geojson 转换成wkt wkt=converters.geojson_to_wkt(geoco)
converters源码解读
-- coding: utf-8 --
“”"
geodaisy.converters
This module provides converters to and from GeoJSON, WKT, geo_interface, etc.
geodaisy.geo_object uses these converters; they can also be used directly.
"""
import json
import re
from ast import literal_eval
from typing import Union # noqa: F401
geo_types = {'Point', 'MultiPoint', 'LineString', 'MultiLineString',
'Polygon', 'MultiPolygon'}
wkt_types = {x.upper() for x in geo_types}
type_translations = {x.upper(): x for x in geo_types}
def geo_interface_to_wkt(geo_interface):
# type: (dict) -> str
"""Converts a geo_interface dictionary to a Well Known Text string."""
# Convert to string and change brackets to parentheses
coords = str(geo_interface['coordinates'])
coords = coords.replace('[', '(')
coords = coords.replace(']', ')')
# Remove commas within coordinate pairs
coords = re.sub(r'(?<=\d),', '', coords)
# Remove parentheses and commas separating coordinates
coords = re.sub(r'(?<=\d)\), \(', ', ', coords)
# Get the type and clean up extra parentheses in special cases
geo_type = geo_interface['type'].upper()
if geo_type == 'LINESTRING':
coords = coords.replace('((', '(')
coords = coords.replace('))', ')')
coords = coords.replace('), (', ', ')
elif geo_type in {'MULTILINESTRING', 'POLYGON'}:
coords = coords.replace('(((', '((')
coords = coords.replace(')))', '))')
coords = coords.replace(')), ((', '), (')
elif geo_type == 'MULTIPOINT':
coords = coords.replace('((', '(')
coords = coords.replace('))', ')')
elif geo_type == 'MULTIPOLYGON':
coords = coords.replace('((((', '(((')
coords = coords.replace('))))', ')))')
coords = coords.replace('))), (((', ')), ((')
return '{} {}'.format(geo_type, coords)
def wkt_to_geo_interface(wkt):
# type: (str) -> dict
"""Converts a WKT string to a geo_interface dictionary."""
try:
wkt_type, coords = re.split(r'(?<=[A-Z])\s', wkt)
geo_type = type_translations[wkt_type]
# Clean up the strings so they'll covert correctly
if geo_type in {'Polygon', 'MultiLineString', 'MultiPolygon'}:
coords = re.sub(r'(?<=\d)\), \((?=\d)', ')), ((', coords)
# Pairs of coordinates must be enclosed in parentheses
coords = re.sub(r'(?<=\d), (?=\d)', '), (', coords)
# Coordinates within parentheses must be separated by commas
coords = re.sub(r'(?<=\d) (?=\d)', ', ', coords)
# Now we can turn the string into a tuple or a tuple of tuples
coords = literal_eval(coords)
coords = reformat_coordinates(coords, 'geo_interface') # type: ignore # noqa: E501
# If we only have a simple polygon (no hole), the coordinate array
# won't be deep enough to satisfy the GeoJSON/geo_interface spec, so
# we need to enclose it in a list.
numbers = {float, int}
if geo_type == 'Polygon' and type(coords[0][0]) in numbers:
coords = [coords] # type: ignore
elif geo_type == 'MultiPolygon' and type(coords[0][0][0]) in numbers:
coords = [coords] # type: ignore
except Exception:
raise ValueError('{} is not a WKT string'.format(wkt))
return {'type': geo_type, 'coordinates': coords}
def dict_to_geo_interface(geo_dict):
# type: (dict) -> dict
"""Converts a dictionary into a standardized geo_interface dictionary."""
if not geo_dict.get('type') in geo_types:
raise ValueError('A geo_interface-compatible dictionary must'
' have a "type" key with one of the following'
'values: {}'.format(geo_types))
try:
coordinates = geo_dict['coordinates']
except KeyError:
raise KeyError('A geo_interface-compatible dictionary must'
' have a "coordinates" key-value pair.')
geo_dict['coordinates'] = reformat_coordinates(coordinates,
'geo_interface')
return geo_dict
def geo_interface_to_geojson(geo_interface):
# type: (dict) -> dict
"""Converts a geo_interface dictionary into a raw GeoJSON dictionary."""
coords = reformat_coordinates(geo_interface['coordinates'], 'geojson')
return {'type': geo_interface['type'], 'coordinates': coords}
def wkt_to_geojson(wkt):
# type: (str) -> str
"""Converts a WKT string to serialized GeoJSON."""
return json.dumps(geo_interface_to_geojson(wkt_to_geo_interface(wkt)))
def geojson_to_wkt(geojson):
# type: (Union[str, dict]) -> str
"""Converts GeoJSON (serialize or raw) to a WKT string."""
if isinstance(geojson, str):
raw_geojson = json.loads(geojson) # type: dict
elif isinstance(geojson, dict):
raw_geojson = geojson
else:
raise ValueError('{} is not GeoJSON'.format(geojson))
return geo_interface_to_wkt(dict_to_geo_interface(raw_geojson))
def reformat_coordinates(item, style):
# type: (Union[list, tuple], str) -> Union[list, tuple]
"""
Converts tuples, tuples of tuples, lists of tuples, etc. into lists and
lists of lists, etc. and preserves points/coordinate pairs as lists or
tuples depending on the desired style.
"""
if type(item) in {tuple, list} and type(item[0]) in {tuple, list}:
return [reformat_coordinates(x, style) for x in item]
else:
if style == 'geojson':
return list(item)
elif style == 'geo_interface':
return tuple(item)
else:
raise ValueError('style must be geojson or geo_interface.')