2021-06-29

package com.spacemv.mv.api.task.controller;

import com.spacemv.mv.api.common.Utils.Result;
import com.spacemv.mv.api.entity.*;
import com.spacemv.mv.api.service.*;
import com.spacemv.mv.api.task.entity.TaskInfo;
import com.spacemv.mv.api.task.manager.AsyncTaskManager;
import com.spacemv.mv.interpretator.domain.PredictionInput;
import com.spacemv.mv.interpretator.domain.PredictionOutput;
import com.spacemv.mv.interpretator.exceptions.PredictionException;
import com.spacemv.mv.interpretator.service.DeepLearningPredictionService;
import com.spacemv.mv.io.FileHelper;
import com.spacemv.mv.task.TaskProgressHandler;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

@RestController
@Api(tags = "异步任务管理")
@RequestMapping(value = "api/task")
public class AsyncTaskController {
    private Logger logger = LoggerFactory.getLogger(AsyncTaskController.class);

    @Value("${resource.path}")
    private String resourcePath;
    @Value("${upload.directory_name}")
    private String uploadDirectoryName;

    @Autowired
    AsyncTaskManager asyncTaskManager;

    @Autowired
    MvInterpretationTaskDetailService mvInterpretationTaskDetailService;
    @Autowired
    MvInterpretationTaskService mvInterpretationTaskService;

    @Autowired
    MvAlgorithmModelService mvAlgorithmModelService;

    @Autowired
    DeepLearningPredictionService predictionService;

    @Autowired
    MvInterpretationTaskDataService taskDataService;
    @Autowired
    MvInterpretationTaskLogService mvInterpretationTaskLogService;


