多边形外的点到多边形边界最近点的坐标
package com.ruoyi.system.utils;
import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSON;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.system.domain.TbRail;
import com.ruoyi.system.domain.TbRailPoint;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Param;
import java.awt.geom.Point2D;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
@Slf4j
public class RailUtil {
public static TbRailPoint findClosestPointOnPolygonBoundary(List<Point2D.Double> railPointList, TbRailPoint point){
TbRailPoint rtn = new TbRailPoint();
rtn.setLongitude(BigDecimal.ZERO);
rtn.setLatitude(BigDecimal.ZERO);
Point2D.Double closestPointOnPolygonBoundary = findClosestPointOnPolygonBoundary(railPointList, new Point2D.Double(point.getLongitude().doubleValue(), point.getLatitude().doubleValue()));
if (Objects.isNull(closestPointOnPolygonBoundary)){
return rtn;
}
rtn.setLongitude(BigDecimal.valueOf(closestPointOnPolygonBoundary.x));
rtn.setLatitude(BigDecimal.valueOf(closestPointOnPolygonBoundary.y));
return rtn;
}
public static Point2D.Double findClosestPointOnPolygonBoundary(List<Point2D.Double> polygonVertices, Point2D.Double externalPoint) {
double minDistance = Double.MAX_VALUE;
Point2D.Double closestPoint = null;
for (int i = 0; i < polygonVertices.size(); i++) {
Point2D.Double p1 = polygonVertices.get(i);
Point2D.Double p2 = polygonVertices.get((i + 1) % polygonVertices.size());
Point2D.Double nearestOnEdge = findNearestPointOnLineSegment(p1, p2, externalPoint);
double distance = distance(externalPoint, nearestOnEdge);
if (distance < minDistance) {
minDistance = distance;
closestPoint = nearestOnEdge;
}
}
return closestPoint;
}
public static double distance(Point2D.Double p1, Point2D.Double p2) {
return Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2));
}
public static Point2D.Double findNearestPointOnLineSegment(Point2D.Double p, Point2D.Double q, Point2D.Double r) {
double l2 = distance(p, q) * distance(p, q);
if (l2 == 0.0) return p;
double t = ((r.x - p.x) * (q.x - p.x) + (r.y - p.y) * (q.y - p.y)) / l2;
t = Math.max(0, Math.min(1, t));
Point2D.Double projection = new Point2D.Double();
projection.x = p.x + t * (q.x - p.x);
projection.y = p.y + t * (q.y - p.y);
return projection;
}
public static Point2D.Double perpendicularIntersection(Point2D.Double point, Point2D.Double lineStart, Point2D.Double lineEnd) {
double dx1 = lineEnd.x - lineStart.x;
double dy1 = lineEnd.y - lineStart.y;
double dx2 = point.x - lineStart.x;
double dy2 = point.y - lineStart.y;
double dotProduct = dx1 * dx2 + dy1 * dy2;
if (dotProduct <= 0) {
return lineStart;
}
double lineLengthSquared = dx1 * dx1 + dy1 * dy1;
if (dotProduct >= lineLengthSquared) {
return lineEnd;
}
double projLength = dotProduct / lineLengthSquared;
double closestX = lineStart.x + dx1 * projLength;
double closestY = lineStart.y + dy1 * projLength;
return new Point2D.Double(closestX,closestY);
}
public static TbRailPoint findClosestPointOnPolygonBoundary2(List<Point2D.Double> polygonVertices, TbRailPoint point) {
TbRailPoint rtn = new TbRailPoint();
rtn.setLongitude(BigDecimal.ZERO);
rtn.setLatitude(BigDecimal.ZERO);
Point2D.Double externalPoint = new Point2D.Double(point.getLongitude().doubleValue(), point.getLatitude().doubleValue());
if (CollUtil.isEmpty(polygonVertices) || polygonVertices.size()!=4){
log.info("【3D围栏维护】边界异常 {} ", JSON.toJSONString(polygonVertices));
return rtn;
}
Point2D.Double p1 = perpendicularIntersection(externalPoint, polygonVertices.get(0), polygonVertices.get(1));
Point2D.Double p2 = perpendicularIntersection(externalPoint, polygonVertices.get(1), polygonVertices.get(2));
Point2D.Double p3 = perpendicularIntersection(externalPoint, polygonVertices.get(2), polygonVertices.get(3));
Point2D.Double p4 = perpendicularIntersection(externalPoint, polygonVertices.get(3), polygonVertices.get(0));
ArrayList<Point2D.Double> nearPts = CollUtil.newArrayList(p1, p2, p3, p4);
nearPts.addAll(polygonVertices);
double minDis = distance(externalPoint, p1);
Point2D.Double nearest = p1;
for (Point2D.Double nearPt : nearPts) {
double distance = distance(externalPoint, p2);
if (distance<minDis){
minDis = distance;
nearest = nearPt;
}
}
rtn.setLongitude(BigDecimal.valueOf(nearest.x));
rtn.setLatitude(BigDecimal.valueOf(nearest.y));
return rtn;
}
public static void main(String[] args) {
Point2D.Double point = new Point2D.Double(-1, -1);
Point2D.Double intersection = perpendicularIntersection(point, new Point2D.Double(0.0, 0.0), new Point2D.Double(2.0, 2.0));
System.out.println("Intersection point: (" + intersection.x + ", " + intersection.y + ")");
}
}