Author: desruisseaux
Date: 2006-03-22 03:04:25 -0800 (Wed, 22 Mar 2006)
New Revision: 18775
Modified:
geotools/branches/2.2.x/module/referencing/src/org/geotools/factory/Ab=
stractFactory.java
geotools/branches/2.2.x/module/referencing/src/org/geotools/metadata/i=
so/extent/GeographicBoundingBoxImpl.java
geotools/branches/2.2.x/module/referencing/src/org/geotools/referencin=
g/CRS.java
geotools/branches/2.2.x/module/referencing/src/org/geotools/referencin=
g/factory/AllAuthoritiesFactory.java
Log:
CRS.getEnvelope(...) returns an envelope in terms of the specified CRS in=
stead of WGS84 (GEOT-825). AbstractFactory.hints type downgrated from 'Hi=
nts' to Map, in order to accept null values as specified in Factory.getIm=
plementationHints() contract.
Modified: geotools/branches/2.2.x/module/referencing/src/org/geotools/fac=
tory/AbstractFactory.java
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- geotools/branches/2.2.x/module/referencing/src/org/geotools/factory/A=
bstractFactory.java 2006-03-22 07:58:13 UTC (rev 18774)
+++ geotools/branches/2.2.x/module/referencing/src/org/geotools/factory/A=
bstractFactory.java 2006-03-22 11:04:25 UTC (rev 18775)
@@ -20,6 +20,7 @@
=20
// J2SE dependencies
import java.util.Map;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.Collections;
import javax.imageio.spi.RegisterableService;
@@ -65,28 +66,27 @@
* <p>
* {@code AbstractFactory} do <strong>not</strong> provides any facility=
for the first case.
* Factories implementations shall inspect themselves all relevant hints=
supplied by the user,
- * and pass them to any dependencies. Do <strong>not</strong> uses the {=
@link #hints} field for
- * that; uses the hints provided by the user in the constructor. If all =
dependencies are created
+ * and pass them to any dependencies. Do <strong>not</strong> use the {@=
link #hints} field for
+ * that; use the hints provided by the user in the constructor. If all d=
ependencies are created
* at construction time (<cite>constructor injection</cite>), there is n=
o need to keep user's hints
* once the construction is finished.
* <p>
* The {@link #hints} field is for the second case only. Implementations=
shall copy in this
- * field only the user's hints that are know to be relevant to this fact=
ory. Only direct
- * dependencies shall be put in the {@link #hints} map. Indirect depende=
ncies (i.e. hints used
- * by other factories used by this factory) will be inspected automatica=
lly by
- * {@link FactoryRegistry} in a recursive way.
+ * field only the user's hints that are know to be relevant to this fact=
ory. If a hint is
+ * relevant but the user didn't specified any value, the hint key should=
be added to the
+ * {@link #hints} map anyway with a {@code null} value. Only direct depe=
ndencies shall be put
+ * in the {@link #hints} map. Indirect dependencies (i.e. hints used by =
other factories used
+ * by this factory) will be inspected automatically by {@link FactoryReg=
istry} in a recursive way.
* <p>
- * The lack of constructor expecting a {@link Map} argument is intention=
al. Implementations
- * should not copy blindly all user-supplied hints into the {@link #hint=
s} field. Instead, they
- * should pickup only the relevant hints and {@linkplain Map#put put} th=
em in the {@link #hints}
- * field. An exception to this rule is when not all factories can be cre=
ated at construction time.
- * In this case, all user-supplied hints must be kept.
+ * <strong>Note:</strong> The lack of constructor expecting a {@link Map=
} argument is intentional.
+ * This is in order to discourage blind-copy of all user-supplied hints =
to the {@link #hints} map.
* <p>
* <strong>Example:</strong> Lets two factories, A and B. Factory A need=
an instance of Factory B.
* Factory A can be implemented as below:
*
- * <table><tr><td>
- * <blockquote><pre>
+ * <table border=3D'1'>
+ * <tr><th>Code</th><th>Observations</th></tr>
+ * <tr><td><blockquote><pre>
* class FactoryA extends AbstractFactory {
* FactoryB fb;
*
@@ -95,9 +95,8 @@
* this.hints.put(Hints.FACTORY_B, fb);
* }
* }
- * </pre></blockquote>
- * </td><td>
- * <strong>Observations:</strong>
+ * </pre></blockquote></td>
+ * <td>
* <ul>
* <li>The user-supplied map ({@code userHints}) is never modified.</l=
i>
* <li>All hints relevant to other factories are used in the construct=
or. Hints relevant to
@@ -150,14 +149,16 @@
* filled by subclasses at construction time. If possible, construct=
ors should not copy blindly
* all user-provided hints. They should select only the relevant hin=
ts and resolve them as of
* {@linkplain Factory#getImplementationHints implementation hints} =
contract.
- *=20
- * <p><strong>Reminder:</strong> the primary use of this map is to c=
heck if this factory can be
- * reused. It is not for creating new factories.</p>
- *
- * <p>Once the hints are accessibles to the user (this usually means=
when the subclass
- * construction is finished), this map should not change anymore.</p=
>
+ * <p>
+ * <strong>Reminder:</strong> the primary use of this map is to chec=
k if this factory can be
+ * reused. It is not for creating new factories. This explain why th=
is field is not an instance
+ * of {@link Hints}. An other reason is to allow for null values, as=
of
+ * {@linkplain Factory#getImplementationHints implementation hints} =
contract.
+ * <p>
+ * Once the hints are accessibles to the user (this usually means wh=
en the subclass
+ * construction is finished), this map should not change anymore.
*/
- protected final Hints hints =3D new Hints(null);
+ protected final Map hints =3D new HashMap();
=20
/**
* An unmodifiable view of {@link #hints}. This is the actual map to=
be returned
Modified: geotools/branches/2.2.x/module/referencing/src/org/geotools/met=
adata/iso/extent/GeographicBoundingBoxImpl.java
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- geotools/branches/2.2.x/module/referencing/src/org/geotools/metadata/=
iso/extent/GeographicBoundingBoxImpl.java 2006-03-22 07:58:13 UTC (rev 18=
774)
+++ geotools/branches/2.2.x/module/referencing/src/org/geotools/metadata/=
iso/extent/GeographicBoundingBoxImpl.java 2006-03-22 11:04:25 UTC (rev 18=
775)
@@ -36,6 +36,7 @@
import org.opengis.spatialschema.geometry.Envelope;
=20
// Geotools dependencies
+import org.geotools.factory.Hints;
import org.geotools.measure.Latitude;
import org.geotools.measure.Longitude;
import org.geotools.measure.AngleFormat;
@@ -79,6 +80,14 @@
}
=20
/**
+ * A set of hints used in order to fetch lenient coordinate operatio=
n factory. We accept
+ * lenient transforms because {@link GeographicBoundingBox} are usua=
lly for approximative
+ * bounds (e.g. the area of validity of some CRS). If a user wants a=
ccurate bounds, he
+ * should probably use an {@link Envelope} with the appropriate CRS.
+ */
+ private static final Hints LENIENT =3D new Hints(Hints.LENIENT_DATUM=
_SHIFT, Boolean.TRUE);
+
+ /**
* The western-most coordinate of the limit of the dataset extent.
* The value is expressed in longitude in decimal degrees (positive =
east).
*/
@@ -133,11 +142,12 @@
// TODO: use a more direct way if we add a 'getCRS()' method str=
aight into Envelope.
final CoordinateReferenceSystem crs =3D envelope.getLowerCorner(=
).getCoordinateReferenceSystem();
if (crs !=3D null) {
- if (!CRSUtilities.equalsIgnoreMetadata(CRSUtilities.getSubCR=
S(crs,0,2), DefaultGeographicCRS.WGS84) &&
- !CRSUtilities.equalsIgnoreMetadata(CRSUtilities.getSubCR=
S(crs,0,3), DefaultGeographicCRS.WGS84_3D))
+ if (!startsWith(crs, DefaultGeographicCRS.WGS84) &&
+ !startsWith(crs, DefaultGeographicCRS.WGS84_3D))
{
- final CoordinateOperationFactory factory =3D FactoryFind=
er.getCoordinateOperationFactory(null);
final CoordinateOperation operation;
+ final CoordinateOperationFactory factory;
+ factory =3D FactoryFinder.getCoordinateOperationFactory(=
LENIENT);
try {
operation =3D factory.createOperation(crs, DefaultGe=
ographicCRS.WGS84);
} catch (FactoryException exception) {
@@ -154,6 +164,17 @@
}
=20
/**
+ * Returns {@code true} if the specified {@code crs} starts with the=
specified {@code head}.
+ */
+ private static final boolean startsWith(final CoordinateReferenceSys=
tem crs,
+ final CoordinateReferenceSys=
tem head)
+ {
+ final int dimension =3D head.getCoordinateSystem().getDimension(=
);
+ return crs.getCoordinateSystem().getDimension()>=3Ddimension &&
+ CRSUtilities.equalsIgnoreMetadata(CRSUtilities.getSubCRS(=
crs,0,dimension), head);
+ }
+
+ /**
* Constructs a geographic bounding box from the specified rectangle=
.
* The rectangle is assumed in {@linkplain DefaultGeographicCRS#WGS8=
4 WGS 84} CRS.
*/
Modified: geotools/branches/2.2.x/module/referencing/src/org/geotools/ref=
erencing/CRS.java
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- geotools/branches/2.2.x/module/referencing/src/org/geotools/referenci=
ng/CRS.java 2006-03-22 07:58:13 UTC (rev 18774)
+++ geotools/branches/2.2.x/module/referencing/src/org/geotools/referenci=
ng/CRS.java 2006-03-22 11:04:25 UTC (rev 18775)
@@ -25,24 +25,29 @@
import java.util.Set;
=20
// OpenGIS dependencies
+import org.opengis.metadata.extent.GeographicBoundingBox;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.NoSuchAuthorityCodeException; // =
For javadoc
import org.opengis.referencing.crs.CRSAuthorityFactory;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.opengis.referencing.operation.MathTransform;
+import org.opengis.referencing.operation.TransformException;
import org.opengis.referencing.operation.CoordinateOperation; // =
For javadoc
import org.opengis.referencing.operation.CoordinateOperationFactory; // =
For javadoc
-import org.opengis.referencing.operation.MathTransform;
import org.opengis.spatialschema.geometry.Envelope;
=20
// Geotools dependencies
import org.geotools.factory.Hints;
+import org.geotools.geometry.GeneralEnvelope;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.geotools.referencing.factory.AllAuthoritiesFactory; // =
For javadoc
+import org.geotools.metadata.iso.extent.GeographicBoundingBoxImpl;
import org.geotools.metadata.iso.citation.Citations;
import org.geotools.resources.i18n.VocabularyKeys;
import org.geotools.resources.i18n.Vocabulary;
import org.geotools.resources.i18n.ErrorKeys;
import org.geotools.resources.i18n.Errors;
+import org.geotools.resources.CRSUtilities;
import org.geotools.resources.Utilities;
import org.geotools.util.GenericName;
=20
@@ -377,19 +382,90 @@
/**
* Returns the valid area bounding box for the specified coordinate =
reference system, or
* {@code null} if unknown. This method search in the metadata infor=
mations associated with
- * the given CRS.
+ * the given CRS. The returned envelope is expressed in terms of the=
specified CRS.
*
* @param crs The coordinate reference system, or {@code null}.
- * @return The envelope, or {@code null} if none.
+ * @return The envelope in terms of the specified CRS, or {@code nul=
l} if none.
*
* @since 2.2
*/
- public static Envelope getEnvelope(final CoordinateReferenceSystem c=
rs) {
+ public static Envelope getEnvelope(CoordinateReferenceSystem crs) {
+ Envelope envelope =3D getGeographicEnvelope(crs);
+ if (envelope !=3D null) {
+ // TODO: Use a more direct method if we provide such method =
in a future GeoAPI version.
+ final CoordinateReferenceSystem sourceCRS;
+ sourceCRS =3D envelope.getUpperCorner().getCoordinateReferen=
ceSystem();
+ if (sourceCRS !=3D null) try {
+ crs =3D CRSUtilities.getCRS2D(crs);
+ if (!equalsIgnoreMetadata(sourceCRS, crs)) {
+ final GeneralEnvelope e;
+ e =3D CRSUtilities.transform(transform(sourceCRS, cr=
s, true), envelope);
+ e.setCoordinateReferenceSystem(crs);
+ envelope =3D e;
+ }
+ } catch (FactoryException exception) {
+ /*
+ * No transformation path was found for the specified CR=
S. Logs a warning and
+ * returns null, since it is a legal return value accord=
ing this method contract.
+ */
+ envelope =3D null;
+ Utilities.unexpectedException("org.geotools.referencing"=
, "CRS",
+ "getEnvelope", exception);
+ } catch (TransformException exception) {
+ /*
+ * The envelope is probably outside the range of validit=
y for this CRS.
+ * It should not occurs, since the envelope is supposed =
to describe the
+ * CRS area of validity. Logs a warning and returns null=
, since it is a
+ * legal return value according this method contract.
+ */
+ envelope =3D null;
+ Utilities.unexpectedException("org.geotools.referencing"=
, "CRS",
+ "getEnvelope", exception);
+ } =20
+ }
+ return envelope;
+ }
+
+ /**
+ * Returns the valid area bounding box for the specified coordinate =
reference system, or
+ * {@code null} if unknown. This method search in the metadata infor=
mations associated with
+ * the given CRS. The returned envelope is always expressed in terms=
of the
+ * {@linkplain DefaultGeographicCRS#WGS_84 WGS 84} CRS.
+ *
+ * @param crs The coordinate reference system, or {@code null}.
+ * @return The envelope, or {@code null} if none.
+ */
+ private static Envelope getGeographicEnvelope(final CoordinateRefere=
nceSystem crs) {
// TODO: Copy the implementation from CRSUtilities there.
- return org.geotools.resources.CRSUtilities.getEnvelope(crs);
+ return CRSUtilities.getEnvelope(crs);
}
=20
/**
+ * Returns the valid geographic area for the specified coordinate re=
ference system, or
+ * {@code null} if unknown. This method search in the metadata infor=
mations associated
+ * with the given CRS.
+ *
+ * @param crs The coordinate reference system, or {@code null}.
+ * @return The geographic area, or {@code null} if none.
+ *
+ * @since 2.3
+ */
+ public static GeographicBoundingBox getGeographicBoundingBox(final C=
oordinateReferenceSystem crs) {
+ final Envelope envelope =3D getGeographicEnvelope(crs);
+ if (envelope !=3D null) try {
+ return new GeographicBoundingBoxImpl(envelope);
+ } catch (TransformException exception) {
+ /*
+ * Should not occurs, since envelopes are usually already in=
geographic coordinates.
+ * If it occurs anyway, returns null since it is allowed by =
this method contract.
+ */
+ Utilities.unexpectedException("org.geotools.referencing", "C=
RS",
+ "getGeographicBoundingBox", ex=
ception);
+ }
+ return null;
+ }
+
+ /**
* ESTIMATE the distance between the two points.
* 1. transforms both points to lat/lon
* 2. find the distance between the two points
Modified: geotools/branches/2.2.x/module/referencing/src/org/geotools/ref=
erencing/factory/AllAuthoritiesFactory.java
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- geotools/branches/2.2.x/module/referencing/src/org/geotools/referenci=
ng/factory/AllAuthoritiesFactory.java 2006-03-22 07:58:13 UTC (rev 18774)
+++ geotools/branches/2.2.x/module/referencing/src/org/geotools/referenci=
ng/factory/AllAuthoritiesFactory.java 2006-03-22 11:04:25 UTC (rev 18775)
@@ -38,6 +38,7 @@
=20
// Geotools dependencies
import org.geotools.factory.Hints;
+import org.geotools.factory.Factory;
import org.geotools.factory.FactoryRegistryException;
import org.geotools.referencing.FactoryFinder;
import org.geotools.metadata.iso.citation.Citations;
@@ -61,7 +62,7 @@
* example if any {@code createFoo(...)} method in this class is invoked=
with a code starting
* by {@code "EPSG:"}, then this class delegates the object creation to =
the authority factory
* provided by <code>FactoryFinder.{@linkplain FactoryFinder#getCRSAutho=
rityFactory
- * getCRSAuthorityFactory}("EPSG", {@linkplain #hints hints})</code>.
+ * getCRSAuthorityFactory}("EPSG", hints)</code>.
* <p>
* This class is not registered in {@link FactoryFinder}, because it is =
not a real authority
* factory. There is not a single authority name associated to this fact=
ory, but rather a set
@@ -99,13 +100,19 @@
private final char separator;
=20
/**
+ * User-supplied hints provided at construction time.
+ * Its content may or may not be identical to {@link #hints}.
+ */
+ private final Hints userHints;
+
+ /**
* Creates a new factory using the specified hints and the
* {@linkplain GenericName#DEFAULT_SEPARATOR default name separator}=
.
*
* @param hints An optional set of hints, or {@code null} if none.
*/
public AllAuthoritiesFactory(final Hints hints) {
- this(hints, null, GenericName.DEFAULT_SEPARATOR);
+ this(hints, null);
}
=20
/**
@@ -138,11 +145,13 @@
{
super(hints, NORMAL_PRIORITY);
this.separator =3D separator;
- if (hints !=3D null) {
- this.hints.putAll(hints);
- }
+ this.userHints =3D new Hints(hints);
if (factories!=3Dnull && !factories.isEmpty()) {
this.factories =3D new LinkedHashSet(factories);
+ for (final Iterator it=3Dthis.factories.iterator(); it.hasNe=
xt();) {
+ final Factory factory =3D (Factory) it.next();
+ this.hints.putAll(factory.getImplementationHints());
+ }
} else {
this.factories =3D null;
}
@@ -230,7 +239,7 @@
DatumAuthorityFactory factory =3D (DatumAuthorityFactory) // TOD=
O: remove cast with J2SE 1.5.
getAuthorityFactory(DatumAuthorityFactory.class, authori=
ty);
if (factory =3D=3D null) try {
- factory =3D FactoryFinder.getDatumAuthorityFactory(authority=
, hints);
+ factory =3D FactoryFinder.getDatumAuthorityFactory(authority=
, userHints);
} catch (FactoryRegistryException cause) {
throw noSuchAuthority(code, cause);
}
@@ -251,7 +260,7 @@
CSAuthorityFactory factory =3D (CSAuthorityFactory) // TODO: rem=
ove cast with J2SE 1.5.
getAuthorityFactory(CSAuthorityFactory.class, authority)=
;
if (factory =3D=3D null) try {
- factory =3D FactoryFinder.getCSAuthorityFactory(authority, h=
ints);
+ factory =3D FactoryFinder.getCSAuthorityFactory(authority, u=
serHints);
} catch (FactoryRegistryException cause) {
throw noSuchAuthority(code, cause);
}
@@ -272,7 +281,7 @@
CRSAuthorityFactory factory =3D (CRSAuthorityFactory) // TODO: r=
emove cast with J2SE 1.5.
getAuthorityFactory(CRSAuthorityFactory.class, authority=
);
if (factory =3D=3D null) try {
- factory =3D FactoryFinder.getCRSAuthorityFactory(authority, =
hints);
+ factory =3D FactoryFinder.getCRSAuthorityFactory(authority, =
userHints);
} catch (FactoryRegistryException cause) {
throw noSuchAuthority(code, cause);
}
@@ -293,7 +302,7 @@
CoordinateOperationAuthorityFactory factory =3D (CoordinateOpera=
tionAuthorityFactory) // TODO: remove cast with J2SE 1.5.
getAuthorityFactory(CoordinateOperationAuthorityFactory.=
class, authority);
if (factory =3D=3D null) try {
- factory =3D FactoryFinder.getCoordinateOperationAuthorityFac=
tory(authority, hints);
+ factory =3D FactoryFinder.getCoordinateOperationAuthorityFac=
tory(authority, userHints);
} catch (FactoryRegistryException cause) {
throw noSuchAuthority(code, cause);
}
|