用于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.

654 lines
22 KiB

5 months ago
// 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.
#include "sql/gis/geometries.h"
#include <utility> // std::swap
#include "my_dbug.h"
#include "sql/gis/geometries_cs.h"
#include "sql/gis/geometry_visitor.h"
namespace gis {
bool Point::accept(Geometry_visitor *v) { return v->visit(this); }
template <>
double Point::get<0>() const {
return m_x;
}
template <>
double Point::get<1>() const {
return m_y;
}
double Point::x() const { return get<0>(); }
double Point::y() const { return get<1>(); }
template <>
void Point::set<0>(double d) {
m_x = d;
}
template <>
void Point::set<1>(double d) {
m_y = d;
}
void Point::x(double d) { set<0>(d); }
void Point::y(double d) { set<1>(d); }
bool Cartesian_linestring::accept(Geometry_visitor *v) {
if (!v->visit_enter(this) && m_points.size() > 0) {
if (m_points[0].accept(v)) return true;
for (decltype(m_points)::size_type i = 1; i < m_points.size(); i++) {
if (v->visit(this) || m_points[i].accept(v)) return true;
}
}
return v->visit_leave(this);
}
void Cartesian_linestring::push_back(const Point &pt) {
DBUG_ASSERT(pt.coordinate_system() == Coordinate_system::kCartesian);
m_points.push_back(static_cast<const Cartesian_point &>(pt));
}
void Cartesian_linestring::push_back(Point &&pt) {
DBUG_ASSERT(pt.coordinate_system() == Coordinate_system::kCartesian);
m_points.push_back(static_cast<Cartesian_point &&>(pt));
}
bool Cartesian_linestring::empty() const { return m_points.empty(); }
bool Geographic_linestring::accept(Geometry_visitor *v) {
if (!v->visit_enter(this) && m_points.size() > 0) {
if (m_points[0].accept(v)) return true;
for (decltype(m_points)::size_type i = 1; i < m_points.size(); i++) {
if (v->visit(this) || m_points[i].accept(v)) return true;
}
}
return v->visit_leave(this);
}
void Geographic_linestring::push_back(const Point &pt) {
DBUG_ASSERT(pt.coordinate_system() == Coordinate_system::kGeographic);
m_points.push_back(static_cast<const Geographic_point &>(pt));
}
void Geographic_linestring::push_back(Point &&pt) {
DBUG_ASSERT(pt.coordinate_system() == Coordinate_system::kGeographic);
m_points.push_back(static_cast<Geographic_point &&>(pt));
}
bool Geographic_linestring::empty() const { return m_points.empty(); }
bool Cartesian_linearring::accept(Geometry_visitor *v) {
if (!v->visit_enter(this) && m_points.size() > 0) {
if (m_points[0].accept(v)) return true;
for (decltype(m_points)::size_type i = 1; i < m_points.size(); i++) {
if (v->visit(this) || m_points[i].accept(v)) return true;
}
}
return v->visit_leave(this);
}
bool Geographic_linearring::accept(Geometry_visitor *v) {
if (!v->visit_enter(this) && m_points.size() > 0) {
if (m_points[0].accept(v)) return true;
for (decltype(m_points)::size_type i = 1; i < m_points.size(); i++) {
if (v->visit(this) || m_points[i].accept(v)) return true;
}
}
return v->visit_leave(this);
}
bool Cartesian_polygon::accept(Geometry_visitor *v) {
if (!v->visit_enter(this)) {
if (m_exterior_ring.accept(v)) return true;
for (auto &&ring : m_interior_rings) {
if (v->visit(this) || ring.accept(v)) return true;
}
}
return v->visit_leave(this);
}
void Cartesian_polygon::push_back(const Linearring &lr) {
DBUG_ASSERT(lr.coordinate_system() == Coordinate_system::kCartesian);
if (m_exterior_ring.empty() && m_interior_rings.empty())
m_exterior_ring = static_cast<const Cartesian_linearring &>(lr);
else
m_interior_rings.push_back(static_cast<const Cartesian_linearring &>(lr));
}
void Cartesian_polygon::push_back(Linearring &&lr) {
DBUG_ASSERT(lr.coordinate_system() == Coordinate_system::kCartesian);
if (m_exterior_ring.empty() && m_interior_rings.empty())
m_exterior_ring = static_cast<Cartesian_linearring &&>(lr);
else
m_interior_rings.push_back(static_cast<Cartesian_linearring &&>(lr));
}
bool Cartesian_polygon::empty() const {
return m_exterior_ring.empty() && m_interior_rings.empty();
}
std::size_t Cartesian_polygon::size() const {
std::size_t sz = m_interior_rings.size();
if (!m_exterior_ring.empty()) sz++;
return sz;
}
Linearring &Cartesian_polygon::interior_ring(std::size_t n) {
return m_interior_rings[n];
}
bool Geographic_polygon::accept(Geometry_visitor *v) {
if (!v->visit_enter(this)) {
if (m_exterior_ring.accept(v)) return true;
for (auto &&ring : m_interior_rings) {
if (v->visit(this) || ring.accept(v)) return true;
}
}
return v->visit_leave(this);
}
Cartesian_linearring &Cartesian_polygon::cartesian_exterior_ring() const {
return const_cast<Cartesian_linearring &>(m_exterior_ring);
}
// Doxygen doesn't understand decltype as it is used here.
#ifndef IN_DOXYGEN
decltype(Cartesian_polygon::m_interior_rings) &
Cartesian_polygon::interior_rings() {
return m_interior_rings;
}
decltype(Cartesian_polygon::m_interior_rings) const &
Cartesian_polygon::const_interior_rings() const {
return m_interior_rings;
}
#endif // IN_DOXYGEN
void Geographic_polygon::push_back(const Linearring &lr) {
DBUG_ASSERT(lr.coordinate_system() == Coordinate_system::kGeographic);
if (m_exterior_ring.empty() && m_interior_rings.empty())
m_exterior_ring = static_cast<const Geographic_linearring &>(lr);
else
m_interior_rings.push_back(static_cast<const Geographic_linearring &>(lr));
}
void Geographic_polygon::push_back(Linearring &&lr) {
DBUG_ASSERT(lr.coordinate_system() == Coordinate_system::kGeographic);
if (m_exterior_ring.empty() && m_interior_rings.empty())
m_exterior_ring = static_cast<Geographic_linearring &&>(lr);
else
m_interior_rings.push_back(static_cast<Geographic_linearring &&>(lr));
}
bool Geographic_polygon::empty() const {
return m_exterior_ring.empty() && m_interior_rings.empty();
}
std::size_t Geographic_polygon::size() const {
std::size_t sz = m_interior_rings.size();
if (!m_exterior_ring.empty()) sz++;
return sz;
}
Geographic_linearring &Geographic_polygon::geographic_exterior_ring() const {
return const_cast<Geographic_linearring &>(m_exterior_ring);
}
Linearring &Geographic_polygon::interior_ring(std::size_t n) {
return m_interior_rings[n];
}
// Doxygen doesn't understand decltype as it is used here.
#ifndef IN_DOXYGEN
decltype(Geographic_polygon::m_interior_rings) &
Geographic_polygon::interior_rings() {
return m_interior_rings;
}
decltype(Geographic_polygon::m_interior_rings) const &
Geographic_polygon::const_interior_rings() const {
return m_interior_rings;
}
#endif // IN_DOXYGEN
Cartesian_geometrycollection::Cartesian_geometrycollection(
const Cartesian_geometrycollection &gc)
: m_geometries(
Malloc_allocator<Geometry *>(key_memory_Geometry_objects_data)) {
for (Geometry *g : gc.m_geometries) {
switch (g->type()) {
case Geometry_type::kPoint:
m_geometries.push_back(
new Cartesian_point(*static_cast<Cartesian_point *>(g)));
break;
case Geometry_type::kLinestring:
m_geometries.push_back(
new Cartesian_linestring(*static_cast<Cartesian_linestring *>(g)));
break;
case Geometry_type::kPolygon:
m_geometries.push_back(
new Cartesian_polygon(*static_cast<Cartesian_polygon *>(g)));
break;
case Geometry_type::kGeometrycollection:
m_geometries.push_back(new Cartesian_geometrycollection(
*static_cast<Cartesian_geometrycollection *>(g)));
break;
case Geometry_type::kMultipoint:
m_geometries.push_back(
new Cartesian_multipoint(*static_cast<Cartesian_multipoint *>(g)));
break;
case Geometry_type::kMultilinestring:
m_geometries.push_back(new Cartesian_multilinestring(
*static_cast<Cartesian_multilinestring *>(g)));
break;
case Geometry_type::kMultipolygon:
m_geometries.push_back(new Cartesian_multipolygon(
*static_cast<Cartesian_multipolygon *>(g)));
break;
default:
DBUG_ASSERT(false); /* purecov: inspected */
}
}
}
bool Cartesian_geometrycollection::accept(Geometry_visitor *v) {
if (!v->visit_enter(this) && m_geometries.size() > 0) {
if (m_geometries[0]->accept(v)) return true;
for (decltype(m_geometries)::size_type i = 1; i < m_geometries.size();
i++) {
if (v->visit(this) || m_geometries[i]->accept(v)) return true;
}
}
return v->visit_leave(this);
}
void Cartesian_geometrycollection::push_back(const Geometry &g) {
switch (g.type()) {
case Geometry_type::kPoint:
m_geometries.push_back(
new Cartesian_point(static_cast<const Cartesian_point &>(g)));
break;
case Geometry_type::kLinestring:
m_geometries.push_back(new Cartesian_linestring(
static_cast<const Cartesian_linestring &>(g)));
break;
case Geometry_type::kPolygon:
m_geometries.push_back(
new Cartesian_polygon(static_cast<const Cartesian_polygon &>(g)));
break;
case Geometry_type::kGeometrycollection:
m_geometries.push_back(new Cartesian_geometrycollection(
static_cast<const Cartesian_geometrycollection &>(g)));
break;
case Geometry_type::kMultipoint:
m_geometries.push_back(new Cartesian_multipoint(
static_cast<const Cartesian_multipoint &>(g)));
break;
case Geometry_type::kMultilinestring:
m_geometries.push_back(new Cartesian_multilinestring(
static_cast<const Cartesian_multilinestring &>(g)));
break;
case Geometry_type::kMultipolygon:
m_geometries.push_back(new Cartesian_multipolygon(
static_cast<const Cartesian_multipolygon &>(g)));
break;
default:
DBUG_ASSERT(false); /* purecov: inspected */
}
}
void Cartesian_geometrycollection::push_back(Geometry &&g) {
switch (g.type()) {
case Geometry_type::kPoint:
m_geometries.push_back(
new Cartesian_point(static_cast<Cartesian_point &&>(g)));
break;
case Geometry_type::kLinestring:
m_geometries.push_back(
new Cartesian_linestring(static_cast<Cartesian_linestring &&>(g)));
break;
case Geometry_type::kPolygon:
m_geometries.push_back(
new Cartesian_polygon(static_cast<Cartesian_polygon &&>(g)));
break;
case Geometry_type::kGeometrycollection:
m_geometries.push_back(new Cartesian_geometrycollection(
static_cast<Cartesian_geometrycollection &&>(g)));
break;
case Geometry_type::kMultipoint:
m_geometries.push_back(
new Cartesian_multipoint(static_cast<Cartesian_multipoint &&>(g)));
break;
case Geometry_type::kMultilinestring:
m_geometries.push_back(new Cartesian_multilinestring(
static_cast<Cartesian_multilinestring &&>(g)));
break;
case Geometry_type::kMultipolygon:
m_geometries.push_back(new Cartesian_multipolygon(
static_cast<Cartesian_multipolygon &&>(g)));
break;
default:
DBUG_ASSERT(false); /* purecov: inspected */
}
}
bool Cartesian_geometrycollection::empty() const {
return m_geometries.empty();
}
Geographic_geometrycollection::Geographic_geometrycollection(
const Geographic_geometrycollection &gc)
: m_geometries(
Malloc_allocator<Geometry *>(key_memory_Geometry_objects_data)) {
for (Geometry *g : gc.m_geometries) {
switch (g->type()) {
case Geometry_type::kPoint:
m_geometries.push_back(
new Geographic_point(*static_cast<Geographic_point *>(g)));
break;
case Geometry_type::kLinestring:
m_geometries.push_back(new Geographic_linestring(
*static_cast<Geographic_linestring *>(g)));
break;
case Geometry_type::kPolygon:
m_geometries.push_back(
new Geographic_polygon(*static_cast<Geographic_polygon *>(g)));
break;
case Geometry_type::kGeometrycollection:
m_geometries.push_back(new Geographic_geometrycollection(
*static_cast<Geographic_geometrycollection *>(g)));
break;
case Geometry_type::kMultipoint:
m_geometries.push_back(new Geographic_multipoint(
*static_cast<Geographic_multipoint *>(g)));
break;
case Geometry_type::kMultilinestring:
m_geometries.push_back(new Geographic_multilinestring(
*static_cast<Geographic_multilinestring *>(g)));
break;
case Geometry_type::kMultipolygon:
m_geometries.push_back(new Geographic_multipolygon(
*static_cast<Geographic_multipolygon *>(g)));
break;
default:
DBUG_ASSERT(false); /* purecov: inspected */
}
}
}
bool Geographic_geometrycollection::accept(Geometry_visitor *v) {
if (!v->visit_enter(this) && m_geometries.size() > 0) {
if (m_geometries[0]->accept(v)) return true;
for (decltype(m_geometries)::size_type i = 1; i < m_geometries.size();
i++) {
if (v->visit(this) || m_geometries[i]->accept(v)) return true;
}
}
return v->visit_leave(this);
}
void Geographic_geometrycollection::push_back(const Geometry &g) {
switch (g.type()) {
case Geometry_type::kPoint:
m_geometries.push_back(
new Geographic_point(static_cast<const Geographic_point &>(g)));
break;
case Geometry_type::kLinestring:
m_geometries.push_back(new Geographic_linestring(
static_cast<const Geographic_linestring &>(g)));
break;
case Geometry_type::kPolygon:
m_geometries.push_back(
new Geographic_polygon(static_cast<const Geographic_polygon &>(g)));
break;
case Geometry_type::kGeometrycollection:
m_geometries.push_back(new Geographic_geometrycollection(
static_cast<const Geographic_geometrycollection &>(g)));
break;
case Geometry_type::kMultipoint:
m_geometries.push_back(new Geographic_multipoint(
static_cast<const Geographic_multipoint &>(g)));
break;
case Geometry_type::kMultilinestring:
m_geometries.push_back(new Geographic_multilinestring(
static_cast<const Geographic_multilinestring &>(g)));
break;
case Geometry_type::kMultipolygon:
m_geometries.push_back(new Geographic_multipolygon(
static_cast<const Geographic_multipolygon &>(g)));
break;
default:
DBUG_ASSERT(false); /* purecov: inspected */
}
}
void Geographic_geometrycollection::push_back(Geometry &&g) {
switch (g.type()) {
case Geometry_type::kPoint:
m_geometries.push_back(
new Geographic_point(static_cast<Geographic_point &&>(g)));
break;
case Geometry_type::kLinestring:
m_geometries.push_back(
new Geographic_linestring(static_cast<Geographic_linestring &&>(g)));
break;
case Geometry_type::kPolygon:
m_geometries.push_back(
new Geographic_polygon(static_cast<Geographic_polygon &&>(g)));
break;
case Geometry_type::kGeometrycollection:
m_geometries.push_back(new Geographic_geometrycollection(
static_cast<Geographic_geometrycollection &&>(g)));
break;
case Geometry_type::kMultipoint:
m_geometries.push_back(
new Geographic_multipoint(static_cast<Geographic_multipoint &&>(g)));
break;
case Geometry_type::kMultilinestring:
m_geometries.push_back(new Geographic_multilinestring(
static_cast<Geographic_multilinestring &&>(g)));
break;
case Geometry_type::kMultipolygon:
m_geometries.push_back(new Geographic_multipolygon(
static_cast<Geographic_multipolygon &&>(g)));
break;
default:
DBUG_ASSERT(false); /* purecov: inspected */
}
}
bool Geographic_geometrycollection::empty() const {
return m_geometries.empty();
}
bool Cartesian_multipoint::accept(Geometry_visitor *v) {
if (!v->visit_enter(this) && m_points.size() > 0) {
if (m_points[0].accept(v)) return true;
for (decltype(m_points)::size_type i = 1; i < m_points.size(); i++) {
if (v->visit(this) || m_points[i].accept(v)) return true;
}
}
return v->visit_leave(this);
}
void Cartesian_multipoint::push_back(const Geometry &pt) {
DBUG_ASSERT(pt.coordinate_system() == Coordinate_system::kCartesian);
m_points.push_back(static_cast<const Cartesian_point &>(pt));
}
void Cartesian_multipoint::push_back(Geometry &&pt) {
DBUG_ASSERT(pt.coordinate_system() == Coordinate_system::kCartesian);
m_points.push_back(static_cast<Cartesian_point &&>(pt));
}
bool Cartesian_multipoint::empty() const { return m_points.empty(); }
bool Geographic_multipoint::accept(Geometry_visitor *v) {
if (!v->visit_enter(this) && m_points.size() > 0) {
if (m_points[0].accept(v)) return true;
for (decltype(m_points)::size_type i = 1; i < m_points.size(); i++) {
if (v->visit(this) || m_points[i].accept(v)) return true;
}
}
return v->visit_leave(this);
}
void Geographic_multipoint::push_back(const Geometry &pt) {
DBUG_ASSERT(pt.coordinate_system() == Coordinate_system::kGeographic);
m_points.push_back(static_cast<const Geographic_point &>(pt));
}
void Geographic_multipoint::push_back(Geometry &&pt) {
DBUG_ASSERT(pt.coordinate_system() == Coordinate_system::kGeographic);
m_points.push_back(static_cast<Geographic_point &&>(pt));
}
bool Geographic_multipoint::empty() const { return m_points.empty(); }
bool Cartesian_multilinestring::accept(Geometry_visitor *v) {
if (!v->visit_enter(this) && m_linestrings.size() > 0) {
if (m_linestrings[0].accept(v)) return true;
for (decltype(m_linestrings)::size_type i = 1; i < m_linestrings.size();
i++) {
if (v->visit(this) || m_linestrings[i].accept(v)) return true;
}
}
return v->visit_leave(this);
}
void Cartesian_multilinestring::push_back(const Geometry &ls) {
DBUG_ASSERT(ls.coordinate_system() == Coordinate_system::kCartesian);
m_linestrings.push_back(static_cast<const Cartesian_linestring &>(ls));
}
void Cartesian_multilinestring::push_back(Geometry &&ls) {
DBUG_ASSERT(ls.coordinate_system() == Coordinate_system::kCartesian);
m_linestrings.push_back(static_cast<Cartesian_linestring &&>(ls));
}
bool Cartesian_multilinestring::empty() const { return m_linestrings.empty(); }
bool Geographic_multilinestring::accept(Geometry_visitor *v) {
if (!v->visit_enter(this) && m_linestrings.size() > 0) {
if (m_linestrings[0].accept(v)) return true;
for (decltype(m_linestrings)::size_type i = 1; i < m_linestrings.size();
i++) {
if (v->visit(this) || m_linestrings[i].accept(v)) return true;
}
}
return v->visit_leave(this);
}
void Geographic_multilinestring::push_back(const Geometry &ls) {
DBUG_ASSERT(ls.coordinate_system() == Coordinate_system::kGeographic);
m_linestrings.push_back(static_cast<const Geographic_linestring &>(ls));
}
void Geographic_multilinestring::push_back(Geometry &&ls) {
DBUG_ASSERT(ls.coordinate_system() == Coordinate_system::kGeographic);
m_linestrings.push_back(static_cast<Geographic_linestring &&>(ls));
}
bool Geographic_multilinestring::empty() const { return m_linestrings.empty(); }
bool Cartesian_multipolygon::accept(Geometry_visitor *v) {
if (!v->visit_enter(this) && m_polygons.size() > 0) {
if (m_polygons[0].accept(v)) return true;
for (decltype(m_polygons)::size_type i = 1; i < m_polygons.size(); i++) {
if (v->visit(this) || m_polygons[i].accept(v)) return true;
}
}
return v->visit_leave(this);
}
void Cartesian_multipolygon::push_back(const Geometry &py) {
DBUG_ASSERT(py.coordinate_system() == Coordinate_system::kCartesian);
m_polygons.push_back(static_cast<const Cartesian_polygon &>(py));
}
void Cartesian_multipolygon::push_back(Geometry &&py) {
DBUG_ASSERT(py.coordinate_system() == Coordinate_system::kCartesian);
m_polygons.push_back(static_cast<Cartesian_polygon &&>(py));
}
bool Cartesian_multipolygon::empty() const { return m_polygons.empty(); }
bool Geographic_multipolygon::accept(Geometry_visitor *v) {
if (!v->visit_enter(this) && m_polygons.size() > 0) {
if (m_polygons[0].accept(v)) return true;
for (decltype(m_polygons)::size_type i = 1; i < m_polygons.size(); i++) {
if (v->visit(this) || m_polygons[i].accept(v)) return true;
}
}
return v->visit_leave(this);
}
void Geographic_multipolygon::push_back(const Geometry &py) {
DBUG_ASSERT(py.coordinate_system() == Coordinate_system::kGeographic);
m_polygons.push_back(static_cast<const Geographic_polygon &>(py));
}
void Geographic_multipolygon::push_back(Geometry &&py) {
DBUG_ASSERT(py.coordinate_system() == Coordinate_system::kGeographic);
m_polygons.push_back(static_cast<Geographic_polygon &&>(py));
}
bool Geographic_multipolygon::empty() const { return m_polygons.empty(); }
const char *type_to_name(Geometry_type type) {
switch (type) {
case Geometry_type::kPoint:
return "POINT";
case Geometry_type::kLinestring:
return "LINESTRING";
case Geometry_type::kPolygon:
return "POLYGON";
case Geometry_type::kGeometrycollection:
return "GEOMCOLLECTION";
case Geometry_type::kMultipoint:
return "MULTIPOINT";
case Geometry_type::kMultilinestring:
return "MULTILINESTRING";
case Geometry_type::kMultipolygon:
return "MULTIPOLYGON";
default:
/* purecov: begin inspected */
DBUG_ASSERT(false);
return "UNKNOWN";
/* purecov: end */
}
}
} // namespace gis