GEOS 3.14.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
23namespace geos {
24namespace algorithm {
25
26class GEOS_DLL Interpolate {
27
28private:
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
114public:
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 geos.h:39