/** * Provides a filtered, sorted view over the available EPSG coordinate reference systems. * * @author Gabriel Roldan - OpenGeo * @author Andrea Aime - OpenGeo */ public class SRSProvider extends GeoServerDataProvider<SRSProvider.SRS> { private static final long serialVersionUID = 3731647638872356912L; /** * Spots integral numbers * * @see #buildCodeList() */ private static Pattern NUMERIC = Pattern.compile("\\d+"); /** * A lightweight bean to carry over the code and description of a {@link * CoordinateReferenceSystem} * * @author Gabriel Roldan - OpenGeo */ public static class SRS implements Serializable, Comparable<SRS> { private static final long serialVersionUID = -4155644876049747585L; private String code; private transient String description; public SRS(String code) { this.code = code; } public String getCode() { return code; } public String getDescription() { // lazy loading of description if (description == null) { // grab the description String desc = "-"; try { // REVISIT: as far as I know the EPSG names are not localized? anyway, if // they're revisit to use the page locale // description = CRS.getAuthorityFactory(true).getDescriptionText("EPSG:" + // code) // .toString(getLocale()).toUpperCase(); desc = CRS.getAuthorityFactory(true).getDescriptionText("EPSG:" + code).toString(); } catch (Exception e) { // no problem } description = desc; } return description; } @Override public boolean equals(Object o) { return code.equals(((SRS) o).code); } @Override public int hashCode() { return 17 * code.hashCode(); } public int compareTo(SRS o) { return code.compareTo(o.code); } } /** custom geoserver crs factory which loads codes from epsg.properties file in data directory */ private static CRSAuthorityFactory customFactory = ReferencingFactoryFinder.getCRSAuthorityFactory( "EPSG", new Hints(Hints.CRS_AUTHORITY_FACTORY, GeoserverCustomWKTFactory.class)); public static final Property<SRS> CODE = new BeanProperty<SRS>("code", "code") { private static final long serialVersionUID = -1638823520421390286L; @Override public Comparator<SRS> getComparator() { return new CodeComparator(); } }; public static final Property<SRS> DESCRIPTION = new BeanProperty<SRS>("description", "description") { private static final long serialVersionUID = 3549074714488486991L; @Override public Comparator<SRS> getComparator() { return new Comparator<SRS>() { public int compare(SRS o1, SRS o2) { return String.CASE_INSENSITIVE_ORDER.compare( o1.getDescription(), o2.getDescription()); } }; } }; @SuppressWarnings("unchecked") private static final ArrayList<Property<SRS>> PROPERTIES = new ArrayList<Property<SRS>>(Arrays.asList(CODE, DESCRIPTION)); private List<SRS> items; @Override protected List<SRS> getItems() { if (items == null) { synchronized (SRSProvider.class) { if (items == null) { items = buildCodeList(); } } } return items; } @Override protected List<Property<SRS>> getProperties() { return PROPERTIES; } static List<SRS> buildCodeList() { long t = System.currentTimeMillis(); Set<String> codes = CRS.getSupportedCodes("EPSG"); try { codes.addAll(customFactory.getAuthorityCodes(CoordinateReferenceSystem.class)); } catch (FactoryException e) { LOGGER.log(Level.WARNING, "Error occurred while trying to gather custom CRS codes", e); } // make a set with each code Set<SRS> idSet = new HashSet<SRS>(); for (String code : codes) { // make sure we're using just the non prefix part String id = code.substring(code.indexOf(':') + 1); // avoid WGS84DD and eventual friends, as we're still not able to handle them, // if they are chosen exceptions arises everywhere if (NUMERIC.matcher(id).matches()) { idSet.add(new SRS(id)); } } List<SRS> srsList = new ArrayList<SRS>(idSet); Collections.sort(srsList, new CodeComparator()); // sort to get them in order return srsList; } /** * Compares the codes so that most of the codes ger compared as numbers, but unfortunately some * non numeric ones can sneak in... * * @author Andrea Aime - TOPP */ private static class CodeComparator implements Comparator<SRS> { public int compare(SRS srs1, SRS srs2) { String s1 = srs1.getCode(); String s2 = srs2.getCode(); Integer c1 = null, c2 = null; try { c1 = Integer.parseInt(s1); } catch (NumberFormatException e) { // } try { c2 = Integer.parseInt(s2); } catch (NumberFormatException e) { // } if (c1 == null) { if (c2 == null) return s1.compareTo(s2); else return -1; } else { if (c2 == null) return 1; else return c1 - c2; } } } }
/** Returns a factory of the given type. */ private static final <T extends AbstractAuthorityFactory> T getFactory(final Class<T> type) { return type.cast( ReferencingFactoryFinder.getCRSAuthorityFactory( "EPSG", new Hints(Hints.CRS_AUTHORITY_FACTORY, type))); }
public static CoordinateReferenceSystem getCRS(MapProjection projection, Datum datum) { CoordinateReferenceSystem result = WGS84; try { final MapTransform mapTransform = projection.getMapTransform(); if (mapTransform.getDescriptor() instanceof IdentityTransformDescriptor) { // 1. Identity map projection if (Datum.ITRF_97.equals(datum)) { result = ITRF97; } else if (Datum.WGS_72.equals(datum)) { result = WGS72; } } else if (projection instanceof UTMProjection && !Datum.ITRF_97.equals(datum)) { // 2. UTM map projections final UTMProjection utmProjection = (UTMProjection) projection; final int zone = utmProjection.getZone(); if (zone >= 1 && zone <= 60) { final CRSAuthorityFactory factory = ReferencingFactoryFinder.getCRSAuthorityFactory("EPSG", null); if (utmProjection.isNorth()) { if (Datum.WGS_72.equals(datum)) { final int WGS72_UTM_zone_N_BASE = 32200; result = factory.createProjectedCRS("EPSG:" + (WGS72_UTM_zone_N_BASE + zone)); } else if (Datum.WGS_84.equals(datum)) { final int WGS84_UTM_zone_N_BASE = 32600; result = factory.createProjectedCRS("EPSG:" + (WGS84_UTM_zone_N_BASE + zone)); } } else { if (Datum.WGS_72.equals(datum)) { final int WGS72_UTM_zone_S_BASE = 32300; result = factory.createProjectedCRS("EPSG:" + (WGS72_UTM_zone_S_BASE + zone)); } else if (Datum.WGS_84.equals(datum)) { final int WGS84_UTM_zone_S_BASE = 32700; result = factory.createProjectedCRS("EPSG:" + (WGS84_UTM_zone_S_BASE + zone)); } } } } else if (Datum.ITRF_97.equals(datum)) { // 3. Other map projections final String crsName = "ITRF 97 / " + mapTransform.getDescriptor().getName(); final MathTransform mathTransform = getMathTransform(mapTransform); if (mathTransform != null) { result = new DefaultProjectedCRS(crsName, ITRF97, mathTransform, DefaultCartesianCS.PROJECTED); } } else if (Datum.WGS_72.equals(datum)) { final String crsName = "WGS 72 / " + mapTransform.getDescriptor().getName(); final MathTransform mathTransform = getMathTransform(mapTransform); if (mathTransform != null) { result = new DefaultProjectedCRS(crsName, WGS72, mathTransform, DefaultCartesianCS.PROJECTED); } } else if (Datum.WGS_84.equals(datum)) { final String crsName = "WGS 84 / " + mapTransform.getDescriptor().getName(); final MathTransform mathTransform = getMathTransform(mapTransform); if (mathTransform != null) { result = new DefaultProjectedCRS(crsName, WGS84, mathTransform, DefaultCartesianCS.PROJECTED); } } } catch (FactoryException e) { // ignore } return result; }