aiqtech commited on
Commit
55df423
ยท
verified ยท
1 Parent(s): 5377d50

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +601 -19
index.html CHANGED
@@ -1,19 +1,601 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="ko">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>๋””์ง€ํ„ธ ๋“ฑ๊ณ ์„  ์ง€ํ˜• ์ง€๋„</title>
7
+ <style>
8
+ * {
9
+ margin: 0;
10
+ padding: 0;
11
+ box-sizing: border-box;
12
+ }
13
+
14
+ body {
15
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
16
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
17
+ min-height: 100vh;
18
+ display: flex;
19
+ justify-content: center;
20
+ align-items: center;
21
+ padding: 20px;
22
+ }
23
+
24
+ .container {
25
+ background: rgba(255, 255, 255, 0.95);
26
+ border-radius: 20px;
27
+ padding: 30px;
28
+ box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
29
+ max-width: 1200px;
30
+ width: 100%;
31
+ }
32
+
33
+ h1 {
34
+ text-align: center;
35
+ color: #333;
36
+ margin-bottom: 10px;
37
+ font-size: 2em;
38
+ background: linear-gradient(135deg, #667eea, #764ba2);
39
+ -webkit-background-clip: text;
40
+ -webkit-text-fill-color: transparent;
41
+ }
42
+
43
+ .map-container {
44
+ position: relative;
45
+ margin: 20px auto;
46
+ border-radius: 10px;
47
+ overflow: hidden;
48
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
49
+ }
50
+
51
+ canvas {
52
+ display: block;
53
+ cursor: crosshair;
54
+ width: 100%;
55
+ height: auto;
56
+ }
57
+
58
+ .controls {
59
+ display: flex;
60
+ justify-content: center;
61
+ gap: 15px;
62
+ margin: 20px 0;
63
+ flex-wrap: wrap;
64
+ }
65
+
66
+ button {
67
+ padding: 12px 24px;
68
+ background: linear-gradient(135deg, #667eea, #764ba2);
69
+ color: white;
70
+ border: none;
71
+ border-radius: 25px;
72
+ cursor: pointer;
73
+ font-size: 14px;
74
+ font-weight: 600;
75
+ transition: all 0.3s ease;
76
+ box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
77
+ }
78
+
79
+ button:hover {
80
+ transform: translateY(-2px);
81
+ box-shadow: 0 6px 20px rgba(102, 126, 234, 0.6);
82
+ }
83
+
84
+ button:active {
85
+ transform: translateY(0);
86
+ }
87
+
88
+ .info-panel {
89
+ background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
90
+ padding: 15px;
91
+ border-radius: 10px;
92
+ margin-top: 20px;
93
+ display: flex;
94
+ justify-content: space-around;
95
+ flex-wrap: wrap;
96
+ gap: 15px;
97
+ }
98
+
99
+ .info-item {
100
+ text-align: center;
101
+ padding: 10px;
102
+ background: white;
103
+ border-radius: 8px;
104
+ min-width: 120px;
105
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
106
+ }
107
+
108
+ .info-label {
109
+ font-size: 12px;
110
+ color: #666;
111
+ margin-bottom: 5px;
112
+ text-transform: uppercase;
113
+ letter-spacing: 1px;
114
+ }
115
+
116
+ .info-value {
117
+ font-size: 18px;
118
+ font-weight: bold;
119
+ color: #333;
120
+ }
121
+
122
+ .legend {
123
+ display: flex;
124
+ align-items: center;
125
+ justify-content: center;
126
+ gap: 20px;
127
+ margin-top: 20px;
128
+ padding: 15px;
129
+ background: #f8f9fa;
130
+ border-radius: 10px;
131
+ }
132
+
133
+ .legend-item {
134
+ display: flex;
135
+ align-items: center;
136
+ gap: 8px;
137
+ }
138
+
139
+ .legend-color {
140
+ width: 30px;
141
+ height: 20px;
142
+ border-radius: 4px;
143
+ border: 1px solid #ddd;
144
+ }
145
+
146
+ .tooltip {
147
+ position: absolute;
148
+ background: rgba(0, 0, 0, 0.9);
149
+ color: white;
150
+ padding: 8px 12px;
151
+ border-radius: 6px;
152
+ font-size: 14px;
153
+ pointer-events: none;
154
+ z-index: 1000;
155
+ display: none;
156
+ transition: all 0.2s ease;
157
+ }
158
+
159
+ select {
160
+ padding: 10px 15px;
161
+ border-radius: 8px;
162
+ border: 2px solid #667eea;
163
+ background: white;
164
+ font-size: 14px;
165
+ cursor: pointer;
166
+ transition: all 0.3s ease;
167
+ }
168
+
169
+ select:hover {
170
+ border-color: #764ba2;
171
+ }
172
+
173
+ select:focus {
174
+ outline: none;
175
+ box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.2);
176
+ }
177
+ </style>
178
+ </head>
179
+ <body>
180
+ <div class="container">
181
+ <h1>๐Ÿ—บ๏ธ ๋””์ง€ํ„ธ ๋“ฑ๊ณ ์„  ์ง€ํ˜• ์ง€๋„</h1>
182
+
183
+ <div class="controls">
184
+ <button onclick="generateNewTerrain()">๐Ÿ”๏ธ ์ƒˆ๋กœ์šด ์ง€ํ˜• ์ƒ์„ฑ</button>
185
+ <button onclick="toggleContours()">๐Ÿ“Š ๋“ฑ๊ณ ์„  ํ‘œ์‹œ/์ˆจ๊ธฐ๊ธฐ</button>
186
+ <button onclick="toggleHeatmap()">๐ŸŒก๏ธ ํžˆํŠธ๋งต ์ „ํ™˜</button>
187
+ <button onclick="toggle3D()">๐ŸŽฎ 3D ๋ทฐ ์ „ํ™˜</button>
188
+ <select id="terrainType" onchange="changeTerrainType()">
189
+ <option value="mountain">โ›ฐ๏ธ ์‚ฐ์•… ์ง€ํ˜•</option>
190
+ <option value="valley">๐Ÿž๏ธ ๊ณ„๊ณก ์ง€ํ˜•</option>
191
+ <option value="plateau">๐Ÿ”๏ธ ๊ณ ์› ์ง€ํ˜•</option>
192
+ <option value="island">๐Ÿ๏ธ ์„ฌ ์ง€ํ˜•</option>
193
+ </select>
194
+ <button onclick="exportMap()">๐Ÿ’พ ์ง€๋„ ์ €์žฅ</button>
195
+ </div>
196
+
197
+ <div class="map-container">
198
+ <canvas id="mapCanvas"></canvas>
199
+ <div class="tooltip" id="tooltip"></div>
200
+ </div>
201
+
202
+ <div class="info-panel">
203
+ <div class="info-item">
204
+ <div class="info-label">์ขŒํ‘œ</div>
205
+ <div class="info-value" id="coordinates">-</div>
206
+ </div>
207
+ <div class="info-item">
208
+ <div class="info-label">๊ณ ๋„</div>
209
+ <div class="info-value" id="elevation">-</div>
210
+ </div>
211
+ <div class="info-item">
212
+ <div class="info-label">๊ฒฝ์‚ฌ๋„</div>
213
+ <div class="info-value" id="slope">-</div>
214
+ </div>
215
+ <div class="info-item">
216
+ <div class="info-label">๋“ฑ๊ณ ์„  ๊ฐ„๊ฒฉ</div>
217
+ <div class="info-value">10m</div>
218
+ </div>
219
+ </div>
220
+
221
+ <div class="legend">
222
+ <div class="legend-item">
223
+ <div class="legend-color" style="background: #0d4f8b;"></div>
224
+ <span>๋‚ฎ์€ ๊ณ ๋„ (0-200m)</span>
225
+ </div>
226
+ <div class="legend-item">
227
+ <div class="legend-color" style="background: #61a861;"></div>
228
+ <span>์ค‘๊ฐ„ ๊ณ ๋„ (200-500m)</span>
229
+ </div>
230
+ <div class="legend-item">
231
+ <div class="legend-color" style="background: #f5deb3;"></div>
232
+ <span>๋†’์€ ๊ณ ๋„ (500-800m)</span>
233
+ </div>
234
+ <div class="legend-item">
235
+ <div class="legend-color" style="background: #8b4513;"></div>
236
+ <span>์ตœ๊ณ  ๊ณ ๋„ (800m+)</span>
237
+ </div>
238
+ </div>
239
+ </div>
240
+
241
+ <script>
242
+ const canvas = document.getElementById('mapCanvas');
243
+ const ctx = canvas.getContext('2d');
244
+ const tooltip = document.getElementById('tooltip');
245
+
246
+ // ์บ”๋ฒ„์Šค ํฌ๊ธฐ ์„ค์ •
247
+ const WIDTH = 800;
248
+ const HEIGHT = 600;
249
+ canvas.width = WIDTH;
250
+ canvas.height = HEIGHT;
251
+
252
+ // ์ง€ํ˜• ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•  ๋ฐฐ์—ด
253
+ let heightMap = [];
254
+ let showContours = true;
255
+ let showHeatmap = false;
256
+ let is3D = false;
257
+ let terrainType = 'mountain';
258
+
259
+ // ๋…ธ์ด์ฆˆ ํ•จ์ˆ˜ (Perlin noise ๊ฐ„๋‹จ ๊ตฌํ˜„)
260
+ function noise(x, y, scale, octaves) {
261
+ let value = 0;
262
+ let amplitude = 1;
263
+ let frequency = scale;
264
+ let maxValue = 0;
265
+
266
+ for (let i = 0; i < octaves; i++) {
267
+ value += amplitude * simpleNoise(x * frequency, y * frequency);
268
+ maxValue += amplitude;
269
+ amplitude *= 0.5;
270
+ frequency *= 2;
271
+ }
272
+
273
+ return value / maxValue;
274
+ }
275
+
276
+ function simpleNoise(x, y) {
277
+ const n = Math.sin(x * 12.9898 + y * 78.233) * 43758.5453;
278
+ return (n - Math.floor(n)) * 2 - 1;
279
+ }
280
+
281
+ // ์ง€ํ˜• ์ƒ์„ฑ ํ•จ์ˆ˜
282
+ function generateTerrain() {
283
+ heightMap = [];
284
+ const gridSize = 100;
285
+
286
+ for (let y = 0; y < gridSize; y++) {
287
+ heightMap[y] = [];
288
+ for (let x = 0; x < gridSize; x++) {
289
+ let height = 0;
290
+
291
+ switch(terrainType) {
292
+ case 'mountain':
293
+ // ์‚ฐ์•… ์ง€ํ˜•
294
+ height = noise(x, y, 0.02, 6) * 0.6;
295
+ height += noise(x, y, 0.05, 4) * 0.3;
296
+ height += noise(x, y, 0.1, 2) * 0.1;
297
+ height = Math.pow(Math.abs(height), 1.2) * Math.sign(height);
298
+ break;
299
+
300
+ case 'valley':
301
+ // ๊ณ„๊ณก ์ง€ํ˜•
302
+ const distX = (x - gridSize/2) / gridSize;
303
+ const distY = (y - gridSize/2) / gridSize;
304
+ const dist = Math.sqrt(distX*distX + distY*distY);
305
+ height = noise(x, y, 0.03, 4) * 0.5;
306
+ height *= (1 - dist * 0.5);
307
+ height -= dist * 0.3;
308
+ break;
309
+
310
+ case 'plateau':
311
+ // ๊ณ ์› ์ง€ํ˜•
312
+ height = noise(x, y, 0.02, 3) * 0.3;
313
+ if (height > 0.1) height = 0.3 + noise(x, y, 0.05, 2) * 0.1;
314
+ break;
315
+
316
+ case 'island':
317
+ // ์„ฌ ์ง€ํ˜•
318
+ const centerX = (x - gridSize/2) / gridSize;
319
+ const centerY = (y - gridSize/2) / gridSize;
320
+ const radius = Math.sqrt(centerX*centerX + centerY*centerY);
321
+ height = noise(x, y, 0.03, 5) * 0.6;
322
+ height *= Math.max(0, 1 - radius * 2);
323
+ break;
324
+ }
325
+
326
+ // ์ •๊ทœํ™” (0-1 ๋ฒ”์œ„)
327
+ height = Math.max(0, Math.min(1, (height + 1) / 2));
328
+ heightMap[y][x] = height;
329
+ }
330
+ }
331
+ }
332
+
333
+ // ๋“ฑ๊ณ ์„  ๊ณ„์‚ฐ
334
+ function calculateContours(interval) {
335
+ const contours = [];
336
+ const levels = [];
337
+
338
+ for (let level = 0; level <= 1; level += interval) {
339
+ levels.push(level);
340
+ }
341
+
342
+ return { contours, levels };
343
+ }
344
+
345
+ // ์ง€๋„ ๊ทธ๋ฆฌ๊ธฐ
346
+ function drawMap() {
347
+ ctx.clearRect(0, 0, WIDTH, HEIGHT);
348
+
349
+ const gridSize = heightMap.length;
350
+ const cellWidth = WIDTH / gridSize;
351
+ const cellHeight = HEIGHT / gridSize;
352
+
353
+ // ๋ฐฐ๊ฒฝ ๊ทธ๋ฆฌ๊ธฐ (๋†’์ด๋งต ๋˜๋Š” ํžˆํŠธ๋งต)
354
+ for (let y = 0; y < gridSize; y++) {
355
+ for (let x = 0; x < gridSize; x++) {
356
+ const height = heightMap[y][x];
357
+
358
+ if (showHeatmap) {
359
+ // ํžˆํŠธ๋งต ์ƒ‰์ƒ
360
+ const hue = (1 - height) * 240;
361
+ ctx.fillStyle = `hsl(${hue}, 70%, 50%)`;
362
+ } else {
363
+ // ์ง€ํ˜• ์ƒ‰์ƒ
364
+ ctx.fillStyle = getTerrainColor(height);
365
+ }
366
+
367
+ if (is3D) {
368
+ // 3D ํšจ๊ณผ
369
+ const offset = height * 10;
370
+ ctx.fillRect(
371
+ x * cellWidth + offset,
372
+ y * cellHeight - offset,
373
+ cellWidth + 1,
374
+ cellHeight + 1
375
+ );
376
+ } else {
377
+ ctx.fillRect(
378
+ x * cellWidth,
379
+ y * cellHeight,
380
+ cellWidth + 1,
381
+ cellHeight + 1
382
+ );
383
+ }
384
+ }
385
+ }
386
+
387
+ // ๋“ฑ๊ณ ์„  ๊ทธ๋ฆฌ๊ธฐ
388
+ if (showContours) {
389
+ ctx.strokeStyle = 'rgba(0, 0, 0, 0.3)';
390
+ ctx.lineWidth = 1;
391
+
392
+ const contourLevels = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9];
393
+
394
+ for (let level of contourLevels) {
395
+ ctx.beginPath();
396
+
397
+ for (let y = 0; y < gridSize - 1; y++) {
398
+ for (let x = 0; x < gridSize - 1; x++) {
399
+ const corners = [
400
+ heightMap[y][x],
401
+ heightMap[y][x + 1],
402
+ heightMap[y + 1][x + 1],
403
+ heightMap[y + 1][x]
404
+ ];
405
+
406
+ drawContourCell(
407
+ x * cellWidth,
408
+ y * cellHeight,
409
+ cellWidth,
410
+ cellHeight,
411
+ corners,
412
+ level
413
+ );
414
+ }
415
+ }
416
+
417
+ // ์ฃผ ๋“ฑ๊ณ ์„ ์€ ๊ตต๊ฒŒ
418
+ if (level % 0.2 === 0) {
419
+ ctx.lineWidth = 2;
420
+ ctx.strokeStyle = 'rgba(0, 0, 0, 0.5)';
421
+ } else {
422
+ ctx.lineWidth = 1;
423
+ ctx.strokeStyle = 'rgba(0, 0, 0, 0.3)';
424
+ }
425
+
426
+ ctx.stroke();
427
+ }
428
+ }
429
+
430
+ // ๊ทธ๋ฆฌ๋“œ ํ‘œ์‹œ
431
+ ctx.strokeStyle = 'rgba(255, 255, 255, 0.1)';
432
+ ctx.lineWidth = 0.5;
433
+ for (let i = 0; i <= gridSize; i += 10) {
434
+ ctx.beginPath();
435
+ ctx.moveTo(i * cellWidth, 0);
436
+ ctx.lineTo(i * cellWidth, HEIGHT);
437
+ ctx.stroke();
438
+
439
+ ctx.beginPath();
440
+ ctx.moveTo(0, i * cellHeight);
441
+ ctx.lineTo(WIDTH, i * cellHeight);
442
+ ctx.stroke();
443
+ }
444
+ }
445
+
446
+ // Marching squares ์•Œ๊ณ ๋ฆฌ์ฆ˜์œผ๋กœ ๋“ฑ๊ณ ์„  ๊ทธ๋ฆฌ๊ธฐ
447
+ function drawContourCell(x, y, width, height, corners, level) {
448
+ let state = 0;
449
+ if (corners[0] > level) state |= 1;
450
+ if (corners[1] > level) state |= 2;
451
+ if (corners[2] > level) state |= 4;
452
+ if (corners[3] > level) state |= 8;
453
+
454
+ switch(state) {
455
+ case 1: case 14:
456
+ drawLine(x, y + height * interpolate(corners[0], corners[3], level),
457
+ x + width * interpolate(corners[0], corners[1], level), y);
458
+ break;
459
+ case 2: case 13:
460
+ drawLine(x + width * interpolate(corners[0], corners[1], level), y,
461
+ x + width, y + height * interpolate(corners[1], corners[2], level));
462
+ break;
463
+ case 3: case 12:
464
+ drawLine(x, y + height * interpolate(corners[0], corners[3], level),
465
+ x + width, y + height * interpolate(corners[1], corners[2], level));
466
+ break;
467
+ case 4: case 11:
468
+ drawLine(x + width, y + height * interpolate(corners[1], corners[2], level),
469
+ x + width * interpolate(corners[3], corners[2], level), y + height);
470
+ break;
471
+ case 5:
472
+ drawLine(x, y + height * interpolate(corners[0], corners[3], level),
473
+ x + width * interpolate(corners[0], corners[1], level), y);
474
+ drawLine(x + width, y + height * interpolate(corners[1], corners[2], level),
475
+ x + width * interpolate(corners[3], corners[2], level), y + height);
476
+ break;
477
+ case 6: case 9:
478
+ drawLine(x + width * interpolate(corners[0], corners[1], level), y,
479
+ x + width * interpolate(corners[3], corners[2], level), y + height);
480
+ break;
481
+ case 7: case 8:
482
+ drawLine(x, y + height * interpolate(corners[0], corners[3], level),
483
+ x + width * interpolate(corners[3], corners[2], level), y + height);
484
+ break;
485
+ case 10:
486
+ drawLine(x + width * interpolate(corners[0], corners[1], level), y,
487
+ x + width, y + height * interpolate(corners[1], corners[2], level));
488
+ drawLine(x, y + height * interpolate(corners[0], corners[3], level),
489
+ x + width * interpolate(corners[3], corners[2], level), y + height);
490
+ break;
491
+ }
492
+ }
493
+
494
+ function interpolate(v1, v2, level) {
495
+ return (level - v1) / (v2 - v1);
496
+ }
497
+
498
+ function drawLine(x1, y1, x2, y2) {
499
+ ctx.moveTo(x1, y1);
500
+ ctx.lineTo(x2, y2);
501
+ }
502
+
503
+ // ์ง€ํ˜• ์ƒ‰์ƒ ๊ฒฐ์ •
504
+ function getTerrainColor(height) {
505
+ if (height < 0.2) return '#0d4f8b'; // ๊นŠ์€ ๋ฌผ
506
+ if (height < 0.3) return '#1e7eb8'; // ์–•์€ ๋ฌผ
507
+ if (height < 0.4) return '#61a861'; // ๋‚ฎ์€ ์ง€๋Œ€ (์ดˆ๋ก)
508
+ if (height < 0.5) return '#8fc68f'; // ํ‰์ง€
509
+ if (height < 0.6) return '#c4d4aa'; // ์–ธ๋•
510
+ if (height < 0.7) return '#f5deb3'; // ๋†’์€ ์–ธ๋•
511
+ if (height < 0.8) return '#d2b48c'; // ๋‚ฎ์€ ์‚ฐ
512
+ if (height < 0.9) return '#8b4513'; // ์‚ฐ
513
+ return '#fff'; // ๋ˆˆ ๋ฎ์ธ ์‚ฐ๊ผญ๋Œ€๊ธฐ
514
+ }
515
+
516
+ // ๋งˆ์šฐ์Šค ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ
517
+ canvas.addEventListener('mousemove', (e) => {
518
+ const rect = canvas.getBoundingClientRect();
519
+ const x = (e.clientX - rect.left) * (WIDTH / rect.width);
520
+ const y = (e.clientY - rect.top) * (HEIGHT / rect.height);
521
+
522
+ const gridSize = heightMap.length;
523
+ const gridX = Math.floor(x / (WIDTH / gridSize));
524
+ const gridY = Math.floor(y / (HEIGHT / gridSize));
525
+
526
+ if (gridX >= 0 && gridX < gridSize && gridY >= 0 && gridY < gridSize) {
527
+ const height = heightMap[gridY][gridX];
528
+ const elevation = Math.round(height * 1000);
529
+
530
+ // ๊ฒฝ์‚ฌ๋„ ๊ณ„์‚ฐ
531
+ let slope = 0;
532
+ if (gridX > 0 && gridX < gridSize - 1 && gridY > 0 && gridY < gridSize - 1) {
533
+ const dx = heightMap[gridY][gridX + 1] - heightMap[gridY][gridX - 1];
534
+ const dy = heightMap[gridY + 1][gridX] - heightMap[gridY - 1][gridX];
535
+ slope = Math.round(Math.sqrt(dx * dx + dy * dy) * 100);
536
+ }
537
+
538
+ document.getElementById('coordinates').textContent = `${gridX}, ${gridY}`;
539
+ document.getElementById('elevation').textContent = `${elevation}m`;
540
+ document.getElementById('slope').textContent = `${slope}ยฐ`;
541
+
542
+ // ํˆดํŒ ํ‘œ์‹œ
543
+ tooltip.style.display = 'block';
544
+ tooltip.style.left = e.clientX + 10 + 'px';
545
+ tooltip.style.top = e.clientY - 30 + 'px';
546
+ tooltip.textContent = `๊ณ ๋„: ${elevation}m`;
547
+ }
548
+ });
549
+
550
+ canvas.addEventListener('mouseleave', () => {
551
+ tooltip.style.display = 'none';
552
+ document.getElementById('coordinates').textContent = '-';
553
+ document.getElementById('elevation').textContent = '-';
554
+ document.getElementById('slope').textContent = '-';
555
+ });
556
+
557
+ // ์ปจํŠธ๋กค ํ•จ์ˆ˜๋“ค
558
+ function generateNewTerrain() {
559
+ generateTerrain();
560
+ drawMap();
561
+ }
562
+
563
+ function toggleContours() {
564
+ showContours = !showContours;
565
+ drawMap();
566
+ }
567
+
568
+ function toggleHeatmap() {
569
+ showHeatmap = !showHeatmap;
570
+ drawMap();
571
+ }
572
+
573
+ function toggle3D() {
574
+ is3D = !is3D;
575
+ drawMap();
576
+ }
577
+
578
+ function changeTerrainType() {
579
+ terrainType = document.getElementById('terrainType').value;
580
+ generateTerrain();
581
+ drawMap();
582
+ }
583
+
584
+ function exportMap() {
585
+ const link = document.createElement('a');
586
+ link.download = 'topographic-map.png';
587
+ link.href = canvas.toDataURL();
588
+ link.click();
589
+ }
590
+
591
+ // ์ดˆ๊ธฐํ™”
592
+ generateTerrain();
593
+ drawMap();
594
+
595
+ // ํ™”๋ฉด ํฌ๊ธฐ ๋ณ€๊ฒฝ ๋Œ€์‘
596
+ window.addEventListener('resize', () => {
597
+ drawMap();
598
+ });
599
+ </script>
600
+ </body>
601
+ </html>