ucar.unidata.geoloc.ogc.WKTParser Maven / Gradle / Ivy
The newest version!
/*
* Copyright (c) 1998-2018 University Corporation for Atmospheric Research/Unidata
* See LICENSE for license information.
*/
package ucar.unidata.geoloc.ogc;
import java.util.HashMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ucar.nc2.units.SimpleUnit;
import ucar.unidata.geoloc.ProjectionImpl;
import ucar.unidata.geoloc.projection.*;
import java.text.ParseException;
/**
* This class parses OGC WKT Spatial Reference Text.
*
* @author Barrodale Computing Services, Ltd. (Eric Davies)
* @author Unidata Java Development Team
* @deprecated will move in ver6
*/
@Deprecated
public class WKTParser {
private static Logger logger = LoggerFactory.getLogger(WKTParser.class);
/*
* geogcs info
*/
/**
* geo coord sys name
*/
private String geogcsName;
/**
* datum name
*/
private String datumName;
/**
* spheriod name
*/
private String spheroidName;
/**
* major axis, inverse minor axis
*/
private double majorAxis, inverseMinor;
/**
* primeMeridian name
*/
private String primeMeridianName;
/**
* primeMeridian name
*/
private double primeMeridianValue;
/**
* geographic unit name
*/
private String geogUnitName;
/**
* geographic unit value
*/
private double geogUnitValue;
/**
* is this a projection
*/
private boolean isAProjection;
/**
* projection name
*/
private String projName;
/**
* projection type
*/
private String projectionType;
/**
* projection parameters
*/
private HashMap parameters = new HashMap<>();
/**
* projection unit name
*/
private String projUnitName;
/**
* projection unit value
*/
private double projUnitValue;
/**
* parse position
*/
private int position;
/**
* the reader
*/
java.io.StringReader reader;
/**
* Creates a new instance of WKTParser. If the constructor
* succeeds, the spatial reference text was successfully parsed.
*
* @param srtext The spatial reference text to be parsed.
* Geocentric coordinate text is not currently supported.
* @throws ParseException A ParseException is thrown
* if the spatial reference text could not be parsed.
*/
public WKTParser(String srtext) throws ParseException {
reader = new java.io.StringReader(srtext);
if (srtext.startsWith("PROJCS")) {
isAProjection = true;
parseProjcs();
} else {
isAProjection = false;
parseGeogcs();
}
}
/**
* Peek ahead
*
* @return the char
* @throws ParseException problem parsing
*/
private char peek() throws ParseException {
try {
reader.mark(10);
int aChar = reader.read();
reader.reset();
if (aChar < 0) {
return (char) 0;
} else {
return (char) aChar;
}
} catch (java.io.IOException e1) {
throw new ParseException("Strange io error " + e1, position);
}
}
private char getChar() throws ParseException {
try {
int val = reader.read();
position++;
if (val < 0) {
throw new ParseException("unexpected eof of srtext", position);
}
return (char) val;
} catch (java.io.IOException e1) {
throw new ParseException(e1.toString(), position);
}
}
private void eatLiteral(String literal) throws ParseException {
int n = literal.length();
for (int i = 0; i < n; i++) {
char v = getChar();
if (v != literal.charAt(i)) {
throw new ParseException("bad srtext", position);
}
}
}
private double eatReal() throws ParseException {
StringBuilder b = new StringBuilder();
for (;;) {
char t = peek();
if (Character.isDigit(t) || (t == 'e') || (t == 'E') || (t == '.') || (t == '-') || (t == '+')) {
b.append(getChar());
} else {
break;
}
}
try {
return Double.parseDouble(b.toString());
} catch (NumberFormatException e1) {
throw new ParseException("bad number" + e1, position);
}
}
private String eatString() throws ParseException {
StringBuilder b = new StringBuilder();
if (getChar() != '"') {
throw new ParseException("expected string", position);
}
for (;;) {
char t = getChar();
if (t == '"') {
break;
}
b.append(t);
}
return b.toString();
}
private String eatTerm() throws ParseException {
StringBuilder b = new StringBuilder();
for (;;) {
char val = peek();
if (!Character.isJavaIdentifierPart(val)) {
break;
}
b.append(getChar());
}
return b.toString();
}
private void eatComma() throws ParseException {
if (getChar() != ',') {
throw new ParseException("expected comma", position);
}
}
private void eatOpenBrace() throws ParseException {
if (getChar() != '[') {
throw new ParseException("expected [", position);
}
}
private void eatCloseBrace() throws ParseException {
if (getChar() != ']') {
throw new ParseException("expected ]", position);
}
}
private void parseProjcs() throws ParseException {
eatLiteral("PROJCS[");
projName = eatString();
eatComma();
parseGeogcs();
for (;;) {
char next = getChar();
if (next == ']') {
break;
} else if (next != ',') {
throw new ParseException("expected , or ]", position);
} else {
String term = eatTerm();
switch (term) {
case "PARAMETER":
eatParameter();
break;
case "UNIT":
eatProjcsUnit();
break;
case "PROJECTION":
eatProjectionType();
break;
}
}
}
}
private void eatParameter() throws ParseException {
eatOpenBrace();
String parameterName = eatString();
eatComma();
Double value = eatReal();
eatCloseBrace();
parameters.put(parameterName.toLowerCase(), value);
}
private void eatProjcsUnit() throws ParseException {
eatOpenBrace();
projUnitName = eatString();
eatComma();
projUnitValue = eatReal();
eatCloseBrace();
}
private void eatProjectionType() throws ParseException {
eatOpenBrace();
projectionType = eatString();
eatCloseBrace();
}
private void parseGeogcs() throws ParseException {
eatLiteral("GEOGCS[");
geogcsName = eatString();
for (;;) {
char t = getChar();
if (t == ']') {
break;
} else if (t != ',') {
throw new ParseException("expected , or ]", position);
} else {
String term = eatTerm();
switch (term) {
case "DATUM":
eatDatum();
break;
case "PRIMEM":
eatPrimem();
break;
case "UNIT":
eatUnit();
break;
}
}
}
}
private void eatDatum() throws ParseException {
eatOpenBrace();
datumName = eatString();
eatComma();
eatSpheroid();
eatCloseBrace();
}
private void eatPrimem() throws ParseException {
eatOpenBrace();
primeMeridianName = eatString();
eatComma();
primeMeridianValue = eatReal();
eatCloseBrace();
}
private void eatSpheroid() throws ParseException {
eatLiteral("SPHEROID");
eatOpenBrace();
spheroidName = eatString();
eatComma();
majorAxis = eatReal();
eatComma();
inverseMinor = eatReal();
eatCloseBrace();
}
private void eatUnit() throws ParseException {
eatOpenBrace();
geogUnitName = eatString();
eatComma();
geogUnitValue = eatReal();
eatCloseBrace();
}
/**
* Get the name of the geographic coordinate system.
*
* @return the name.
*/
public String getGeogcsName() {
return geogcsName;
}
/**
* Get the datum name. Note that the datum name itself implies information
* not found in the spheroid.
*
* @return The name of the datum.
*/
public String getDatumName() {
return datumName;
}
/**
* Get the name of the spheroid.
*
* @return The name of the spheroid.
*/
public String getSpheroidName() {
return spheroidName;
}
/**
* Get the major axis of the spheroid.
*
* @return The major axis of the spheroid, in meters.
*/
public double getMajorAxis() {
return majorAxis;
}
/**
* Get the inverse flattening.
*
* @return The inverse flattening. Note that this is unitless.
*/
public double getInverseFlattening() {
return inverseMinor;
}
/**
* Get the name of the prime meridian.
*
* @return the name of the prime meridian. Usually "Greenwich".
*/
public String getPrimeMeridianName() {
return primeMeridianName;
}
/**
* Return the value of prime meridian.
*
* @return The longitude of the prime meridian, usually 0.
*/
public double getPrimeMeridianValue() {
return primeMeridianValue;
}
/**
* Get the name of the unit that the prime meridian is expressed in.
*
* @return Tje name of the unit that the prime meridian is expressed in. Usually "Degree".
*/
public String getGeogUnitName() {
return geogUnitName;
}
/**
* Get the size of the unit that the prime meridian is expressed in.
*
* @return The conversion from the prime meridian units to radians.
*/
public double getGeogUnitValue() {
return geogUnitValue;
}
/**
* Inquire if a particular projection parameter is present.
*
* @param name The name of the parameter. Case is ignored.
* @return True if the parameter is present.
*/
public boolean hasParameter(String name) {
return (parameters.containsKey(name.toLowerCase()));
}
/**
* Get the value of the projection parameter. An IllegalArgument exception
* is thrown if the parameter is not found.
*
* @param name The name of the parameter. Case is ignored.
* @return The value of the parameter, as a double.
*/
public double getParameter(String name) {
Double val = parameters.get(name.toLowerCase());
if (val == null) {
throw new IllegalArgumentException("no parameter called " + name);
}
return val;
}
/**
* Determine if the spatial reference text defines a planar projection,
* as opposed to a Geographic coordinate system.
*
* @return True if the spatial reference text defines a planar projection system.
*/
public boolean isPlanarProjection() {
return isAProjection;
}
/**
* Get the name of the projection.
*
* @return The name of the projection.
*/
public String getProjName() {
return projName;
}
/**
* Get the name of the type of projection.
*
* @return Returns the name of the type of the projection. For example,Transverse_Mercator.
* Returns null for geographic coordinate systems.
*/
public String getProjectionType() {
return projectionType;
}
/**
* Get the name of the projection unit.
*
* @return Get the name of the projection unit. Usually "Meter".
*/
public String getProjUnitName() {
return projUnitName;
}
/**
* Get the projection unit value.
*
* @return The size of the projection unit, in meters.
*/
public double getProjUnitValue() {
return projUnitValue;
}
/**
* Convert OGC spatial reference WKT to a ProjectionImpl.
* An IllegalArgumentException may be thrown if a parameter is missing.
*
* @param srp The parsed OGC WKT spatial reference text.
* @return The ProjectionImpl class.
*/
public static ProjectionImpl convertWKTToProjection(WKTParser srp) {
if (!srp.isPlanarProjection()) {
return new ucar.unidata.geoloc.projection.LatLonProjection();
} else {
String projectionType = srp.getProjectionType();
double falseEasting = 0;
double falseNorthing = 0;
ProjectionImpl proj = null;
if (srp.hasParameter("False_Easting")) {
falseEasting = srp.getParameter("False_Easting");
}
if (srp.hasParameter("False_Northing")) {
falseNorthing = srp.getParameter("False_Northing");
}
if ((falseEasting != 0.0) || (falseNorthing != 0.0)) {
double scalef = 1.0;
if (srp.getProjUnitName() != null) {
try {
SimpleUnit unit = SimpleUnit.factoryWithExceptions(srp.getProjUnitName());
scalef = unit.convertTo(srp.getProjUnitValue(), SimpleUnit.kmUnit);
} catch (Exception e) {
logger.warn("{} {} not convertible to km", srp.getProjUnitValue(), srp.getProjUnitName());
}
}
falseEasting *= scalef;
falseNorthing *= scalef;
}
if (srp.getProjName().contains("UTM_Zone_"))
return processUTM(srp);
if ("Transverse_Mercator".equals(projectionType)) {
double lat0 = srp.getParameter("Latitude_Of_Origin");
double scale = srp.getParameter("Scale_Factor");
double tangentLon = srp.getParameter("Central_Meridian");
proj = new TransverseMercator(lat0, tangentLon, scale, falseEasting, falseNorthing);
} else if ("Lambert_Conformal_Conic".equals(projectionType)) {
double lon0 = srp.getParameter("Central_Meridian");
double par1 = srp.getParameter("Standard_Parallel_1");
double par2 = par1;
if (srp.hasParameter("Standard_Parallel_2")) {
par2 = srp.getParameter("Standard_Parallel_2");
}
double lat0 = srp.getParameter("Latitude_Of_Origin");
return new LambertConformal(lat0, lon0, par1, par2, falseEasting, falseNorthing);
} else if ("Albers".equals(projectionType)) {
double lon0 = srp.getParameter("Central_Meridian");
double par1 = srp.getParameter("Standard_Parallel_1");
double par2 = par1;
if (srp.hasParameter("Standard_Parallel_2")) {
par2 = srp.getParameter("Standard_Parallel_2");
}
double lat0 = srp.getParameter("Latitude_Of_Origin");
return new AlbersEqualArea(lat0, lon0, par1, par2, falseEasting, falseNorthing);
} else if ("Stereographic".equals(projectionType)) {
double lont = srp.getParameter("Central_Meridian");
double scale = srp.getParameter("Scale_Factor");
double latt = srp.getParameter("Latitude_Of_Origin");
return new Stereographic(latt, lont, scale, falseEasting, falseNorthing);
} else if ("Mercator".equals(projectionType)) {
double lat0 = srp.getParameter("Latitude_Of_Origin");
double lon0 = srp.getParameter("Central_Meridian");
proj = new Mercator(lon0, lat0, falseEasting, falseNorthing);
} else if ("Universal_Transverse_Mercator".equals(projectionType)) {
// throw new java.text.ParseException(
// "UTM adapter not implemented yet", 0);
}
return proj;
}
}
static ProjectionImpl processUTM(WKTParser srp) {
// NAD_1983_UTM_Zone_12N
String name = srp.getProjName();
int pos = name.indexOf("UTM_Zone_");
String zoneS = name.substring(pos + 9);
char lastC;
int zone = Integer.parseInt(zoneS.substring(0, zoneS.length() - 1));
lastC = zoneS.charAt(zoneS.length() - 1);
boolean isNorth = (lastC == 'N');
return new UtmProjection(zone, isNorth);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy