// eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-nocheck -- OL 패키지 제거됨 (기능 미사용, Session G 패스) /** * 원(Circle) 리사이즈 커스텀 인터랙션 * * 원은 64점 Polygon으로 저장되어 있으므로, 테두리 드래그 시 * 중심에서 드래그 좌표까지의 거리를 새 반지름으로 계산하고 * fromCircle()로 Polygon을 재생성. * * 감지 방식: 개별 꼭짓점이 아닌, 중심~포인터 거리와 반지름 비교 (테두리 전체 감지) */ import PointerInteraction from 'ol/interaction/Pointer'; import { fromCircle } from 'ol/geom/Polygon'; import OlCircle from 'ol/geom/Circle'; import type Feature from 'ol/Feature'; import type { Polygon } from 'ol/geom'; import type MapBrowserEvent from 'ol/MapBrowserEvent'; import type OlMap from 'ol/Map'; const PIXEL_TOLERANCE = 16; const MIN_RADIUS = 100; // 최소 반지름 (미터) interface CircleResizeInteractionOptions { feature: Feature; center: [number, number]; // EPSG:3857 [x, y] onResize?: (feature: Feature) => void; } interface HandleResult { cursor: string; } export default class CircleResizeInteraction extends PointerInteraction { private feature_: Feature; private center_: [number, number]; private onResize_: ((feature: Feature) => void) | null; private dragging_: boolean; constructor(options: CircleResizeInteractionOptions) { super({ handleDownEvent: (evt: MapBrowserEvent) => CircleResizeInteraction.prototype._handleDown.call(this, evt), handleDragEvent: (evt: MapBrowserEvent) => CircleResizeInteraction.prototype._handleDrag.call(this, evt), handleUpEvent: () => CircleResizeInteraction.prototype._handleUp.call(this), }); this.feature_ = options.feature; this.center_ = options.center; // EPSG:3857 [x, y] this.onResize_ = options.onResize || null; this.dragging_ = false; } /** 중심~포인터 픽셀 거리와 표시 반지름 비교 */ private _isNearEdge(map: OlMap, pixel: number[]): boolean { const centerPixel = map.getPixelFromCoordinate(this.center_); const coords = this.feature_.getGeometry()!.getCoordinates()[0]; const edgePixel = map.getPixelFromCoordinate(coords[0]); const radiusPixels = Math.hypot( edgePixel[0] - centerPixel[0], edgePixel[1] - centerPixel[1], ); const distFromCenter = Math.hypot( pixel[0] - centerPixel[0], pixel[1] - centerPixel[1], ); return Math.abs(distFromCenter - radiusPixels) < PIXEL_TOLERANCE; } private _handleDown(evt: MapBrowserEvent): boolean { if (this._isNearEdge(evt.map, evt.pixel as unknown as number[])) { this.dragging_ = true; return true; } return false; } private _handleDrag(evt: MapBrowserEvent): void { if (!this.dragging_) return; const coord = evt.coordinate; const dx = coord[0] - this.center_[0]; const dy = coord[1] - this.center_[1]; const newRadius = Math.max(Math.sqrt(dx * dx + dy * dy), MIN_RADIUS); const circleGeom = new OlCircle(this.center_, newRadius); const polyGeom = fromCircle(circleGeom, 64); this.feature_.setGeometry(polyGeom); } private _handleUp(): boolean { if (this.dragging_) { this.dragging_ = false; if (this.onResize_) this.onResize_(this.feature_); return true; } return false; } /** 외부에서 center 업데이트 (Translate 후) */ setCenter(center: [number, number]): void { this.center_ = center; } /** * 호버 감지: 픽셀이 리사이즈 핸들(테두리) 위인지 확인 */ isOverHandle(map: OlMap, pixel: number[]): HandleResult | null { if (this._isNearEdge(map, pixel)) { return { cursor: 'nesw-resize' }; } return null; } }