本文整理了一些地理坐标系之间的转换(Java代码)
<dependency>
<groupId>com.vividsolutions</groupId>
<artifactId>jts</artifactId>
<version>1.13</version>
</dependency>
<dependency>
<groupId>org.osgeo</groupId>
<artifactId>proj4j</artifactId>
<version>0.1.0</version>
</dependency>
package com.mytest.algorithm.geometry;
import com.mytest.algorithm.model.Pixel;
import com.mytest.algorithm.model.Tile;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Envelope;
import org.osgeo.proj4j.BasicCoordinateTransform;
import org.osgeo.proj4j.CRSFactory;
import org.osgeo.proj4j.CoordinateReferenceSystem;
import org.osgeo.proj4j.ProjCoordinate;
/*************************************
*Class Name:GeoTransform
*Description:<坐标转换工具类>
*@since 1.0.0
*************************************/
public class GeoTransform {
/**
* 赤道半径
*/
private final static double EarthRadius = 6378137.0;
/**
* 地球周长
*/
private final static double EarthPerimeter = 2 * Math.PI * EarthRadius;
/**
* 瓦片大小,默认256
*/
private final static int tileSize = 256;
/**
* 初始像素分辨率.
*/
private final static double initialResolution = EarthPerimeter / tileSize;
/**
* 坐标原点
*/
private final static Coordinate origin = new Coordinate(-EarthPerimeter / 2.0, EarthPerimeter / 2.0);
private final static BasicCoordinateTransform transform1;
private final static BasicCoordinateTransform transform2;
private final static CRSFactory crsFactory = new CRSFactory();
private final static CoordinateReferenceSystem WGS84CRS = crsFactory.createFromName("EPSG:4326");
private final static CoordinateReferenceSystem WebMercatorCRS = crsFactory.createFromName("EPSG:3857");
static {
transform1 = new BasicCoordinateTransform(WGS84CRS, WebMercatorCRS);
transform2 = new BasicCoordinateTransform(WebMercatorCRS, WGS84CRS);
}
/**
* 缩放级别换算地图分辨率
*
* @param zoom 级别
*/
public double zoomToResolution(int zoom) {
return initialResolution / Math.pow(2, zoom);
}
/**
* 经纬度转墨卡托
*
* @param pt 经纬度坐标
* @return 墨卡托坐标
*/
public Coordinate geographic2Mercator(Coordinate pt) {
synchronized (transform1) {
ProjCoordinate pt1 = new ProjCoordinate(pt.x, pt.y);
ProjCoordinate pt2 = new ProjCoordinate();
transform1.transform(pt1, pt2);
return new Coordinate(pt2.x, pt2.y);
}
}
/**
* 墨卡托转经纬度
*
* @param pt 墨卡托坐标
* @return 经纬度坐标
*/
public Coordinate mercator2Geographic(Coordinate pt) {
synchronized (transform2) {
ProjCoordinate pt1 = new ProjCoordinate(pt.x, pt.y);
ProjCoordinate pt2 = new ProjCoordinate();
transform2.transform(pt1, pt2);
return new Coordinate(pt2.x, pt2.y);
}
}
/**
* 高斯转经纬度
*
* @param pt 高斯坐标
* @param d 度带号(3度带)
* @return 经纬度坐标
*/
public Coordinate gk2Geographic(Coordinate pt, int d) {
synchronized (crsFactory) {
CoordinateReferenceSystem GKCRS = crsFactory.createFromParameters("WGS84", String.format("+proj=tmerc +lat_0=0 +lon_0=%d +k=1 +x_0=500000 +y_0=0 +ellps=WGS84 +units=m +no_defs", d * 3));
BasicCoordinateTransform transform = new BasicCoordinateTransform(GKCRS, WGS84CRS);
ProjCoordinate pt1 = new ProjCoordinate(pt.x, pt.y);
ProjCoordinate pt2 = new ProjCoordinate();
transform.transform(pt1, pt2);
return new Coordinate(pt2.x, pt2.y);
}
}
/**
* 经纬度转高斯
*
* @param pt 经纬度坐标
* @return 高斯坐标
*/
public Coordinate geographic2GK(Coordinate pt) {
synchronized (crsFactory) {
int d = (int) Math.floor((pt.y + 1.5) / 3);
CoordinateReferenceSystem GKCRS = crsFactory.createFromParameters("WGS84", String.format("+proj=tmerc +lat_0=0 +lon_0=%d +k=1 +x_0=500000 +y_0=0 +ellps=WGS84 +units=m +no_defs", d * 3));
BasicCoordinateTransform transform = new BasicCoordinateTransform(WGS84CRS, GKCRS);
ProjCoordinate pt1 = new ProjCoordinate(pt.x, pt.y);
ProjCoordinate pt2 = new ProjCoordinate();
transform.transform(pt1, pt2);
return new Coordinate(pt2.x, pt2.y);
}
}
/**
* 高斯转web墨卡托
*
* @param pt 高斯坐标
* @param d 度带好(3度带)
* @return 墨卡托坐标
*/
public Coordinate gk2Mercator(Coordinate pt, int d) {
synchronized (crsFactory) {
CoordinateReferenceSystem GKCRS = crsFactory.createFromParameters("WGS84", String.format("+proj=tmerc +lat_0=0 +lon_0=%d +k=1 +x_0=500000 +y_0=0 +ellps=WGS84 +units=m +no_defs", d * 3));
BasicCoordinateTransform transform = new BasicCoordinateTransform(GKCRS, WebMercatorCRS);
ProjCoordinate pt1 = new ProjCoordinate(pt.x, pt.y);
ProjCoordinate pt2 = new ProjCoordinate();
transform.transform(pt1, pt2);
return new Coordinate(pt2.x, pt2.y);
}
}
/**
* 墨卡托转像素
*
* @param pt 墨卡托坐标
* @param zoom 缩放级别
* @return 像素坐标
*/
public Pixel mercator2Pixel(Coordinate pt, int zoom) {
double res = zoomToResolution(zoom);
Double px = (pt.x - origin.x) / res;
Double py = -(pt.y - origin.y) / res;
//System.out.println(px+","+py);
//fixme 精度向下取整
return new Pixel((long) Math.floor(px), (long) Math.floor(py));
}
/**
* 像素转墨卡托
*
* @param pixel 像素坐标
* @param zoom 缩放级别
* @return 墨卡托坐标
*/
public Coordinate pixel2Mercator(Pixel pixel, int zoom) {
double res = zoomToResolution(zoom);
double x = pixel.getX() * res + origin.x;
double y = origin.y - pixel.getY() * res;
return new Coordinate(x, y);
}
/**
* 像素坐标所在瓦片
*
* @param pixel 像素坐标
* @return 瓦片坐标
*/
public Tile pixelAtTile(Pixel pixel) {
long tileX = pixel.getX() / tileSize;
long tileY = pixel.getY() / tileSize;
return new Tile(tileX, tileY);
}
/**
* 像素转瓦片内像素
*
* @param pixel 像素坐标
* @param tile 瓦片坐标
* @return 瓦片内像素坐标
*/
public Pixel pixel2Tile(Pixel pixel, Tile tile) {
long pX = pixel.getX() - tile.getX() * tileSize;
long pY = pixel.getY() - tile.getY() * tileSize;
return new Pixel(pX, pY);
}
/**
* 瓦片内像素转像素
*
* @param p 瓦片内像素坐标
* @param tile 瓦片坐标
* @return 像素坐标
*/
public Pixel tile2Pixel(Pixel p, Tile tile) {
long pixelX = p.getX() + tile.getX() * tileSize;
long pixelY = p.getY() + tile.getY() * tileSize;
return new Pixel(pixelX, pixelY);
}
/**
* 墨卡托转瓦片内像素
*
* @param pt 墨卡托坐标
* @param tile 瓦片坐标
* @param zoom 缩放级别
* @return 瓦片内像素坐标
*/
public Pixel mercator2Tile(Coordinate pt, Tile tile, int zoom) {
Pixel p = mercator2Pixel(pt, zoom);
Pixel pixel = pixel2Tile(p, tile);
return pixel;
}
/**
* 经纬度转像素
*
* @param pt 经纬度坐标
* @param zoom 缩放级别
* @return 像素坐标
*/
public Pixel geographic2Pixel(Coordinate pt, int zoom) {
Coordinate mpt = geographic2Mercator(pt);
Pixel pixel = mercator2Pixel(mpt, zoom);
return pixel;
}
/**
* 经纬度转瓦片内像素
*
* @param pt 经纬度坐标
* @param tile 瓦片坐标
* @param zoom 缩放级别
* @return 瓦片内像素坐标
*/
public Pixel geographic2Tile(Coordinate pt, Tile tile, int zoom) {
Pixel pixel = geographic2Pixel(pt, zoom);
Pixel p = this.pixel2Tile(pixel, tile);
return p;
}
/**
* 像素转经纬度
*
* @param pixel 像素坐标
* @param zoom 缩放级别
* @return 经纬度坐标
*/
public Coordinate pixel2Geographic(Pixel pixel, int zoom) {
Coordinate mpt = pixel2Mercator(pixel, zoom);
Coordinate lonlat = this.mercator2Geographic(mpt);
return lonlat;
}
/**
* Tile坐标转换为所在的Tile的矩形
*
* @param tile 瓦片坐标
* @return 矩形
*/
public Envelope tile2Envelope(Tile tile) {
long px = tile.getX() * tileSize;
long py = tile.getY() * tileSize;
Pixel pixel1 = new Pixel(px, py + 256);//左下
Pixel pixel2 = new Pixel(px + 256, py);//右上
Coordinate sw = pixel2Geographic(pixel1, tile.getZ());
Coordinate ne = pixel2Geographic(pixel2, tile.getZ());
return new Envelope(sw, ne);
}
/**
* 瓦片坐标转换为QuadKey四叉树键值
*
* @param tile 瓦片坐标
* @return String QuadKey四叉树键值
*/
public String tile2QuadKey(Tile tile) {
long tileX = tile.getX();
long tileY = tile.getY();
StringBuilder quadKey = new StringBuilder();
for (int i = tile.getZ(); i > 0; i--) {
char digit = '0';
int mask = 1 << (i - 1);
if ((tileX & mask) != 0) {
digit++;
}
if ((tileY & mask) != 0) {
digit++;
digit++;
}
quadKey.append(digit);
}
return quadKey.toString();
}
/**
* QuadKey四叉树键值转换为瓦片坐标
*
* @param quadKey QuadKey四叉树键值
* @return 瓦片坐标
*/
public Tile quadKey2Tile(String quadKey) {
long tileX = 0;
long tileY = 0;
int levelOfDetail = quadKey.length();
for (int i = levelOfDetail; i > 0; i--) {
int mask = 1 << (i - 1);
switch (quadKey.charAt(levelOfDetail - i)) {
case '0':
break;
case '1':
tileX |= mask;
break;
case '2':
tileY |= mask;
break;
case '3':
tileX |= mask;
tileY |= mask;
break;
//default:throw new ArgumentException("Invalid QuadKey digit sequence.");
}
}
return new Tile(tileX, tileY, levelOfDetail);
}
}
import lombok.Data;
/**
*
* 屏幕像素坐标类,该类为基础类(单位:像素)。
* 像素坐标系(Pixel Coordinates)单位。
* 以左上角为原点(0,0),向右向下为正方向。
* @version 1.0
* @author
*/
@Data
public class Pixel {
/**
* 横向像素
*/
long x;
/**
* 纵向像素
*/
long y;
/**
* 根据给定参数构造Pixel的新实例
* @param x 横向像素
* @param y 纵向像素
*/
public Pixel(long x, long y){
this.x=x;
this.y=y;
}
}
import lombok.Getter;
import lombok.Setter;
/**
*
* 瓦片类,该类为基础类(单位:块)。
* 地图瓦片坐标系(Tile Coordinates)单位。
* 瓦片坐标系以左上角为原点(0, 0),到右下角(2 ^ 图像级别 - 1, 2 ^ 图像级别 - 1)为止。
* @version 1.0
* @author
*/
@Getter
@Setter
public class Tile{
/**
* 横向瓦片数
*/
long x;
/**
* 纵向瓦片数
*/
long y;
/**
* 级别
*/
int z;
public Tile(){
}
/**
* 根据给定参数构造Tile的新实例
* @param x 横向瓦片数
* @param y 纵向瓦片数
*/
public Tile(long x, long y){
this.x=x;
this.y=y;
}
/**
* 根据给定参数构造Tile的新实例
* @param x 横向瓦片数
* @param y 纵向瓦片数
* @param z 级别
*/
public Tile(long x, long y, int z){
this.x=x;
this.y=y;
this.z=z;
}
@Override
public String toString(){
return "Tile("+x+","+y+","+z+")";
}
}
over!
文章浏览阅读6.6k次。1. kernel config<M>USB Gadget precomposed configurations<M>Ethernet Gadget (with CDC Ethernet support) <M>Network Control Model (NCM) support2. build modulesmake ARCH=arm64 CROSS_COMPILE=aar..._linux usb ncm
文章浏览阅读1.9k次。 翻译:SpringSide团队 转载请注明出处。有很多人都很熟悉 Struts, 无论是从项目中直接获得的实战经验还是从书中了解到的。我们这一系列文章,将通过一个由 Stuts 转移到 Struts2 简单的例子向大家展现Struts2的所有特征。 在我们开始这个例子之前,你需要去知道一点 Struts2的背景知识。 在第一部分的文章中,我们将介绍Struts2与Struts的核心
文章浏览阅读94次。需要源码可以滴滴我。
文章浏览阅读188次。打开MRTG软件包中的"MRTG.cfg"文件,该文件是MRTG的主配置文件。打开MRTG软件包中的"MRTG.cfg"文件,该文件是MRTG的主配置文件。确保将命令中的"C:\MRTG"替换为你的MRTG安装目录和配置文件路径,"community"替换为你的SNMP团体字符串,"device_ip"替换为目标设备的IP地址。确保将命令中的"C:\MRTG"替换为你的MRTG安装目录和配置文件路径,"community"替换为你的SNMP团体字符串,"device_ip"替换为目标设备的IP地址。_mrtg 下载
文章浏览阅读1w次,点赞7次,收藏35次。Kaggle机器学习竞赛、托管数据库、编写和分享代码_kaggle在线写代码
文章浏览阅读3.1k次,点赞11次,收藏14次。CentOS7突然连接不了网络,使用systemctl status network后报如下错误network.service - LSB: Bring up/down networkingLoaded: loaded (/etc/rc.d/init.d/network; bad; vendor preset: disabled)Active: failed (Result: exit-code)【解决方案】停止NetworkManager并取消开机启动chkconfig NetworkMan_network.service - lsb: bring up/down networking loaded: loaded (/etc/rc.d/in
文章浏览阅读1.7k次。目标在本章中,我们将学习:寻找图像梯度、边缘等 我们将看到以下职能:cv2.sobel(), cv2.scharr(), cv2.Laplacian()等理论OpenCV提供三种类型的梯度滤波器或高通滤波器,Sobel、Scharr和Laplacian.我们会看到他们中的每一个。1.Sobel和Scharr衍生物¶Sobel算子是一种联合高斯平滑加微分运算,具有更强的..._opencv 计算梯度图像
文章浏览阅读2.6k次。网上找了找 零零碎碎有一些文章 没找到一个整体的 自己做完记录一下 防止忘了大体就是这样聊天气泡用的是https://blog.csdn.net/oterminator12/article/details/105790961这个文章看到的然后表情用的是https://blog.csdn.net/qq_36676433/article/details/104756685这个文章看到的整体结构及底部输入/表情选择部分body下的结构主要为最外层Column,然后聊天部分用F..._flutter表情包插件
文章浏览阅读2.8k次,点赞3次,收藏2次。登录便签,一直报错:执行此操作需要Internet,0x800704cf。笔者网络是没有问题的,其它程序可以正常访问。解决方法关闭代理1.Win+R打开运行,输入 inetcpl.cpl 打开internet选项界面2.切换到[连接]选项,点击局域网设置。红色框选处的两个勾取消。笔者上述配置后即可解决问题。如若还不能解决,试试下面这个方法设置DNS服务器地址,首选设置为4.2.2.1 备用设置为4.2.2.2..._xbox0x800704cf错误代码
文章浏览阅读8.9w次,点赞55次,收藏138次。在服务器上想要使用别人搭好的环境,但是又怕自己对环境的修改更新会影响他人的使用,这个时候可以使用conda命令进行复制环境。首先假设已经安装了Anaconda。根据已有环境名复制生成新的环境假设已有环境名为A,需要生成的环境名为B:conda create -n B --clone A根据已有环境路径复制生成新的环境假设已有环境路径为D:\A,需要生成的新的环境名为B:conda ..._conda clone
文章浏览阅读3.1k次。在本文中,我们非常详细地描述如何使用 MySQL connector 来同步 MySQL 和 Elasticsearch 的索引。它使用起来非常方便。如果大家对 Logstash 很熟悉的话,请参阅我之前的文章 “Elastic:开发者上手指南” 中的 “数据库数据同步章节。我们还可以使用 Pipeline 对数据进行清洗。这个就不做展示了。_mysql connectors
文章浏览阅读1.5k次。HttpClientUtils工具类。_httpclientutils