001/*
002 *    GeoAPI - Java interfaces for OGC/ISO standards
003 *    http://www.geoapi.org
004 *
005 *    Copyright (C) 2011-2019 Open Geospatial Consortium, Inc.
006 *    All Rights Reserved. http://www.opengeospatial.org/ogc/legal
007 *
008 *    Permission to use, copy, and modify this software and its documentation, with
009 *    or without modification, for any purpose and without fee or royalty is hereby
010 *    granted, provided that you include the following on ALL copies of the software
011 *    and documentation or portions thereof, including modifications, that you make:
012 *
013 *    1. The full text of this NOTICE in a location viewable to users of the
014 *       redistributed or derivative work.
015 *    2. Notice of any changes or modifications to the OGC files, including the
016 *       date changes were made.
017 *
018 *    THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE
019 *    NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
020 *    TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT
021 *    THE USE OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY
022 *    PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
023 *
024 *    COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR
025 *    CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR DOCUMENTATION.
026 *
027 *    The name and trademarks of copyright holders may NOT be used in advertising or
028 *    publicity pertaining to the software without specific, written prior permission.
029 *    Title to copyright in this software and any associated documentation will at all
030 *    times remain with copyright holders.
031 */
032package org.opengis.test.referencing.gigs;
033
034import java.util.List;
035import java.util.Random;
036import javax.measure.Unit;
037import javax.measure.UnitConverter;
038import javax.measure.IncommensurableException;
039
040import org.opengis.util.Factory;
041import org.opengis.util.FactoryException;
042import org.opengis.referencing.cs.CSAuthorityFactory;
043import org.opengis.referencing.NoSuchAuthorityCodeException;
044import org.opengis.test.Configuration;
045import org.opengis.test.FactoryFilter;
046import org.opengis.test.Units;
047
048import org.junit.Test;
049import org.junit.runner.RunWith;
050import org.junit.runners.Parameterized;
051
052import static org.junit.Assume.*;
053import static org.junit.Assert.*;
054
055
056/**
057 * Verifies reference units of measure bundled with the geoscience software.
058 *
059 * <table class="gigs" summary="Test description"><tr>
060 *   <th>Test method:</th>
061 *   <td>Compare unit definitions included in the software against the EPSG Dataset.</td>
062 * </tr><tr>
063 *   <th>Test data:</th>
064 *   <td><a href="doc-files/GIGS_2001_libUnit.csv">{@code GIGS_2001_libUnit.csv}</a>
065 *   and EPSG Dataset.
066 *   Contains EPSG {@linkplain #code code} and {@linkplain #name name} for the unit of measure, together with the
067 *   {@linkplain #unitToBase ratio} of the unit to the ISO {@linkplain #baseUnit base unit} for that unit type.
068 *   The test methods are separated in three blocks for linear units, angular units and scaling units.</td>
069 * </tr><tr>
070 *   <th>Tested API:</th>
071 *   <td>{@link CSAuthorityFactory#createUnit(String)}.</td>
072 * </tr><tr>
073 *   <th>Expected result:</th>
074 *   <td>Unit of measure definitions bundled with software should have the ratio to the appropriate base unit
075 *   as in the EPSG Dataset. The values of the base unit per unit should be correct to at least 10 significant figures.
076 *   Units missing from the software or at variance with those in the EPSG Dataset should be reported.</td>
077 * </tr></table>
078 *
079 *
080 * <div class="note"><b>Usage example:</b>
081 * in order to specify their factories and run the tests in a JUnit framework, implementors can
082 * define a subclass in their own test suite as in the example below:
083 *
084 * <blockquote><pre>import org.junit.runner.RunWith;
085 *import org.junit.runners.JUnit4;
086 *import org.opengis.test.referencing.gigs.GIGS2001;
087 *
088 *&#64;RunWith(JUnit4.class)
089 *public class MyTest extends GIGS2001 {
090 *    public MyTest() {
091 *        super(new MyCSAuthorityFactory());
092 *    }
093 *}</pre></blockquote>
094 * </div>
095 *
096 * @author  GIGS (IOGP)
097 * @author  Martin Desruisseaux (Geomatys)
098 * @author  Alexis Manin (Geomatys)
099 * @version 3.1
100 * @since   3.1
101 */
102@RunWith(Parameterized.class)
103public strictfp class GIGS2001 extends AuthorityFactoryTestCase<Unit<?>> {
104    /**
105     * Amount of {@linkplain #baseUnit base units} in one {@linkplain #getIdentifiedObject() tested unit}.
106     * If this amount is not a constant (as in sexagesimal unit), then this factor is set to {@link Double#NaN}.
107     */
108    public double unitToBase;
109
110    /**
111     * The base unit of the unit to create. This field will have one of the following values:
112     *
113     * <ul>
114     *   <li>{@link Units#metre()} if the unit to create is linear,</li>
115     *   <li>{@link Units#radian()} if the unit to create is angular (except sexagesimal unit),</li>
116     *   <li>{@link Units#one()} if the unit to create is a scale or a coefficient, or</li>
117     *   <li>(exceptionally) {@link Units#degree()} in the special case of {@link #testSexagesimalDegree()}.
118     *       Note that sexagesimal units also have the {@linkplain #unitToBase ratio of the unit to base unit}
119     *       set to {@link Double#NaN}.</li>
120     * </ul>
121     */
122    public Unit<?> baseUnit;
123
124    /**
125     * The unit of measurement created by the factory,
126     * or {@code null} if not yet created or if the unit creation failed.
127     *
128     * @see #csAuthorityFactory
129     */
130    private Unit<?> unit;
131
132    /**
133     * Factory to use for building {@link Unit} instances, or {@code null} if none.
134     * This is the factory used by the {@link #getIdentifiedObject()} method.
135     */
136    protected final CSAuthorityFactory csAuthorityFactory;
137
138    /**
139     * Returns a default set of factories to use for running the tests. Those factories are given
140     * in arguments to the constructor when this test class is instantiated directly by JUnit (for
141     * example as a {@linkplain org.junit.runners.Suite.SuiteClasses suite} element), instead than
142     * subclassed by the implementor. The factories are fetched as documented in the
143     * {@link #factories(Class[])} javadoc.
144     *
145     * @return the default set of arguments to be given to the {@code GIGS2001} constructor.
146     */
147    @Parameterized.Parameters
148    @SuppressWarnings("unchecked")
149    public static List<Factory[]> factories() {
150        return factories(FactoryFilter.ByAuthority.EPSG, CSAuthorityFactory.class);
151    }
152
153    /**
154     * Creates a new test using the given factory. If a given factory is {@code null},
155     * then the tests which depend on it will be skipped.
156     *
157     * @param csFactory  factory for creating {@link Unit} instances.
158     */
159    public GIGS2001(final CSAuthorityFactory csFactory) {
160        super(csFactory);
161        csAuthorityFactory = csFactory;
162    }
163
164    /**
165     * Returns information about the configuration of the test which has been run.
166     * This method returns a map containing:
167     *
168     * <ul>
169     *   <li>All the following values associated to the {@link org.opengis.test.Configuration.Key} of the same name:
170     *     <ul>
171     *       <li>{@link #isStandardNameSupported}</li>
172     *       <li>{@link #isStandardAliasSupported}</li>
173     *       <li>{@link #isDependencyIdentificationSupported}</li>
174     *       <li>{@link #csAuthorityFactory}</li>
175     *     </ul>
176     *   </li>
177     * </ul>
178     *
179     * @return the configuration of the test being run.
180     */
181    @Override
182    public Configuration configuration() {
183        final Configuration op = super.configuration();
184        assertNull(op.put(Configuration.Key.csAuthorityFactory, csAuthorityFactory));
185        return op;
186    }
187
188    /**
189     * Returns the unit instance to be tested. When this method is invoked for the first time, it creates the unit
190     * to test by invoking the {@link CSAuthorityFactory#createUnit(String)} method with the current {@link #code}
191     * value in argument. The created object is then cached and returned in all subsequent invocations of this method.
192     *
193     * @return the unit instance to test.
194     * @throws FactoryException if an error occurred while creating the unit instance.
195     */
196    @Override
197    public Unit<?> getIdentifiedObject() throws FactoryException {
198        if (unit == null) {
199            assumeNotNull(csAuthorityFactory);
200            try {
201                unit = csAuthorityFactory.createUnit(String.valueOf(code));
202            } catch (NoSuchAuthorityCodeException e) {
203                unsupportedCode(Unit.class, code);
204                throw e;
205            }
206        }
207        return unit;
208    }
209
210    /**
211     * Gets the unit given by {@link #getIdentifiedObject()},
212     * then creates and returns the converter from that unit to the base unit.
213     *
214     * @throws FactoryException if an error occurred while creating the unit from the EPSG code.
215     */
216    private UnitConverter createConverter() throws FactoryException {
217        final Unit<?> unit = getIdentifiedObject();
218        assertNotNull("Unit", unit);
219        final UnitConverter converter;
220        try {
221            converter = unit.getConverterToAny(baseUnit);
222        } catch (IncommensurableException e) {
223            throw new AssertionError("Can not convert “" + name + "” from “" + unit + "” to “" + baseUnit + "”.", e);
224        }
225        return converter;
226    }
227
228    /**
229     * Converts random values using the unit converter and compares against the expected value.
230     * The expected values are obtained by multiplying the values to convert by the given factor.
231     *
232     * @param  converter  the converter from tested {@link #unit} to the base unit.
233     */
234    private void verifyLinearConversions(final UnitConverter converter) {
235        final Random random = new Random();
236        final double tolerance = TOLERANCE * unitToBase;
237        assertEquals(name, 0, converter.convert(0), tolerance);
238        assertEquals(name,  unitToBase, converter.convert( 1), tolerance);
239        assertEquals(name, -unitToBase, converter.convert(-1), tolerance);
240        for (double sample = -90; sample <= 90; sample += 4*random.nextDouble()) {
241            final double expected = sample * unitToBase;
242            assertEquals(name, expected, converter.convert(sample), tolerance);
243        }
244    }
245
246    /**
247     * Tests “metre” unit creation from the factory.
248     *
249     * <ul>
250     *   <li>EPSG UoM code: <b>9001</b></li>
251     *   <li>Type: <b>Linear</b></li>
252     *   <li>Name of Units used in EPSG dataset: <b>metre</b></li>
253     *   <li>Base units per unit: <b>1</b></li>
254     *   <li>Specific usage / Remarks: <b>Numerous</b></li>
255     *   <li>Particularly important to E&amp;P industry.</li>
256     * </ul>
257     *
258     * @throws FactoryException if an error occurred while creating the unit from the EPSG code.
259     */
260    @Test
261    public void testMetre() throws FactoryException {
262        important  = true;
263        code       = 9001;
264        name       = "metre";
265        aliases    = NONE;
266        unitToBase = 1.0;
267        baseUnit   = units.metre();
268        verifyLinearConversions(createConverter());
269    }
270
271    /**
272     * Tests “kilometre” unit creation from the factory.
273     *
274     * <ul>
275     *   <li>EPSG UoM code: <b>9036</b></li>
276     *   <li>Type: <b>Linear</b></li>
277     *   <li>Name of Units used in EPSG dataset: <b>kilometre</b></li>
278     *   <li>Base units per unit: <b>1000</b></li>
279     *   <li>Specific usage / Remarks: <b>Tunisia</b></li>
280     *   <li>Particularly important to E&amp;P industry.</li>
281     * </ul>
282     *
283     * @throws FactoryException if an error occurred while creating the unit from the EPSG code.
284     */
285    @Test
286    public void testKilometre() throws FactoryException {
287        important  = true;
288        code       = 9036;
289        name       = "kilometre";
290        aliases    = NONE;
291        unitToBase = 1000.0;
292        baseUnit   = units.metre();
293        verifyLinearConversions(createConverter());
294    }
295
296    /**
297     * Tests “foot” unit creation from the factory.
298     *
299     * <ul>
300     *   <li>EPSG UoM code: <b>9002</b></li>
301     *   <li>Type: <b>Linear</b></li>
302     *   <li>Name of Units used in EPSG dataset: <b>foot</b></li>
303     *   <li>Base units per unit: <b>0.3048</b></li>
304     *   <li>Specific usage / Remarks: <b>US</b></li>
305     *   <li>Particularly important to E&amp;P industry.</li>
306     * </ul>
307     *
308     * @throws FactoryException if an error occurred while creating the unit from the EPSG code.
309     */
310    @Test
311    public void testFoot() throws FactoryException {
312        important  = true;
313        code       = 9002;
314        name       = "foot";
315        aliases    = NONE;
316        unitToBase = 0.3048;
317        baseUnit   = units.metre();
318        verifyLinearConversions(createConverter());
319    }
320
321    /**
322     * Tests “US survey foot” unit creation from the factory.
323     *
324     * <ul>
325     *   <li>EPSG UoM code: <b>9003</b></li>
326     *   <li>Type: <b>Linear</b></li>
327     *   <li>Name of Units used in EPSG dataset: <b>US survey foot</b></li>
328     *   <li>Base units per unit: <b>0.30480060960121924</b></li>
329     *   <li>Specific usage / Remarks: <b>US</b></li>
330     *   <li>Particularly important to E&amp;P industry.</li>
331     * </ul>
332     *
333     * @throws FactoryException if an error occurred while creating the unit from the EPSG code.
334     */
335    @Test
336    public void testUSSurveyFoot() throws FactoryException {
337        important  = true;
338        code       = 9003;
339        name       = "US survey foot";
340        aliases    = NONE;
341        unitToBase = 0.30480060960121924;
342        baseUnit   = units.metre();
343        verifyLinearConversions(createConverter());
344    }
345
346    /**
347     * Tests “German legal metre” unit creation from the factory.
348     *
349     * <ul>
350     *   <li>EPSG UoM code: <b>9031</b></li>
351     *   <li>Type: <b>Linear</b></li>
352     *   <li>Name of Units used in EPSG dataset: <b>German legal metre</b></li>
353     *   <li>Base units per unit: <b>1.0000135965</b></li>
354     *   <li>Specific usage / Remarks: <b>Namibia</b></li>
355     *   <li>Particularly important to E&amp;P industry.</li>
356     * </ul>
357     *
358     * @throws FactoryException if an error occurred while creating the unit from the EPSG code.
359     */
360    @Test
361    public void testGermanLegalMetre() throws FactoryException {
362        important  = true;
363        code       = 9031;
364        name       = "German legal metre";
365        aliases    = NONE;
366        unitToBase = 1.0000135965;
367        baseUnit   = units.metre();
368        verifyLinearConversions(createConverter());
369    }
370
371    /**
372     * Tests “Clarke's foot” unit creation from the factory.
373     *
374     * <ul>
375     *   <li>EPSG UoM code: <b>9005</b></li>
376     *   <li>Type: <b>Linear</b></li>
377     *   <li>Name of Units used in EPSG dataset: <b>Clarke's foot</b></li>
378     *   <li>Base units per unit: <b>0.3047972654</b></li>
379     *   <li>Specific usage / Remarks: <b>Trinidad</b></li>
380     *   <li>Particularly important to E&amp;P industry.</li>
381     * </ul>
382     *
383     * @throws FactoryException if an error occurred while creating the unit from the EPSG code.
384     */
385    @Test
386    public void testClarkeFoot() throws FactoryException {
387        important  = true;
388        code       = 9005;
389        name       = "Clarke's foot";
390        aliases    = NONE;
391        unitToBase = 0.3047972654;
392        baseUnit   = units.metre();
393        verifyLinearConversions(createConverter());
394    }
395
396    /**
397     * Tests “Clarke's link” unit creation from the factory.
398     *
399     * <ul>
400     *   <li>EPSG UoM code: <b>9039</b></li>
401     *   <li>Type: <b>Linear</b></li>
402     *   <li>Name of Units used in EPSG dataset: <b>Clarke's link</b></li>
403     *   <li>Base units per unit: <b>0.201166195164</b></li>
404     *   <li>Specific usage / Remarks: <b>Trinidad</b></li>
405     *   <li>Particularly important to E&amp;P industry.</li>
406     * </ul>
407     *
408     * @throws FactoryException if an error occurred while creating the unit from the EPSG code.
409     */
410    @Test
411    public void testClarkeLink() throws FactoryException {
412        important  = true;
413        code       = 9039;
414        name       = "Clarke's link";
415        aliases    = NONE;
416        unitToBase = 0.201166195164;
417        baseUnit   = units.metre();
418        verifyLinearConversions(createConverter());
419    }
420
421    /**
422     * Tests “British chain (Sears 1922)” unit creation from the factory.
423     *
424     * <ul>
425     *   <li>EPSG UoM code: <b>9042</b></li>
426     *   <li>Type: <b>Linear</b></li>
427     *   <li>Name of Units used in EPSG dataset: <b>British chain (Sears 1922)</b></li>
428     *   <li>Base units per unit: <b>20.116765121552632</b></li>
429     *   <li>Specific usage / Remarks: <b>Brunei Malaysia</b></li>
430     *   <li>Particularly important to E&amp;P industry.</li>
431     * </ul>
432     *
433     * @throws FactoryException if an error occurred while creating the unit from the EPSG code.
434     *
435     * @see #testBritishChainTruncated()
436     */
437    @Test
438    public void testBritishChain() throws FactoryException {
439        important  = true;
440        code       = 9042;
441        name       = "British chain (Sears 1922)";
442        aliases    = NONE;
443        unitToBase = 20.116765121552632;
444        baseUnit   = units.metre();
445        verifyLinearConversions(createConverter());
446    }
447
448    /**
449     * Tests “British foot (Sears 1922)” unit creation from the factory.
450     *
451     * <ul>
452     *   <li>EPSG UoM code: <b>9051</b></li>
453     *   <li>Type: <b>Linear</b></li>
454     *   <li>Name of Units used in EPSG dataset: <b>British foot (Sears 1922)</b></li>
455     *   <li>Base units per unit: <b>0.3047997333333333</b></li>
456     *   <li>Specific usage / Remarks: <b>Brunei Malaysia</b></li>
457     *   <li>Particularly important to E&amp;P industry.</li>
458     * </ul>
459     *
460     * @throws FactoryException if an error occurred while creating the unit from the EPSG code.
461     */
462    @Test
463    public void testBritishFoot() throws FactoryException {
464        important  = true;
465        code       = 9051;
466        name       = "British foot (Sears 1922)";
467        aliases    = NONE;
468        unitToBase = 0.3047997333333333;
469        baseUnit   = units.metre();
470        verifyLinearConversions(createConverter());
471    }
472
473    /**
474     * Tests “British yard (Sears 1922)” unit creation from the factory.
475     *
476     * <ul>
477     *   <li>EPSG UoM code: <b>9040</b></li>
478     *   <li>Type: <b>Linear</b></li>
479     *   <li>Name of Units used in EPSG dataset: <b>British yard (Sears 1922)</b></li>
480     *   <li>Base units per unit: <b>0.9143984146160287</b></li>
481     *   <li>Specific usage / Remarks: <b>New Zealand</b></li>
482     *   <li>Particularly important to E&amp;P industry.</li>
483     * </ul>
484     *
485     * @throws FactoryException if an error occurred while creating the unit from the EPSG code.
486     */
487    @Test
488    public void testBritishYard() throws FactoryException {
489        important  = true;
490        code       = 9040;
491        name       = "British yard (Sears 1922)";
492        aliases    = NONE;
493        unitToBase = 0.9143984146160287;
494        baseUnit   = units.metre();
495        verifyLinearConversions(createConverter());
496    }
497
498    /**
499     * Tests “British chain (Sears 1922 truncated)” unit creation from the factory.
500     *
501     * <ul>
502     *   <li>EPSG UoM code: <b>9301</b></li>
503     *   <li>Type: <b>Linear</b></li>
504     *   <li>Name of Units used in EPSG dataset: <b>British chain (Sears 1922 truncated)</b></li>
505     *   <li>Base units per unit: <b>20.116756</b></li>
506     *   <li>Specific usage / Remarks: <b>Malaysia</b></li>
507     *   <li>Particularly important to E&amp;P industry.</li>
508     * </ul>
509     *
510     * @throws FactoryException if an error occurred while creating the unit from the EPSG code.
511     *
512     * @see #testBritishChain()
513     */
514    @Test
515    public void testBritishChainTruncated() throws FactoryException {
516        important  = true;
517        code       = 9301;
518        name       = "British chain (Sears 1922 truncated)";
519        aliases    = NONE;
520        unitToBase = 20.116756;
521        baseUnit   = units.metre();
522        verifyLinearConversions(createConverter());
523    }
524
525    /**
526     * Tests “Indian yard” unit creation from the factory.
527     *
528     * <ul>
529     *   <li>EPSG UoM code: <b>9084</b></li>
530     *   <li>Type: <b>Linear</b></li>
531     *   <li>Name of Units used in EPSG dataset: <b>Indian yard</b></li>
532     *   <li>Base units per unit: <b>0.9143985307444408</b></li>
533     *   <li>Specific usage / Remarks: <b>south Asia - historic</b></li>
534     * </ul>
535     *
536     * @throws FactoryException if an error occurred while creating the unit from the EPSG code.
537     */
538    @Test
539    public void testIndianYard() throws FactoryException {
540        code       = 9084;
541        name       = "Indian yard";
542        aliases    = NONE;
543        unitToBase = 0.9143985307444408;
544        baseUnit   = units.metre();
545        verifyLinearConversions(createConverter());
546    }
547
548    /**
549     * Tests “Gold Coast foot” unit creation from the factory.
550     *
551     * <ul>
552     *   <li>EPSG UoM code: <b>9094</b></li>
553     *   <li>Type: <b>Linear</b></li>
554     *   <li>Name of Units used in EPSG dataset: <b>Gold Coast foot</b></li>
555     *   <li>Base units per unit: <b>0.3047997101815088</b></li>
556     *   <li>Specific usage / Remarks: <b>Ghana</b></li>
557     * </ul>
558     *
559     * @throws FactoryException if an error occurred while creating the unit from the EPSG code.
560     */
561    @Test
562    public void testGoldCoastFoot() throws FactoryException {
563        code       = 9094;
564        name       = "Gold Coast foot";
565        aliases    = NONE;
566        unitToBase = 0.3047997101815088;
567        baseUnit   = units.metre();
568        verifyLinearConversions(createConverter());
569    }
570
571    /**
572     * Tests “link” unit creation from the factory.
573     *
574     * <ul>
575     *   <li>EPSG UoM code: <b>9098</b></li>
576     *   <li>Type: <b>Linear</b></li>
577     *   <li>Name of Units used in EPSG dataset: <b>link</b></li>
578     *   <li>Base units per unit: <b>0.201168</b></li>
579     *   <li>Specific usage / Remarks: <b>Fiji</b></li>
580     * </ul>
581     *
582     * @throws FactoryException if an error occurred while creating the unit from the EPSG code.
583     */
584    @Test
585    public void testLink() throws FactoryException {
586        code       = 9098;
587        name       = "link";
588        aliases    = NONE;
589        unitToBase = 0.201168;
590        baseUnit   = units.metre();
591        verifyLinearConversions(createConverter());
592    }
593
594    /**
595     * Tests “radian” unit creation from the factory.
596     *
597     * <ul>
598     *   <li>EPSG UoM code: <b>9101</b></li>
599     *   <li>Type: <b>Angle</b></li>
600     *   <li>Name of Units used in EPSG dataset: <b>radian</b></li>
601     *   <li>Base units per unit: <b>1.0</b></li>
602     *   <li>Specific usage / Remarks: <b>Some geocentric 7- and 10-parameter transformations for Colombia and US/Canada.</b></li>
603     *   <li>Particularly important to E&amp;P industry.</li>
604     * </ul>
605     *
606     * @throws FactoryException if an error occurred while creating the unit from the EPSG code.
607     */
608    @Test
609    public void testRadian() throws FactoryException {
610        important  = true;
611        code       = 9101;
612        name       = "radian";
613        aliases    = NONE;
614        unitToBase = 1.0;
615        baseUnit   = units.radian();
616        verifyLinearConversions(createConverter());
617    }
618
619    /**
620     * Tests “degree” unit creation from the factory.
621     *
622     * <ul>
623     *   <li>EPSG UoM code: <b>9102</b></li>
624     *   <li>Type: <b>Angle</b></li>
625     *   <li>Name of Units used in EPSG dataset: <b>degree</b></li>
626     *   <li>Base units per unit: <b>0.017453292519943278</b></li>
627     *   <li>Specific usage / Remarks: <b>Numerous</b></li>
628     *   <li>Particularly important to E&amp;P industry.</li>
629     * </ul>
630     *
631     * @throws FactoryException if an error occurred while creating the unit from the EPSG code.
632     */
633    @Test
634    public void testDegree() throws FactoryException {
635        important  = true;
636        code       = 9102;
637        name       = "degree";
638        aliases    = NONE;
639        unitToBase = 0.017453292519943278;
640        baseUnit   = units.radian();
641        verifyLinearConversions(createConverter());
642    }
643
644    /**
645     * Tests “arc-second” unit creation from the factory.
646     *
647     * <ul>
648     *   <li>EPSG UoM code: <b>9104</b></li>
649     *   <li>Type: <b>Angle</b></li>
650     *   <li>Name of Units used in EPSG dataset: <b>arc-second</b></li>
651     *   <li>Base units per unit: <b>4.848136811095355E-6</b></li>
652     *   <li>Specific usage / Remarks: <b>Numerous</b></li>
653     *   <li>Particularly important to E&amp;P industry.</li>
654     * </ul>
655     *
656     * @throws FactoryException if an error occurred while creating the unit from the EPSG code.
657     */
658    @Test
659    public void testArcSecond() throws FactoryException {
660        important  = true;
661        code       = 9104;
662        name       = "arc-second";
663        aliases    = NONE;
664        unitToBase = 4.848136811095355E-6;
665        baseUnit   = units.radian();
666        verifyLinearConversions(createConverter());
667    }
668
669    /**
670     * Tests “grad” unit creation from the factory.
671     *
672     * <ul>
673     *   <li>EPSG UoM code: <b>9105</b></li>
674     *   <li>Type: <b>Angle</b></li>
675     *   <li>Name of Units used in EPSG dataset: <b>grad</b></li>
676     *   <li>Base units per unit: <b>0.01570796326794895</b></li>
677     *   <li>Specific usage / Remarks: <b>France</b></li>
678     *   <li>Particularly important to E&amp;P industry.</li>
679     * </ul>
680     *
681     * @throws FactoryException if an error occurred while creating the unit from the EPSG code.
682     */
683    @Test
684    public void testGrad() throws FactoryException {
685        important  = true;
686        code       = 9105;
687        name       = "grad";
688        aliases    = NONE;
689        unitToBase = 0.01570796326794895;
690        baseUnit   = units.radian();
691        verifyLinearConversions(createConverter());
692    }
693
694    /**
695     * Tests “microradian” unit creation from the factory.
696     *
697     * <ul>
698     *   <li>EPSG UoM code: <b>9109</b></li>
699     *   <li>Type: <b>Angle</b></li>
700     *   <li>Name of Units used in EPSG dataset: <b>microradian</b></li>
701     *   <li>Base units per unit: <b>1E-6</b></li>
702     *   <li>Specific usage / Remarks: <b>Some 7- and 10-parameter transformations for Netherlands and Norway.</b></li>
703     *   <li>Particularly important to E&amp;P industry.</li>
704     * </ul>
705     *
706     * @throws FactoryException if an error occurred while creating the unit from the EPSG code.
707     */
708    @Test
709    public void testMicroRadian() throws FactoryException {
710        important  = true;
711        code       = 9109;
712        name       = "microradian";
713        aliases    = NONE;
714        unitToBase = 1E-6;
715        baseUnit   = units.radian();
716        verifyLinearConversions(createConverter());
717    }
718
719    /**
720     * Tests “sexagesimal DMS” unit creation from the factory.
721     *
722     * <ul>
723     *   <li>EPSG UoM code: <b>9110</b></li>
724     *   <li>Type: <b>Angle</b></li>
725     *   <li>Name of Units used in EPSG dataset: <b>sexagesimal DMS</b></li>
726     *   <li>Base units per unit: <b>not a constant</b></li>
727     *   <li>Specific usage / Remarks: <b>Special EPSG construct for storing sexagesimal degree values as a single real number.</b>
728     *       Applications do not necessarily have to adopt this approach but should somehow exactly honour sexagesimal value.
729     *       Sexagesimal degree (123º45'67.8"[H]) should be used for display at human interface.</li>
730     *   <li>Particularly important to E&amp;P industry.</li>
731     * </ul>
732     *
733     * @throws FactoryException if an error occurred while creating the unit from the EPSG code.
734     */
735    @Test
736    public void testSexagesimalDegree() throws FactoryException {
737        important  = true;
738        code       = 9110;
739        name       = "sexagesimal DMS";
740        aliases    = NONE;
741        unitToBase = Double.NaN;
742        baseUnit   = units.degree();
743        final UnitConverter converter = createConverter();
744        final double tolerance = 10*TOLERANCE;
745        assertEquals(name,  10.00, converter.convert( 10.0000), tolerance);
746        assertEquals(name, -10.00, converter.convert(-10.0000), tolerance);
747        assertEquals(name,  20.01, converter.convert( 20.0036), tolerance);
748        assertEquals(name, -20.01, converter.convert(-20.0036), tolerance);
749        assertEquals(name,  30.50, converter.convert( 30.3000), tolerance);
750        assertEquals(name, -30.50, converter.convert(-30.3000), tolerance);
751        assertEquals(name,  40.99, converter.convert( 40.5924), tolerance);
752        assertEquals(name, -40.99, converter.convert(-40.5924), tolerance);
753    }
754
755    /**
756     * Tests “centesimal second” unit creation from the factory.
757     *
758     * <ul>
759     *   <li>EPSG UoM code: <b>9113</b></li>
760     *   <li>Type: <b>Angle</b></li>
761     *   <li>Name of Units used in EPSG dataset: <b>centesimal second</b></li>
762     *   <li>Base units per unit: <b>1.570796326794895E-6</b></li>
763     *   <li>Specific usage / Remarks: <b>Used in one geocentric 7-parameter transformation for Switzerland.</b></li>
764     * </ul>
765     *
766     * @throws FactoryException if an error occurred while creating the unit from the EPSG code.
767     */
768    @Test
769    public void testCentesimalSecond() throws FactoryException {
770        code       = 9113;
771        name       = "centesimal second";
772        aliases    = NONE;
773        unitToBase = 1.570796326794895E-6;
774        baseUnit   = units.radian();
775        verifyLinearConversions(createConverter());
776    }
777
778    /**
779     * Tests “unity” unit creation from the factory.
780     *
781     * <ul>
782     *   <li>EPSG UoM code: <b>9201</b></li>
783     *   <li>Type: <b>Scale</b></li>
784     *   <li>Name of Units used in EPSG dataset: <b>unity</b></li>
785     *   <li>Base units per unit: <b>1.0</b></li>
786     *   <li>Specific usage / Remarks: <b>Numerous</b></li>
787     *   <li>Particularly important to E&amp;P industry.</li>
788     * </ul>
789     *
790     * @throws FactoryException if an error occurred while creating the unit from the EPSG code.
791     */
792    @Test
793    public void testUnity() throws FactoryException {
794        important  = true;
795        code       = 9201;
796        name       = "unity";
797        aliases    = NONE;
798        unitToBase = 1.0;
799        baseUnit   = units.one();
800        verifyLinearConversions(createConverter());
801    }
802
803    /**
804     * Tests “parts per million” unit creation from the factory.
805     *
806     * <ul>
807     *   <li>EPSG UoM code: <b>9202</b></li>
808     *   <li>Type: <b>Scale</b></li>
809     *   <li>Name of Units used in EPSG dataset: <b>parts per million</b></li>
810     *   <li>Base units per unit: <b>1E-6</b></li>
811     *   <li>Specific usage / Remarks: <b>Numerous</b></li>
812     *   <li>Particularly important to E&amp;P industry.</li>
813     * </ul>
814     *
815     * @throws FactoryException if an error occurred while creating the unit from the EPSG code.
816     */
817    @Test
818    public void testPartsPerMillion() throws FactoryException {
819        important  = true;
820        code       = 9202;
821        name       = "parts per million";
822        aliases    = NONE;
823        unitToBase = 1E-6;
824        baseUnit   = units.one();
825        verifyLinearConversions(createConverter());
826    }
827
828    /**
829     * Tests “coefficient” unit creation from the factory.
830     *
831     * <ul>
832     *   <li>EPSG UoM code: <b>9203</b></li>
833     *   <li>Type: <b>Scale</b></li>
834     *   <li>Name of Units used in EPSG dataset: <b>coefficient</b></li>
835     *   <li>Base units per unit: <b>1.0</b></li>
836     *   <li>Specific usage / Remarks: <b>Numerous</b></li>
837     *   <li>Particularly important to E&amp;P industry.</li>
838     * </ul>
839     *
840     * @throws FactoryException if an error occurred while creating the unit from the EPSG code.
841     */
842    @Test
843    public void testCoefficient() throws FactoryException {
844        important  = true;
845        code       = 9203;
846        name       = "coefficient";
847        aliases    = NONE;
848        unitToBase = 1.0;
849        baseUnit   = units.one();
850        verifyLinearConversions(createConverter());
851    }
852}