inline std::pair<double, FloatCoordinate> projectPointOnSegment(const FloatCoordinate &source,
                                                                const FloatCoordinate &target,
                                                                const FloatCoordinate &coordinate)
{
    const FloatCoordinate slope_vector{target.lon - source.lon, target.lat - source.lat};
    const FloatCoordinate rel_coordinate{coordinate.lon - source.lon, coordinate.lat - source.lat};
    // dot product of two un-normed vectors
    const auto unnormed_ratio = static_cast<double>(slope_vector.lon * rel_coordinate.lon) +
                                static_cast<double>(slope_vector.lat * rel_coordinate.lat);
    // squared length of the slope vector
    const auto squared_length = static_cast<double>(slope_vector.lon * slope_vector.lon) +
                                static_cast<double>(slope_vector.lat * slope_vector.lat);

    if (squared_length < std::numeric_limits<double>::epsilon())
    {
        return {0, source};
    }

    const double normed_ratio = unnormed_ratio / squared_length;
    double clamped_ratio = normed_ratio;
    if (clamped_ratio > 1.)
    {
        clamped_ratio = 1.;
    }
    else if (clamped_ratio < 0.)
    {
        clamped_ratio = 0.;
    }

    return {clamped_ratio,
            {
                FloatLongitude(1.0 - clamped_ratio) * source.lon +
                    target.lon * FloatLongitude(clamped_ratio),
                FloatLatitude(1.0 - clamped_ratio) * source.lat +
                    target.lat * FloatLatitude(clamped_ratio),
            }};
}
Esempio n. 2
0
bool FloatCoordinate::IsValid() const
{
    return !(lat > FloatLatitude(90) || lat < FloatLatitude(-90) || lon > FloatLongitude(180) ||
             lon < FloatLongitude(-180));
}
inline FloatLongitude clamp(const FloatLongitude lon)
{
    return std::max(std::min(lon, FloatLongitude(detail::MAX_LONGITUDE)),
                    FloatLongitude(-detail::MAX_LONGITUDE));
}