Merge pull request 'feat: 특정어업수역 폴리곤 기반 수역 분류 + 연결선 성능 수정' (#96) from fix/fishing-overlay-perf into develop
This commit is contained in:
커밋
8b0bbf3d66
@ -5,6 +5,7 @@
|
||||
## [Unreleased]
|
||||
|
||||
### 추가
|
||||
- 특정어업수역 Ⅰ~Ⅳ 실제 폴리곤 기반 수역 분류 (경도 하드코딩 → point-in-polygon)
|
||||
- 중국어선 조업분석: AIS Ship Type 30 + 선박명 패턴 분류, GC-KCG-2026-001/CSSA 기반 안강망 추가
|
||||
- 중국어선 선단 탐지: 본선-부속선 쌍, 운반선 환적, 선망 선단
|
||||
- 어구/어망 카테고리 신설 + 모선 연결선 시각화
|
||||
@ -15,6 +16,9 @@
|
||||
- 정부기관 건물 레이어 (GovBuildingLayer)
|
||||
- CCTV 프록시 컨트롤러
|
||||
|
||||
### 수정
|
||||
- 중국어선감시 연결선 폭발 수정: 부분매칭 제거 + 거리제한 10NM + 마커 상한 200개
|
||||
|
||||
### 변경
|
||||
- 레이어 재구성: 선박(최상위) → 항공망 → 해양안전 → 국가기관망
|
||||
- 오른쪽 패널 접기/펼치기 기능
|
||||
|
||||
66
frontend/package-lock.json
generated
66
frontend/package-lock.json
generated
@ -9,6 +9,8 @@
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"@tailwindcss/vite": "^4.2.1",
|
||||
"@turf/boolean-point-in-polygon": "^7.3.4",
|
||||
"@turf/helpers": "^7.3.4",
|
||||
"@types/leaflet": "^1.9.21",
|
||||
"date-fns": "^4.1.0",
|
||||
"hls.js": "^1.6.15",
|
||||
@ -1628,6 +1630,49 @@
|
||||
"vite": "^5.2.0 || ^6 || ^7"
|
||||
}
|
||||
},
|
||||
"node_modules/@turf/boolean-point-in-polygon": {
|
||||
"version": "7.3.4",
|
||||
"resolved": "https://registry.npmjs.org/@turf/boolean-point-in-polygon/-/boolean-point-in-polygon-7.3.4.tgz",
|
||||
"integrity": "sha512-v/4hfyY90Vz9cDgs2GwjQf+Lft8o7mNCLJOTz/iv8SHAIgMMX0czEoIaNVOJr7tBqPqwin1CGwsncrkf5C9n8Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@turf/helpers": "7.3.4",
|
||||
"@turf/invariant": "7.3.4",
|
||||
"@types/geojson": "^7946.0.10",
|
||||
"point-in-polygon-hao": "^1.1.0",
|
||||
"tslib": "^2.8.1"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/turf"
|
||||
}
|
||||
},
|
||||
"node_modules/@turf/helpers": {
|
||||
"version": "7.3.4",
|
||||
"resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.3.4.tgz",
|
||||
"integrity": "sha512-U/S5qyqgx3WTvg4twaH0WxF3EixoTCfDsmk98g1E3/5e2YKp7JKYZdz0vivsS5/UZLJeZDEElOSFH4pUgp+l7g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/geojson": "^7946.0.10",
|
||||
"tslib": "^2.8.1"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/turf"
|
||||
}
|
||||
},
|
||||
"node_modules/@turf/invariant": {
|
||||
"version": "7.3.4",
|
||||
"resolved": "https://registry.npmjs.org/@turf/invariant/-/invariant-7.3.4.tgz",
|
||||
"integrity": "sha512-88Eo4va4rce9sNZs6XiMJowWkikM3cS2TBhaCKlU+GFHdNf8PFEpiU42VDU8q5tOF6/fu21Rvlke5odgOGW4AQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@turf/helpers": "7.3.4",
|
||||
"@types/geojson": "^7946.0.10",
|
||||
"tslib": "^2.8.1"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/turf"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/babel__core": {
|
||||
"version": "7.20.5",
|
||||
"dev": true,
|
||||
@ -3579,6 +3624,15 @@
|
||||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
}
|
||||
},
|
||||
"node_modules/point-in-polygon-hao": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/point-in-polygon-hao/-/point-in-polygon-hao-1.2.4.tgz",
|
||||
"integrity": "sha512-x2pcvXeqhRHlNRdhLs/tgFapAbSSe86wa/eqmj1G6pWftbEs5aVRJhRGM6FYSUERKu0PjekJzMq0gsI2XyiclQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"robust-predicates": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/postcss": {
|
||||
"version": "8.5.8",
|
||||
"funding": [
|
||||
@ -3805,6 +3859,12 @@
|
||||
"protocol-buffers-schema": "^3.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/robust-predicates": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz",
|
||||
"integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==",
|
||||
"license": "Unlicense"
|
||||
},
|
||||
"node_modules/rollup": {
|
||||
"version": "4.59.0",
|
||||
"license": "MIT",
|
||||
@ -4043,6 +4103,12 @@
|
||||
"typescript": ">=4.8.4"
|
||||
}
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "2.8.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
||||
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
||||
"license": "0BSD"
|
||||
},
|
||||
"node_modules/type-check": {
|
||||
"version": "0.4.0",
|
||||
"dev": true,
|
||||
|
||||
@ -11,6 +11,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@tailwindcss/vite": "^4.2.1",
|
||||
"@turf/boolean-point-in-polygon": "^7.3.4",
|
||||
"@turf/helpers": "^7.3.4",
|
||||
"@types/leaflet": "^1.9.21",
|
||||
"date-fns": "^4.1.0",
|
||||
"hls.js": "^1.6.15",
|
||||
|
||||
1
frontend/src/data/zones/특정어업수역Ⅰ.json
Normal file
1
frontend/src/data/zones/특정어업수역Ⅰ.json
Normal file
File diff suppressed because one or more lines are too long
1
frontend/src/data/zones/특정어업수역Ⅱ.json
Normal file
1
frontend/src/data/zones/특정어업수역Ⅱ.json
Normal file
File diff suppressed because one or more lines are too long
1
frontend/src/data/zones/특정어업수역Ⅲ.json
Normal file
1
frontend/src/data/zones/특정어업수역Ⅲ.json
Normal file
File diff suppressed because one or more lines are too long
1
frontend/src/data/zones/특정어업수역Ⅳ.json
Normal file
1
frontend/src/data/zones/특정어업수역Ⅳ.json
Normal file
@ -0,0 +1 @@
|
||||
{"type": "FeatureCollection", "name": "\ud2b9\uc815\uc5b4\uc5c5\uc218\uc5ed4", "crs": {"type": "name", "properties": {"name": "urn:ogc:def:crs:OGC:1.3:CRS84"}}, "features": [{"type": "Feature", "properties": {"fid": 0, "GML_ID": null, "OBJECTID": null, "ZONE_NM": null, "MNCT_NO": null, "MNCT_SCALE": null, "MNCT_NM": null, "RELREGLTN": null, "RELGOAG": null, "REVIYR": null, "ZONE_DESC": null, "PHOTO1_PAT": null, "ID": -2147483647, "CATE_CD": null, "ADR_CD": null, "ADR_KNM": null, "ORIGIN": null, "ORIYR": null, "ORIORG": null, "NAME": "\ud2b9\uc815\uc5b4\uc5c5\uc218\uc5ed\u2163", "WARD_NM": null, "WARD_ID": null, "GISID": null, "FID_2": null, "NAME_2": null, "FID_3": null, "NAME_3": null, "GID": null, "NAME_4": null, "FID_4": null, "NAME_5": null, "FID_5": null, "NAME_6": null}, "geometry": {"type": "MultiPolygon", "coordinates": [[[[13859276.603817873, 4232038.462456921], [13859276.603762543, 4321218.244482412], [13859276.603710985, 4404317.064005076], [13840719.645028654, 4439106.786523586], [13884632.712472571, 4439106.787250583], [13884632.712472571, 4439504.084564682], [13940418.269436067, 4439504.375880923], [13969123.924724836, 4439504.525783945], [13968718.329494288, 4438626.439593866], [13962623.599395147, 4425543.915710401], [13960437.31344761, 4420657.3891166765], [13958238.813611617, 4416093.569832627], [13958143.094601436, 4415900.994484875], [13958143.094601437, 4415900.994484875], [13957298.344237303, 4414201.456484755], [13953878.455604602, 4406316.186534493], [13949652.450365951, 4397019.979821594], [13948553.200448176, 4393395.13065616], [13947612.731073817, 4389132.176741289], [13947612.731072996, 4387549.226905922], [13947466.164417507, 4385829.556682826], [13947783.725505754, 4381721.729468383], [13948260.06713652, 4379835.70012994], [13949359.317054221, 4375897.403884492], [13951093.689146286, 4371808.582233328], [13954867.780530114, 4365670.678186072], [13964809.885341855, 4351190.629491161], [13978342.873219142, 4331838.456925102], [13980382.592510404, 4329007.496874151], [13981728.043604897, 4327079.749205159], [13985775.34591557, 4321280.81855131], [13997066.763484716, 4305102.598482491], [13999424.043863578, 4300225.286038025], [14003039.354703771, 4290447.064438686], [14005091.287883686, 4284626.561498255], [14006520.312777169, 4279426.932176922], [14007631.77658257, 4275178.643476352], [14008242.470981453, 4271549.325573796], [14009378.362562515, 4262248.123573576], [14009427.990871342, 4261704.85208626], [14009708.137538105, 4258638.140769343], [14009854.704193696, 4257224.555715567], [14009378.362562606, 4254698.603440943], [14005347.779531531, 4240996.452433007], [14002367.590864772, 4231511.1380338315], [14001280.554835469, 4227266.412716273], [14000486.652116666, 4225212.134400094], [13998047.81589918, 4222926.459154359], [13991387.305576058, 4216684.234498038], [13970721.407121927, 4197120.494488488], [13958654.085803084, 4185745.4565721145], [13956602.15262321, 4184012.5742896623], [13944065.033685392, 4171984.566055202], [13940467.606607554, 4168533.224265296], [13935619.01320107, 4163881.1438622964], [13935718.55954324, 4163976.6556012244], [13817590.293393573, 4163976.6556012244], [13859276.603817873, 4232038.462456921]]]]}}]}
|
||||
@ -2,6 +2,14 @@
|
||||
// 한중어업협정 허가현황 (2026.01.06, 906척) + GB/T 5147-2003 어구 분류
|
||||
|
||||
import type { Ship } from '../types';
|
||||
import booleanPointInPolygon from '@turf/boolean-point-in-polygon';
|
||||
import { point, multiPolygon } from '@turf/helpers';
|
||||
import type { Feature, MultiPolygon } from 'geojson';
|
||||
|
||||
import zone1Data from '../data/zones/특정어업수역Ⅰ.json';
|
||||
import zone2Data from '../data/zones/특정어업수역Ⅱ.json';
|
||||
import zone3Data from '../data/zones/특정어업수역Ⅲ.json';
|
||||
import zone4Data from '../data/zones/특정어업수역Ⅳ.json';
|
||||
|
||||
/**
|
||||
* 중국 허가 업종 코드 (허가번호 접두사)
|
||||
@ -43,14 +51,57 @@ const GEAR_META: Record<FishingGearType, {
|
||||
export { GEAR_META as GEAR_LABELS };
|
||||
|
||||
/**
|
||||
* 특정어업수역 정의 (한중어업협정)
|
||||
* EPSG:3857 → WGS84 좌표 변환
|
||||
*/
|
||||
const _FISHING_ZONES = {
|
||||
I: { name: '수역Ⅰ(동해)', lngMin: 128.86, lngMax: 131.67, latMin: 35.65, latMax: 38.25, allowed: ['PS', 'FC'] },
|
||||
II: { name: '수역Ⅱ(남해)', lngMin: 126.00, lngMax: 128.89, latMin: 32.18, latMax: 34.34, allowed: ['PT', 'OT', 'GN', 'PS', 'FC'] },
|
||||
III:{ name: '수역Ⅲ(서남해)', lngMin: 124.01, lngMax: 126.08, latMin: 32.18, latMax: 35.00, allowed: ['PT', 'OT', 'GN', 'PS', 'FC'] },
|
||||
IV: { name: '수역Ⅳ(서해)', lngMin: 124.13, lngMax: 125.85, latMin: 35.00, latMax: 37.00, allowed: ['GN', 'PS', 'FC'] },
|
||||
};
|
||||
function epsg3857ToWgs84(x: number, y: number): [number, number] {
|
||||
const lon = (x / (Math.PI * 6378137)) * 180;
|
||||
const lat = Math.atan(Math.exp(y / 6378137)) * (360 / Math.PI) - 90;
|
||||
return [lon, lat]; // GeoJSON [lng, lat] 순서
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
function convertZoneToWgs84(data: any): Feature<MultiPolygon> {
|
||||
const feat = data.features[0];
|
||||
const multiCoords: number[][][][] = feat.geometry.coordinates.map(
|
||||
(poly: number[][][]) => poly.map(
|
||||
(ring: number[][]) => ring.map(([x, y]: number[]) => epsg3857ToWgs84(x, y)),
|
||||
),
|
||||
);
|
||||
return multiPolygon(multiCoords).geometry
|
||||
? { type: 'Feature', properties: {}, geometry: { type: 'MultiPolygon', coordinates: multiCoords } }
|
||||
: multiPolygon(multiCoords) as unknown as Feature<MultiPolygon>;
|
||||
}
|
||||
|
||||
export type FishingZoneId = 'ZONE_I' | 'ZONE_II' | 'ZONE_III' | 'ZONE_IV' | 'OUTSIDE';
|
||||
|
||||
export interface FishingZoneInfo {
|
||||
zone: FishingZoneId;
|
||||
name: string;
|
||||
allowed: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* 특정어업수역 Ⅰ~Ⅳ 폴리곤 (WGS84 변환 캐시)
|
||||
*/
|
||||
const ZONE_POLYGONS: { id: FishingZoneId; name: string; allowed: string[]; geojson: Feature<MultiPolygon> }[] = [
|
||||
{ id: 'ZONE_I', name: '수역Ⅰ(동해)', allowed: ['PS', 'FC'], geojson: convertZoneToWgs84(zone1Data) },
|
||||
{ id: 'ZONE_II', name: '수역Ⅱ(남해)', allowed: ['PT', 'OT', 'GN', 'PS', 'FC'], geojson: convertZoneToWgs84(zone2Data) },
|
||||
{ id: 'ZONE_III', name: '수역Ⅲ(서남해)', allowed: ['PT', 'OT', 'GN', 'PS', 'FC'], geojson: convertZoneToWgs84(zone3Data) },
|
||||
{ id: 'ZONE_IV', name: '수역Ⅳ(서해)', allowed: ['GN', 'PS', 'FC'], geojson: convertZoneToWgs84(zone4Data) },
|
||||
];
|
||||
|
||||
/**
|
||||
* 특정어업수역 폴리곤 기반 수역 분류
|
||||
*/
|
||||
export function classifyFishingZone(lat: number, lng: number): FishingZoneInfo {
|
||||
const pt = point([lng, lat]);
|
||||
for (const z of ZONE_POLYGONS) {
|
||||
if (booleanPointInPolygon(pt, z.geojson)) {
|
||||
return { zone: z.id, name: z.name, allowed: z.allowed };
|
||||
}
|
||||
}
|
||||
return { zone: 'OUTSIDE', name: '수역 외', allowed: [] };
|
||||
}
|
||||
|
||||
/**
|
||||
* 업종별 허가 기간 (월/일)
|
||||
|
||||
@ -10,6 +10,7 @@ TERRITORIAL_SEA_NM = 12.0
|
||||
CONTIGUOUS_ZONE_NM = 24.0
|
||||
|
||||
_baseline_points: Optional[List[Tuple[float, float]]] = None
|
||||
_zone_polygons: Optional[list] = None
|
||||
|
||||
|
||||
def _load_baseline() -> List[Tuple[float, float]]:
|
||||
@ -46,10 +47,91 @@ def dist_to_baseline(vessel_lat: float, vessel_lon: float,
|
||||
return min_dist
|
||||
|
||||
|
||||
def classify_zone(vessel_lat: float, vessel_lon: float) -> dict:
|
||||
"""선박 위치 수역 분류."""
|
||||
dist = dist_to_baseline(vessel_lat, vessel_lon)
|
||||
def _epsg3857_to_wgs84(x: float, y: float) -> Tuple[float, float]:
|
||||
"""EPSG:3857 (Web Mercator) → WGS84 변환."""
|
||||
lon = x / (math.pi * 6378137) * 180
|
||||
lat = math.atan(math.exp(y / 6378137)) * 360 / math.pi - 90
|
||||
return lat, lon
|
||||
|
||||
|
||||
def _load_zone_polygons() -> list:
|
||||
"""특정어업수역 Ⅰ~Ⅳ GeoJSON 로드 + EPSG:3857→WGS84 변환."""
|
||||
global _zone_polygons
|
||||
if _zone_polygons is not None:
|
||||
return _zone_polygons
|
||||
|
||||
zone_dir = Path(__file__).parent.parent / 'data' / 'zones'
|
||||
zones_meta = [
|
||||
('ZONE_I', '수역Ⅰ(동해)', ['PS', 'FC'], '특정어업수역Ⅰ.json'),
|
||||
('ZONE_II', '수역Ⅱ(남해)', ['PT', 'OT', 'GN', 'PS', 'FC'], '특정어업수역Ⅱ.json'),
|
||||
('ZONE_III', '수역Ⅲ(서남해)', ['PT', 'OT', 'GN', 'PS', 'FC'], '특정어업수역Ⅲ.json'),
|
||||
('ZONE_IV', '수역Ⅳ(서해)', ['GN', 'PS', 'FC'], '특정어업수역Ⅳ.json'),
|
||||
]
|
||||
result = []
|
||||
for zone_id, name, allowed, filename in zones_meta:
|
||||
filepath = zone_dir / filename
|
||||
if not filepath.exists():
|
||||
continue
|
||||
with open(filepath, 'r') as f:
|
||||
data = json.load(f)
|
||||
multi_coords = data['features'][0]['geometry']['coordinates']
|
||||
wgs84_polys = []
|
||||
for poly in multi_coords:
|
||||
wgs84_rings = []
|
||||
for ring in poly:
|
||||
wgs84_rings.append([_epsg3857_to_wgs84(x, y) for x, y in ring])
|
||||
wgs84_polys.append(wgs84_rings)
|
||||
result.append({
|
||||
'id': zone_id, 'name': name, 'allowed': allowed,
|
||||
'polygons': wgs84_polys,
|
||||
})
|
||||
_zone_polygons = result
|
||||
return result
|
||||
|
||||
|
||||
def _point_in_polygon(lat: float, lon: float, ring: list) -> bool:
|
||||
"""Ray-casting point-in-polygon."""
|
||||
n = len(ring)
|
||||
inside = False
|
||||
j = n - 1
|
||||
for i in range(n):
|
||||
yi, xi = ring[i]
|
||||
yj, xj = ring[j]
|
||||
if ((yi > lat) != (yj > lat)) and (lon < (xj - xi) * (lat - yi) / (yj - yi) + xi):
|
||||
inside = not inside
|
||||
j = i
|
||||
return inside
|
||||
|
||||
|
||||
def _point_in_multipolygon(lat: float, lon: float, polygons: list) -> bool:
|
||||
"""MultiPolygon 내 포함 여부 (외곽 링 in + 내곽 링 hole 제외)."""
|
||||
for poly in polygons:
|
||||
outer = poly[0]
|
||||
if _point_in_polygon(lat, lon, outer):
|
||||
for hole in poly[1:]:
|
||||
if _point_in_polygon(lat, lon, hole):
|
||||
return False
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def classify_zone(vessel_lat: float, vessel_lon: float) -> dict:
|
||||
"""선박 위치 수역 분류 — 특정어업수역 Ⅰ~Ⅳ 폴리곤 기반."""
|
||||
zones = _load_zone_polygons()
|
||||
|
||||
for z in zones:
|
||||
if _point_in_multipolygon(vessel_lat, vessel_lon, z['polygons']):
|
||||
dist = dist_to_baseline(vessel_lat, vessel_lon)
|
||||
return {
|
||||
'zone': z['id'],
|
||||
'zone_name': z['name'],
|
||||
'allowed_gears': z['allowed'],
|
||||
'dist_from_baseline_nm': round(dist, 2),
|
||||
'violation': False,
|
||||
'alert_level': 'WATCH',
|
||||
}
|
||||
|
||||
dist = dist_to_baseline(vessel_lat, vessel_lon)
|
||||
if dist <= TERRITORIAL_SEA_NM:
|
||||
return {
|
||||
'zone': 'TERRITORIAL_SEA',
|
||||
|
||||
1
prediction/data/zones/특정어업수역Ⅰ.json
Normal file
1
prediction/data/zones/특정어업수역Ⅰ.json
Normal file
File diff suppressed because one or more lines are too long
1
prediction/data/zones/특정어업수역Ⅱ.json
Normal file
1
prediction/data/zones/특정어업수역Ⅱ.json
Normal file
File diff suppressed because one or more lines are too long
1
prediction/data/zones/특정어업수역Ⅲ.json
Normal file
1
prediction/data/zones/특정어업수역Ⅲ.json
Normal file
File diff suppressed because one or more lines are too long
1
prediction/data/zones/특정어업수역Ⅳ.json
Normal file
1
prediction/data/zones/특정어업수역Ⅳ.json
Normal file
@ -0,0 +1 @@
|
||||
{"type": "FeatureCollection", "name": "\ud2b9\uc815\uc5b4\uc5c5\uc218\uc5ed4", "crs": {"type": "name", "properties": {"name": "urn:ogc:def:crs:OGC:1.3:CRS84"}}, "features": [{"type": "Feature", "properties": {"fid": 0, "GML_ID": null, "OBJECTID": null, "ZONE_NM": null, "MNCT_NO": null, "MNCT_SCALE": null, "MNCT_NM": null, "RELREGLTN": null, "RELGOAG": null, "REVIYR": null, "ZONE_DESC": null, "PHOTO1_PAT": null, "ID": -2147483647, "CATE_CD": null, "ADR_CD": null, "ADR_KNM": null, "ORIGIN": null, "ORIYR": null, "ORIORG": null, "NAME": "\ud2b9\uc815\uc5b4\uc5c5\uc218\uc5ed\u2163", "WARD_NM": null, "WARD_ID": null, "GISID": null, "FID_2": null, "NAME_2": null, "FID_3": null, "NAME_3": null, "GID": null, "NAME_4": null, "FID_4": null, "NAME_5": null, "FID_5": null, "NAME_6": null}, "geometry": {"type": "MultiPolygon", "coordinates": [[[[13859276.603817873, 4232038.462456921], [13859276.603762543, 4321218.244482412], [13859276.603710985, 4404317.064005076], [13840719.645028654, 4439106.786523586], [13884632.712472571, 4439106.787250583], [13884632.712472571, 4439504.084564682], [13940418.269436067, 4439504.375880923], [13969123.924724836, 4439504.525783945], [13968718.329494288, 4438626.439593866], [13962623.599395147, 4425543.915710401], [13960437.31344761, 4420657.3891166765], [13958238.813611617, 4416093.569832627], [13958143.094601436, 4415900.994484875], [13958143.094601437, 4415900.994484875], [13957298.344237303, 4414201.456484755], [13953878.455604602, 4406316.186534493], [13949652.450365951, 4397019.979821594], [13948553.200448176, 4393395.13065616], [13947612.731073817, 4389132.176741289], [13947612.731072996, 4387549.226905922], [13947466.164417507, 4385829.556682826], [13947783.725505754, 4381721.729468383], [13948260.06713652, 4379835.70012994], [13949359.317054221, 4375897.403884492], [13951093.689146286, 4371808.582233328], [13954867.780530114, 4365670.678186072], [13964809.885341855, 4351190.629491161], [13978342.873219142, 4331838.456925102], [13980382.592510404, 4329007.496874151], [13981728.043604897, 4327079.749205159], [13985775.34591557, 4321280.81855131], [13997066.763484716, 4305102.598482491], [13999424.043863578, 4300225.286038025], [14003039.354703771, 4290447.064438686], [14005091.287883686, 4284626.561498255], [14006520.312777169, 4279426.932176922], [14007631.77658257, 4275178.643476352], [14008242.470981453, 4271549.325573796], [14009378.362562515, 4262248.123573576], [14009427.990871342, 4261704.85208626], [14009708.137538105, 4258638.140769343], [14009854.704193696, 4257224.555715567], [14009378.362562606, 4254698.603440943], [14005347.779531531, 4240996.452433007], [14002367.590864772, 4231511.1380338315], [14001280.554835469, 4227266.412716273], [14000486.652116666, 4225212.134400094], [13998047.81589918, 4222926.459154359], [13991387.305576058, 4216684.234498038], [13970721.407121927, 4197120.494488488], [13958654.085803084, 4185745.4565721145], [13956602.15262321, 4184012.5742896623], [13944065.033685392, 4171984.566055202], [13940467.606607554, 4168533.224265296], [13935619.01320107, 4163881.1438622964], [13935718.55954324, 4163976.6556012244], [13817590.293393573, 4163976.6556012244], [13859276.603817873, 4232038.462456921]]]]}}]}
|
||||
불러오는 중...
Reference in New Issue
Block a user