Commit 8ac28715 by chamberone

提交geometry模块

1 parent 91af9dc9
...@@ -9,6 +9,7 @@ gatewayConfig=$(cat ../config/project-gateway.yaml) ...@@ -9,6 +9,7 @@ gatewayConfig=$(cat ../config/project-gateway.yaml)
providerConfig=$(cat ../config/project-provider.yaml) providerConfig=$(cat ../config/project-provider.yaml)
consumerConfig=$(cat ../config/project-consumer.yaml) consumerConfig=$(cat ../config/project-consumer.yaml)
userConfig=$(cat ../config/project-user.yaml) userConfig=$(cat ../config/project-user.yaml)
gisConfig=$(cat ../config/project-gis.yaml)
groupId="project" groupId="project"
curl -X POST "nacos-server:8848/nacos/v1/cs/configs" -d "dataId=datasource-config.yaml&group=${groupId}&content=${datasourceConfig}" curl -X POST "nacos-server:8848/nacos/v1/cs/configs" -d "dataId=datasource-config.yaml&group=${groupId}&content=${datasourceConfig}"
curl -X POST "nacos-server:8848/nacos/v1/cs/configs" -d "dataId=project-storage.yaml&group=${groupId}&content=${storageConfig}" curl -X POST "nacos-server:8848/nacos/v1/cs/configs" -d "dataId=project-storage.yaml&group=${groupId}&content=${storageConfig}"
...@@ -18,4 +19,5 @@ curl -X POST "nacos-server:8848/nacos/v1/cs/configs" -d "dataId=project-gateway. ...@@ -18,4 +19,5 @@ curl -X POST "nacos-server:8848/nacos/v1/cs/configs" -d "dataId=project-gateway.
curl -X POST "nacos-server:8848/nacos/v1/cs/configs" -d "dataId=project-provider.yaml&group=${groupId}&content=${providerConfig}" curl -X POST "nacos-server:8848/nacos/v1/cs/configs" -d "dataId=project-provider.yaml&group=${groupId}&content=${providerConfig}"
curl -X POST "nacos-server:8848/nacos/v1/cs/configs" -d "dataId=project-consumer.yaml&group=${groupId}&content=${consumerConfig}" curl -X POST "nacos-server:8848/nacos/v1/cs/configs" -d "dataId=project-consumer.yaml&group=${groupId}&content=${consumerConfig}"
curl -X POST "nacos-server:8848/nacos/v1/cs/configs" -d "dataId=project-user.yaml&group=${groupId}&content=${userConfig}" curl -X POST "nacos-server:8848/nacos/v1/cs/configs" -d "dataId=project-user.yaml&group=${groupId}&content=${userConfig}"
curl -X POST "nacos-server:8848/nacos/v1/cs/configs" -d "dataId=project-gis.yaml&group=${groupId}&content=${gisConfig}"
echo "Nacos config pushed successfully finished" echo "Nacos config pushed successfully finished"
\ No newline at end of file
...@@ -7,4 +7,5 @@ STORAGE_PORT=8011 ...@@ -7,4 +7,5 @@ STORAGE_PORT=8011
PRAISE_PROVIDER_PORT=8015 PRAISE_PROVIDER_PORT=8015
PRAISE_CONSUMER_PORT=8014 PRAISE_CONSUMER_PORT=8014
USER_PORT=8000 USER_PORT=8000
GIS_PORT=8001 GIS_PORT=8001
\ No newline at end of file GEOMETRY_PORT=8002
\ No newline at end of file
...@@ -252,4 +252,21 @@ services: ...@@ -252,4 +252,21 @@ services:
- nacos - nacos
- mysql - mysql
- postgres - postgres
- project-geometry
# geometry module
project-geometry:
image: project-geometry
restart: always
build:
dockerfile: ./project-geometry/Dockerfile
context: ../
env_file:
- .env
container_name: project-geometry
ports:
- ${GEOMETRY_PORT}:${GEOMETRY_PORT}
depends_on:
- nacos
\ No newline at end of file
FROM registry.cn-hangzhou.aliyuncs.com/dituhui/smo:j11-s9.1.0
COPY ./target/project-geometry-*.jar /app.jar
EXPOSE 8002
CMD cd /opt/SMO/Support/aksusbd-2.2.1-i386/ && (./dinst &) && sleep 10 && pkill -9 hasp_update && cd / && java -version && java -jar app.jar
<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-parent</artifactId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>project-geometry</artifactId>
<name>Spring Cloud Alibaba geometry</name>
<description>geometry module</description>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<smo.version>9.1.0.15802</smo.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</dependency>
<dependency>
<groupId>com.supermap</groupId>
<artifactId>com.supermap.data</artifactId>
<version>${smo.version}</version>
</dependency>
<dependency>
<groupId>com.supermap</groupId>
<artifactId>com.supermap.data.topology</artifactId>
<version>${smo.version}</version>
</dependency>
<dependency>
<groupId>com.supermap</groupId>
<artifactId>com.supermap.analyst.spatialanalyst</artifactId>
<version>${smo.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>net.jpountz.lz4</groupId>
<artifactId>lz4</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.31</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>21.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.5</version>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.3</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>project-interface</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
package com.dituhui.mp.geometry;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableFeignClients
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
package com.dituhui.mp.geometry.controller;
import com.dituhui.mp.geometry.IGeometry;
import com.dituhui.mp.geometry.service.GeometryService;
import com.dituhui.mp.pojo.GeometryInfo;
import com.dituhui.mp.pojo.WebResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.RestController;
/**
* IGeometryController
* 用于几何接口的类
*
* @author zhouyun
* 2020/03/10 16:54
* <p>Company: 成都地图慧科技有限公司</p>
*/
@RestController
@RefreshScope
public class IGeometryController implements IGeometry {
@Autowired
private GeometryService geometryService;
@Override
public WebResult<GeometryInfo> topology(GeometryInfo geometryInfo) {
return WebResult.ok(geometryService.topology(geometryInfo));
}
@Override
public WebResult<String> test() {
return WebResult.ok("Geometry");
}
}
package com.dituhui.mp.geometry.service;
import com.dituhui.mp.geometry.util.GeoCalculator;
import com.dituhui.mp.pojo.GeometryInfo;
import com.dituhui.mp.pojo.PointBase;
import com.supermap.data.GeoRegion;
import com.supermap.data.Point2D;
import com.supermap.data.Point2Ds;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
/**
* GeometryService
* 用于几何接口实现的类
*
* @author zhouyun
* 2021/3/10 15:11
* <p>Company: 成都地图慧科技有限公司</p>
*/
@Service
public class GeometryService {
/**
* 拓扑处理
*
* @param geometryInfo geo对象
* @return 处理后geo对象
*/
public GeometryInfo topology(GeometryInfo geometryInfo) {
GeoRegion geoRegion = infoToRegion(geometryInfo);
GeoRegion region = GeoCalculator.topComplexRegion(geoRegion);
if (null == region) {
return null;
}
return regionToInfo(region);
}
private GeometryInfo regionToInfo(GeoRegion region) {
int[] parts = new int[region.getPartCount()];
List<PointBase> points = new ArrayList<>();
for (int i = 0; i < region.getPartCount(); i++) {
Point2Ds point2Ds = region.getPart(i);
parts[i] = point2Ds.getCount();
for (int j = 0; j < parts[i]; j++) {
Point2D point2D = point2Ds.getItem(j);
points.add(new PointBase(point2D.getX(), point2D.getY()));
}
}
GeometryInfo geometry = new GeometryInfo();
geometry.setParts(parts);
geometry.setPoints(points);
return geometry;
}
private GeoRegion infoToRegion(GeometryInfo geometryInfo) {
GeoRegion geoRegion = new GeoRegion();
int[] parts = geometryInfo.getParts();
List<PointBase> points = geometryInfo.getPoints();
int i = 0;
for (int part : parts) {
int count = 0;
Point2Ds point2Ds = new Point2Ds();
while (count < part) {
PointBase point = points.get(i);
point2Ds.add(new Point2D(point.getX(), point.getY()));
count++;
i++;
}
geoRegion.addPart(point2Ds);
}
return geoRegion;
}
}
package com.dituhui.mp.geometry.util;
import com.supermap.analyst.spatialanalyst.EliminateMode;
import com.supermap.analyst.spatialanalyst.Generalization;
import com.supermap.data.*;
import com.supermap.data.topology.TopologyProcessing;
import com.supermap.data.topology.TopologyProcessingOptions;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
/**
* 空间几何计算工具。依赖SuperMap Objects。test
*
*/
@Component
public class GeoCalculator {
private static final Logger LOGGER = Logger.getLogger(GeoCalculator.class);
private static volatile Datasource memoryDatasource;
private static double minSize = 2.56;
private static final List<Integer> integers = IntStream.range(0, 100000).boxed().collect(Collectors.toList());
public static List<GeoRegion> topology(List<GeoRegion> regions, boolean isDeleteSingleRegion) {
if (memoryDatasource == null) {
// 初始化
EngineType enginetype = EngineType.MEMORY;
Workspace w = new Workspace();
DatasourceConnectionInfo datasourceConnectionInfo = new DatasourceConnectionInfo();
datasourceConnectionInfo.setEngineType(enginetype);
datasourceConnectionInfo.setReadOnly(false);
memoryDatasource = w.getDatasources().create(datasourceConnectionInfo);
}
// 线拓扑构面
// 源数据集名称
String srcDatasetName ;
int random = getIntUnduplicate();
srcDatasetName = "l" + random;
// 目标数据集名称
String outputDatasetName ;
outputDatasetName = "r" + random;
// 线数据集
DatasetVectorInfo datasetVectorInfo = new DatasetVectorInfo();
Datasets datasets = memoryDatasource.getDatasets();
srcDatasetName = datasets.getAvailableDatasetName(srcDatasetName);
// System.out.println("srcDatasetName = " + srcDatasetName);
outputDatasetName = datasets.getAvailableDatasetName(outputDatasetName);
// System.out.println("outputDatasetName = " + outputDatasetName);
datasetVectorInfo.setName(srcDatasetName);
DatasetType datasetType = DatasetType.LINE;
datasetVectorInfo.setType(datasetType);
DatasetVector lineDatasetVector = datasets.create(datasetVectorInfo);
if (lineDatasetVector == null) {
LOGGER.warn("创建数据集失败");
return null;
}
// TODO: 9c换为MemRecordset
Recordset lineRecordset = lineDatasetVector.getRecordset(false, CursorType.DYNAMIC);
for (GeoRegion region : regions) {
lineRecordset.addNew(region.convertToLine());
lineRecordset.edit();
lineRecordset.update();
}
lineRecordset.close();
// 拓扑参数
TopologyProcessingOptions tpOptions = new TopologyProcessingOptions();
tpOptions.setAdjacentEndpointsMerged(true);
tpOptions.setDuplicatedLinesCleaned(true);
tpOptions.setLinesIntersected(true);
tpOptions.setOvershootsCleaned(true);
tpOptions.setPseudoNodesCleaned(true);
tpOptions.setRedundantVerticesCleaned(true);
tpOptions.setUndershootsExtended(true);
// 拓扑构面
DatasetVector regionDatasetVector = TopologyProcessing.buildRegions(lineDatasetVector, memoryDatasource, outputDatasetName, tpOptions);
if (regionDatasetVector == null) {
LOGGER.info("regionDatasetVector is null");
return null;
}
// 获取面集合中面的最小面积
double minArea = getMinRegionArea(regions);
// 取最小面积的3/4作为容限
minArea = minArea * 3 / 4;
// 碎多边形合并
if (Generalization.eliminate(regionDatasetVector, minArea, 0.5, EliminateMode.ELIMINATE_BY_AREA, isDeleteSingleRegion)) {
LOGGER.debug("碎多边形合并成功");
} else {
LOGGER.info("碎多边形合并失败");
}
Recordset rs = regionDatasetVector.getRecordset(false, CursorType.STATIC);
List<GeoRegion> newRegions = new ArrayList<>();
rs.moveFirst();
while (!rs.isEOF()) {
GeoRegion geoRegion = (GeoRegion) rs.getGeometry();
// 暂时关闭重采样
if (false) {
// 重采样,去掉碎线。
geoRegion = (GeoRegion) Geometrist.resample(geoRegion, ResampleType.RTGENERAL, 10);
}
if (geoRegion != null) {
newRegions.add(geoRegion);
}
rs.moveNext();
}
// 清理资源
rs.close();
lineDatasetVector.close();
regionDatasetVector.close();
datasets.delete(srcDatasetName);
datasets.delete(outputDatasetName);
dispose(random);
return newRegions;
}
/**
* 获取面集合中面的最小面积
*
* @param regions 面集合
* @return 最小面的面积
*/
private static double getMinRegionArea(List<GeoRegion> regions) {
double minArea = 0;
for (GeoRegion region : regions) {
double regionArea = region.getArea();
if (regionArea < minArea || minArea == 0) {
minArea = regionArea;
}
}
return minArea;
}
private synchronized static int getIntUnduplicate(){
Integer out = integers.get(0);
integers.remove(out);
return out;
}
private synchronized static void dispose(int disposeInt){
integers.add(disposeInt);
}
public static GeoRegion topComplexRegion(GeoRegion geoRegion) {
List<GeoRegion> regions = new ArrayList<>();
GeoRegion region = null;
GeoRegion simpleRegion = null;
//保护性分解, 保留符合规定的飞地、洞
GeoRegion[] protectGeoRegions = new GeoRegion[]{geoRegion};
try {
if (geoRegion.getPartCount() > 1) {
protectGeoRegions = geoRegion.protectedDecompose();
}
for (GeoRegion protectGeoRegion : protectGeoRegions) {
if (protectGeoRegion.getArea() < minSize) {
continue;
}
GeoRegion temp = topSimpleRegion(protectGeoRegion);
if (null != temp)
regions.add(temp);
}
if (regions.size() >= 1) {
region = regions.get(0);
for (int i = 1; i < regions.size(); i++) {
simpleRegion = regions.get(i);
for (int j = 0; j < simpleRegion.getPartCount(); j++) {
region.addPart(simpleRegion.getPart(j));
}
}
}
return null == region ? null : region.clone();
} finally {
GeometryUtil.disposeGeometry(region, simpleRegion);
GeometryUtil.disposeGeometry(protectGeoRegions);
GeometryUtil.disposeGeometry(regions.toArray(new Geometry[]{}));
}
}
/**
* 拓扑处理 只保留一个面 或洞数据
*/
private static GeoRegion topSimpleRegion(GeoRegion geoRegion) {
//一个part时直接拓扑处理
if (null == geoRegion || geoRegion.getPartCount() == 0) {
return null;
}
if (geoRegion.getPartCount() == 1) {
List<GeoRegion> topology = topology(List.of(geoRegion), false);
return topology != null ? topology.get(0) : null;
}
GeoRegion resultRegion = null;
//洞数据 直接拓扑只会保留最大part, 每个part单独拓扑结果作异或运算还原洞数据
for (int i = 0; i < geoRegion.getPartCount(); i++) {
GeoRegion temp = topSimpleRegion(new GeoRegion(geoRegion.getPart(i)));
if (resultRegion == null && temp != null) {
resultRegion = temp;
} else if (resultRegion != null && temp != null) {
resultRegion = (GeoRegion) Geometrist.xOR(resultRegion, temp);
}
}
return resultRegion;
}
}
package com.dituhui.mp.geometry.util;
import com.supermap.data.Geometry;
/**
* GeoUtil
* 用于的类
*
* @author zhouyun
* 2021/3/10 15:52
* <p>Company: 成都地图慧科技有限公司</p>
*/
public class GeometryUtil {
public static void disposeGeometry(Geometry... geo) {
for (Geometry g : geo) {
try {
if (null != g) {
g.dispose();
}
} catch (Exception e) {
System.out.println(e);
}
}
}
}
server:
port: 8002
spring:
application:
name: geometry
serverlet:
encoding:
charset: utf-8
force: true
main:
allow-bean-definition-overriding: true
cloud:
nacos:
discovery:
server-addr: nacos-server:8848
group: project
config:
server-addr: nacos-server:8848
group: project
file-extension: yaml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<springProperty scope="context" name="springAppName" source="spring.application.name"/>
<!-- Example for logging into the build folder of your project -->
<property name="LOG_FILE" value="logs/${springAppName}"/>
<!-- You can override this to have a custom pattern -->
<property name="CONSOLE_LOG_PATTERN"
value="%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>
<!-- Appender to log to console -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<!-- Minimum logging level to be presented in the console logs-->
<level>DEBUG</level>
</filter>
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<charset>utf8</charset>
</encoder>
</appender>
<!-- Appender to log to file -->
<appender name="flatfile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_FILE}</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.gz</fileNamePattern>
<maxHistory>7</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<charset>utf8</charset>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="console"/>
<!-- uncomment this to have also JSON logs
<appender-ref ref="logstash"/> -->
<!--<appender-ref ref="flatfile"/>-->
</root>
</configuration>
\ No newline at end of file
package com.dituhui.mp.geometry.test;
import com.dituhui.mp.geometry.Application;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
/**
* AreaTest
* <p>
* 用于的类
*
* @author zhouyun
* 2020/11/20 13:53
* 成都地图慧科技有限公司
* <p>
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class GeometryTest {
}
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!