MySQL 9.1.0
Source Code Documentation
functor.h
Go to the documentation of this file.
1#ifndef SQL_GIS_FUNCTOR_H_INCLUDED
2#define SQL_GIS_FUNCTOR_H_INCLUDED
3// Copyright (c) 2017, 2024, Oracle and/or its affiliates.
4//
5// This program is free software; you can redistribute it and/or modify
6// it under the terms of the GNU General Public License, version 2.0,
7// as published by the Free Software Foundation.
8//
9// This program is designed to work with certain software (including
10// but not limited to OpenSSL) that is licensed under separate terms,
11// as designated in a particular file or component or in included license
12// documentation. The authors of MySQL hereby grant you an additional
13// permission to link the program and your derivative works with the
14// separately licensed software that they have either included with
15// the program or referenced in the documentation.
16//
17// This program is distributed in the hope that it will be useful,
18// but WITHOUT ANY WARRANTY; without even the implied warranty of
19// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20// GNU General Public License, version 2.0, for more details.
21//
22// You should have received a copy of the GNU General Public License
23// along with this program; if not, write to the Free Software
24// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
25
26/// @file
27///
28/// This file contains the superclasses for GIS functors.
29///
30/// Each GIS function is split in two: a functor class (for internal use) and a
31/// function (for external use) that uses the functor. The functor provides the
32/// internal interface to GIS functions, and it may throw exceptions. Some
33/// functions may need a combination of different functors to implement the
34/// desired functionality.
35///
36/// The function, not the functor, is the interface to the rest of MySQL.
37///
38/// @see distance_functor.h
39
40#include <assert.h>
41#include <exception> // std::exception
42#include <sstream> // std::stringstream
43#include <string> // std::string
44
45// assert
46#include "sql/gis/geometries.h" // gis::{Geometry{,_type}, Coordinate_system}
47#include "sql/gis/geometries_cs.h" // gis::{Cartesian_*, Geographic_*}
48#include "template_utils.h" // down_cast
49
50namespace gis {
51
52/// Longitude out of range exception
53///
54/// Thrown by GIS functors when longtitude is out of range when reinterpreting
55/// geometry coordinates.
56struct longitude_out_of_range_exception : public std::exception {
57 double value;
58 double range_min;
59 double range_max;
60
62 double range_max)
64};
65
66/// Latitude out of range exception
67///
68/// Thrown by GIS functors when latitude is out of range when reinterpreting
69/// geometry coordinates.
70struct latitude_out_of_range_exception : public std::exception {
71 double value;
72 double range_min;
73 double range_max;
74
76 double range_max)
78};
79
80/// Function/parameter combination not implemented exception.
81///
82/// Geometry is tagged as geographic or Cartesian/projected. In the latter case,
83/// whether it is Cartesian or projected is determined by the accompanying SRS.
84///
85/// To obtain an instance of this exception, use
86/// not_implemented_exception::for_projected if geometry is projected, and
87/// not_implemented_exception::for_non_projected otherwise.
88class not_implemented_exception : public std::exception {
89 public:
91
92 private:
94
95 std::string m_typenames;
96
99 m_typenames = std::string(type_to_name(g.type()));
100 }
101
103 const Geometry &g2) {
104 assert(g1.coordinate_system() == g2.coordinate_system());
106 std::stringstream ss;
107 ss << type_to_name(g1.type()) << ", " << type_to_name(g2.type());
108 m_typenames = ss.str();
109 }
110
111 public:
112 Srs_type srs_type() const { return m_srs_type; }
113 const char *typenames() const { return m_typenames.c_str(); }
114
117 }
118
120 const Geometry &g2) {
122 }
123
125 switch (g.coordinate_system()) {
126 default:
127 assert(false); // C++11 woes. /* purecov: inspected */
132 }
133 }
134
136 const Geometry &g2) {
137 switch (g1.coordinate_system()) {
138 default:
139 assert(false); // C++11 woes. /* purecov: inspected */
144 }
145 }
146};
147
148/// NULL value exception.
149///
150/// Thrown when the functor discovers that the result is NULL. Normally, NULL
151/// returns can be detected before calling the functor, but not always.
152class null_value_exception : public std::exception {};
153
154/// The base class of all functors that takes two geometry arguments.
155///
156/// Subclasses of this functor base class will implement operator() and call
157/// apply() to do type combination dispatching. The actual body of the functor
158/// is in the eval() member function, which must be implemented for each
159/// different parameter type combination.
160///
161/// The functor may throw exceptions.
162///
163/// @tparam T The return type of the functor.
164template <typename T>
165class Functor {
166 public:
167 virtual T operator()(const Geometry *g1, const Geometry *g2) const = 0;
168 virtual ~Functor() = default;
169
170 protected:
171 template <typename F>
172 static inline T apply(F &f, const Geometry *g1, const Geometry *g2) {
173 assert(g1->coordinate_system() == g2->coordinate_system());
174 switch (g1->coordinate_system()) {
176 switch (g1->type()) {
178 switch (g2->type()) {
180 return f.eval(down_cast<const Cartesian_point *>(g1),
181 down_cast<const Cartesian_point *>(g2));
183 return f.eval(down_cast<const Cartesian_point *>(g1),
184 down_cast<const Cartesian_linestring *>(g2));
186 return f.eval(down_cast<const Cartesian_point *>(g1),
187 down_cast<const Cartesian_polygon *>(g2));
189 return f.eval(
190 down_cast<const Cartesian_point *>(g1),
191 down_cast<const Cartesian_geometrycollection *>(g2));
193 return f.eval(down_cast<const Cartesian_point *>(g1),
194 down_cast<const Cartesian_multipoint *>(g2));
196 return f.eval(down_cast<const Cartesian_point *>(g1),
197 down_cast<const Cartesian_multilinestring *>(g2));
199 return f.eval(down_cast<const Cartesian_point *>(g1),
200 down_cast<const Cartesian_multipolygon *>(g2));
201 default:
202 assert(false); /* purecov: inspected */
204 }
206 switch (g2->type()) {
208 return f.eval(down_cast<const Cartesian_linestring *>(g1),
209 down_cast<const Cartesian_point *>(g2));
211 return f.eval(down_cast<const Cartesian_linestring *>(g1),
212 down_cast<const Cartesian_linestring *>(g2));
214 return f.eval(down_cast<const Cartesian_linestring *>(g1),
215 down_cast<const Cartesian_polygon *>(g2));
217 return f.eval(
218 down_cast<const Cartesian_linestring *>(g1),
219 down_cast<const Cartesian_geometrycollection *>(g2));
221 return f.eval(down_cast<const Cartesian_linestring *>(g1),
222 down_cast<const Cartesian_multipoint *>(g2));
224 return f.eval(down_cast<const Cartesian_linestring *>(g1),
225 down_cast<const Cartesian_multilinestring *>(g2));
227 return f.eval(down_cast<const Cartesian_linestring *>(g1),
228 down_cast<const Cartesian_multipolygon *>(g2));
229 default:
230 assert(false); /* purecov: inspected */
232 }
234 switch (g2->type()) {
236 return f.eval(down_cast<const Cartesian_polygon *>(g1),
237 down_cast<const Cartesian_point *>(g2));
239 return f.eval(down_cast<const Cartesian_polygon *>(g1),
240 down_cast<const Cartesian_linestring *>(g2));
242 return f.eval(down_cast<const Cartesian_polygon *>(g1),
243 down_cast<const Cartesian_polygon *>(g2));
245 return f.eval(
246 down_cast<const Cartesian_polygon *>(g1),
247 down_cast<const Cartesian_geometrycollection *>(g2));
249 return f.eval(down_cast<const Cartesian_polygon *>(g1),
250 down_cast<const Cartesian_multipoint *>(g2));
252 return f.eval(down_cast<const Cartesian_polygon *>(g1),
253 down_cast<const Cartesian_multilinestring *>(g2));
255 return f.eval(down_cast<const Cartesian_polygon *>(g1),
256 down_cast<const Cartesian_multipolygon *>(g2));
257 default:
258 assert(false); /* purecov: inspected */
260 }
262 switch (g2->type()) {
264 return f.eval(
265 down_cast<const Cartesian_geometrycollection *>(g1),
266 down_cast<const Cartesian_point *>(g2));
268 return f.eval(
269 down_cast<const Cartesian_geometrycollection *>(g1),
270 down_cast<const Cartesian_linestring *>(g2));
272 return f.eval(
273 down_cast<const Cartesian_geometrycollection *>(g1),
274 down_cast<const Cartesian_polygon *>(g2));
276 return f.eval(
277 down_cast<const Cartesian_geometrycollection *>(g1),
278 down_cast<const Cartesian_geometrycollection *>(g2));
280 return f.eval(
281 down_cast<const Cartesian_geometrycollection *>(g1),
282 down_cast<const Cartesian_multipoint *>(g2));
284 return f.eval(
285 down_cast<const Cartesian_geometrycollection *>(g1),
286 down_cast<const Cartesian_multilinestring *>(g2));
288 return f.eval(
289 down_cast<const Cartesian_geometrycollection *>(g1),
290 down_cast<const Cartesian_multipolygon *>(g2));
291 default:
292 assert(false); /* purecov: inspected */
294 }
296 switch (g2->type()) {
298 return f.eval(down_cast<const Cartesian_multipoint *>(g1),
299 down_cast<const Cartesian_point *>(g2));
301 return f.eval(down_cast<const Cartesian_multipoint *>(g1),
302 down_cast<const Cartesian_linestring *>(g2));
304 return f.eval(down_cast<const Cartesian_multipoint *>(g1),
305 down_cast<const Cartesian_polygon *>(g2));
307 return f.eval(
308 down_cast<const Cartesian_multipoint *>(g1),
309 down_cast<const Cartesian_geometrycollection *>(g2));
311 return f.eval(down_cast<const Cartesian_multipoint *>(g1),
312 down_cast<const Cartesian_multipoint *>(g2));
314 return f.eval(down_cast<const Cartesian_multipoint *>(g1),
315 down_cast<const Cartesian_multilinestring *>(g2));
317 return f.eval(down_cast<const Cartesian_multipoint *>(g1),
318 down_cast<const Cartesian_multipolygon *>(g2));
319 default:
320 assert(false); /* purecov: inspected */
322 }
324 switch (g2->type()) {
326 return f.eval(down_cast<const Cartesian_multilinestring *>(g1),
327 down_cast<const Cartesian_point *>(g2));
329 return f.eval(down_cast<const Cartesian_multilinestring *>(g1),
330 down_cast<const Cartesian_linestring *>(g2));
332 return f.eval(down_cast<const Cartesian_multilinestring *>(g1),
333 down_cast<const Cartesian_polygon *>(g2));
335 return f.eval(
336 down_cast<const Cartesian_multilinestring *>(g1),
337 down_cast<const Cartesian_geometrycollection *>(g2));
339 return f.eval(down_cast<const Cartesian_multilinestring *>(g1),
340 down_cast<const Cartesian_multipoint *>(g2));
342 return f.eval(down_cast<const Cartesian_multilinestring *>(g1),
343 down_cast<const Cartesian_multilinestring *>(g2));
345 return f.eval(down_cast<const Cartesian_multilinestring *>(g1),
346 down_cast<const Cartesian_multipolygon *>(g2));
347 default:
348 assert(false); /* purecov: inspected */
350 }
352 switch (g2->type()) {
354 return f.eval(down_cast<const Cartesian_multipolygon *>(g1),
355 down_cast<const Cartesian_point *>(g2));
357 return f.eval(down_cast<const Cartesian_multipolygon *>(g1),
358 down_cast<const Cartesian_linestring *>(g2));
360 return f.eval(down_cast<const Cartesian_multipolygon *>(g1),
361 down_cast<const Cartesian_polygon *>(g2));
363 return f.eval(
364 down_cast<const Cartesian_multipolygon *>(g1),
365 down_cast<const Cartesian_geometrycollection *>(g2));
367 return f.eval(down_cast<const Cartesian_multipolygon *>(g1),
368 down_cast<const Cartesian_multipoint *>(g2));
370 return f.eval(down_cast<const Cartesian_multipolygon *>(g1),
371 down_cast<const Cartesian_multilinestring *>(g2));
373 return f.eval(down_cast<const Cartesian_multipolygon *>(g1),
374 down_cast<const Cartesian_multipolygon *>(g2));
375 default:
376 assert(false); /* purecov: inspected */
378 }
379 default:
380 assert(false); /* purecov: inspected */
382 } // switch (g1->type())
384 switch (g1->type()) {
386 switch (g2->type()) {
388 return f.eval(down_cast<const Geographic_point *>(g1),
389 down_cast<const Geographic_point *>(g2));
391 return f.eval(down_cast<const Geographic_point *>(g1),
392 down_cast<const Geographic_linestring *>(g2));
394 return f.eval(down_cast<const Geographic_point *>(g1),
395 down_cast<const Geographic_polygon *>(g2));
397 return f.eval(
398 down_cast<const Geographic_point *>(g1),
399 down_cast<const Geographic_geometrycollection *>(g2));
401 return f.eval(down_cast<const Geographic_point *>(g1),
402 down_cast<const Geographic_multipoint *>(g2));
404 return f.eval(
405 down_cast<const Geographic_point *>(g1),
406 down_cast<const Geographic_multilinestring *>(g2));
408 return f.eval(down_cast<const Geographic_point *>(g1),
409 down_cast<const Geographic_multipolygon *>(g2));
410 default:
411 assert(false); /* purecov: inspected */
413 }
415 switch (g2->type()) {
417 return f.eval(down_cast<const Geographic_linestring *>(g1),
418 down_cast<const Geographic_point *>(g2));
420 return f.eval(down_cast<const Geographic_linestring *>(g1),
421 down_cast<const Geographic_linestring *>(g2));
423 return f.eval(down_cast<const Geographic_linestring *>(g1),
424 down_cast<const Geographic_polygon *>(g2));
426 return f.eval(
427 down_cast<const Geographic_linestring *>(g1),
428 down_cast<const Geographic_geometrycollection *>(g2));
430 return f.eval(down_cast<const Geographic_linestring *>(g1),
431 down_cast<const Geographic_multipoint *>(g2));
433 return f.eval(
434 down_cast<const Geographic_linestring *>(g1),
435 down_cast<const Geographic_multilinestring *>(g2));
437 return f.eval(down_cast<const Geographic_linestring *>(g1),
438 down_cast<const Geographic_multipolygon *>(g2));
439 default:
440 assert(false); /* purecov: inspected */
442 }
444 switch (g2->type()) {
446 return f.eval(down_cast<const Geographic_polygon *>(g1),
447 down_cast<const Geographic_point *>(g2));
449 return f.eval(down_cast<const Geographic_polygon *>(g1),
450 down_cast<const Geographic_linestring *>(g2));
452 return f.eval(down_cast<const Geographic_polygon *>(g1),
453 down_cast<const Geographic_polygon *>(g2));
455 return f.eval(
456 down_cast<const Geographic_polygon *>(g1),
457 down_cast<const Geographic_geometrycollection *>(g2));
459 return f.eval(down_cast<const Geographic_polygon *>(g1),
460 down_cast<const Geographic_multipoint *>(g2));
462 return f.eval(
463 down_cast<const Geographic_polygon *>(g1),
464 down_cast<const Geographic_multilinestring *>(g2));
466 return f.eval(down_cast<const Geographic_polygon *>(g1),
467 down_cast<const Geographic_multipolygon *>(g2));
468 default:
469 assert(false); /* purecov: inspected */
471 }
473 switch (g2->type()) {
475 return f.eval(
476 down_cast<const Geographic_geometrycollection *>(g1),
477 down_cast<const Geographic_point *>(g2));
479 return f.eval(
480 down_cast<const Geographic_geometrycollection *>(g1),
481 down_cast<const Geographic_linestring *>(g2));
483 return f.eval(
484 down_cast<const Geographic_geometrycollection *>(g1),
485 down_cast<const Geographic_polygon *>(g2));
487 return f.eval(
488 down_cast<const Geographic_geometrycollection *>(g1),
489 down_cast<const Geographic_geometrycollection *>(g2));
491 return f.eval(
492 down_cast<const Geographic_geometrycollection *>(g1),
493 down_cast<const Geographic_multipoint *>(g2));
495 return f.eval(
496 down_cast<const Geographic_geometrycollection *>(g1),
497 down_cast<const Geographic_multilinestring *>(g2));
499 return f.eval(
500 down_cast<const Geographic_geometrycollection *>(g1),
501 down_cast<const Geographic_multipolygon *>(g2));
502 default:
503 assert(false); /* purecov: inspected */
505 }
507 switch (g2->type()) {
509 return f.eval(down_cast<const Geographic_multipoint *>(g1),
510 down_cast<const Geographic_point *>(g2));
512 return f.eval(down_cast<const Geographic_multipoint *>(g1),
513 down_cast<const Geographic_linestring *>(g2));
515 return f.eval(down_cast<const Geographic_multipoint *>(g1),
516 down_cast<const Geographic_polygon *>(g2));
518 return f.eval(
519 down_cast<const Geographic_multipoint *>(g1),
520 down_cast<const Geographic_geometrycollection *>(g2));
522 return f.eval(down_cast<const Geographic_multipoint *>(g1),
523 down_cast<const Geographic_multipoint *>(g2));
525 return f.eval(
526 down_cast<const Geographic_multipoint *>(g1),
527 down_cast<const Geographic_multilinestring *>(g2));
529 return f.eval(down_cast<const Geographic_multipoint *>(g1),
530 down_cast<const Geographic_multipolygon *>(g2));
531 default:
532 assert(false); /* purecov: inspected */
534 }
536 switch (g2->type()) {
538 return f.eval(down_cast<const Geographic_multilinestring *>(g1),
539 down_cast<const Geographic_point *>(g2));
541 return f.eval(down_cast<const Geographic_multilinestring *>(g1),
542 down_cast<const Geographic_linestring *>(g2));
544 return f.eval(down_cast<const Geographic_multilinestring *>(g1),
545 down_cast<const Geographic_polygon *>(g2));
547 return f.eval(
548 down_cast<const Geographic_multilinestring *>(g1),
549 down_cast<const Geographic_geometrycollection *>(g2));
551 return f.eval(down_cast<const Geographic_multilinestring *>(g1),
552 down_cast<const Geographic_multipoint *>(g2));
554 return f.eval(
555 down_cast<const Geographic_multilinestring *>(g1),
556 down_cast<const Geographic_multilinestring *>(g2));
558 return f.eval(down_cast<const Geographic_multilinestring *>(g1),
559 down_cast<const Geographic_multipolygon *>(g2));
560 default:
561 assert(false); /* purecov: inspected */
563 }
565 switch (g2->type()) {
567 return f.eval(down_cast<const Geographic_multipolygon *>(g1),
568 down_cast<const Geographic_point *>(g2));
570 return f.eval(down_cast<const Geographic_multipolygon *>(g1),
571 down_cast<const Geographic_linestring *>(g2));
573 return f.eval(down_cast<const Geographic_multipolygon *>(g1),
574 down_cast<const Geographic_polygon *>(g2));
576 return f.eval(
577 down_cast<const Geographic_multipolygon *>(g1),
578 down_cast<const Geographic_geometrycollection *>(g2));
580 return f.eval(down_cast<const Geographic_multipolygon *>(g1),
581 down_cast<const Geographic_multipoint *>(g2));
583 return f.eval(
584 down_cast<const Geographic_multipolygon *>(g1),
585 down_cast<const Geographic_multilinestring *>(g2));
587 return f.eval(down_cast<const Geographic_multipolygon *>(g1),
588 down_cast<const Geographic_multipolygon *>(g2));
589 default:
590 assert(false); /* purecov: inspected */
592 }
593 default:
594 assert(false); /* purecov: inspected */
596 } // switch (g1->type())
597 } // switch (g1->coordinate_system())
598
599 assert(false); /* purecov: inspected */
601 }
602};
603
604/// The base class of all functors that take one geometry argument.
605///
606/// Subclasses of this functor base class will implement operator() and call
607/// apply() to do type combination dispatching. The actual body of the functor
608/// is in the eval() member function, which must be implemented for each
609/// different parameter type combination.
610///
611/// The functor may throw exceptions.
612///
613/// @tparam T The return type of the functor.
614template <typename T>
616 public:
617 virtual T operator()(const Geometry &) const = 0;
618 virtual ~Unary_functor() = default;
619
620 protected:
621 template <class F>
622 static inline T apply(F &f, const Geometry &g) {
623 switch (g.coordinate_system()) {
625 switch (g.type()) {
627 return f.eval(down_cast<const Cartesian_point &>(g));
629 return f.eval(down_cast<const Cartesian_linestring &>(g));
631 return f.eval(down_cast<const Cartesian_polygon &>(g));
633 return f.eval(down_cast<const Cartesian_geometrycollection &>(g));
635 return f.eval(down_cast<const Cartesian_multipoint &>(g));
637 return f.eval(down_cast<const Cartesian_multilinestring &>(g));
639 return f.eval(down_cast<const Cartesian_multipolygon &>(g));
640 default:
641 assert(false); /* purecov: inspected */
642 // We don't know here whether the geometry is Cartesan or projected.
643 // Assume Cartesian. This is dead code anyway.
645 }
646 }
648 switch (g.type()) {
650 return f.eval(down_cast<const Geographic_point &>(g));
652 return f.eval(down_cast<const Geographic_linestring &>(g));
654 return f.eval(down_cast<const Geographic_polygon &>(g));
656 return f.eval(down_cast<const Geographic_geometrycollection &>(g));
658 return f.eval(down_cast<const Geographic_multipoint &>(g));
660 return f.eval(down_cast<const Geographic_multilinestring &>(g));
662 return f.eval(down_cast<const Geographic_multipolygon &>(g));
663 default:
664 assert(false); /* purecov: inspected */
665 // We don't know here whether the geometry is Cartesan or projected.
666 // Assume Cartesian. This is dead code anyway.
668 }
669 }
670 }
671 assert(false); /* purecov: inspected */
672 // We don't know here whether the geometry is Cartesan or projected.
673 // Assume Cartesian. This is dead code anyway.
675 }
676};
677
678} // namespace gis
679
680#endif // SQL_GIS_FUNCTOR_H_INCLUDED
The base class of all functors that takes two geometry arguments.
Definition: functor.h:165
virtual T operator()(const Geometry *g1, const Geometry *g2) const =0
virtual ~Functor()=default
static T apply(F &f, const Geometry *g1, const Geometry *g2)
Definition: functor.h:172
Abstract superclass for all geometric objects.
Definition: geometries.h:100
virtual Coordinate_system coordinate_system() const =0
Gets the coordinate system.
virtual Geometry_type type() const =0
Gets the geometry type of the object.
The base class of all functors that take one geometry argument.
Definition: functor.h:615
virtual T operator()(const Geometry &) const =0
virtual ~Unary_functor()=default
static T apply(F &f, const Geometry &g)
Definition: functor.h:622
Function/parameter combination not implemented exception.
Definition: functor.h:88
Srs_type
Definition: functor.h:90
@ kCartesian
Definition: functor.h:90
@ kProjected
Definition: functor.h:90
@ kGeographic
Definition: functor.h:90
const char * typenames() const
Definition: functor.h:113
Srs_type m_srs_type
Definition: functor.h:93
std::string m_typenames
Definition: functor.h:95
static not_implemented_exception for_projected(const Geometry &g1, const Geometry &g2)
Definition: functor.h:119
Srs_type srs_type() const
Definition: functor.h:112
static not_implemented_exception for_non_projected(const Geometry &g)
Definition: functor.h:124
not_implemented_exception(Srs_type srs_type, const Geometry &g1, const Geometry &g2)
Definition: functor.h:102
static not_implemented_exception for_non_projected(const Geometry &g1, const Geometry &g2)
Definition: functor.h:135
static not_implemented_exception for_projected(const Geometry &g)
Definition: functor.h:115
not_implemented_exception(Srs_type srs_type, const Geometry &g)
Definition: functor.h:97
NULL value exception.
Definition: functor.h:152
This file declares the geometry class hierarchy used by the server as the internal representation of ...
This file declares the coordinate system specific subclasses of the geometry class hierarchy.
Definition: area.cc:47
@ kCartesian
A Cartesian plane with the same unit in both directions.
@ kGeographic
An ellipsoidal system with longitude and latitude coordinates, both in the same unit.
const char * type_to_name(Geometry_type type)
Get the type name string corresponding to a geometry type.
Definition: geometries.cc:688
Latitude out of range exception.
Definition: functor.h:70
double range_min
Definition: functor.h:72
double range_max
Definition: functor.h:73
latitude_out_of_range_exception(double value, double range_min, double range_max)
Definition: functor.h:75
double value
Definition: functor.h:71
Longitude out of range exception.
Definition: functor.h:56
longitude_out_of_range_exception(double value, double range_min, double range_max)
Definition: functor.h:61
double value
Definition: functor.h:57
double range_min
Definition: functor.h:58
double range_max
Definition: functor.h:59