4

在我们当前的项目中,我们使用 Maven 设置来管理依赖项并运行单元测试。在开发的某个时刻,我们的一项测试停止工作(我们不确定究竟是在什么时候,所以我们不知道到底发生了什么变化)。失败的具体事情是使用 geotools(9 和 9.1 尝试过)从笛卡尔坐标到地理坐标的转换。有趣的是,同样的测试在 eclipse 中也能正常工作。我们在分析问题上投入了大量精力,并创建了一个最小示例来显示我们看到的行为,我们(合理地)确定它不是类路径问题。

这个例子

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>

测试者.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]);
    }
}

如果我们对此调用“mvn 测试”,我们会得到以下异常:

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".

如果我们从 Eclipse 运行 JUnit 测试,这将完美运行。任何想法为什么会发生这种情况或我们如何避免它?


作为旁注:以下三行是已弃用的 factory.createProjectedCRS(properties, geoCRS, null, parameters, cartCS) 方法的解决方法,如果有人有更好的解决方案,请作为我的客人:)

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

2 回答 2

4

正如 Werner 所说,可以通过在万无一失的测试运行期间禁用断言来解决问题。如果要在其余代码中保持启用断言,则只能MapProjection通过修改 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>

或在 Java 中:

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

由于 geotools 估计其准确性的方式存在错误(https://osgeo-org. atlassian.net/browse/GEOT-4207)。该错误与 OP 的情况无关,因为这里的点远离 UTM 区域(距中央子午线约 40 度),并且转换误差(约 10 公里)不可忽略(对于某些应用程序)。

于 2015-02-07T20:06:36.077 回答
2

我有同样的问题,可以通过在万无一失的测试运行期间禁用断言来解决它。您需要将以下行添加到您的 pom 中:

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <configuration>
                <enableAssertions>false</enableAssertions>
            </configuration>
        </plugin>
于 2013-08-27T08:35:55.320 回答