Properly clip lines so that we don't get crazy coords with long linestrings (relative to tile coords)
This commit is contained in:
		
							parent
							
								
									fc027417d8
								
							
						
					
					
						commit
						08e56956d6
					
				| @ -3,6 +3,10 @@ | |||||||
| 
 | 
 | ||||||
| #include "util/coordinate_calculation.hpp" | #include "util/coordinate_calculation.hpp" | ||||||
| 
 | 
 | ||||||
|  | #include <boost/geometry.hpp> | ||||||
|  | #include <boost/geometry/geometries/point_xy.hpp> | ||||||
|  | #include <boost/geometry/geometries/geometries.hpp> | ||||||
|  | 
 | ||||||
| #include <protozero/varint.hpp> | #include <protozero/varint.hpp> | ||||||
| #include <protozero/pbf_writer.hpp> | #include <protozero/pbf_writer.hpp> | ||||||
| 
 | 
 | ||||||
| @ -23,6 +27,7 @@ namespace detail | |||||||
| { | { | ||||||
| // Vector tiles are 4096 virtual pixels on each side
 | // Vector tiles are 4096 virtual pixels on each side
 | ||||||
| const constexpr double VECTOR_TILE_EXTENT = 4096.0; | const constexpr double VECTOR_TILE_EXTENT = 4096.0; | ||||||
|  | const constexpr double VECTOR_TILE_BUFFER = 128.0; | ||||||
| 
 | 
 | ||||||
| // Simple container class for WSG84 coordinates
 | // Simple container class for WSG84 coordinates
 | ||||||
| template <typename T> struct Point final | template <typename T> struct Point final | ||||||
| @ -67,6 +72,14 @@ struct point_type_i final | |||||||
| using FixedLine = std::vector<detail::Point<std::int32_t>>; | using FixedLine = std::vector<detail::Point<std::int32_t>>; | ||||||
| using FloatLine = std::vector<detail::Point<double>>; | using FloatLine = std::vector<detail::Point<double>>; | ||||||
| 
 | 
 | ||||||
|  | typedef boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian> point_t; | ||||||
|  | typedef boost::geometry::model::linestring<point_t> linestring_t; | ||||||
|  | typedef boost::geometry::model::box<point_t> box_t; | ||||||
|  | typedef boost::geometry::model::multi_linestring<linestring_t> multi_linestring_t; | ||||||
|  | const static box_t clip_box({-detail::VECTOR_TILE_BUFFER, -detail::VECTOR_TILE_BUFFER}, | ||||||
|  |                             {detail::VECTOR_TILE_EXTENT + detail::VECTOR_TILE_BUFFER, | ||||||
|  |                              detail::VECTOR_TILE_EXTENT + detail::VECTOR_TILE_BUFFER}); | ||||||
|  | 
 | ||||||
| // from mapnik-vector-tile
 | // from mapnik-vector-tile
 | ||||||
| // Encodes a linestring using protobuf zigzag encoding
 | // Encodes a linestring using protobuf zigzag encoding
 | ||||||
| inline bool encodeLinestring(const FixedLine &line, | inline bool encodeLinestring(const FixedLine &line, | ||||||
| @ -111,7 +124,9 @@ FixedLine coordinatesToTileLine(const util::Coordinate start, | |||||||
|                           static_cast<double>(util::toFloating(start.lat))); |                           static_cast<double>(util::toFloating(start.lat))); | ||||||
|     geo_line.emplace_back(static_cast<double>(util::toFloating(target.lon)), |     geo_line.emplace_back(static_cast<double>(util::toFloating(target.lon)), | ||||||
|                           static_cast<double>(util::toFloating(target.lat))); |                           static_cast<double>(util::toFloating(target.lat))); | ||||||
|     FixedLine tile_line; | 
 | ||||||
|  |     linestring_t unclipped_line; | ||||||
|  | 
 | ||||||
|     for (auto const &pt : geo_line) |     for (auto const &pt : geo_line) | ||||||
|     { |     { | ||||||
|         double px_merc = pt.x * mercator::DEGREE_TO_PX; |         double px_merc = pt.x * mercator::DEGREE_TO_PX; | ||||||
| @ -123,8 +138,29 @@ FixedLine coordinatesToTileLine(const util::Coordinate start, | |||||||
|         const auto py = std::round( |         const auto py = std::round( | ||||||
|             ((tile_bbox.maxy - py_merc) * mercator::TILE_SIZE / tile_bbox.height()) * |             ((tile_bbox.maxy - py_merc) * mercator::TILE_SIZE / tile_bbox.height()) * | ||||||
|             detail::VECTOR_TILE_EXTENT / util::coordinate_calculation::mercator::TILE_SIZE); |             detail::VECTOR_TILE_EXTENT / util::coordinate_calculation::mercator::TILE_SIZE); | ||||||
|         tile_line.emplace_back(px, py); | 
 | ||||||
|  |         boost::geometry::append(unclipped_line, point_t(px, py)); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     multi_linestring_t clipped_line; | ||||||
|  | 
 | ||||||
|  |     boost::geometry::intersection(clip_box, unclipped_line, clipped_line); | ||||||
|  | 
 | ||||||
|  |     FixedLine tile_line; | ||||||
|  | 
 | ||||||
|  |     // b::g::intersection might return a line with one point if the
 | ||||||
|  |     // original line was very short and coords were dupes
 | ||||||
|  |     if (!clipped_line.empty() && clipped_line[0].size() == 2) | ||||||
|  |     { | ||||||
|  |         if (clipped_line[0].size() == 2) | ||||||
|  |         { | ||||||
|  |             for (const auto &p : clipped_line[0]) | ||||||
|  |             { | ||||||
|  |                 tile_line.emplace_back(p.get<0>(), p.get<1>()); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     return tile_line; |     return tile_line; | ||||||
| } | } | ||||||
| } | } | ||||||
| @ -317,6 +353,7 @@ Status TilePlugin::HandleRequest(const api::TileParameters ¶meters, std::str | |||||||
|                                           duration); // duration value offset
 |                                           duration); // duration value offset
 | ||||||
|                     } |                     } | ||||||
|                     { |                     { | ||||||
|  | 
 | ||||||
|                         // Encode the geometry for the feature
 |                         // Encode the geometry for the feature
 | ||||||
|                         protozero::packed_field_uint32 geometry(feature_writer, 4); |                         protozero::packed_field_uint32 geometry(feature_writer, 4); | ||||||
|                         encodeLinestring(tile_line, geometry, start_x, start_y); |                         encodeLinestring(tile_line, geometry, start_x, start_y); | ||||||
| @ -334,9 +371,12 @@ Status TilePlugin::HandleRequest(const api::TileParameters ¶meters, std::str | |||||||
|                         static_cast<std::uint32_t>(round(length / forward_weight * 10 * 3.6)); |                         static_cast<std::uint32_t>(round(length / forward_weight * 10 * 3.6)); | ||||||
| 
 | 
 | ||||||
|                     auto tile_line = coordinatesToTileLine(a, b, tile_bbox); |                     auto tile_line = coordinatesToTileLine(a, b, tile_bbox); | ||||||
|  |                     if (!tile_line.empty()) | ||||||
|  |                     { | ||||||
|                         encode_tile_line(tile_line, speed_kmh, weight_offsets[forward_weight], |                         encode_tile_line(tile_line, speed_kmh, weight_offsets[forward_weight], | ||||||
|                                          forward_datasource, start_x, start_y); |                                          forward_datasource, start_x, start_y); | ||||||
|                     } |                     } | ||||||
|  |                 } | ||||||
| 
 | 
 | ||||||
|                 // Repeat the above for the coordinates reversed and using the `reverse`
 |                 // Repeat the above for the coordinates reversed and using the `reverse`
 | ||||||
|                 // properties
 |                 // properties
 | ||||||
| @ -350,11 +390,14 @@ Status TilePlugin::HandleRequest(const api::TileParameters ¶meters, std::str | |||||||
|                         static_cast<std::uint32_t>(round(length / reverse_weight * 10 * 3.6)); |                         static_cast<std::uint32_t>(round(length / reverse_weight * 10 * 3.6)); | ||||||
| 
 | 
 | ||||||
|                     auto tile_line = coordinatesToTileLine(b, a, tile_bbox); |                     auto tile_line = coordinatesToTileLine(b, a, tile_bbox); | ||||||
|  |                     if (!tile_line.empty()) | ||||||
|  |                     { | ||||||
|                         encode_tile_line(tile_line, speed_kmh, weight_offsets[reverse_weight], |                         encode_tile_line(tile_line, speed_kmh, weight_offsets[reverse_weight], | ||||||
|                                          reverse_datasource, start_x, start_y); |                                          reverse_datasource, start_x, start_y); | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         // Field id 3 is the "keys" attribute
 |         // Field id 3 is the "keys" attribute
 | ||||||
|         // We need two "key" fields, these are referred to with 0 and 1 (their array indexes)
 |         // We need two "key" fields, these are referred to with 0 and 1 (their array indexes)
 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user