File: osm_lua_processing.h

package info (click to toggle)
tilemaker 3.0.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 78,284 kB
  • sloc: cpp: 28,715; ansic: 4,052; makefile: 180; ruby: 77; sh: 6
file content (311 lines) | stat: -rw-r--r-- 9,646 bytes parent folder | download
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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
/*! \file */ 
#ifndef _OSM_LUA_PROCESSING_H
#define _OSM_LUA_PROCESSING_H

#include <vector>
#include <string>
#include <sstream>
#include <map>
#include "geom.h"
#include "osm_store.h"
#include "shared_data.h"
#include "output_object.h"
#include "shp_mem_tiles.h"
#include "osm_mem_tiles.h"
#include "helpers.h"
#include "pbf_reader.h"
#include <protozero/data_view.hpp>

#include <boost/container/flat_map.hpp>

class TagMap;
class SignificantTags;

// Lua
extern "C" {
	#include "lua.h"
    #include "lualib.h"
    #include "lauxlib.h"
}

#include "external/kaguya.hpp"

// FIXME: why is this global ?
extern bool verbose;

class AttributeStore;
class AttributeSet;

/**
	\brief OsmLuaProcessing - converts OSM objects into OutputObjects.
	
	The input objects are generated by PbfReader. The output objects are sent to OsmMemTiles for storage.

	This class provides a consistent interface for Lua scripts to access.
*/
class OsmLuaProcessing { 

public:
	// ----	initialization routines

	OsmLuaProcessing(
		OSMStore &osmStore,
		const class Config &configIn,
		class LayerDefinition &layers, 
		const std::string &luaFile,
		const class ShpMemTiles &shpMemTiles, 
		class OsmMemTiles &osmMemTiles,
		AttributeStore &attributeStore,
		bool materializeGeometries
	);
	~OsmLuaProcessing();

	// ----	Helpers provided for main routine
	void handleUserSignal(int signum);

	// Has this object been assigned to any layers?
	bool empty();
	
	// Do we have Lua routines for non-MP relations?
	bool canReadRelations();
	bool canPostScanRelations();
	bool canWriteRelations();

	// Shapefile tag remapping
	bool canRemapShapefiles();
	kaguya::LuaTable newTable();
	kaguya::LuaTable remapAttributes(kaguya::LuaTable& in_table, const std::string &layerName);

	// ----	Data loading methods

	using tag_map_t = boost::container::flat_map<protozero::data_view, protozero::data_view, DataViewLessThan>;

	// Scan non-MP relation
	bool scanRelation(WayID id, const TagMap& tags);

	// Post-scan non-MP relations
	void postScanRelations();
	
	/// \brief We are now processing a significant node
	bool setNode(NodeID id, LatpLon node, const TagMap& tags);

	/// \brief We are now processing a way
	bool setWay(WayID wayId, LatpLonVec const &llVec, const TagMap& tags);

	/** \brief We are now processing a relation
	 * (note that we store relations as ways with artificial IDs, and that
	 *  we use decrementing positive IDs to give a bit more space for way IDs)
	 */
	void setRelation(
		const std::vector<protozero::data_view>& stringTable,
		const PbfReader::Relation& relation,
		const WayVec& outerWayVec,
		const WayVec& innerWayVec,
		const TagMap& tags,
		bool isNativeMP,
		bool isInnerOuter
	);

	// ----	Metadata queries called from Lua

	// Get the ID of the current object
	std::string Id() const;

	// Check if there's a value for a given key
	bool Holds(const std::string& key) const;

	// Get an OSM tag for a given key (or return empty string if none)
	const std::string Find(const std::string& key) const;

	// Check if an object has any tags
	bool HasTags() const;

	// ----	Spatial queries called from Lua

	// Find intersecting shapefile layer
	std::vector<std::string> FindIntersecting(const std::string &layerName);
	double AreaIntersecting(const std::string &layerName);
	bool Intersects(const std::string &layerName);
	template <typename GeometryT> double intersectsArea(const std::string &layerName, GeometryT &geom) const;
	template <typename GeometryT> std::vector<uint> intersectsQuery(const std::string &layerName, bool once, GeometryT &geom) const;

	std::vector<std::string> FindCovering(const std::string &layerName);
	bool CoveredBy(const std::string &layerName);
	template <typename GeometryT> std::vector<uint> coveredQuery(const std::string &layerName, bool once, GeometryT &geom) const;
		
	// Returns whether it is closed polygon
	bool IsClosed() const;

	// Returns area
	double Area();
	double multiPolygonArea(const MultiPolygon &mp) const;

	// Returns length
	double Length();
	
	// Return centroid lat/lon
	std::vector<double> Centroid(kaguya::VariadicArgType algorithm);

	enum class CentroidAlgorithm: char { Centroid = 0, Polylabel = 1 };
	CentroidAlgorithm defaultCentroidAlgorithm() const { return CentroidAlgorithm::Polylabel; }
	CentroidAlgorithm parseCentroidAlgorithm(const std::string& algorithm) const;
	Point calculateCentroid(CentroidAlgorithm algorithm);

