1515#include < optional>
1616#include < queue>
1717
18- #include " cheap_ruler.hpp"
1918#include " crs_transform.hpp"
2019#include " eigen_helpers.hpp"
2120
@@ -224,7 +223,7 @@ struct PolylineRuler
224223 : polyline_(polyline), //
225224 N_ (polyline.rows()), //
226225 is_wgs84_(is_wgs84), //
227- k_(is_wgs84 ? CheapRuler::k (polyline(0 , 1 )) //
226+ k_(is_wgs84 ? cheap_ruler_k (polyline(0 , 1 )) //
228227 : Eigen::Vector3d::Ones())
229228 {
230229 }
@@ -244,6 +243,7 @@ struct PolylineRuler
244243 // cache
245244 mutable std::optional<Eigen::VectorXd> ranges_;
246245 mutable std::optional<RowVectors> dirs_;
246+ mutable std::optional<RowVectors> enus_; // only when is_wgs84==true
247247
248248 public:
249249 const RowVectors &polyline () const { return polyline_; }
@@ -370,6 +370,49 @@ struct PolylineRuler
370370 return *dirs_;
371371 }
372372
373+ private:
374+ const RowVectors &enus () const
375+ {
376+ assert (is_wgs84_);
377+ if (!enus_) {
378+ enus_ = __lla2enu (polyline_);
379+ }
380+ return *enus_;
381+ }
382+ Eigen::Vector3d __enu2lla (const Eigen::Vector3d &enu) const
383+ {
384+ return (enu.array () / k_.array ()) + Eigen::Array3d (polyline_ (0 , 0 ),
385+ polyline_ (0 , 1 ),
386+ polyline_ (0 , 2 ));
387+ }
388+ Eigen::Vector3d __lla2enu (const Eigen::Vector3d &lla) const
389+ {
390+ return k_.array () * (lla - Eigen::Vector3d (polyline_ (0 , 0 ), //
391+ polyline_ (0 , 1 ), //
392+ polyline_ (0 , 2 )))
393+ .array ();
394+ }
395+
396+ RowVectors __enu2lla (const RowVectors &enus) const
397+ {
398+ RowVectors llas = enus;
399+ for (int i = 0 ; i < 3 ; ++i) {
400+ llas.col (i).array () /= k_[i];
401+ llas.col (i).array () += polyline_ (0 , i);
402+ }
403+ return llas;
404+ }
405+ RowVectors __lla2enu (const RowVectors &llas) const
406+ {
407+ RowVectors enus = llas;
408+ for (int i = 0 ; i < 3 ; ++i) {
409+ enus.col (i).array () -= polyline_ (0 , i);
410+ enus.col (i).array () *= k_[i];
411+ }
412+ return enus;
413+ }
414+
415+ public:
373416 Eigen::Vector3d dir (int pt_index) const
374417 {
375418 return dirs ().row (std::min (pt_index, N_ - 2 ));
@@ -395,8 +438,7 @@ struct PolylineRuler
395438 Eigen::Vector3d extended_along (double range) const
396439 {
397440 auto [i, t] = segment_index_t (range);
398- return interpolate (polyline_.row (i), polyline_.row (i + 1 ), t,
399- is_wgs84_);
441+ return interpolate (polyline_.row (i), polyline_.row (i + 1 ), t);
400442 }
401443
402444 Eigen::Vector3d at (double range) const { return extended_along (range); }
@@ -405,7 +447,7 @@ struct PolylineRuler
405447 {
406448 return interpolate (polyline_.row (seg_idx), //
407449 polyline_.row (seg_idx + 1 ), //
408- t, is_wgs84_ );
450+ t);
409451 }
410452
411453 std::pair<Eigen::Vector3d, Eigen::Vector3d> arrow (int seg_idx,
@@ -432,7 +474,8 @@ struct PolylineRuler
432474 xyzs.row (i) = arrow.first ;
433475 dirs.row (i) = arrow.second ;
434476 }
435- return std::make_tuple (std::move (ranges), std::move (xyzs),
477+ return std::make_tuple (std::move (ranges), //
478+ std::move (xyzs), //
436479 std::move (dirs));
437480 }
438481
@@ -536,7 +579,8 @@ struct PolylineRuler
536579 }
537580 Eigen::Vector3d along (double dist) const
538581 {
539- return along (polyline_, dist, is_wgs84_);
582+ return is_wgs84_ ? __enu2lla (along (enus (), dist))
583+ : along (polyline_, dist);
540584 }
541585
542586 static double pointToSegmentDistance (const Eigen::Vector3d &p,
@@ -609,7 +653,11 @@ struct PolylineRuler
609653 std::tuple<Eigen::Vector3d, int , double >
610654 pointOnLine (const Eigen::Vector3d &p) const
611655 {
612- return pointOnLine (polyline_, p, is_wgs84_);
656+ if (!is_wgs84_) {
657+ return pointOnLine (polyline_, p);
658+ }
659+ auto [enu, i, t] = pointOnLine (enus (), __lla2enu (p));
660+ return std::make_tuple (__enu2lla (enu), i, t);
613661 }
614662
615663 static RowVectors lineSlice (const Eigen::Vector3d &start,
@@ -668,7 +716,10 @@ struct PolylineRuler
668716 RowVectors lineSlice (const Eigen::Vector3d &start,
669717 const Eigen::Vector3d &stop) const
670718 {
671- return lineSlice (start, stop, polyline_, is_wgs84_);
719+ if (!is_wgs84_) {
720+ return lineSlice (start, stop, polyline_);
721+ }
722+ return __enu2lla (lineSlice (__lla2enu (start), __lla2enu (stop), enus ()));
672723 }
673724
674725 static RowVectors lineSliceAlong (double start, double stop,
@@ -709,23 +760,15 @@ struct PolylineRuler
709760 }
710761 RowVectors lineSliceAlong (double start, double stop) const
711762 {
712- return lineSliceAlong (start, stop, polyline_, is_wgs84_);
763+ if (!is_wgs84_) {
764+ return lineSliceAlong (start, stop, polyline_);
765+ }
766+ return __enu2lla (lineSliceAlong (start, stop, enus ()));
713767 }
714768
715769 static Eigen::Vector3d interpolate (const Eigen::Vector3d &a,
716- const Eigen::Vector3d &b, double t,
717- bool is_wgs84 = false )
770+ const Eigen::Vector3d &b, double t)
718771 {
719- if (is_wgs84) {
720- RowVectors llas (2 , 3 );
721- llas.row (0 ) = a;
722- llas.row (1 ) = b;
723- auto enus = lla2enu (llas);
724- return enu2lla (interpolate (enus.row (0 ), enus.row (1 ), t, !is_wgs84)
725- .transpose (),
726- llas.row (0 ))
727- .row (0 );
728- }
729772 return a + (b - a) * t;
730773 }
731774};
@@ -755,8 +798,9 @@ inline void douglas_simplify(const Eigen::Ref<const RowVectors> &coords,
755798 douglas_simplify (coords, to_keep, max_index, j, epsilon);
756799}
757800
758- void douglas_simplify_iter (const Eigen::Ref<const RowVectors> &coords,
759- Eigen::VectorXi &to_keep, const double epsilon)
801+ inline void douglas_simplify_iter (const Eigen::Ref<const RowVectors> &coords,
802+ Eigen::VectorXi &to_keep,
803+ const double epsilon)
760804{
761805 std::queue<std::pair<int , int >> q;
762806 q.push ({0 , to_keep.size () - 1 });
0 commit comments