Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2011-2026 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 NBHeightMapper.h
15 : /// @author Jakob Erdmann
16 : /// @author Laura Bieker
17 : /// @author Michael Behrisch
18 : /// @date Sept 2011
19 : ///
20 : // Set z-values for all network positions based on data from a height map
21 : /****************************************************************************/
22 : #pragma once
23 : #include <config.h>
24 :
25 : #ifdef WIN32
26 : typedef __int16 int16_t;
27 : #else
28 : #include <stdint.h>
29 : #endif
30 :
31 : #include <string>
32 : #include <foreign/rtree/RTree.h>
33 : #include <utils/geom/PositionVector.h>
34 : #include <utils/geom/Boundary.h>
35 : #include <utils/common/UtilExceptions.h>
36 :
37 : #ifdef HAVE_GDAL
38 : #include <ogr_spatialref.h>
39 : #endif
40 :
41 : #define TRIANGLE_RTREE_QUAL RTree<NBHeightMapper::Triangle*, NBHeightMapper::Triangle, float, 2, NBHeightMapper::QueryResult>
42 :
43 : // ===========================================================================
44 : // class declarations
45 : // ===========================================================================
46 : class OptionsCont;
47 :
48 :
49 : // ===========================================================================
50 : // class definitions
51 : // ===========================================================================
52 : /**
53 : * @class NBHeightMapper
54 : * @brief Set z-values for all network positions based on data from a height map
55 : *
56 : * Importing data from '.shp'-files works only if SUMO was compiled with GDAL-support.
57 : * If not, an error message is generated.
58 : */
59 : class NBHeightMapper {
60 :
61 : friend class NBHeightMapperTest;
62 :
63 : public:
64 : /** @brief loads height map data if any loading options are set
65 : *
66 : * @param[in] oc The options container to get further options from
67 : * @exception ProcessError if something fails
68 : */
69 : static void loadIfSet(OptionsCont& oc);
70 :
71 : /// @brief return the singleton instance (maybe 0)
72 : static const NBHeightMapper& get();
73 :
74 : /// @brief returns whether the NBHeightMapper has data
75 : bool ready() const;
76 :
77 : /// @brief returns the convex boundary of all known triangles
78 : const Boundary& getBoundary() {
79 : return myInstance.myBoundary;
80 : }
81 :
82 : /// @brief returns height for the given geo coordinate (WGS84)
83 : double getZ(const Position& geo) const;
84 :
85 : class QueryResult;
86 : /* @brief content class for the rtree. Since we wish to be able to use the
87 : * rtree for spatial querying we have to jump through some minor hoops:
88 : * We let each found triangle callback the NBHeightMapper and add itself the
89 : * the query result
90 : * */
91 : class Triangle {
92 :
93 : public:
94 : Triangle(const PositionVector& corners);
95 687 : ~Triangle() {};
96 :
97 : /// @brief callback for RTree search
98 : void addSelf(const QueryResult& queryResult) const;
99 :
100 : /// @brief checks whether pos lies within triangle (only checks x,y)
101 : bool contains(const Position& pos) const;
102 :
103 : /// @brief returns the projection of the give geoCoordinate (WGS84) onto triangle plane
104 : double getZ(const Position& geo) const;
105 :
106 : /// @brief returns the normal vector for this triangles plane
107 : Position normalVector() const;
108 :
109 : /// @brief the corners of the triangle
110 : PositionVector myCorners;
111 :
112 : };
113 :
114 : typedef std::vector<const Triangle*> Triangles;
115 :
116 : /// @brief class for cirumventing the const-restriction of RTree::Search-context
117 : class QueryResult {
118 : public:
119 : QueryResult() {};
120 851 : ~QueryResult() {};
121 : // @brief method not realy const
122 : void add(Triangle* triangle) const {
123 : triangles.push_back(triangle);
124 : };
125 : mutable Triangles triangles;
126 : };
127 :
128 : private:
129 :
130 10 : struct RasterData {
131 : float* raster;
132 : Boundary boundary;
133 : int xSize;
134 : int ySize;
135 : #ifdef HAVE_GDAL
136 : OGRCoordinateTransformation* transform;
137 : #endif
138 : };
139 :
140 : /// @brief the singleton instance
141 : static NBHeightMapper myInstance;
142 :
143 : Triangles myTriangles;
144 :
145 : /// @brief The RTree for spatial queries
146 : TRIANGLE_RTREE_QUAL myRTree;
147 :
148 : /// @brief raster height information in m for all loaded files
149 : std::vector<RasterData> myRasters;
150 :
151 : /// @brief dimensions of one pixel in raster data
152 : Position mySizeOfPixel;
153 :
154 : /// @brief convex boundary of all known triangles;
155 : Boundary myBoundary;
156 :
157 : private:
158 : /// @brief private constructor and destructor (Singleton)
159 : NBHeightMapper();
160 : ~NBHeightMapper();
161 :
162 : /// @brief adds one triangles worth of height data
163 : void addTriangle(PositionVector corners);
164 :
165 : /** @brief load height data from Arcgis-shape file and returns the number of parsed features
166 : * @return The number of parsed features
167 : * @throws ProcessError
168 : */
169 : int loadShapeFile(const std::string& file);
170 :
171 : /** @brief load height data from GeoTIFF file and returns the number of non void pixels
172 : * @return The number of valid pixels
173 : * @throws ProcessError
174 : */
175 : int loadTiff(const std::string& file);
176 :
177 : /// @brief clears loaded data
178 : void clearData();
179 :
180 : /// @brief Invalidated copy constructor.
181 : NBHeightMapper(const NBHeightMapper&);
182 :
183 : /// @brief Invalidated assignment operator.
184 : NBHeightMapper& operator=(const NBHeightMapper&);
185 :
186 : };
187 :
188 :
189 : // ===========================================================================
190 : // RTree specialization for speedup and avoiding warnings (ripped from SUMORTree.h)
191 : // ===========================================================================
192 : template<>
193 : inline float TRIANGLE_RTREE_QUAL::RectSphericalVolume(Rect* a_rect) {
194 : ASSERT(a_rect);
195 0 : const float extent0 = a_rect->m_max[0] - a_rect->m_min[0];
196 0 : const float extent1 = a_rect->m_max[1] - a_rect->m_min[1];
197 0 : return .78539816f * (extent0 * extent0 + extent1 * extent1);
198 : }
199 :
200 : template<>
201 : inline TRIANGLE_RTREE_QUAL::Rect TRIANGLE_RTREE_QUAL::CombineRect(Rect* a_rectA, Rect* a_rectB) {
202 : ASSERT(a_rectA && a_rectB);
203 : Rect newRect;
204 0 : newRect.m_min[0] = rtree_min(a_rectA->m_min[0], a_rectB->m_min[0]);
205 0 : newRect.m_max[0] = rtree_max(a_rectA->m_max[0], a_rectB->m_max[0]);
206 0 : newRect.m_min[1] = rtree_min(a_rectA->m_min[1], a_rectB->m_min[1]);
207 0 : newRect.m_max[1] = rtree_max(a_rectA->m_max[1], a_rectB->m_max[1]);
208 : return newRect;
209 : }
|