/**
* Copyright (c) 2011 Ontology Engineering Group,
* Departamento de Inteligencia Artificial,
* Facultad de Informetica, Universidad
* Politecnica de Madrid, Spain
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package es.upm.fi.dia.oeg.map4rdf.server.util;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
import org.geotools.geometry.jts.JTSFactoryFinder;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.io.WKTReader;
import es.upm.fi.dia.oeg.map4rdf.share.Geometry;
import es.upm.fi.dia.oeg.map4rdf.share.MultiPolygonBean;
import es.upm.fi.dia.oeg.map4rdf.share.Point;
import es.upm.fi.dia.oeg.map4rdf.share.PointBean;
import es.upm.fi.dia.oeg.map4rdf.share.PolyLineBean;
import es.upm.fi.dia.oeg.map4rdf.share.Polygon;
import es.upm.fi.dia.oeg.map4rdf.share.PolygonBean;
import es.upm.fi.dia.oeg.map4rdf.share.TwoDimentionalCoordinate;
import es.upm.fi.dia.oeg.map4rdf.share.TwoDimentionalCoordinateBean;
import es.upm.fi.dia.oeg.map4rdf.share.WKTGeometryBean;
/**
* @author Alexander De Leon
*/
public class GeoUtils {
private static final Logger LOG = Logger.getLogger(es.upm.fi.dia.oeg.map4rdf.server.util.GeoUtils.class);
//If you modify this enum remember to modify validWKTTypes String and transformWKTtoOEG method.
private static enum WKTTypes{Point, LineString, Polygon,MultiPoint,MultiPolygon,MultiLineString}
private static String validWKTTypes="{Point, LineString, Polygon,MultiPoint,MultiPolygon,MultiLineString}";
public static double getDistance(TwoDimentionalCoordinate point1, TwoDimentionalCoordinate point2) {
return Math.sqrt(Math.pow(point1.getX() - point2.getX(), 2) + Math.pow(point1.getY() - point2.getY(), 2));
}
//TODO remove unused comments
public static List<Geometry> getWKTGeometries(String uri ,String GMLText, String WKTText,String projection){
String crs=projection;
/*if(GMLText.contains("srsName")){
String parseText=GMLText.substring(GMLText.indexOf("srsName"), GMLText.indexOf(" ", GMLText.indexOf("srsName")));
parseText=parseText.replace(" ", "");
parseText=parseText.replace("srsName=", "");
parseText=parseText.replace("\"", "");
crs=parseText;
}else{
String error="GML not contains \"srsName\" for use specific CRS. Use default CRS";
printGMLError(uri, error, GMLText);
}*/
/*if(!crs.contains("EPSG")){
String error="CRS: "+crs+". Is not valid. Valid CRS are EPSG:XXXX. Use default CRS";
printGMLError(uri, error, GMLText);
crs=TwoDimentionalCoordinateBean.getDefaultProjection();
}*/
String realWKTText="";
int firtsIndex=-1;
for(WKTTypes i: WKTTypes.values()){
int index=WKTText.toLowerCase().indexOf(i.toString().toLowerCase());
if(index>=0 && (index<firtsIndex || firtsIndex==-1)){
firtsIndex=index;
}
}
if(firtsIndex==-1){
printWKTError(uri,"Not found valid WKTType. Valid types are:"+validWKTTypes, WKTText);
return null;
}
realWKTText=WKTText.substring(firtsIndex, WKTText.length());
int count=1;
int lastIndex=-1;
int searchIndex=realWKTText.indexOf("(");
if(searchIndex==-1 || searchIndex==realWKTText.length()-1){
printWKTError(uri, "Not found '(' character.", WKTText);
return null;
}
for(int i=searchIndex+1;i<realWKTText.length();i++){
if(realWKTText.charAt(i)=='('){
count++;
}
if(realWKTText.charAt(i)==')'){
count--;
}
if(count==0){
lastIndex=i+1;
break;
}
}
if(lastIndex==-1){
printWKTError(uri, "Not balanced '(' and ')' characters.", WKTText);
return null;
}
realWKTText=realWKTText.substring(0,lastIndex);
/*parseWKTGeotools(uri, GMLText, realWKTText, projection);
//parseWKTGeotools(uri, GMLText, WKTText, projection);
parseWKTGeotools("", "", "POINT(1 45)", "");
parseWKTGeotools("", "", "MULTIPOINT(40 35, 20 10)", "");
parseWKTGeotools("", "", "LINESTRING(1 1, 2 2, 3 3, 4 4, 5 5, 6 6)", "");
parseWKTGeotools("", "", "MULTILINESTRING((1 1, 2 2),(3 3, 4 4))", "");
parseWKTGeotools("", "", "POLYGON ( (0 0, 10 0, 10 10, 0 10, 0 0),( 20 20, 20 40, 40 40, 40 20, 20 20) )", "");
parseWKTGeotools("", "", "MULTIPOLYGON(((1 1, 2 1,2 0, 1 1)),((3 3, 4 3,4 2, 3 3)))", "");
parseWKTGeotools("", "", "POLYGON((1 1, 2 1,2 0, 1 1))", "");*/
//return parseWKTGeotools(uri, GMLText, realWKTText, crs);
return parseToOpenLayersWKT(uri,realWKTText,crs);
}
private static List<Geometry> transforWKTtoOEG(String uri,String realWKTText,String crs){
if(realWKTText.toLowerCase().contains(WKTTypes.Point.toString().toLowerCase())){
String stringPoints=realWKTText.toLowerCase().replace(WKTTypes.Point.toString().toLowerCase(), "");
List<TwoDimentionalCoordinate> points=extractTwoDimentionalCoordinate(uri, crs, stringPoints);
if(!points.isEmpty()){
List<Geometry> geometries= new ArrayList<Geometry>();
for(TwoDimentionalCoordinate point:points){
geometries.add(new PointBean(uri, point.getX(), point.getY(),point.getProjection()));
}
return geometries;
}
return null;
}
if(realWKTText.toLowerCase().contains(WKTTypes.LineString.toString().toLowerCase())){
String stringLineString=realWKTText.toLowerCase().replace(WKTTypes.LineString.toString().toLowerCase(), "");
stringLineString=stringLineString.replaceAll(" +", " ");;
stringLineString=stringLineString.replace(')', 'z');
stringLineString=stringLineString.replaceAll("z ,", "z,");
List<Geometry> geometries=new ArrayList<Geometry>();
for(String lineStringSplit:stringLineString.split("z,")){
List<TwoDimentionalCoordinate> coordinates=extractTwoDimentionalCoordinate(uri, crs, lineStringSplit);
if(!coordinates.isEmpty()){
List<Point> points=new ArrayList<Point>();
for(TwoDimentionalCoordinate point:coordinates){
points.add(new PointBean(uri, point.getX(), point.getY(),point.getProjection()));
}
if(!points.isEmpty()){
geometries.add(new PolyLineBean(uri, points,points.get(0).getProjection()));
}
}
}
return geometries;
}
if(realWKTText.toLowerCase().contains(WKTTypes.Polygon.toString().toLowerCase())){
String stringLineString=realWKTText.toLowerCase().replace(WKTTypes.Polygon.toString().toLowerCase(), "");
stringLineString=stringLineString.replaceAll(" +", " ");;
stringLineString=stringLineString.replace(')', 'z');
stringLineString=stringLineString.replaceAll("z ,", "z,");
List<Geometry> geometries=new ArrayList<Geometry>();
for(String lineStringSplit:stringLineString.split("z,")){
List<TwoDimentionalCoordinate> coordinates=extractTwoDimentionalCoordinate(uri, crs, lineStringSplit);
if(!coordinates.isEmpty()){
List<Point> points=new ArrayList<Point>();
for(TwoDimentionalCoordinate point:coordinates){
points.add(new PointBean(uri, point.getX(), point.getY(),point.getProjection()));
}
if(!points.isEmpty()){
geometries.add(new PolygonBean(uri, points,crs));
}
}
}
return geometries;
}
return null;
}
private static List<TwoDimentionalCoordinate> extractTwoDimentionalCoordinate(String uri,String crs,String points){
List<TwoDimentionalCoordinate> toReturn= new ArrayList<TwoDimentionalCoordinate>();
points=points.replace('(', 'z');
points=points.replace(')', 'z');
points=points.replace("z","");
points=points.trim();
points=points.replaceAll(" +", " ");
for(String WKTPoint:points.split(",")){
WKTPoint=WKTPoint.trim();
String [] coordenates=WKTPoint.split(" ");
try{
double x=Double.parseDouble(coordenates[0]);
double y=Double.parseDouble(coordenates[1]);
//double[] xy=convertPoint(x,y,crs,"EPSG:4326");
TwoDimentionalCoordinateBean point= new TwoDimentionalCoordinateBean(x, y,crs);
toReturn.add(point);
}catch(NumberFormatException e){
LOG.error(e);
LOG.error("NumberFormatException in parse point:"+WKTPoint);
LOG.error("In URI:"+uri);
}
}
return toReturn;
}
private static void printWKTError(String uri, String error, String WKTText){
LOG.warn("Error WKT is malformed");
LOG.warn(error);
LOG.warn("In resource:"+uri);
LOG.warn("WKT Text:"+"\""+WKTText+"\"");
}
/*private static void printGMLError(String uri,String error, String GMLText){
LOG.warn("Error GML is malformed");
LOG.warn(error);
LOG.warn("In resource:"+uri);
LOG.warn("GML Text:"+"\""+GMLText+"\"");
}*/
/*private static double[] convertPoint(double x,double y, String epsgFrom, String epsgTo){
double toReturnX=0.0;
double toReturnY=0.0;
try {
CoordinateReferenceSystem sourceCRS = CRS.decode("EPSG:25830");
CoordinateReferenceSystem targetCRS = CRS.decode(epsgTo);
MathTransform transform = CRS.findMathTransform(sourceCRS, targetCRS, false);
GeometryBuilder builder = new GeometryBuilder( sourceCRS );
Point point = (Point) builder.createPoint( x, y );
Point targetPoint = (Point) JTS.transform((com.vividsolutions.jts.geom.Geometry)point, transform);
toReturnX=targetPoint.getX();
toReturnY=targetPoint.getY();
} catch (NoSuchAuthorityCodeException e) {
e.printStackTrace();
} catch (FactoryException e) {
e.printStackTrace();
} catch (TransformException e) {
e.printStackTrace();
}
return new double[]{toReturnX, toReturnY};
}*/
private static List<Geometry> parseToOpenLayersWKT(String uri,String WKTText,String projection){
List<Geometry> geometries = new ArrayList<Geometry>();
geometries.add(new WKTGeometryBean(uri, WKTText, projection));
return geometries;
}
private static List<Geometry> parseWKTGeotools(String uri ,String GMLText, String WKTText,String projection){
try{
/*GeoTools.addClassLoader(ClassLoader.getSystemClassLoader());
CoordinateReferenceSystem crs = CRS.decode("EPSG:23030");
GeometryFactory geometryFactory = new GeometryFactoryImpl(crs);
PositionFactory positionFactory = new PositionFactoryImpl();
PrimitiveFactory primitiveFactory = new PrimitiveFactoryImpl();
AggregateFactory aggregateFactory = new AggregateFactoryImpl();
WKTParser parser = new WKTParser( geometryFactory, primitiveFactory, positionFactory, aggregateFactory);
org.opengis.geometry.Geometry geometry = parser.parse(WKTText);*/
//CoordinateReferenceSystem crs = CRS.decode("EPSG:23030");
com.vividsolutions.jts.geom.GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory();
WKTReader reader = new WKTReader(geometryFactory);
com.vividsolutions.jts.geom.Geometry geometry = reader.read(WKTText);
if(geometry==null){
printWKTError(uri, "Error in GeoTools INVALID WKT of resource: "+uri, WKTText);
return null;
}
return transformGeoToolsGeometryToOEG(uri,WKTText,projection,geometry);
}catch(Exception e){
printWKTError(uri, "Error in GeoTools parse WKT of resource: "+uri, WKTText);
LOG.error("",e);
}
return null;
}
private static List<Geometry> transformGeoToolsGeometryToOEG(String uri, String WKTText, String projection,
com.vividsolutions.jts.geom.Geometry geometry) {
List<Geometry> geometrias = new ArrayList<Geometry>();
switch (geometry.getGeometryType().toLowerCase()) {
case "multipolygon":
List<Polygon> polygons= new ArrayList<Polygon>();
int poligonos = 0;
for(int i=0; i<geometry.getNumGeometries();i++){
Coordinate [] coordinates = geometry.getGeometryN(i).getCoordinates();
List<Point> points= new ArrayList<Point>();
poligonos++;
for(int j=0;j<coordinates.length;j++){
points.add(new PointBean(uri,coordinates[j].x, coordinates[j].y, projection));
}
polygons.add(new PolygonBean(uri, points,projection));
}
System.out.println("Se han encontrado "+poligonos+" poligonos.");
geometrias.add(new MultiPolygonBean(uri, polygons,projection));
break;
case "polygon":
for(int i=0; i<geometry.getNumGeometries();i++){
Coordinate [] coordinates = geometry.getGeometryN(i).getCoordinates();
List<Point> points= new ArrayList<Point>();
for(int j=0;j<coordinates.length;j++){
points.add(new PointBean(uri,coordinates[j].x, coordinates[j].y, projection));
}
geometrias.add(new PolygonBean(uri, points,projection));
}
break;
case "multilinestring":
case "linestring":
for(int i=0; i<geometry.getNumGeometries();i++){
Coordinate [] coordinates = geometry.getGeometryN(i).getCoordinates();
List<Point> points= new ArrayList<Point>();
for(int j=0;j<coordinates.length;j++){
points.add(new PointBean(uri,coordinates[j].x, coordinates[j].y, projection));
}
geometrias.add(new PolyLineBean(uri, points,projection));
}
break;
case "point":
case "multipoint":
for(int i=0; i<geometry.getNumGeometries();i++){
Coordinate [] coordinates = geometry.getGeometryN(i).getCoordinates();
for(int j=0;j<coordinates.length;j++){
geometrias.add(new PointBean(uri,coordinates[j].x, coordinates[j].y, projection));
}
}
break;
default:
printWKTError(uri, "GeoTools return a invalid type of geometry.", WKTText);
return null;
}
return geometrias;
}
}