-
Notifications
You must be signed in to change notification settings - Fork 0
/
add-doors-to-rooms.py
120 lines (103 loc) · 5.64 KB
/
add-doors-to-rooms.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
import json
from turfpy.transformation import circle, intersect
from geojson import Point, Feature, FeatureCollection
from turfpy.measurement import center, point_to_line_distance
circle_radius_cm = 60
include_lintels = True
lintel_properties = {'height': 8, 'base_height': 5, 'tags': {'indoor': 'lintel'}}
f = open('data/add-doors-to-rooms/input.geojson', encoding='utf-8')
data = json.load(f)
doors = [x for x in data['features'] if
x['geometry']['type'] == 'Point' and x['properties']['tags'].get('door') == 'yes']
def cutLine(lineString, baseLine, sliceLine):
coords = lineString['geometry']['coordinates']
sliceCoords = sliceLine['geometry']['coordinates']
firstSliceCoords = []
secondSliceCoords = []
found = False
# look for the baseLine
for lineStartPointIndex in range(len(coords[:-1])):
line = Feature(geometry={'coordinates': [coords[lineStartPointIndex],
coords[lineStartPointIndex + 1]],
'type': 'LineString'})
if line['geometry'] == baseLine['geometry']:
found = True
firstSliceCoords += [coords[lineStartPointIndex], sliceCoords[0]]
secondSliceCoords += [sliceCoords[1], coords[lineStartPointIndex + 1]]
else:
if found:
secondSliceCoords += [coords[lineStartPointIndex], coords[lineStartPointIndex + 1]]
else:
firstSliceCoords += [coords[lineStartPointIndex], coords[lineStartPointIndex + 1]]
return Feature(geometry={'coordinates': [firstSliceCoords, secondSliceCoords], 'type': 'MultiLineString'})
def cutRoom(roomLineString, intersections):
coords = roomLineString['geometry']['coordinates']
lines = []
for lineStartPointIndex in range(len(coords[:-1])):
line = Feature(geometry={'coordinates': [coords[lineStartPointIndex],
coords[lineStartPointIndex + 1]],
'type': 'LineString'})
intersectionFound = False
for intersection in intersections:
if intersection['onLine']['geometry'] == line['geometry']:
intersectionFound = True
newLine = cutLine(line, line, intersection['intersection'])
lines += newLine['geometry']['coordinates']
if not intersectionFound:
lines += [line['geometry']['coordinates']]
return Feature(geometry={'coordinates': lines, 'type': 'MultiLineString'})
final = []
for feature in data['features']:
if feature['geometry']['type'] == 'Polygon' and feature['properties']['tags'].get('indoor') == 'room':
# feature is a room
roomBorder = Feature(geometry={'coordinates': feature['geometry']['coordinates'][0], 'type': 'LineString'})
roomBorderML = Feature(
geometry={'coordinates': [feature['geometry']['coordinates'][0]], 'type': 'MultiLineString'})
roomBorderFC = FeatureCollection(features=[roomBorder])
intersectionsToCutOut = []
lintels = []
room = Feature(geometry={'coordinates': feature['geometry']['coordinates'], 'type': 'Polygon'})
# find its doors
roomDoors = [x for x in doors if x['properties']['room_id'] == feature['properties']['id']]
for door in roomDoors:
centerCoord = Feature(
geometry=Point((door['geometry']['coordinates'][0], door['geometry']['coordinates'][1])))
# make a circle
doorCircle = circle(center=centerCoord, radius=circle_radius_cm, steps=50, units='cen')
# find intersecting points
intersection = intersect([doorCircle, roomBorder])
# make sure they have only 2 intersections
if len(intersection['geometry']['coordinates']) != 2:
continue
# save intersection as door lintel
lintel = intersection
lintel['properties'] = lintel_properties
lintels += [lintel]
# cut room border from intersections
# find which line contains the intersection line
minLine = Feature(geometry={'coordinates': [roomBorder['geometry']['coordinates'][0],
roomBorder['geometry']['coordinates'][1]],
'type': 'LineString'})
minPointIndex = 0
minDistance = 1000
for pointIndex in range(len(roomBorder['geometry']['coordinates'][:-1])):
line = Feature(geometry={'coordinates': [roomBorder['geometry']['coordinates'][pointIndex],
roomBorder['geometry']['coordinates'][pointIndex + 1]],
'type': 'LineString'})
intersectionCenterPoint = center(FeatureCollection([intersection]))
distance = point_to_line_distance(intersectionCenterPoint, line, units='m')
if distance < minDistance:
minLine = line
minPointIndex = pointIndex
minDistance = distance
# minLine is the one containing the intersection
# save all then cut out the intersection from minLine from the room border
intersectionsToCutOut += [{'intersection': intersection, 'onLine': minLine}]
slicedRoom = cutRoom(roomBorder, intersectionsToCutOut)
final.append(slicedRoom)
if include_lintels:
final += lintels
newGeojson = {'type': 'FeatureCollection', 'features': final}
with open('data/add-doors-to-rooms/output.geojson', 'w', encoding='utf-8') as f:
json.dump(newGeojson, f, indent=4)
f.close()