    @ApiOperation("启动任务")
    @RequestMapping(value = "/start", method = RequestMethod.POST)
    public Result startAsyncTask(@RequestBody String[] taskIds) {
        //1.在任务管理界面启动任务,可以勾选多个
        //2.每次执行任务,在detail中插入一条记录

        List<TaskInfo> taskInfos = new ArrayList<>();
        for (String taskUid : taskIds) {
            //1.向detail数据插入一个数据

            MvInterpretationTaskDetail mvInterpretationTaskDetail = new MvInterpretationTaskDetail();
            mvInterpretationTaskDetail.setUid(UUID.randomUUID().toString());
            mvInterpretationTaskDetail.setTaskUid(taskUid);
            mvInterpretationTaskDetail.setProgress(0);
            mvInterpretationTaskDetail.setTaskStatus(TaskStatus.getEXECUTING());
            mvInterpretationTaskDetail.setStartTime(new Date());
            mvInterpretationTaskDetail.setOutputRasterDataUid(UUID.randomUUID().toString());
            mvInterpretationTaskDetailService.insert(mvInterpretationTaskDetail);

            Integer taskDetailId = mvInterpretationTaskDetail.getId();

            //向日志表插入数据
            MvInterpretationTaskLog mvInterpretationTaskLogPretreatment = new MvInterpretationTaskLog();
            mvInterpretationTaskLogPretreatment.setLogUid(UUID.randomUUID().toString());
            mvInterpretationTaskLogPretreatment.setTaskDetailUid(mvInterpretationTaskDetail.getUid());
            mvInterpretationTaskLogPretreatment.setTitle("数据预处理");
            mvInterpretationTaskLogPretreatment.setLogTime(new Date());
            mvInterpretationTaskLogPretreatment.setDetails("11");
            mvInterpretationTaskLogPretreatment.setLogType(LogTypeStatus.getInTheLine());
            mvInterpretationTaskLogService.insert(mvInterpretationTaskLogPretreatment);

            MvInterpretationTask mvInterpretationTask = mvInterpretationTaskService.queryByUid(mvInterpretationTaskDetail.getTaskUid());
            Integer modelId = mvInterpretationTask.getModelId();
            MvAlgorithmModel mvAlgorithmModel = mvAlgorithmModelService.queryById(modelId);

            // /upload/xxxx
            MvInterpretationTaskData inputData = taskDataService.selectData(mvInterpretationTask.getInputDataUid());
            String inputDataPath = inputData.getFilePath();

            //2.获取任务信息,获取模型信息
            String inputFilePath = FileHelper.combine(resourcePath, inputDataPath);
            String modelFilePath = mvAlgorithmModel.getModelPath();
            String modelFileFullPath = FileHelper.combine(resourcePath, modelFilePath);
            //3. 开启异步任务
            TaskInfo taskInfo = asyncTaskManager.submit(() -> {
                try {
                    mvInterpretationTaskDetailService.updateProgress(1, taskDetailId);
                    PredictionInput input = new PredictionInput();
                    //目录结构 :
                    //          upload/task_uid/input1.tif
                    //          upload/task_uid/input2.tif
                    //          upload/task_uid/input3.tif
                    //  输出目录        upload/task_uid/task_detail_uid/
                    String outputDataDir = FileHelper.combine(uploadDirectoryName, taskUid, mvInterpretationTaskDetail.getUid());
                    String taskOutputDataFullDir = FileHelper.combine(resourcePath, outputDataDir);
                    FileHelper.checkOrCreateFolder(taskOutputDataFullDir, true);
                    logger.info("创建输出目录:" + taskOutputDataFullDir);
                    input.setWorkspace(taskOutputDataFullDir);
                    input.setModelFilePath(modelFileFullPath);
                    input.getInputFiles().add(inputFilePath);
                    try {

                        MvInterpretationTaskLog mvInterpretationTaskLogOngoing = new MvInterpretationTaskLog();
                        mvInterpretationTaskLogOngoing.setLogUid(UUID.randomUUID().toString());
                        mvInterpretationTaskLogOngoing.setTaskDetailUid(mvInterpretationTaskDetail.getUid());
                        mvInterpretationTaskLogOngoing.setTitle("解译中");
                        mvInterpretationTaskLogOngoing.setLogTime(new Date());
                        mvInterpretationTaskLogOngoing.setDetails("11");
                        mvInterpretationTaskLogOngoing.setLogType(LogTypeStatus.getEXECUTING());
                        mvInterpretationTaskLogService.insert(mvInterpretationTaskLogOngoing);

                        mvInterpretationTaskDetailService.updateProgress(2, taskDetailId);

                        predictionService.setProgressHandler(new TaskProgressHandler() {
                            @Override
                            public void progress(Integer progress) {
                                mvInterpretationTaskDetailService.updateProgress(progress, taskDetailId);
                            }
                        });

                        PredictionOutput output = predictionService.predict(input);
                        String outputFileName = output.getResults().get(0);
                        String outputFilePath = FileHelper.combine(outputDataDir, outputFileName);
                        MvInterpretationTaskData data = new MvInterpretationTaskData();
                        data.setUid(UUID.randomUUID().toString());
                        data.setFileName(outputFileName);
                        data.setFilePath(outputFilePath);
                        data.setFileExt(FileHelper.getFileExtensionName(outputFileName));
                        data.setUploadTime(new Date());
                        taskDataService.insert(data);
                        updateStatusSuccess(taskUid, mvInterpretationTaskDetail, data);
                        //向日志表插入数据
                        MvInterpretationTaskLog mvInterpretationTaskLogSuccess = new MvInterpretationTaskLog();
                        mvInterpretationTaskLogSuccess.setLogUid(UUID.randomUUID().toString());
                        mvInterpretationTaskLogSuccess.setTaskDetailUid(mvInterpretationTaskDetail.getUid());
                        mvInterpretationTaskLogSuccess.setTitle("解译成功");
                        mvInterpretationTaskLogSuccess.setLogTime(new Date());
                        mvInterpretationTaskLogSuccess.setDetails("11");
                        mvInterpretationTaskLogSuccess.setLogType(LogTypeStatus.getSUCCESS());
                        mvInterpretationTaskLogService.insert(mvInterpretationTaskLogSuccess);

                    } catch (PredictionException e) {
                        //任务执行失败,返回状态为3
                        updateStatusFailure(taskUid, mvInterpretationTaskDetail);
                        //向日志表插入数据
                        MvInterpretationTaskLog mvInterpretationTaskLogFailure = new MvInterpretationTaskLog();
                        mvInterpretationTaskLogFailure.setLogUid(UUID.randomUUID().toString());
                        mvInterpretationTaskLogFailure.setTaskDetailUid(mvInterpretationTaskDetail.getUid());
                        mvInterpretationTaskLogFailure.setTitle("解译失败");
                        mvInterpretationTaskLogFailure.setLogTime(new Date());
                        mvInterpretationTaskLogFailure.setDetails("11");
                        mvInterpretationTaskLogFailure.setLogType(LogTypeStatus.getFAILURE());
                        mvInterpretationTaskLogService.insert(mvInterpretationTaskLogFailure);
                        logger.error(e.getMessage());
                        e.printStackTrace();
                    }
                } catch (Exception e) {

                    logger.error(e.getMessage());
                    e.printStackTrace();
                }
            });
            taskInfos.add(taskInfo);
        }
        //调用任务管理器中的submit去提交一个异步任务
        return Result.success(taskInfos);
    }

