Properly clip lines so that we don't get crazy coords with long linestrings (relative to tile coords)
This commit is contained in:
parent
4e8ccd6f7d
commit
663a7c52c7
@ -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,8 +371,11 @@ 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);
|
||||||
encode_tile_line(tile_line, speed_kmh, weight_offsets[forward_weight],
|
if (!tile_line.empty())
|
||||||
forward_datasource, start_x, start_y);
|
{
|
||||||
|
encode_tile_line(tile_line, speed_kmh, weight_offsets[forward_weight],
|
||||||
|
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`
|
||||||
@ -350,8 +390,11 @@ 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);
|
||||||
encode_tile_line(tile_line, speed_kmh, weight_offsets[reverse_weight],
|
if (!tile_line.empty())
|
||||||
reverse_datasource, start_x, start_y);
|
{
|
||||||
|
encode_tile_line(tile_line, speed_kmh, weight_offsets[reverse_weight],
|
||||||
|
reverse_datasource, start_x, start_y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user