Skip to content

Commit 3738330

Browse files
authored
[UNI-215] fix : 구글 구면좌표계 제거 및 interpolate 함수 및 distance 함수 구현 (#118)
1 parent 7baf013 commit 3738330

File tree

10 files changed

+78
-77
lines changed

10 files changed

+78
-77
lines changed

uniro_frontend/src/hooks/useMap.tsx

+2-4
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,19 @@ const useMap = (mapOptions?: google.maps.MapOptions) => {
77
const [overlay, setOverlay] = useState<google.maps.OverlayView | null>(null);
88
const [AdvancedMarker, setAdvancedMarker] = useState<typeof google.maps.marker.AdvancedMarkerElement | null>(null);
99
const [Polyline, setPolyline] = useState<typeof google.maps.Polyline | null>(null);
10-
const [spherical, setSpherical] = useState<typeof google.maps.geometry.spherical | null>(null);
1110
const [mapLoaded, setMapLoaded] = useState<boolean>(false);
1211

1312
useEffect(() => {
1413
if (!mapRef.current) return;
1514

1615
const initMap = async () => {
1716
try {
18-
const { map, overlay, AdvancedMarkerElement, Polyline, spherical } = await initializeMap(
17+
const { map, overlay, AdvancedMarkerElement, Polyline } = await initializeMap(
1918
mapRef.current,
2019
mapOptions,
2120
);
2221
setMap(map);
2322
setOverlay(overlay);
24-
setSpherical(() => spherical);
2523
setAdvancedMarker(() => AdvancedMarkerElement);
2624
setPolyline(() => Polyline);
2725
setMapLoaded(true);
@@ -39,7 +37,7 @@ const useMap = (mapOptions?: google.maps.MapOptions) => {
3937
};
4038
}, []);
4139

42-
return { mapRef, map, overlay, AdvancedMarker, Polyline, spherical, mapLoaded };
40+
return { mapRef, map, overlay, AdvancedMarker, Polyline, mapLoaded };
4341
};
4442

4543
export default useMap;

uniro_frontend/src/map/initializer/googleMapInitializer.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,13 @@ interface MapWithOverlay {
77
overlay: google.maps.OverlayView | null;
88
AdvancedMarkerElement: typeof google.maps.marker.AdvancedMarkerElement;
99
Polyline: typeof google.maps.Polyline;
10-
spherical: typeof google.maps.geometry.spherical;
1110
}
1211

1312
export const initializeMap = async (
1413
mapElement: HTMLElement | null,
1514
mapOptions?: google.maps.MapOptions,
1615
): Promise<MapWithOverlay> => {
17-
const { Map, OverlayView, AdvancedMarkerElement, Polyline, spherical } = await loadGoogleMapsLibraries();
16+
const { Map, OverlayView, AdvancedMarkerElement, Polyline } = await loadGoogleMapsLibraries();
1817

1918
if (!mapElement) {
2019
throw new Error("Map Element is not provided");
@@ -45,5 +44,5 @@ export const initializeMap = async (
4544
overlay.onRemove = function () {};
4645
overlay.setMap(map);
4746

48-
return { map, overlay, AdvancedMarkerElement, Polyline, spherical };
47+
return { map, overlay, AdvancedMarkerElement, Polyline };
4948
};

uniro_frontend/src/map/loader/googleMapLoader.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,8 @@ const GoogleMapsLoader = new Loader({
99
const loadGoogleMapsLibraries = async () => {
1010
const { Map, OverlayView, Polyline } = await GoogleMapsLoader.importLibrary("maps");
1111
const { AdvancedMarkerElement } = await GoogleMapsLoader.importLibrary("marker");
12-
const { spherical } = await GoogleMapsLoader.importLibrary("geometry");
1312

14-
return { Map, OverlayView, AdvancedMarkerElement, Polyline, spherical };
13+
return { Map, OverlayView, AdvancedMarkerElement, Polyline };
1514
};
1615

1716
export default loadGoogleMapsLibraries;

uniro_frontend/src/pages/reportRisk.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ interface reportMarkerTypes extends MarkerTypesWithElement {
3333
}
3434

3535
export default function ReportRiskPage() {
36-
const { map, mapRef, AdvancedMarker, Polyline, spherical } = useMap({ zoom: 18, minZoom: 17 });
36+
const { map, mapRef, AdvancedMarker, Polyline } = useMap({ zoom: 18, minZoom: 17 });
3737

3838
const [reportMarker, setReportMarker] = useState<reportMarkerTypes>();
3939

@@ -166,12 +166,12 @@ export default function ReportRiskPage() {
166166
});
167167

168168
const point = LatLngToLiteral(e.latLng);
169-
const { edge: nearestEdge, point: nearestPoint } = findNearestSubEdge(spherical, edges, point);
169+
const { edge: nearestEdge, point: nearestPoint } = findNearestSubEdge(edges, point);
170170

171171
const newReportMarker = createAdvancedMarker(
172172
AdvancedMarker,
173173
map,
174-
centerCoordinate(spherical, nearestEdge.node1, nearestEdge.node2),
174+
centerCoordinate(nearestEdge.node1, nearestEdge.node2),
175175
createMarkerElement({
176176
type: Markers.REPORT,
177177
className: "translate-routemarker",

uniro_frontend/src/pages/reportRoute.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ type SelectedMarkerTypes = {
3838
export default function ReportRoutePage() {
3939
const navigate = useNavigate();
4040
const queryClient = useQueryClient();
41-
const { map, mapRef, AdvancedMarker, Polyline, spherical } = useMap({ zoom: 18, minZoom: 17 });
41+
const { map, mapRef, AdvancedMarker, Polyline } = useMap({ zoom: 18, minZoom: 17 });
4242
const originPoint = useRef<{ point: Node; element: AdvancedMarker } | undefined>();
4343
const [newPoints, setNewPoints] = useState<{ element: AdvancedMarker | null; coords: (Coord | Node)[] }>({
4444
element: null,
@@ -241,7 +241,7 @@ export default function ReportRoutePage() {
241241
const lastPoint = newPoints.coords[newPoints.coords.length - 1] as Node | Coord;
242242

243243
for (const edge of edges) {
244-
const subNode = createSubNodes(spherical, new Polyline({ path: edge })).slice(0, -1);
244+
const subNode = createSubNodes(new Polyline({ path: edge })).slice(0, -1);
245245
subNodes.push(...subNode);
246246
}
247247

@@ -288,7 +288,7 @@ export default function ReportRoutePage() {
288288
});
289289

290290
const point = LatLngToLiteral(e.latLng);
291-
const { edge: nearestEdge, point: nearestPoint } = findNearestSubEdge(spherical, edges, point);
291+
const { edge: nearestEdge, point: nearestPoint } = findNearestSubEdge(edges, point);
292292

293293
const tempWaypointMarker = createAdvancedMarker(
294294
AdvancedMarker,
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,6 @@
11
import { Coord } from "../../data/types/coord";
2-
import { LatLngToLiteral } from "./coordinateTransform";
2+
import { interpolate } from "../interpolate";
33

4-
export default function centerCoordinate(
5-
spherical: typeof google.maps.geometry.spherical | null,
6-
point1: Coord,
7-
point2: Coord,
8-
): Coord {
9-
if (spherical === null) {
10-
return {
11-
lat: (point1.lat + point2.lat) / 2,
12-
lng: (point1.lng + point2.lng) / 2,
13-
};
14-
} else {
15-
return LatLngToLiteral(spherical.interpolate(point1, point2, 0.5));
16-
}
4+
export default function centerCoordinate(point1: Coord, point2: Coord): Coord {
5+
return interpolate(point1, point2, 0.5);
176
}
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,26 @@
1-
/** 하버사인 공식 */
2-
export default function distance(
3-
spherical: typeof google.maps.geometry.spherical | null,
4-
point1: google.maps.LatLngLiteral,
5-
point2: google.maps.LatLngLiteral,
6-
): number {
7-
const { lat: lat1, lng: lng1 } = point1;
8-
const { lat: lat2, lng: lng2 } = point2;
9-
10-
if (spherical === null) {
11-
const R = 6371000;
12-
const toRad = (angle: number) => (angle * Math.PI) / 180;
1+
import { Coord } from "../../data/types/coord";
132

14-
const dLat = toRad(lat2 - lat1);
15-
const dLon = toRad(lng2 - lng1);
3+
/** 하버사인 공식 */
4+
export default function distance(point1: Coord, point2: Coord): number {
5+
const R = 6378137;
6+
const { lat: lat_a, lng: lng_a } = point1;
7+
const { lat: lat_b, lng: lng_b } = point2;
168

17-
const a = Math.sin(dLat / 2) ** 2 + Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) * Math.sin(dLon / 2) ** 2;
18-
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
9+
const rad_lat_a = toRad(lat_a);
10+
const rad_lng_a = toRad(lng_a);
11+
const rad_lat_b = toRad(lat_b);
12+
const rad_lng_b = toRad(lng_b);
1913

20-
return R * c;
21-
}
22-
return spherical.computeLength([point1, point2]);
14+
return (
15+
R *
16+
2 *
17+
Math.asin(
18+
Math.sqrt(
19+
Math.pow(Math.sin((rad_lat_a - rad_lat_b) / 2), 2) +
20+
Math.cos(rad_lat_a) * Math.cos(rad_lat_b) * Math.pow(Math.sin((rad_lng_a - rad_lng_b) / 2), 2),
21+
),
22+
)
23+
);
2324
}
25+
26+
const toRad = (angle: number) => (angle * Math.PI) / 180;
+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { Coord } from "../data/types/coord";
2+
3+
function toRad(deg: number) {
4+
return (deg * Math.PI) / 180;
5+
}
6+
function toDeg(rad: number) {
7+
return (rad * 180) / Math.PI;
8+
}
9+
10+
export function interpolate(point1: Coord, point2: Coord, fraction: number): Coord {
11+
const lat1 = toRad(point1.lat);
12+
const lng1 = toRad(point1.lng);
13+
14+
const lat2 = toRad(point2.lat);
15+
const lng2 = toRad(point2.lng);
16+
17+
const angle = Math.acos(Math.sin(lat1) * Math.sin(lat2) + Math.cos(lat1) * Math.cos(lat2) * Math.cos(lng2 - lng1));
18+
19+
const sinAngle = Math.sin(angle);
20+
21+
const A = Math.sin((1 - fraction) * angle) / sinAngle;
22+
const B = Math.sin(fraction * angle) / sinAngle;
23+
24+
const x = A * Math.cos(lat1) * Math.cos(lng1) + B * Math.cos(lat2) * Math.cos(lng2);
25+
const y = A * Math.cos(lat1) * Math.sin(lng1) + B * Math.cos(lat2) * Math.sin(lng2);
26+
const z = A * Math.sin(lat1) + B * Math.sin(lat2);
27+
28+
const interpolatedLat = Math.atan2(z, Math.sqrt(x * x + y * y));
29+
const interpolatedLng = Math.atan2(y, x);
30+
31+
return {
32+
lat: toDeg(interpolatedLat),
33+
lng: toDeg(interpolatedLng),
34+
};
35+
}

uniro_frontend/src/utils/polylines/createSubnodes.ts

+4-25
Original file line numberDiff line numberDiff line change
@@ -2,43 +2,22 @@ import { EDGE_LENGTH } from "../../constant/edge";
22
import { Coord } from "../../data/types/coord";
33
import { LatLngToLiteral } from "../coordinates/coordinateTransform";
44
import distance from "../coordinates/distance";
5+
import { interpolate } from "../interpolate";
56

67
/** 구면 보간 없이 계산한 결과 */
7-
export default function createSubNodes(
8-
spherical: typeof google.maps.geometry.spherical | null,
9-
polyLine: google.maps.Polyline,
10-
): Coord[] {
8+
export default function createSubNodes(polyLine: google.maps.Polyline): Coord[] {
119
const paths = polyLine.getPath();
1210
const [startNode, endNode] = paths.getArray().map((el) => LatLngToLiteral(el));
1311

14-
const length = distance(spherical, startNode, endNode);
15-
console.log("구면 보간", length);
12+
const length = distance(startNode, endNode);
1613

1714
const subEdgesCount = Math.ceil(length / EDGE_LENGTH);
1815

1916
const subNodes: Coord[] = [startNode];
2017

21-
if (spherical === null || !spherical) {
22-
const interval = {
23-
lat: (endNode.lat - startNode.lat) / subEdgesCount,
24-
lng: (endNode.lng - startNode.lng) / subEdgesCount,
25-
};
26-
27-
for (let i = 1; i < subEdgesCount; i++) {
28-
const subNode: Coord = {
29-
lat: startNode.lat + interval.lat * i,
30-
lng: startNode.lng + interval.lng * i,
31-
};
32-
subNodes.push(subNode);
33-
}
34-
35-
subNodes.push(endNode);
36-
return subNodes;
37-
}
38-
3918
for (let i = 1; i < subEdgesCount; i++) {
4019
const fraction = i / subEdgesCount;
41-
subNodes.push(LatLngToLiteral(spherical.interpolate(startNode, endNode, fraction)));
20+
subNodes.push(interpolate(startNode, endNode, fraction));
4221
}
4322

4423
subNodes.push(endNode);

uniro_frontend/src/utils/polylines/findNearestEdge.ts

+3-4
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import centerCoordinate from "../coordinates/centerCoordinate";
55
import distance from "../coordinates/distance";
66

77
export default function findNearestSubEdge(
8-
spherical: typeof google.maps.geometry.spherical | null,
98
edges: CoreRoute[],
109
point: Coord,
1110
): {
@@ -16,7 +15,7 @@ export default function findNearestSubEdge(
1615
.map((edge) => {
1716
return {
1817
edge,
19-
distance: distance(spherical, point, centerCoordinate(spherical, edge.node1, edge.node2)),
18+
distance: distance(point, centerCoordinate(edge.node1, edge.node2)),
2019
};
2120
})
2221
.sort((a, b) => {
@@ -26,8 +25,8 @@ export default function findNearestSubEdge(
2625
const nearestEdge = edgesWithDistance[0].edge;
2726

2827
const { node1, node2 } = nearestEdge;
29-
const distance0 = distance(spherical, node1, point);
30-
const distance1 = distance(spherical, node2, point);
28+
const distance0 = distance(node1, point);
29+
const distance1 = distance(node2, point);
3130
const nearestPoint = distance0 > distance1 ? node2 : node1;
3231

3332
return {

0 commit comments

Comments
 (0)