mirror of
https://github.com/ciphervance/supercell-wx.git
synced 2025-11-01 19:30:05 +00:00
Determine if a geographic area contains a point
This commit is contained in:
parent
6ec594144d
commit
8780da4148
5 changed files with 85 additions and 1 deletions
|
|
@ -1,4 +1,9 @@
|
|||
#include <scwx/qt/util/geographic_lib.hpp>
|
||||
#include <scwx/util/logger.hpp>
|
||||
|
||||
#include <GeographicLib/Gnomonic.hpp>
|
||||
#include <geos/algorithm/PointLocation.h>
|
||||
#include <geos/geom/CoordinateSequence.h>
|
||||
|
||||
namespace scwx
|
||||
{
|
||||
|
|
@ -9,6 +14,9 @@ namespace util
|
|||
namespace GeographicLib
|
||||
{
|
||||
|
||||
static const std::string logPrefix_ = "scwx::qt::util::geographic_lib";
|
||||
static const auto logger_ = scwx::util::Logger::Create(logPrefix_);
|
||||
|
||||
const ::GeographicLib::Geodesic& DefaultGeodesic()
|
||||
{
|
||||
static const ::GeographicLib::Geodesic geodesic_ {
|
||||
|
|
@ -18,6 +26,60 @@ const ::GeographicLib::Geodesic& DefaultGeodesic()
|
|||
return geodesic_;
|
||||
}
|
||||
|
||||
bool AreaContainsPoint(const std::vector<common::Coordinate>& area,
|
||||
const common::Coordinate& point)
|
||||
{
|
||||
// Cannot have an area with just two points
|
||||
if (area.size() <= 2 || area.size() == 3 && area.front() == area.back())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
::GeographicLib::Gnomonic gnomonic {};
|
||||
geos::geom::CoordinateSequence sequence {};
|
||||
double x;
|
||||
double y;
|
||||
bool areaContainsPoint = false;
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// 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
|
||||
{
|
||||
areaContainsPoint =
|
||||
geos::algorithm::PointLocation::isInRing(zero, &sequence);
|
||||
}
|
||||
catch (const std::exception&)
|
||||
{
|
||||
logger_->trace("Invalid area sequence");
|
||||
}
|
||||
}
|
||||
|
||||
return areaContainsPoint;
|
||||
}
|
||||
|
||||
units::angle::degrees<double>
|
||||
GetAngle(double lat1, double lon1, double lat2, double lon2)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,5 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
#include <scwx/common/geographic.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <GeographicLib/Geodesic.hpp>
|
||||
#include <units/angle.h>
|
||||
#include <units/length.h>
|
||||
|
|
@ -20,6 +24,18 @@ namespace GeographicLib
|
|||
*/
|
||||
const ::GeographicLib::Geodesic& DefaultGeodesic();
|
||||
|
||||
/**
|
||||
* Determine if an area/ring, oriented in either direction, contains a point. A
|
||||
* point lying on the area boundary is considered to be inside the area.
|
||||
*
|
||||
* @param [in] area A vector of Coordinates representing the area
|
||||
* @param [in] point The point to check against the area
|
||||
*
|
||||
* @return true if point is inside the area
|
||||
*/
|
||||
bool AreaContainsPoint(const std::vector<common::Coordinate>& area,
|
||||
const common::Coordinate& point);
|
||||
|
||||
/**
|
||||
* Get the angle between two points.
|
||||
*
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue