sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rmarec...@apache.org
Subject svn commit: r1769159 - in /sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff: GeoTiffStore.java TiffCRSBuilder.java
Date Thu, 10 Nov 2016 17:05:34 GMT
Author: rmarechal
Date: Thu Nov 10 17:05:34 2016
New Revision: 1769159

URL: http://svn.apache.org/viewvc?rev=1769159&view=rev
Log:
Continue CRS creation from tiff tag : add Geographic CRS behavior and some documentation.Work in progress.

Modified:
    sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GeoTiffStore.java
    sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/TiffCRSBuilder.java

Modified: sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GeoTiffStore.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GeoTiffStore.java?rev=1769159&r1=1769158&r2=1769159&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GeoTiffStore.java [UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GeoTiffStore.java [UTF-8] Thu Nov 10 17:05:34 2016
@@ -31,6 +31,7 @@ import org.apache.sis.internal.storage.C
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.Classes;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.opengis.util.FactoryException;
 
 
@@ -104,8 +105,15 @@ public class GeoTiffStore extends DataSt
             while ((dir = reader.getImageFileDirectory(n++)) != null) {
                 dir.completeMetadata(reader.metadata, locale);
             }
-            // Add Coordinate Reference System built from GeoTIFF tags.
-            reader.metadata.add(reader.crsBuilder.build());
+
+            //-- add geotiff CRS if exist
+            //-- tiff image may not contain any CRS.
+            {
+                final CoordinateReferenceSystem crs = reader.crsBuilder.build();
+                //-- add if exist
+                if (crs != null) reader.metadata.add(crs);
+            }
+
             metadata = reader.metadata.build(true);
         } catch (IOException e) {
             throw new DataStoreException(reader.errors().getString(Errors.Keys.CanNotRead_1, reader.input.filename), e);

Modified: sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/TiffCRSBuilder.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/TiffCRSBuilder.java?rev=1769159&r1=1769158&r2=1769159&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/TiffCRSBuilder.java [UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/TiffCRSBuilder.java [UTF-8] Thu Nov 10 17:05:34 2016
@@ -17,37 +17,19 @@
 package org.apache.sis.storage.geotiff;
 
 import java.io.IOException;
+
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.logging.Level;
 import java.util.logging.LogRecord;
+
 import javax.measure.Unit;
 
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
 
-import org.apache.sis.internal.geotiff.Resources;
-import org.apache.sis.internal.system.DefaultFactories;
-import org.apache.sis.math.Vector;
-import org.apache.sis.measure.Units;
-import org.apache.sis.metadata.iso.citation.DefaultCitation;
-import org.apache.sis.referencing.CRS;
-import org.apache.sis.referencing.CommonCRS;
-import org.apache.sis.referencing.IdentifiedObjects;
-import org.apache.sis.referencing.crs.AbstractCRS;
-import org.apache.sis.referencing.crs.DefaultProjectedCRS;
-import org.apache.sis.referencing.cs.AxesConvention;
-import org.apache.sis.referencing.cs.CoordinateSystems;
-import org.apache.sis.referencing.cs.DefaultCartesianCS;
-import org.apache.sis.referencing.cs.DefaultCoordinateSystemAxis;
-import org.apache.sis.referencing.datum.DefaultEllipsoid;
-import org.apache.sis.referencing.datum.DefaultGeodeticDatum;
-import org.apache.sis.referencing.factory.GeodeticAuthorityFactory;
-import org.apache.sis.referencing.factory.GeodeticObjectFactory;
-import org.apache.sis.storage.DataStoreContentException;
-import org.apache.sis.util.ArgumentChecks;
-import org.apache.sis.util.resources.Vocabulary;
 import org.opengis.parameter.ParameterValueGroup;
+
 import org.opengis.referencing.IdentifiedObject;
 import org.opengis.referencing.crs.CRSFactory;
 import org.opengis.referencing.crs.GeodeticCRS;
@@ -62,28 +44,124 @@ import org.opengis.referencing.datum.Ell
 import org.opengis.referencing.datum.GeodeticDatum;
 import org.opengis.referencing.datum.PrimeMeridian;
 import org.opengis.referencing.operation.Conversion;
+import org.opengis.referencing.operation.CoordinateOperation;
 import org.opengis.referencing.operation.CoordinateOperationFactory;
-import org.opengis.referencing.operation.MathTransformFactory;
 import org.opengis.referencing.operation.OperationMethod;
+
 import org.opengis.util.FactoryException;
 import org.opengis.util.NoSuchIdentifierException;
 
+import org.apache.sis.internal.geotiff.Resources;
+import org.apache.sis.internal.system.DefaultFactories;
+
+import org.apache.sis.math.Vector;
+
+import org.apache.sis.measure.Units;
+
+import org.apache.sis.metadata.iso.citation.DefaultCitation;
+
+import org.apache.sis.referencing.CRS;
+import org.apache.sis.referencing.CommonCRS;
+import org.apache.sis.referencing.IdentifiedObjects;
+import org.apache.sis.referencing.crs.AbstractCRS;
+import org.apache.sis.referencing.crs.DefaultGeographicCRS;
+import org.apache.sis.referencing.crs.DefaultProjectedCRS;
+import org.apache.sis.referencing.cs.AxesConvention;
+import org.apache.sis.referencing.cs.CoordinateSystems;
+import org.apache.sis.referencing.cs.DefaultCartesianCS;
+import org.apache.sis.referencing.cs.DefaultCoordinateSystemAxis;
+import org.apache.sis.referencing.factory.GeodeticAuthorityFactory;
+import org.apache.sis.referencing.factory.GeodeticObjectFactory;
+import org.apache.sis.storage.DataStoreContentException;
+import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.util.resources.Vocabulary;
+
 /**
+ * Build a {@link CoordinateReferenceSystem} from Tiff tags informations.<br>
+ * More precisely we have to parse 3 Tiff tags which are<br>
+ * GeoKeyDirectoryTag(34735),<br>
+ * GeoDoubleParamsTag(34736),<br>
+ * GeoAsciiParamsTag(34737).<br><br>
+ *
+ * Forexample, for each tag data content are organize as follow :<br><br>
+ *
+ * Example:<br>
+ * <table summary="GeoKeys">
+ *    <tr>
+ *       <td>GeoKeyDirectoryTag=( </td>
+ *       <td> 1,</td>
+ *       <td> 1,</td>
+ *       <td> 2,</td>
+ *       <td> 6,</td>
+ *    </tr>
+ *    <tr>
+ *       <td> </td>
+ *       <td> 1024,</td>
+ *       <td> 0,</td>
+ *       <td> 1,</td>
+ *       <td> 2,</td>
+ *    </tr>
+ *    <tr>
+ *       <td> </td>
+ *       <td> 1026,</td>
+ *       <td> 34737,</td>
+ *       <td> 0,</td>
+ *       <td> 12,</td>
+ *    </tr>
+ *    <tr>
+ *       <td> </td>
+ *       <td> 2048,</td>
+ *       <td> 0,</td>
+ *       <td> 1,</td>
+ *       <td> 32767,</td>
+ *    </tr>
+ *    <tr>
+ *       <td> </td>
+ *       <td> 2049,</td>
+ *       <td> 34737,</td>
+ *       <td> 14,</td>
+ *       <td> 12,</td>
+ *    </tr>
+ *    <tr>
+ *       <td> </td>
+ *       <td> 2050,</td>
+ *       <td> 0,</td>
+ *       <td> 1,</td>
+ *       <td> 6,</td>
+ *    </tr>
+ *    <tr>
+ *       <td> </td>
+ *       <td> 2051,</td>
+ *       <td> 34736,</td>
+ *       <td> 1,</td>
+ *       <td> 0)</td>
+ *    </tr>
+ * </table>
+ * GeoDoubleParamsTag(34736)=(1.5)<br>
+ * GeoAsciiParamsTag(34737)=("Custom File|My Geographic|")<br><br>
+ *
+ * The first line indicates that this is a Version 1 GeoTIFF GeoKey directory,
+ * the keys are Rev. 1.2, and there are 6 Keys defined in this tag.<br>
+ *
+ * The next line indicates that the first Key (ID=1024 = GTModelTypeGeoKey) has the value 2 (Geographic),
+ * explicitly placed in the entry list (since TIFFTagLocation=0).<br><br>
+ * The next line indicates that the Key 1026 (the GTCitationGeoKey) is listed in the GeoAsciiParamsTag (34737) array,
+ * starting at offset 0 (the first in array), and running for 12 bytes and so has the value
+ * "Custom File" (the "|" is converted to a null delimiter at the end). <br><br>
+ * Going further down the list, the Key 2051 (GeogLinearUnitSizeGeoKey) is located in the GeoDoubleParamsTag (34736),
+ * at offset 0 and has the value 1.5; the value of key 2049 (GeogCitationGeoKey) is "My Geographic".
  *
  * @author Remi Marechal (Geomatys).
  * @since   0.8
  * @version 0.8
  * @module
+ * @see GeoKeys
  */
 public class TiffCRSBuilder {
 
     /** EPSG Factory for creating {@link GeodeticDatum}objects. */
     private DatumFactory datumObjFactory;
-    /**
-     * Cached {@link MathTransformFactory} for building {@link MathTransform}
-     * objects.
-     */
-    private MathTransformFactory mtFactory ;
+
     /** EPSG factories for various purposes. */
     private GeodeticAuthorityFactory epsgFactory;
 
@@ -120,21 +198,9 @@ public class TiffCRSBuilder {
         this.reader = reader;
     }
 
-    //----------------------------- Private ------------------------------------
-    /**
-     * Check if given string is null, empty or equals to zero.
-     * Geotiff tags are often badly defined, this ensure we skip "0.0" tags in the
-     * hope another tag will define a proper value.
-     * In the worst case if no valid tags are found the 0.0 value will be used anyway.
-     *
-     * @param code
-     * @return true if value is zero
-     */
-    private static boolean isZero(final String code) {
-        if (code == null || code.isEmpty()) return true;
-        final double d = Double.parseDouble(code);
-        return d == 0.0;
-    }
+    ////////////////////////////////////////////////////////////////////////////
+    //---------------------------- UTILITY -----------------------------------//
+    ////////////////////////////////////////////////////////////////////////////
 
     /**
      * Reports a warning represented by the given message and key.
@@ -150,215 +216,82 @@ public class TiffCRSBuilder {
         reader.owner.warning(r);
     }
 
+    //----------------------------- Factories ----------------------------------
     /**
-     * Initialyse all requested factories to build {@link CoordinateReferenceSystem}.
+     * Creates the {@linkplain GeodeticAuthorityFactory EPSG factory} object,
+     * if it does not already exists, then returns it.
      *
-     * @throws FactoryException if problem during factories instanciation.
+     * @return the EPSG factory (never {@code null}).
      */
-    private void initFactories()
+    private GeodeticAuthorityFactory epsgFactory()
             throws FactoryException {
-
-        if (mtFactory == null)
-            mtFactory = DefaultFactories.forBuildin(MathTransformFactory.class);
         if (epsgFactory == null)
             epsgFactory = (GeodeticAuthorityFactory) CRS.getAuthorityFactory("EPSG");
+        return epsgFactory;
+    }
+
+    /**
+     * Creates the {@linkplain GeodeticObjectFactory object factory} object,
+     * if it does not already exists, then returns it.
+     *
+     * @return the object factory (never {@code null}).
+     */
+    private GeodeticObjectFactory objectFactory() {
         if (objFactory == null)
             objFactory = DefaultFactories.forBuildin(CRSFactory.class, GeodeticObjectFactory.class);
+        return objFactory;
+    }
+
+    /**
+     * Creates the {@linkplain CoordinateOperationFactory operation factory} object,
+     * if it does not already exists, then returns it.
+     *
+     * @return the operation factory (never {@code null}).
+     */
+    private CoordinateOperationFactory operationFactory() {
         if (operationFactory == null)
             operationFactory = DefaultFactories.forBuildin(CoordinateOperationFactory.class);
+        return operationFactory;
+    }
 
-//        mtFactory.getDefaultParameters("Geotiff:"+GeoKeys.CRS.CT_LambertAzimEqualArea);
+    /**
+     * Creates the {@linkplain DatumFactory datum factory} object,
+     * if it does not already exists, then returns it.
+     *
+     * @return the datum factory (never {@code null}).
+     */
+    private DatumFactory datumFactory() {
+        if (datumObjFactory == null)
+            datumObjFactory = DefaultFactories.forBuildin(DatumFactory.class);
+        return datumObjFactory;
     }
 
+    /**
+     * Utility method to help name creation to build georeferencement object from factories.
+     * @param name
+     * @return
+     */
     private static Map<String,?> name(final String name) {
         return Collections.singletonMap(IdentifiedObject.NAME_KEY, name);
     }
 
     /**
-     * @todo we should somehow try to to support user defined coordinate
-     *       transformation even if for the moment is not so clear to me how we
-     *       could achieve that since if we have no clue about the coordinate
-     *       transform what we are supposed to do in order to build a
-     *       conversion, guess it? How could we pick up the parameters, should
-     *       look for all and then guess the right transformation?
+     * Throw formated exception for missing key.
      *
-     * @param name indicates the name for the projection.
-     * @param metadata to use for building this {@link ParameterValueGroup}.
-     * @return a {@link ParameterValueGroup} that can be used to trigger this
-     *         projection.
-     * @throws IOException
-     * @throws FactoryException
+     * @param key the missing key.
      */
-    private ParameterValueGroup createUserDefinedProjectionParameter(
-            final String name)
-            throws FactoryException, NoSuchIdentifierException, DataStoreContentException {
-        // //
-        //
-        // Trying to get the name for the coordinate transformation involved.
-        //
-        // ///
-        final String coordTrans = geoKeys.getAsString(GeoKeys.CRS.ProjCoordTransGeoKey);
-
-        // throw descriptive exception if ProjCoordTransGeoKey not defined
-        if ((coordTrans == null)
-                || coordTrans.equalsIgnoreCase(GeoKeys.Configuration.GTUserDefinedGeoKey_String)) {
-            throw new DataStoreContentException("User defined projections must specify"
-                    + " coordinate transformation code in ProjCoordTransGeoKey");
-        }
-
-        // getting math transform factory
-        return setParametersForProjection(name, coordTrans);
+    private void missingKeyException(final int key)//-- TODO : is it pertinency ??
+            throws DataStoreContentException {
+        throw new DataStoreContentException(reader.resources().getString(Resources.Keys.UnexpectedKeyValue_3,
+                        GeoKeys.CRS.getName(key)+" ("+key+")", "non null value", "null"));
     }
 
+    //---------------------------- geokeys parsing -----------------------------
     /**
-     * Set the projection parameters basing its decision on the projection name.
-     * I found a complete list of projections on the geotiff website at address
-     * http://www.remotesensing.org/geotiff/proj_list.
-     *
-     * I had no time to implement support for all of them therefore you will not
-     * find all of them. If you want go ahead and add support for the missing
-     * ones. I have tested this code against some geotiff files you can find on
-     * the geotiff website under the ftp sample directory but I can say that
-     * they are a real mess! I am respecting the specification strictly while
-     * many of those fields do not! I could make this method trickier and use
-     * workarounds in order to be less strict but I will not do this, since I
-     * believe it is may lead us just on a very dangerous path.
+     * Parse {@link #geoKeyDirectoryTag} content to get and store each geo keys and their value.
      *
-     *
-     * @param name
-     * @param metadata to use fo building this {@link ParameterValueGroup}.
-     * @param coordTrans
-     *            a {@link ParameterValueGroup} that can be used to trigger this
-     *            projection.
-     *
-     * @return
-     * @throws GeoTiffException
+     * @see #geoKeyDirectoryTag
      */
-    private ParameterValueGroup setParametersForProjection(final String name, final String coordTransCode)
-            throws NoSuchIdentifierException, DataStoreContentException {
-
-        if (name == null && coordTransCode == null)
-            throw new DataStoreContentException("bla bla bla");//-- TODO : do better
-
-        final String projName = (name == null)
-                                ? GeoKeys.CRS.getName(Integer.parseInt(coordTransCode))
-                                : name;
-
-        final ParameterValueGroup parameters = mtFactory.getDefaultParameters(projName);
-
-        //-- particularity cases
-        for (int key : geoKeys.keySet()) {
-            if (GeoKeys.CRS.contain(key)) {
-                String keyName = GeoKeys.CRS.getName(key);
-                keyName = keyName.substring(4, keyName.length()-6);
-                parameters.parameter(keyName).setValue(geoKeys.getAsString(key));
-            }
-        }
-
-        //-- maybe particularity case
-//            /**
-//             * Mercator_1SP
-//             * Mercator_2SP
-//             */
-//            if (name.equalsIgnoreCase("mercator_1SP")
-//                    || name.equalsIgnoreCase("Mercator_2SP")
-//                    || code == CT_Mercator) {
-//
-//                final double standard_parallel_1 = metadata.getAsDouble(ProjStdParallel1GeoKey);
-//                boolean isMercator2SP = false;
-//                if (!Double.isNaN(standard_parallel_1)) {
-//                    parameters = mtFactory.getDefaultParameters("Mercator_2SP");
-//                    isMercator2SP = true;
-//                } else {
-//                    parameters = mtFactory.getDefaultParameters("Mercator_1SP");
-//                }
-//
-//                parameters.parameter(code(Mercator1SP.LONGITUDE_OF_ORIGIN)).setValue(getOriginLong(metadata));
-//                parameters.parameter(code(Mercator1SP.LATITUDE_OF_ORIGIN)).setValue(getOriginLat(metadata));
-//                parameters.parameter(code(Mercator2SP.FALSE_EASTING)).setValue(getFalseEasting(metadata));
-//                parameters.parameter(code(Mercator2SP.FALSE_NORTHING)).setValue(getFalseNorthing(metadata));
-//                if (isMercator2SP) {
-//                    parameters.parameter(code(Mercator2SP.STANDARD_PARALLEL)).setValue(standard_parallel_1);
-//                } else {
-//                    parameters.parameter(code(Mercator1SP.SCALE_FACTOR)).setValue(getScaleFactor(metadata));
-//                }
-//                return parameters;
-//            }
-//
-//            /**
-//             * POLAR_STEREOGRAPHIC variant A B and C
-//             */
-//            if (code == CT_PolarStereographic) {
-//
-//                /**
-//                 * They exist 3 kind of polar StereoGraphic projections,define the case
-//                 * relative to existing needed attributs
-//                 */
-//                //-- set the mutual projection attributs
-//                //-- all polar stereographic formulas share LONGITUDE_OF_ORIGIN
-//                final double longitudeOfOrigin = metadata.getAsDouble(ProjStraightVertPoleLongGeoKey);
-//
-//                /*
-//                * For polar Stereographic variant A only latitudeOfNaturalOrigin expected values are {-90; +90}.
-//                * In some case, standard parallele is stipulate into latitudeOfNaturalOrigin tiff tag by error.
-//                * To avoid CRS problem creation, try to anticipe this comportement by switch latitudeOfNaturalOrigin into standard parallele.
-//                * HACK FOR USGS LANDSAT 8 difference between geotiff tag and Landsat 8 metadata MTL.txt file.
-//                */
-//                double standardParallel                 = metadata.getAsDouble(ProjStdParallel1GeoKey);
-//                final double latitudeOfNaturalOrigin    = metadata.getAsDouble(ProjNatOriginLatGeoKey);
-//                final boolean isVariantALatitudeConform = (Math.abs(Latitude.MAX_VALUE - Math.abs(latitudeOfNaturalOrigin)) <  Formulas.ANGULAR_TOLERANCE);
-//
-//                if (!isVariantALatitudeConform && Double.isNaN(standardParallel)) {
-//                    LOGGER.log(Level.WARNING, "The latitudeOfNaturalOrigin for Polar Stereographic variant A is not conform.\n"
-//                            + "Expected values are {-90; +90}, found : "+latitudeOfNaturalOrigin+"\n"
-//                            + "Switch latitudeOfNaturalOrigin by Latitude of standard parallel to try building of Polar Stereographic Variant B or C.");
-//                    standardParallel = latitudeOfNaturalOrigin;
-//                }
-//
-//                if (Double.isNaN(standardParallel)) {
-//                    //-- no standard parallele : PolarStereoGraphic VARIANT A
-//                    final OperationMethod method = DefaultFactories.forBuildin(CoordinateOperationFactory.class)
-//                    .getOperationMethod("Polar Stereographic (variant A)");
-//
-//                    parameters = method.getParameters().createValue();
-//                    parameters.parameter(code(PolarStereographicA.LONGITUDE_OF_ORIGIN)).setValue(longitudeOfOrigin);
-//                    parameters.parameter(code(PolarStereographicA.LATITUDE_OF_ORIGIN)).setValue(latitudeOfNaturalOrigin);
-//                    parameters.parameter(code(PolarStereographicA.SCALE_FACTOR)).setValue(metadata.getAsDouble(ProjScaleAtNatOriginGeoKey));
-//                    parameters.parameter(code(PolarStereographicA.FALSE_EASTING)).setValue(metadata.getAsDouble(ProjFalseEastingGeoKey));
-//                    parameters.parameter(code(PolarStereographicA.FALSE_NORTHING)).setValue(metadata.getAsDouble(ProjFalseNorthingGeoKey));
-//
-//                } else {
-//
-//                    //-- Variant B and C share STANDARD_PARALLEL
-//
-//                    final double falseOriginEasting = metadata.getAsDouble(ProjFalseOriginEastingGeoKey);
-//                    if (Double.isNaN(falseOriginEasting)) {
-//                        //-- no false Origin Easting : PolarStereoGraphic VARIANT B
-//                        final OperationMethod method = DefaultFactories.forBuildin(CoordinateOperationFactory.class)
-//                              .getOperationMethod("Polar Stereographic (variant B)");
-//
-//                        parameters = method.getParameters().createValue();
-//                        parameters.parameter(code(PolarStereographicB.STANDARD_PARALLEL)).setValue(standardParallel);
-//                        parameters.parameter(code(PolarStereographicB.LONGITUDE_OF_ORIGIN)).setValue(longitudeOfOrigin);
-//                        parameters.parameter(code(PolarStereographicB.FALSE_EASTING)).setValue(metadata.getAsDouble(ProjFalseEastingGeoKey));
-//                        parameters.parameter(code(PolarStereographicB.FALSE_NORTHING)).setValue(metadata.getAsDouble(ProjFalseNorthingGeoKey));
-//                    } else {
-//                        //-- PolarStereoGraphic VARIANT C
-//                        final OperationMethod method = DefaultFactories.forBuildin(CoordinateOperationFactory.class)
-//                              .getOperationMethod("Polar Stereographic (variant C)");
-//
-//                        parameters = method.getParameters().createValue();
-//                        parameters.parameter(code(PolarStereographicB.STANDARD_PARALLEL)).setValue(standardParallel);
-//                        parameters.parameter(code(PolarStereographicB.LONGITUDE_OF_ORIGIN)).setValue(longitudeOfOrigin);
-//                        parameters.parameter(code(PolarStereographicC.EASTING_AT_FALSE_ORIGIN)).setValue(metadata.getAsDouble(ProjFalseOriginEastingGeoKey));
-//                        parameters.parameter(code(PolarStereographicC.NORTHING_AT_FALSE_ORIGIN)).setValue(metadata.getAsDouble(ProjFalseNorthingGeoKey));
-//                    }
-//                }
-//            }
-
-        return parameters;
-    }
-
     private void parseGeoKeyDirectory() {
         int p   = 4;
         int key = 0;
@@ -370,6 +303,15 @@ public class TiffCRSBuilder {
         }
     }
 
+    /**
+     * Parse and store "geoKey" and its content into internal {@link #geoKeys}.
+     *
+     * @param KeyID geokey Id
+     * @param tiffTagLocation 0 if offset is the data, or one of GeoDoubleParamsTag or GeoAsciiParamsTag.
+     * @param count 1 if offset is data or n if data store into another geokey.
+     * @param value_Offset data or offset if into another geokey.
+     * @see TiffCRSBuilder
+     */
     private void setKey(final int KeyID, final int tiffTagLocation, final int count, final int value_Offset) {
         if (tiffTagLocation == 0) {
             //-- tiff taglocation = 0 mean offset is the stored value
@@ -391,6 +333,7 @@ public class TiffCRSBuilder {
         }
     }
 
+    //----------------------------- GEO UTILS ----------------------------------
     /**
      * This code creates an <code>javax.Units.Unit</code> object out of the
      * <code>ProjLinearUnitsGeoKey</code> and the
@@ -426,27 +369,241 @@ public class TiffCRSBuilder {
             final String unitSize = geoKeys.getAsString(userDefinedKey);
 
             //-- missing needed key
-            if (unitSize == null)
-                throw new DataStoreContentException(reader.resources().getString(Resources.Keys.UnexpectedKeyValue_3,
-                        GeoKeys.CRS.getName(key)+" ("+key+")", "non null value", "null"));
+            if (unitSize == null) missingKeyException(key);
 
             final double sz = Double.parseDouble(unitSize);
             return base.multiply(sz);
         }
 
         //-- using epsg code for this unit
-        return epsgFactory.createUnit(String.valueOf(unitCode));
+        return epsgFactory().createUnit(String.valueOf(unitCode));
     }
 
     /**
+     * Creating a Geodetic Datum for the {@link #createUserDefinedGCS(javax.measure.Unit, javax.measure.Unit) } method
+     * we are creating at an higher level.<br>
+     * As usual this method tries to follow the geotiff specification<br>
+     * Needed tags are :
+     * <ul>
+     * <li> a code definition given by {@link GeoKeys.CRS.GeogGeodeticDatumGeoKey} tag </li>
+     * <li> a name given by {@link GeoKeys.CRS.GeogCitationGeoKey} </li>
+     * <li> required prime meridian tiff tags </li>
+     * <li> required ellipsoid tiff tags </li>
+     * </ul>
      *
-     * @return
+     * @param unit to use for building this {@link GeodeticDatum}.
+     * @return a {@link GeodeticDatum}.
+     * @throws DataStoreContentException if datum code from relative tiff tag is missing ({@code null}).
+     * @throws FactoryException if factory problem during Datum creation.
+     * @see #createPrimeMeridian(javax.measure.Unit)
+     * @see #createEllipsoid(javax.measure.Unit)
+     */
+    private GeodeticDatum createGeodeticDatum(final Unit unit)
+            throws DataStoreContentException, FactoryException {
+
+        // lookup the datum (w/o PrimeMeridian).
+        String datumCode = geoKeys.getAsString(GeoKeys.CRS.GeogGeodeticDatumGeoKey);
+
+        if (datumCode == null) missingKeyException(GeoKeys.CRS.GeogGeodeticDatumGeoKey);
+
+        datumCode = datumCode.trim().intern();
+
+        //-- Geodetic Datum define as an EPSG code.
+        if (!datumCode.equals(GeoKeys.Configuration.GTUserDefinedGeoKey_String))
+            return (GeodeticDatum) epsgFactory().createDatum(String.valueOf(datumCode));
+
+        //-- USER DEFINE Geodetic Datum creation
+        {
+            //-- Datum name
+            assert datumCode.equals(GeoKeys.Configuration.GTUserDefinedGeoKey_String);
+            String datumName = geoKeys.getAsString(GeoKeys.CRS.GeogCitationGeoKey);
+            datumName        = (datumName == null) ? "Unamed User Defined Geodetic Datum" : datumName.trim().intern();
+
+            //-- particularity case
+            if (datumName.equalsIgnoreCase("WGS84")) return CommonCRS.WGS84.datum();
+
+            //-- ELLIPSOID creation
+            final Ellipsoid ellipsoid = createEllipsoid(unit);
+
+            //-- PRIME MERIDIAN
+            final PrimeMeridian primeMeridian = createPrimeMeridian(unit);
+
+            //-- factory Datum creation
+            return objectFactory().createGeodeticDatum(name(datumName), ellipsoid, primeMeridian);
+        }
+    }
+
+    /**
+     * Creating a prime meridian for the {@link #createGeodeticDatum(javax.measure.Unit) } method
+     * we are creating at an higher level.<br>
+     * As usual this method tries to follow the geotiff specification<br>
+     * Needed tags are :
+     * <ul>
+     * <li> a code definition given by {@link GeoKeys.CRS.GeogPrimeMeridianGeoKey} tag </li>
+     * <li> a name given by {@link GeoKeys.CRS.GeogCitationGeoKey} </li>
+     * <li> a prime meridian value given by {@link GeoKeys.CRS.GeogPrimeMeridianLongGeoKey} </li>
+     * </ul>
+     *
+     * @param linearUnit use for building this {@link PrimeMeridian}.
+     * @return a {@link PrimeMeridian} built using the provided {@link Unit} and
+     *         the provided metadata.
+     * @throws FactoryException if problem during factory Prime Meridian creation.
+     */
+    private PrimeMeridian createPrimeMeridian(final Unit linearUnit)
+            throws FactoryException {
+        //-- prime meridian :
+        //-- could be an EPSG code
+        //-- or could be user defined
+        //-- or not defined = greenwich
+        String pmCode = geoKeys.getAsString(GeoKeys.CRS.GeogPrimeMeridianGeoKey);
+
+        //-- if Prime Meridian code not define, assume WGS84
+        if (pmCode == null) return CommonCRS.WGS84.primeMeridian();
+        pmCode = pmCode.trim().intern();
+
+        //-- if Prime Meridian define as an EPSG code.
+        if (!pmCode.equals(GeoKeys.Configuration.GTUserDefinedGeoKey_String))
+            return epsgFactory().createPrimeMeridian(String.valueOf(pmCode));
+
+        //-- user define Prime Meridian creation
+        {
+            assert pmCode.equals(GeoKeys.Configuration.GTUserDefinedGeoKey_String);
+
+            final String pmValue = geoKeys.getAsString(GeoKeys.CRS.GeogPrimeMeridianLongGeoKey);
+            final double pmNumeric;
+            if (pmValue == null) {
+                warning(reader, Level.WARNING, Resources.Keys.UnexpectedKeyValue_3, "GeogPrimeMeridianLongGeoKey (2061)","non null","null");
+                pmNumeric = 0;
+            } else {
+                pmNumeric = Double.parseDouble(pmValue.trim().intern());
+            }
+
+            //-- if user define prime meridian is not define, assume WGS84
+            if (pmNumeric == 0) return CommonCRS.WGS84.primeMeridian();
+
+            final String name = geoKeys.getAsString(GeoKeys.CRS.GeogCitationGeoKey);
+            return datumFactory().createPrimeMeridian(
+                    name((name == null)? "User Defined GEOTIFF Prime Meridian" : name), pmNumeric, linearUnit);
+        }
+    }
+
+    /**
+     * Creating an {@link Ellipsoid} following the GeoTiff spec.<br>
+     * Creating a Ellipsoid for the {@link #createGeodeticDatum(javax.measure.Unit) } method
+     * we are creating at an higher level.<br>
+     * As usual this method tries to follow the geotiff specification<br>
+     * Needed tags are :
+     * <ul>
+     * <li> a code definition given by {@link GeoKeys.CRS.GeogEllipsoidGeoKey} tag </li>
+     * <li> a name given by {@link GeoKeys.CRS.GeogCitationGeoKey} </li>
+     * <li> a semi major axis value given by {@link GeoKeys.CRS.GeogSemiMajorAxisGeoKey} </li>
+     * <li> a semi major axis value given by {@link GeoKeys.CRS.GeogInvFlatteningGeoKey} </li>
+     * <li> a semi major axis value given by {@link GeoKeys.CRS.GeogSemiMinorAxisGeoKey} </li>
+     * </ul>
+     *
+     * @param unit use for building this {@link Ellipsoid}.
+     * @return a {@link Ellipsoid} built using the provided {@link Unit} and
+     *         the provided metadata.
+     * @throws FactoryException if problem during factory Prime Meridian creation.
+     * @throws DataStoreContentException if missing needed geokeys.
+     */
+    private Ellipsoid createEllipsoid(final Unit unit) throws FactoryException, DataStoreContentException { //-- TODO refactor this method
+
+        //-- ellipsoid key
+        final String ellipsoidKey = geoKeys.getAsString(GeoKeys.CRS.GeogEllipsoidGeoKey);
+
+        //-- if ellipsoid key NOT "user define" decode EPSG code.
+        if (ellipsoidKey != null && !ellipsoidKey.equalsIgnoreCase(GeoKeys.Configuration.GTUserDefinedGeoKey_String))
+            return epsgFactory().createEllipsoid(String.valueOf(ellipsoidKey.trim().intern()));
+
+        //-- User define Ellipsoid creation
+        {
+            String nameEllipsoid = geoKeys.getAsString(GeoKeys.CRS.GeogCitationGeoKey);
+            nameEllipsoid = (nameEllipsoid == null) ? "User define unamed Ellipsoid" : nameEllipsoid.trim().intern();
+            //-- particularity case
+            if (nameEllipsoid.equalsIgnoreCase("WGS84"))
+                return CommonCRS.WGS84.ellipsoid();
+
+            //-- try to build ellipsoid from others parameters.
+            //-- get semi Major axis and, semi minor or invertflattening
+
+            //-- semi Major
+            final String semiMajSTR = geoKeys.getAsString(GeoKeys.CRS.GeogSemiMajorAxisGeoKey);
+            if (semiMajSTR == null) missingKeyException(GeoKeys.CRS.GeogSemiMajorAxisGeoKey);
+            final double semiMajorAxis = Double.parseDouble(semiMajSTR.trim());
+
+            //-- try to get inverseFlattening
+            final String invFlatSTR = geoKeys.getAsString(GeoKeys.CRS.GeogInvFlatteningGeoKey);
+
+            final double inverseFlattening;
+            if (invFlatSTR == null) {
+                //-- get semi minor axis to build missing inverseFlattening
+                final String semiMinSTR = geoKeys.getAsString(GeoKeys.CRS.GeogSemiMinorAxisGeoKey);
+                if (semiMinSTR == null)
+                    throw new DataStoreContentException(reader.resources().getString(Resources.Keys.UnexpectedKeyValue_3,
+                                GeoKeys.CRS.getName(GeoKeys.CRS.GeogSemiMinorAxisGeoKey)+"("+GeoKeys.CRS.GeogSemiMinorAxisGeoKey+"):",
+                                "non null value", "null"));
+                inverseFlattening = semiMajorAxis / (semiMajorAxis - Double.parseDouble(semiMinSTR.trim()));
+            } else {
+                inverseFlattening = Double.parseDouble(invFlatSTR.trim());
+            }
+
+            //-- ellipsoid creation
+            return objectFactory().createFlattenedSphere(name(nameEllipsoid), semiMajorAxis, inverseFlattening, unit);
+        }
+    }
+
+
+    //-- TODO : maybe this method is equals to epsgFactory().createCartesianCS("EPSG:4400");
+    /**
+     * Creates a {@link CartesianCS} for a {@link ProjectedCRS} given the
+     * provided {@link Unit}.
+     *
+     * @todo consider caching this items
+     * @param linearUnit to be used for building this {@link CartesianCS}.
+     * @return an instance of {@link CartesianCS} using the provided {@link Unit},
+     */
+    private DefaultCartesianCS createProjectedCS(final Unit linearUnit) {
+        ArgumentChecks.ensureNonNull("ProjectedCS: LinearUnit", linearUnit);
+        if (!linearUnit.isCompatible(Units.METRE)) {
+            throw new IllegalArgumentException(
+                    "Error when trying to create a PCS using this linear UoM "
+                    + linearUnit.toString());
+        }
+        //-- TODO Vocabulary.Keys.Projected Easting Northing
+        return new DefaultCartesianCS(name(Vocabulary.formatInternational(/*Vocabulary.Keys.Projected*/(short)208).toString()),
+                new DefaultCoordinateSystemAxis(name(Vocabulary.formatInternational(/*Vocabulary.Keys.Easting*/(short)74).toString()), "E",
+                AxisDirection.EAST, linearUnit),
+                new DefaultCoordinateSystemAxis(name(Vocabulary.formatInternational(/*Vocabulary.Keys.Northing*/(short)178).toString()), "N",
+                AxisDirection.NORTH, linearUnit));
+    }
+
+
+    ////////////////////////////////////////////////////////////////////////////
+    //-------------------------- PROJECTED CRS -------------------------------//
+    ////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Creating a {@linkplain CoordinateReferenceSystem Projected CRS} following the GeoTiff spec.<br>
+     * As usual this method tries to follow the geotiff specification<br>
+     * Needed tags are :
+     * <ul>
+     * <li> a code definition given by {@link GeoKeys.CRS.ProjectedCSTypeGeoKey} tag </li>
+     * <li> a name given by {@link GeoKeys.CRS.GeogCitationGeoKey} </li>
+     * <li> a semi major axis value given by {@link GeoKeys.CRS.GeogSemiMajorAxisGeoKey} </li>
+     * <li> a semi major axis value given by {@link GeoKeys.CRS.GeogInvFlatteningGeoKey} </li>
+     * <li> a semi major axis value given by {@link GeoKeys.CRS.GeogSemiMinorAxisGeoKey} </li>
+     * </ul>
+     *
+     * @param unit use for building this {@link CoordinateReferenceSystem}.
+     * @return a {@link CoordinateReferenceSystem} built using the provided {@link Unit}.
+     * @throws FactoryException if problem during factory Projected CRS creation.
+     * @throws DataStoreContentException if missing needed geokeys.
      */
     private CoordinateReferenceSystem createProjectedCRS()
             throws FactoryException, DataStoreContentException {
 
-        String tempCode = geoKeys.getAsString(GeoKeys.CRS.ProjectedCSTypeGeoKey);
-        if (tempCode == null) tempCode = "unnamed";
+        final String projCode = geoKeys.getAsString(GeoKeys.CRS.ProjectedCSTypeGeoKey);
 
         //-- getting the linear unit used by this coordinate reference system.
         final Unit linearUnit = createUnit(GeoKeys.CRS.ProjLinearUnitsGeoKey,
@@ -456,27 +613,26 @@ public class TiffCRSBuilder {
         //-- if it's user defined, we have to parse many informations and
         //-- try to build appropriate projected CRS from theses parsed informations.
         //-- like base gcrs, datum, unit ...
-        if (tempCode.equalsIgnoreCase("unnamed")
-         || tempCode.equals(GeoKeys.Configuration.GTUserDefinedGeoKey_String)) {
+        if (projCode == null
+         || projCode.equals(GeoKeys.Configuration.GTUserDefinedGeoKey_String))
             return createUserDefinedProjectedCRS(linearUnit);
-        }
         //---------------------------------------------------------------------//
 
         //---------------------- EPSG CODE PERTINENCY -------------------------//
         //-- do a decode
-        final StringBuffer projCode = new StringBuffer(tempCode.trim().intern());
-        if (!tempCode.startsWith("EPSG") && !tempCode.startsWith("epsg")) {
-            projCode.insert(0, "EPSG:");
-        }
+        final StringBuffer epsgProjCode = new StringBuffer(projCode.trim().intern());
+        if (!projCode.startsWith("EPSG")
+         && !projCode.startsWith("epsg")) epsgProjCode.insert(0, "EPSG:");
 
         //TODO : jsorel : are we sure of this ? always long/lat order ?
-        ProjectedCRS pcrs = (ProjectedCRS) AbstractCRS.castOrCopy(CRS.forCode(projCode.toString())).forConvention(AxesConvention.RIGHT_HANDED);
+        //-- TODO rmarechal : I think just a decode is enought
+        ProjectedCRS pcrs = (ProjectedCRS) AbstractCRS.castOrCopy(CRS.forCode(epsgProjCode.toString())).forConvention(AxesConvention.RIGHT_HANDED);
 
         //-- if 'tiff defined unit' does not match with decoded Projected CRS, build another converted projected CRS.
         if (linearUnit != null && !linearUnit.equals(pcrs.getCoordinateSystem().getAxis(0).getUnit())) {
             //-- Creating anew projected CRS
             pcrs = new DefaultProjectedCRS(
-                    java.util.Collections.singletonMap("name", IdentifiedObjects.getName(pcrs, new DefaultCitation("EPSG"))),
+                    name(IdentifiedObjects.getName(pcrs, new DefaultCitation("EPSG"))),
                     (GeographicCRS) pcrs.getBaseCRS(),
                     pcrs.getConversionFromBase(),
                     createProjectedCS(linearUnit));
@@ -485,200 +641,137 @@ public class TiffCRSBuilder {
     }
 
     /**
-     * We have a user defined {@link ProjectedCRS} (means, exist some additionals geokeys to build this projectedCRS).
+     * Creating a User Define {@linkplain CoordinateReferenceSystem Projected CRS} following the GeoTiff spec.<br>
+     * As usual this method tries to follow the geotiff specification<br>
+     * Needed tags are :
+     * <ul>
+     * <li> a name given by {@link GeoKeys.CRS.PCSCitationGeoKey} </li>
+     * <li> a {@link CoordinateOperation} given by {@link GeoKeys.CRS.ProjectionGeoKey} </li>
+     * <li> an {@link OperationMethod} given by {@link GeoKeys.CRS.ProjCoordTransGeoKey} </li>
+     * </ul>
      *
-     * @param linearUnit
-     *            is the UoM that this {@link ProjectedCRS} will use. It could
-     *            be null.
+     * @param linearUnit is the UoM that this {@link ProjectedCRS} will use. It could be {@code null}.
      *
      * @return a user-defined {@link ProjectedCRS}.
-     * @throws IOException
-     * @throws FactoryException
+     * @throws DataStoreContentException if missing needed geoKey.
+     * @throws FactoryException if problem during projected CRS factory build.
      */
     private ProjectedCRS createUserDefinedProjectedCRS(final Unit linearUnit)
             throws FactoryException, DataStoreContentException {
-        //-- get projected CRS Name or code
+        //-- get projected CRS Name
         String projectedCrsName = geoKeys.getAsString(GeoKeys.CRS.PCSCitationGeoKey);
-        if (projectedCrsName == null) {
-            projectedCrsName = "unnamed".intern();
-        }
-
-        // /////////////////////////////////////////////////////////////////////
-        // PROJECTION geo key for this projected coordinate reference system.
-        // get the projection code for this PCRS to build it from the GCS.
-        //
-        // In case i is user defined it requires:
-        // PCSCitationGeoKey
-        // ProjCoordTransGeoKey
-        // ProjLinearUnitsGeoKey
-        // /////////////////////////////////////////////////////////////////////
-        final String projCode = geoKeys.getAsString(GeoKeys.CRS.ProjectionGeoKey).trim().intern();
-        final boolean projUserDefined = (projCode == null
-                                      || projCode.equals(GeoKeys.Configuration.GTUserDefinedGeoKey_String));
-
+        if (projectedCrsName == null)
+            projectedCrsName = "User Defined unnamed ProjectedCRS".intern();
 
         //--------------------------------------------------------------------//
-        //                       GEOGRAPHIC BASE CRS                          //
+        //                   get the GEOGRAPHIC BASE CRS                      //
         //--------------------------------------------------------------------//
         final GeographicCRS gcs = createGeographicBaseCRS();
 
+        CartesianCS predefineCartesianCS = epsgFactory().createCartesianCS("EPSG:4400");
+
+        //-- get the projection code if exist
+        final String projCode = geoKeys.getAsString(GeoKeys.CRS.ProjectionGeoKey).trim().intern();
+
         //-- is it user defined?
-        Conversion projection = null;
-        final ParameterValueGroup parameters;
-        if (projUserDefined) {
-            //-- A user defined projection is made up by
-            //-- PCSCitationGeoKey (NAME)
-            //-- ProjCoordTransGeoKey
-            //-- ProjLinearUnitsGeoKey
-            String projectionName = geoKeys.getAsString(GeoKeys.CRS.PCSCitationGeoKey);
-            if (projectionName == null) projectionName = "unnamed";
+        final Conversion projection;
+        if (projCode == null
+         || projCode.equals(GeoKeys.Configuration.GTUserDefinedGeoKey_String)) {
 
-            //-- getting default parameters for this projection and filling them
-            //-- with the values found inside the geokeys list.
+            //-- get Operation Method from proj key
             final String coordTrans               = geoKeys.getAsString(GeoKeys.CRS.ProjCoordTransGeoKey);
-            final OperationMethod operationMethod = operationFactory.getOperationMethod(coordTrans);
-            parameters                            = operationMethod.getParameters().createValue();
-            projection                            = operationFactory.createDefiningConversion(name(projectionName), operationMethod, parameters);
-
-            //-- is a user define projection
-            //-- we need to set the remaining parameters.
-            final GeodeticDatum tempDatum = ((GeodeticDatum) gcs.getDatum());
-            final DefaultEllipsoid tempEll = (DefaultEllipsoid) tempDatum.getEllipsoid();
-            double inverseFlattening = tempEll.getInverseFlattening();
-            double semiMajorAxis = tempEll.getSemiMajorAxis();
-            //-- setting missing parameters
-            parameters.parameter("semi_minor").setValue(
-                    semiMajorAxis * (1 - (1 / inverseFlattening)));
-            parameters.parameter("semi_major").setValue(semiMajorAxis);
-
-            //-- manage Units
-            CartesianCS cs = getPredefineCartesianCS();
-            if(linearUnit != null && !linearUnit.equals(Units.METRE)){
-                cs = (CartesianCS) CoordinateSystems.replaceLinearUnit(cs, linearUnit);//-- TODO : retrouver un code epsg corespondant a l'ensemble (cs + unité)
-            }
-
-            return objFactory.createProjectedCRS(
-                    Collections.singletonMap("name", projectedCrsName),
-                    gcs, projection, cs);
+            if (coordTrans == null) missingKeyException(GeoKeys.CRS.ProjCoordTransGeoKey);
+            final OperationMethod operationMethod = operationFactory().getOperationMethod(coordTrans);
+            final ParameterValueGroup parameters  = operationMethod.getParameters().createValue();
+            projection                            = operationFactory().createDefiningConversion(name(projectedCrsName), operationMethod, parameters);
+        } else {
+            projection = (Conversion) epsgFactory().createCoordinateOperation(String.valueOf(projCode));
         }
 
-        projection = (Conversion) epsgFactory.createCoordinateOperation(String.valueOf(projCode));
-
-        //-- standard projection
         //-- manage unit if necessary
-        if (linearUnit != null && !linearUnit.equals(Units.METRE)) {
-            return objFactory.createProjectedCRS(Collections.singletonMap(
-                    "name", projectedCrsName), gcs, projection,
-                    (CartesianCS) CoordinateSystems.replaceLinearUnit(getPredefineCartesianCS(), linearUnit)); //-- TODO : retrouver un code epsg corespondant a l'ensemble (cs + unité)
-        }
-        return objFactory.createProjectedCRS(Collections.singletonMap("name",
-                projectedCrsName), gcs, projection,
-                getPredefineCartesianCS());
-    }
+        if (linearUnit != null && !linearUnit.equals(Units.METRE))
+            predefineCartesianCS = (CartesianCS) CoordinateSystems.replaceLinearUnit(predefineCartesianCS, linearUnit);//-- TODO : retrouver un code epsg corespondant a l'ensemble (cs + unité)
 
-    private CartesianCS getPredefineCartesianCS()
-            throws FactoryException {
-        return epsgFactory.createCartesianCS("EPSG:4400");
-    }
-
-    /**
-     * Creates a {@link CartesianCS} for a {@link ProjectedCRS} given the
-     * provided {@link Unit}.
-     *
-     * @todo consider caching this items
-     * @param linearUnit
-     *            to be used for building this {@link CartesianCS}.
-     * @return an instance of {@link CartesianCS} using the provided
-     *         {@link Unit},
-     */
-    private DefaultCartesianCS createProjectedCS(final Unit linearUnit) {
-        ArgumentChecks.ensureNonNull("ProjectedCS: LinearUnit", linearUnit);
-        if (!linearUnit.isCompatible(Units.METRE)) {
-            throw new IllegalArgumentException(
-                    "Error when trying to create a PCS using this linear UoM "
-                    + linearUnit.toString());
-        }
-        //-- TODO Vocabulary.Keys.Projected Easting Northing
-        return new DefaultCartesianCS(name(Vocabulary.formatInternational(/*Vocabulary.Keys.Projected*/(short)208).toString()),
-                new DefaultCoordinateSystemAxis(name(Vocabulary.formatInternational(/*Vocabulary.Keys.Easting*/(short)74).toString()), "E",
-                AxisDirection.EAST, linearUnit),
-                new DefaultCoordinateSystemAxis(name(Vocabulary.formatInternational(/*Vocabulary.Keys.Northing*/(short)178).toString()), "N",
-                AxisDirection.NORTH, linearUnit));
+        return objectFactory().createProjectedCRS(name(projectedCrsName), gcs, projection, predefineCartesianCS);
     }
 
 
-    //----------------------------- GEOGRAPHIC ---------------------------------
+    ////////////////////////////////////////////////////////////////////////////
+    //-------------------------- GEOGRAPHIC CRS ------------------------------//
+    ////////////////////////////////////////////////////////////////////////////
     /**
      *
      * @return
      */
-    private CoordinateReferenceSystem createGeographicCRS() {
-        return null;
-    }
+    private CoordinateReferenceSystem createGeographicCRS()
+            throws FactoryException, DataStoreContentException {
+        GeographicCRS gcs = null;
+
+        //-- Get the crs code
+        final String tempCode = geoKeys.getAsString(GeoKeys.CRS.GeographicTypeGeoKey);
+        // lookup the angular units used in this geotiff image
+        Unit angularUnit = createUnit(GeoKeys.CRS.GeogAngularUnitsGeoKey,
+                    GeoKeys.CRS.GeogAngularUnitSizeGeoKey, Units.RADIAN,
+                    Units.DEGREE);
+        // linear unit
+        Unit linearUnit = createUnit(GeoKeys.CRS.GeogLinearUnitsGeoKey,
+                    GeoKeys.CRS.GeogLinearUnitSizeGeoKey, Units.METRE,
+                    Units.METRE);
+        // if it's user defined, there's a lot of work to do
+        if (tempCode == null
+         || tempCode.equals(GeoKeys.Configuration.GTUserDefinedGeoKey_String)) {
+            // ////////////////////////////////////////////////////////////////////
+            // it is user-defined we have to parse a lot of information in order
+            // to built it.
+            // ////////////////////////////////////////////////////////////////////
+            return createUserDefinedGCS(linearUnit, angularUnit);
+        }
+
+        // ////////////////////////////////////////////////////////////////////
+        // If it's not user defined, just use the EPSG factory to create
+        // the coordinate system but check if the user specified a
+        // different angular unit. In this case we need to create a
+        // user-defined GCRS.
+        // ////////////////////////////////////////////////////////////////////
+        final StringBuffer geogCode = new StringBuffer(tempCode);
+        if (!tempCode.startsWith("EPSG")
+                && !tempCode.startsWith("epsg")) {
+            geogCode.insert(0, "EPSG:");
+        }
 
-    /**
-     * Creating an ellipsoid following the GeoTiff spec.
-     *
-     * @param unit to build this {@link Ellipsoid}..
-     * @return an {@link Ellipsoid}.
-     * @throws GeoTiffException
-     */
-    private Ellipsoid createEllipsoid(final Unit unit) throws FactoryException { //-- TODO refactor this method
-        // /////////////////////////////////////////////////////////////////////
-        // Getting the ellipsoid key in order to understand if we are working
-        // against a common ellipsoid or a user defined one.
-        // /////////////////////////////////////////////////////////////////////
-        // ellipsoid key
-        final String ellipsoidKey = geoKeys.getAsString(GeoKeys.CRS.GeogEllipsoidGeoKey);
-        String temp = null;
-        // is the ellipsoid user defined?
-        if (ellipsoidKey.equalsIgnoreCase(GeoKeys.Configuration.GTUserDefinedGeoKey_String)) {
-            // /////////////////////////////////////////////////////////////////////
-            // USER DEFINED ELLIPSOID
-            // /////////////////////////////////////////////////////////////////////
-            String nameEllipsoid = geoKeys.getAsString(GeoKeys.CRS.GeogCitationGeoKey);
-            if (nameEllipsoid == null) {
-                nameEllipsoid = "unnamed";
-            }
-            // is it the default for WGS84?
-            if (nameEllipsoid.trim().equalsIgnoreCase("WGS84")) {
-                return CommonCRS.WGS84.ellipsoid();
-            }
+        final CoordinateReferenceSystem decCRS = AbstractCRS.castOrCopy(CRS.forCode(geogCode.toString())).forConvention(AxesConvention.RIGHT_HANDED);
+        //-- all CRS must be Geodetic
+        if (!(decCRS instanceof GeodeticCRS))
+            throw new IllegalArgumentException("Impossible to define CRS from none Geodetic base. found : "+decCRS.toWKT());
+
+        if (decCRS instanceof GeographicCRS) {
+            gcs = (GeographicCRS) AbstractCRS.castOrCopy(CRS.forCode(geogCode.toString())).forConvention(AxesConvention.RIGHT_HANDED);
+        } else {
+            //-- Try to build it from datum and re-create Geographic CRS. //-- TODO : Log warning
+//                    LOGGER.log(Level.WARNING, "Impossible to build Projected CRS from none Geographic base CRS, replaced by Geographic CRS.");
+            final GeodeticCRS geodeticCrs = (GeodeticCRS) decCRS;
+            final GeodeticDatum datum = geodeticCrs.getDatum();
+            final HashMap<String, Object> properties = new HashMap<String, Object>();
+            properties.put(GeographicCRS.NAME_KEY, decCRS.getName());
+            gcs = new DefaultGeographicCRS(properties, datum, org.apache.sis.referencing.CommonCRS.defaultGeographic().getCoordinateSystem());
+        }
 
+        if (angularUnit != null
+        && !angularUnit.equals(gcs.getCoordinateSystem().getAxis(0).getUnit())) {
             // //
-            // It is worth to point out that I ALWAYS use the inverse flattening
-            // along with the semi-major axis to builde the Flattened Sphere.
-            // This
-            // has to be done in order to comply with the opposite process of
-            // going from CRS to metadata where this coupls is always used.
+            // Create a user-defined GCRS using the provided angular
+            // unit.
             // //
-            // getting temporary parameters
-            temp = geoKeys.getAsString(GeoKeys.CRS.GeogSemiMajorAxisGeoKey);
-            final double semiMajorAxis = (temp != null ? Double.parseDouble(temp) : Double.NaN);
-            temp = geoKeys.getAsString(GeoKeys.CRS.GeogInvFlatteningGeoKey);
-            final double inverseFlattening;
-            if (temp != null) {
-                inverseFlattening = (temp != null ? Double.parseDouble(temp)
-                        : Double.NaN);
-            } else {
-                temp = geoKeys.getAsString(GeoKeys.CRS.GeogSemiMinorAxisGeoKey);
-                final double semiMinorAxis = (temp != null ? Double.parseDouble(temp) : Double.NaN);
-                inverseFlattening = semiMajorAxis
-                        / (semiMajorAxis - semiMinorAxis);
-
-            }
-            // look for the Ellipsoid first then build the datum
-            return DefaultEllipsoid.createFlattenedSphere(
-                    Collections.singletonMap(DefaultEllipsoid.NAME_KEY, nameEllipsoid),
-                    semiMajorAxis, inverseFlattening, unit);
+            gcs = objectFactory().createGeographicCRS(name(IdentifiedObjects.getName(gcs, new DefaultCitation("EPSG"))),
+                    (GeodeticDatum) gcs.getDatum(),
+                    (EllipsoidalCS) CoordinateSystems.replaceAngularUnit(CommonCRS.defaultGeographic().getCoordinateSystem(), angularUnit));
         }
 
-        // /////////////////////////////////////////////////////////////////////
-        // EPSG STANDARD ELLIPSOID
-        // /////////////////////////////////////////////////////////////////////
-        return epsgFactory.createEllipsoid(String.valueOf(ellipsoidKey));
+        return gcs;
     }
 
+
+
     /**
      * Creation of a geographic coordinate reference system as specified in the
      * GeoTiff specification. User defined values are supported for all the
@@ -744,12 +837,12 @@ public class TiffCRSBuilder {
             final HashMap<String, Object> properties = new HashMap<String, Object>();
             properties.put(GeographicCRS.NAME_KEY, decCRS.getName());
 
-            gcs = objFactory.createGeographicCRS(properties, datum, org.apache.sis.referencing.CommonCRS.defaultGeographic().getCoordinateSystem());
+            gcs = objectFactory().createGeographicCRS(properties, datum, org.apache.sis.referencing.CommonCRS.defaultGeographic().getCoordinateSystem());
         }
 
         if (angularUnit != null && !angularUnit.equals(gcs.getCoordinateSystem().getAxis(0).getUnit())) {
             //-- Create a user-defined GCRS using the provided angular unit.
-            gcs = objFactory.createGeographicCRS(name(IdentifiedObjects.getName(gcs, new DefaultCitation("EPSG"))),
+            gcs = objectFactory().createGeographicCRS(name(IdentifiedObjects.getName(gcs, new DefaultCitation("EPSG"))),
                     (GeodeticDatum) gcs.getDatum(),
                     (EllipsoidalCS) CoordinateSystems.replaceAngularUnit(CommonCRS.defaultGeographic().getCoordinateSystem(), angularUnit));
         }
@@ -783,128 +876,22 @@ public class TiffCRSBuilder {
 
         final GeodeticDatum datum = createGeodeticDatum(linearUnit); //-- TODO ?? is it conform ??
         CoordinateSystem replaceAngularUnit = CoordinateSystems.replaceAngularUnit(CommonCRS.defaultGeographic().getCoordinateSystem(),
-                angularUnit);
+                angularUnit);//-- debug
 
         // make the user defined GCS from all the components...
-        return objFactory.createGeographicCRS(Collections.singletonMap("name", name),
+        return objectFactory().createGeographicCRS(name(name),
                                               datum,
                                               (EllipsoidalCS) CoordinateSystems.replaceAngularUnit(CommonCRS.defaultGeographic().getCoordinateSystem(),
                                                                                                    angularUnit));
     }
 
-    /**
-     * Looks up the Geodetic Datum as specified in the GeoTIFFWritingUtilities
-     * file. The geotools definition of the geodetic datum includes both an
-     * ellipsoid and a prime meridian, but the code in the
-     * GeoTIFFWritingUtilities file does NOT include the prime meridian, as it
-     * is specified separately. This code currently does not support user
-     * defined datum.
-     *
-     * @param unit to use for building this {@link GeodeticDatum}.
-     * @return a {@link GeodeticDatum}.
-     * @throws IOException
-     * @throws GeoTiffException
-     *
-     */
-    private GeodeticDatum createGeodeticDatum(final Unit unit)
-            throws DataStoreContentException, FactoryException { //-- TODO : refactor this method
-        // lookup the datum (w/o PrimeMeridian), error if "user defined"
-        GeodeticDatum datum = null;
-        final String datumCode = geoKeys.getAsString(GeoKeys.CRS.GeogGeodeticDatumGeoKey);
-
-        if (datumCode == null) {
-            throw new DataStoreContentException("A user defined Geographic Coordinate system must include a predefined datum!");
-        }
-
-        if (datumCode.equals(GeoKeys.Configuration.GTUserDefinedGeoKey_String)) {
-            /**
-             * USER DEFINED DATUM
-             */
-            // datum name
-            final String datumName = (geoKeys.getAsString(GeoKeys.CRS.GeogCitationGeoKey) != null ? geoKeys.getAsString(GeoKeys.CRS.GeogCitationGeoKey)
-                    : "unnamed");
-
-            // is it WGS84?
-            if (datumName.trim().equalsIgnoreCase("WGS84")) {
-                return CommonCRS.WGS84.datum();
-            }
-
-            // ELLIPSOID
-            final Ellipsoid ellipsoid = createEllipsoid(unit);
-
-            // PRIME MERIDIAN
-            // lookup the Prime Meridian.
-            final PrimeMeridian primeMeridian = createPrimeMeridian(unit);
-
-            // DATUM
-            datum = new DefaultGeodeticDatum(Collections.singletonMap(GeodeticDatum.NAME_KEY, datumName), ellipsoid,
-                    primeMeridian);
-        } else {
-            /**
-             * NOT USER DEFINED DATUM
-             */
-            // we are going to use the provided EPSG code
-            datum = (GeodeticDatum) (epsgFactory.createDatum(String.valueOf(datumCode)));
-        }
-
-        return datum;
-    }
-
-    /**
-     * Creating a prime meridian for the gcs we are creating at an higher level.
-     * As usual this method tries to follow the geotiff specification.
-     *
-     * @param linearUnit
-     *            to use for building this {@link PrimeMeridian}.
-     * @return a {@link PrimeMeridian} built using the provided {@link Unit} and
-     *         the provided metadata.
-     * @throws IOException
-     */
-    private PrimeMeridian createPrimeMeridian(final Unit linearUnit) //-- TODO refactor this method
-            throws DataStoreContentException, FactoryException {
-        // look up the prime meridian:
-        // + could be an EPSG code
-        // + could be user defined
-        // + not defined = greenwich
-        final String pmCode = geoKeys.getAsString(GeoKeys.CRS.GeogPrimeMeridianGeoKey);
-        PrimeMeridian pm = null;
-
-        if (pmCode != null) {
-            if (pmCode.equals(GeoKeys.Configuration.GTUserDefinedGeoKey_String)) {
-                try {
-                    final String name = geoKeys.getAsString(GeoKeys.CRS.GeogCitationGeoKey);
-                    final String pmValue = geoKeys.getAsString(GeoKeys.CRS.GeogPrimeMeridianLongGeoKey);
-                    final double pmNumeric = Double.parseDouble(pmValue);
-                    // is it Greenwich?
-                    if (pmNumeric == 0) {
-                        return CommonCRS.WGS84.primeMeridian();
-                    }
-                    final Map props = new HashMap();
-                    props.put("name", (name != null) ? name
-                            : "User Defined GEOTIFF Prime Meridian");
-                    pm = datumObjFactory.createPrimeMeridian(props,
-                            pmNumeric, linearUnit);
-                } catch (NumberFormatException nfe) {
-                    throw new DataStoreContentException("Invalid user-defined prime meridian spec.",nfe);
-                }
-            } else {
-                pm = epsgFactory.createPrimeMeridian(String.valueOf(pmCode));
-            }
-        } else {
-            pm = CommonCRS.WGS84.primeMeridian();
-        }
-
-        return pm;
-    }
-
-
     //------------------------------- GEOCENTRIQUE -----------------------------
     /**
      *
      * @return
      */
     private CoordinateReferenceSystem createGeocentricCRS() {
-        return null;
+        throw new IllegalStateException("Not implemented yet.");
     }
 
 
@@ -957,17 +944,14 @@ public class TiffCRSBuilder {
         if (geoKeyDirectoryTag == null)
             return null; //-- TODO image CRS2D ??
 
-        initFactories();//-- TODO : only build needed factories
-
         //-- build Coordinate Reference System keys
         parseGeoKeyDirectory();
 
         final int crsType = geoKeys.getAsInteger(GeoKeys.Configuration.GTModelTypeGeoKey);
 
-        final CoordinateReferenceSystem crs;
         switch (crsType) {
             case GeoKeys.Configuration.ModelTypeProjected  : return createProjectedCRS();
-            case GeoKeys.Configuration.ModelTypeGeographic : throw new DataStoreContentException("not implemented yet : Geographic CRS");//return null;
+            case GeoKeys.Configuration.ModelTypeGeographic : return createGeographicCRS();//return null;
             case GeoKeys.Configuration.ModelTypeGeocentric : throw new DataStoreContentException("not implemented yet : Geocentric CRS");//return null;
             default : {
                 return null; //-- TODO image CRS2D ??
@@ -976,6 +960,196 @@ public class TiffCRSBuilder {
     }
 
 //------------------------------------------------------------------------------
+//                      TODO SEE LATER PARTICULARITY CASE CRS WITH
+//                      MERCATOR1SP AND MERCATOR2SP
+//                      POLAR STEREOGRAPHIC VARIANT A B AND C
+//------------------------------------------------------------------------------
+    /**
+     * @todo we should somehow try to to support user defined coordinate
+     *       transformation even if for the moment is not so clear to me how we
+     *       could achieve that since if we have no clue about the coordinate
+     *       transform what we are supposed to do in order to build a
+     *       conversion, guess it? How could we pick up the parameters, should
+     *       look for all and then guess the right transformation?
+     *
+     * @param name indicates the name for the projection.
+     * @param metadata to use for building this {@link ParameterValueGroup}.
+     * @return a {@link ParameterValueGroup} that can be used to trigger this
+     *         projection.
+     * @throws IOException
+     * @throws FactoryException
+     */
+    private ParameterValueGroup createUserDefinedProjectionParameter(
+            final String name)
+            throws FactoryException, NoSuchIdentifierException, DataStoreContentException {
+        // //
+        //
+        // Trying to get the name for the coordinate transformation involved.
+        //
+        // ///
+        final String coordTrans = geoKeys.getAsString(GeoKeys.CRS.ProjCoordTransGeoKey);
+
+        // throw descriptive exception if ProjCoordTransGeoKey not defined
+        if ((coordTrans == null)
+                || coordTrans.equalsIgnoreCase(GeoKeys.Configuration.GTUserDefinedGeoKey_String)) {
+            throw new DataStoreContentException("User defined projections must specify"
+                    + " coordinate transformation code in ProjCoordTransGeoKey");
+        }
+
+        // getting math transform factory
+        return setParametersForProjection(name, coordTrans);
+    }
+
+    /**
+     * Set the projection parameters basing its decision on the projection name.
+     * I found a complete list of projections on the geotiff website at address
+     * http://www.remotesensing.org/geotiff/proj_list.
+     *
+     * I had no time to implement support for all of them therefore you will not
+     * find all of them. If you want go ahead and add support for the missing
+     * ones. I have tested this code against some geotiff files you can find on
+     * the geotiff website under the ftp sample directory but I can say that
+     * they are a real mess! I am respecting the specification strictly while
+     * many of those fields do not! I could make this method trickier and use
+     * workarounds in order to be less strict but I will not do this, since I
+     * believe it is may lead us just on a very dangerous path.
+     *
+     *
+     * @param name
+     * @param metadata to use fo building this {@link ParameterValueGroup}.
+     * @param coordTrans
+     *            a {@link ParameterValueGroup} that can be used to trigger this
+     *            projection.
+     *
+     * @return
+     * @throws GeoTiffException
+     */
+    private ParameterValueGroup setParametersForProjection(final String name, final String coordTransCode)
+            throws NoSuchIdentifierException, DataStoreContentException {
+
+        if (name == null && coordTransCode == null)
+            throw new DataStoreContentException("bla bla bla");//-- TODO : do better
+
+        final String projName = (name == null)
+                                ? GeoKeys.CRS.getName(Integer.parseInt(coordTransCode))
+                                : name;
+
+        final ParameterValueGroup parameters = null;//mtFactory.getDefaultParameters(projName);
+
+        //-- particularity cases
+        for (int key : geoKeys.keySet()) {
+            if (GeoKeys.CRS.contain(key)) {
+                String keyName = GeoKeys.CRS.getName(key);
+                keyName = keyName.substring(4, keyName.length()-6);
+                parameters.parameter(keyName).setValue(geoKeys.getAsString(key));
+            }
+        }
+
+        //-- maybe particularity case
+//            /**
+//             * Mercator_1SP
+//             * Mercator_2SP
+//             */
+//            if (name.equalsIgnoreCase("mercator_1SP")
+//                    || name.equalsIgnoreCase("Mercator_2SP")
+//                    || code == CT_Mercator) {
+//
+//                final double standard_parallel_1 = metadata.getAsDouble(ProjStdParallel1GeoKey);
+//                boolean isMercator2SP = false;
+//                if (!Double.isNaN(standard_parallel_1)) {
+//                    parameters = mtFactory.getDefaultParameters("Mercator_2SP");
+//                    isMercator2SP = true;
+//                } else {
+//                    parameters = mtFactory.getDefaultParameters("Mercator_1SP");
+//                }
+//
+//                parameters.parameter(code(Mercator1SP.LONGITUDE_OF_ORIGIN)).setValue(getOriginLong(metadata));
+//                parameters.parameter(code(Mercator1SP.LATITUDE_OF_ORIGIN)).setValue(getOriginLat(metadata));
+//                parameters.parameter(code(Mercator2SP.FALSE_EASTING)).setValue(getFalseEasting(metadata));
+//                parameters.parameter(code(Mercator2SP.FALSE_NORTHING)).setValue(getFalseNorthing(metadata));
+//                if (isMercator2SP) {
+//                    parameters.parameter(code(Mercator2SP.STANDARD_PARALLEL)).setValue(standard_parallel_1);
+//                } else {
+//                    parameters.parameter(code(Mercator1SP.SCALE_FACTOR)).setValue(getScaleFactor(metadata));
+//                }
+//                return parameters;
+//            }
+//
+//            /**
+//             * POLAR_STEREOGRAPHIC variant A B and C
+//             */
+//            if (code == CT_PolarStereographic) {
+//
+//                /**
+//                 * They exist 3 kind of polar StereoGraphic projections,define the case
+//                 * relative to existing needed attributs
+//                 */
+//                //-- set the mutual projection attributs
+//                //-- all polar stereographic formulas share LONGITUDE_OF_ORIGIN
+//                final double longitudeOfOrigin = metadata.getAsDouble(ProjStraightVertPoleLongGeoKey);
+//
+//                /*
+//                * For polar Stereographic variant A only latitudeOfNaturalOrigin expected values are {-90; +90}.
+//                * In some case, standard parallele is stipulate into latitudeOfNaturalOrigin tiff tag by error.
+//                * To avoid CRS problem creation, try to anticipe this comportement by switch latitudeOfNaturalOrigin into standard parallele.
+//                * HACK FOR USGS LANDSAT 8 difference between geotiff tag and Landsat 8 metadata MTL.txt file.
+//                */
+//                double standardParallel                 = metadata.getAsDouble(ProjStdParallel1GeoKey);
+//                final double latitudeOfNaturalOrigin    = metadata.getAsDouble(ProjNatOriginLatGeoKey);
+//                final boolean isVariantALatitudeConform = (Math.abs(Latitude.MAX_VALUE - Math.abs(latitudeOfNaturalOrigin)) <  Formulas.ANGULAR_TOLERANCE);
+//
+//                if (!isVariantALatitudeConform && Double.isNaN(standardParallel)) {
+//                    LOGGER.log(Level.WARNING, "The latitudeOfNaturalOrigin for Polar Stereographic variant A is not conform.\n"
+//                            + "Expected values are {-90; +90}, found : "+latitudeOfNaturalOrigin+"\n"
+//                            + "Switch latitudeOfNaturalOrigin by Latitude of standard parallel to try building of Polar Stereographic Variant B or C.");
+//                    standardParallel = latitudeOfNaturalOrigin;
+//                }
+//
+//                if (Double.isNaN(standardParallel)) {
+//                    //-- no standard parallele : PolarStereoGraphic VARIANT A
+//                    final OperationMethod method = DefaultFactories.forBuildin(CoordinateOperationFactory.class)
+//                    .getOperationMethod("Polar Stereographic (variant A)");
+//
+//                    parameters = method.getParameters().createValue();
+//                    parameters.parameter(code(PolarStereographicA.LONGITUDE_OF_ORIGIN)).setValue(longitudeOfOrigin);
+//                    parameters.parameter(code(PolarStereographicA.LATITUDE_OF_ORIGIN)).setValue(latitudeOfNaturalOrigin);
+//                    parameters.parameter(code(PolarStereographicA.SCALE_FACTOR)).setValue(metadata.getAsDouble(ProjScaleAtNatOriginGeoKey));
+//                    parameters.parameter(code(PolarStereographicA.FALSE_EASTING)).setValue(metadata.getAsDouble(ProjFalseEastingGeoKey));
+//                    parameters.parameter(code(PolarStereographicA.FALSE_NORTHING)).setValue(metadata.getAsDouble(ProjFalseNorthingGeoKey));
+//
+//                } else {
+//
+//                    //-- Variant B and C share STANDARD_PARALLEL
+//
+//                    final double falseOriginEasting = metadata.getAsDouble(ProjFalseOriginEastingGeoKey);
+//                    if (Double.isNaN(falseOriginEasting)) {
+//                        //-- no false Origin Easting : PolarStereoGraphic VARIANT B
+//                        final OperationMethod method = DefaultFactories.forBuildin(CoordinateOperationFactory.class)
+//                              .getOperationMethod("Polar Stereographic (variant B)");
+//
+//                        parameters = method.getParameters().createValue();
+//                        parameters.parameter(code(PolarStereographicB.STANDARD_PARALLEL)).setValue(standardParallel);
+//                        parameters.parameter(code(PolarStereographicB.LONGITUDE_OF_ORIGIN)).setValue(longitudeOfOrigin);
+//                        parameters.parameter(code(PolarStereographicB.FALSE_EASTING)).setValue(metadata.getAsDouble(ProjFalseEastingGeoKey));
+//                        parameters.parameter(code(PolarStereographicB.FALSE_NORTHING)).setValue(metadata.getAsDouble(ProjFalseNorthingGeoKey));
+//                    } else {
+//                        //-- PolarStereoGraphic VARIANT C
+//                        final OperationMethod method = DefaultFactories.forBuildin(CoordinateOperationFactory.class)
+//                              .getOperationMethod("Polar Stereographic (variant C)");
+//
+//                        parameters = method.getParameters().createValue();
+//                        parameters.parameter(code(PolarStereographicB.STANDARD_PARALLEL)).setValue(standardParallel);
+//                        parameters.parameter(code(PolarStereographicB.LONGITUDE_OF_ORIGIN)).setValue(longitudeOfOrigin);
+//                        parameters.parameter(code(PolarStereographicC.EASTING_AT_FALSE_ORIGIN)).setValue(metadata.getAsDouble(ProjFalseOriginEastingGeoKey));
+//                        parameters.parameter(code(PolarStereographicC.NORTHING_AT_FALSE_ORIGIN)).setValue(metadata.getAsDouble(ProjFalseNorthingGeoKey));
+//                    }
+//                }
+//            }
+
+        return parameters;
+    }
+
+//------------------------------------------------------------------------------
     /**
      * Map to store all keys from GeoKeyDirectory needed to build CRS.
      */



Mime
View raw message