mirror of
https://github.com/ciphervance/supercell-wx.git
synced 2025-10-30 20:00:05 +00:00
Began working on distance from location code
This commit is contained in:
parent
60aed45450
commit
9f47e0ad72
7 changed files with 198 additions and 4 deletions
|
|
@ -5,14 +5,16 @@
|
|||
|
||||
#include <GeographicLib/Gnomonic.hpp>
|
||||
#include <geos/algorithm/PointLocation.h>
|
||||
#include <geos/algorithm/distance/PointPairDistance.h>
|
||||
#include <geos/algorithm/distance/DistanceToPoint.h>
|
||||
#include <geos/geom/CoordinateSequence.h>
|
||||
#include <geos/geom/GeometryFactory.h>
|
||||
|
||||
namespace scwx
|
||||
{
|
||||
namespace qt
|
||||
{
|
||||
namespace util
|
||||
{
|
||||
namespace util {
|
||||
namespace GeographicLib
|
||||
{
|
||||
|
||||
|
|
@ -82,6 +84,12 @@ bool AreaContainsPoint(const std::vector<common::Coordinate>& area,
|
|||
return areaContainsPoint;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
units::angle::degrees<double>
|
||||
GetAngle(double lat1, double lon1, double lat2, double lon2)
|
||||
{
|
||||
|
|
@ -137,6 +145,93 @@ GetDistance(double lat1, double lon1, double lat2, double lon2)
|
|||
return units::length::meters<double> {distance};
|
||||
}
|
||||
|
||||
bool AreaInRangeOfPoint(const std::vector<common::Coordinate>& area,
|
||||
const common::Coordinate& point,
|
||||
const units::length::meters<double> distance)
|
||||
{
|
||||
// Cannot have an area with just two points
|
||||
if (area.size() <= 2 || (area.size() == 3 && area.front() == area.back()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
::GeographicLib::Gnomonic gnomonic =
|
||||
::GeographicLib::Gnomonic(DefaultGeodesic());
|
||||
geos::geom::CoordinateSequence sequence {};
|
||||
double x;
|
||||
double y;
|
||||
|
||||
// Using a gnomonic projection with the test point as the center
|
||||
// latitude/longitude, the projected test point will be at (0, 0)
|
||||
geos::geom::CoordinateXY zero {};
|
||||
|
||||
// Create the area coordinate sequence using a gnomonic projection
|
||||
for (auto& areaCoordinate : area)
|
||||
{
|
||||
gnomonic.Forward(point.latitude_,
|
||||
point.longitude_,
|
||||
areaCoordinate.latitude_,
|
||||
areaCoordinate.longitude_,
|
||||
x,
|
||||
y);
|
||||
sequence.add(x, y);
|
||||
}
|
||||
|
||||
// get a point on the circle with the radius of the range in lat lon.
|
||||
units::angle::degrees<double> angle = units::angle::degrees<double>(0);
|
||||
common::Coordinate radiusPoint = GetCoordinate(point, angle, distance);
|
||||
// get the radius in gnomonic projection
|
||||
gnomonic.Forward(point.latitude_,
|
||||
point.longitude_,
|
||||
radiusPoint.latitude_,
|
||||
radiusPoint.longitude_,
|
||||
x,
|
||||
y);
|
||||
double gnomonicRadius = sqrt(x * x + y * y);
|
||||
|
||||
// If the sequence is not a ring, add the first point again for closure
|
||||
if (!sequence.isRing())
|
||||
{
|
||||
sequence.add(sequence.front(), false);
|
||||
}
|
||||
|
||||
// The sequence should be a ring at this point, but make sure
|
||||
if (sequence.isRing())
|
||||
{
|
||||
try
|
||||
{
|
||||
if (geos::algorithm::PointLocation::isInRing(zero, &sequence))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Calculate the distance the point is from the output
|
||||
geos::algorithm::distance::PointPairDistance distancePair;
|
||||
auto geometryFactory =
|
||||
geos::geom::GeometryFactory::getDefaultInstance();
|
||||
auto linearRing = geometryFactory->createLinearRing(sequence);
|
||||
auto polygon =
|
||||
geometryFactory->createPolygon(std::move(linearRing));
|
||||
geos::algorithm::distance::DistanceToPoint::computeDistance(*polygon,
|
||||
zero,
|
||||
distancePair);
|
||||
if (gnomonicRadius > distancePair.getDistance())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
catch (const std::exception&)
|
||||
{
|
||||
logger_->trace("Invalid area sequence");
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace GeographicLib
|
||||
} // namespace util
|
||||
} // namespace qt
|
||||
|
|
|
|||
|
|
@ -90,6 +90,23 @@ common::Coordinate GetCoordinate(const common::Coordinate& center,
|
|||
units::length::meters<double>
|
||||
GetDistance(double lat1, double lon1, double lat2, double lon2);
|
||||
|
||||
|
||||
/**
|
||||
* Determine if an area/ring, oriented in either direction, is within a
|
||||
* distance of a point. A point lying on the area boundary is considered to be
|
||||
* inside the area, and thus always in range. Any part of the area being inside
|
||||
* the radius counts as inside.
|
||||
*
|
||||
* @param [in] area A vector of Coordinates representing the area
|
||||
* @param [in] point The point to check against the area
|
||||
* @param [in] distance The max distance in meters
|
||||
*
|
||||
* @return true if area is inside the radius of the point
|
||||
*/
|
||||
bool AreaInRangeOfPoint(const std::vector<common::Coordinate>& area,
|
||||
const common::Coordinate& point,
|
||||
const units::length::meters<double> distance);
|
||||
|
||||
} // namespace GeographicLib
|
||||
} // namespace util
|
||||
} // namespace qt
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue