-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy patharea.py
144 lines (120 loc) · 4.71 KB
/
area.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
from typing import Iterator
from shapely.geometry import Polygon
class Area:
def __init__(self, name: str, polygon: Polygon, metadata: dict):
self.name = name
self.polygon = polygon
self.metadata = metadata
def __repr__(self):
return f"Area(name={self.name}, polygon={self.polygon}, metadata={self.metadata})"
def polygontoArray(self):
coords = list(self.polygon.exterior.coords)
return [[x, y] for x, y in coords]
def assignPolygon(self, candidates: 'MultiAreas', assign: str):
max_intersection_area = 0
best_match = None
for candidate in candidates:
if self.polygon.within(candidate.polygon):
best_match = candidate
break
intersection = self.polygon.intersection(candidate.polygon)
intersection_area = intersection.area
if intersection_area > max_intersection_area:
max_intersection_area = intersection_area
best_match = candidate
if best_match:
self.metadata.update(best_match.metadata)
self.metadata[assign] = best_match.name
def assignCentroid(self):
self.metadata["CENTROID"] = self.polygon.centroid.coords[0]
class MultiAreas:
def __init__(self, areas: list):
if not all(isinstance(area, Area) for area in areas):
raise ValueError("All elements in the areas list must be instances of the Area class.")
self.areas = areas
def __repr__(self):
return f"MultiArea(areas={self.areas})"
def __iter__(self) -> Iterator[Area]:
return iter(self.areas)
def exportToExcel(self, filename: str):
import pandas as pd
data = []
for area in self.areas:
data.append({
"name": area.name,
**area.metadata
})
df = pd.DataFrame(data)
df.to_excel(filename, index=False)
def exportToJSON(self, filename: str):
import json
data = []
for area in self.areas:
data.append({
"name": area.name,
"coordinates": area.polygontoArray(),
**area.metadata
})
with open(filename, "w") as f:
json.dump(data, f)
def exportToCSV(self, filename: str):
import csv
data = []
for area in self.areas:
data.append({
"name": area.name,
"coordinates": area.polygontoArray(),
**area.metadata
})
with open(filename, "w", newline="") as f:
writer = csv.DictWriter(f, fieldnames=["name", "coordinates", *area.metadata.keys()])
writer.writeheader()
writer.writerows(data)
def exportToKML(self, filename: str):
import xml.etree.ElementTree as ET
from xml.dom import minidom
kml = ET.Element("kml", xmlns="http://www.opengis.net/kml/2.2")
document = ET.SubElement(kml, "Document")
for area in self.areas:
placemark = ET.SubElement(document, "Placemark")
name = ET.SubElement(placemark, "name")
name.text = area.name
polygon = ET.SubElement(placemark, "Polygon")
outer_boundary_is = ET.SubElement(polygon, "outerBoundaryIs")
linear_ring = ET.SubElement(outer_boundary_is, "LinearRing")
coordinates = ET.SubElement(linear_ring, "coordinates")
coords = " ".join([f"{x},{y}" for x, y in area.polygon.exterior.coords])
coordinates.text = coords
xmlstr = minidom.parseString(ET.tostring(kml)).toprettyxml(indent=" ")
with open(filename, "w") as f:
f.write(xmlstr)
def exportToGeoJSON(self, filename: str):
import json
data = {
"type": "FeatureCollection",
"features": []
}
for area in self.areas:
feature = {
"type": "Feature",
"properties": area.metadata,
"geometry": {
"type": "Polygon",
"coordinates": [area.polygontoArray()]
}
}
data["features"].append(feature)
with open(filename, "w") as f:
json.dump(data, f)
def exportToDatabase(self, uri: str, database: str, collection: str):
import pymongo
from pymongo.server_api import ServerApi
client = pymongo.MongoClient(uri, server_api=ServerApi('1'))
db = client[database]
areas = db[collection]
areas.insert_many([{
"name": area.name,
"coordinates": area.polygontoArray(),
**area.metadata
} for area in self.areas])
client.close()