GEOS  3.13.0dev
Interpolate.h
1 /**********************************************************************
2  *
3  * GEOS - Geometry Engine Open Source
4  * http://geos.osgeo.org
5  *
6  * Copyright (C) 2016 Vivid Solutions Inc.
7  * Copyright (C) 2023 ISciences LLC
8  *
9  * This is free software; you can redistribute and/or modify it under
10  * the terms of the GNU Lesser General Public Licence as published
11  * by the Free Software Foundation.
12  * See the COPYING file for more information.
13  *
14  **********************************************************************/
15 
16 #pragma once
17 
18 #include <geos/export.h>
19 #include <geos/geom/Coordinate.h>
20 
21 #include <cmath>
22 
23 namespace geos {
24 namespace algorithm {
25 
26 class GEOS_DLL Interpolate {
27 
28 private:
29 
30  template<geom::Ordinate Ord, typename CoordType>
31  static double
32  interpolate(const geom::CoordinateXY& p, const CoordType& p1, const CoordType& p2)
33  {
34  double p1z = p1.template get<Ord>();
35  double p2z = p2.template get<Ord>();
36 
37  if (std::isnan(p1z)) {
38  return p2z; // may be NaN
39  }
40  if (std::isnan(p2z)) {
41  return p1z; // may be NaN
42  }
43  if (p.equals2D(p1)) {
44  return p1z; // not NaN
45  }
46  if (p.equals2D(p2)) {
47  return p2z; // not NaN
48  }
49  double dz = p2z - p1z;
50  if (dz == 0.0) {
51  return p1z;
52  }
53 
54  // interpolate Z from distance of p along p1-p2
55  double dx = (p2.x - p1.x);
56  double dy = (p2.y - p1.y);
57  // seg has non-zero length since p1 < p < p2
58  double seglen = (dx * dx + dy * dy);
59  double xoff = (p.x - p1.x);
60  double yoff = (p.y - p1.y);
61  double plen = (xoff * xoff + yoff * yoff);
62  double frac = std::sqrt(plen / seglen);
63  double zoff = dz * frac;
64  double zInterpolated = p1z + zoff;
65 
66  return zInterpolated;
67  }
68 
69  template<geom::Ordinate Ord, typename C1, typename C2>
70  static double
71  interpolate(const geom::CoordinateXY& p, const C1& p1, const C1& p2, const C2& q1, const C2& q2)
72  {
73  double zp = interpolate<Ord>(p, p1, p2);
74  double zq = interpolate<Ord>(p, q1, q2);
75 
76  if (std::isnan(zp)) {
77  return zq; // may be NaN
78  }
79  if (std::isnan(zq)) {
80  return zp; // may be NaN
81  }
82 
83  return (zp + zq) / 2.0;
84  }
85 
86  template<geom::Ordinate Ord, typename C1, typename C2>
87  static double
88  get(const C1& p, const C2& q)
89  {
90  double a = p.template get<Ord>();
91  double b = q.template get<Ord>();
92  if (std::isnan(a)) {
93  return b;
94  }
95  return a;
96  }
97 
98  template<geom::Ordinate Ord, typename C1, typename C2>
99  static double
100  getOrInterpolate(const C1& p, const C2& p1, const C2& p2)
101  {
102  double z = p.template get<Ord>();
103  if (!std::isnan(z)) return z;
104  return interpolate<Ord>(p, p1, p2);
105  }
106 
107  static double
108  interpolate(const geom::CoordinateXY& p, const geom::CoordinateXY& p1, const geom::CoordinateXY& p2)
109  {
110  (void) p; (void) p1; (void) p2;
111  return DoubleNotANumber;
112  }
113 
114 public:
116  template<typename CoordType>
117  static double
118  zInterpolate(const geom::CoordinateXY& p, const CoordType& p1, const CoordType& p2)
119  {
120  return interpolate<geom::Ordinate::Z>(p, p1, p2);
121  }
122 
124  template<typename C1, typename C2>
125  static double
126  zInterpolate(const geom::CoordinateXY& p, const C1& p1, const C1& p2, const C2& q1, const C2& q2)
127  {
128  return interpolate<geom::Ordinate::Z>(p, p1, p2, q1, q2);
129  }
130 
132  template<typename CoordType>
133  static double
134  mInterpolate(const geom::CoordinateXY& p, const CoordType& p1, const CoordType& p2)
135  {
136  return interpolate<geom::Ordinate::M>(p, p1, p2);
137  }
138 
140  template<typename C1, typename C2>
141  static double
142  mInterpolate(const geom::CoordinateXY& p, const C1& p1, const C1& p2, const C2& q1, const C2& q2)
143  {
144  return interpolate<geom::Ordinate::M>(p, p1, p2, q1, q2);
145  }
146 
148  template<typename C1, typename C2>
149  static double
150  zGet(const C1& p, const C2& q)
151  {
152  return get<geom::Ordinate::Z>(p, q);
153  }
154 
156  template<typename C1, typename C2>
157  static double
158  mGet(const C1& p, const C2& q)
159  {
160  return get<geom::Ordinate::M>(p, q);
161  }
162 
164  template<typename C1, typename C2>
165  static double
166  zGetOrInterpolate(const C1& p, const C2& p1, const C2& p2)
167  {
168  return getOrInterpolate<geom::Ordinate::Z>(p, p1, p2);
169  }
170 
172  template<typename C1, typename C2>
173  static double
174  mGetOrInterpolate(const C1& p, const C2& p1, const C2& p2)
175  {
176  return getOrInterpolate<geom::Ordinate::M>(p, p1, p2);
177  }
178 
179 };
180 
181 }
182 }
Basic namespace for all GEOS functionalities.
Definition: Angle.h:25