alaCarte Maps
Renderer for OpenStreetMap tiles
geodata.cpp
Go to the documentation of this file.
1 
22 /*
23  * =====================================================================================
24  *
25  * Filename: geodata.cpp
26  *
27  * Description:
28  *
29  * =====================================================================================
30  */
31 #include <boost/archive/binary_iarchive.hpp>
32 #include <boost/archive/binary_oarchive.hpp>
33 #include <boost/serialization/base_object.hpp>
34 #include <boost/filesystem/operations.hpp>
35 #include <boost/filesystem/path.hpp>
36 
37 #include <limits>
38 
39 #include "general/geodata.hpp"
40 
41 #include "general/node.hpp"
42 #include "general/way.hpp"
43 #include "general/relation.hpp"
44 #include "general/rtree.hpp"
45 #include "utils/rect.hpp"
46 #include "utils/archive.hpp"
47 
49 void Geodata::buildTrees(const string& nodePath, const string& wayPath, const string& relationPath)
50 {
51  if (nodes->size() > 0)
52  {
53  std::vector<FixedPoint> points;;
54  for (auto& n : *nodes)
55  points.push_back(n.getLocation());
56 
57  nodesTree->build(points, nodePath);
58  }
59 
60  if (ways->size() > 0)
61  {
62  std::vector<FixedRect> rects;
63  for (auto& w : *ways)
64  rects.push_back(calculateBoundingBox(w));
65 
66  waysTree->build(rects, wayPath);
67  }
68 
69  if (relations->size() > 0)
70  {
71  std::vector<FixedRect> rects;
72  for (auto& r : *relations)
73  rects.push_back(calculateBoundingBox(r));
74 
75  relTree->build(rects, relationPath);
76  }
77 }
78 
79 void Geodata::insertNodes(const shared_ptr<std::vector<Node> >& nodes)
80 {
81  this->nodes = nodes;
82  if (nodes->size() > 0)
83  this->nodesTree = boost::make_shared<RTree<NodeId, FixedPoint> >();
84 }
85 
86 void Geodata::insertWays(const shared_ptr<std::vector<Way> >& ways)
87 {
88  this->ways = ways;
89  if (ways->size() > 0)
90  this->waysTree = boost::make_shared<RTree<WayId, FixedRect> >();
91 }
92 
93 void Geodata::insertRelations(const shared_ptr<std::vector<Relation> >& relations)
94 {
95  this->relations = relations;
96  if (relations->size() > 0)
97  this->relTree = boost::make_shared<RTree<RelId, FixedRect>>();
98 }
99 
100 bool Geodata::containsData(const FixedRect &rect) const
101 {
102  return (nodesTree && nodesTree->contains(rect))
103  || (waysTree && waysTree->contains(rect))
104  || (relTree && relTree->contains(rect));
105 }
106 
107 shared_ptr<std::vector<NodeId> > Geodata::getNodeIDs(const FixedRect& rect) const
108 {
109  shared_ptr<std::vector<NodeId> > nodeIDs = boost::make_shared< std::vector<NodeId> >();
110  if (nodesTree)
111  nodesTree->search(nodeIDs, rect);
112  return nodeIDs;
113 }
114 
115 shared_ptr<std::vector<WayId> > Geodata::getWayIDs(const FixedRect& rect) const
116 {
117  shared_ptr<std::vector<WayId> > wayIDs = boost::make_shared< std::vector<WayId> >();
118  if (waysTree)
119  waysTree->search(wayIDs, rect);
120  return wayIDs;
121 }
122 
123 shared_ptr<std::vector<RelId> > Geodata::getRelationIDs(const FixedRect& rect) const
124 {
125  shared_ptr<std::vector<RelId> > relationIDs = boost::make_shared< std::vector<RelId> >();
126  if (relTree)
127  relTree->search(relationIDs, rect);
128  return relationIDs;
129 }
130 
132 {
133  return &nodes->at(id.getRaw());
134 }
135 
137 {
138  return &ways->at(id.getRaw());
139 }
140 
142 {
143  return &relations->at(id.getRaw());
144 }
145 
146 void Geodata::load(const string& path)
147 {
148  LOG_SEV(geo_log, info) << "Load geodata from \"" << path << "\"";
149 
150  Archive a(path);
151  std::vector<Archive::entry_t> entries;
152  a.getEntries(entries);
153 
154  int i = 0;
155  std::ifstream ifs(path, std::ios::binary | std::ios::in);
156  ifs.seekg(entries[i++].offset);
157  boost::archive::binary_iarchive ia(ifs);
158  ia >> *this;
159 
160  // set offsets of leaf inside archive file
161  if (nodesTree) {
162  nodesTree->setLeafFile(path, entries[i].offset, entries[i].length);
163  i++;
164  }
165  if (waysTree) {
166  waysTree->setLeafFile(path, entries[i].offset, entries[i].length);
167  i++;
168  }
169  if (relTree) {
170  relTree->setLeafFile(path, entries[i].offset, entries[i].length);
171  i++;
172  }
173 }
174 
175 void Geodata::serialize(const string& serPath) const
176 {
177  LOG_SEV(geo_log, info) << "Serialize to \"" << serPath << "\"";
178 
179  std::ofstream ofs(serPath, std::ios::binary | std::ios::out);
180  boost::archive::binary_oarchive oa(ofs);
181  oa << *this;
182 }
183 
184 void Geodata::save(const string& outPath)
185 {
186  boost::filesystem::path out = boost::filesystem::absolute(boost::filesystem::path(outPath));
187  boost::filesystem::path base = out.parent_path();
188  string serPath = (base / "data.ser").string();
189  string nodesPath = (base / "nodes.bin").string();
190  string waysPath = (base / "ways.bin").string();
191  string relationsPath = (base / "relations.bin").string();
192 
193  buildTrees(nodesPath, waysPath, relationsPath);
194 
195  serialize(serPath);
196 
197  LOG_SEV(geo_log, info) << "Save geodata to \"" << outPath << "\"";
198  Archive a(outPath);
199  a.addFile(serPath);
200  if (nodesTree)
201  a.addFile(nodesPath);
202  if (waysTree)
203  a.addFile(waysPath);
204  if (relTree)
205  a.addFile(relationsPath);
206  a.write();
207 
208  // remove temp files
209  remove(serPath.c_str());
210  if (nodesTree)
211  remove(nodesPath.c_str());
212  if (waysTree)
213  remove(waysPath.c_str());
214  if (relTree)
215  remove(relationsPath.c_str());
216 }
217 
219 {
220  return calculateBoundingBox(way.getNodeIDs());
221 }
222 
224 {
225  coord_t maxX = std::numeric_limits<coord_t>::min();
226  coord_t maxY = std::numeric_limits<coord_t>::min();
227  coord_t minX = std::numeric_limits<coord_t>::max();
228  coord_t minY = std::numeric_limits<coord_t>::max();
229 
230  const std::vector<NodeId>& nodeIDs = relation.getNodeIDs();
231  if (nodeIDs.size() > 0)
232  {
233  FixedRect result = calculateBoundingBox(nodeIDs);
234  minX = result.minX;
235  minY = result.minY;
236  maxX = result.maxX;
237  maxY = result.maxY;
238  }
239 
240  const std::vector<WayId>& wayIDs = relation.getWayIDs();
241  if (wayIDs.size() > 0)
242  {
243  FixedRect result = calculateBoundingBox(wayIDs);
244  minX = std::min(minX, result.minX);
245  minY = std::min(minY, result.minY);
246  maxX = std::max(maxX, result.maxX);
247  maxY = std::max(maxY, result.maxY);
248  }
249 
250  if (maxX < minX || maxY < minY)
251  return FixedRect(0, 0, 0, 0);
252 
253  return FixedRect(minX, minY, maxX, maxY);
254 }
255 
256 FixedRect Geodata::calculateBoundingBox(const std::vector<NodeId>& nodeIDs) const
257 {
259  coord_t maxX = std::numeric_limits<coord_t>::min();
260  coord_t maxY = std::numeric_limits<coord_t>::min();
261  coord_t minX = std::numeric_limits<coord_t>::max();
262  coord_t minY = std::numeric_limits<coord_t>::max();
263 
264  for (NodeId i : nodeIDs) {
265  help = nodes->at(i.getRaw()).getLocation();
266 
267  maxX = std::max(maxX, help.x);
268  maxY = std::max(maxY, help.y);
269  minX = std::min(minX, help.x);
270  minY = std::min(minY, help.y);
271  }
272 
273  if (maxX < minX || maxY < minY)
274  return FixedRect(0, 0, 0, 0.0);
275 
276  return FixedRect(minX, minY, maxX, maxY);
277 }
278 
279 FixedRect Geodata::calculateBoundingBox(const std::vector<WayId>& wayIDs) const
280 {
281  coord_t maxX = std::numeric_limits<coord_t>::min();
282  coord_t maxY = std::numeric_limits<coord_t>::min();
283  coord_t minX = std::numeric_limits<coord_t>::max();
284  coord_t minY = std::numeric_limits<coord_t>::max();
285 
286  for (WayId i : wayIDs) {
287  FixedRect bounds = calculateBoundingBox(ways->at(i.getRaw()));
288  minX = std::min(minX, bounds.minX);
289  minY = std::min(minY, bounds.minY);
290  maxX = std::max(maxX, bounds.maxX);
291  maxY = std::max(maxY, bounds.maxY);
292  }
293 
294  if (maxX < minX || maxY < minY)
295  return FixedRect(0, 0, 0, 0.0);
296 
297  return FixedRect(minX, minY, maxX, maxY);
298 }
TESTABLE FixedRect calculateBoundingBox(const Way &way) const
Definition: geodata.cpp:218
basic_rect< coord_t > FixedRect
Definition: rect.hpp:171
void getEntries(std::vector< entry_t > &entries)
Definition: archive.cpp:93
shared_ptr< std::vector< Relation > > relations
Definition: geodata.hpp:67
TESTABLE shared_ptr< std::vector< WayId > > getWayIDs(const FixedRect &rect) const
Definition: geodata.cpp:115
Definition: node.hpp:28
bool containsData(const FixedRect &rect) const
Definition: geodata.cpp:100
void write()
Definition: archive.cpp:40
TESTABLE const std::vector< NodeId > & getNodeIDs() const
Definition: relation.cpp:44
shared_ptr< std::vector< Way > > ways
Definition: geodata.hpp:65
TESTABLE void save(const string &path)
Definition: geodata.cpp:184
std::int32_t coord_t
Definition: settings.hpp:117
TESTABLE Way * getWay(WayId id) const
Definition: geodata.cpp:136
T minY
Definition: rect.hpp:52
TESTABLE const std::vector< WayId > & getWayIDs() const
Definition: relation.cpp:39
TESTABLE void insertWays(const shared_ptr< std::vector< Way > > &ways)
Definition: geodata.cpp:86
#define LOG_SEV(log, lvl)
Definition: settings.hpp:78
shared_ptr< RTree< NodeId, FixedPoint > > nodesTree
note the trees are initialized by buildTree on serialisation
Definition: geodata.hpp:70
void addFile(const string &filePath)
Definition: archive.cpp:35
void buildTrees(const string &nodePath, const string &wayPath, const string &relationPath)
This file is part of alaCarte.
Definition: geodata.cpp:49
void serialize(const string &serPath) const
Definition: geodata.cpp:175
TESTABLE shared_ptr< std::vector< RelId > > getRelationIDs(const FixedRect &rect) const
Definition: geodata.cpp:123
shared_ptr< RTree< RelId, FixedRect > > relTree
Definition: geodata.hpp:72
TESTABLE void insertRelations(const shared_ptr< std::vector< Relation > > &relations)
Definition: geodata.cpp:93
shared_ptr< RTree< WayId, FixedRect > > waysTree
Definition: geodata.hpp:71
TESTABLE Node * getNode(NodeId id) const
Definition: geodata.cpp:131
shared_ptr< std::vector< Node > > nodes
Definition: geodata.hpp:66
T maxX
Definition: rect.hpp:53
TESTABLE void load(const string &path)
Definition: geodata.cpp:146
static const char * help
Use Configuration::has to check weather the user wanted help.
TESTABLE void insertNodes(const shared_ptr< std::vector< Node > > &nodes)
Definition: geodata.cpp:79
TESTABLE Relation * getRelation(RelId id) const
Definition: geodata.cpp:141
TESTABLE shared_ptr< std::vector< NodeId > > getNodeIDs(const FixedRect &rect) const
Definition: geodata.cpp:107
Definition: way.hpp:31
const std::vector< NodeId > & getNodeIDs() const
Definition: way.hpp:45
T maxY
Definition: rect.hpp:54
T minX
Definition: rect.hpp:51