@operato/weather 9.0.0-beta.56

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.
Files changed (60) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +337 -0
  3. package/assets/images/no-image.png +0 -0
  4. package/dist/src/index.d.ts +1 -0
  5. package/dist/src/index.js +2 -0
  6. package/dist/src/index.js.map +1 -0
  7. package/dist/src/layers/base-weather-layer.d.ts +56 -0
  8. package/dist/src/layers/base-weather-layer.js +83 -0
  9. package/dist/src/layers/base-weather-layer.js.map +1 -0
  10. package/dist/src/layers/cloud-layer.d.ts +17 -0
  11. package/dist/src/layers/cloud-layer.js +203 -0
  12. package/dist/src/layers/cloud-layer.js.map +1 -0
  13. package/dist/src/layers/precipitation-layer.d.ts +27 -0
  14. package/dist/src/layers/precipitation-layer.js +344 -0
  15. package/dist/src/layers/precipitation-layer.js.map +1 -0
  16. package/dist/src/layers/solar-layer.d.ts +17 -0
  17. package/dist/src/layers/solar-layer.js +253 -0
  18. package/dist/src/layers/solar-layer.js.map +1 -0
  19. package/dist/src/layers/temperature-layer.d.ts +13 -0
  20. package/dist/src/layers/temperature-layer.js +230 -0
  21. package/dist/src/layers/temperature-layer.js.map +1 -0
  22. package/dist/src/layers/wind-layer.d.ts +60 -0
  23. package/dist/src/layers/wind-layer.js +311 -0
  24. package/dist/src/layers/wind-layer.js.map +1 -0
  25. package/dist/src/ox-weather.d.ts +112 -0
  26. package/dist/src/ox-weather.js +645 -0
  27. package/dist/src/ox-weather.js.map +1 -0
  28. package/dist/src/ox-wind.d.ts +91 -0
  29. package/dist/src/ox-wind.js +425 -0
  30. package/dist/src/ox-wind.js.map +1 -0
  31. package/dist/src/services/weather-service.d.ts +79 -0
  32. package/dist/src/services/weather-service.js +560 -0
  33. package/dist/src/services/weather-service.js.map +1 -0
  34. package/dist/src/types.d.ts +71 -0
  35. package/dist/src/types.js +2 -0
  36. package/dist/src/types.js.map +1 -0
  37. package/dist/stories/data-weather.stories.d.ts +47 -0
  38. package/dist/stories/data-weather.stories.js +93 -0
  39. package/dist/stories/data-weather.stories.js.map +1 -0
  40. package/dist/tsconfig.tsbuildinfo +1 -0
  41. package/package.json +86 -0
  42. package/themes/app-theme.css +138 -0
  43. package/themes/calendar-theme.css +61 -0
  44. package/themes/dark.css +51 -0
  45. package/themes/form-theme.css +70 -0
  46. package/themes/grist-theme.css +175 -0
  47. package/themes/layout-theme.css +94 -0
  48. package/themes/light.css +51 -0
  49. package/themes/material-theme.css +23 -0
  50. package/themes/md-typescale-styles.css +100 -0
  51. package/themes/oops-theme.css +22 -0
  52. package/themes/report-theme.css +47 -0
  53. package/themes/spacing.css +23 -0
  54. package/themes/state-color.css +6 -0
  55. package/themes/tooltip-theme.css +11 -0
  56. package/translations/en.json +1 -0
  57. package/translations/ja.json +1 -0
  58. package/translations/ko.json +1 -0
  59. package/translations/ms.json +1 -0
  60. package/translations/zh.json +1 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"temperature-layer.js","sourceRoot":"","sources":["../../../src/layers/temperature-layer.ts"],"names":[],"mappings":"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","sourcesContent":["import BaseLayer from 'ol/layer/Base'\nimport VectorSource from 'ol/source/Vector'\nimport { Heatmap as HeatmapLayer } from 'ol/layer'\nimport Feature from 'ol/Feature'\nimport Point from 'ol/geom/Point'\nimport { fromLonLat } from 'ol/proj'\nimport Polygon from 'ol/geom/Polygon'\nimport { Fill } from 'ol/style'\nimport VectorLayer from 'ol/layer/Vector'\nimport { Style, Stroke } from 'ol/style'\n\nimport { BaseWeatherLayer } from './base-weather-layer.js'\nimport { WeatherData, WeatherLayerType } from '../types.js'\n\n/**\n * 온도 레이어 구현\n */\nexport class TemperatureLayer extends BaseWeatherLayer {\n getType(): WeatherLayerType {\n return 'temperature'\n }\n\n /**\n * 히트맵 레이어를 생성하여 온도를 표현합니다.\n */\n createLayer(): BaseLayer {\n const source = new VectorSource()\n\n console.log('온도 레이어 생성 - 데이터 존재 여부:', !!this.weatherData, '데이터 개수:', this.weatherData?.length)\n\n if (!this.weatherData || this.weatherData.length === 0) {\n console.log('온도 레이어: 날씨 데이터가 없음')\n return new VectorLayer({\n source,\n zIndex: 5\n })\n }\n\n // 온도 값이 있는지 확인\n const validData = this.weatherData.filter(data => {\n const hasTemp = data.temperature && typeof data.temperature.current === 'number'\n if (!hasTemp) {\n console.log('온도 데이터 없음:', data)\n }\n return hasTemp\n })\n\n console.log('유효한 온도 데이터 수:', validData.length)\n\n if (validData.length === 0) {\n console.log('온도 레이어: 유효한 온도 데이터가 없음')\n return new VectorLayer({\n source,\n zIndex: 5\n })\n }\n\n // 온도 범위 계산\n let minTemp = Infinity\n let maxTemp = -Infinity\n\n validData.forEach(data => {\n const temp = data.temperature.current\n minTemp = Math.min(minTemp, temp)\n maxTemp = Math.max(maxTemp, temp)\n })\n\n // 각 데이터 포인트의 위치와 온도 추출\n const points = validData.map(data => ({\n lon: data.location.longitude,\n lat: data.location.latitude,\n temp: data.temperature.current\n }))\n\n console.log('온도 데이터 포인트:', points.length, '첫 번째 포인트:', points[0])\n\n // 온도 정규화 함수 - 0~1 범위로 변환\n const normalizeTemp = (temp: number) => {\n if (maxTemp === minTemp) return 0.5\n return (temp - minTemp) / (maxTemp - minTemp)\n }\n\n // 개선된 온도 보간 함수 - IDW(Inverse Distance Weighting) 기반 보간법\n const interpolateTemp = (lon: number, lat: number) => {\n // 가장 가까운 이웃 개수 제한 - 모든 포인트 대신 가까운 포인트만 사용하여 국지적 패턴 유지\n const MAX_NEIGHBORS = 5\n\n // 현재 위치에서 모든 포인트까지의 거리 계산\n const distances = points.map(point => {\n const dx = lon - point.lon\n const dy = lat - point.lat\n return {\n point,\n dist: Math.sqrt(dx * dx + dy * dy)\n }\n })\n\n // 거리에 따라 정렬하고 가장 가까운 이웃만 선택\n const nearestNeighbors = distances.sort((a, b) => a.dist - b.dist).slice(0, MAX_NEIGHBORS)\n\n // 포인트가 정확히 일치하는 경우\n if (nearestNeighbors.length > 0 && nearestNeighbors[0].dist < 0.0001) {\n return nearestNeighbors[0].point.temp\n }\n\n // 역거리 가중치 보간법 적용 - 거리의 제곱에 반비례하는 가중치 사용\n let totalWeight = 0\n let weightedTemp = 0\n\n // 가중치 지수 - 낮을수록 더 부드러운 보간, 높을수록 가까운 값에 더 큰 영향\n const power = 1.5\n\n nearestNeighbors.forEach(({ point, dist }) => {\n // 작은 값으로 나누기 방지\n const adjustedDist = Math.max(dist, 0.0001)\n const weight = 1 / Math.pow(adjustedDist, power)\n\n totalWeight += weight\n weightedTemp += point.temp * weight\n })\n\n return weightedTemp / totalWeight\n }\n\n // 온도에 따른 색상 계산 함수\n const getColorFromTemp = (temp: number) => {\n const normalized = normalizeTemp(temp)\n\n // HSL 색상 모델 사용 - 보다 자연스러운 온도 색상 맵핑\n // 파랑(추움, 240) -> 하양(중간, 180) -> 빨강(더움, 0)\n const hue = Math.max(0, Math.min(240, 240 - normalized * 240))\n\n // 온도에 따라 채도 변화 - 극단적 온도에서 더 선명하게\n const saturation = 70 + Math.abs(normalized - 0.5) * 60\n\n // 온도에 따라 밝기 조정 - 중간 온도는 더 밝게\n const lightness = 50 + Math.abs(normalized - 0.5) * 20\n\n // 투명도 설정 - 중간 온도는 더 투명하게, 극단적 온도는 더 선명하게\n const alpha = 0.4 + Math.abs(normalized - 0.5) * 0.4\n\n return `hsla(${hue}, ${saturation}%, ${lightness}%, ${alpha})`\n }\n\n // 그라데이션을 적용할 그리드 생성\n const bounds = {\n minLon: Infinity,\n maxLon: -Infinity,\n minLat: Infinity,\n maxLat: -Infinity\n }\n\n // 데이터 포인트로부터 영역 경계 계산\n points.forEach(point => {\n bounds.minLon = Math.min(bounds.minLon, point.lon)\n bounds.maxLon = Math.max(bounds.maxLon, point.lon)\n bounds.minLat = Math.min(bounds.minLat, point.lat)\n bounds.maxLat = Math.max(bounds.maxLat, point.lat)\n })\n\n // 경계에 마진 추가\n const margin = 0.1\n bounds.minLon -= margin\n bounds.maxLon += margin\n bounds.minLat -= margin\n bounds.maxLat += margin\n\n // 고해상도 그리드 생성 (더 매끄러운 그라데이션을 위해)\n const gridResolution = 120 // 적절한 해상도로 조정\n const lonStep = (bounds.maxLon - bounds.minLon) / gridResolution\n const latStep = (bounds.maxLat - bounds.minLat) / gridResolution\n\n // 인접 셀 간의 온도 차이 최소화를 위한 스무딩 함수\n const smoothGrid = (grid: number[][], passes: number = 2): number[][] => {\n const rows = grid.length\n if (rows === 0) return grid\n\n const cols = grid[0].length\n const result = Array(rows)\n .fill(0)\n .map(() => Array(cols).fill(0))\n\n // 여러 번 스무딩 패스 적용\n for (let pass = 0; pass < passes; pass++) {\n const currentGrid = pass === 0 ? grid : result\n\n for (let i = 0; i < rows; i++) {\n for (let j = 0; j < cols; j++) {\n // 현재 셀과 인접 셀의 평균 계산\n let sum = currentGrid[i][j]\n let count = 1\n\n // 상하좌우 셀 확인\n const neighbors = [\n [i - 1, j],\n [i + 1, j],\n [i, j - 1],\n [i, j + 1]\n ]\n\n neighbors.forEach(([ni, nj]) => {\n if (ni >= 0 && ni < rows && nj >= 0 && nj < cols) {\n sum += currentGrid[ni][nj]\n count++\n }\n })\n\n // 평균값으로 스무딩 (약간의 원본 가중치 부여)\n result[i][j] = currentGrid[i][j] * 0.6 + ((sum - currentGrid[i][j]) / (count - 1)) * 0.4\n }\n }\n }\n\n return result\n }\n\n // 온도 데이터 그리드 생성\n const tempGrid: number[][] = []\n\n for (let i = 0; i < gridResolution; i++) {\n tempGrid[i] = []\n for (let j = 0; j < gridResolution; j++) {\n const centerLon = bounds.minLon + (j + 0.5) * lonStep\n const centerLat = bounds.minLat + (i + 0.5) * latStep\n tempGrid[i][j] = interpolateTemp(centerLon, centerLat)\n }\n }\n\n // 그리드 스무딩 적용\n const smoothedGrid = smoothGrid(tempGrid, 2)\n\n // 셀 생성 및 피처 추가\n for (let i = 0; i < gridResolution; i++) {\n for (let j = 0; j < gridResolution; j++) {\n const lonMin = bounds.minLon + j * lonStep\n const lonMax = bounds.minLon + (j + 1) * lonStep\n const latMin = bounds.minLat + i * latStep\n const latMax = bounds.minLat + (i + 1) * latStep\n\n // 스무딩된 온도값 사용\n const interpolatedTemp = smoothedGrid[i][j]\n\n // 셀 좌표 계산 및 변환\n const coordinates = [\n [lonMin, latMin],\n [lonMax, latMin],\n [lonMax, latMax],\n [lonMin, latMax],\n [lonMin, latMin]\n ].map(coord => fromLonLat(coord))\n\n // 다각형 피처 생성\n const feature = new Feature({\n geometry: new Polygon([coordinates]),\n temperature: interpolatedTemp\n })\n\n source.addFeature(feature)\n }\n }\n\n // 벡터 레이어 생성 - 경계선 제거\n return new VectorLayer({\n source,\n zIndex: 6,\n opacity: 0.8, // 전체 레이어 투명도 설정\n className: 'temperature-layer', // 사용자 정의 클래스 이름 추가\n style: feature => {\n const temp = feature.get('temperature') as number\n return new Style({\n fill: new Fill({\n color: getColorFromTemp(temp)\n }),\n // 경계선 완전히 제거\n stroke: undefined\n })\n }\n })\n }\n}\n"]}
