在我们当前的项目中,我们使用maven设置来管理依赖项并运行单元测试。在开发的某个阶段,我们的一个测试停止了工作(我们不确定究竟是什么时候,所以我们不知道到底发生了什么变化)。失败的具体事情是使用geotools从笛卡尔到地理坐标的转换(尝试了9和9.1)。多汁的部分是相同的测试在日食中工作正常。我们非常努力地分析问题,并创建了一个最小的示例,显示了我们所看到的行为(合理地)确定它不是类路径问题。
的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]);
}
}
如果我们对此调用'mvn test',我们会得到以下异常:
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测试,这非常有效。任何想法为什么会发生这种情况或我们如何避免它?
作为旁注:以下三行是已弃用的factories.createProjectedCRS(属性,geoCRS,null,参数,cartCS)方法的解决方法,如果有人有更好的解决方案是我的客人:)
CRSFactory crsFactory = factories.getCRSFactory();
DefiningConversion conv = new DefiningConversion("test", parameters);
projCRS = crsFactory.createProjectedCRS(properties, geoCRS, conv, cartCS);
答案 0 :(得分:4)
正如Werner所说,问题可以通过在surefire测试运行期间禁用断言来解决。如果要在其余代码中启用断言,则只能通过修改POM来禁用MapProjection
类中的断言:
<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);
即使转换点距离UTM区域的中央子午线3度以内(并且实际转换误差可以忽略不计),也会发生此错误,原因是geotools估计其准确性的方式存在错误(https://osgeo-org.atlassian.net/browse/GEOT-4207 )。这个错误与OP的情况无关,因为这里的点远离UTM区域(距离中央子午线大约40度),转换误差(大约10公里)不可忽略(对于某些应用) )。
答案 1 :(得分:2)
我有同样的问题,可以通过在surefire测试运行期间禁用断言来解决它。 您需要将以下行添加到您的pom:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<enableAssertions>false</enableAssertions>
</configuration>
</plugin>