All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.geolatte.geom.codec.CrsWktDecoder Maven / Gradle / Ivy

Go to download

This geoLatte-geom library offers a geometry model that conforms to the OGC Simple Features for SQL specification.

There is a newer version: 1.9.1
Show newest version
/*
 * This file is part of the GeoLatte project.
 *
 *     GeoLatte is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU Lesser General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 *
 *     GeoLatte is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU Lesser General Public License for more details.
 *
 *     You should have received a copy of the GNU Lesser General Public License
 *     along with GeoLatte.  If not, see .
 *
 * Copyright (C) 2010 - 2011 and Ownership of code is shared by:
 * Qmino bvba - Romeinsestraat 18 - 3001 Heverlee  (http://www.qmino.com)
 * Geovise bvba - Generaal Eisenhowerlei 9 - 2140 Antwerpen (http://www.geovise.com)
 */

package org.geolatte.geom.codec;

import org.geolatte.geom.C3D;
import org.geolatte.geom.Position;
import org.geolatte.geom.crs.*;

import java.util.ArrayList;
import java.util.List;

/**
 * A decoder for CoordinateReferenceSystem definitions in WKT.
 * 

*

The current implementation ensures that the postgis CRS WKT's are correctly interpreted. There are * some minor differences with the OGC specification: "Coordinate Transformation Services (rev. 1.00)".

*

*

The implementation uses a recursive-decent parsing approach.

*

*

This class is not thread-safe.

* * @author Karel Maesen, Geovise BVBA * creation-date: 8/2/11 */ public class CrsWktDecoder extends AbstractWktDecoder { private final static CrsWktVariant CRS_TOKENS = new CrsWktVariant(); private int srid = 0; /** * Initiates a new CrsWktDecoder that uses the CrsWktVariant. */ public CrsWktDecoder() { super(CRS_TOKENS); } /** * Decodes a WKT representation of a CoordinateReferenceSystem. * * @param wkt the WKT string to decode * @return The CoordinateReferenceSystem that is encoded in the input WKT. */ public CoordinateReferenceSystem decode(String wkt, int srid) { this.srid = srid; setTokenizer(new CrsWktTokenizer(wkt, getWktVariant())); nextToken(); return decode(); } /** * Determines the WKT variant and calls the according method to decode the WKT. * * @return The decoded WKT as a CoordinateReferenceSystem object. */ private CoordinateReferenceSystem decode() { if (currentToken == CrsWktVariant.PROJCS) { return decodeProjectedCrs(); } else if (currentToken == CrsWktVariant.GEOGCS) { return decodeGeographicCrs(); } else if (currentToken == CrsWktVariant.GEOCCS) { return decodeGeocentricCrs(); } throw new WktDecodeException("Expected Wkt Token PROJCS, GEOGCS or GEOCCS"); } /** * Implementation to decode Geocentric CRS. * Currently not used in Postgis and also not implemented here! * * @throws UnsupportedConversionException Geocentric CRS is currently not implemented */ private CoordinateReferenceSystem decodeGeocentricCrs() { throw new UnsupportedConversionException("Currently not implemented"); } /** * Implementation to decode a Geographic CRS. * * @return The GeographicCoordinateReferenceSystem that is decoded from the WKT. */ private Geographic2DCoordinateReferenceSystem decodeGeographicCrs() { String crsName = decodeName(); matchesElementSeparator(); Datum datum = decodeDatum(); matchesElementSeparator(); PrimeMeridian primem = decodePrimem(); matchesElementSeparator(); Unit unit = decodeUnit(false); CoordinateSystemAxis[] twinAxes = decodeOptionalTwinAxis(unit, Geographic2DCoordinateReferenceSystem.class); CrsId cr = decodeOptionalAuthority(srid); matchesCloseList(); Geographic2DCoordinateReferenceSystem system = new Geographic2DCoordinateReferenceSystem(cr, crsName, new EllipsoidalCoordinateSystem2D((EllipsoidalAxis) twinAxes[0], (EllipsoidalAxis) twinAxes[1])); system.setDatum(datum); system.setPrimeMeridian(primem); return system; } /** * Implementation to decode a Projected CRS. * * @return The ProjectedCoordinateReferenceSystem that is decoded from the WKT. */ private ProjectedCoordinateReferenceSystem decodeProjectedCrs() { String crsName = decodeName(); matchesElementSeparator(); Geographic2DCoordinateReferenceSystem geogcs = decodeGeographicCrs(); matchesElementSeparator(); Unit unit; Projection projection; List parameters; // spatial_reference.sql contains both variants of ProjCRS Wkt if (currentToken == CrsWktVariant.UNIT) { unit = decodeUnit(true); projection = decodeProjection(); parameters = decodeOptionalParameters(); } else { projection = decodeProjection(); parameters = decodeOptionalParameters(); unit = decodeUnit(true); } CrsId crsId = decodeOptionalAuthority(srid); CoordinateSystemAxis[] twinAxes = decodeOptionalTwinAxis(unit, ProjectedCoordinateReferenceSystem.class); return new ProjectedCoordinateReferenceSystem(crsId, crsName, geogcs, projection, parameters, new CartesianCoordinateSystem2D((StraightLineAxis)twinAxes[0], (StraightLineAxis)twinAxes[1])); } private List decodeOptionalParameters() { List parameters = new ArrayList(); CrsParameter parameter = decodeOptionalParameter(); while (parameter != null) { parameters.add(parameter); parameter = decodeOptionalParameter(); } return parameters; } private CrsParameter decodeOptionalParameter() { matchesElementSeparator(); if (currentToken != CrsWktVariant.PARAMETER) { return null; } nextToken(); String name = decodeName(); matchesElementSeparator(); double value = decodeNumber(); matchesCloseList(); return new CrsParameter(name, value); } private Projection decodeProjection() { matchesElementSeparator(); if (currentToken != CrsWktVariant.PROJECTION) { throw new WktDecodeException("Expected PROJECTION keyword, found " + currentToken.toString()); } String name = decodeName(); CrsId crsId = decodeOptionalAuthority(CrsId.UNDEFINED.getCode()); matchesCloseList(); return new Projection(crsId, name); } private CoordinateSystemAxis[] decodeOptionalTwinAxis(Unit unit, Class crsClass) { matchesElementSeparator(); if (currentToken != CrsWktVariant.AXIS) { return defaultCRS(unit, crsClass); } CoordinateSystemAxis[] twinAxes = new CoordinateSystemAxis[2]; twinAxes[0] = decodeAxis(unit, crsClass); matchesElementSeparator(); twinAxes[1] = decodeAxis(unit, crsClass); return twinAxes; } private CoordinateSystemAxis[] defaultCRS(Unit unit, Class crsClass) { if (Geographic2DCoordinateReferenceSystem.class.isAssignableFrom(crsClass)) { return new CoordinateSystemAxis[]{ new GeodeticLongitudeCSAxis("Lon", (AngularUnit)unit), new GeodeticLatitudeCSAxis("Lat", (AngularUnit)unit) }; } if (ProjectedCoordinateReferenceSystem.class.isAssignableFrom(crsClass)) { return new CoordinateSystemAxis[]{ new StraightLineAxis("X", CoordinateSystemAxisDirection.EAST, (LinearUnit)unit), new StraightLineAxis("Y", CoordinateSystemAxisDirection.NORTH, (LinearUnit)unit) }; } if (GeocentricCartesianCoordinateReferenceSystem.class.isAssignableFrom(crsClass)) { return new CoordinateSystemAxis[]{ new StraightLineAxis("X", CoordinateSystemAxisDirection.GeocentricX, (LinearUnit)unit), new StraightLineAxis("Y", CoordinateSystemAxisDirection.GeocentricY, (LinearUnit)unit), new StraightLineAxis("Z", CoordinateSystemAxisDirection.GeocentricZ, (LinearUnit)unit) }; } throw new IllegalStateException("Can't create default for CrsRegistry of type " + crsClass.getCanonicalName()); } private CoordinateSystemAxis decodeAxis(Unit unit, Class crsClass) { if (currentToken != CrsWktVariant.AXIS) { throw new WktDecodeException("Expected AXIS keyword, found " + currentToken.toString()); } String name = decodeName(); matchesElementSeparator(); CoordinateSystemAxisDirection direction = CoordinateSystemAxisDirection.valueOf(currentToken.toString()); nextToken(); matchesCloseList(); if (Geographic2DCoordinateReferenceSystem.class.isAssignableFrom(crsClass)) { if (direction.equals(CoordinateSystemAxisDirection.NORTH)) { return new GeodeticLatitudeCSAxis(name, (AngularUnit) unit); } else if (direction.equals(CoordinateSystemAxisDirection.EAST)) { return new GeodeticLongitudeCSAxis(name, (AngularUnit) unit); } else { throw new IllegalStateException("Axis in horizontal Geographic coordinate system is neither latitude," + " nor longitude"); } } if (ProjectedCoordinateReferenceSystem.class.isAssignableFrom(crsClass)) { //this fixes problems with some polar projection systems. if (direction == CoordinateSystemAxisDirection.UNKNOWN) { if (name.equalsIgnoreCase("X") || name.equalsIgnoreCase("Easting")) { return new StraightLineAxis(name, direction, 0, (LinearUnit) unit); } else { return new StraightLineAxis(name, direction, 1, (LinearUnit) unit); } } return new StraightLineAxis(name, direction, (LinearUnit) unit); } if (GeocentricCartesianCoordinateReferenceSystem.class.isAssignableFrom(crsClass)) { return new StraightLineAxis(name, direction, (LinearUnit)unit); } throw new IllegalStateException("Can't create default for CrsRegistry of type " + crsClass.getCanonicalName()); } private Unit decodeUnit(boolean isLinear) { if (currentToken != CrsWktVariant.UNIT) { throw new WktDecodeException("Expected UNIT keyword, found " + currentToken.toString()); } String name = decodeName(); matchesElementSeparator(); double cf = decodeNumber(); matchesElementSeparator(); CrsId crsId = decodeOptionalAuthority(CrsId.UNDEFINED.getCode()); matchesCloseList(); return isLinear ? new LinearUnit(crsId, name, cf) : new AngularUnit(crsId, name, cf); } private PrimeMeridian decodePrimem() { if (currentToken != CrsWktVariant.PRIMEM) { throw new WktDecodeException("Expected PRIMEM keyword, received " + currentToken.toString()); } String name = decodeName(); matchesElementSeparator(); double longitude = decodeNumber(); CrsId crsId = decodeOptionalAuthority(CrsId.UNDEFINED.getCode()); matchesCloseList(); return new PrimeMeridian(crsId, name, longitude); } private Datum decodeDatum() { if (currentToken != CrsWktVariant.DATUM) { throw new WktDecodeException("Expected DATUM token."); } String datumName = decodeName(); matchesElementSeparator(); Ellipsoid ellipsoid = decodeSpheroid(); double[] toWGS84 = decodeOptionalToWGS84(); CrsId crsId = decodeOptionalAuthority(CrsId.UNDEFINED.getCode()); matchesCloseList(); return new Datum(crsId, ellipsoid, datumName, toWGS84); } private double[] decodeOptionalToWGS84() { matchesElementSeparator(); if (currentToken != CrsWktVariant.TOWGS84) { return new double[0]; } nextToken(); double[] toWGS = new double[7]; matchesOpenList(); for (int i = 0; i < 7; i++) { toWGS[i] = decodeNumber(); matchesElementSeparator(); } matchesCloseList(); return toWGS; } private Ellipsoid decodeSpheroid() { if (currentToken != CrsWktVariant.SPHEROID) { throw new WktDecodeException("Expected SPHEROID keyword, but received " + currentToken.toString()); } String ellipsoidName = decodeName(); matchesElementSeparator(); double semiMajorAxis = decodeNumber(); matchesElementSeparator(); double inverseFlattening = decodeNumber(); CrsId crsId = decodeOptionalAuthority(CrsId.UNDEFINED.getCode()); matchesCloseList(); return new Ellipsoid(crsId, ellipsoidName, semiMajorAxis, inverseFlattening); } private CrsId decodeOptionalAuthority(int srid) { matchesElementSeparator(); if (currentToken != CrsWktVariant.AUTHORITY) { return CrsId.valueOf(srid); } nextToken(); matchesOpenList(); String authority = decodeText(); matchesElementSeparator(); String value = decodeText(); matchesCloseList(); if (authority.equals("EPSG")) { try { return new CrsId("EPSG", Integer.parseInt(value)); } catch (NumberFormatException e) { throw new WktDecodeException("Expected EPSG integer code, received " + value); } } return CrsId.valueOf(srid); } private String decodeName() { nextToken(); matchesOpenList(); return decodeText(); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy