Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/tools/net/reprojectpolys.py
169673 views
1
#!/usr/bin/env python
2
# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
# Copyright (C) 2008-2025 German Aerospace Center (DLR) and others.
4
# This program and the accompanying materials are made available under the
5
# terms of the Eclipse Public License 2.0 which is available at
6
# https://www.eclipse.org/legal/epl-2.0/
7
# This Source Code may also be made available under the following Secondary
8
# Licenses when the conditions for such availability set forth in the Eclipse
9
# Public License 2.0 are satisfied: GNU General Public License, version 2
10
# or later which is available at
11
# https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12
# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13
14
# @file reprojectpolys.py
15
# @author Daniel Krajzewicz
16
# @author Michael Behrisch
17
# @date 2008-03-27
18
19
"""
20
This script computes the projection needed to make net2 (-2) fit
21
to net1 (-1). The read polygons (-p) are then reprojected
22
using this projection.
23
24
This means, the resulting polygons, written to the output
25
specified by --output, are net2's polygons as they would
26
be on net1.
27
"""
28
from __future__ import absolute_import
29
from __future__ import print_function
30
31
import sys
32
from optparse import OptionParser
33
from xml.sax import make_parser, handler
34
sys.path.append("../lib")
35
import rmsd # noqa
36
37
38
class NetReader(handler.ContentHandler):
39
40
"""Reads a network, storing nodes and their positions"""
41
42
def __init__(self):
43
self._id = ''
44
self._node2x = {}
45
self._node2y = {}
46
self._nodes = []
47
48
def startElement(self, name, attrs):
49
if name == 'junction':
50
self._id = attrs['id']
51
if self._id[0] != ':':
52
self._node2x[attrs['id']] = float(attrs['x'])
53
self._node2y[attrs['id']] = float(attrs['y'])
54
self._nodes.append(attrs['id'])
55
else:
56
self._id = ""
57
58
def getNodeIndex(self, name):
59
for i, n in enumerate(self._nodes):
60
if n == name:
61
return i
62
return -1
63
64
def getNodePositionList(self):
65
ret = []
66
for n in self._nodes:
67
ret.append((self._node2x[n], self._node2y[n]))
68
return ret
69
70
71
class PolyReader(handler.ContentHandler):
72
73
"""Reads a list of polygons, stores them"""
74
75
def __init__(self):
76
self._polys = []
77
self._parsingPoly = False
78
self._shapes = []
79
80
def startElement(self, name, attrs):
81
self._parsingPoly = False
82
self._chars = ""
83
if name == 'poly':
84
self._parsingPoly = True
85
self._polys.append({})
86
for attr in attrs.keys():
87
self._polys[-1][attr] = attrs[attr]
88
89
def characters(self, chars):
90
if self._parsingPoly:
91
self._chars = self._chars + chars
92
93
def endElement(self, name):
94
if self._parsingPoly:
95
poses = self._chars.split(' ')
96
shape = []
97
for pos in poses:
98
coord = pos.split(',')
99
shape.append([float(coord[0]), float(coord[1])])
100
self._shapes.append([float(coord[0]), float(coord[1])])
101
self._polys[-1]['shape'] = shape
102
103
def getPositionList(self):
104
return self._shapes
105
106
def write(self, into):
107
for poly in self._polys:
108
into.write(" <poly id=\"" + poly['id'])
109
for attr in poly:
110
if attr != "id" and attr != "shape":
111
into.write("\" " + attr + "=\"" + poly[attr])
112
into.write("\">")
113
shape = poly["shape"]
114
for i, c in enumerate(shape):
115
if i != 0:
116
into.write(" ")
117
into.write(str(c[0]) + "," + str(c[1]))
118
into.write("</poly>\n")
119
120
121
class PolyReprojector:
122
123
def __init__(self, net1, net2):
124
self._net1 = net1
125
self._net2 = net2
126
127
def match(self, nodes1, nodes2, polys, verbose):
128
nodes1 = nodes1.split(',')
129
nodes2 = nodes2.split(',')
130
# build match matrix for nodes
131
# and lists of matching indices
132
rmsdSelection1 = []
133
rmsdSelection2 = []
134
if verbose:
135
print(" Setting initial nodes...")
136
for i in range(0, len(nodes1)):
137
index1 = self._net1.getNodeIndex(nodes1[i])
138
index2 = self._net2.getNodeIndex(nodes2[i])
139
rmsdSelection1.append(index1)
140
rmsdSelection2.append(index2)
141
if verbose:
142
print(str(index1) + " " + str(index2))
143
# build rmsd matrices
144
if verbose:
145
print(" Computing projection...")
146
rmsdNodePositions1 = self._net1.getNodePositionList()
147
rmsdNodePositions2 = self._net2.getNodePositionList()
148
rmsdNodePositions2.extend(polys.getPositionList())
149
projection = rmsd.superpose(
150
rmsdNodePositions1, rmsdNodePositions2, rmsdSelection1, rmsdSelection2)
151
# we now have new coordinates for the second node set in projection
152
# transfer to net
153
if verbose:
154
print(" Applying projection...")
155
index = 0
156
for i, n in enumerate(self._net2._nodes):
157
self._net2._node2x[n] = projection[i][0]
158
self._net2._node2y[n] = projection[i][1]
159
index = index + 1
160
for poly in polys._polys:
161
for i in range(0, len(poly["shape"])):
162
poly["shape"][i][0] = projection[i][0]
163
poly["shape"][i][1] = projection[i][1]
164
index = index + 1
165
166
167
# initialise
168
optParser = OptionParser()
169
optParser.add_option("-v", "--verbose", action="store_true", dest="verbose",
170
default=False, help="tell me what you are doing")
171
# i/o
172
optParser.add_option("-1", "--net1", dest="net1",
173
help="The network to project at", metavar="FILE")
174
optParser.add_option("-2", "--net2", dest="net2",
175
help="The network to reproject", metavar="FILE")
176
optParser.add_option("-p", "--polys", dest="polys",
177
help="The polygons to reproject", metavar="FILE")
178
optParser.add_option("-a", "--nodes1", dest="nodes1",
179
help="The first matching nodes", metavar="FILE")
180
optParser.add_option("-b", "--nodes2", dest="nodes2",
181
help="The second matching nodes", metavar="FILE")
182
optParser.add_option("-o", "--output", dest="output",
183
help="File to save reprojected polys into", metavar="FILE")
184
# parse options
185
(options, args) = optParser.parse_args()
186
187
188
# read network#1
189
if options.verbose:
190
print("Reading net#1...")
191
parser = make_parser()
192
net1 = NetReader()
193
parser.setContentHandler(net1)
194
parser.parse(options.net1)
195
196
# read network#2
197
if options.verbose:
198
print("Reading net#2...")
199
parser = make_parser()
200
net2 = NetReader()
201
parser.setContentHandler(net2)
202
parser.parse(options.net2)
203
204
# read polygons
205
if options.verbose:
206
print("Reading polygons...")
207
parser = make_parser()
208
polys = PolyReader()
209
parser.setContentHandler(polys)
210
parser.parse(options.polys)
211
212
# match
213
if options.verbose:
214
print("(Re)Projecting...")
215
matcher = PolyReprojector(net1, net2)
216
matcher.match(options.nodes1, options.nodes2, polys, options.verbose)
217
218
# write
219
if options.verbose:
220
print("Writing...")
221
fd = open(options.output, "w")
222
fd.write("<polygons>\n\n")
223
polys.write(fd)
224
fd.write("</polygons>\n")
225
fd.close()
226
227