MySQL 8.0.30
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, 2022, 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 also distributed 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 included with MySQL.
15//
16// This program is distributed in the hope that it will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19// GNU General Public License, version 2.0, for more details.
20//
21// You should have received a copy of the GNU General Public License
22// along with this program; if not, write to the Free Software
23// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24
25/// @file
26///
27/// This file contains the superclasses for GIS functors.
28///
29/// Each GIS function is split in two: a functor class (for internal use) and a
30/// function (for external use) that uses the functor. The functor provides the
31/// internal interface to GIS functions, and it may throw exceptions. Some
32/// functions may need a combination of different functors to implement the
33/// desired functionality.
34///
35/// The function, not the functor, is the interface to the rest of MySQL.
36///
37/// @see distance_functor.h
38
39#include <assert.h>
40#include <exception> // std::exception
41#include <sstream> // std::stringstream
42#include <string> // std::string
43
44// assert
45#include "sql/gis/geometries.h" // gis::{Geometry{,_type}, Coordinate_system}
46#include "sql/gis/geometries_cs.h" // gis::{Cartesian_*, Geographic_*}
47#include "template_utils.h" // down_cast
48
49namespace gis {
50
51/// Longitude out of range exception
52///
53/// Thrown by GIS functors when longtitude is out of range when reinterpreting
54/// geometry coordinates.
55struct longitude_out_of_range_exception : public std::exception {
56 double value;
57 double range_min;
58 double range_max;
59
61 double range_max)
63};
64
65/// Latitude out of range exception
66///
67/// Thrown by GIS functors when latitude is out of range when reinterpreting
68/// geometry coordinates.
69struct latitude_out_of_range_exception : public std::exception {
70 double value;
71 double range_min;
72 double range_max;
73
75 double range_max)
77};
78
79/// Function/parameter combination not implemented exception.
80///
81/// Geometry is tagged as geographic or Cartesian/projected. In the latter case,
82/// whether it is Cartesian or projected is determined by the accompanying SRS.
83///
84/// To obtain an instance of this exception, use
85/// not_implemented_exception::for_projected if geometry is projected, and
86/// not_implemented_exception::for_non_projected otherwise.
87class not_implemented_exception : public std::exception {
88 public:
90
91 private:
93
94 std::string m_typenames;
95
98 m_typenames = std::string(type_to_name(g.type()));
99 }
100
102 const Geometry &g2) {
103 assert(g1.coordinate_system() == g2.coordinate_system());
105 std::stringstream ss;
106 ss << type_to_name(g1.type()) << ", " << type_to_name(g2.type());
107 m_typenames = ss.str();
108 }
109
110 public:
111 Srs_type srs_type() const { return m_srs_type; }
112 const char *typenames() const { return m_typenames.c_str(); }
113
116 }
117
119 const Geometry &g2) {
121 }
122
124 switch (g.coordinate_system()) {
125 default:
126 assert(false); // C++11 woes. /* purecov: inspected */
131 }
132 }
133
135 const Geometry &g2) {
136 switch (g1.coordinate_system()) {
137 default:
138 assert(false); // C++11 woes. /* purecov: inspected */
143 }
144 }
145};
146
147/// NULL value exception.
148///
149/// Thrown when the functor discovers that the result is NULL. Normally, NULL
150/// returns can be detected before calling the functor, but not always.
151class null_value_exception : public std::exception {};
152
153/// The base class of all functors that takes two geometry arguments.
154///
155/// Subclasses of this functor base class will implement operator() and call
156/// apply() to do type combination dispatching. The actual body of the functor
157/// is in the eval() member function, which must be implemented for each
158/// different parameter type combination.
159///
160/// The functor may throw exceptions.
161///
162/// @tparam T The return type of the functor.
163template <typename T>
164class Functor {
165 public:
166 virtual T operator()(const Geometry *g1, const Geometry *g2) const = 0;
167 virtual ~Functor() = default;
168
169 protected:
170 template <typename F>
171 static inline T apply(F &f, const Geometry *g1, const Geometry *g2) {
172 assert(g1->coordinate_system() == g2->coordinate_system());
173 switch (g1->coordinate_system()) {
175 switch (g1->type()) {
177 switch (g2->type()) {
179 return f.eval(down_cast<const Cartesian_point *>(g1),
180 down_cast<const Cartesian_point *>(g2));
182 return f.eval(down_cast<const Cartesian_point *>(g1),
183 down_cast<const Cartesian_linestring *>(g2));
185 return f.eval(down_cast<const Cartesian_point *>(g1),
186 down_cast<const Cartesian_polygon *>(g2));
188 return f.eval(
189 down_cast<const Cartesian_point *>(g1),
190 down_cast<const Cartesian_geometrycollection *>(g2));
192 return f.eval(down_cast<const Cartesian_point *>(g1),
193 down_cast<const Cartesian_multipoint *>(g2));
195 return f.eval(down_cast<const Cartesian_point *>(g1),
196 down_cast<const Cartesian_multilinestring *>(g2));
198 return f.eval(down_cast<const Cartesian_point *>(g1),
199 down_cast<const Cartesian_multipolygon *>(g2));
200 default:
201 assert(false); /* purecov: inspected */
203 }
205 switch (g2->type()) {
207 return f.eval(down_cast<const Cartesian_linestring *>(g1),
208 down_cast<const Cartesian_point *>(g2));
210 return f.eval(down_cast<const Cartesian_linestring *>(g1),
211 down_cast<const Cartesian_linestring *>(g2));
213 return f.eval(down_cast<const Cartesian_linestring *>(g1),
214 down_cast<const Cartesian_polygon *>(g2));
216 return f.eval(
217 down_cast<const Cartesian_linestring *>(g1),
218 down_cast<const Cartesian_geometrycollection *>(g2));
220 return f.eval(down_cast<const Cartesian_linestring *>(g1),
221 down_cast<const Cartesian_multipoint *>(g2));
223 return f.eval(down_cast<const Cartesian_linestring *>(g1),
224 down_cast<const Cartesian_multilinestring *>(g2));
226 return f.eval(down_cast<const Cartesian_linestring *>(g1),
227 down_cast<const Cartesian_multipolygon *>(g2));
228 default:
229 assert(false); /* purecov: inspected */
231 }
233 switch (g2->type()) {
235 return f.eval(down_cast<const Cartesian_polygon *>(g1),
236 down_cast<const Cartesian_point *>(g2));
238 return f.eval(down_cast<const Cartesian_polygon *>(g1),
239 down_cast<const Cartesian_linestring *>(g2));
241 return f.eval(down_cast<const Cartesian_polygon *>(g1),
242 down_cast<const Cartesian_polygon *>(g2));
244 return f.eval(
245 down_cast<const Cartesian_polygon *>(g1),
246 down_cast<const Cartesian_geometrycollection *>(g2));
248 return f.eval(down_cast<const Cartesian_polygon *>(g1),
249 down_cast<const Cartesian_multipoint *>(g2));
251 return f.eval(down_cast<const Cartesian_polygon *>(g1),
252 down_cast<const Cartesian_multilinestring *>(g2));
254 return f.eval(down_cast<const Cartesian_polygon *>(g1),
255 down_cast<const Cartesian_multipolygon *>(g2));
256 default:
257 assert(false); /* purecov: inspected */
259 }
261 switch (g2->type()) {
263 return f.eval(
264 down_cast<const Cartesian_geometrycollection *>(g1),
265 down_cast<const Cartesian_point *>(g2));
267 return f.eval(
268 down_cast<const Cartesian_geometrycollection *>(g1),
269 down_cast<const Cartesian_linestring *>(g2));
271 return f.eval(
272 down_cast<const Cartesian_geometrycollection *>(g1),
273 down_cast<const Cartesian_polygon *>(g2));
275 return f.eval(
276 down_cast<const Cartesian_geometrycollection *>(g1),
277 down_cast<const Cartesian_geometrycollection *>(g2));
279 return f.eval(
280 down_cast<const Cartesian_geometrycollection *>(g1),
281 down_cast<const Cartesian_multipoint *>(g2));
283 return f.eval(
284 down_cast<const Cartesian_geometrycollection *>(g1),
285 down_cast<const Cartesian_multilinestring *>(g2));
287 return f.eval(
288 down_cast<const Cartesian_geometrycollection *>(g1),
289 down_cast<const Cartesian_multipolygon *>(g2));
290 default:
291 assert(false); /* purecov: inspected */
293 }
295 switch (g2->type()) {
297 return f.eval(down_cast<const Cartesian_multipoint *>(g1),
298 down_cast<const Cartesian_point *>(g2));
300 return f.eval(down_cast<const Cartesian_multipoint *>(g1),
301 down_cast<const Cartesian_linestring *>(g2));
303 return f.eval(down_cast<const Cartesian_multipoint *>(g1),
304 down_cast<const Cartesian_polygon *>(g2));
306 return f.eval(
307 down_cast<const Cartesian_multipoint *>(g1),
308 down_cast<const Cartesian_geometrycollection *>(g2));
310 return f.eval(down_cast<const Cartesian_multipoint *>(g1),
311 down_cast<const Cartesian_multipoint *>(g2));
313 return f.eval(down_cast<const Cartesian_multipoint *>(g1),
314 down_cast<const Cartesian_multilinestring *>(g2));
316 return f.eval(down_cast<const Cartesian_multipoint *>(g1),
317 down_cast<const Cartesian_multipolygon *>(g2));
318 default:
319 assert(false); /* purecov: inspected */
321 }
323 switch (g2->type()) {
325 return f.eval(down_cast<const Cartesian_multilinestring *>(g1),
326 down_cast<const Cartesian_point *>(g2));
328 return f.eval(down_cast<const Cartesian_multilinestring *>(g1),
329 down_cast<const Cartesian_linestring *>(g2));
331 return f.eval(down_cast<const Cartesian_multilinestring *>(g1),
332 down_cast<const Cartesian_polygon *>(g2));
334 return f.eval(
335 down_cast<const Cartesian_multilinestring *>(g1),
336 down_cast<const Cartesian_geometrycollection *>(g2));
338 return f.eval(down_cast<const Cartesian_multilinestring *>(g1),
339 down_cast<const Cartesian_multipoint *>(g2));
341 return f.eval(down_cast<const Cartesian_multilinestring *>(g1),
342 down_cast<const Cartesian_multilinestring *>(g2));
344 return f.eval(down_cast<const Cartesian_multilinestring *>(g1),
345 down_cast<const Cartesian_multipolygon *>(g2));
346 default:
347 assert(false); /* purecov: inspected */
349 }
351 switch (g2->type()) {
353 return f.eval(down_cast<const Cartesian_multipolygon *>(g1),
354 down_cast<const Cartesian_point *>(g2));
356 return f.eval(down_cast<const Cartesian_multipolygon *>(g1),
357 down_cast<const Cartesian_linestring *>(g2));
359 return f.eval(down_cast<const Cartesian_multipolygon *>(g1),
360 down_cast<const Cartesian_polygon *>(g2));
362 return f.eval(
363 down_cast<const Cartesian_multipolygon *>(g1),
364 down_cast<const Cartesian_geometrycollection *>(g2));
366 return f.eval(down_cast<const Cartesian_multipolygon *>(g1),
367 down_cast<const Cartesian_multipoint *>(g2));
369 return f.eval(down_cast<const Cartesian_multipolygon *>(g1),
370 down_cast<const Cartesian_multilinestring *>(g2));
372 return f.eval(down_cast<const Cartesian_multipolygon *>(g1),
373 down_cast<const Cartesian_multipolygon *>(g2));
374 default:
375 assert(false); /* purecov: inspected */
377 }
378 default:
379 assert(false); /* purecov: inspected */
381 } // switch (g1->type())
383 switch (g1->type()) {
385 switch (g2->type()) {
387 return f.eval(down_cast<const Geographic_point *>(g1),
388 down_cast<const Geographic_point *>(g2));
390 return f.eval(down_cast<const Geographic_point *>(g1),
391 down_cast<const Geographic_linestring *>(g2));
393 return f.eval(down_cast<const Geographic_point *>(g1),
394 down_cast<const Geographic_polygon *>(g2));
396 return f.eval(
397 down_cast<const Geographic_point *>(g1),
398 down_cast<const Geographic_geometrycollection *>(g2));
400 return f.eval(down_cast<const Geographic_point *>(g1),
401 down_cast<const Geographic_multipoint *>(g2));
403 return f.eval(
404 down_cast<const Geographic_point *>(g1),
405 down_cast<const Geographic_multilinestring *>(g2));
407 return f.eval(down_cast<const Geographic_point *>(g1),
408 down_cast<const Geographic_multipolygon *>(g2));
409 default:
410 assert(false); /* purecov: inspected */
412 }
414 switch (g2->type()) {
416 return f.eval(down_cast<const Geographic_linestring *>(g1),
417 down_cast<const Geographic_point *>(g2));
419 return f.eval(down_cast<const Geographic_linestring *>(g1),
420 down_cast<const Geographic_linestring *>(g2));
422 return f.eval(down_cast<const Geographic_linestring *>(g1),
423 down_cast<const Geographic_polygon *>(g2));
425 return f.eval(
426 down_cast<const Geographic_linestring *>(g1),
427 down_cast<const Geographic_geometrycollection *>(g2));
429 return f.eval(down_cast<const Geographic_linestring *>(g1),
430 down_cast<const Geographic_multipoint *>(g2));
432 return f.eval(
433 down_cast<const Geographic_linestring *>(g1),
434 down_cast<const Geographic_multilinestring *>(g2));
436 return f.eval(down_cast<const Geographic_linestring *>(g1),
437 down_cast<const Geographic_multipolygon *>(g2));
438 default:
439 assert(false); /* purecov: inspected */
441 }
443 switch (g2->type()) {
445 return f.eval(down_cast<const Geographic_polygon *>(g1),
446 down_cast<const Geographic_point *>(g2));
448 return f.eval(down_cast<const Geographic_polygon *>(g1),
449 down_cast<const Geographic_linestring *>(g2));
451 return f.eval(down_cast<const Geographic_polygon *>(g1),
452 down_cast<const Geographic_polygon *>(g2));
454 return f.eval(
455 down_cast<const Geographic_polygon *>(g1),
456 down_cast<const Geographic_geometrycollection *>(g2));
458 return f.eval(down_cast<const Geographic_polygon *>(g1),
459 down_cast<const Geographic_multipoint *>(g2));
461 return f.eval(
462 down_cast<const Geographic_polygon *>(g1),
463 down_cast<const Geographic_multilinestring *>(g2));
465 return f.eval(down_cast<const Geographic_polygon *>(g1),
466 down_cast<const Geographic_multipolygon *>(g2));
467 default:
468 assert(false); /* purecov: inspected */
470 }
472 switch (g2->type()) {
474 return f.eval(
475 down_cast<const Geographic_geometrycollection *>(g1),
476 down_cast<const Geographic_point *>(g2));
478 return f.eval(
479 down_cast<const Geographic_geometrycollection *>(g1),
480 down_cast<const Geographic_linestring *>(g2));
482 return f.eval(
483 down_cast<const Geographic_geometrycollection *>(g1),
484 down_cast<const Geographic_polygon *>(g2));
486 return f.eval(
487 down_cast<const Geographic_geometrycollection *>(g1),
488 down_cast<const Geographic_geometrycollection *>(g2));
490 return f.eval(
491 down_cast<const Geographic_geometrycollection *>(g1),
492 down_cast<const Geographic_multipoint *>(g2));
494 return f.eval(
495 down_cast<const Geographic_geometrycollection *>(g1),
496 down_cast<const Geographic_multilinestring *>(g2));
498 return f.eval(
499 down_cast<const Geographic_geometrycollection *>(g1),
500 down_cast<const Geographic_multipolygon *>(g2));
501 default:
502 assert(false); /* purecov: inspected */
504 }
506 switch (g2->type()) {
508 return f.eval(down_cast<const Geographic_multipoint *>(g1),
509 down_cast<const Geographic_point *>(g2));
511 return f.eval(down_cast<const Geographic_multipoint *>(g1),
512 down_cast<const Geographic_linestring *>(g2));
514 return f.eval(down_cast<const Geographic_multipoint *>(g1),
515 down_cast<const Geographic_polygon *>(g2));
517 return f.eval(
518 down_cast<const Geographic_multipoint *>(g1),
519 down_cast<const Geographic_geometrycollection *>(g2));
521 return f.eval(down_cast<const Geographic_multipoint *>(g1),
522 down_cast<const Geographic_multipoint *>(g2));
524 return f.eval(
525 down_cast<const Geographic_multipoint *>(g1),
526 down_cast<const Geographic_multilinestring *>(g2));
528 return f.eval(down_cast<const Geographic_multipoint *>(g1),
529 down_cast<const Geographic_multipolygon *>(g2));
530 default:
531 assert(false); /* purecov: inspected */
533 }
535 switch (g2->type()) {
537 return f.eval(down_cast<const Geographic_multilinestring *>(g1),
538 down_cast<const Geographic_point *>(g2));
540 return f.eval(down_cast<const Geographic_multilinestring *>(g1),
541 down_cast<const Geographic_linestring *>(g2));
543 return f.eval(down_cast<const Geographic_multilinestring *>(g1),
544 down_cast<const Geographic_polygon *>(g2));
546 return f.eval(
547 down_cast<const Geographic_multilinestring *>(g1),
548 down_cast<const Geographic_geometrycollection *>(g2));
550 return f.eval(down_cast<const Geographic_multilinestring *>(g1),
551 down_cast<const Geographic_multipoint *>(g2));
553 return f.eval(
554 down_cast<const Geographic_multilinestring *>(g1),
555 down_cast<const Geographic_multilinestring *>(g2));
557 return f.eval(down_cast<const Geographic_multilinestring *>(g1),
558 down_cast<const Geographic_multipolygon *>(g2));
559 default:
560 assert(false); /* purecov: inspected */
562 }
564 switch (g2->type()) {
566 return f.eval(down_cast<const Geographic_multipolygon *>(g1),
567 down_cast<const Geographic_point *>(g2));
569 return f.eval(down_cast<const Geographic_multipolygon *>(g1),
570 down_cast<const Geographic_linestring *>(g2));
572 return f.eval(down_cast<const Geographic_multipolygon *>(g1),
573 down_cast<const Geographic_polygon *>(g2));
575 return f.eval(
576 down_cast<const Geographic_multipolygon *>(g1),
577 down_cast<const Geographic_geometrycollection *>(g2));
579 return f.eval(down_cast<const Geographic_multipolygon *>(g1),
580 down_cast<const Geographic_multipoint *>(g2));
582 return f.eval(
583 down_cast<const Geographic_multipolygon *>(g1),
584 down_cast<const Geographic_multilinestring *>(g2));
586 return f.eval(down_cast<const Geographic_multipolygon *>(g1),
587 down_cast<const Geographic_multipolygon *>(g2));
588 default:
589 assert(false); /* purecov: inspected */
591 }
592 default:
593 assert(false); /* purecov: inspected */
595 } // switch (g1->type())
596 } // switch (g1->coordinate_system())
597
598 assert(false); /* purecov: inspected */
600 }
601};
602
603/// The base class of all functors that take one geometry argument.
604///
605/// Subclasses of this functor base class will implement operator() and call
606/// apply() to do type combination dispatching. The actual body of the functor
607/// is in the eval() member function, which must be implemented for each
608/// different parameter type combination.
609///
610/// The functor may throw exceptions.
611///
612/// @tparam T The return type of the functor.
613template <typename T>
615 public:
616 virtual T operator()(const Geometry &) const = 0;
617 virtual ~Unary_functor() = default;
618
619 protected:
620 template <class F>
621 static inline T apply(F &f, const Geometry &g) {
622 switch (g.coordinate_system()) {
624 switch (g.type()) {
626 return f.eval(down_cast<const Cartesian_point &>(g));
628 return f.eval(down_cast<const Cartesian_linestring &>(g));
630 return f.eval(down_cast<const Cartesian_polygon &>(g));
632 return f.eval(down_cast<const Cartesian_geometrycollection &>(g));
634 return f.eval(down_cast<const Cartesian_multipoint &>(g));
636 return f.eval(down_cast<const Cartesian_multilinestring &>(g));
638 return f.eval(down_cast<const Cartesian_multipolygon &>(g));
639 default:
640 assert(false); /* purecov: inspected */
641 // We don't know here whether the geometry is Cartesan or projected.
642 // Assume Cartesian. This is dead code anyway.
644 }
645 }
647 switch (g.type()) {
649 return f.eval(down_cast<const Geographic_point &>(g));
651 return f.eval(down_cast<const Geographic_linestring &>(g));
653 return f.eval(down_cast<const Geographic_polygon &>(g));
655 return f.eval(down_cast<const Geographic_geometrycollection &>(g));
657 return f.eval(down_cast<const Geographic_multipoint &>(g));
659 return f.eval(down_cast<const Geographic_multilinestring &>(g));
661 return f.eval(down_cast<const Geographic_multipolygon &>(g));
662 default:
663 assert(false); /* purecov: inspected */
664 // We don't know here whether the geometry is Cartesan or projected.
665 // Assume Cartesian. This is dead code anyway.
667 }
668 }
669 }
670 assert(false); /* purecov: inspected */
671 // We don't know here whether the geometry is Cartesan or projected.
672 // Assume Cartesian. This is dead code anyway.
674 }
675};
676
677} // namespace gis
678
679#endif // SQL_GIS_FUNCTOR_H_INCLUDED
The base class of all functors that takes two geometry arguments.
Definition: functor.h:164
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:171
Abstract superclass for all geometric objects.
Definition: geometries.h:99
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:614
virtual T operator()(const Geometry &) const =0
virtual ~Unary_functor()=default
static T apply(F &f, const Geometry &g)
Definition: functor.h:621
Function/parameter combination not implemented exception.
Definition: functor.h:87
Srs_type
Definition: functor.h:89
@ kCartesian
Definition: functor.h:89
@ kProjected
Definition: functor.h:89
@ kGeographic
Definition: functor.h:89
const char * typenames() const
Definition: functor.h:112
Srs_type m_srs_type
Definition: functor.h:92
std::string m_typenames
Definition: functor.h:94
static not_implemented_exception for_projected(const Geometry &g1, const Geometry &g2)
Definition: functor.h:118
Srs_type srs_type() const
Definition: functor.h:111
static not_implemented_exception for_non_projected(const Geometry &g)
Definition: functor.h:123
not_implemented_exception(Srs_type srs_type, const Geometry &g1, const Geometry &g2)
Definition: functor.h:101
static not_implemented_exception for_non_projected(const Geometry &g1, const Geometry &g2)
Definition: functor.h:134
static not_implemented_exception for_projected(const Geometry &g)
Definition: functor.h:114
not_implemented_exception(Srs_type srs_type, const Geometry &g)
Definition: functor.h:96
NULL value exception.
Definition: functor.h:151
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:46
@ 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:687
Latitude out of range exception.
Definition: functor.h:69
double range_min
Definition: functor.h:71
double range_max
Definition: functor.h:72
latitude_out_of_range_exception(double value, double range_min, double range_max)
Definition: functor.h:74
double value
Definition: functor.h:70
Longitude out of range exception.
Definition: functor.h:55
longitude_out_of_range_exception(double value, double range_min, double range_max)
Definition: functor.h:60
double value
Definition: functor.h:56
double range_min
Definition: functor.h:57
double range_max
Definition: functor.h:58