root / org.gvsig.geotools.proj / trunk / org.gvsig.geotools.proj / org.gvsig.geotools.proj.catalog.impl / src / main / java / org / gvsig / geotools / proj / catalog / GtCRSCatalogManager.java @ 867
History | View | Annotate | Download (22.9 KB)
1 |
package org.gvsig.geotools.proj.catalog; |
---|---|
2 |
|
3 |
import java.io.File; |
4 |
import java.sql.Connection; |
5 |
import java.sql.PreparedStatement; |
6 |
import java.sql.ResultSet; |
7 |
import java.sql.SQLException; |
8 |
import java.text.ParseException; |
9 |
import java.util.ArrayList; |
10 |
import java.util.Arrays; |
11 |
import java.util.Collection; |
12 |
import java.util.Collections; |
13 |
import java.util.HashMap; |
14 |
import java.util.List; |
15 |
import java.util.Map; |
16 |
import java.util.Set; |
17 |
import java.util.regex.Pattern; |
18 |
|
19 |
import javax.sql.DataSource; |
20 |
|
21 |
import org.geotools.factory.FactoryFinder; |
22 |
import org.geotools.factory.FactoryNotFoundException; |
23 |
import org.geotools.factory.Hints; |
24 |
import org.geotools.metadata.iso.citation.Citations; |
25 |
import org.geotools.referencing.CRS; |
26 |
import org.geotools.referencing.CRS.AxisOrder; |
27 |
import org.geotools.referencing.ReferencingFactoryFinder; |
28 |
import org.geotools.referencing.factory.AbstractAuthorityFactory; |
29 |
import org.geotools.referencing.factory.BufferedAuthorityFactory; |
30 |
import org.geotools.referencing.factory.epsg.HsqlEpsgDatabase; |
31 |
import org.geotools.referencing.factory.epsg.ThreadedEpsgFactory; |
32 |
import org.geotools.referencing.wkt.MathTransformParser; |
33 |
import org.geotools.referencing.wkt.Parser; |
34 |
import org.geotools.resources.i18n.ErrorKeys; |
35 |
import org.geotools.resources.i18n.Errors; |
36 |
import org.gvsig.geotools.proj.catalog.extent.DefaultExtent; |
37 |
import org.gvsig.geotools.proj.catalog.extent.DefaultGeographicBoundingBox; |
38 |
import org.gvsig.geotools.proj.catalog.extent.DefaultVerticalExtent; |
39 |
import org.gvsig.geotools.proj.catalog.utils.GtUtils; |
40 |
import org.gvsig.geotools.proj.catalog.utils.WKTUtils; |
41 |
import org.gvsig.proj.catalog.CRSCatalogManager; |
42 |
import org.gvsig.proj.catalog.CRSDefinition; |
43 |
import org.gvsig.proj.catalog.CRSType; |
44 |
import org.gvsig.proj.catalog.TextSerialization; |
45 |
import org.gvsig.proj.catalog.TextSerialization.Format; |
46 |
import org.gvsig.proj.catalog.TransformationDefinition; |
47 |
import org.gvsig.proj.catalog.exception.CoordinateReferenceSystemException; |
48 |
import org.gvsig.proj.catalog.exception.UnsupportedCoordinateReferenceSystemException; |
49 |
import org.gvsig.proj.catalog.exception.UnsupportedFormatException; |
50 |
import org.gvsig.proj.catalog.exception.UnsupportedTransformationException; |
51 |
import org.gvsig.proj.catalog.extent.Extent; |
52 |
import org.gvsig.proj.catalog.extent.GeographicBoundingBox; |
53 |
import org.gvsig.proj.catalog.extent.VerticalExtent; |
54 |
import org.opengis.referencing.AuthorityFactory; |
55 |
import org.opengis.referencing.FactoryException; |
56 |
import org.opengis.referencing.NoSuchAuthorityCodeException; |
57 |
import org.opengis.referencing.crs.CRSAuthorityFactory; |
58 |
import org.opengis.referencing.crs.CRSFactory; |
59 |
import org.opengis.referencing.crs.CompoundCRS; |
60 |
import org.opengis.referencing.crs.CoordinateReferenceSystem; |
61 |
import org.opengis.referencing.crs.GeocentricCRS; |
62 |
import org.opengis.referencing.crs.GeographicCRS; |
63 |
import org.opengis.referencing.cs.CartesianCS; |
64 |
import org.opengis.referencing.cs.CoordinateSystem; |
65 |
import org.opengis.referencing.cs.EllipsoidalCS; |
66 |
import org.opengis.referencing.cs.SphericalCS; |
67 |
import org.opengis.referencing.cs.VerticalCS; |
68 |
import org.opengis.referencing.datum.EngineeringDatum; |
69 |
import org.opengis.referencing.datum.GeodeticDatum; |
70 |
import org.opengis.referencing.datum.VerticalDatum; |
71 |
import org.opengis.referencing.operation.Conversion; |
72 |
import org.opengis.referencing.operation.CoordinateOperation; |
73 |
import org.opengis.referencing.operation.CoordinateOperationAuthorityFactory; |
74 |
import org.opengis.referencing.operation.CoordinateOperationFactory; |
75 |
import org.opengis.referencing.operation.MathTransform; |
76 |
import org.opengis.referencing.operation.Projection; |
77 |
|
78 |
public class GtCRSCatalogManager implements CRSCatalogManager { |
79 |
private static final String EPSG_DB_SUBFOLDER = "epsg"; |
80 |
private static final List<TextSerialization.Format> SUPPORTED_FORMATS = Arrays.asList(TextSerialization.Format.WKT1); |
81 |
private static final List<String> supportedAuthorities = Collections.unmodifiableList(Arrays.asList("EPSG", "ESRI", "USER")); |
82 |
|
83 |
public GtCRSCatalogManager() {
|
84 |
|
85 |
} |
86 |
|
87 |
@Override
|
88 |
public List<String> getAuthorityNames() { |
89 |
return supportedAuthorities;
|
90 |
//return new ArrayList<String>(CRS.getSupportedAuthorities(true));
|
91 |
} |
92 |
|
93 |
protected String toCode(String authorityName, String relCode) { |
94 |
return authorityName + ":" + relCode; |
95 |
} |
96 |
|
97 |
@Override
|
98 |
public List<String> getCodes() { |
99 |
ArrayList<String> codes = new ArrayList<String>(); |
100 |
Set<String> authorities = CRS.getSupportedAuthorities(true); |
101 |
for (String auth: authorities) { |
102 |
CRSAuthorityFactory factory = ReferencingFactoryFinder.getCRSAuthorityFactory(auth, null);
|
103 |
try {
|
104 |
for (String code: factory.getAuthorityCodes(CoordinateReferenceSystem.class)) { |
105 |
codes.add(toCode(auth, code)); |
106 |
} |
107 |
} catch (FactoryException | FactoryNotFoundException e) {
|
108 |
// TODO Auto-generated catch block
|
109 |
e.printStackTrace(); |
110 |
} |
111 |
} |
112 |
return codes;
|
113 |
} |
114 |
|
115 |
@Override
|
116 |
public List<String> getCodes(String authorityName) { |
117 |
// FIXME handle other authorities
|
118 |
ArrayList<String> codes = new ArrayList<String>(); |
119 |
|
120 |
if ("EPSG".equals(authorityName)) { |
121 |
try {
|
122 |
CRSAuthorityFactory factory = ReferencingFactoryFinder.getCRSAuthorityFactory(authorityName, null);
|
123 |
for (String code: factory.getAuthorityCodes(CoordinateReferenceSystem.class)) { |
124 |
codes.add(toCode(authorityName, code)); |
125 |
} |
126 |
|
127 |
} catch (FactoryException | FactoryNotFoundException e) {
|
128 |
// TODO Auto-generated catch block
|
129 |
e.printStackTrace(); |
130 |
} |
131 |
} |
132 |
return codes;
|
133 |
} |
134 |
|
135 |
@Override
|
136 |
public List<String> search(String searchString) { |
137 |
// FIXME handle other authorities
|
138 |
return searchEpsg(searchString, null, null); |
139 |
} |
140 |
|
141 |
@Override
|
142 |
public List<String> search(String authority, String searchString) { |
143 |
// FIXME handle other authorities
|
144 |
if (authority.equals("EPSG")) { |
145 |
return searchEpsg(searchString, null, null); |
146 |
} |
147 |
return Collections.emptyList(); |
148 |
} |
149 |
|
150 |
@Override
|
151 |
public List<String> search(String authority, String searchString, CRSType[] includeTypes, CRSType[] excludeTypes) { |
152 |
// FIXME handle other authorities
|
153 |
if (authority.equals("EPSG")) { |
154 |
return searchEpsg(searchString, includeTypes, excludeTypes);
|
155 |
} |
156 |
return Collections.emptyList(); |
157 |
} |
158 |
|
159 |
|
160 |
protected List<String> searchEpsg(String searchString, CRSType[] includeTypes, CRSType[] excludeTypes) { |
161 |
// FIXME handle other authorities
|
162 |
CRSAuthorityFactory factory = ReferencingFactoryFinder.getCRSAuthorityFactory("EPSG", null); |
163 |
if (factory instanceof ThreadedEpsgFactory) { |
164 |
ThreadedEpsgFactory epsgFactory = (ThreadedEpsgFactory) factory; |
165 |
try {
|
166 |
DataSource ds = epsgFactory.getDataSource();
|
167 |
Connection c = ds.getConnection();
|
168 |
return searchEpsg(searchString, c, includeTypes, excludeTypes);
|
169 |
} catch (SQLException e) { |
170 |
// TODO Auto-generated catch block
|
171 |
e.printStackTrace(); |
172 |
} |
173 |
} |
174 |
return Collections.EMPTY_LIST; |
175 |
} |
176 |
|
177 |
private boolean isExcluded(CRSType type, CRSType[] excludeTypes) { |
178 |
for (CRSType excluded: excludeTypes) {
|
179 |
if (type.equals(excluded)) {
|
180 |
return true; |
181 |
} |
182 |
} |
183 |
return false; |
184 |
} |
185 |
|
186 |
public synchronized List<String> searchEpsg(String searchString, Connection conn, |
187 |
CRSType[] includeTypes, CRSType[] excludeTypes) throws SQLException |
188 |
{ |
189 |
ArrayList<String> codes = new ArrayList<String>(); |
190 |
|
191 |
if (searchString == null) { |
192 |
searchString = "";
|
193 |
} |
194 |
else if (searchString.startsWith("EPSG:")) { |
195 |
searchString = searchString.substring(5);
|
196 |
} |
197 |
searchString = "%" + searchString.toLowerCase() + "%"; |
198 |
StringBuilder builder = new StringBuilder("SELECT COORD_REF_SYS_CODE," |
199 |
+ " COORD_REF_SYS_NAME,"
|
200 |
+ " AREA_OF_USE_CODE,"
|
201 |
+ " CRS_SCOPE,"
|
202 |
+ " REMARKS,"
|
203 |
+ " COORD_REF_SYS_KIND,"
|
204 |
+ " COORD_SYS_CODE," // Null for CompoundCRS |
205 |
+ " DATUM_CODE," // Null for ProjectedCRS |
206 |
+ " SOURCE_GEOGCRS_CODE," // For ProjectedCRS |
207 |
+ " PROJECTION_CONV_CODE," // For ProjectedCRS |
208 |
+ " CMPD_HORIZCRS_CODE," // For CompoundCRS only |
209 |
+ " CMPD_VERTCRS_CODE," // For CompoundCRS only |
210 |
+ " DEPRECATED"
|
211 |
+ " FROM epsg_coordinatereferencesystem"
|
212 |
+ " WHERE DEPRECATED = 0 AND (COORD_REF_SYS_CODE LIKE ? OR LCASE(COORD_REF_SYS_NAME) LIKE ?"
|
213 |
+ " OR LCASE(REMARKS) LIKE ?"
|
214 |
+ " OR LCASE(CRS_SCOPE) LIKE ?)");
|
215 |
|
216 |
if (includeTypes != null) { |
217 |
boolean first = true; |
218 |
builder.append(" AND (");
|
219 |
for (CRSType type: includeTypes) {
|
220 |
if (first) {
|
221 |
first = false;
|
222 |
builder.append("COORD_REF_SYS_KIND LIKE '").append(type.toEpsgString()).append("'"); |
223 |
} |
224 |
else {
|
225 |
builder.append(" OR COORD_REF_SYS_KIND LIKE '").append(type.toEpsgString()).append("'"); |
226 |
} |
227 |
} |
228 |
builder.append(")");
|
229 |
} |
230 |
if (excludeTypes != null) { |
231 |
boolean first = true; |
232 |
builder.append(" AND NOT(");
|
233 |
for (CRSType type: excludeTypes) {
|
234 |
if (first) {
|
235 |
first = false;
|
236 |
builder.append("COORD_REF_SYS_KIND LIKE '").append(type.toEpsgString()).append("'"); |
237 |
} |
238 |
else {
|
239 |
builder.append(" OR COORD_REF_SYS_KIND LIKE '").append(type.toEpsgString()).append("'"); |
240 |
} |
241 |
} |
242 |
builder.append(")");
|
243 |
} |
244 |
|
245 |
try {
|
246 |
// FIXME: JOIN query with area of use. Maybe also with COORD_SYS_CODE to search for coord sys name
|
247 |
final PreparedStatement stmt; |
248 |
stmt = conn.prepareStatement(builder.toString()); |
249 |
stmt.setString(1, searchString);
|
250 |
stmt.setString(2, searchString);
|
251 |
stmt.setString(3, searchString);
|
252 |
stmt.setString(4, searchString);
|
253 |
ResultSet result = stmt.executeQuery();
|
254 |
while (result.next()) {
|
255 |
final String epsg = result.getString(1);//getString(result, 1, code); |
256 |
final String name = result.getString(2);//getString(result, 2, code); |
257 |
final String area = result.getString(3); |
258 |
final String scope = result.getString(4); |
259 |
final String remarks = result.getString(5); |
260 |
final String kind = result.getString(6); |
261 |
|
262 |
final String csCode = result.getString(7); |
263 |
final String dmCode = result.getString( 8); // geographic |
264 |
final String geoCode = result.getString(9); |
265 |
final String opCode = result.getString(10); |
266 |
// vertical:
|
267 |
final String code1 = result.getString(11); |
268 |
final String code2 = result.getString(12); |
269 |
codes.add("EPSG:"+epsg);
|
270 |
} |
271 |
result.close(); |
272 |
} catch (SQLException exception) { |
273 |
throw exception;
|
274 |
} |
275 |
conn.close(); |
276 |
return codes;
|
277 |
} |
278 |
|
279 |
@Override
|
280 |
public DefaultCRSDefinition getCRSDefinition(String code) throws UnsupportedCoordinateReferenceSystemException { |
281 |
CoordinateReferenceSystem crs; |
282 |
CoordinateReferenceSystem internalCrs; |
283 |
try {
|
284 |
crs = CRS.decode(code, false);
|
285 |
if (CRS.getAxisOrder(crs) == AxisOrder.NORTH_EAST) {
|
286 |
internalCrs = CRS.decode(code, true);
|
287 |
} |
288 |
else {
|
289 |
internalCrs = crs; |
290 |
} |
291 |
return new DefaultCRSDefinition(crs, internalCrs, null); |
292 |
} catch (NoSuchAuthorityCodeException e) {
|
293 |
throw new UnsupportedCoordinateReferenceSystemException(code, e); |
294 |
} catch (FactoryException e) {
|
295 |
throw new UnsupportedCoordinateReferenceSystemException(code, e); |
296 |
} |
297 |
} |
298 |
|
299 |
public DefaultCRSDefinition getCRSDefinition(CoordinateReferenceSystem crs) throws UnsupportedCoordinateReferenceSystemException { |
300 |
return new DefaultCRSDefinition(crs); |
301 |
} |
302 |
|
303 |
@Override
|
304 |
public CRSDefinition getCompoundCRS(CRSDefinition... crsList) throws UnsupportedCoordinateReferenceSystemException { |
305 |
ArrayList<CoordinateReferenceSystem> components = new ArrayList<CoordinateReferenceSystem>(); |
306 |
for (CRSDefinition def: crsList) {
|
307 |
if (def instanceof DefaultCRSDefinition) { |
308 |
components.add(((DefaultCRSDefinition)def).getInternalCRS()); |
309 |
} |
310 |
else {
|
311 |
def = parseCRSDefinition(def.toWKT()); |
312 |
} |
313 |
} |
314 |
CRSFactory crsFactory = ReferencingFactoryFinder.getCRSFactory(null);
|
315 |
CoordinateReferenceSystem compoundCRS; |
316 |
try {
|
317 |
Map<String, String> properties = new HashMap<String, String>(); |
318 |
crsFactory.createCompoundCRS(properties, components.toArray(new CoordinateReferenceSystem[components.size()]));
|
319 |
compoundCRS = crsFactory.createCompoundCRS(properties, components.toArray(new CoordinateReferenceSystem[components.size()]));;
|
320 |
return new DefaultCRSDefinition(compoundCRS); |
321 |
} catch (FactoryException e) {
|
322 |
throw new UnsupportedCoordinateReferenceSystemException(e); |
323 |
} |
324 |
} |
325 |
|
326 |
/**
|
327 |
* Removes axis definition from a WKT string
|
328 |
*
|
329 |
* @param wktDef
|
330 |
* @return A WKT string without any axis definition
|
331 |
*/
|
332 |
private static String removeWktAxis(String wktDef) { |
333 |
return WKTUtils.removeAxisDefinition(wktDef);
|
334 |
} |
335 |
|
336 |
@Override
|
337 |
public DefaultCRSDefinition parseCRSDefinition(String def) throws UnsupportedCoordinateReferenceSystemException { |
338 |
CoordinateReferenceSystem crs; |
339 |
CoordinateReferenceSystem internalCrs; |
340 |
try {
|
341 |
crs = CRS.parseWKT(def); |
342 |
if (CRS.getAxisOrder(crs)==AxisOrder.NORTH_EAST) {
|
343 |
String id = GtUtils.getIdentifier(crs);
|
344 |
if (id != null && id.startsWith("EPSG:")) { //FIXME: could this also work for other authorities such as ESRI? |
345 |
internalCrs = CRS.decode(id, true);
|
346 |
} |
347 |
else {
|
348 |
// Hack: remove the axis from the WKT. It could be better to try to derive a CRS with default axis order, but I don't see the way for non EPSG CRSs
|
349 |
internalCrs = CRS.parseWKT(removeWktAxis(def)); |
350 |
} |
351 |
} |
352 |
else {
|
353 |
internalCrs = crs; |
354 |
} |
355 |
} catch (NoSuchAuthorityCodeException e) {
|
356 |
throw new UnsupportedCoordinateReferenceSystemException(def, e); |
357 |
} catch (FactoryException e) {
|
358 |
throw new UnsupportedCoordinateReferenceSystemException(def, e); |
359 |
} |
360 |
return new DefaultCRSDefinition(crs, internalCrs, def); |
361 |
} |
362 |
|
363 |
|
364 |
@Override
|
365 |
public DefaultCRSDefinition parseCRSDefinition(String def, Format format) |
366 |
throws UnsupportedCoordinateReferenceSystemException, UnsupportedFormatException {
|
367 |
if (SUPPORTED_FORMATS.contains(format)) {
|
368 |
parseCRSDefinition(def); |
369 |
} |
370 |
throw new UnsupportedFormatException(format); |
371 |
} |
372 |
|
373 |
@Override
|
374 |
public TransformationDefinition getTransformationDefinition(String code) |
375 |
throws UnsupportedTransformationException {
|
376 |
try {
|
377 |
AuthorityFactory factory = ReferencingFactoryFinder.getCoordinateOperationAuthorityFactory( |
378 |
"EPSG",
|
379 |
null);
|
380 |
CoordinateOperation op; |
381 |
if (factory instanceof AbstractAuthorityFactory) { |
382 |
op = ((AbstractAuthorityFactory)factory).createCoordinateOperation(code); |
383 |
} |
384 |
else {
|
385 |
Object obj;
|
386 |
// We need to check the returned object type, since AuthorityFactory.createObject()
|
387 |
// will not create a CoordinateOperatoin if there is a CRS that has the same code as the coordinate operation
|
388 |
obj = factory.createObject(code); |
389 |
if (obj instanceof CoordinateOperation) { |
390 |
// we have it
|
391 |
op = (CoordinateOperation) obj; |
392 |
} |
393 |
else { // we found another object having the same code, sigh |
394 |
throw new UnsupportedTransformationException(code); |
395 |
} |
396 |
} |
397 |
return new DefaultTransformationDefinition(op, |
398 |
getCRSDefinition(op.getSourceCRS()), getCRSDefinition(op.getTargetCRS())); |
399 |
} catch (FactoryException | CoordinateReferenceSystemException e) {
|
400 |
throw new UnsupportedTransformationException(code, e); |
401 |
} |
402 |
} |
403 |
|
404 |
@Override
|
405 |
public TransformationDefinition parseTransformationDefinition(String def, String sourceCRS, String targetCRS) |
406 |
throws UnsupportedTransformationException, ParseException { |
407 |
DefaultCRSDefinition source; |
408 |
try {
|
409 |
source = parseCRSDefinition(sourceCRS); |
410 |
DefaultCRSDefinition target = parseCRSDefinition(sourceCRS); |
411 |
MathTransformParser parser = new MathTransformParser();
|
412 |
MathTransform mt = parser.parseMathTransform(def); |
413 |
return new DefaultTransformationDefinition(mt, source, target); |
414 |
} catch (CoordinateReferenceSystemException e) {
|
415 |
throw new UnsupportedTransformationException(e); |
416 |
} |
417 |
} |
418 |
|
419 |
@Override
|
420 |
public TransformationDefinition parseTransformationDefinition(String def, String sourceCRS, String targetCRS, |
421 |
Format format) throws UnsupportedTransformationException, ParseException, UnsupportedFormatException { |
422 |
if (format==Format.WKT1) { |
423 |
return parseTransformationDefinition(def, sourceCRS, targetCRS);
|
424 |
} |
425 |
throw new UnsupportedFormatException(format); |
426 |
} |
427 |
|
428 |
@Override
|
429 |
public DefaultTransformationDefinition parseTransformationDefinition(String def) |
430 |
throws ParseException, CoordinateReferenceSystemException { |
431 |
// This implementation don't support this method because only WKT1 format is supported,
|
432 |
// but try to parse to raise an indicative exception
|
433 |
MathTransformParser parser = new MathTransformParser();
|
434 |
parser.parseMathTransform(def); |
435 |
throw new CoordinateReferenceSystemException("Not enough information to construct the transformation. WKT1 does not encode source and target CRSs"); |
436 |
} |
437 |
|
438 |
@Override
|
439 |
public DefaultTransformationDefinition parseTransformationDefinition(String def, Format format) |
440 |
throws ParseException, CoordinateReferenceSystemException { |
441 |
if (SUPPORTED_FORMATS.contains(format)) {
|
442 |
parseTransformationDefinition(def); |
443 |
} |
444 |
throw new UnsupportedFormatException(format); |
445 |
} |
446 |
|
447 |
@Override
|
448 |
public String registerCoordinateReferenceSystem(String wktDefinition, String description) { |
449 |
// TODO Auto-generated method stub
|
450 |
return null; |
451 |
} |
452 |
|
453 |
@Override
|
454 |
public String registerTransformation(String wktDefinition, String sourceCRS, String targetCRS, String description) |
455 |
throws UnsupportedTransformationException, ParseException { |
456 |
// TODO Auto-generated method stub
|
457 |
return null; |
458 |
} |
459 |
|
460 |
@Override
|
461 |
public String registerCoordinateTransformationPVT(String sourceCRS, String targetCRS, String description, |
462 |
float xTraslation, float yTraslation, float zTraslation, float xRotation, float yRotation, float zRotation, |
463 |
float scaleDifference) {
|
464 |
// TODO Auto-generated method stub
|
465 |
return null; |
466 |
} |
467 |
|
468 |
@Override
|
469 |
public String registerCoordinateTransformationCFR(String sourceCRS, String targetCRS, String description, |
470 |
float xTraslation, float yTraslation, float zTraslation, float xRotation, float yRotation, float zRotation, |
471 |
float scaleDifference) {
|
472 |
// TODO Auto-generated method stub
|
473 |
return null; |
474 |
} |
475 |
|
476 |
@Override
|
477 |
public String registerCoordinateTransformation(String sourceCRS, String targetCRS, String description, |
478 |
File ntv2Grid) {
|
479 |
// TODO Auto-generated method stub
|
480 |
return null; |
481 |
} |
482 |
|
483 |
@Override
|
484 |
public List<TransformationDefinition> getCoordinateTransformations(CRSDefinition source, CRSDefinition target) |
485 |
throws UnsupportedTransformationException {
|
486 |
DefaultCRSDefinition sourceDef = (DefaultCRSDefinition) source; |
487 |
DefaultCRSDefinition targetDef = (DefaultCRSDefinition) target; |
488 |
ArrayList<TransformationDefinition> transforms = new ArrayList<TransformationDefinition>(); |
489 |
try {
|
490 |
CoordinateReferenceSystem sourceCRS = sourceDef.getInternalCRS(); |
491 |
CoordinateReferenceSystem targetCRS = targetDef.getInternalCRS(); |
492 |
CoordinateOperationFactory operationFactory = CRS.getCoordinateOperationFactory(false);
|
493 |
Set<CoordinateOperation> ops = operationFactory.findOperations(sourceCRS, targetCRS);
|
494 |
for (CoordinateOperation op: ops) {
|
495 |
if (GtUtils.getIdentifier(op) == null) { |
496 |
CoordinateOperation defOp = GtUtils.getDefiningOperation(op); |
497 |
if (GtUtils.getIdentifier(defOp) == null) { |
498 |
/**
|
499 |
* When Geotools computes the inverse transformation, we loose the identifier, which
|
500 |
* makes the transformation quite useless for the final users since they can't distinguish
|
501 |
* it from any other operation. Therefore, we skip operations lacking an identifier, and
|
502 |
* we'll add them later requesting the inverse operation. It is quite hacky but I can't see
|
503 |
* a better approach
|
504 |
*/
|
505 |
continue;
|
506 |
} |
507 |
} |
508 |
DefaultTransformationDefinition def = new DefaultTransformationDefinition(op, sourceDef, targetDef);
|
509 |
transforms.add(def); |
510 |
} |
511 |
|
512 |
// now we'll try the inverse transformation
|
513 |
ops = operationFactory.findOperations(targetCRS, sourceCRS); |
514 |
for (CoordinateOperation op: ops) {
|
515 |
if (GtUtils.getIdentifier(op) == null) { |
516 |
CoordinateOperation defOp = GtUtils.getDefiningOperation(op); |
517 |
if (GtUtils.getIdentifier(defOp) == null) { |
518 |
continue;
|
519 |
} |
520 |
} |
521 |
DefaultTransformationDefinition def = new DefaultTransformationDefinition(op, sourceDef, targetDef);
|
522 |
transforms.add(def); |
523 |
} |
524 |
} catch (FactoryException e) {
|
525 |
// FIXME: we should log instead of raising an exception
|
526 |
throw new UnsupportedTransformationException(e); |
527 |
} |
528 |
return transforms;
|
529 |
} |
530 |
|
531 |
@Override
|
532 |
public List<TransformationDefinition> getCoordinateTransformations(String source, String target) throws UnsupportedTransformationException { |
533 |
try {
|
534 |
DefaultCRSDefinition sourceDef = getCRSDefinition(source); |
535 |
DefaultCRSDefinition targetDef = getCRSDefinition(target); |
536 |
return getCoordinateTransformations(sourceDef, targetDef);
|
537 |
} catch (UnsupportedCoordinateReferenceSystemException e) {
|
538 |
// FIXME: we should log instead of raising an exception
|
539 |
throw new UnsupportedTransformationException(e); |
540 |
} |
541 |
} |
542 |
|
543 |
/**
|
544 |
* Sets the path to the folder to be used by the library to load the CRS and
|
545 |
* transformation definitions. The specified path must contain one or more subfolders,
|
546 |
* containg the CRS and transformation database in the appropriate format:
|
547 |
* <ul><li>for EPSG database: a "epsg" subfolder must exist, which contains a HSQL database
|
548 |
* called "EPSG". The structure of this database must be the same used by Geotools,
|
549 |
* which is essentially based in the EPSG data model.</li>
|
550 |
* </ul>
|
551 |
*
|
552 |
* This method only has effect when it is called before any other method in the manager
|
553 |
* (before instantiating any CRS, transformation, etc).
|
554 |
*
|
555 |
* @param path The path to the folder containing the system CRS and transformation
|
556 |
* definitions
|
557 |
*/
|
558 |
@Override
|
559 |
public void setSystemDataPath(File path) { |
560 |
System.setProperty(HsqlEpsgDatabase.DIRECTORY_KEY, path.getAbsolutePath() + "/" + EPSG_DB_SUBFOLDER); |
561 |
} |
562 |
|
563 |
@Override
|
564 |
public void setUserDataPath(File path) { |
565 |
// TODO Auto-generated method stub
|
566 |
|
567 |
} |
568 |
|
569 |
@Override
|
570 |
public List<TextSerialization.Format> getSupportedFormats() { |
571 |
// TODO Auto-generated method stub
|
572 |
return SUPPORTED_FORMATS;
|
573 |
} |
574 |
|
575 |
@Override
|
576 |
public GeographicBoundingBox createBoundingBox(double westBoundLongitude, double eastBoundLongitude, |
577 |
double northBoundLatitude, double southBoundLatitude) { |
578 |
return new DefaultGeographicBoundingBox(westBoundLongitude, eastBoundLongitude, northBoundLatitude, southBoundLatitude); |
579 |
} |
580 |
|
581 |
@Override
|
582 |
public VerticalExtent createVerticalExtent(CRSDefinition crs, double minValue, double maxValue) { |
583 |
return new DefaultVerticalExtent(crs, minValue, maxValue); |
584 |
} |
585 |
|
586 |
@Override
|
587 |
public Extent createExtent(String description, |
588 |
Collection<GeographicBoundingBox> horizontalBoundingBoxList,
|
589 |
Collection<VerticalExtent> verticalBoundingBoxList) {
|
590 |
return new DefaultExtent(description, horizontalBoundingBoxList, verticalBoundingBoxList); |
591 |
} |
592 |
} |