문제

In our current project we use a maven setup to manage dependencies and run unit tests. At some point in development one of our tests stoped working (we are not sure at what point exactly, so we don't know what exactly changed). The specific thing failing is a transformation from cartesian to geographic coordinates using geotools (9 and 9.1 tried). The juicy part is that the same test works fine in eclipse. We heavily worked on analysing the problem and created a minimal example that shows the behavior we see where we are (reasonably) sure that it is not classpath problem.

The Example

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example.geotest</groupId>
    <artifactId>geotest</artifactId>
    <name>geotest</name>
    <version>1.0.0</version>
    <description></description>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <geotools.version>9.1</geotools.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.geotools</groupId>
            <artifactId>gt-main</artifactId>
            <version>${geotools.version}</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.0</version>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifest>
                            <mainClass>com.example.geotest.Geotest</mainClass>
                        </manifest>
                    </archive>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <repositories>
        <repository>
            <id>maven2-repository.dev.java.net</id>
            <name>Java.net repository</name>
            <url>http://download.java.net/maven/2</url>
        </repository>
        <repository>
            <id>osgeo</id>
            <name>Open Source Geospatial Foundation Repository</name>
            <url>http://download.osgeo.org/webdav/geotools/</url>
        </repository>
    </repositories>
</project>

Tester.java

package com.example.geotest;

import java.awt.geom.Point2D;
import java.util.Collections;
import java.util.Map;

import org.geotools.referencing.CRS;
import org.geotools.referencing.ReferencingFactoryFinder;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.geotools.referencing.cs.DefaultCartesianCS;
import org.geotools.referencing.factory.ReferencingFactoryContainer;
import org.geotools.referencing.operation.DefaultConversion;
import org.geotools.referencing.operation.DefiningConversion;
import org.junit.Test;
import org.opengis.parameter.ParameterValueGroup;
import org.opengis.referencing.crs.CRSFactory;
import org.opengis.referencing.crs.GeographicCRS;
import org.opengis.referencing.crs.ProjectedCRS;
import org.opengis.referencing.cs.CartesianCS;
import org.opengis.referencing.operation.Conversion;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.MathTransformFactory;
import org.opengis.referencing.operation.TransformException;

public class Tester {

    @Test
    public void testtesttest() throws Exception {

        // prepare actuall action
        final MathTransformFactory mtFactory = ReferencingFactoryFinder.getMathTransformFactory(null);
        final ReferencingFactoryContainer factories = new ReferencingFactoryContainer(null);
        final GeographicCRS geoCRS = DefaultGeographicCRS.WGS84;
        final CartesianCS cartCS = DefaultCartesianCS.GENERIC_2D;

        ProjectedCRS projCRS;
        MathTransform transformGeoToCrs;
        MathTransform transformCrsToGeo;


        ParameterValueGroup parameters = mtFactory.getDefaultParameters("Transverse_Mercator");
        parameters.parameter("central_meridian").setValue(9);
        parameters.parameter("latitude_of_origin").setValue(0.0);
        //0.9996 (a reduction of 1:2500); (40 cm/km)
        parameters.parameter("scale_factor").setValue(0.9996);
        //500 km for north hemisphere
        parameters.parameter("false_easting").setValue(500000.0);
        //10,0000 km for south hemisphere
        parameters.parameter("false_northing").setValue(0.0);

        Map<String, String> properties = Collections.singletonMap("name", "WGS 84 / UTM Zone 32");

        CRSFactory crsFactory = factories.getCRSFactory();
        DefiningConversion conv = new DefiningConversion("test", parameters);
        projCRS = crsFactory.createProjectedCRS(properties, geoCRS, conv, cartCS);
        transformGeoToCrs = CRS.findMathTransform(geoCRS, projCRS);
        transformCrsToGeo = CRS.findMathTransform(projCRS, geoCRS);

        // execute actual test
        double[] src = new double[] {5838597.0, 807147.75};
        double[] dest = new double[2];

        try {
            // this fails in maven
            transformCrsToGeo.transform(src, 0, dest, 0, 1);
        } catch (TransformException e) {
            throw new RuntimeException(e);
        }

        Point2D.Double geo = new Point2D.Double(dest[0], dest[1]);
    }
}

If we call a 'mvn test' on this we get the following exception:

Tests in error:
    testtesttest(com.example.geotest.Tester): org.geotools.referencing.operation.projection.ProjectionException: The transform result may be 9.478,277 meters away from the expected position. Are you sure that the input coordinates are inside this map projection area of validity? The point is located 43°20.6'E away from the central meridian and 5°19.1'N away from the latitude of origin. The projection is "Transverse_Mercator".

If we run the JUnit test from eclipse this works perfectly. Any ideas why this is happening or how we can avoid it?


As a side note: the following three lines are a workaround for the deprecated factories.createProjectedCRS(properties, geoCRS, null, parameters, cartCS) method, if anyone has a better solution be my guest :)

CRSFactory crsFactory = factories.getCRSFactory();
DefiningConversion conv = new DefiningConversion("test", parameters);
projCRS = crsFactory.createProjectedCRS(properties, geoCRS, conv, cartCS);
도움이 되었습니까?

해결책 2

I had the same problem and could solve it by disabling assertions during surefire test runs. You need to add the following lines to your pom:

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <configuration>
                <enableAssertions>false</enableAssertions>
            </configuration>
        </plugin>

다른 팁

As Werner said, the problem can be solved by disabling the assertion during surefire test run. If you want to keep assertions enabled in the rest of your code, you can only disable assertions in the MapProjection class either by modifying your POM:

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <configuration>
            <argLine>-da:org.geotools.referencing.operation.projection.MapProjection</argLine>
        </configuration>
    </plugin>

or in Java:

MapProjection.class.getClassLoader().setClassAssertionStatus(MapProjection.class.getName(), false);

This error can occur even if the transformed point is within 3 degrees from the central meridian of the UTM zone (and the actual transformation error is negligible) due to a bug in the way geotools estimates its accuracy ( https://osgeo-org.atlassian.net/browse/GEOT-4207 ). That bug is not relevant in the OP's case, as here the point is far out of the UTM zone (about 40 degrees from the central meridian) and the transformation error (about 10 kilometers) is not negligible (for some applications).

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top