	enum class CorrectGeometryResult: char { Invalid = 0, Valid = 1, Corrected = 2 };
	// ----	Requests from Lua to write this way/node to a vector tile's Layer
	template<class GeometryT>
	CorrectGeometryResult CorrectGeometry(GeometryT &geom)
	{
		geom::validity_failure_type failure = geom::validity_failure_type::no_failure;
		if (isRelation && !geom::is_valid(geom,failure)) {
			if (verbose) std::cout << "Relation " << originalOsmID << " has " << boost_validity_error(failure) << std::endl;
		} else if (isWay && !geom::is_valid(geom,failure)) {
			if (verbose && failure!=22) std::cout << "Way " << originalOsmID << " has " << boost_validity_error(failure) << std::endl;
		}
		
		if (failure==boost::geometry::failure_spikes)
			geom::remove_spikes(geom);
		if (failure == boost::geometry::failure_few_points) 
			return CorrectGeometryResult::Invalid;
		if (failure) {
			std::time_t start = std::time(0);
			make_valid(geom);
			if (verbose && std::time(0)-start>3) {
				std::cout << (isRelation ? "Relation " : "Way ") << originalOsmID << " took " << (std::time(0)-start) << " seconds to correct" << std::endl;
			}
			return CorrectGeometryResult::Corrected;
		}
		return CorrectGeometryResult::Valid;
	}

	// Add layer
	void Layer(const std::string &layerName, bool area);
	void LayerAsCentroid(const std::string &layerName, kaguya::VariadicArgType nodeSources);
	
	// Set attributes in a vector tile's Attributes table
	void Attribute(const std::string &key, const protozero::data_view val, const char minzoom);
	void AttributeNumeric(const std::string &key, const float val, const char minzoom);
	void AttributeBoolean(const std::string &key, const bool val, const char minzoom);
	void MinZoom(const double z);
	void ZOrder(const double z);
	
	// Relation scan support

	struct OptionalRelation {
		bool done;
		lua_Integer id;
		std::string role;
	};
	OptionalRelation NextRelation();
	void RestartRelations();
	std::string FindInRelation(const std::string &key);
	void Accept();
	void SetTag(const std::string &key, const std::string &value);

	// Write error if in verbose mode
	void ProcessingError(const std::string &errStr) {
		if (verbose) { std::cerr << errStr << std::endl; }
	}

	// ----	vector_layers metadata entry

	void setVectorLayerMetadata(const uint_least8_t layer, const std::string &key, const uint type);

	SignificantTags GetSignificantNodeKeys();
	SignificantTags GetSignificantWayKeys();

	// ---- Cached geometries creation

	const Linestring &linestringCached();

	const Polygon &polygonCached();

	const MultiLinestring &multiLinestringCached();

	const MultiPolygon &multiPolygonCached();

	inline AttributeStore &getAttributeStore() { return attributeStore; }

	struct luaProcessingException :std::exception {};
	const TagMap* currentTags;
	bool isPostScanRelation;				// processing a relation in postScanRelation

private:
	/// Internal: clear current cached state
	inline void reset() {
		outputs.clear();
		currentRelation = nullptr;
		stringTable = nullptr;
		llVecPtr = nullptr;
		outerWayVecPtr = nullptr;
		innerWayVecPtr = nullptr;
		linestringInited = false;
		multiLinestringInited = false;
		polygonInited = false;
		multiPolygonInited = false;
		relationAccepted = false;
		relationList.clear();
		relationSubscript = -1;
		lastStoredGeometryId = 0;
		isWay = false;
		isRelation = false;
		isPostScanRelation = false;
	}

	void removeAttributeIfNeeded(const std::string& key);

	const inline Point getPoint() {
		return Point(lon/10000000.0,latp/10000000.0);
	}
	
	OSMStore &osmStore;	// global OSM store

	kaguya::State luaState;
	bool supportsRemappingShapefiles;
	bool supportsReadingRelations;
	bool supportsPostScanRelations;
	bool supportsWritingRelations;
	const class ShpMemTiles &shpMemTiles;
	class OsmMemTiles &osmMemTiles;
	AttributeStore &attributeStore;			// key/value store

	int64_t originalOsmID;					///< Original OSM object ID
	bool isWay, isRelation, isClosed;		///< Way, node, relation?

	bool relationAccepted;					// in scanRelation, whether we're using a non-MP relation
	std::vector<std::pair<WayID, uint16_t>> relationList;		// in processNode/processWay, list of relations this entity is in, and its role
	int relationSubscript = -1;				// in processWay, position in the relation list

	int32_t lon,latp;						///< Node coordinates
	LatpLonVec const *llVecPtr;
	WayVec const *outerWayVecPtr;
	WayVec const *innerWayVecPtr;

	Linestring linestringCache;
	bool linestringInited;
	Polygon polygonCache;
	bool polygonInited;
	MultiLinestring multiLinestringCache;
	bool multiLinestringInited;
	MultiPolygon multiPolygonCache;
	bool multiPolygonInited;

	NodeID lastStoredGeometryId;
	OutputGeometryType lastStoredGeometryType;

	const class Config &config;
	class LayerDefinition &layers;

	std::vector<std::pair<OutputObject, AttributeSet>> outputs;		// All output objects that have been created
	std::vector<std::string> outputKeys;
	const PbfReader::Relation* currentRelation;
	const boost::container::flat_map<std::string, std::string>* currentPostScanTags; // for postScan only
	const std::vector<protozero::data_view>* stringTable;

	std::vector<OutputObject> finalizeOutputs();

	bool materializeGeometries;
	bool wayEmitted;
};

#endif //_OSM_LUA_PROCESSING_H