001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2003-2006, Geotools Project Managment Committee (PMC)
005: * (C) 2002, Institut de Recherche pour le Développement
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License as published by the Free Software Foundation; either
010: * version 2.1 of the License, or (at your option) any later version.
011: *
012: * This library is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: */
017: package org.geotools.referencing.wkt;
018:
019: // J2SE dependencies
020: import java.io.BufferedReader;
021: import java.io.FileNotFoundException;
022: import java.io.IOException;
023: import java.text.ParseException;
024: import java.util.Collection;
025: import java.util.HashSet;
026:
027: // JUnit dependencies
028: import junit.framework.Test;
029: import junit.framework.TestCase;
030: import junit.framework.TestSuite;
031:
032: // OpenGIS dependencies
033: import org.opengis.parameter.ParameterValueGroup;
034: import org.opengis.referencing.crs.CoordinateReferenceSystem;
035:
036: // Geotools dependencies
037: import org.geotools.referencing.crs.DefaultProjectedCRS;
038: import org.geotools.referencing.wkt.AbstractParser;
039: import org.geotools.referencing.wkt.MathTransformParser;
040: import org.geotools.referencing.wkt.Parser;
041: import org.geotools.referencing.TestScript;
042: import org.geotools.test.TestData;
043:
044: /**
045: * Tests the WKT {@link Parser} implementation.
046: *
047: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/referencing/src/test/java/org/geotools/referencing/wkt/ParserTest.java $
048: * @version $Id: ParserTest.java 27848 2007-11-12 13:10:32Z desruisseaux $
049: * @author Yann Cézard
050: * @author Remi Eve
051: * @author Martin Desruisseaux
052: */
053: public final class ParserTest extends TestCase {
054: /**
055: * Run the suite from the command line.
056: */
057: public static void main(String[] args) {
058: org.geotools.util.logging.Logging.GEOTOOLS
059: .forceMonolineConsoleOutput();
060: junit.textui.TestRunner.run(suite());
061: }
062:
063: /**
064: * Returns the test suite.
065: */
066: public static Test suite() {
067: return new TestSuite(ParserTest.class);
068: }
069:
070: /**
071: * Constructs a test case with the given name.
072: */
073: public ParserTest(final String name) {
074: super (name);
075: }
076:
077: /**
078: * Test a hard coded version of a WKT. This is more convenient for debugging.
079: */
080: public void testHardCoded() throws ParseException {
081: final Parser parser = new Parser();
082: String wkt1, wkt2;
083: DefaultProjectedCRS crs1, crs2;
084: ParameterValueGroup param;
085: /*
086: * First, rather simple Mercator projection.
087: * Uses standard units and axis order.
088: */
089: wkt1 = "PROJCS[\"Mercator test\",\n"
090: + " GEOGCS[\"WGS84\",\n"
091: + " DATUM[\"WGS84\",\n"
092: + " SPHEROID[\"WGS84\", 6378137.0, 298.257223563]],\n"
093: + " PRIMEM[\"Greenwich\", 0.0],\n"
094: + " UNIT[\"degree\", 0.017453292519943295],\n"
095: + " AXIS[\"Longitude\", EAST],\n"
096: + " AXIS[\"Latitude\", NORTH]],\n"
097: + " PROJECTION[\"Mercator_1SP\"],\n"
098: + " PARAMETER[\"central_meridian\", -20.0],\n"
099: + " PARAMETER[\"scale_factor\", 1.0],\n"
100: + " PARAMETER[\"false_easting\", 500000.0],\n"
101: + " PARAMETER[\"false_northing\", 0.0],\n"
102: + " UNIT[\"m\", 1.0],\n" + " AXIS[\"x\", EAST],\n"
103: + " AXIS[\"y\", NORTH]]\n";
104: assertTrue(Symbols.DEFAULT.containsAxis(wkt1));
105: crs1 = (DefaultProjectedCRS) parser.parseObject(wkt1);
106: wkt2 = parser.format(crs1);
107: crs2 = (DefaultProjectedCRS) parser.parseObject(wkt2);
108: param = crs1.getConversionFromBase().getParameterValues();
109: assertEquals(crs1, crs2);
110: assertEquals("Mercator_1SP", crs1.getConversionFromBase()
111: .getMethod().getName().getCode());
112: assertTrue(crs1.getConversionFromBase().getMathTransform()
113: .toWKT().startsWith("PARAM_MT[\"Mercator_1SP\""));
114: assertEquals("semi_major", 6378137.0, param.parameter(
115: "semi_major").doubleValue(), 1E-4);
116: assertEquals("semi_minor", 6356752.3, param.parameter(
117: "semi_minor").doubleValue(), 1E-1);
118: assertEquals("central_meridian", -20.0, param.parameter(
119: "central_meridian").doubleValue(), 1E-8);
120: assertEquals("scale_factor", 1.0, param.parameter(
121: "scale_factor").doubleValue(), 1E-8);
122: assertEquals("false_easting", 500000.0, param.parameter(
123: "false_easting").doubleValue(), 1E-4);
124: assertEquals("false_northing", 0.0, param.parameter(
125: "false_northing").doubleValue(), 1E-4);
126: /*
127: * Same Mercator projection as above, but
128: * switch longitude and latitude axis.
129: */
130: wkt1 = "PROJCS[\"Mercator test\",\n"
131: + " GEOGCS[\"WGS84\",\n"
132: + " DATUM[\"WGS84\",\n"
133: + " SPHEROID[\"WGS84\", 6378137.0, 298.257223563]],\n"
134: + " PRIMEM[\"Greenwich\", 0.0],\n"
135: + " UNIT[\"degree\", 0.017453292519943295],\n"
136: + " AXIS[\"Latitude\", NORTH],\n"
137: + " AXIS[\"Longitude\", EAST]],\n"
138: + " PROJECTION[\"Mercator_1SP\"],\n"
139: + " PARAMETER[\"central_meridian\", -20.0],\n"
140: + " PARAMETER[\"scale_factor\", 1.0],\n"
141: + " PARAMETER[\"false_easting\", 500000.0],\n"
142: + " PARAMETER[\"false_northing\", 0.0],\n"
143: + " UNIT[\"m\", 1.0],\n" + " AXIS[\"x\", EAST],\n"
144: + " AXIS[\"y\", NORTH]]\n";
145: assertTrue(Symbols.DEFAULT.containsAxis(wkt1));
146: crs1 = (DefaultProjectedCRS) parser.parseObject(wkt1);
147: wkt2 = parser.format(crs1);
148: crs2 = (DefaultProjectedCRS) parser.parseObject(wkt2);
149: param = crs1.getConversionFromBase().getParameterValues();
150: assertEquals(crs1, crs2);
151: assertEquals("Mercator_1SP", crs1.getConversionFromBase()
152: .getMethod().getName().getCode());
153: assertTrue(crs1.getConversionFromBase().getMathTransform()
154: .toWKT().startsWith("CONCAT_MT[PARAM_MT["));
155: assertEquals("semi_major", 6378137.0, param.parameter(
156: "semi_major").doubleValue(), 1E-4);
157: assertEquals("semi_minor", 6356752.3, param.parameter(
158: "semi_minor").doubleValue(), 1E-1);
159: assertEquals("central_meridian", -20.0, param.parameter(
160: "central_meridian").doubleValue(), 1E-8);
161: assertEquals("scale_factor", 1.0, param.parameter(
162: "scale_factor").doubleValue(), 1E-8);
163: assertEquals("false_easting", 500000.0, param.parameter(
164: "false_easting").doubleValue(), 1E-4);
165: assertEquals("false_northing", 0.0, param.parameter(
166: "false_northing").doubleValue(), 1E-4);
167: /*
168: * Try an other projection (Transverse Mercator).
169: */
170: wkt1 = "PROJCS[\"OSGB 1936 / British National Grid\",\n"
171: + " GEOGCS[\"OSGB 1936\",\n"
172: + " DATUM[\"OSGB_1936\",\n"
173: + " SPHEROID[\"Airy 1830\", 6377563.396, 299.3249646, AUTHORITY[\"EPSG\",\"7001\"]],\n"
174: + " TOWGS84[375.0, -111.0, 431.0, 0.0, 0.0, 0.0, 0.0],\n"
175: + " AUTHORITY[\"EPSG\",\"6277\"]],\n"
176: + " PRIMEM[\"Greenwich\",0.0, AUTHORITY[\"EPSG\",\"8901\"]],\n"
177: + " UNIT[\"DMSH\",0.0174532925199433, AUTHORITY[\"EPSG\",\"9108\"]],\n"
178: + " AXIS[\"Lat\",NORTH],AXIS[\"Long\",EAST], AUTHORITY[\"EPSG\",\"4277\"]],\n"
179: + " PROJECTION[\"Transverse_Mercator\"],\n"
180: + " PARAMETER[\"latitude_of_origin\", 49.0],\n"
181: + " PARAMETER[\"central_meridian\", -2.0],\n"
182: + " PARAMETER[\"scale_factor\", 0.999601272],\n"
183: + " PARAMETER[\"false_easting\", 400000.0],\n"
184: + " PARAMETER[\"false_northing\", -100000.0],\n"
185: + " UNIT[\"metre\", 1.0, AUTHORITY[\"EPSG\",\"9001\"]],\n"
186: + " AXIS[\"E\",EAST],\n" + " AXIS[\"N\",NORTH],\n"
187: + " AUTHORITY[\"EPSG\",\"27700\"]]\n";
188: assertTrue(Symbols.DEFAULT.containsAxis(wkt1));
189: crs1 = (DefaultProjectedCRS) parser.parseObject(wkt1);
190: wkt2 = parser.format(crs1);
191: crs2 = (DefaultProjectedCRS) parser.parseObject(wkt2);
192: param = crs1.getConversionFromBase().getParameterValues();
193: assertEquals(crs1, crs2);
194: assertEquals("Transverse_Mercator", crs1
195: .getConversionFromBase().getMethod().getName()
196: .getCode());
197: assertEquals("semi_major", 6377563.396, param.parameter(
198: "semi_major").doubleValue(), 1E-4);
199: assertEquals("semi_minor", 6356256.909, param.parameter(
200: "semi_minor").doubleValue(), 1E-3);
201: assertEquals("latitude_of_origin", 49.0, param.parameter(
202: "latitude_of_origin").doubleValue(), 1E-8);
203: assertEquals("central_meridian", -2.0, param.parameter(
204: "central_meridian").doubleValue(), 1E-8);
205: assertEquals("scale_factor", 0.9996, param.parameter(
206: "scale_factor").doubleValue(), 1E-5);
207: assertEquals("false_easting", 400000.0, param.parameter(
208: "false_easting").doubleValue(), 1E-4);
209: assertEquals("false_northing", -100000.0, param.parameter(
210: "false_northing").doubleValue(), 1E-4);
211: /*
212: * Try a projection with feet units.
213: */
214: wkt1 = "PROJCS[\"TransverseMercator\",\n"
215: + " GEOGCS[\"Sphere\",\n"
216: + " DATUM[\"Sphere\",\n"
217: + " SPHEROID[\"Sphere\", 6370997.0, 0.0],\n"
218: + " TOWGS84[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]],\n"
219: + " PRIMEM[\"Greenwich\", 0.0],\n"
220: + " UNIT[\"degree\", 0.017453292519943295],\n"
221: + " AXIS[\"Longitude\", EAST],\n"
222: + " AXIS[\"Latitude\", NORTH]],\n"
223: + " PROJECTION[\"Transverse_Mercator\",\n"
224: + " AUTHORITY[\"OGC\",\"Transverse_Mercator\"]],\n"
225: + " PARAMETER[\"central_meridian\", 170.0],\n"
226: + " PARAMETER[\"latitude_of_origin\", 50.0],\n"
227: + " PARAMETER[\"scale_factor\", 0.95],\n"
228: + " PARAMETER[\"false_easting\", 0.0],\n"
229: + " PARAMETER[\"false_northing\", 0.0],\n"
230: + " UNIT[\"feet\", 0.304800609601219],\n"
231: + " AXIS[\"x\", EAST],\n" + " AXIS[\"y\", NORTH]]\n";
232: assertTrue(Symbols.DEFAULT.containsAxis(wkt1));
233: crs1 = (DefaultProjectedCRS) parser.parseObject(wkt1);
234: wkt2 = parser.format(crs1);
235: crs2 = (DefaultProjectedCRS) parser.parseObject(wkt2);
236: param = crs1.getConversionFromBase().getParameterValues();
237: assertEquals(crs1, crs2);
238: assertEquals("Transverse_Mercator", crs1
239: .getConversionFromBase().getMethod().getName()
240: .getCode());
241: assertEquals("semi_major", 6370997.0, param.parameter(
242: "semi_major").doubleValue(), 1E-5);
243: assertEquals("semi_minor", 6370997.0, param.parameter(
244: "semi_minor").doubleValue(), 1E-5);
245: assertEquals("latitude_of_origin", 50.0, param.parameter(
246: "latitude_of_origin").doubleValue(), 1E-8);
247: assertEquals("central_meridian", 170.0, param.parameter(
248: "central_meridian").doubleValue(), 1E-8);
249: assertEquals("scale_factor", 0.95, param.parameter(
250: "scale_factor").doubleValue(), 1E-8);
251: assertEquals("false_easting", 0.0, param.parameter(
252: "false_easting").doubleValue(), 1E-8);
253: assertEquals("false_northing", 0.0, param.parameter(
254: "false_northing").doubleValue(), 1E-8);
255: /*
256: * Try with a number using scientific notation.
257: */
258: wkt1 = "GEOGCS[\"NAD83 / NFIS Seconds\",DATUM[\"North_American_Datum_1983\",\n"
259: + " SPHEROID[\"GRS 1980\", 6378137, 298.257222101]],\n"
260: + " PRIMEM[\"Greenwich\", 0],\n"
261: + " UNIT[\"Decimal_Second\", 4.84813681109536e-06],\n"
262: + " AUTHORITY[\"EPSG\", \"100001\"]]";
263: assertFalse(Symbols.DEFAULT.containsAxis(wkt1));
264: parser.parseObject(wkt1);
265: }
266:
267: /**
268: * Tests the Oracle variant of WKT.
269: */
270: public void testOracleWKT() throws ParseException {
271: final String wkt = "PROJCS[\"Datum 73 / Modified Portuguese Grid\","
272: + " GEOGCS [ \"Datum 73\","
273: + " DATUM[\"Datum 73 (EPSG ID 6274)\","
274: + " SPHEROID [\"International 1924 (EPSG ID 7022)\", 6378388, 297],"
275: + " -231, 102.6, 29.8, .6149999999999993660366746131394108039579,"
276: + " -.1979999999999997958947342656936639661522,"
277: + " .8809999999999990918346509498793836069706, .99999821],"
278: + " PRIMEM [ \"Greenwich\", 0.000000 ],"
279: + " UNIT [\"Decimal Degree\", 0.01745329251994328]],"
280: + " PROJECTION[\"Transverse_Mercator\"],"
281: +
282: // " PROJECTION[\"Modified Portuguese Grid (EPSG OP 19974)\"]," +
283: // TODO: The real projection is "Modified Portugues", but it is not yet implemented in Geotools.
284: " PARAMETER[\"Latitude_Of_Origin\", 39.66666666666666666666666666666666666667],"
285: + " PARAMETER[\"Central_Meridian\", -8.13190611111111111111111111111111111111],"
286: + " PARAMETER[\"Scale_Factor\", 1],"
287: + " PARAMETER [\"False_Easting\", 180.598],"
288: + " PARAMETER[\"False_Northing\", -86.99],"
289: + " UNIT [\"Meter\", 1]]";
290: assertFalse(Symbols.DEFAULT.containsAxis(wkt));
291: final Parser parser = new Parser();
292: CoordinateReferenceSystem crs1 = parser
293: .parseCoordinateReferenceSystem(wkt);
294: final String check = parser.format(crs1);
295: assertTrue(check.indexOf("TOWGS84[-231") >= 0);
296: CoordinateReferenceSystem crs2 = parser
297: .parseCoordinateReferenceSystem(check);
298: assertEquals(crs1, crs2);
299: }
300:
301: /**
302: * Parse parsing of math transforms.
303: */
304: public void testMathTransform() throws IOException, ParseException {
305: testParsing(new MathTransformParser(), "wkt/MathTransform.txt");
306: }
307:
308: /**
309: * Parse parsing of coordinate reference systems.
310: */
311: public void testCoordinateReferenceSystem() throws IOException,
312: ParseException {
313: testParsing(new Parser(), "wkt/CoordinateReferenceSystem.txt");
314: }
315:
316: /**
317: * Parse all elements from the specified file. Parsing creates a set of
318: * geographic objects. No special processing are done with them; we just
319: * check if the parsing work without error and produces distincts objects.
320: */
321: private void testParsing(final AbstractParser parser,
322: final String filename) throws IOException, ParseException {
323: final BufferedReader reader = TestData.openReader(
324: TestScript.class, filename);
325: if (reader == null) {
326: throw new FileNotFoundException(filename);
327: }
328: final Collection pool = new HashSet();
329: String line;
330: while ((line = reader.readLine()) != null) {
331: line = line.trim();
332: if (line.length() == 0 || line.startsWith("#")) {
333: continue;
334: }
335: /*
336: * Parse a line. If the parse fails, then dump the WKT
337: * and rethrow the exception.
338: */
339: final Object parsed;
340: try {
341: parsed = parser.parseObject(line);
342: } catch (ParseException exception) {
343: System.err.println();
344: System.err.println("-----------------------------");
345: System.err.println("Parse failed. Dump WKT below.");
346: System.err.println("-----------------------------");
347: System.err.println(line);
348: System.err.println();
349: throw exception;
350: }
351: assertNotNull("Parsing returns null.", parsed);
352: assertEquals("Inconsistent equals method", parsed, parsed);
353: assertSame("Parsing twice returns different objects.",
354: parsed, parser.parseObject(line));
355: assertTrue("An identical object already exists.", pool
356: .add(parsed));
357: assertTrue("Inconsistent hashCode or equals method.", pool
358: .contains(parsed));
359: /*
360: * Format the object and parse it again.
361: * Ensure that the result is consistent.
362: */
363: String formatted = parser.format(parsed);
364: final Object again;
365: try {
366: again = parser.parseObject(formatted);
367: } catch (ParseException exception) {
368: System.err.println();
369: System.err
370: .println("------------------------------------");
371: System.err
372: .println("Second parse failed. Dump WKT below.");
373: System.err
374: .println("------------------------------------");
375: System.err.println(line);
376: System.err.println();
377: System.err
378: .println("------ Reformatted WKT below -------");
379: System.err.println();
380: System.err.println(formatted);
381: System.err.println();
382: throw exception;
383: }
384: assertEquals("Second parsing produced different objects",
385: parsed, again);
386: assertTrue("Inconsistent hashCode or equals method.", pool
387: .contains(again));
388: }
389: reader.close();
390: }
391: }
|