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