    private void updateStatusSuccess(String taskUid, MvInterpretationTaskDetail mvInterpretationTaskDetail, MvInterpretationTaskData data) {
        mvInterpretationTaskDetail.setOutputRasterDataUid(data.getUid());
        mvInterpretationTaskDetail.setTaskUid(taskUid);
        mvInterpretationTaskDetail.setTaskStatus(TaskStatus.getSUCCESS());
        mvInterpretationTaskDetail.setProgress(100);
        mvInterpretationTaskDetail.setEndTime(new Date());
        mvInterpretationTaskDetailService.update(mvInterpretationTaskDetail);
    }

    private void updateStatusFailure(String taskUid, MvInterpretationTaskDetail mvInterpretationTaskDetail) {
        mvInterpretationTaskDetail.setTaskUid(taskUid);
        mvInterpretationTaskDetail.setTaskStatus(TaskStatus.getFAILURE());
        mvInterpretationTaskDetail.setEndTime(new Date());
        mvInterpretationTaskDetailService.update(mvInterpretationTaskDetail);
    }

    @RequestMapping(value = "/status", method = RequestMethod.GET)
    public Result getTaskStatus(
            @RequestParam("taskId") String taskId) {
        return Result.success(asyncTaskManager.getTaskInfo(taskId));
    }
}

package com.spacemv.mv.api.task.entity;

/**
 * 任务状态枚举
 */
public enum TaskStatusEnum {

    STARTED(1, "任务已经启动"),
    RUNNING(0, "任务正在运行"),
    SUCCESS(2, "任务执行成功"),
    FAILED(-2, "任务执行失败");
    private int state;
    private String stateInfo;

    TaskStatusEnum(int state, String stateInfo) {
        this.state = state;
        this.stateInfo = stateInfo;
    }

    public int getState() {
        return state;
    }

    public String getStateInfo() {
        return stateInfo;
    }

}

package com.spacemv.mv.api.task.manager;

import com.spacemv.mv.api.task.entity.TaskInfo;
import com.spacemv.mv.api.task.entity.TaskStatusEnum;
import com.spacemv.mv.api.task.service.AsyncTaskConstructor;
import com.spacemv.mv.api.task.service.AsyncTaskExecutor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * 异步任务管理器
 */
@Component
public class AsyncTaskManager {
    private Map<String, TaskInfo> taskContainer = new HashMap<>(16);
    @Autowired
    AsyncTaskExecutor asyncTaskExecutor;


    /**
     * 初始化任务
     *
     * @return taskInfo
     */
    public TaskInfo initTask() {
        TaskInfo taskInfo = new TaskInfo();
        taskInfo.setTaskId(getTaskId());
        taskInfo.setStatus(TaskStatusEnum.STARTED);
        taskInfo.setStartTime(new Date());
        setTaskInfo(taskInfo);
        return taskInfo;
    }

