From 06ab6ee75f938cab682fbddbd9dd4f31b793d0ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?dhji=28=EC=A7=80=EB=8C=80=ED=95=9C=29?= Date: Fri, 15 Mar 2024 14:14:30 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20websocket=20client=20=ED=98=B8=EC=B6=9C?= =?UTF-8?q?=EC=8B=9C=20parameter=20=EC=B6=94=EA=B0=80=20=EB=B2=94=EC=9C=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://www.notion.so/PAV-KAC-websocket-client-schedule-call-25d5df23be114f8997aee9b2b51697f4?pvs=4 --- .../kac/websocket/service/ControlService.java | 15 ++- .../java/kr/co/palnet/kac/util/CoordUtil.java | 125 ++++++++++++++++++ http-client/http/ws.http | 13 +- 3 files changed, 148 insertions(+), 5 deletions(-) diff --git a/app/kac-websocket-app/src/main/java/kr/co/palnet/kac/websocket/service/ControlService.java b/app/kac-websocket-app/src/main/java/kr/co/palnet/kac/websocket/service/ControlService.java index 1ba9795..3d0b405 100644 --- a/app/kac-websocket-app/src/main/java/kr/co/palnet/kac/websocket/service/ControlService.java +++ b/app/kac-websocket-app/src/main/java/kr/co/palnet/kac/websocket/service/ControlService.java @@ -2,13 +2,17 @@ package kr.co.palnet.kac.websocket.service; import kr.co.palnet.kac.common.model.common.DroneControlDto; import kr.co.palnet.kac.common.model.common.DroneDto; +import kr.co.palnet.kac.util.CoordUtil; import kr.co.palnet.kac.websocket.core.model.BoundaryCoordinates; import kr.co.palnet.kac.websocket.core.storage.ControlStorage; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; -import java.util.*; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; @Slf4j @RequiredArgsConstructor @@ -16,17 +20,22 @@ import java.util.*; public class ControlService { public List getList(List coordinatesList) { + List polygon = coordinatesList.stream().map(bc -> CoordUtil.Coordinates.builder().x(bc.getLon()).y(bc.getLat()).build()).toList(); ControlStorage controlStorage = ControlStorage.getInstance(); List controlDtoList = controlStorage.getList(); if (controlDtoList == null || controlDtoList.isEmpty()) return new ArrayList<>(); - controlDtoList.sort(Comparator.reverseOrder()); + List result = controlDtoList.stream().filter(controlDto -> +// CoordUtil.isInsidePolygon(polygon, CoordUtil.Coordinates.builder().x(controlDto.getLon()).y(controlDto.getLat()).build()) + CoordUtil.isInsideRectangle(polygon, CoordUtil.Coordinates.builder().x(controlDto.getLon()).y(controlDto.getLat()).build()) + ).sorted(Comparator.reverseOrder()).toList(); - return controlDtoList; + return result; } + public DroneControlDto dronDtoToControlDtoConvert(DroneDto dronDto) { ControlStorage controlCache = ControlStorage.getInstance(); diff --git a/common/util/src/main/java/kr/co/palnet/kac/util/CoordUtil.java b/common/util/src/main/java/kr/co/palnet/kac/util/CoordUtil.java index 34872d7..7595f5e 100644 --- a/common/util/src/main/java/kr/co/palnet/kac/util/CoordUtil.java +++ b/common/util/src/main/java/kr/co/palnet/kac/util/CoordUtil.java @@ -4,7 +4,11 @@ import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import java.util.List; + +@Slf4j public class CoordUtil { @@ -15,8 +19,13 @@ public class CoordUtil { public static class Coordinates { public double x; public double y; + + public String toString() { + return String.format("[x:: %s, y:: %s]", x, y); + } } + // 좌표 두 거리간의 거리 public static double calculateDistance(Coordinates c1, Coordinates c2) { double earthRadius = 6371; // 지구의 반지름 (단위: km) @@ -36,4 +45,120 @@ public class CoordUtil { return distance; } + + // 특정 좌표가 다각형의 내부에 포함 여부 확인 + public static boolean isInsidePolygon(List polygon, Coordinates point) { + if (polygon.size() < 3) { + log.warn("polygon size more then 3 point."); + return false; + } + int intersectCount = 0; + for (int i = 0; i < polygon.size(); i++) { + Coordinates start = polygon.get(i); + Coordinates end = polygon.get((i + 1) % polygon.size()); + + + // [무시] 주어진 좌표로 부터 선분이 좌측에 있을 경우 제외한다. + if (point.x > Math.max(start.x, end.x)) { +// log.info(">>> x pass -- px: {}, sx: {}, ex: {}", point.x, start.x, end.x); + continue; + } + // [무시] 주어진 좌표로 부터 선분이 위에 있거나 아래 있을 경우 교차 되지 않으므로 제외한다. + if (point.y < Math.min(start.y, end.y) || point.y > Math.max(start.y, end.y)) { +// log.info(">>> y pass -- py: {}, sy: {}, ey: {}", point.y, start.y, end.y); + continue; + } + + // [선분위] 수직 선분 위에 주어진 좌표가 존재할 경우 + if (point.x == start.x && point.x == end.x) { +// log.info("[선분위] 수직 선분 위에 주어진 좌표가 존재할 경우 {} - {} - {}", point, start, end); + return true; + } + + // 수평 선분 + if (start.y == end.y) { + if (point.y == start.y && point.x >= Math.min(start.x, start.y) && point.x <= Math.max(start.x, end.x)) { + // [선분위] 수평 선분 위에 주어진 좌표가 존재할 경우 +// log.info("[선분위] 수평 선분 위에 주어진 좌표가 존재할 경우 {} - {} - {}", point, start, end); + return true; + } else { + // [무시] 그외 수평 선분은 제외 + continue; + } + } + // [무시] 선분의 끝점이 주어진 좌표 y와 동일할 경우 아래에 있는 선분은 제외 + if (point.y == Math.max(start.y, end.y)) { +// log.info("[무시] 선분의 끝점이 주어진 좌표 y와 동일할 경우 아래에 있는 선분은 제외"); + continue; + } + + double x = (point.y - start.y) * (end.x - start.x) / (end.y - start.y) + start.x; + + // [선분위] 주어진 좌표가 선분 위에 존재할 경우 + if (x == point.x) { +// log.info("[선분위] 주어진 좌표가 선분 위에 존재할 경우 {} - {} - {}", point, start, end); + return true; + } + + if (x > point.x) { + intersectCount++; + } + } + return intersectCount % 2 == 1; + } + + // 직사각형 내부 포함 여부 + public static boolean isInsideRectangle(List polygon, Coordinates point) { + if (polygon == null || polygon.size() != 4) { + log.warn("polygon size only 4 point"); + return false; + } + + double maxX = polygon.getFirst().getX(); + double minX = polygon.getFirst().getX(); + ; + double maxY = polygon.getFirst().getY(); + ; + double minY = polygon.getFirst().getY(); + ; + + for (int i = 1; i < polygon.size(); i++) { + if (polygon.get(i).getX() > maxX) { + maxX = polygon.get(i).getX(); + } + if (polygon.get(i).getX() < minX) { + minX = polygon.get(i).getX(); + } + if (polygon.get(i).getY() > maxY) { + maxY = polygon.get(i).getY(); + } + if (polygon.get(i).getY() < minY) { + minY = polygon.get(i).getY(); + } + } + + if (point.getX() >= minX && point.getX() <= maxX && point.getY() >= minY && point.getY() <= maxY) { + return true; + } + return false; + } + +// public static void main(String[] args) { +// List polygon = new ArrayList<>(); +// polygon.add(Coordinates.builder().x(15.0).y(10.0).build()); +// polygon.add(Coordinates.builder().x(10.0).y(15.0).build()); +// polygon.add(Coordinates.builder().x(10.0).y(20.0).build()); +// polygon.add(Coordinates.builder().x(15.0).y(20.0).build()); +// polygon.add(Coordinates.builder().x(20.0).y(15.0).build()); +// polygon.add(Coordinates.builder().x(15.0).y(15.0).build()); +// +// for (int i = 21; i >= 9; i--) { +// for (int j = 9; j <= 21; j++) { +// Coordinates p = Coordinates.builder().x(j).y(i).build(); +// boolean flag = CoordUtil.isInsidePolygon(polygon, p); +// System.out.printf("%s ", flag ? "◼︎" : "◻︎"); +// } +// System.out.println(); +// } +// } } diff --git a/http-client/http/ws.http b/http-client/http/ws.http index 9024aa6..04623e1 100644 --- a/http-client/http/ws.http +++ b/http-client/http/ws.http @@ -6,8 +6,17 @@ WEBSOCKET {{wsHost}}/ws "type": "CURRENT_DRONE", "body": [ { - "lat": 111.000, - "lon": 222.22 + "lat": 35.36, + "lon": 126.6 + },{ + "lat": 36.46, + "lon": 126.6 + },{ + "lat": 36.46, + "lon": 127.77 + },{ + "lat": 35.36, + "lon": 127.77 } ] }