@mint-ui/map 1.2.0-test.34 → 1.2.0-test.35

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,47 +3,161 @@ import { MintMapController } from "../../MintMapController";
3
3
  import { KonvaCanvasData } from "./types";
4
4
  /**
5
5
  * 폴리곤 offset 계산
6
+ *
7
+ * GeoJSON MultiPolygon 형식의 위경도 좌표를 화면 픽셀 좌표로 변환합니다.
8
+ *
9
+ * @param polygonData 폴리곤 데이터 (paths 필드 필수)
10
+ * @param controller MintMapController 인스턴스
11
+ * @returns 변환된 화면 좌표 배열 (4차원 배열) 또는 null (변환 실패 시)
12
+ *
13
+ * @remarks
14
+ * - 반환 형식: [MultiPolygon][Polygon][Point][x/y]
15
+ * - 성능: O(n), n은 폴리곤의 총 좌표 수
16
+ * - GeoJSON MultiPolygon 형식 지원
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * const offsets = computePolygonOffsets(polygonData, controller);
21
+ * if (!offsets) return; // 변환 실패
22
+ *
23
+ * // offsets 구조: [MultiPolygon][Polygon][Point][x/y]
24
+ * for (const multiPolygon of offsets) {
25
+ * for (const polygon of multiPolygon) {
26
+ * // polygon은 [Point][x/y] 배열
27
+ * }
28
+ * }
29
+ * ```
6
30
  */
7
31
  export declare const computePolygonOffsets: (polygonData: KonvaCanvasData<any>, controller: MintMapController) => number[][][][] | null;
8
32
  /**
9
33
  * 마커 offset 계산
34
+ *
35
+ * 마커의 위경도 좌표를 화면 픽셀 좌표로 변환합니다.
36
+ *
37
+ * @param markerData 마커 데이터 (position 필드 필수)
38
+ * @param controller MintMapController 인스턴스
39
+ * @returns 변환된 화면 좌표 (Offset) 또는 null (변환 실패 시)
40
+ *
41
+ * @remarks
42
+ * - 반환된 좌표는 마커의 중심점 (x, y)
43
+ * - 성능: O(1) - 단일 좌표 변환
44
+ *
45
+ * @example
46
+ * ```typescript
47
+ * const offset = computeMarkerOffset(markerData, controller);
48
+ * if (!offset) return; // 변환 실패
49
+ * // offset.x, offset.y는 화면 픽셀 좌표
50
+ * ```
10
51
  */
11
52
  export declare const computeMarkerOffset: (markerData: KonvaCanvasData<any>, controller: MintMapController) => Offset | null;
12
53
  /**
13
54
  * Point-in-Polygon 알고리즘
55
+ *
56
+ * Ray Casting 알고리즘을 사용하여 점이 폴리곤 내부에 있는지 확인합니다.
57
+ *
58
+ * @param point 확인할 점의 좌표
59
+ * @param polygon 폴리곤 좌표 배열 (각 요소는 [x, y] 형식)
60
+ * @returns 점이 폴리곤 내부에 있으면 true, 아니면 false
61
+ *
62
+ * @remarks
63
+ * - **알고리즘**: Ray Casting (Ray Crossing)
64
+ * - **성능**: O(n), n은 폴리곤의 좌표 수
65
+ * - **경계 처리**: 경계선 위의 점은 내부로 간주
66
+ *
67
+ * @example
68
+ * ```typescript
69
+ * const point = { x: 100, y: 200 };
70
+ * const polygon = [[0, 0], [100, 0], [100, 100], [0, 100]];
71
+ * const isInside = isPointInPolygon(point, polygon);
72
+ * ```
14
73
  */
15
74
  export declare const isPointInPolygon: (point: Offset, polygon: number[][]) => boolean;
16
75
  /**
17
76
  * 폴리곤 히트 테스트 (도넛 폴리곤 지원)
18
77
  *
19
- * 로직:
20
- * 1. 외부 폴리곤(첫 번째): 내부에 있어야 함
21
- * 2. 내부 구멍들(나머지): 내부에 있으면 안 됨 (evenodd 규칙)
78
+ * 점이 폴리곤 내부에 있는지 확인합니다. 도넛 폴리곤(구멍이 있는 폴리곤)을 지원합니다.
79
+ *
80
+ * @param clickedOffset 클릭/마우스 위치 좌표
81
+ * @param polygonData 폴리곤 데이터
82
+ * @param getPolygonOffsets 폴리곤 좌표 변환 함수
83
+ * @returns 점이 폴리곤 내부에 있으면 true, 아니면 false
22
84
  *
23
- * 중요: 도넛 폴리곤과 내부 폴리곤은 별개의 polygonData로 처리됨
85
+ * @remarks
86
+ * - **도넛 폴리곤 처리** (isDonutPolygon === true):
87
+ * 1. 외부 폴리곤(첫 번째): 내부에 있어야 함
88
+ * 2. 내부 구멍들(나머지): 내부에 있으면 안 됨 (evenodd 규칙)
89
+ * - **일반 폴리곤 처리**: Point-in-Polygon 알고리즘 사용
90
+ * - **성능**: O(n), n은 폴리곤의 총 좌표 수
91
+ *
92
+ * **중요**: 도넛 폴리곤과 내부 폴리곤은 별개의 polygonData로 처리됩니다.
24
93
  * - 도넛 폴리곤 A: isDonutPolygon=true
25
94
  * - 내부 폴리곤 B: isDonutPolygon=false (별도 데이터)
95
+ *
96
+ * @example
97
+ * ```typescript
98
+ * const isHit = isPointInPolygonData(
99
+ * clickedOffset,
100
+ * polygonData,
101
+ * getOrComputePolygonOffsets
102
+ * );
103
+ * ```
26
104
  */
27
105
  export declare const isPointInPolygonData: (clickedOffset: Offset, polygonData: KonvaCanvasData<any>, getPolygonOffsets: (data: KonvaCanvasData<any>) => number[][][][] | null) => boolean;
28
106
  /**
29
107
  * 마커 히트 테스트 (클릭/hover 영역 체크)
30
108
  *
31
- * 🎯 중요: 꼬리(tail)는 Hit Test 영역에서 제외됩니다!
32
- * - markerOffset.y마커 최하단(꼬리 끝) 좌표
33
- * - boxHeight는 마커 본체만 포함 (꼬리 제외)
34
- * - tailHeight만큼 위로 올려서 본체만 Hit Test 영역으로 사용
109
+ * 점이 마커의 클릭/호버 영역 내부에 있는지 확인합니다.
110
+ * 마커의 꼬리(tail)Hit Test 영역에서 제외됩니다.
111
+ *
112
+ * @param clickedOffset 클릭/마우스 위치 좌표
113
+ * @param markerData 마커 데이터
114
+ * @param getMarkerOffset 마커 좌표 변환 함수
115
+ * @returns 점이 마커 영역 내부에 있으면 true, 아니면 false
116
+ *
117
+ * @remarks
118
+ * - **꼬리 제외**: 꼬리(tail)는 Hit Test 영역에서 제외됩니다
119
+ * - markerOffset.y는 마커 최하단(꼬리 끝) 좌표
120
+ * - boxHeight는 마커 본체만 포함 (꼬리 제외)
121
+ * - tailHeight만큼 위로 올려서 본체만 Hit Test 영역으로 사용
122
+ * - **성능**: O(1) - 단순 사각형 영역 체크
123
+ *
124
+ * @example
125
+ * ```typescript
126
+ * const isHit = isPointInMarkerData(
127
+ * clickedOffset,
128
+ * markerData,
129
+ * getOrComputeMarkerOffset
130
+ * );
131
+ * ```
35
132
  */
36
133
  export declare const isPointInMarkerData: (clickedOffset: Offset, markerData: KonvaCanvasData<any>, getMarkerOffset: (data: KonvaCanvasData<any>) => Offset | null) => boolean;
37
134
  export declare const hexToRgba: (hexColor: string, alpha?: number) => string;
38
135
  /**
39
136
  * 텍스트 박스의 너비를 계산합니다.
40
137
  *
41
- * @param {Object} params - 파라미터 객체
42
- * @param {string} params.text - 측정할 텍스트
43
- * @param {string} params.fontConfig - 폰트 설정 (예: 'bold 16px Arial')
44
- * @param {number} params.padding - 텍스트 박스에 적용할 패딩 값
45
- * @param {number} params.minWidth - 최소 너비
46
- * @returns {number} 계산된 텍스트 박스의 너비
138
+ * Canvas 2D Context의 measureText()를 사용하여 텍스트의 실제 너비를 계산하고,
139
+ * 패딩과 최소 너비를 고려하여 최종 너비를 반환합니다.
140
+ *
141
+ * @param params 파라미터 객체
142
+ * @param params.text 측정할 텍스트
143
+ * @param params.fontConfig 폰트 설정 (예: 'bold 16px Arial')
144
+ * @param params.padding 텍스트 박스에 적용할 패딩 값 (px)
145
+ * @param params.minWidth 최소 너비 (px)
146
+ * @returns 계산된 텍스트 박스의 너비 (px)
147
+ *
148
+ * @remarks
149
+ * - 성능: O(1) - 단일 텍스트 측정
150
+ * - 임시 Canvas를 사용하여 정확한 너비 측정
151
+ *
152
+ * @example
153
+ * ```typescript
154
+ * const width = calculateTextBoxWidth({
155
+ * text: "Hello World",
156
+ * fontConfig: 'bold 16px Arial',
157
+ * padding: 20,
158
+ * minWidth: 60
159
+ * });
160
+ * ```
47
161
  */
48
162
  export declare const calculateTextBoxWidth: ({ text, fontConfig, padding, minWidth, }: {
49
163
  text: string;
@@ -8,6 +8,30 @@ require('../../../types/MapEventTypes.js');
8
8
 
9
9
  /**
10
10
  * 폴리곤 offset 계산
11
+ *
12
+ * GeoJSON MultiPolygon 형식의 위경도 좌표를 화면 픽셀 좌표로 변환합니다.
13
+ *
14
+ * @param polygonData 폴리곤 데이터 (paths 필드 필수)
15
+ * @param controller MintMapController 인스턴스
16
+ * @returns 변환된 화면 좌표 배열 (4차원 배열) 또는 null (변환 실패 시)
17
+ *
18
+ * @remarks
19
+ * - 반환 형식: [MultiPolygon][Polygon][Point][x/y]
20
+ * - 성능: O(n), n은 폴리곤의 총 좌표 수
21
+ * - GeoJSON MultiPolygon 형식 지원
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * const offsets = computePolygonOffsets(polygonData, controller);
26
+ * if (!offsets) return; // 변환 실패
27
+ *
28
+ * // offsets 구조: [MultiPolygon][Polygon][Point][x/y]
29
+ * for (const multiPolygon of offsets) {
30
+ * for (const polygon of multiPolygon) {
31
+ * // polygon은 [Point][x/y] 배열
32
+ * }
33
+ * }
34
+ * ```
11
35
  */
12
36
 
13
37
  var computePolygonOffsets = function (polygonData, controller) {
@@ -44,6 +68,23 @@ var computePolygonOffsets = function (polygonData, controller) {
44
68
  };
45
69
  /**
46
70
  * 마커 offset 계산
71
+ *
72
+ * 마커의 위경도 좌표를 화면 픽셀 좌표로 변환합니다.
73
+ *
74
+ * @param markerData 마커 데이터 (position 필드 필수)
75
+ * @param controller MintMapController 인스턴스
76
+ * @returns 변환된 화면 좌표 (Offset) 또는 null (변환 실패 시)
77
+ *
78
+ * @remarks
79
+ * - 반환된 좌표는 마커의 중심점 (x, y)
80
+ * - 성능: O(1) - 단일 좌표 변환
81
+ *
82
+ * @example
83
+ * ```typescript
84
+ * const offset = computeMarkerOffset(markerData, controller);
85
+ * if (!offset) return; // 변환 실패
86
+ * // offset.x, offset.y는 화면 픽셀 좌표
87
+ * ```
47
88
  */
48
89
 
49
90
  var computeMarkerOffset = function (markerData, controller) {
@@ -55,6 +96,24 @@ var computeMarkerOffset = function (markerData, controller) {
55
96
  };
56
97
  /**
57
98
  * Point-in-Polygon 알고리즘
99
+ *
100
+ * Ray Casting 알고리즘을 사용하여 점이 폴리곤 내부에 있는지 확인합니다.
101
+ *
102
+ * @param point 확인할 점의 좌표
103
+ * @param polygon 폴리곤 좌표 배열 (각 요소는 [x, y] 형식)
104
+ * @returns 점이 폴리곤 내부에 있으면 true, 아니면 false
105
+ *
106
+ * @remarks
107
+ * - **알고리즘**: Ray Casting (Ray Crossing)
108
+ * - **성능**: O(n), n은 폴리곤의 좌표 수
109
+ * - **경계 처리**: 경계선 위의 점은 내부로 간주
110
+ *
111
+ * @example
112
+ * ```typescript
113
+ * const point = { x: 100, y: 200 };
114
+ * const polygon = [[0, 0], [100, 0], [100, 100], [0, 100]];
115
+ * const isInside = isPointInPolygon(point, polygon);
116
+ * ```
58
117
  */
59
118
 
60
119
  var isPointInPolygon = function (point, polygon) {
@@ -74,13 +133,32 @@ var isPointInPolygon = function (point, polygon) {
74
133
  /**
75
134
  * 폴리곤 히트 테스트 (도넛 폴리곤 지원)
76
135
  *
77
- * 로직:
78
- * 1. 외부 폴리곤(첫 번째): 내부에 있어야 함
79
- * 2. 내부 구멍들(나머지): 내부에 있으면 안 됨 (evenodd 규칙)
136
+ * 점이 폴리곤 내부에 있는지 확인합니다. 도넛 폴리곤(구멍이 있는 폴리곤)을 지원합니다.
137
+ *
138
+ * @param clickedOffset 클릭/마우스 위치 좌표
139
+ * @param polygonData 폴리곤 데이터
140
+ * @param getPolygonOffsets 폴리곤 좌표 변환 함수
141
+ * @returns 점이 폴리곤 내부에 있으면 true, 아니면 false
80
142
  *
81
- * 중요: 도넛 폴리곤과 내부 폴리곤은 별개의 polygonData로 처리됨
143
+ * @remarks
144
+ * - **도넛 폴리곤 처리** (isDonutPolygon === true):
145
+ * 1. 외부 폴리곤(첫 번째): 내부에 있어야 함
146
+ * 2. 내부 구멍들(나머지): 내부에 있으면 안 됨 (evenodd 규칙)
147
+ * - **일반 폴리곤 처리**: Point-in-Polygon 알고리즘 사용
148
+ * - **성능**: O(n), n은 폴리곤의 총 좌표 수
149
+ *
150
+ * **중요**: 도넛 폴리곤과 내부 폴리곤은 별개의 polygonData로 처리됩니다.
82
151
  * - 도넛 폴리곤 A: isDonutPolygon=true
83
152
  * - 내부 폴리곤 B: isDonutPolygon=false (별도 데이터)
153
+ *
154
+ * @example
155
+ * ```typescript
156
+ * const isHit = isPointInPolygonData(
157
+ * clickedOffset,
158
+ * polygonData,
159
+ * getOrComputePolygonOffsets
160
+ * );
161
+ * ```
84
162
  */
85
163
 
86
164
  var isPointInPolygonData = function (clickedOffset, polygonData, getPolygonOffsets) {
@@ -145,10 +223,29 @@ var isPointInPolygonData = function (clickedOffset, polygonData, getPolygonOffse
145
223
  /**
146
224
  * 마커 히트 테스트 (클릭/hover 영역 체크)
147
225
  *
148
- * 🎯 중요: 꼬리(tail)는 Hit Test 영역에서 제외됩니다!
149
- * - markerOffset.y마커 최하단(꼬리 끝) 좌표
150
- * - boxHeight는 마커 본체만 포함 (꼬리 제외)
151
- * - tailHeight만큼 위로 올려서 본체만 Hit Test 영역으로 사용
226
+ * 점이 마커의 클릭/호버 영역 내부에 있는지 확인합니다.
227
+ * 마커의 꼬리(tail)Hit Test 영역에서 제외됩니다.
228
+ *
229
+ * @param clickedOffset 클릭/마우스 위치 좌표
230
+ * @param markerData 마커 데이터
231
+ * @param getMarkerOffset 마커 좌표 변환 함수
232
+ * @returns 점이 마커 영역 내부에 있으면 true, 아니면 false
233
+ *
234
+ * @remarks
235
+ * - **꼬리 제외**: 꼬리(tail)는 Hit Test 영역에서 제외됩니다
236
+ * - markerOffset.y는 마커 최하단(꼬리 끝) 좌표
237
+ * - boxHeight는 마커 본체만 포함 (꼬리 제외)
238
+ * - tailHeight만큼 위로 올려서 본체만 Hit Test 영역으로 사용
239
+ * - **성능**: O(1) - 단순 사각형 영역 체크
240
+ *
241
+ * @example
242
+ * ```typescript
243
+ * const isHit = isPointInMarkerData(
244
+ * clickedOffset,
245
+ * markerData,
246
+ * getOrComputeMarkerOffset
247
+ * );
248
+ * ```
152
249
  */
153
250
 
154
251
  var isPointInMarkerData = function (clickedOffset, markerData, getMarkerOffset) {
@@ -185,12 +282,29 @@ var tempCtx = tempCanvas.getContext('2d');
185
282
  /**
186
283
  * 텍스트 박스의 너비를 계산합니다.
187
284
  *
188
- * @param {Object} params - 파라미터 객체
189
- * @param {string} params.text - 측정할 텍스트
190
- * @param {string} params.fontConfig - 폰트 설정 (예: 'bold 16px Arial')
191
- * @param {number} params.padding - 텍스트 박스에 적용할 패딩 값
192
- * @param {number} params.minWidth - 최소 너비
193
- * @returns {number} 계산된 텍스트 박스의 너비
285
+ * Canvas 2D Context의 measureText()를 사용하여 텍스트의 실제 너비를 계산하고,
286
+ * 패딩과 최소 너비를 고려하여 최종 너비를 반환합니다.
287
+ *
288
+ * @param params 파라미터 객체
289
+ * @param params.text 측정할 텍스트
290
+ * @param params.fontConfig 폰트 설정 (예: 'bold 16px Arial')
291
+ * @param params.padding 텍스트 박스에 적용할 패딩 값 (px)
292
+ * @param params.minWidth 최소 너비 (px)
293
+ * @returns 계산된 텍스트 박스의 너비 (px)
294
+ *
295
+ * @remarks
296
+ * - 성능: O(1) - 단일 텍스트 측정
297
+ * - 임시 Canvas를 사용하여 정확한 너비 측정
298
+ *
299
+ * @example
300
+ * ```typescript
301
+ * const width = calculateTextBoxWidth({
302
+ * text: "Hello World",
303
+ * fontConfig: 'bold 16px Arial',
304
+ * padding: 20,
305
+ * minWidth: 60
306
+ * });
307
+ * ```
194
308
  */
195
309
 
196
310
  var calculateTextBoxWidth = function (_a) {
@@ -0,0 +1,72 @@
1
+ import { MutableRefObject } from "react";
2
+ import { KonvaCanvasData } from "./types";
3
+ /**
4
+ * 뷰포트 영역 (화면에 보이는 영역)
5
+ */
6
+ export interface ViewportBounds {
7
+ minX: number;
8
+ maxX: number;
9
+ minY: number;
10
+ maxY: number;
11
+ }
12
+ /**
13
+ * 바운딩 박스 (마커/폴리곤의 최소/최대 좌표)
14
+ */
15
+ export interface BoundingBox {
16
+ minX: number;
17
+ minY: number;
18
+ maxX: number;
19
+ maxY: number;
20
+ }
21
+ /**
22
+ * 현재 뷰포트 영역 계산
23
+ *
24
+ * Konva Stage의 크기와 컬링 마진을 기반으로 뷰포트 경계를 계산합니다.
25
+ *
26
+ * @param stage Konva Stage 인스턴스 (width, height 메서드 제공)
27
+ * @param cullingMargin 컬링 여유 공간 (px)
28
+ * @param viewportRef 뷰포트 경계를 저장할 ref
29
+ *
30
+ * @remarks
31
+ * - 화면 밖 cullingMargin만큼의 영역까지 포함하여 계산
32
+ * - 스크롤 시 부드러운 전환을 위해 여유 공간 포함
33
+ *
34
+ * @example
35
+ * ```typescript
36
+ * updateViewport(stageRef.current, cullingMargin, viewportRef);
37
+ * ```
38
+ */
39
+ export declare const updateViewport: (stage: {
40
+ width: () => number;
41
+ height: () => number;
42
+ } | null, cullingMargin: number, viewportRef: MutableRefObject<ViewportBounds | null>) => void;
43
+ /**
44
+ * 아이템이 현재 뷰포트 안에 있는지 확인 (바운딩 박스 캐싱)
45
+ *
46
+ * 뷰포트 컬링을 위한 함수입니다. 바운딩 박스와 뷰포트 경계의 교차를 확인합니다.
47
+ * 바운딩 박스는 캐시되어 성능을 최적화합니다.
48
+ *
49
+ * @template T 마커/폴리곤 데이터의 추가 속성 타입
50
+ * @param item 확인할 아이템
51
+ * @param enableViewportCulling 뷰포트 컬링 활성화 여부
52
+ * @param viewportRef 뷰포트 경계 ref
53
+ * @param boundingBoxCacheRef 바운딩 박스 캐시 ref
54
+ * @param computeBoundingBox 바운딩 박스 계산 함수
55
+ * @returns 뷰포트 안에 있으면 true, 아니면 false
56
+ *
57
+ * @remarks
58
+ * - 성능: O(1) (캐시 히트 시) 또는 O(바운딩 박스 계산 비용) (캐시 미스 시)
59
+ * - 바운딩 박스는 자동으로 캐시되어 재사용됨
60
+ *
61
+ * @example
62
+ * ```typescript
63
+ * const isVisible = isInViewport(
64
+ * item,
65
+ * enableViewportCulling,
66
+ * viewportRef,
67
+ * boundingBoxCacheRef,
68
+ * computeBoundingBox
69
+ * );
70
+ * ```
71
+ */
72
+ export declare const isInViewport: <T>(item: KonvaCanvasData<T>, enableViewportCulling: boolean, viewportRef: MutableRefObject<ViewportBounds | null>, boundingBoxCacheRef: MutableRefObject<Map<string, BoundingBox>>, computeBoundingBox: (item: KonvaCanvasData<T>) => BoundingBox | null) => boolean;
@@ -0,0 +1,81 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ /**
6
+ * 현재 뷰포트 영역 계산
7
+ *
8
+ * Konva Stage의 크기와 컬링 마진을 기반으로 뷰포트 경계를 계산합니다.
9
+ *
10
+ * @param stage Konva Stage 인스턴스 (width, height 메서드 제공)
11
+ * @param cullingMargin 컬링 여유 공간 (px)
12
+ * @param viewportRef 뷰포트 경계를 저장할 ref
13
+ *
14
+ * @remarks
15
+ * - 화면 밖 cullingMargin만큼의 영역까지 포함하여 계산
16
+ * - 스크롤 시 부드러운 전환을 위해 여유 공간 포함
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * updateViewport(stageRef.current, cullingMargin, viewportRef);
21
+ * ```
22
+ */
23
+ var updateViewport = function (stage, cullingMargin, viewportRef) {
24
+ if (!stage) return;
25
+ viewportRef.current = {
26
+ minX: -cullingMargin,
27
+ maxX: stage.width() + cullingMargin,
28
+ minY: -cullingMargin,
29
+ maxY: stage.height() + cullingMargin
30
+ };
31
+ };
32
+ /**
33
+ * 아이템이 현재 뷰포트 안에 있는지 확인 (바운딩 박스 캐싱)
34
+ *
35
+ * 뷰포트 컬링을 위한 함수입니다. 바운딩 박스와 뷰포트 경계의 교차를 확인합니다.
36
+ * 바운딩 박스는 캐시되어 성능을 최적화합니다.
37
+ *
38
+ * @template T 마커/폴리곤 데이터의 추가 속성 타입
39
+ * @param item 확인할 아이템
40
+ * @param enableViewportCulling 뷰포트 컬링 활성화 여부
41
+ * @param viewportRef 뷰포트 경계 ref
42
+ * @param boundingBoxCacheRef 바운딩 박스 캐시 ref
43
+ * @param computeBoundingBox 바운딩 박스 계산 함수
44
+ * @returns 뷰포트 안에 있으면 true, 아니면 false
45
+ *
46
+ * @remarks
47
+ * - 성능: O(1) (캐시 히트 시) 또는 O(바운딩 박스 계산 비용) (캐시 미스 시)
48
+ * - 바운딩 박스는 자동으로 캐시되어 재사용됨
49
+ *
50
+ * @example
51
+ * ```typescript
52
+ * const isVisible = isInViewport(
53
+ * item,
54
+ * enableViewportCulling,
55
+ * viewportRef,
56
+ * boundingBoxCacheRef,
57
+ * computeBoundingBox
58
+ * );
59
+ * ```
60
+ */
61
+
62
+ var isInViewport = function (item, enableViewportCulling, viewportRef, boundingBoxCacheRef, computeBoundingBox) {
63
+ if (!enableViewportCulling || !viewportRef.current) return true;
64
+ var viewport = viewportRef.current; // 캐시된 바운딩 박스 확인
65
+
66
+ var bbox = boundingBoxCacheRef.current.get(item.id);
67
+
68
+ if (!bbox) {
69
+ // 바운딩 박스 계산 (공통 함수 사용)
70
+ var computed = computeBoundingBox(item);
71
+ if (!computed) return false;
72
+ bbox = computed;
73
+ boundingBoxCacheRef.current.set(item.id, bbox);
74
+ } // 바운딩 박스와 viewport 교차 체크
75
+
76
+
77
+ return !(bbox.maxX < viewport.minX || bbox.minX > viewport.maxX || bbox.maxY < viewport.minY || bbox.minY > viewport.maxY);
78
+ };
79
+
80
+ exports.isInViewport = isInViewport;
81
+ exports.updateViewport = updateViewport;