用于EagleEye3.0 规则集漏报和误报测试的示例项目,项目收集于github和gitee
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

678 lines
34 KiB

#ifndef SQL_GIS_FUNCTOR_H_INCLUDED
#define SQL_GIS_FUNCTOR_H_INCLUDED
// Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License, version 2.0,
// as published by the Free Software Foundation.
//
// This program is also distributed with certain software (including
// but not limited to OpenSSL) that is licensed under separate terms,
// as designated in a particular file or component or in included license
// documentation. The authors of MySQL hereby grant you an additional
// permission to link the program and your derivative works with the
// separately licensed software that they have included with MySQL.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License, version 2.0, for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
/// @file
///
/// This file contains the superclasses for GIS functors.
///
/// Each GIS function is split in two: a functor class (for internal use) and a
/// function (for external use) that uses the functor. The functor provides the
/// internal interface to GIS functions, and it may throw exceptions. Some
/// functions may need a combination of different functors to implement the
/// desired functionality.
///
/// The function, not the functor, is the interface to the rest of MySQL.
///
/// @see distance_functor.h
#include <exception> // std::exception
#include <sstream> // std::stringstream
#include <string> // std::string
#include "my_dbug.h" // DBUG_ASSERT
#include "sql/gis/geometries.h" // gis::{Geometry{,_type}, Coordinate_system}
#include "sql/gis/geometries_cs.h" // gis::{Cartesian_*, Geographic_*}
#include "template_utils.h" // down_cast
namespace gis {
/// Longitude out of range exception
///
/// Thrown by GIS functors when longtitude is out of range when reinterpreting
/// geometry coordinates.
struct longitude_out_of_range_exception : public std::exception {
double value;
double range_min;
double range_max;
longitude_out_of_range_exception(double value, double range_min,
double range_max)
: value{value}, range_min{range_min}, range_max{range_max} {}
};
/// Latitude out of range exception
///
/// Thrown by GIS functors when latitude is out of range when reinterpreting
/// geometry coordinates.
struct latitude_out_of_range_exception : public std::exception {
double value;
double range_min;
double range_max;
latitude_out_of_range_exception(double value, double range_min,
double range_max)
: value{value}, range_min{range_min}, range_max{range_max} {}
};
/// Function/parameter combination not implemented exception.
///
/// Geometry is tagged as geographic or Cartesian/projected. In the latter case,
/// whether it is Cartesian or projected is determined by the accompanying SRS.
///
/// To obtain an instance of this exception, use
/// not_implemented_exception::for_projected if geometry is projected, and
/// not_implemented_exception::for_non_projected otherwise.
class not_implemented_exception : public std::exception {
public:
enum Srs_type : char { kCartesian, kGeographic, kProjected };
private:
Srs_type m_srs_type;
std::string m_typenames;
not_implemented_exception(Srs_type srs_type, const Geometry &g) {
m_srs_type = srs_type;
m_typenames = std::string(type_to_name(g.type()));
}
not_implemented_exception(Srs_type srs_type, const Geometry &g1,
const Geometry &g2) {
DBUG_ASSERT(g1.coordinate_system() == g2.coordinate_system());
m_srs_type = srs_type;
std::stringstream ss;
ss << type_to_name(g1.type()) << ", " << type_to_name(g2.type());
m_typenames = ss.str();
}
public:
Srs_type srs_type() const { return m_srs_type; }
const char *typenames() const { return m_typenames.c_str(); }
static not_implemented_exception for_projected(const Geometry &g) {
return not_implemented_exception(kProjected, g);
}
static not_implemented_exception for_projected(const Geometry &g1,
const Geometry &g2) {
return not_implemented_exception(kProjected, g1, g2);
}
static not_implemented_exception for_non_projected(const Geometry &g) {
switch (g.coordinate_system()) {
default:
DBUG_ASSERT(false); // C++11 woes. /* purecov: inspected */
case Coordinate_system::kCartesian:
return not_implemented_exception(kCartesian, g);
case Coordinate_system::kGeographic:
return not_implemented_exception(kGeographic, g);
}
}
static not_implemented_exception for_non_projected(const Geometry &g1,
const Geometry &g2) {
switch (g1.coordinate_system()) {
default:
DBUG_ASSERT(false); // C++11 woes. /* purecov: inspected */
case Coordinate_system::kCartesian:
return not_implemented_exception(kCartesian, g1, g2);
case Coordinate_system::kGeographic:
return not_implemented_exception(kGeographic, g1, g2);
}
}
};
/// NULL value exception.
///
/// Thrown when the functor discovers that the result is NULL. Normally, NULL
/// returns can be detected before calling the functor, but not always.
class null_value_exception : public std::exception {};
/// The base class of all functors that takes two geometry arguments.
///
/// Subclasses of this functor base class will implement operator() and call
/// apply() to do type combination dispatching. The actual body of the functor
/// is in the eval() member function, which must be implemented for each
/// different parameter type combination.
///
/// The functor may throw exceptions.
///
/// @tparam T The return type of the functor.
template <typename T>
class Functor {
public:
virtual T operator()(const Geometry *g1, const Geometry *g2) const = 0;
virtual ~Functor() {}
protected:
template <typename F>
static inline T apply(F &f, const Geometry *g1, const Geometry *g2) {
DBUG_ASSERT(g1->coordinate_system() == g2->coordinate_system());
switch (g1->coordinate_system()) {
case Coordinate_system::kCartesian:
switch (g1->type()) {
case Geometry_type::kPoint:
switch (g2->type()) {
case Geometry_type::kPoint:
return f.eval(down_cast<const Cartesian_point *>(g1),
down_cast<const Cartesian_point *>(g2));
case Geometry_type::kLinestring:
return f.eval(down_cast<const Cartesian_point *>(g1),
down_cast<const Cartesian_linestring *>(g2));
case Geometry_type::kPolygon:
return f.eval(down_cast<const Cartesian_point *>(g1),
down_cast<const Cartesian_polygon *>(g2));
case Geometry_type::kGeometrycollection:
return f.eval(
down_cast<const Cartesian_point *>(g1),
down_cast<const Cartesian_geometrycollection *>(g2));
case Geometry_type::kMultipoint:
return f.eval(down_cast<const Cartesian_point *>(g1),
down_cast<const Cartesian_multipoint *>(g2));
case Geometry_type::kMultilinestring:
return f.eval(down_cast<const Cartesian_point *>(g1),
down_cast<const Cartesian_multilinestring *>(g2));
case Geometry_type::kMultipolygon:
return f.eval(down_cast<const Cartesian_point *>(g1),
down_cast<const Cartesian_multipolygon *>(g2));
default:
DBUG_ASSERT(false); /* purecov: inspected */
throw not_implemented_exception::for_non_projected(*g1, *g2);
}
case Geometry_type::kLinestring:
switch (g2->type()) {
case Geometry_type::kPoint:
return f.eval(down_cast<const Cartesian_linestring *>(g1),
down_cast<const Cartesian_point *>(g2));
case Geometry_type::kLinestring:
return f.eval(down_cast<const Cartesian_linestring *>(g1),
down_cast<const Cartesian_linestring *>(g2));
case Geometry_type::kPolygon:
return f.eval(down_cast<const Cartesian_linestring *>(g1),
down_cast<const Cartesian_polygon *>(g2));
case Geometry_type::kGeometrycollection:
return f.eval(
down_cast<const Cartesian_linestring *>(g1),
down_cast<const Cartesian_geometrycollection *>(g2));
case Geometry_type::kMultipoint:
return f.eval(down_cast<const Cartesian_linestring *>(g1),
down_cast<const Cartesian_multipoint *>(g2));
case Geometry_type::kMultilinestring:
return f.eval(down_cast<const Cartesian_linestring *>(g1),
down_cast<const Cartesian_multilinestring *>(g2));
case Geometry_type::kMultipolygon:
return f.eval(down_cast<const Cartesian_linestring *>(g1),
down_cast<const Cartesian_multipolygon *>(g2));
default:
DBUG_ASSERT(false); /* purecov: inspected */
throw not_implemented_exception::for_non_projected(*g1, *g2);
}
case Geometry_type::kPolygon:
switch (g2->type()) {
case Geometry_type::kPoint:
return f.eval(down_cast<const Cartesian_polygon *>(g1),
down_cast<const Cartesian_point *>(g2));
case Geometry_type::kLinestring:
return f.eval(down_cast<const Cartesian_polygon *>(g1),
down_cast<const Cartesian_linestring *>(g2));
case Geometry_type::kPolygon:
return f.eval(down_cast<const Cartesian_polygon *>(g1),
down_cast<const Cartesian_polygon *>(g2));
case Geometry_type::kGeometrycollection:
return f.eval(
down_cast<const Cartesian_polygon *>(g1),
down_cast<const Cartesian_geometrycollection *>(g2));
case Geometry_type::kMultipoint:
return f.eval(down_cast<const Cartesian_polygon *>(g1),
down_cast<const Cartesian_multipoint *>(g2));
case Geometry_type::kMultilinestring:
return f.eval(down_cast<const Cartesian_polygon *>(g1),
down_cast<const Cartesian_multilinestring *>(g2));
case Geometry_type::kMultipolygon:
return f.eval(down_cast<const Cartesian_polygon *>(g1),
down_cast<const Cartesian_multipolygon *>(g2));
default:
DBUG_ASSERT(false); /* purecov: inspected */
throw not_implemented_exception::for_non_projected(*g1, *g2);
}
case Geometry_type::kGeometrycollection:
switch (g2->type()) {
case Geometry_type::kPoint:
return f.eval(
down_cast<const Cartesian_geometrycollection *>(g1),
down_cast<const Cartesian_point *>(g2));
case Geometry_type::kLinestring:
return f.eval(
down_cast<const Cartesian_geometrycollection *>(g1),
down_cast<const Cartesian_linestring *>(g2));
case Geometry_type::kPolygon:
return f.eval(
down_cast<const Cartesian_geometrycollection *>(g1),
down_cast<const Cartesian_polygon *>(g2));
case Geometry_type::kGeometrycollection:
return f.eval(
down_cast<const Cartesian_geometrycollection *>(g1),
down_cast<const Cartesian_geometrycollection *>(g2));
case Geometry_type::kMultipoint:
return f.eval(
down_cast<const Cartesian_geometrycollection *>(g1),
down_cast<const Cartesian_multipoint *>(g2));
case Geometry_type::kMultilinestring:
return f.eval(
down_cast<const Cartesian_geometrycollection *>(g1),
down_cast<const Cartesian_multilinestring *>(g2));
case Geometry_type::kMultipolygon:
return f.eval(
down_cast<const Cartesian_geometrycollection *>(g1),
down_cast<const Cartesian_multipolygon *>(g2));
default:
DBUG_ASSERT(false); /* purecov: inspected */
throw not_implemented_exception::for_non_projected(*g1, *g2);
}
case Geometry_type::kMultipoint:
switch (g2->type()) {
case Geometry_type::kPoint:
return f.eval(down_cast<const Cartesian_multipoint *>(g1),
down_cast<const Cartesian_point *>(g2));
case Geometry_type::kLinestring:
return f.eval(down_cast<const Cartesian_multipoint *>(g1),
down_cast<const Cartesian_linestring *>(g2));
case Geometry_type::kPolygon:
return f.eval(down_cast<const Cartesian_multipoint *>(g1),
down_cast<const Cartesian_polygon *>(g2));
case Geometry_type::kGeometrycollection:
return f.eval(
down_cast<const Cartesian_multipoint *>(g1),
down_cast<const Cartesian_geometrycollection *>(g2));
case Geometry_type::kMultipoint:
return f.eval(down_cast<const Cartesian_multipoint *>(g1),
down_cast<const Cartesian_multipoint *>(g2));
case Geometry_type::kMultilinestring:
return f.eval(down_cast<const Cartesian_multipoint *>(g1),
down_cast<const Cartesian_multilinestring *>(g2));
case Geometry_type::kMultipolygon:
return f.eval(down_cast<const Cartesian_multipoint *>(g1),
down_cast<const Cartesian_multipolygon *>(g2));
default:
DBUG_ASSERT(false); /* purecov: inspected */
throw not_implemented_exception::for_non_projected(*g1, *g2);
}
case Geometry_type::kMultilinestring:
switch (g2->type()) {
case Geometry_type::kPoint:
return f.eval(down_cast<const Cartesian_multilinestring *>(g1),
down_cast<const Cartesian_point *>(g2));
case Geometry_type::kLinestring:
return f.eval(down_cast<const Cartesian_multilinestring *>(g1),
down_cast<const Cartesian_linestring *>(g2));
case Geometry_type::kPolygon:
return f.eval(down_cast<const Cartesian_multilinestring *>(g1),
down_cast<const Cartesian_polygon *>(g2));
case Geometry_type::kGeometrycollection:
return f.eval(
down_cast<const Cartesian_multilinestring *>(g1),
down_cast<const Cartesian_geometrycollection *>(g2));
case Geometry_type::kMultipoint:
return f.eval(down_cast<const Cartesian_multilinestring *>(g1),
down_cast<const Cartesian_multipoint *>(g2));
case Geometry_type::kMultilinestring:
return f.eval(down_cast<const Cartesian_multilinestring *>(g1),
down_cast<const Cartesian_multilinestring *>(g2));
case Geometry_type::kMultipolygon:
return f.eval(down_cast<const Cartesian_multilinestring *>(g1),
down_cast<const Cartesian_multipolygon *>(g2));
default:
DBUG_ASSERT(false); /* purecov: inspected */
throw not_implemented_exception::for_non_projected(*g1, *g2);
}
case Geometry_type::kMultipolygon:
switch (g2->type()) {
case Geometry_type::kPoint:
return f.eval(down_cast<const Cartesian_multipolygon *>(g1),
down_cast<const Cartesian_point *>(g2));
case Geometry_type::kLinestring:
return f.eval(down_cast<const Cartesian_multipolygon *>(g1),
down_cast<const Cartesian_linestring *>(g2));
case Geometry_type::kPolygon:
return f.eval(down_cast<const Cartesian_multipolygon *>(g1),
down_cast<const Cartesian_polygon *>(g2));
case Geometry_type::kGeometrycollection:
return f.eval(
down_cast<const Cartesian_multipolygon *>(g1),
down_cast<const Cartesian_geometrycollection *>(g2));
case Geometry_type::kMultipoint:
return f.eval(down_cast<const Cartesian_multipolygon *>(g1),
down_cast<const Cartesian_multipoint *>(g2));
case Geometry_type::kMultilinestring:
return f.eval(down_cast<const Cartesian_multipolygon *>(g1),
down_cast<const Cartesian_multilinestring *>(g2));
case Geometry_type::kMultipolygon:
return f.eval(down_cast<const Cartesian_multipolygon *>(g1),
down_cast<const Cartesian_multipolygon *>(g2));
default:
DBUG_ASSERT(false); /* purecov: inspected */
throw not_implemented_exception::for_non_projected(*g1, *g2);
}
default:
DBUG_ASSERT(false); /* purecov: inspected */
throw not_implemented_exception::for_non_projected(*g1, *g2);
} // switch (g1->type())
case Coordinate_system::kGeographic:
switch (g1->type()) {
case Geometry_type::kPoint:
switch (g2->type()) {
case Geometry_type::kPoint:
return f.eval(down_cast<const Geographic_point *>(g1),
down_cast<const Geographic_point *>(g2));
case Geometry_type::kLinestring:
return f.eval(down_cast<const Geographic_point *>(g1),
down_cast<const Geographic_linestring *>(g2));
case Geometry_type::kPolygon:
return f.eval(down_cast<const Geographic_point *>(g1),
down_cast<const Geographic_polygon *>(g2));
case Geometry_type::kGeometrycollection:
return f.eval(
down_cast<const Geographic_point *>(g1),
down_cast<const Geographic_geometrycollection *>(g2));
case Geometry_type::kMultipoint:
return f.eval(down_cast<const Geographic_point *>(g1),
down_cast<const Geographic_multipoint *>(g2));
case Geometry_type::kMultilinestring:
return f.eval(
down_cast<const Geographic_point *>(g1),
down_cast<const Geographic_multilinestring *>(g2));
case Geometry_type::kMultipolygon:
return f.eval(down_cast<const Geographic_point *>(g1),
down_cast<const Geographic_multipolygon *>(g2));
default:
DBUG_ASSERT(false); /* purecov: inspected */
throw not_implemented_exception::for_non_projected(*g1, *g2);
}
case Geometry_type::kLinestring:
switch (g2->type()) {
case Geometry_type::kPoint:
return f.eval(down_cast<const Geographic_linestring *>(g1),
down_cast<const Geographic_point *>(g2));
case Geometry_type::kLinestring:
return f.eval(down_cast<const Geographic_linestring *>(g1),
down_cast<const Geographic_linestring *>(g2));
case Geometry_type::kPolygon:
return f.eval(down_cast<const Geographic_linestring *>(g1),
down_cast<const Geographic_polygon *>(g2));
case Geometry_type::kGeometrycollection:
return f.eval(
down_cast<const Geographic_linestring *>(g1),
down_cast<const Geographic_geometrycollection *>(g2));
case Geometry_type::kMultipoint:
return f.eval(down_cast<const Geographic_linestring *>(g1),
down_cast<const Geographic_multipoint *>(g2));
case Geometry_type::kMultilinestring:
return f.eval(
down_cast<const Geographic_linestring *>(g1),
down_cast<const Geographic_multilinestring *>(g2));
case Geometry_type::kMultipolygon:
return f.eval(down_cast<const Geographic_linestring *>(g1),
down_cast<const Geographic_multipolygon *>(g2));
default:
DBUG_ASSERT(false); /* purecov: inspected */
throw not_implemented_exception::for_non_projected(*g1, *g2);
}
case Geometry_type::kPolygon:
switch (g2->type()) {
case Geometry_type::kPoint:
return f.eval(down_cast<const Geographic_polygon *>(g1),
down_cast<const Geographic_point *>(g2));
case Geometry_type::kLinestring:
return f.eval(down_cast<const Geographic_polygon *>(g1),
down_cast<const Geographic_linestring *>(g2));
case Geometry_type::kPolygon:
return f.eval(down_cast<const Geographic_polygon *>(g1),
down_cast<const Geographic_polygon *>(g2));
case Geometry_type::kGeometrycollection:
return f.eval(
down_cast<const Geographic_polygon *>(g1),
down_cast<const Geographic_geometrycollection *>(g2));
case Geometry_type::kMultipoint:
return f.eval(down_cast<const Geographic_polygon *>(g1),
down_cast<const Geographic_multipoint *>(g2));
case Geometry_type::kMultilinestring:
return f.eval(
down_cast<const Geographic_polygon *>(g1),
down_cast<const Geographic_multilinestring *>(g2));
case Geometry_type::kMultipolygon:
return f.eval(down_cast<const Geographic_polygon *>(g1),
down_cast<const Geographic_multipolygon *>(g2));
default:
DBUG_ASSERT(false); /* purecov: inspected */
throw not_implemented_exception::for_non_projected(*g1, *g2);
}
case Geometry_type::kGeometrycollection:
switch (g2->type()) {
case Geometry_type::kPoint:
return f.eval(
down_cast<const Geographic_geometrycollection *>(g1),
down_cast<const Geographic_point *>(g2));
case Geometry_type::kLinestring:
return f.eval(
down_cast<const Geographic_geometrycollection *>(g1),
down_cast<const Geographic_linestring *>(g2));
case Geometry_type::kPolygon:
return f.eval(
down_cast<const Geographic_geometrycollection *>(g1),
down_cast<const Geographic_polygon *>(g2));
case Geometry_type::kGeometrycollection:
return f.eval(
down_cast<const Geographic_geometrycollection *>(g1),
down_cast<const Geographic_geometrycollection *>(g2));
case Geometry_type::kMultipoint:
return f.eval(
down_cast<const Geographic_geometrycollection *>(g1),
down_cast<const Geographic_multipoint *>(g2));
case Geometry_type::kMultilinestring:
return f.eval(
down_cast<const Geographic_geometrycollection *>(g1),
down_cast<const Geographic_multilinestring *>(g2));
case Geometry_type::kMultipolygon:
return f.eval(
down_cast<const Geographic_geometrycollection *>(g1),
down_cast<const Geographic_multipolygon *>(g2));
default:
DBUG_ASSERT(false); /* purecov: inspected */
throw not_implemented_exception::for_non_projected(*g1, *g2);
}
case Geometry_type::kMultipoint:
switch (g2->type()) {
case Geometry_type::kPoint:
return f.eval(down_cast<const Geographic_multipoint *>(g1),
down_cast<const Geographic_point *>(g2));
case Geometry_type::kLinestring:
return f.eval(down_cast<const Geographic_multipoint *>(g1),
down_cast<const Geographic_linestring *>(g2));
case Geometry_type::kPolygon:
return f.eval(down_cast<const Geographic_multipoint *>(g1),
down_cast<const Geographic_polygon *>(g2));
case Geometry_type::kGeometrycollection:
return f.eval(
down_cast<const Geographic_multipoint *>(g1),
down_cast<const Geographic_geometrycollection *>(g2));
case Geometry_type::kMultipoint:
return f.eval(down_cast<const Geographic_multipoint *>(g1),
down_cast<const Geographic_multipoint *>(g2));
case Geometry_type::kMultilinestring:
return f.eval(
down_cast<const Geographic_multipoint *>(g1),
down_cast<const Geographic_multilinestring *>(g2));
case Geometry_type::kMultipolygon:
return f.eval(down_cast<const Geographic_multipoint *>(g1),
down_cast<const Geographic_multipolygon *>(g2));
default:
DBUG_ASSERT(false); /* purecov: inspected */
throw not_implemented_exception::for_non_projected(*g1, *g2);
}
case Geometry_type::kMultilinestring:
switch (g2->type()) {
case Geometry_type::kPoint:
return f.eval(down_cast<const Geographic_multilinestring *>(g1),
down_cast<const Geographic_point *>(g2));
case Geometry_type::kLinestring:
return f.eval(down_cast<const Geographic_multilinestring *>(g1),
down_cast<const Geographic_linestring *>(g2));
case Geometry_type::kPolygon:
return f.eval(down_cast<const Geographic_multilinestring *>(g1),
down_cast<const Geographic_polygon *>(g2));
case Geometry_type::kGeometrycollection:
return f.eval(
down_cast<const Geographic_multilinestring *>(g1),
down_cast<const Geographic_geometrycollection *>(g2));
case Geometry_type::kMultipoint:
return f.eval(down_cast<const Geographic_multilinestring *>(g1),
down_cast<const Geographic_multipoint *>(g2));
case Geometry_type::kMultilinestring:
return f.eval(
down_cast<const Geographic_multilinestring *>(g1),
down_cast<const Geographic_multilinestring *>(g2));
case Geometry_type::kMultipolygon:
return f.eval(down_cast<const Geographic_multilinestring *>(g1),
down_cast<const Geographic_multipolygon *>(g2));
default:
DBUG_ASSERT(false); /* purecov: inspected */
throw not_implemented_exception::for_non_projected(*g1, *g2);
}
case Geometry_type::kMultipolygon:
switch (g2->type()) {
case Geometry_type::kPoint:
return f.eval(down_cast<const Geographic_multipolygon *>(g1),
down_cast<const Geographic_point *>(g2));
case Geometry_type::kLinestring:
return f.eval(down_cast<const Geographic_multipolygon *>(g1),
down_cast<const Geographic_linestring *>(g2));
case Geometry_type::kPolygon:
return f.eval(down_cast<const Geographic_multipolygon *>(g1),
down_cast<const Geographic_polygon *>(g2));
case Geometry_type::kGeometrycollection:
return f.eval(
down_cast<const Geographic_multipolygon *>(g1),
down_cast<const Geographic_geometrycollection *>(g2));
case Geometry_type::kMultipoint:
return f.eval(down_cast<const Geographic_multipolygon *>(g1),
down_cast<const Geographic_multipoint *>(g2));
case Geometry_type::kMultilinestring:
return f.eval(
down_cast<const Geographic_multipolygon *>(g1),
down_cast<const Geographic_multilinestring *>(g2));
case Geometry_type::kMultipolygon:
return f.eval(down_cast<const Geographic_multipolygon *>(g1),
down_cast<const Geographic_multipolygon *>(g2));
default:
DBUG_ASSERT(false); /* purecov: inspected */
throw not_implemented_exception::for_non_projected(*g1, *g2);
}
default:
DBUG_ASSERT(false); /* purecov: inspected */
throw not_implemented_exception::for_non_projected(*g1, *g2);
} // switch (g1->type())
} // switch (g1->coordinate_system())
DBUG_ASSERT(false); /* purecov: inspected */
throw not_implemented_exception::for_non_projected(*g1, *g2);
}
};
/// The base class of all functors that take one geometry argument.
///
/// Subclasses of this functor base class will implement operator() and call
/// apply() to do type combination dispatching. The actual body of the functor
/// is in the eval() member function, which must be implemented for each
/// different parameter type combination.
///
/// The functor may throw exceptions.
///
/// @tparam T The return type of the functor.
template <typename T>
class Unary_functor {
public:
virtual T operator()(const Geometry &) const = 0;
virtual ~Unary_functor() {}
protected:
template <class F>
static inline T apply(F &f, const Geometry &g) {
switch (g.coordinate_system()) {
case Coordinate_system::kCartesian: {
switch (g.type()) {
case Geometry_type::kPoint:
return f.eval(down_cast<const Cartesian_point &>(g));
case Geometry_type::kLinestring:
return f.eval(down_cast<const Cartesian_linestring &>(g));
case Geometry_type::kPolygon:
return f.eval(down_cast<const Cartesian_polygon &>(g));
case Geometry_type::kGeometrycollection:
return f.eval(down_cast<const Cartesian_geometrycollection &>(g));
case Geometry_type::kMultipoint:
return f.eval(down_cast<const Cartesian_multipoint &>(g));
case Geometry_type::kMultilinestring:
return f.eval(down_cast<const Cartesian_multilinestring &>(g));
case Geometry_type::kMultipolygon:
return f.eval(down_cast<const Cartesian_multipolygon &>(g));
default:
DBUG_ASSERT(false); /* purecov: inspected */
// We don't know here whether the geometry is Cartesan or projected.
// Assume Cartesian. This is dead code anyway.
throw not_implemented_exception::for_non_projected(g);
}
}
case Coordinate_system::kGeographic: {
switch (g.type()) {
case Geometry_type::kPoint:
return f.eval(down_cast<const Geographic_point &>(g));
case Geometry_type::kLinestring:
return f.eval(down_cast<const Geographic_linestring &>(g));
case Geometry_type::kPolygon:
return f.eval(down_cast<const Geographic_polygon &>(g));
case Geometry_type::kGeometrycollection:
return f.eval(down_cast<const Geographic_geometrycollection &>(g));
case Geometry_type::kMultipoint:
return f.eval(down_cast<const Geographic_multipoint &>(g));
case Geometry_type::kMultilinestring:
return f.eval(down_cast<const Geographic_multilinestring &>(g));
case Geometry_type::kMultipolygon:
return f.eval(down_cast<const Geographic_multipolygon &>(g));
default:
DBUG_ASSERT(false); /* purecov: inspected */
// We don't know here whether the geometry is Cartesan or projected.
// Assume Cartesian. This is dead code anyway.
throw not_implemented_exception::for_non_projected(g);
}
}
}
DBUG_ASSERT(false); /* purecov: inspected */
// We don't know here whether the geometry is Cartesan or projected.
// Assume Cartesian. This is dead code anyway.
throw not_implemented_exception::for_non_projected(g);
}
};
} // namespace gis
#endif // SQL_GIS_FUNCTOR_H_INCLUDED