package com.midea.cloudSearch.druid.spatial;
import java.util.ArrayList;
import java.util.List;
import com.google.common.base.Joiner;
public class WktToGeoJsonConverter {
public static String toGeoJson(String wkt){
wkt = wkt.toLowerCase();
int startOfCoordinates = wkt.indexOf("(");
if(startOfCoordinates == -1)
throw new IllegalArgumentException("not valid wkt");
String wktType = wkt.substring(0, startOfCoordinates).trim();
wkt = wkt.substring(startOfCoordinates);
String type="";
String coordinates="";
switch (wktType){
case("point"):
type = "Point";
coordinates = pointCoordinatesFromWkt(wkt);
break;
case("polygon"):
type = "Polygon";
coordinates = polygonCoordinatesFromWkt(wkt);
break;
case("linestring"):
type = "LineString";
coordinates = lineStringCoordinatesFromWkt(wkt);
break;
case("multipolygon"):
type = "MultiPolygon";
coordinates = multiPolygonCoordinatesFromWkt(wkt);
break;
case("multipoint"):
type = "MultiPoint";
coordinates = multiPointCoordinatesFromWkt(wkt);
break;
case("multilinestring"):
type = "MultiLineString";
coordinates = multiLineStringCoordinatesFromWkt(wkt);
break;
default:
throw new IllegalArgumentException("not supported wkt type");
}
return buildGeoJson(type,coordinates);
}
//input: ((10 10, 20 20, 10 40),(40 40, 30 30, 40 20, 30 10))
private static String multiLineStringCoordinatesFromWkt(String wkt) {
wkt = removeBrackets(wkt,1);
String lineStringsWithPipeSeparator = wkt.replaceAll("\\s*\\)\\s*,\\s*\\(",")|(");
String[] lineStrings = lineStringsWithPipeSeparator.split("\\|");
String[] coordinates = new String[lineStrings.length];
for (int i=0;i<lineStrings.length;i++){
coordinates[i] = lineStringCoordinatesFromWkt(lineStrings[i]);
}
String multiLineStringCoordinates = Joiner.on(',').join(coordinates);
return String.format("[%s]", multiLineStringCoordinates);
}
//input v1:MULTIPOINT (10 40, 40 30, 20 20, 30 10)
//v2:MULTIPOINT ((10 40), (40 30), (20 20), (30 10))
private static String multiPointCoordinatesFromWkt(String wkt) {
wkt = removeBrackets(wkt,1);
boolean isSecondVersionMultiPoint = wkt.contains("(");
String coordinates = "";
if(isSecondVersionMultiPoint){
//(10 40), (40 30), (20 20)-> 10 40, 40 30, 20 20
wkt = wkt.replaceAll("\\(|\\)" ,"");
}
coordinates = getJsonArrayFromListOfPoints(wkt);
return coordinates;
}
//input (((30 20, 45 40, 10 40, 30 20)),((15 5, 40 10, 10 20, 5 10, 15 5)))
private static String multiPolygonCoordinatesFromWkt(String wkt) {
wkt = removeBrackets(wkt,1);
String polygonsWithPipeSeparator = wkt.replaceAll("\\s*\\)\\s*\\)\\s*,\\s*\\(\\s*\\(\\s*","))|((");
String[] polygons = polygonsWithPipeSeparator.split("\\|");
String[] polygonsCoordinates = new String[polygons.length];
for (int i=0;i<polygons.length;i++){
polygonsCoordinates[i] = polygonCoordinatesFromWkt(polygons[i]);
}
String coordinates = Joiner.on(',').join(polygonsCoordinates);
return String.format("[%s]", coordinates);
}
//input : (30 10, 10 30, 40 40)
private static String lineStringCoordinatesFromWkt(String wkt) {
wkt = removeBrackets(wkt,1);
return getJsonArrayFromListOfPoints(wkt);
}
//input: v1:((35 10, 45 45, 15 40, 10 20, 35 10))
//v2:((35 10, 45 45, 15 40, 10 20, 35 10),(20 30, 35 35, 30 20, 20 30))
private static String polygonCoordinatesFromWkt(String wkt) {
wkt = removeBrackets(wkt,2);
String coordinates;
boolean polygonContainsInnerHoles = wkt.contains("(");
if(polygonContainsInnerHoles) {
String[] polygons = wkt.split("\\s*\\)\\s*,\\s*\\(\\s*");
String[] coordinatesOfPolygons = new String[polygons.length];
for (int i = 0; i < polygons.length; i++) {
String polygonCoordinates = getJsonArrayFromListOfPoints(polygons[i]);
coordinatesOfPolygons[i] = polygonCoordinates;
}
coordinates = Joiner.on(',').join(coordinatesOfPolygons);
}
else {
coordinates = getJsonArrayFromListOfPoints(wkt);
}
return String.format("[%s]", coordinates);
}
private static String getJsonArrayFromListOfPoints(String pointsInWkt) {
String[] points = pointsInWkt.split(",");
List<String> coordinates = new ArrayList<>();
for(String point : points){
coordinates.add(extractCoordinateFromPoint(point));
}
String joinedCoordinates = Joiner.on(',').join(coordinates);
return String.format("[%s]", joinedCoordinates);
}
private static String buildGeoJson(String type, String coordinates) {
return String.format("{\"type\":\"%s\", \"coordinates\": %s}", type, coordinates);
}
//input : (30 10)
public static String pointCoordinatesFromWkt(String wkt) {
wkt = removeBrackets(wkt,1);
return extractCoordinateFromPoint(wkt);
}
private static String extractCoordinateFromPoint(String point) {
String pointPattern = "(\\s*)([0-9\\.]+)(\\s*)([0-9\\.]+)(\\s*)";
return point.replaceAll(pointPattern,"[$2,$4]");
}
private static String removeBrackets(String wkt, int num) {
String result= wkt;
for(int i=0;i<num;i++){
int lastClosingBrackets = result.lastIndexOf(")");
int firstOpenBrackets = result.indexOf("(");
if(lastClosingBrackets == -1 || firstOpenBrackets == -1)
throw new IllegalArgumentException("not enough brackets");
result = result.substring(firstOpenBrackets+1, lastClosingBrackets);
}
return result;
}
}