16 #include "eckit/container/KDTree.h" 18 #include "atlas/library/config.h" 19 #include "atlas/runtime/Exception.h" 20 #include "atlas/runtime/Log.h" 21 #include "atlas/util/Geometry.h" 22 #include "atlas/util/Object.h" 33 template <
typename PayloadT,
typename Po
intT = Po
int3>
35 #define ENABLE_IF_3D_AND_IS_LONLAT( POINT ) \ 36 typename = typename std::enable_if < PointT::DIMS == 3 && POINT::DIMS == 2 > ::type 42 using Payload = PayloadT;
44 using PayloadList = std::vector<Payload>;
48 using Payload = PayloadT;
52 using Point =
typename KDTreeTraits::Point;
53 using Payload =
typename KDTreeTraits::Payload;
55 template <
typename Node>
56 Value(
const Node& node ) :
Value( node.point(), node.payload(), node.distance() ) {}
58 Value(
const Point& point,
const Payload& payload ) : point_( point ), payload_( payload ) {}
60 Value(
const Point& point,
const Payload& payload,
double distance ) :
61 point_( point ), payload_( payload ), distance_( distance ) {}
63 const Point& point()
const {
return point_; }
64 const Payload& payload()
const {
return payload_; }
65 const double& distance()
const {
return distance_; }
75 using std::vector<Value>::vector;
76 PayloadList payloads()
const {
78 list.reserve( this->size() );
79 for (
auto& item : *
this ) {
80 list.emplace_back( item.payload() );
85 template <
typename NodeList>
88 for (
const auto& item : _list ) {
89 this->emplace_back( item );
93 void print( std::ostream& out )
const {
95 for (
size_t i = 0; i < this->size(); ++i ) {
96 const auto& value = this->at( i );
97 out <<
"{payload:" << value.payload() <<
",distance:" << value.distance() <<
",point:" << value.point()
99 if ( i < this->size() - 1 ) {
105 friend std::ostream& operator<<( std::ostream& out,
ValueList& This ) {
119 const Geometry& geometry()
const {
return geometry_; }
121 bool empty()
const {
return size() == 0; }
123 virtual idx_t size()
const = 0;
125 virtual size_t footprint()
const = 0;
133 template <
typename Po
int>
134 void insert(
const Point& p,
const Payload& payload ) {
135 do_insert( p, payload );
147 virtual void build( std::vector<Value>& values ) = 0;
151 template <
typename Longitudes,
typename Latitudes,
typename Payloads>
152 void build(
const Longitudes& longitudes,
const Latitudes& latitudes,
const Payloads& payloads ) {
153 build( longitudes.begin(), longitudes.end(), latitudes.begin(), latitudes.end(), payloads.begin(),
159 template <
typename LongitudesIterator,
typename LatitudesIterator,
typename PayloadsIterator>
160 void build(
const LongitudesIterator& longitudes_begin,
const LongitudesIterator& longitudes_end,
161 const LatitudesIterator& latitudes_begin,
const LatitudesIterator& latitudes_end,
162 const PayloadsIterator& payloads_begin,
const PayloadsIterator& payloads_end ) {
163 reserve( std::distance( payloads_begin, payloads_end ) );
164 auto lon = longitudes_begin;
165 auto lat = latitudes_begin;
166 auto payload = payloads_begin;
167 for ( ; lon != longitudes_end && lat != latitudes_end && payload != payloads_end; lon++, lat++, payload++ ) {
168 insert( Point2{*lon, *lat}, *payload );
170 ATLAS_ASSERT( lon == longitudes_end );
171 ATLAS_ASSERT( lat == latitudes_end );
172 ATLAS_ASSERT( payload == payloads_end );
178 template <
typename Po
ints,
typename Payloads>
179 void build(
const Points& points,
const Payloads& payloads ) {
180 build( points.begin(), points.end(), payloads.begin(), payloads.end() );
185 template <
typename Po
intIterator,
typename PayloadsIterator>
186 void build(
const PointIterator& points_begin,
const PointIterator& points_end,
187 const PayloadsIterator& payloads_begin,
const PayloadsIterator& payloads_end ) {
188 reserve( std::distance( points_begin, points_end ) );
189 PointIterator point = points_begin;
190 PayloadsIterator payload = payloads_begin;
191 for ( ; point != points_end && payload != payloads_end; ++point, ++payload ) {
192 insert( *point, *payload );
194 ATLAS_ASSERT( point == points_end );
195 ATLAS_ASSERT( payload == payloads_end );
201 template <
typename Po
int>
203 return do_closestPoints( p, k );
207 template <
typename Po
int>
209 return do_closestPoint( p );
213 template <
typename Po
int>
215 return do_closestPointsWithinRadius( p, radius );
221 void do_insert(
const Point& p,
const Payload& payload ) {
insert(
Value{p, payload} ); }
226 template <
typename LonLat, ENABLE_IF_3D_AND_IS_LONLAT( LonLat )>
227 void do_insert(
const LonLat& p,
const Payload& payload ) {
228 do_insert( make_Point( p ), payload );
232 virtual ValueList do_closestPoints(
const Point&,
size_t k )
const = 0;
235 virtual Value do_closestPoint(
const Point& )
const = 0;
238 virtual ValueList do_closestPointsWithinRadius(
const Point&,
double radius )
const = 0;
242 template <
typename LonLat, ENABLE_IF_3D_AND_IS_LONLAT( LonLat )>
243 ValueList do_closestPoints(
const LonLat& p,
size_t k )
const {
244 return do_closestPoints( make_Point( p ), k );
248 template <
typename LonLat, ENABLE_IF_3D_AND_IS_LONLAT( LonLat )>
249 Value do_closestPoint(
const LonLat& p )
const {
250 return do_closestPoint( make_Point( p ) );
254 template <
typename LonLat, ENABLE_IF_3D_AND_IS_LONLAT( LonLat )>
255 ValueList do_closestPointsWithinRadius(
const LonLat& p,
double radius )
const {
256 return do_closestPointsWithinRadius( make_Point( p ), radius );
259 template <
typename LonLat, ENABLE_IF_3D_AND_IS_LONLAT( LonLat )>
260 Point make_Point(
const LonLat& lonlat )
const {
261 static_assert( std::is_base_of<Point2, LonLat>::value,
"LonLat must be derived from Point2" );
262 static_assert( std::is_base_of<Point3, Point>::value,
"Point must be derived from Point3" );
264 geometry().lonlat2xyz( lonlat, xyz );
267 #undef ENABLE_IF_3D_AND_IS_LONLAT 273 template <
typename TreeT,
typename PayloadT =
typename TreeT::Payload,
typename Po
intT =
typename TreeT::Po
int>
279 using Point =
typename Base::Point;
280 using Payload =
typename Base::Payload;
281 using PayloadList =
typename Base::PayloadList;
286 using Base::closestPoint;
287 using Base::closestPoints;
288 using Base::closestPointsWithinRadius;
293 template <
typename... Args>
300 template <
typename... Args>
301 KDTree_eckit( Args... args ) : tree_(
new Tree( args... ) ) {
305 KDTree_eckit(
const std::shared_ptr<Tree>& tree ) : tree_( tree ) { static_asserts(); }
307 KDTree_eckit(
const std::shared_ptr<Tree>& tree,
const Geometry& geometry ) :
312 idx_t size()
const override {
313 #if ATLAS_ECKIT_VERSION_INT >= 11302 // v1.13.2 314 return static_cast<idx_t>( tree_->size() );
320 for (
const auto& item : *tree_ ) {
324 catch (
const eckit::AssertionFailed& ) {
330 size_t footprint()
const override {
return size() *
sizeof(
typename Tree::Node ); }
334 void build()
override;
336 void build( std::vector<Value>& )
override;
340 void insert(
const Value& value )
override;
343 ValueList do_closestPoints(
const Point&,
size_t k )
const override;
346 Value do_closestPoint(
const Point& )
const override;
349 ValueList do_closestPointsWithinRadius(
const Point&,
double radius )
const override;
351 const Tree& tree()
const {
return *tree_; }
354 void assert_built()
const;
356 static void static_asserts() {
357 static_assert( std::is_convertible<typename Tree::Payload, Payload>::value,
358 "Tree::Payload must be convertible this Payload type" );
359 static_assert( std::is_convertible<typename Tree::Point, Point>::value,
360 "Tree::Point must be convertible to this Point type" );
364 std::vector<Value> tmp_;
365 mutable std::shared_ptr<Tree> tree_;
370 template <
typename Payload,
typename Po
int>
375 template <
typename TreeT,
typename PayloadT,
typename Po
intT>
377 tmp_.reserve( size );
381 template <
typename TreeT,
typename PayloadT,
typename Po
intT>
383 if ( tmp_.capacity() ) {
384 tmp_.emplace_back( value );
387 tree_->insert( value );
391 template <
typename TreeT,
typename PayloadT,
typename Po
intT>
396 tmp_.shrink_to_fit();
400 template <
typename TreeT,
typename PayloadT,
typename Po
intT>
402 tree_->build( values );
406 template <
typename TreeT,
typename PayloadT,
typename Po
intT>
408 const Point& p,
size_t k )
const {
410 return tree_->kNearestNeighbours( p, k );
413 template <
typename TreeT,
typename PayloadT,
typename Po
intT>
415 const Point& p )
const {
417 return tree_->nearestNeighbour( p );
420 template <
typename TreeT,
typename PayloadT,
typename Po
intT>
421 typename KDTree_eckit<TreeT, PayloadT, PointT>::ValueList
424 return tree_->findInSphere( p, radius );
427 template <
typename TreeT,
typename PayloadT,
typename Po
intT>
429 if ( tmp_.capacity() ) {
430 throw_AssertionFailed(
"KDTree was used before calling build()" );
void build(const Longitudes &longitudes, const Latitudes &latitudes, const Payloads &payloads)
Build with spherical points (lon,lat) where longitudes, latitudes, and payloads are separate containe...
Definition: KDTree.h:152
void insert(const Value &value) override
Insert 3D cartesian point (x,y,z) If memory has been reserved with reserve(), insertion will be delay...
Definition: KDTree.h:382
void build() override
Build the kd-tree in one shot, if memory has been reserved, depending on derived class implementation...
Definition: KDTree.h:392
Definition: atlas-benchmark-sorting.cc:55
Value do_closestPoint(const Point &) const override
Find nearest neighbour given a 3D cartesian point (x,y,z)
Definition: KDTree.h:414
Definition: Geometry.h:94
This file contains classes and functions working on points.
void build(const LongitudesIterator &longitudes_begin, const LongitudesIterator &longitudes_end, const LatitudesIterator &latitudes_begin, const LatitudesIterator &latitudes_end, const PayloadsIterator &payloads_begin, const PayloadsIterator &payloads_end)
Build with spherical points (lon,lat) given separate iterator ranges for longitudes, latitudes, and payloads.
Definition: KDTree.h:160
ValueList do_closestPoints(const Point &, size_t k) const override
Find k nearest neighbours given a 3D cartesian point (x,y,z)
Definition: KDTree.h:407
ValueList closestPoints(const Point &p, size_t k) const
Find k nearest neighbours given a 3D cartesian point (x,y,z) or 2D lonlat point(lon,lat)
Definition: KDTree.h:202
void build(const Points &points, const Payloads &payloads)
Build with spherical points (lon,lat) where longitudes, latitudes, and payloads are separate containe...
Definition: KDTree.h:179
void build(const PointIterator &points_begin, const PointIterator &points_end, const PayloadsIterator &payloads_begin, const PayloadsIterator &payloads_end)
Build with spherical points (lon,lat) given separate iterator ranges for longitudes, latitudes, and payloads.
Definition: KDTree.h:186
virtual void reserve(idx_t)
Reserve memory for building the kdtree in one shot (optional, at cost of extra memory) Implementation...
Definition: KDTree.h:129
void reserve(idx_t size) override
Reserve memory for building the kdtree in one shot (optional, at cost of extra memory) Implementation...
Definition: KDTree.h:376
void insert(const Point &p, const Payload &payload)
Insert spherical point (lon,lat) or 3D cartesian point (x,y,z) If memory has been reserved with reser...
Definition: KDTree.h:134
Value closestPoint(const Point &p) const
Find nearest neighbour given a 3D cartesian point (x,y,z)
Definition: KDTree.h:208
virtual void build()
Build the kd-tree in one shot, if memory has been reserved, depending on derived class implementation...
Definition: KDTree.h:144
Contains all atlas classes and methods.
Definition: atlas-grids.cc:33
long idx_t
Integer type for indices in connectivity tables.
Definition: config.h:42
ValueList do_closestPointsWithinRadius(const Point &, double radius) const override
Find all points within a distance of given radius from a given point (x,y,z)
Definition: KDTree.h:422
ValueList closestPointsWithinRadius(const Point &p, double radius) const
Find all points within a distance of given radius from a given point (x,y,z)
Definition: KDTree.h:214