@@ -0,0 +1,60 @@
1
+ import BaseLayer from 'ol/layer/Base';
2
+ import { WeatherLayerType } from '../types';
3
+ import { BaseWeatherLayer } from './base-weather-layer';
4
+ /**
5
+ * 바람 레이어 클래스
6
+ * OpenLayers Flow 레이어를 사용하여 바람 흐름을 표현합니다.
7
+ * https://github.com/openlayers/openlayers/blob/v10.4.0/examples/wind.js 참고
8
+ */
9
+ export declare class WindLayer extends BaseWeatherLayer {
10
+ private windLayer?;
11
+ private windSource?;
12
+ protected layerType: string;
13
+ private maxSpeed;
14
+ private minSpeed;
15
+ private tileGrid;
16
+ private tileSize;
17
+ private weatherPoints;
18
+ /**
19
+ * 생성자
20
+ */
21
+ constructor(options?: any);
22
+ /**
23
+ * 레이어 타입 반환
24
+ */
25
+ getType(): WeatherLayerType;
26
+ /**
27
+ * 레이어 생성
28
+ * OpenLayers Flow 레이어를 사용하여 바람 흐름을 표현합니다.
29
+ * OpenLayers 공식 예제 참고: https://github.com/openlayers/openlayers/blob/v10.4.0/examples/wind.js
30
+ */
31
+ createLayer(): BaseLayer;
32
+ /**
33
+ * 날씨 데이터에서 바람 정보 추출
34
+ */
35
+ private prepareWindData;
36
+ /**
37
+ * 목업 바람 데이터 생성
38
+ */
39
+ private createMockWindData;
40
+ /**
41
+ * 타일에 바람 데이터 생성
42
+ */
43
+ private createWindTile;
44
+ /**
45
+ * 주어진 위치의 바람 벡터를 보간하여 반환
46
+ */
47
+ private interpolateWindVector;
48
+ /**
49
+ * 레이어 가시성 설정
50
+ */
51
+ setVisible(visible: boolean): void;
52
+ /**
53
+ * 레이어 제거
54
+ */
55
+ removeLayer(): void;
56
+ /**
57
+ * 레이어 업데이트
58
+ */
59
+ protected updateLayer(): void;
60
+ }
@@ -0,0 +1,311 @@
1
+ import BaseLayer from 'ol/layer/Base';
2
+ import { BaseWeatherLayer } from './base-weather-layer';
3
+ import { transform } from 'ol/proj';
4
+ import Flow from 'ol/layer/Flow';
5
+ import DataTileSource from 'ol/source/DataTile';
6
+ import { get as getProjection } from 'ol/proj';
7
+ import { createXYZ, wrapX } from 'ol/tilegrid';
8
+ /**
9
+ * 바람 레이어 클래스
10
+ * OpenLayers Flow 레이어를 사용하여 바람 흐름을 표현합니다.
11
+ * https://github.com/openlayers/openlayers/blob/v10.4.0/examples/wind.js 참고
12
+ */
13
+ export class WindLayer extends BaseWeatherLayer {
14
+ /**
15
+ * 생성자
16
+ */
17
+ constructor(options = {}) {
18
+ super();
19
+ this.layerType = 'wind';
20
+ // 바람 속도 범위 설정
21
+ this.maxSpeed = 15; // 최대 바람 속도 (m/s)
22
+ this.minSpeed = 0; // 최소 바람 속도
23
+ // 타일 생성 관련 설정
24
+ this.tileGrid = createXYZ();
25
+ this.tileSize = 256;
26
+ this.weatherPoints = [];
27
+ // 옵션 설정
28
+ this.maxSpeed = options.maxSpeed || 15;
29
+ }
30
+ /**
31
+ * 레이어 타입 반환
32
+ */
33
+ getType() {
34
+ return 'wind';
35
+ }
36
+ /**
37
+ * 레이어 생성
38
+ * OpenLayers Flow 레이어를 사용하여 바람 흐름을 표현합니다.
39
+ * OpenLayers 공식 예제 참고: https://github.com/openlayers/openlayers/blob/v10.4.0/examples/wind.js
40
+ */
41
+ createLayer() {
42
+ console.log('바람 레이어 생성 중...');
43
+ // 이미 생성된 레이어가 있다면 반환
44
+ if (this.windLayer) {
45
+ return this.windLayer;
46
+ }
47
+ // 날씨 데이터를 풍속 벡터로 변환 (바람 데이터 준비)
48
+ this.prepareWindData();
49
+ try {
50
+ // 바람 데이터 소스 생성
51
+ this.windSource = new DataTileSource({
52
+ tileGrid: this.tileGrid,
53
+ // transition must be 0, see https://github.com/openlayers/openlayers/issues/16119
54
+ transition: 0,
55
+ wrapX: true,
56
+ loader: (z, x, y) => {
57
+ return this.createWindTile(z, x, y);
58
+ }
59
+ });
60
+ // 실제 바람 데이터의 속도 범위 확인
61
+ let minSpeed = Infinity;
62
+ let maxSpeed = 0;
63
+ let totalSpeed = 0;
64
+ this.weatherPoints.forEach(point => {
65
+ minSpeed = Math.min(minSpeed, point.speed);
66
+ maxSpeed = Math.max(maxSpeed, point.speed);
67
+ totalSpeed += point.speed;
68
+ });
69
+ const avgSpeed = totalSpeed / this.weatherPoints.length;
70
+ console.log(`바람 속도 범위: ${minSpeed.toFixed(2)}~${maxSpeed.toFixed(2)} m/s, 평균: ${avgSpeed.toFixed(2)} m/s`);
71
+ // 효과적인 최대 속도 설정 (데이터 기반)
72
+ const effectiveMaxSpeed = maxSpeed > 0 ? Math.max(10, maxSpeed) : 10;
73
+ this.maxSpeed = effectiveMaxSpeed;
74
+ console.log(`Flow 레이어 최대 속도: ${effectiveMaxSpeed.toFixed(2)} m/s`);
75
+ // Flow 레이어 옵션 설정 - 단일 스타일 사용
76
+ const flowOptions = {
77
+ source: this.windSource,
78
+ zIndex: 10,
79
+ className: 'wind-layer',
80
+ maxSpeed: this.maxSpeed,
81
+ // 파티클 세부 설정 최적화
82
+ tracksPerPixel: 0.5, // 트랙 밀도 증가 (더 많은 입자)
83
+ fadeTrails: true, // 트레일 페이드 효과
84
+ trailLength: 0.45, // 중간 길이 트레일
85
+ // 단일 색상 스타일 - 주의: 복잡한 표현식 사용하지 않음
86
+ style: {
87
+ color: 'rgba(0, 191, 255, 0.8)', // 하늘색 (DeepSkyBlue)
88
+ width: 1.5
89
+ }
90
+ };
91
+ // @ts-ignore - Flow 레이어는 TypeScript 정의가 불완전할 수 있음
92
+ this.windLayer = new Flow(flowOptions);
93
+ console.log('Flow 레이어 생성 완료');
94
+ return this.windLayer;
95
+ }
96
+ catch (error) {
97
+ console.error('Flow 레이어 생성 중 오류:', error);
98
+ // 오류 발생 시 완전히 단순화된 옵션으로 다시 시도
99
+ try {
100
+ console.log('완전히 단순화된 옵션으로 다시 시도합니다...');
101
+ const verySimpleOptions = {
102
+ source: this.windSource,
103
+ zIndex: 10,
104
+ className: 'wind-layer',
105
+ maxSpeed: this.maxSpeed
106
+ };
107
+ // @ts-ignore
108
+ this.windLayer = new Flow(verySimpleOptions);
109
+ console.log('단순 Flow 레이어 생성 완료');
110
+ return this.windLayer;
111
+ }
112
+ catch (fallbackError) {
113
+ console.error('단순 Flow 레이어 생성도 실패:', fallbackError);
114
+ return new BaseLayer({});
115
+ }
116
+ }
117
+ }
118
+ /**
119
+ * 날씨 데이터에서 바람 정보 추출
120
+ */
121
+ prepareWindData() {
122
+ this.weatherPoints = [];
123
+ if (!this.weatherData || this.weatherData.length === 0) {
124
+ console.warn('날씨 데이터가 없어 목업 데이터를 생성합니다.');
125
+ this.createMockWindData();
126
+ return;
127
+ }
128
+ console.log(`${this.weatherData.length}개의 날씨 데이터에서 바람 정보 추출 중...`);
129
+ // 유효한 바람 데이터만 추출
130
+ this.weatherData.forEach(data => {
131
+ if (data.wind &&
132
+ data.location &&
133
+ typeof data.wind.speed === 'number' &&
134
+ typeof data.wind.direction === 'number' &&
135
+ !isNaN(data.wind.speed) &&
136
+ !isNaN(data.wind.direction) &&
137
+ typeof data.location.longitude === 'number' &&
138
+ typeof data.location.latitude === 'number') {
139
+ // 각도를 라디안으로 변환 (바람 방향은 북쪽이 0도, 시계방향으로 증가)
140
+ const dirRad = (data.wind.direction * Math.PI) / 180;
141
+ // u, v 성분 계산 (동서/남북 벡터)
142
+ // 참고: 바람 벡터는 바람이 불어오는 방향이므로 변환 필요
143
+ const u = -Math.sin(dirRad) * data.wind.speed;
144
+ const v = -Math.cos(dirRad) * data.wind.speed;
145
+ this.weatherPoints.push({
146
+ lon: data.location.longitude,
147
+ lat: data.location.latitude,
148
+ u: u,
149
+ v: v,
150
+ speed: data.wind.speed
151
+ });
152
+ }
153
+ });
154
+ console.log(`바람 데이터 추출 완료: ${this.weatherPoints.length}개 포인트`);
155
+ // 데이터가 없으면 목업 데이터 생성
156
+ if (this.weatherPoints.length === 0) {
157
+ console.warn('유효한 바람 데이터가 없어 목업 데이터를 생성합니다.');
158
+ this.createMockWindData();
159
+ }
160
+ }
161
+ /**
162
+ * 목업 바람 데이터 생성
163
+ */
164
+ createMockWindData() {
165
+ console.log('목업 바람 데이터 생성 중...');
166
+ this.weatherPoints = [];
167
+ // 한국 영역에 그리드 형태로 바람 데이터 생성
168
+ const lonMin = 124.0;
169
+ const lonMax = 132.0;
170
+ const latMin = 33.0;
171
+ const latMax = 38.0;
172
+ const cols = 15;
173
+ const rows = 15;
174
+ for (let i = 0; i <= cols; i++) {
175
+ for (let j = 0; j <= rows; j++) {
176
+ const lon = lonMin + (i / cols) * (lonMax - lonMin);
177
+ const lat = latMin + (j / rows) * (latMax - latMin);
178
+ // 위치에 따라 달라지는 패턴 생성
179
+ const patternX = Math.sin(lon * 0.5) * 2;
180
+ const patternY = Math.cos(lat * 0.5) * 2;
181
+ // 바람 속도와 방향 계산 (목업 데이터)
182
+ const speed = 5 + 5 * Math.sin((lon + lat) * 0.2);
183
+ // u, v 벡터 성분 (동서/남북)
184
+ const u = (patternX * speed) / 5;
185
+ const v = (patternY * speed) / 5;
186
+ this.weatherPoints.push({
187
+ lon,
188
+ lat,
189
+ u,
190
+ v,
191
+ speed
192
+ });
193
+ }
194
+ }
195
+ console.log(`목업 바람 데이터 생성 완료: ${this.weatherPoints.length}개 포인트`);
196
+ }
197
+ /**
198
+ * 타일에 바람 데이터 생성
199
+ */
200
+ createWindTile(z, x, y) {
201
+ // 타일 범위 계산
202
+ const projection = getProjection('EPSG:3857');
203
+ if (!projection) {
204
+ console.error('EPSG:3857 투영 생성 실패');
205
+ return new Float32Array(this.tileSize * this.tileSize * 4);
206
+ }
207
+ const tileCoord = wrapX(this.tileGrid, [z, x, y], projection);
208
+ const extent = this.tileGrid.getTileCoordExtent(tileCoord);
209
+ const resolution = this.tileGrid.getResolution(z);
210
+ // 타일 데이터 생성 (RGBA 형식: u, v, speed, 0)
211
+ const data = new Float32Array(this.tileSize * this.tileSize * 4);
212
+ // 데이터가 없을 경우
213
+ if (this.weatherPoints.length === 0) {
214
+ // 빈 데이터 반환 (모든 값 0)
215
+ return data;
216
+ }
217
+ // 타일의 각 픽셀에 대해 바람 벡터 계산
218
+ for (let row = 0; row < this.tileSize; ++row) {
219
+ for (let col = 0; col < this.tileSize; ++col) {
220
+ // 픽셀 위치를 지리 좌표로 변환
221
+ const mapX = extent[0] + col * resolution;
222
+ const mapY = extent[3] - row * resolution;
223
+ // 메르카토르 좌표를 경위도로 변환
224
+ const lonlat = transform([mapX, mapY], 'EPSG:3857', 'EPSG:4326');
225
+ const lon = lonlat[0];
226
+ const lat = lonlat[1];
227
+ // 주변 바람 데이터를 기반으로 보간
228
+ const vector = this.interpolateWindVector(lon, lat);
229
+ // 벡터 크기 조정 (너무 작은 값은 시각적으로 보이지 않음)
230
+ const normalizedSpeed = vector.speed / this.maxSpeed;
231
+ let adjustedU = vector.u;
232
+ let adjustedV = vector.v;
233
+ // 너무 작은 벡터는 약간 증폭
234
+ if (normalizedSpeed > 0 && normalizedSpeed < 0.1) {
235
+ const amplification = 0.1 / normalizedSpeed;
236
+ adjustedU *= Math.min(amplification, 2);
237
+ adjustedV *= Math.min(amplification, 2);
238
+ }
239
+ // 데이터 저장 (RGBA 형식)
240
+ const offset = (row * this.tileSize + col) * 4;
241
+ data[offset] = adjustedU; // R = u (동서 방향)
242
+ data[offset + 1] = adjustedV; // G = v (남북 방향)
243
+ data[offset + 2] = vector.speed; // B = 풍속
244
+ data[offset + 3] = 1; // A = 사용 (중요: 값을 1로 설정)
245
+ }
246
+ }
247
+ return data;
248
+ }
249
+ /**
250
+ * 주어진 위치의 바람 벡터를 보간하여 반환
251
+ */
252
+ interpolateWindVector(lon, lat) {
253
+ if (this.weatherPoints.length === 0) {
254
+ return { u: 0, v: 0, speed: 0 };
255
+ }
256
+ // 역거리 가중치 방식(IDW) 보간 사용
257
+ let totalWeight = 0;
258
+ let weightedU = 0;
259
+ let weightedV = 0;
260
+ // 주변 포인트를 찾아 가중 평균 계산
261
+ this.weatherPoints.forEach(point => {
262
+ // 거리 계산 (단순화된 버전)
263
+ const dx = lon - point.lon;
264
+ const dy = lat - point.lat;
265
+ const dist = Math.sqrt(dx * dx + dy * dy);
266
+ // 가중치 계산 (거리 제곱의 역수)
267
+ const weight = 1 / Math.max(0.0001, dist * dist);
268
+ totalWeight += weight;
269
+ weightedU += point.u * weight;
270
+ weightedV += point.v * weight;
271
+ });
272
+ if (totalWeight === 0) {
273
+ return { u: 0, v: 0, speed: 0 };
274
+ }
275
+ // 가중 평균
276
+ const u = weightedU / totalWeight;
277
+ const v = weightedV / totalWeight;
278
+ const speed = Math.sqrt(u * u + v * v);
279
+ return { u, v, speed };
280
+ }
281
+ /**
282
+ * 레이어 가시성 설정
283
+ */
284
+ setVisible(visible) {
285
+ if (this.windLayer) {
286
+ this.windLayer.setVisible(visible);
287
+ }
288
+ }
289
+ /**
290
+ * 레이어 제거
291
+ */
292
+ removeLayer() {
293
+ if (this.map && this.windLayer) {
294
+ this.map.removeLayer(this.windLayer);
295
+ this.windLayer = undefined;
296
+ }
297
+ }
298
+ /**
299
+ * 레이어 업데이트
300
+ */
301
+ updateLayer() {
302
+ if (!this.map || !this.windLayer) {
303
+ return;
304
+ }
305
+ this.prepareWindData();
306
+ if (this.windSource) {
307
+ this.windSource.refresh();
308
+ }
309
+ }
310
+ }
311
+ //# sourceMappingURL=wind-layer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wind-layer.js","sourceRoot":"","sources":["../../../src/layers/wind-layer.ts"],"names":[],"mappings":"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","sourcesContent":["import { Map } from 'ol'\nimport BaseLayer from 'ol/layer/Base'\nimport { WeatherData, WeatherLayerType } from '../types'\nimport { BaseWeatherLayer } from './base-weather-layer'\nimport { fromLonLat, transform, transformExtent } from 'ol/proj'\nimport Flow from 'ol/layer/Flow'\nimport DataTileSource from 'ol/source/DataTile'\nimport { createEmpty, extend, getWidth, getHeight } from 'ol/extent'\nimport { getVectorContext } from 'ol/render'\nimport { Options as FlowOptions } from 'ol/layer/Flow'\nimport VectorSource from 'ol/source/Vector'\nimport WebGLVectorLayer from 'ol/layer/WebGLVector'\nimport GeoJSON from 'ol/format/GeoJSON'\nimport { get as getProjection } from 'ol/proj'\nimport { createXYZ, wrapX } from 'ol/tilegrid'\n\n/**\n * 바람 벡터 데이터 포인트 인터페이스\n */\ninterface WindPoint {\n x: number\n y: number\n u: number\n v: number\n speed: number\n direction?: number\n}\n\n/**\n * 바람 레이어 클래스\n * OpenLayers Flow 레이어를 사용하여 바람 흐름을 표현합니다.\n * https://github.com/openlayers/openlayers/blob/v10.4.0/examples/wind.js 참고\n */\nexport class WindLayer extends BaseWeatherLayer {\n private windLayer?: BaseLayer\n private windSource?: DataTileSource\n protected layerType = 'wind'\n\n // 바람 속도 범위 설정\n private maxSpeed = 15 // 최대 바람 속도 (m/s)\n private minSpeed = 0 // 최소 바람 속도\n\n // 타일 생성 관련 설정\n private tileGrid = createXYZ()\n private tileSize = 256\n private weatherPoints: Array<{\n lon: number\n lat: number\n u: number\n v: number\n speed: number\n }> = []\n\n /**\n * 생성자\n */\n constructor(options: any = {}) {\n super()\n\n // 옵션 설정\n this.maxSpeed = options.maxSpeed || 15\n }\n\n /**\n * 레이어 타입 반환\n */\n getType(): WeatherLayerType {\n return 'wind' as WeatherLayerType\n }\n\n /**\n * 레이어 생성\n * OpenLayers Flow 레이어를 사용하여 바람 흐름을 표현합니다.\n * OpenLayers 공식 예제 참고: https://github.com/openlayers/openlayers/blob/v10.4.0/examples/wind.js\n */\n createLayer(): BaseLayer {\n console.log('바람 레이어 생성 중...')\n\n // 이미 생성된 레이어가 있다면 반환\n if (this.windLayer) {\n return this.windLayer\n }\n\n // 날씨 데이터를 풍속 벡터로 변환 (바람 데이터 준비)\n this.prepareWindData()\n\n try {\n // 바람 데이터 소스 생성\n this.windSource = new DataTileSource({\n tileGrid: this.tileGrid,\n // transition must be 0, see https://github.com/openlayers/openlayers/issues/16119\n transition: 0,\n wrapX: true,\n loader: (z, x, y) => {\n return this.createWindTile(z, x, y)\n }\n })\n\n // 실제 바람 데이터의 속도 범위 확인\n let minSpeed = Infinity\n let maxSpeed = 0\n let totalSpeed = 0\n\n this.weatherPoints.forEach(point => {\n minSpeed = Math.min(minSpeed, point.speed)\n maxSpeed = Math.max(maxSpeed, point.speed)\n totalSpeed += point.speed\n })\n\n const avgSpeed = totalSpeed / this.weatherPoints.length\n console.log(`바람 속도 범위: ${minSpeed.toFixed(2)}~${maxSpeed.toFixed(2)} m/s, 평균: ${avgSpeed.toFixed(2)} m/s`)\n\n // 효과적인 최대 속도 설정 (데이터 기반)\n const effectiveMaxSpeed = maxSpeed > 0 ? Math.max(10, maxSpeed) : 10\n this.maxSpeed = effectiveMaxSpeed\n\n console.log(`Flow 레이어 최대 속도: ${effectiveMaxSpeed.toFixed(2)} m/s`)\n\n // Flow 레이어 옵션 설정 - 단일 스타일 사용\n const flowOptions: any = {\n source: this.windSource,\n zIndex: 10,\n className: 'wind-layer',\n maxSpeed: this.maxSpeed,\n // 파티클 세부 설정 최적화\n tracksPerPixel: 0.5, // 트랙 밀도 증가 (더 많은 입자)\n fadeTrails: true, // 트레일 페이드 효과\n trailLength: 0.45, // 중간 길이 트레일\n // 단일 색상 스타일 - 주의: 복잡한 표현식 사용하지 않음\n style: {\n color: 'rgba(0, 191, 255, 0.8)', // 하늘색 (DeepSkyBlue)\n width: 1.5\n }\n }\n\n // @ts-ignore - Flow 레이어는 TypeScript 정의가 불완전할 수 있음\n this.windLayer = new Flow(flowOptions)\n console.log('Flow 레이어 생성 완료')\n return this.windLayer\n } catch (error) {\n console.error('Flow 레이어 생성 중 오류:', error)\n\n // 오류 발생 시 완전히 단순화된 옵션으로 다시 시도\n try {\n console.log('완전히 단순화된 옵션으로 다시 시도합니다...')\n const verySimpleOptions: any = {\n source: this.windSource,\n zIndex: 10,\n className: 'wind-layer',\n maxSpeed: this.maxSpeed\n }\n\n // @ts-ignore\n this.windLayer = new Flow(verySimpleOptions)\n console.log('단순 Flow 레이어 생성 완료')\n return this.windLayer\n } catch (fallbackError) {\n console.error('단순 Flow 레이어 생성도 실패:', fallbackError)\n return new BaseLayer({})\n }\n }\n }\n\n /**\n * 날씨 데이터에서 바람 정보 추출\n */\n private prepareWindData(): void {\n this.weatherPoints = []\n\n if (!this.weatherData || this.weatherData.length === 0) {\n console.warn('날씨 데이터가 없어 목업 데이터를 생성합니다.')\n this.createMockWindData()\n return\n }\n\n console.log(`${this.weatherData.length}개의 날씨 데이터에서 바람 정보 추출 중...`)\n\n // 유효한 바람 데이터만 추출\n this.weatherData.forEach(data => {\n if (\n data.wind &&\n data.location &&\n typeof data.wind.speed === 'number' &&\n typeof data.wind.direction === 'number' &&\n !isNaN(data.wind.speed) &&\n !isNaN(data.wind.direction) &&\n typeof data.location.longitude === 'number' &&\n typeof data.location.latitude === 'number'\n ) {\n // 각도를 라디안으로 변환 (바람 방향은 북쪽이 0도, 시계방향으로 증가)\n const dirRad = (data.wind.direction * Math.PI) / 180\n\n // u, v 성분 계산 (동서/남북 벡터)\n // 참고: 바람 벡터는 바람이 불어오는 방향이므로 변환 필요\n const u = -Math.sin(dirRad) * data.wind.speed\n const v = -Math.cos(dirRad) * data.wind.speed\n\n this.weatherPoints.push({\n lon: data.location.longitude,\n lat: data.location.latitude,\n u: u,\n v: v,\n speed: data.wind.speed\n })\n }\n })\n\n console.log(`바람 데이터 추출 완료: ${this.weatherPoints.length}개 포인트`)\n\n // 데이터가 없으면 목업 데이터 생성\n if (this.weatherPoints.length === 0) {\n console.warn('유효한 바람 데이터가 없어 목업 데이터를 생성합니다.')\n this.createMockWindData()\n }\n }\n\n /**\n * 목업 바람 데이터 생성\n */\n private createMockWindData(): void {\n console.log('목업 바람 데이터 생성 중...')\n this.weatherPoints = []\n\n // 한국 영역에 그리드 형태로 바람 데이터 생성\n const lonMin = 124.0\n const lonMax = 132.0\n const latMin = 33.0\n const latMax = 38.0\n\n const cols = 15\n const rows = 15\n\n for (let i = 0; i <= cols; i++) {\n for (let j = 0; j <= rows; j++) {\n const lon = lonMin + (i / cols) * (lonMax - lonMin)\n const lat = latMin + (j / rows) * (latMax - latMin)\n\n // 위치에 따라 달라지는 패턴 생성\n const patternX = Math.sin(lon * 0.5) * 2\n const patternY = Math.cos(lat * 0.5) * 2\n\n // 바람 속도와 방향 계산 (목업 데이터)\n const speed = 5 + 5 * Math.sin((lon + lat) * 0.2)\n\n // u, v 벡터 성분 (동서/남북)\n const u = (patternX * speed) / 5\n const v = (patternY * speed) / 5\n\n this.weatherPoints.push({\n lon,\n lat,\n u,\n v,\n speed\n })\n }\n }\n\n console.log(`목업 바람 데이터 생성 완료: ${this.weatherPoints.length}개 포인트`)\n }\n\n /**\n * 타일에 바람 데이터 생성\n */\n private createWindTile(z: number, x: number, y: number): Float32Array {\n // 타일 범위 계산\n const projection = getProjection('EPSG:3857')\n if (!projection) {\n console.error('EPSG:3857 투영 생성 실패')\n return new Float32Array(this.tileSize * this.tileSize * 4)\n }\n\n const tileCoord = wrapX(this.tileGrid, [z, x, y], projection)\n const extent = this.tileGrid.getTileCoordExtent(tileCoord)\n const resolution = this.tileGrid.getResolution(z as number)\n\n // 타일 데이터 생성 (RGBA 형식: u, v, speed, 0)\n const data = new Float32Array(this.tileSize * this.tileSize * 4)\n\n // 데이터가 없을 경우\n if (this.weatherPoints.length === 0) {\n // 빈 데이터 반환 (모든 값 0)\n return data\n }\n\n // 타일의 각 픽셀에 대해 바람 벡터 계산\n for (let row = 0; row < this.tileSize; ++row) {\n for (let col = 0; col < this.tileSize; ++col) {\n // 픽셀 위치를 지리 좌표로 변환\n const mapX = extent[0] + col * resolution\n const mapY = extent[3] - row * resolution\n\n // 메르카토르 좌표를 경위도로 변환\n const lonlat = transform([mapX, mapY], 'EPSG:3857', 'EPSG:4326')\n const lon = lonlat[0]\n const lat = lonlat[1]\n\n // 주변 바람 데이터를 기반으로 보간\n const vector = this.interpolateWindVector(lon, lat)\n\n // 벡터 크기 조정 (너무 작은 값은 시각적으로 보이지 않음)\n const normalizedSpeed = vector.speed / this.maxSpeed\n let adjustedU = vector.u\n let adjustedV = vector.v\n\n // 너무 작은 벡터는 약간 증폭\n if (normalizedSpeed > 0 && normalizedSpeed < 0.1) {\n const amplification = 0.1 / normalizedSpeed\n adjustedU *= Math.min(amplification, 2)\n adjustedV *= Math.min(amplification, 2)\n }\n\n // 데이터 저장 (RGBA 형식)\n const offset = (row * this.tileSize + col) * 4\n data[offset] = adjustedU // R = u (동서 방향)\n data[offset + 1] = adjustedV // G = v (남북 방향)\n data[offset + 2] = vector.speed // B = 풍속\n data[offset + 3] = 1 // A = 사용 (중요: 값을 1로 설정)\n }\n }\n\n return data\n }\n\n /**\n * 주어진 위치의 바람 벡터를 보간하여 반환\n */\n private interpolateWindVector(lon: number, lat: number): { u: number; v: number; speed: number } {\n if (this.weatherPoints.length === 0) {\n return { u: 0, v: 0, speed: 0 }\n }\n\n // 역거리 가중치 방식(IDW) 보간 사용\n let totalWeight = 0\n let weightedU = 0\n let weightedV = 0\n\n // 주변 포인트를 찾아 가중 평균 계산\n this.weatherPoints.forEach(point => {\n // 거리 계산 (단순화된 버전)\n const dx = lon - point.lon\n const dy = lat - point.lat\n const dist = Math.sqrt(dx * dx + dy * dy)\n\n // 가중치 계산 (거리 제곱의 역수)\n const weight = 1 / Math.max(0.0001, dist * dist)\n\n totalWeight += weight\n weightedU += point.u * weight\n weightedV += point.v * weight\n })\n\n if (totalWeight === 0) {\n return { u: 0, v: 0, speed: 0 }\n }\n\n // 가중 평균\n const u = weightedU / totalWeight\n const v = weightedV / totalWeight\n const speed = Math.sqrt(u * u + v * v)\n\n return { u, v, speed }\n }\n\n /**\n * 레이어 가시성 설정\n */\n setVisible(visible: boolean): void {\n if (this.windLayer) {\n this.windLayer.setVisible(visible)\n }\n }\n\n /**\n * 레이어 제거\n */\n public removeLayer(): void {\n if (this.map && this.windLayer) {\n this.map.removeLayer(this.windLayer)\n this.windLayer = undefined\n }\n }\n\n /**\n * 레이어 업데이트\n */\n protected updateLayer() {\n if (!this.map || !this.windLayer) {\n return\n }\n\n this.prepareWindData()\n\n if (this.windSource) {\n this.windSource.refresh()\n }\n }\n}\n"]}
@@ -0,0 +1,112 @@
1
+ import { LitElement } from 'lit';
2
+ import { WeatherLayerType } from './types.js';
3
+ /**
4
+ * 날씨 시각화 웹 컴포넌트
5
+ */
6
+ export declare class OxWeather extends LitElement {
7
+ /**
8
+ * 지도 객체
9
+ */
10
+ private map?;
11
+ /**
12
+ * 지도가 초기화되었는지 여부
13
+ */
14
+ private mapInitialized;
15
+ /**
16
+ * 날씨 데이터 서비스
17
+ */
18
+ private weatherService;
19
+ /**
20
+ * 날씨 데이터
21
+ */
22
+ private weatherData;
23
+ /**
24
+ * 날씨 레이어 목록
25
+ */
26
+ private weatherLayers;
27
+ /**
28
+ * 위도 (지도 중심점)
29
+ */
30
+ latitude: number;
31
+ /**
32
+ * 경도 (지도 중심점)
33
+ */
34
+ longitude: number;
35
+ /**
36
+ * 줌 레벨
37
+ */
38
+ zoom: number;
39
+ /**
40
+ * 활성 레이어 목록
41
+ * - 'wind': 바람 레이어
42
+ * - 'precipitation': 강수량 레이어
43
+ * - 'temperature': 온도 레이어
44
+ * - 'solar': 일사량 레이어
45
+ */
46
+ activeLayers: WeatherLayerType[];
47
+ /**
48
+ * 날씨 데이터 업데이트 쓰로틀링 관련 변수
49
+ */
50
+ private lastUpdateTime;
51
+ private updateThrottleDelay;
52
+ private updatePending;
53
+ isLoading: boolean;
54
+ /**
55
+ * 컴포넌트 스타일
56
+ */
57
+ static styles: import("lit").CSSResult;
58
+ /**
59
+ * 컴포넌트 초기화
60
+ */
61
+ connectedCallback(): void;
62
+ /**
63
+ * 첫 번째 업데이트 후 호출 (DOM 접근 가능)
64
+ */
65
+ firstUpdated(): void;
66
+ /**
67
+ * 지도를 초기화합니다.
68
+ */
69
+ private initMap;
70
+ /**
71
+ * 초기 날씨 데이터를 가져옵니다.
72
+ */
73
+ private initWeatherData;
74
+ /**
75
+ * 날씨 데이터를 가져옵니다.
76
+ */
77
+ private fetchWeatherData;
78
+ /**
79
+ * 날씨 데이터를 업데이트합니다
80
+ */
81
+ private updateWeatherData;
82
+ /**
83
+ * 날씨 데이터와 활성 레이어가 변경될 때 레이어 업데이트
84
+ */
85
+ updated(changedProperties: any): void;
86
+ /**
87
+ * 날씨 레이어를 비동기적으로 업데이트합니다.
88
+ */
89
+ private updateLayersAsync;
90
+ /**
91
+ * 날씨 레이어를 업데이트합니다.
92
+ */
93
+ private updateLayers;
94
+ /**
95
+ * 레이어가 이미 맵에 있는지 확인합니다.
96
+ * 심층 비교를 통해 정확하게 체크합니다.
97
+ */
98
+ private isLayerInMap;
99
+ /**
100
+ * 바람 레이어 토글 처리 (특별 관리)
101
+ */
102
+ private handleWindLayerToggle;
103
+ /**
104
+ * 바람 레이어 업데이트 (최적화)
105
+ */
106
+ private updateWindLayer;
107
+ /**
108
+ * 레이어 토글 처리
109
+ */
110
+ private handleLayerToggle;
111
+ render(): import("lit-html").TemplateResult<1>;
112
+ }