В нашем текущем проекте мы используем установку maven для управления зависимостями и запуска модульных тестов. В какой-то момент разработки один из наших тестов перестал работать (мы не уверены, в какой именно момент, поэтому не знаем, что именно изменилось). Конкретная ошибка - это преобразование из декартовых координат в географические с использованием геоинструментов (пробовали 9 и 9.1). Самое интересное, что тот же тест отлично работает в eclipse. Мы много работали над анализом проблемы и создали минимальный пример, который показывает поведение, которое мы видим, где мы (разумно) уверены, что это не проблема пути к классам.
Пример
пом.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 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".
Если мы запустим тест JUnit из eclipse, это отлично работает. Любые идеи, почему это происходит или как мы можем этого избежать?
В качестве примечания: следующие три строки являются обходным путем для устаревшего метода factory.createProjectedCRS(properties, geoCRS, null, parameters, cartCS), если у кого-то есть лучшее решение, будьте моим гостем :)
CRSFactory crsFactory = factories.getCRSFactory();
DefiningConversion conv = new DefiningConversion("test", parameters);
projCRS = crsFactory.createProjectedCRS(properties, geoCRS, conv, cartCS);