- 使用 Spring Initializr 创建 Spring Boot 应用程序
- 在Spring Boot中配置Cassandra
- 在 Spring Boot 上配置 Tomcat 连接池
- 将Camel消息路由到嵌入WildFly的Artemis上
JTS Topology Suite(Java Topology Suite)是一个开源的Java软件库,它为欧几里得平面线性几何提供了一个对象模型以及一组基本的几何函数。
JTS 特性:https://locationtech.github.io/jts/jts-features.html
GitHub(JTS):https://github.com/locationtech/jts
JTS java doc:http://locationtech.github.io/jts/javadoc/overview-summary.html
GeoTools(JTS):https://docs.geotools.org/latest/userguide/library/jts/index.html
wikipedia(JTS):https://en.wikipedia.org/wiki/JTS_Topology_Suite
wikipedia(WKT):https://en.wikipedia.org/wiki/Well-known_text_representation_of_geometry
PostGIS 拓扑关系:https://postgis.net/docs/reference.html#idm15481
polygon 和 multipolygon 的区别:https://gis.stackexchange.com/questions/225368/understanding-difference-between-polygon-and-multipolygon-for-shapefiles-in-qgis/225373
几何类型 | WKT |
---|---|
Point | POINT (30 10) |
LineString | LINESTRING (30 10, 10 30, 40 40) |
Polygon | POLYGON ((35 10, 45 45, 15 40, 10 20, 35 10),(20 30, 35 35, 30 20, 20 30)) |
Polygon-with-hole | POLYGON ((35 10, 45 45, 15 40, 10 20, 35 10), (20 30, 35 35, 30 20, 20 30)) |
MultiPoint | MULTIPOINT ((10 40), (40 30), (20 20), (30 10)) |
MultiPoint | MULTIPOINT (10 40, 40 30, 20 20, 30 10) |
MultiLineString | MULTILINESTRING ((10 10, 20 20, 10 40),(40 40, 30 30, 40 20, 30 10)) |
MultiPolygon | MULTIPOLYGON (((30 20, 45 40, 10 40, 30 20)), ((15 5, 40 10, 10 20, 5 10, 15 5))) |
MultiPolygon-with-hole | MULTIPOLYGON (((40 40, 20 45, 45 30, 40 40)), ((20 35, 10 30, 10 10, 30 5, 45 20, 20 35), (30 20, 20 15, 20 25, 30 20))) |
GeometryCollection | GEOMETRYCOLLECTION (POINT (40 10), LINESTRING (10 10, 20 20, 10 40), POLYGON ((40 40, 20 45, 45 30, 40 40))) |
关键字 | 说明 | 参考 |
---|---|---|
equals (相等) | 如果两个几何在空间中包含相同的一组点,则返回 true | ST_Equals |
disjoint(不相交) | 如果两个几何在空间上不相交(它们没有共同点),则返回 true | ST_Disjoint |
intersects(相交) | 如果两个几何/地理在 2D 空间上相交(至少有一个共同点),则返回 true | ST_Intersects |
touches(接触) | 如果两个几何体至少有一个共同点,但它们的内部不相交,则返回 true | ST_Touches |
crosses(交叉) | 如果两个几何具有一些(但不是全部)共同的内部点,则返回 true | ST_Crosses |
within(内含) | 如果几何 A 完全在几何 B 内部,则返回 true | ST_Within |
contains (包含) | 当且仅当 B 的任何点都不在 A 的外部,并且 B 内部的至少一个点在 A 的内部时,才返回 true | ST_Contains |
overlaps(重叠) | 如果两个几何体相交并具有相同的维度,但彼此不完全包含,则返回 true | ST_Overlaps |
关键字 | 说明 | 参考 |
---|---|---|
buffer(缓冲区) | 返回一个几何图形,该几何图形涵盖距几何图形给定距离内的所有点 | ST_Buffer |
convexHull(凸壳) | 计算几何的凸壳 | ST_ConvexHull |
intersection(交集) | 返回表示几何 A 和 B 共享部分的几何 | ST_Intersection |
union(合并) | 返回表示输入几何的点集合并的几何 | ST_Union |
difference(差异) | 返回表示几何 A 中不与几何 B 相交的部分的几何 | ST_Difference |
symDifference(对称差异) | 返回表示几何 A 和 B 不相交部分的几何 | ST_SymDifference |
<!-- https://mvnrepository.com/artifact/org.locationtech.jts/jts-core -->
<dependency>
<groupId>org.locationtech.jts</groupId>
<artifactId>jts-core</artifactId>
<version>1.18.2</version>
</dependency>
package com.example;
import org.locationtech.jts.geom.*;
import org.locationtech.jts.io.ParseException;
import org.locationtech.jts.io.WKTReader;
import java.util.List;
import java.util.Map;
/**
* JTS 几何模型
* 几何类型:点( POINT )、多点( MULTIPOINT )
* 线( LINESTRING )、多线(MULTILINESTRING )
* 面(POLYGON )、多面(MULTIPOLYGON )
* 圆
* 创建方式:几何工厂 和 WKT
* */
public class JTSGeometryUtil {
// 几何工厂对象
private GeometryFactory geometryFactory = new GeometryFactory();
/**
* 获取点
* @param lng 经度
* @param lat 纬度
* */
public Point getPoint(Double lng, Double lat){
Coordinate coordinate = new Coordinate(lng, lat);
return geometryFactory.createPoint(coordinate);
}
/**
* 获取点,通过 WKT 创建
* @param lng 经度
* @param lat 纬度
* */
public Point getPointByWKT(Double lng, Double lat) throws ParseException {
StringBuilder wktSB = new StringBuilder();
// POINT(111 22)
wktSB.append("POINT").append("(").append( lng ).append(" ").append( lat ).append(")");
return (Point) createGeometry(wktSB.toString());
}
/**
* 获取多点
* @param coordinates 坐标集合
* */
public MultiPoint getMultiPoint(Coordinate [] coordinates){
return geometryFactory.createMultiPointFromCoords(coordinates);
}
/**
* 获取多点,通过 WKT 创建
* @param coordinates 坐标集合
* */
public MultiPoint getMultiPointByWKT(Coordinate [] coordinates) throws ParseException {
// MULTIPOINT(111 22 ,111 22)
String wktStr = createWktString("MULTIPOINT", coordinates);
return (MultiPoint) createGeometry(wktStr);
}
/**
* 获取线
* @param coordinates 坐标集合
* */
public LineString getLineString(Coordinate [] coordinates){
return geometryFactory.createLineString(coordinates);
}
/**
* 获取线,通过 WKT 创建
* @param coordinates 坐标集合
* */
public LineString getLineStringByWKT(Coordinate [] coordinates) throws ParseException {
String wktStr = createWktString("LINESTRING", coordinates);
return (LineString) createGeometry(wktStr);
}
/**
* 获取多线
* @param coordList 多个坐标集合
* */
public MultiLineString getMultiLineString(List<Coordinate []> coordList){
LineString [] lineStrings = new LineString[coordList.size()];
for(int m=0; m<coordList.size(); m++){
lineStrings[m] = getLineString(coordList.get(m));
}
return geometryFactory.createMultiLineString(lineStrings);
}
/**
* 获取多线,通过 WKT 创建
* @param coordList 多个坐标集合
* */
public MultiLineString getMultiLineStringByWKT(List<Coordinate []> coordList) throws ParseException {
String wktStr = createMultiWktString("MULTILINESTRING", coordList);
return (MultiLineString) createGeometry(wktStr);
}
/**
* 获取面
* @param coordinates 坐标集合
* */
public Polygon getPolygon(Coordinate [] coordinates){
return geometryFactory.createPolygon(coordinates);
}
/**
* 获面
* @param shellCoordinates 面边界坐标集合
* @param holeCoordList 多个孔洞坐标集合
* */
public Polygon getPolygon(Coordinate [] shellCoordinates, List<Coordinate []> holeCoordList){
LinearRing shell = geometryFactory.createLinearRing(shellCoordinates);
LinearRing[] holes = new LinearRing[holeCoordList.size()];
for(int m=0; m<holeCoordList.size(); m++){
Coordinate [] holeCoordinates = holeCoordList.get(m);
holes[m] = geometryFactory.createLinearRing(holeCoordinates);
}
return geometryFactory.createPolygon(shell, holes);
}
/**
* 获取面,通过 WKT 创建
* @param coordinates 坐标集合
* */
public Polygon getPolygonByWKT(Coordinate [] coordinates) throws ParseException {
String wktStr = createWktStringWithPolygon("POLYGON", coordinates, null);
return (Polygon) createGeometry(wktStr);
}
/**
* 获取面,通过 WKT 创建
* @param shellCoordinates 面边界坐标集合
* @param holeCoordList 多个孔洞坐标集合
* */
public Polygon getPolygonByWKT(Coordinate [] shellCoordinates, List<Coordinate []> holeCoordList) throws ParseException {
String wktStr = createWktStringWithPolygon("POLYGON", shellCoordinates, holeCoordList);
return (Polygon) createGeometry(wktStr);
}
/**
* 获取多面
* @param coordList 多个坐标集合
* */
public MultiPolygon getMultiPolygon(List<Coordinate []> coordList){
Polygon [] polygons = new Polygon[ coordList.size() ];
for(int i=0; i<coordList.size(); i++){
polygons[i] = geometryFactory.createPolygon(coordList.get(i));
}
return geometryFactory.createMultiPolygon(polygons);
}
/**
* 获多面
* @param coordinateMap 面边界和孔洞坐标集合
* */
public MultiPolygon getMultiPolygon(Map<Coordinate [], List<Coordinate []>> coordinateMap){
Polygon [] polygons = new Polygon[ coordinateMap.size() ];
int index = 0;
for(Map.Entry<Coordinate[], List<Coordinate[]>> item : coordinateMap.entrySet()){
LinearRing shell = geometryFactory.createLinearRing(item.getKey()); // 面边界
LinearRing[] holes = new LinearRing[item.getValue().size()]; // 孔洞
for(int m=0; m<item.getValue().size(); m++){
Coordinate [] holeCoordinates = item.getValue().get(m);
holes[m] = geometryFactory.createLinearRing(holeCoordinates);
}
polygons[index] = geometryFactory.createPolygon(shell, holes);
index++;
}
return geometryFactory.createMultiPolygon(polygons);
}
/**
* 获取多面
* @param coordList 多个坐标集合
* */
public MultiPolygon getMultiPolygonByWKT(List<Coordinate []> coordList) throws ParseException {
StringBuilder wktSB = new StringBuilder();
wktSB.append("MULTIPOLYGON").append("(");
int index = 0;
for(Coordinate [] coordinates : coordList){
if(index > 0) { wktSB.append(","); }
// 1. 处理面边界
wktSB.append("(");
wktSB.append("("); // 面边界start
wktSB.append(coordinatesToWktStr(coordinates));
wktSB.append(")"); // 面边界end
wktSB.append(")");
index++;
}
wktSB.append(")");
return (MultiPolygon) createGeometry(wktSB.toString());
}
/**
* 获多面
* @param coordinateMap 面边界和孔洞坐标集合
* */
public MultiPolygon getMultiPolygonByWKT(Map<Coordinate [], List<Coordinate []>> coordinateMap) throws ParseException {
StringBuilder wktSB = new StringBuilder();
wktSB.append("MULTIPOLYGON").append("(");
int index = 0;
for(Map.Entry<Coordinate[], List<Coordinate[]>> item : coordinateMap.entrySet()){
Coordinate [] shellCoordinates = item.getKey();
List<Coordinate []> holeCoordList = item.getValue();
if(index > 0) { wktSB.append(","); }
wktSB.append("(");
wktSB.append(coordinatesToWktStr(shellCoordinates, holeCoordList));
wktSB.append(")");
index++;
}
wktSB.append(")");
return (MultiPolygon) createGeometry(wktSB.toString());
}
/**
* 获取圆(无孔洞)
* @param lng 经度
* @param lat 纬度
* @param radius 半径
* */
public Polygon getCircle(double lng, double lat, final double radius) {
final int arcs = 32; // 弧线点数量
Coordinate coords[] = new Coordinate[ arcs + 1 ];
for (int i = 0; i < arcs; i++) { // 角度转弧度计算
double angle = ((double) i / (double) arcs) * Math.PI * 2.0;
double dx = Math.cos(angle) * radius;
double dy = Math.sin(angle) * radius;
coords[i] = new Coordinate((double) lng + dx, (double) lat + dy);
}
coords[arcs] = coords[0]; // 将第一个数据放在最后,形成闭环
LinearRing ring = geometryFactory.createLinearRing(coords); // 圆环线
Polygon polygon = geometryFactory.createPolygon(ring, null);
return polygon;
}
/**
* 通过 WKT 字符串创建几何对象
* @param wktStr wkt 字符串
* */
public Geometry createGeometry(String wktStr) throws ParseException {
WKTReader wktReader = new WKTReader(geometryFactory);
return wktReader.read(wktStr);
}
/**
* 根据几何类型和坐标集合,创建 WKT 字符串
* @param geomType 几何类型
* @param coordinates 坐标集合
* */
public String createWktString(String geomType, Coordinate [] coordinates){
StringBuilder wktSB = new StringBuilder();
wktSB.append(geomType).append("(");
wktSB.append(coordinatesToWktStr(coordinates));
wktSB.append(")");
return wktSB.toString();
}
/**
* 将坐标集合转换为 wkt 需要的字符串
* @param coordinates 坐标集合
* */
private String coordinatesToWktStr(Coordinate [] coordinates){
StringBuilder wktSB = new StringBuilder();
for(int i=0; i<coordinates.length; i++){
Coordinate coordinate = coordinates[i];
wktSB.append( coordinate.getX() ).append(" ").append( coordinate.getY() );
if(coordinates.length-1 != i){ wktSB.append(","); } // 最后一个坐标不需要加逗号
}
return wktSB.toString();
}
/**
* 将坐标集合转换为 wkt 需要的字符串
* */
private String coordinatesToWktStr(Coordinate [] shellCoordinates, List<Coordinate []> holeCoordList){
StringBuilder wktSB = new StringBuilder();
// 1. 处理面边界
wktSB.append("("); // 面边界start
wktSB.append(coordinatesToWktStr(shellCoordinates));
wktSB.append(")"); // 面边界end
// 2. 处理多个孔洞
if(holeCoordList != null && holeCoordList.size() > 0){
for(int n=0; n<holeCoordList.size(); n++){
Coordinate [] holeCoordinates = holeCoordList.get(n);
wktSB.append(",");
wktSB.append("("); // 面边界start
wktSB.append(coordinatesToWktStr(holeCoordinates));
wktSB.append(")"); // 面边界end
}
}
return wktSB.toString();
}
/**
* 根据几何类型和坐标集合,创建 WKT 字符串(多个几何图形)
* @param geomType 几何类型
* @param coordList 多个坐标集合
* */
public String createMultiWktString(String geomType, List<Coordinate []> coordList){
StringBuilder wktSB = new StringBuilder();
wktSB.append(geomType).append("(");
for(int m=0; m<coordList.size(); m++){
Coordinate [] coordinates = coordList.get(m);
wktSB.append("(");
for(int n=0; n<coordList.size(); n++){
Coordinate coordinate = coordinates[n];
wktSB.append( coordinate.getX() ).append(" ").append( coordinate.getY() );
if(coordinates.length-1 != n){ wktSB.append(","); } // 最后一个坐标不需要加逗号
}
wktSB.append(")");
if(coordList.size()-1 != m){ wktSB.append(","); } // 最后一个坐标不需要加逗号
}
wktSB.append(")");
return wktSB.toString();
}
/**
* 根据几何类型和坐标集合,创建 WKT 字符串
* @param geomType 几何类型
* @param shellCoordinates 面边界坐标集合
* @param holeCoordList 多个孔洞坐标集合
* */
public String createWktStringWithPolygon(String geomType, Coordinate [] shellCoordinates, List<Coordinate []> holeCoordList){
StringBuilder wktSB = new StringBuilder();
wktSB.append(geomType).append("(");
wktSB.append(coordinatesToWktStr(shellCoordinates, holeCoordList));
wktSB.append(")");
return wktSB.toString();
}
}
package com.example;
import org.locationtech.jts.geom.*;
public class App
{
public static void main( String[] args )
{
App app = new App();
// 拓扑关系 contains
app.doContains();
// 叠加分析 intersection
app.doIntersection();
}
private JTSGeometryUtil jtsGeometryUtil = new JTSGeometryUtil();
/**
* Contains 包含
* */
public void doContains(){
// 点
Point point = jtsGeometryUtil.getPoint(116.403406,39.93397);
// 面
Coordinate[] coordinates = new Coordinate[4];
coordinates[0] = new Coordinate(116.361725,39.95676); // 首尾坐标相同
coordinates[1] = new Coordinate(116.364887,39.908515);
coordinates[2] = new Coordinate(116.442501,39.909622);
coordinates[2] = new Coordinate(116.440488,39.955654);
coordinates[3] = new Coordinate(116.361725,39.95676); // 首尾坐标相同
Polygon polygon = jtsGeometryUtil.getPolygon(coordinates);
// 操作
boolean result = polygon.contains(point);
System.out.println(result);
}
/**
* Intersection 交叉分析
* */
public void doIntersection(){
// 线一
Coordinate [] coordinates1 = new Coordinate[2];
coordinates1[0] = new Coordinate(116.361725,39.95676);
coordinates1[1] = new Coordinate(116.442501,39.909622);
LineString lineString1 = jtsGeometryUtil.getLineString(coordinates1);
// 线二
Coordinate [] coordinates2 = new Coordinate[2];
coordinates2[0] = new Coordinate(116.364887,39.908515);
coordinates2[1] = new Coordinate(116.440488,39.955654);
LineString lineString2 = jtsGeometryUtil.getLineString(coordinates2);
// 操作
Geometry geometry = lineString1.intersection(lineString2);
System.out.println(geometry);
}
}
我在网上搜索但没有找到任何合适的文章解释如何使用 javascript 使用 WCF 服务,尤其是 WebScriptEndpoint。 任何人都可以对此给出任何指导吗? 谢谢 最佳答案 这是一篇关于
我正在编写一个将运行 Linux 命令的 C 程序,例如: cat/etc/passwd | grep 列表 |剪切-c 1-5 我没有任何结果 *这里 parent 等待第一个 child (chi
所以我正在尝试处理文件上传,然后将该文件作为二进制文件存储到数据库中。在我存储它之后,我尝试在给定的 URL 上提供文件。我似乎找不到适合这里的方法。我需要使用数据库,因为我使用 Google 应用引
我正在尝试制作一个宏,将下面的公式添加到单元格中,然后将其拖到整个列中并在 H 列中复制相同的公式 我想在 F 和 H 列中输入公式的数据 Range("F1").formula = "=IF(ISE
问题类似于this one ,但我想使用 OperatorPrecedenceParser 解析带有函数应用程序的表达式在 FParsec . 这是我的 AST: type Expression =
我想通过使用 sequelize 和 node.js 将这个查询更改为代码取决于在哪里 select COUNT(gender) as genderCount from customers where
我正在使用GNU bash,版本5.0.3(1)-发行版(x86_64-pc-linux-gnu),我想知道为什么简单的赋值语句会出现语法错误: #/bin/bash var1=/tmp
这里,为什么我的代码在 IE 中不起作用。我的代码适用于所有浏览器。没有问题。但是当我在 IE 上运行我的项目时,它发现错误。 而且我的 jquery 类和 insertadjacentHTMl 也不
我正在尝试更改标签的innerHTML。我无权访问该表单,因此无法编辑 HTML。标签具有的唯一标识符是“for”属性。 这是输入和标签的结构:
我有一个页面,我可以在其中返回用户帖子,可以使用一些 jquery 代码对这些帖子进行即时评论,在发布新评论后,我在帖子下插入新评论以及删除 按钮。问题是 Delete 按钮在新插入的元素上不起作用,
我有一个大约有 20 列的“管道分隔”文件。我只想使用 sha1sum 散列第一列,它是一个数字,如帐号,并按原样返回其余列。 使用 awk 或 sed 执行此操作的最佳方法是什么? Accounti
我需要将以下内容插入到我的表中...我的用户表有五列 id、用户名、密码、名称、条目。 (我还没有提交任何东西到条目中,我稍后会使用 php 来做)但由于某种原因我不断收到这个错误:#1054 - U
所以我试图有一个输入字段,我可以在其中输入任何字符,但然后将输入的值小写,删除任何非字母数字字符,留下“。”而不是空格。 例如,如果我输入: 地球的 70% 是水,-!*#$^^ & 30% 土地 输
我正在尝试做一些我认为非常简单的事情,但出于某种原因我没有得到想要的结果?我是 javascript 的新手,但对 java 有经验,所以我相信我没有使用某种正确的规则。 这是一个获取输入值、检查选择
我想使用 angularjs 从 mysql 数据库加载数据。 这就是应用程序的工作原理;用户登录,他们的用户名存储在 cookie 中。该用户名显示在主页上 我想获取这个值并通过 angularjs
我正在使用 autoLayout,我想在 UITableViewCell 上放置一个 UIlabel,它应该始终位于单元格的右侧和右侧的中心。 这就是我想要实现的目标 所以在这里你可以看到我正在谈论的
我需要与 MySql 等效的 elasticsearch 查询。我的 sql 查询: SELECT DISTINCT t.product_id AS id FROM tbl_sup_price t
我正在实现代码以使用 JSON。 func setup() { if let flickrURL = NSURL(string: "https://api.flickr.com/
我尝试使用for循环声明变量,然后测试cols和rols是否相同。如果是,它将运行递归函数。但是,我在 javascript 中执行 do 时遇到问题。有人可以帮忙吗? 现在,在比较 col.1 和
我举了一个我正在处理的问题的简短示例。 HTML代码: 1 2 3 CSS 代码: .BB a:hover{ color: #000; } .BB > li:after {
我是一名优秀的程序员,十分优秀!