(1)前言
公司使用了仿射变换来完成两个坐标系的转换。所有记录一下踩过的坑。
(2)什么是仿射变换
这个链接解释的很好:http://www.cnblogs.com/ghj1976/p/5199086.html
(3)Java mvn 配置
<dependency>
<groupId>com.vividsolutions</groupId>
<artifactId>jts</artifactId>
<version>1.13</version>
</dependency>
(4)java代码
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.geom.impl.PackedCoordinateSequence;
import com.vividsolutions.jts.geom.util.AffineTransformation;
import com.vividsolutions.jts.geom.util.AffineTransformationBuilder;
import com.vividsolutions.jts.geom.util.NoninvertibleTransformationException;
import com.wanda.map.data.domain.po.ImapAffinePointInfo;
import org.apache.commons.io.IOUtils;
import org.geojson.Feature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;
private static Coordinate createCoordinate(BigDecimal x, BigDecimal y) {
Coordinate coor = new Coordinate(x.doubleValue(), y.doubleValue());
return coor;
}
private static DecimalFormat createDecimalFormat(){
DecimalFormat decimalFormat = new DecimalFormat("##0.########");
return decimalFormat;
}
public static boolean affineTransTst(ImapAffinePointInfo imapAffinePointInfo) {
Coordinate s1 = createCoordinate(imapAffinePointInfo.getCoorM1X(), imapAffinePointInfo.getCoorM1Y());
Coordinate s2 = createCoordinate(imapAffinePointInfo.getCoorM2X(), imapAffinePointInfo.getCoorM2Y());
Coordinate s3 = createCoordinate(imapAffinePointInfo.getCoorM3X(), imapAffinePointInfo.getCoorM3Y());
Coordinate t1 = createCoordinate(imapAffinePointInfo.getCoorR1X(), imapAffinePointInfo.getCoorR1Y());
Coordinate t2 = createCoordinate(imapAffinePointInfo.getCoorR2X(), imapAffinePointInfo.getCoorR2Y());
Coordinate t3 = createCoordinate(imapAffinePointInfo.getCoorR3X(), imapAffinePointInfo.getCoorR3Y());
// 建立仿射变换对象
AffineTransformationBuilder afb = new AffineTransformationBuilder(s1, s2, s3, t1, t2, t3);
AffineTransformation atf = afb.getTransformation();
double[] ddd = atf.getMatrixEntries();
StringBuilder stringBuilder = new StringBuilder();
for (double d : ddd) {
stringBuilder.append(createDecimalFormat().format(d)).append(" ");
}
imapAffinePointInfo.setMtrFormulaPara(stringBuilder.toString());
DecimalFormat decimalFormat = createDecimalFormat();
List<Feature> featureList = new ArrayList<>();
try {
AffineTransformation atf2 = atf.getInverse();
List<AffineModle> affineModleList = parseFile(filePath);
int id = 1;
for (AffineModle affineModle : affineModleList) {
double[] dd = new double[2];
dd[0] = affineModle.getX();
dd[1] = affineModle.getY();
Point pointReuslt = new Point(new PackedCoordinateSequence.Double(dd,2), new GeometryFactory());
// System.out.println("相对坐标 : " +pointReuslt.getX() + " "+ pointReuslt.getY());
pointReuslt.apply(atf2);
// System.out.println("墨卡托坐标: " + pointReuslt.getX() + " "+ pointReuslt.getY());
affineModle.setFormatX(decimalFormat.format(pointReuslt.getX()));
affineModle.setFormatY(decimalFormat.format(pointReuslt.getY()));
Date date = new Date(Long.parseLong(affineModle.getTime()+"000"));
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
GeoMercatorUtil.Point p = GeoMercatorUtil.mercator2lonLat(affineModle.getFormatX(), affineModle.getFormatY());
affineModle.setFormatX(p.getXStr());
affineModle.setFormatY(p.getYStr());
//
System.out.println(affineModle.getPlaza() + "," + affineModle.getFormatX() + "," + affineModle.getFormatY()
+ "," + affineModle.getFloor()+ "," + sdf.format(date));
Feature f = new Feature();
Map<String, Object> props = new HashMap<>();
props.put("x", affineModle.getFormatX());
props.put("y", affineModle.getFormatY());
props.put("time", affineModle.getTime());
props.put("floor", affineModle.getFloor());
props.put("plaza", affineModle.getPlaza());
props.put("id", id);
id ++;
f.setProperties(props);
org.geojson.Point pp = new org.geojson.Point(Double.parseDouble(affineModle.getFormatX()),
Double.parseDouble(affineModle.getFormatY()));
f.setGeometry(pp);
featureList.add(f);
}
JsonModle jsonModle = new JsonModle();
jsonModle.setFeatures(featureList);
jsonModle.setName("user_lbs_track");
jsonModle.setType("FeatureCollection");
ObjectMapper objectMapper = new ObjectMapper();
String sss = null;
try {
sss = objectMapper.writeValueAsString(jsonModle);
try {
IOUtils.write(sss, new FileOutputStream(new File(filePatha)), "UTF-8");
} catch (IOException e) {
e.printStackTrace();
}
} catch (JsonProcessingException e) {
e.printStackTrace();
}
/* String sss =JSON.toJSONString(jsonModle); */
} catch (NoninvertibleTransformationException e) {
logger.error("affine变换错误." + e.getMessage(), e);
return false;
}
return true;
}
ImapAffinePointInfo类,就是简单的POJO对象, 使用了BigDecimal对象表示坐标值x和y。