    /**
     * 初始化任务
     * @param asyncTaskConstructor 异步任务构造器
     * @return taskInfo
     */
    public TaskInfo submit(AsyncTaskConstructor asyncTaskConstructor) {
        TaskInfo info = initTask();
        String taskId = info.getTaskId();
        asyncTaskExecutor.executor(asyncTaskConstructor,taskId);
        return info;
    }

    /**
     * 保存任务信息
     *
     * @param taskInfo 任务信息
     */
    public void setTaskInfo(TaskInfo taskInfo) {
        taskContainer.put(taskInfo.getTaskId(), taskInfo);
    }

    /**
     * 获取任务信息
     *
     * @param taskId 任务ID
     * @return
     */
    public TaskInfo getTaskInfo(String taskId) {
        return taskContainer.get(taskId);
    }

    /**
     * 获取任务状态
     *
     * @param taskId 任务ID
     * @return`在这里插入代码片`
     */
    public TaskStatusEnum getTaskStatus(String taskId) {
        return getTaskInfo(taskId).getStatus();
    }

    /**
     * 生成任务ID
     *
     * @return taskId
     */
    public String getTaskId() {
        return UUID.randomUUID().toString();
    }
}

``

```java
package com.spacemv.mv.api.task.manager;

import com.spacemv.mv.api.task.entity.TaskInfo;
import com.spacemv.mv.api.task.entity.TaskStatusEnum;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Date;

/**
 * Created by shirukai on 2018/7/31
 * 异步任务监控
 */
@Component
@Aspect
public class AsyncTaskMonitor {
    @Autowired
    AsyncTaskManager manager;
    private static Logger LOG = LoggerFactory.getLogger(AsyncTaskMonitor.class);

    @Around("execution(* com.spacemv.mv.api.task.service.AsyncTaskExecutor.*(..))")
    public void taskHandle(ProceedingJoinPoint pjp) {
        //获取taskId
        String taskId = pjp.getArgs()[1].toString();
        //获取任务信息
        TaskInfo taskInfo = manager.getTaskInfo(taskId);
        LOG.info("AsyncTaskMonitor is monitoring async task:{}", taskId);
        taskInfo.setStatus(TaskStatusEnum.RUNNING);
        manager.setTaskInfo(taskInfo);
        TaskStatusEnum status = null;
        try {
            pjp.proceed();
            status = TaskStatusEnum.SUCCESS;
        } catch (Throwable throwable) {
            status = TaskStatusEnum.FAILED;
            LOG.error("AsyncTaskMonitor:async task {} is failed.Error info:{}", taskId, throwable.getMessage());
        }
        taskInfo.setEndTime(new Date());
        taskInfo.setStatus(status);
        taskInfo.setTotalTime();
        manager.setTaskInfo(taskInfo);
    }
}

package com.spacemv.mv.geo.geoserver;

/**
 * Geo Server 信息
 */
public class GeoServerInfo {

    /**
     * Geo Server路径
     */
    private String serverUrl;

    /**
     * Geo Server用户名
     */
    private String userName;

    /**
     * Geo Server密码
     */
    private String password;

    /**
     * 构造方法
     * @param serverUrl Geo Server路径
     * @param userName Geo Server用户名
     * @param password Geo Server密码
     */
    public GeoServerInfo(String serverUrl, String userName, String password) {
        this.serverUrl = serverUrl;
        this.userName = userName;
        this.password = password;
    }

    /**
     * 获取 Geo Server路径
     * @return Geo Server路径
     */
    public String getServerUrl() {
        return serverUrl;
    }

    /**
     * 设置 Geo Server路径
     * @param serverUrl Geo Server路径
     */
    public void setServerUrl(String serverUrl) {
        this.serverUrl = serverUrl;
    }

    /**
     * 获取Geo Server用户名
     * @return Geo Server用户名
     */
    public String getUserName() {
        return userName;
    }

    /**
     * 设置Geo Server用户名
     * @param userName Geo Server用户名
     */
    public void setUserName(String userName) {
        this.userName = userName;
    }

    /**
     * 获取 Geo Server密码
     * @return Geo Server密码
     */
    public String getPassword() {
        return password;
    }

    /**
     * 设置 Geo Server密码
     * @param password Geo Server密码
     */
    public void setPassword(String password) {
        this.password = password;
    }
}

package com.spacemv.mv.geo.geoserver;

import com.spacemv.mv.exception.TXException;
import it.geosolutions.geoserver.rest.GeoServerRESTManager;
import it.geosolutions.geoserver.rest.GeoServerRESTPublisher;
import it.geosolutions.geoserver.rest.GeoServerRESTReader;
import it.geosolutions.geoserver.rest.decoder.RESTDataStoreList;
import it.geosolutions.geoserver.rest.manager.GeoServerRESTStoreManager;
import it.geosolutions.geoserver.rest.manager.GeoServerRESTStyleManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileNotFoundException;
import java.net.URL;
import java.util.List;

/**
 * GeoServer管理类
 */
public class GeoServerManager {
    private static final Logger LOGGER = LoggerFactory.getLogger(GeoServerManager.class);
    /**
     * GeoServer服务器信息
     */
    private GeoServerInfo geoServerInfo;

    /**
     * GeoServer Rest服务管理器
     */
    protected GeoServerRESTManager manager;

    /**
     * GeoServer发布器
     */
    protected GeoServerRESTPublisher publisher;

    /**
     * GeoServer数据读取器
     */
    protected GeoServerRESTReader reader;

    /**
     * GeoServer数据存储管理器
     */
    protected GeoServerRESTStoreManager storeManager;

    /**
     * GeoServer样式管理器
     */
    protected GeoServerRESTStyleManager styleManager;

    /**
     * 构造方法
     *
     * @param geoServerInfo GeoServer服务器信息
     * @throws TXException
     */
    public GeoServerManager(GeoServerInfo geoServerInfo) throws TXException {
        this.geoServerInfo = geoServerInfo;
        initialize();
    }

    /**
     * 初始化
     *
     * @throws TXException
     */
    private void initialize() throws TXException {
        try {
            URL u = new URL(this.geoServerInfo.getServerUrl());
            this.manager = new GeoServerRESTManager(u, this.geoServerInfo.getUserName(), this.geoServerInfo.getPassword());
            this.publisher = manager.getPublisher();
            this.reader = manager.getReader();
            this.storeManager = manager.getStoreManager();
            this.styleManager = manager.getStyleManager();
        } catch (Exception e) {
            LOGGER.error("GeoServerManager 初始化错误。", e);
            throw new TXException(e);
        }
    }

    /**
     * 发布tiff影像数据
     * @param workspace     工作空间名称
     * @param storeName     存储名称
     * @param coverageName  图层名称
     * @param filePath      tiff文件路径
     * @return boolean 是否发布成功
     */
    public boolean publish(String workspace, String storeName, String coverageName, String filePath) {
        try {
            //workspace是否存在,不存在则新建。
            List<String> workspacesList = reader.getWorkspaceNames();
            if (!workspacesList.contains(workspace)) {
                publisher.createWorkspace(workspace);
            }

            //store是否存在,不存在则新建并发布数据。
            RESTDataStoreList dataStoresList = reader.getDatastores(workspace);
            List<String> datastoreNameList = dataStoresList.getNames();
            if (!datastoreNameList.contains(storeName)) {
                File geotiff = new File(filePath);
                boolean result = publisher.publishGeoTIFF(workspace, storeName, coverageName, geotiff);
                return result;
            } else {
                LOGGER.error("数据发布失败,存储已经存在:" + storeName);
            }
        } catch (FileNotFoundException e) {
            LOGGER.error("数据发布失败,文件不存在:" + filePath, e);
        }
        return false;
    }
}

package com.spacemv.mv.geo.image;

import com.spacemv.mv.exception.TXException;
import com.spacemv.mv.geo.GeoUtils;
import com.spacemv.mv.geo.geoserver.GeoServerInfo;
import com.spacemv.mv.geo.geoserver.GeoServerManager;
import com.spacemv.mv.geo.models.Bound;
import com.spacemv.mv.geo.models.TiffImageMetaData;
import com.spacemv.mv.io.FileHelper;
import com.spacemv.mv.utils.NumberHelper;
import org.geotools.coverage.GridSampleDimension;
import org.geotools.coverage.grid.GridCoverage2D;
import org.geotools.coverage.grid.io.AbstractGridFormat;
import org.geotools.coverage.grid.io.GridCoverage2DReader;
import org.geotools.coverage.grid.io.GridFormatFinder;
import org.geotools.coverage.processing.CoverageProcessor;
import org.geotools.gce.geotiff.GeoTiffFormat;
import org.geotools.gce.geotiff.GeoTiffReader;
import org.geotools.geometry.Envelope2D;
import org.geotools.geometry.jts.JTS;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.referencing.CRS;
import org.geotools.util.factory.Hints;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.Envelope;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.Polygon;
import org.opengis.parameter.ParameterValueGroup;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.NoSuchAuthorityCodeException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.TransformException;

import java.io.File;

public class GeoTiffUtils {

    /***
     * 获取TIF文件的元数据
     * @param url geotif文件路径
     * @return TiffImageMetaData tif文件元数据,包括,图像边界坐标,图像波段等。
     * @throws TXException
     */
    public static TiffImageMetaData GetImageMetaData(String url) throws TXException {
        TiffImageMetaData result = new TiffImageMetaData();
        try {
            //String ImageUrl = url.replace("\\", "\\\\");
            File ImageFile = new File(url);
            GeoTiffReader reader = new GeoTiffReader(ImageFile);
            GridCoverage2D coverage = reader.read(null);
            result = getImageMetaData(reader, coverage);

        } catch (Exception e) {
            throw new TXException(e);
        }
        return result;
    }

    private static TiffImageMetaData getImageMetaData(GridCoverage2DReader reader, GridCoverage2D coverage) throws TXException {
        TiffImageMetaData result = new TiffImageMetaData();
        try {
            CoordinateReferenceSystem crs = coverage.getCoordinateReferenceSystem2D();
            Envelope2D coverageEnvelope = coverage.getEnvelope2D();

            double coverageMinX = coverageEnvelope.getMinX();
            double coverageMaxX = coverageEnvelope.getMaxX();
            double coverageMinY = coverageEnvelope.getMinY();
            double coverageMaxY = coverageEnvelope.getMaxY();

            String srs = CRS.lookupIdentifier(crs, true);
            CoordinateReferenceSystem sourceCRS = CRS.decode(srs, true);
            CoordinateReferenceSystem targetCRS = CRS.decode("EPSG:4326", true);
            MathTransform transform = CRS.findMathTransform(sourceCRS, targetCRS, false);
            Coordinate minCoordinate = new Coordinate();
            Coordinate maxCoordinate = new Coordinate();
            JTS.transform(new Coordinate(coverageMinX, coverageMinY), minCoordinate, transform);
            JTS.transform(new Coordinate(coverageMaxX, coverageMaxY), maxCoordinate, transform);

            Bound bound = new Bound(minCoordinate.getX(), maxCoordinate.getX(), minCoordinate.getY(), maxCoordinate.getY());
            result.setBound(bound);

            result.setArea(calcArea(bound));

            result.setResolutions(reader.getResolutionLevels()[0]);
            result.setCenter(GeoUtils.calcCenter(GeoUtils.createPolygon(bound)));

            GridSampleDimension[] dimensions = coverage.getSampleDimensions();
            if (dimensions != null) {
                for (GridSampleDimension dimension : dimensions) {
                    result.getBands().add(dimension.getDescription().toString());
                }
            }
        } catch (Exception e) {
            throw new TXException(e);
        }
        return result;
    }

    private static double calcArea(Bound bound) throws TransformException, FactoryException {
        CoordinateReferenceSystem sourceCRS = CRS.decode("EPSG:4326", true);
        CoordinateReferenceSystem targetCRS = CRS.decode("EPSG:3857", true);
        MathTransform transform = CRS.findMathTransform(sourceCRS, targetCRS, false);

        GeometryFactory factory = new GeometryFactory();
        Coordinate[] polygonCoordinates = new Coordinate[5];

        for (int i = 0; i < 5; i++) {
            polygonCoordinates[i] = new Coordinate();
        }

        JTS.transform(new Coordinate(bound.getMinX(), bound.getMaxY()), polygonCoordinates[0], transform);
        JTS.transform(new Coordinate(bound.getMaxX(), bound.getMaxY()), polygonCoordinates[1], transform);
        JTS.transform(new Coordinate(bound.getMaxX(), bound.getMinY()), polygonCoordinates[2], transform);
        JTS.transform(new Coordinate(bound.getMinX(), bound.getMinY()), polygonCoordinates[3], transform);
        JTS.transform(new Coordinate(bound.getMinX(), bound.getMaxY()), polygonCoordinates[4], transform);
        Polygon polygon = factory.createPolygon(polygonCoordinates);
        return NumberHelper.round(new Double(polygon.getArea()).floatValue() / (1000 * 1000f), 2);
    }

    /**
     * 剪裁TIFF影像文件
     *
     * @param sourceFilePath 源TIFF文件路径
     * @param outputFilePath 输出剪裁后的图片文件路径
<<<<<<< HEAD
     * @param bound          剪裁的边界
=======
     * @param bound          剪裁的边界 (传入的剪裁矩形框约定使用ESPG:4326,经纬度 )
>>>>>>> 19e97618d24f378e7e364702252ab8bcffa19517
     * @throws TXException
     */
    public static TiffImageMetaData cropCoverage(String sourceFilePath, String outputFilePath, Bound bound) throws TXException {
        TiffImageMetaData result = new TiffImageMetaData();
        try {
            File sourceFile = new File(sourceFilePath);
            AbstractGridFormat format = GridFormatFinder.findFormat(sourceFile);

            Hints hints = null;
            if (format instanceof GeoTiffFormat) {
                hints = new Hints(Hints.FORCE_LONGITUDE_FIRST_AXIS_ORDER, Boolean.TRUE);
            }

            GridCoverage2DReader gridReader = format.getReader(sourceFile, hints);
            GridCoverage2D gridCoverage = gridReader.read(null);
            CoordinateReferenceSystem targetCRS = gridCoverage.getCoordinateReferenceSystem();

            CoordinateReferenceSystem sourceCRS = CRS.decode("EPSG:4326", true);

            Bound targetBound = GeoUtils.transform(bound, sourceCRS, targetCRS);

            Envelope envelope = new ReferencedEnvelope(
                    targetBound.getMinX(), targetBound.getMaxX(), targetBound.getMinY(), targetBound.getMaxY(), targetCRS);

            GridCoverage2D finalCoverage = cropCoverage(gridCoverage, envelope);

            File tileFile = new File(outputFilePath);
            format.getWriter(tileFile).write(finalCoverage, null);

            result = getImageMetaData(gridReader, finalCoverage);

        } catch (Exception e) {
            throw new TXException(e);
        }
        return result;
    }

    private static GridCoverage2D cropCoverage(GridCoverage2D gridCoverage, Envelope envelope) {
        CoverageProcessor processor = CoverageProcessor.getInstance();
        final ParameterValueGroup param = processor.getOperation("CoverageCrop").getParameters();
        param.parameter("Source").setValue(gridCoverage);
        param.parameter("Envelope").setValue(envelope);

        return (GridCoverage2D) processor.doOperation(param);
    }
}



package com.spacemv.mv.geo;

import com.spacemv.mv.exception.TXException;
import com.spacemv.mv.geo.models.Bound;
import com.spacemv.mv.geo.models.Point;
import org.geotools.geometry.jts.JTS;
import org.geotools.referencing.CRS;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.Polygon;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.TransformException;

public class GeoUtils {
    public static Point calcCenter(Geometry geometry) {
        org.locationtech.jts.geom.Point center = geometry.getCentroid();
        Point result = new Point(center.getX(), center.getY());
        return result;
    }

    public static Polygon createPolygon(Bound bound) {
        GeometryFactory factory = new GeometryFactory();
        Coordinate[] polygonCoordinates = new Coordinate[5];
        polygonCoordinates[0] = new Coordinate(bound.getMinX(), bound.getMaxY());
        polygonCoordinates[1] = new Coordinate(bound.getMaxX(), bound.getMaxY());
        polygonCoordinates[2] = new Coordinate(bound.getMaxX(), bound.getMinY());
        polygonCoordinates[3] = new Coordinate(bound.getMinX(), bound.getMinY());
        polygonCoordinates[4] = new Coordinate(bound.getMinX(), bound.getMaxY());
        Polygon polygon = factory.createPolygon(polygonCoordinates);
        return polygon;
    }

    public static Bound transform(Bound bound, CoordinateReferenceSystem sourceCRS, CoordinateReferenceSystem targetCRS) throws TXException {
        try {
            String sourceSRS = CRS.lookupIdentifier(sourceCRS,true);
            String targetSRS = CRS.lookupIdentifier(targetCRS,true);

            //两个坐标系是一样的,不需要变换
            if (sourceSRS.equalsIgnoreCase(targetSRS)) {
                return bound;
            }

            MathTransform transform = CRS.findMathTransform(sourceCRS, targetCRS);
            Coordinate minCoordinate = new Coordinate();
            Coordinate maxCoordinate = new Coordinate();
            JTS.transform(new Coordinate(bound.getMinX(), bound.getMinY()), minCoordinate, transform);
            JTS.transform(new Coordinate(bound.getMaxX(), bound.getMaxY()), maxCoordinate, transform);

            Bound boundResult = new Bound(minCoordinate.getX(), maxCoordinate.getX(), minCoordinate.getY(), maxCoordinate.getY());
            return boundResult;
        } catch (Exception e) {
            throw new TXException(e);
        }
    }
}

package com.spacemv.mv.io;


import java.io.File;
import java.util.UUID;

public class FileHelper {
    public static void checkOrCreateFolder(String path, boolean includeSelf) {
        File file = new File(path);
        if (file.exists()) {
            return;
        }

        if (!includeSelf) {
            file.getParentFile().mkdirs();
        } else {
            file.mkdirs();
        }
    }

    /**
     * 获取文件扩展名
     *
     * @param filePath 文件名
     * @return 返回文件扩展名(带前面的点)
     */
    public static String getFileName(String filePath) {
        if (filePath == null) {
            return null;
        }
        File file = new File(filePath);
        return file.getName();
    }

    /**
     * 获取文件扩展名
     *
     * @param fileName 文件名
     * @return 返回文件扩展名(带前面的点)
     */
    public static String getFileExtensionName(String fileName) {
        if (fileName == null) {
            return null;
        }
        int index = fileName.lastIndexOf(".");
        if (index == -1) {    // 无后缀
            return null;
        } else {                    // 存在后缀
            return fileName.substring(index, fileName.length());
        }
    }

    public static String randomFileName(String fileExt) {
        String fileName = UUID.randomUUID().toString().replace("-", "") + fileExt;
        return fileName;
    }

    public static String combine(String basePath, String... paths) {
        if (basePath.endsWith(File.separator)) {
            basePath = basePath.substring(0, basePath.lastIndexOf(File.separator));
        }
        StringBuilder builder = new StringBuilder();
        builder.append(basePath);
        for (String pathName : paths) {
            if (!pathName.startsWith(File.separator)) {
                builder.append(File.separator);
            }
            builder.append(pathName);
        }
        return builder.toString();
    }

    /**
     * 文件改名
     *
     * @param fileName          源文件名(带扩展名)
     * @param newNameWhitoutExt 新文件名(不带扩展名)
     * @return 新文件名(带扩展名)
     */
    public static String reName(String fileName, String newNameWhitoutExt) {
        String extensionName = getFileExtensionName(fileName);
        String newName = newNameWhitoutExt;
        if (extensionName != null) {
            newName += extensionName;
        }
        return newName;
    }

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值