#ifndef SQL_GIS_GEOMETRIES_CS_H_INCLUDED #define SQL_GIS_GEOMETRIES_CS_H_INCLUDED // Copyright (c) 2017, 2024, Oracle and/or its affiliates. // // 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 designed to work 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 either included with // the program or referenced in the documentation. // // 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 declares the coordinate system specific subclasses of /// the geometry class hierarchy. The rest of the hierarchy is defined /// in geometries.h. /// /// For most of the server, including geometries.h should be /// enough. This header is only needed if the code needs to access /// coordinate system specific members. /// /// @see geometries.h #include #include "sql/gis/geometries.h" #include "sql/malloc_allocator.h" namespace gis { /// A Cartesian 2d point. class Cartesian_point : public Point { public: Cartesian_point() = default; Cartesian_point(double x, double y) : Point(x, y) {} Coordinate_system coordinate_system() const override { return Coordinate_system::kCartesian; } Cartesian_point *clone() const override { return new Cartesian_point(*this); } }; /// A geographic (ellipsoidal) 2d point. class Geographic_point : public Point { public: Geographic_point() = default; Geographic_point(double x, double y) : Point(x, y) {} Coordinate_system coordinate_system() const override { return Coordinate_system::kGeographic; } Geographic_point *clone() const override { return new Geographic_point(*this); } }; /// A Cartesian 2d linestring. class Cartesian_linestring : public Linestring { protected: /// String of points constituting the linestring. /// /// The line starts in the first point, goes through all intermediate points, /// and ends in the last point. std::vector> m_points; public: typedef decltype(m_points)::value_type value_type; typedef decltype(m_points)::iterator iterator; typedef decltype(m_points)::const_iterator const_iterator; Cartesian_linestring() : m_points(Malloc_allocator( key_memory_Geometry_objects_data)) {} Coordinate_system coordinate_system() const override { return Coordinate_system::kCartesian; } bool accept(Geometry_visitor *v) override; void push_back(const Point &pt) override; void push_back(Point &&pt) override; void pop_front() override { m_points.erase(m_points.begin()); } bool empty() const override; std::size_t size() const override { return m_points.size(); } void resize(std::size_t count) { m_points.resize(count); } void clear() noexcept override { m_points.clear(); } Cartesian_linestring *clone() const override { return new Cartesian_linestring(*this); } Cartesian_point &back() override { return m_points.back(); } const Cartesian_point &back() const override { return m_points.back(); } iterator begin() noexcept { return m_points.begin(); } const_iterator begin() const noexcept { return m_points.begin(); } iterator end() noexcept { return m_points.end(); } const_iterator end() const noexcept { return m_points.end(); } Cartesian_point &front() override { return m_points.front(); } const Cartesian_point &front() const override { return m_points.front(); } Cartesian_point &operator[](std::size_t i) override { return m_points[i]; } const Cartesian_point &operator[](std::size_t i) const override { return m_points[i]; } }; /// A geographic (ellipsoidal) 2d linestring. /// /// The linestring follows the geodetic between each pair of points. class Geographic_linestring : public Linestring { protected: /// String of points constituting the linestring. /// /// The line starts in the first point, goes through all intermediate points, /// and ends in the last point. std::vector> m_points; public: typedef decltype(m_points)::value_type value_type; typedef decltype(m_points)::iterator iterator; typedef decltype(m_points)::const_iterator const_iterator; Geographic_linestring() : m_points(Malloc_allocator( key_memory_Geometry_objects_data)) {} Coordinate_system coordinate_system() const override { return Coordinate_system::kGeographic; } bool accept(Geometry_visitor *v) override; void push_back(const Point &pt) override; void push_back(Point &&pt) override; void pop_front() override { m_points.erase(m_points.begin()); } bool empty() const override; std::size_t size() const override { return m_points.size(); } void resize(std::size_t count) { m_points.resize(count); } void clear() noexcept override { m_points.clear(); } Geographic_linestring *clone() const override { return new Geographic_linestring(*this); } Geographic_point &back() override { return m_points.back(); } const Geographic_point &back() const override { return m_points.back(); } iterator begin() noexcept { return m_points.begin(); } const_iterator begin() const noexcept { return m_points.begin(); } iterator end() noexcept { return m_points.end(); } const_iterator end() const noexcept { return m_points.end(); } Geographic_point &front() override { return m_points.front(); } const Geographic_point &front() const override { return m_points.front(); } Geographic_point &operator[](std::size_t i) override { return m_points[i]; } const Geographic_point &operator[](std::size_t i) const override { return m_points[i]; } }; /// A Cartesian 2d linear ring. class Cartesian_linearring : public Cartesian_linestring, public Linearring { public: Geometry_type type() const override { return Linearring::type(); } Coordinate_system coordinate_system() const override { return Coordinate_system::kCartesian; } bool accept(Geometry_visitor *v) override; bool is_empty() const override { return Cartesian_linestring::is_empty(); } void push_back(const gis::Point &pt) override { Cartesian_linestring::push_back(pt); } void push_back(gis::Point &&pt) override { Cartesian_linestring::push_back(std::forward(pt)); } void pop_front() override { Cartesian_linestring::pop_front(); } bool empty() const override { return Cartesian_linestring::empty(); } std::size_t size() const override { return Cartesian_linestring::size(); } void clear() noexcept override { Cartesian_linestring::clear(); } /// This implementation of clone() uses a broader return type than /// other implementations. This is due to the restraint in some compilers, /// such as cl.exe, that overriding functions with ambiguous bases must have /// covariant return types. Cartesian_linestring *clone() const override { return new Cartesian_linearring(*this); } Cartesian_point &back() override { return Cartesian_linestring::back(); } const Cartesian_point &back() const override { return Cartesian_linestring::back(); } Cartesian_point &front() override { return Cartesian_linestring::front(); } const Cartesian_point &front() const override { return Cartesian_linestring::front(); } Cartesian_point &operator[](std::size_t i) override { return Cartesian_linestring::operator[](i); } const Cartesian_point &operator[](std::size_t i) const override { return Cartesian_linestring::operator[](i); } }; /// A geographic (ellipsoidal) 2d linear ring. class Geographic_linearring : public Geographic_linestring, public Linearring { public: Geometry_type type() const override { return Linearring::type(); } Coordinate_system coordinate_system() const override { return Coordinate_system::kGeographic; } bool accept(Geometry_visitor *v) override; bool is_empty() const override { return Geographic_linestring::is_empty(); } void push_back(const gis::Point &pt) override { Geographic_linestring::push_back(pt); } void push_back(gis::Point &&pt) override { Geographic_linestring::push_back(std::forward(pt)); } void pop_front() override { Geographic_linestring::pop_front(); } bool empty() const override { return Geographic_linestring::empty(); } std::size_t size() const override { return Geographic_linestring::size(); } void clear() noexcept override { Geographic_linestring::clear(); } /// This implementation of clone() uses a broader return type than /// other implementations. This is due to the restraint in some compilers, /// such as cl.exe, that overriding functions with ambiguous bases must have /// covariant return types. Geographic_linestring *clone() const override { return new Geographic_linearring(*this); } Geographic_point &back() override { return Geographic_linestring::back(); } const Geographic_point &back() const override { return Geographic_linestring::back(); } Geographic_point &front() override { return Geographic_linestring::front(); } const Geographic_point &front() const override { return Geographic_linestring::front(); } Geographic_point &operator[](std::size_t i) override { return Geographic_linestring::operator[](i); } const Geographic_point &operator[](std::size_t i) const override { return Geographic_linestring::operator[](i); } }; /// A Cartesian 2d polygon. class Cartesian_polygon : public Polygon { private: /// Exterior ring. Cartesian_linearring m_exterior_ring; /// Interior rings (holes). std::vector> m_interior_rings; public: Cartesian_polygon() : m_interior_rings(Malloc_allocator( key_memory_Geometry_objects_data)) {} Coordinate_system coordinate_system() const override { return Coordinate_system::kCartesian; } bool accept(Geometry_visitor *v) override; void push_back(const Linearring &lr) override; void push_back(Linearring &&lr) override; bool empty() const override; Cartesian_polygon *clone() const override { return new Cartesian_polygon(*this); } /// Get list of interior rings. /// /// This function is used by the interface to Boost.Geometry. /// /// @return The list of interior rings decltype(m_interior_rings) &interior_rings(); /// Get list of interior rings. /// /// This function is used by the interface to Boost.Geometry. /// /// @return The list of interior rings decltype(m_interior_rings) const &const_interior_rings() const; std::size_t size() const override; /// Get the exterior ring. /// /// This function is used by the interface to Boost.Geometry. /// /// @return The exterior ring. Cartesian_linearring &cartesian_exterior_ring() const; Linearring &exterior_ring() override { return m_exterior_ring; } Linearring &interior_ring(std::size_t n) override; }; /// A geographic (ellipsoidal) 2d polygon. class Geographic_polygon : public Polygon { private: /// Exterior ring. Geographic_linearring m_exterior_ring; /// Interior rings (holes). std::vector> m_interior_rings; public: Geographic_polygon() : m_interior_rings(Malloc_allocator( key_memory_Geometry_objects_data)) {} Coordinate_system coordinate_system() const override { return Coordinate_system::kGeographic; } bool accept(Geometry_visitor *v) override; void push_back(const Linearring &lr) override; void push_back(Linearring &&lr) override; bool empty() const override; Geographic_polygon *clone() const override { return new Geographic_polygon(*this); } /// Get list of interior rings. /// /// This function is used by the interface to Boost.Geometry. /// /// @return The list of interior rings decltype(m_interior_rings) &interior_rings(); /// Get list of interior rings. /// /// This function is used by the interface to Boost.Geometry. /// /// @return The list of interior rings decltype(m_interior_rings) const &const_interior_rings() const; std::size_t size() const override; /// Get the exterior ring. /// /// This function is used by the interface to Boost.Geometry. /// /// @return The exterior ring. Geographic_linearring &geographic_exterior_ring() const; Linearring &exterior_ring() override { return m_exterior_ring; } Linearring &interior_ring(std::size_t n) override; }; /// A Cartesian 2d geometry collection. class Cartesian_geometrycollection : public Geometrycollection { private: /// List of geometries in the collection. std::vector> m_geometries; public: typedef decltype(m_geometries)::iterator iterator; typedef decltype(m_geometries)::const_iterator const_iterator; Cartesian_geometrycollection() : m_geometries( Malloc_allocator(key_memory_Geometry_objects_data)) {} Cartesian_geometrycollection(const Cartesian_geometrycollection &gc); Cartesian_geometrycollection(Cartesian_geometrycollection &&gc) noexcept : m_geometries( Malloc_allocator(key_memory_Geometry_objects_data)) { m_geometries = std::move(gc.m_geometries); } ~Cartesian_geometrycollection() override { for (Geometry *g : m_geometries) { delete g; } } Coordinate_system coordinate_system() const override { return Coordinate_system::kCartesian; } bool accept(Geometry_visitor *v) override; bool is_empty() const override { for (const auto g : m_geometries) { if (!g->is_empty()) return false; } return true; } void pop_front() override { delete *m_geometries.begin(); m_geometries.erase(m_geometries.begin()); } void push_back(const Geometry &g) override; void push_back(Geometry &&g) override; bool empty() const override; std::size_t size() const override { return m_geometries.size(); } void resize(std::size_t count) override { m_geometries.resize(count); } void clear() noexcept override { m_geometries.clear(); } iterator begin() noexcept { return m_geometries.begin(); } const_iterator begin() const noexcept { return m_geometries.begin(); } iterator end() noexcept { return m_geometries.end(); } const_iterator end() const noexcept { return m_geometries.end(); } Geometry &front() override { return *m_geometries.front(); } const Geometry &front() const override { return *m_geometries.front(); } Geometry &operator[](std::size_t i) override { return *m_geometries[i]; } const Geometry &operator[](std::size_t i) const override { return *m_geometries[i]; } Cartesian_geometrycollection *clone() const override { return new Cartesian_geometrycollection(*this); } }; /// A geographic (ellipsoidal) 2d geometry collection. class Geographic_geometrycollection : public Geometrycollection { private: /// List of geometries in the collection. std::vector> m_geometries; public: typedef decltype(m_geometries)::iterator iterator; typedef decltype(m_geometries)::const_iterator const_iterator; Geographic_geometrycollection() : m_geometries( Malloc_allocator(key_memory_Geometry_objects_data)) {} Geographic_geometrycollection(const Geographic_geometrycollection &gc); Geographic_geometrycollection(Geographic_geometrycollection &&gc) noexcept : m_geometries( Malloc_allocator(key_memory_Geometry_objects_data)) { m_geometries = std::move(gc.m_geometries); } ~Geographic_geometrycollection() override { for (Geometry *g : m_geometries) { delete g; } } Coordinate_system coordinate_system() const override { return Coordinate_system::kGeographic; } bool accept(Geometry_visitor *v) override; bool is_empty() const override { for (const auto g : m_geometries) { if (!g->is_empty()) return false; } return true; } void pop_front() override { delete *m_geometries.begin(); m_geometries.erase(m_geometries.begin()); } void push_back(const Geometry &g) override; void push_back(Geometry &&g) override; bool empty() const override; std::size_t size() const override { return m_geometries.size(); } void resize(std::size_t count) override { m_geometries.resize(count); } void clear() noexcept override { m_geometries.clear(); } iterator begin() noexcept { return m_geometries.begin(); } const_iterator begin() const noexcept { return m_geometries.begin(); } iterator end() noexcept { return m_geometries.end(); } const_iterator end() const noexcept { return m_geometries.end(); } Geometry &front() override { return *m_geometries.front(); } const Geometry &front() const override { return *m_geometries.front(); } Geometry &operator[](std::size_t i) override { return *m_geometries[i]; } const Geometry &operator[](std::size_t i) const override { return *m_geometries[i]; } Geographic_geometrycollection *clone() const override { return new Geographic_geometrycollection(*this); } }; /// A Cartesian 2d multipoint. class Cartesian_multipoint : public Multipoint { private: /// List of points in the collection. std::vector> m_points; public: typedef decltype(m_points)::value_type value_type; typedef decltype(m_points)::iterator iterator; typedef decltype(m_points)::const_iterator const_iterator; Cartesian_multipoint() : m_points(Malloc_allocator( key_memory_Geometry_objects_data)) {} Coordinate_system coordinate_system() const override { return Coordinate_system::kCartesian; } bool accept(Geometry_visitor *v) override; bool is_empty() const override { for (const auto &pt : m_points) { if (!pt.is_empty()) return false; } return true; } void pop_front() override { m_points.erase(m_points.begin()); } void push_back(const Geometry &g) override; void push_back(Geometry &&g) override; bool empty() const override; std::size_t size() const override { return m_points.size(); } void resize(std::size_t count) override { m_points.resize(count); } void clear() noexcept override { m_points.clear(); } iterator begin() noexcept { return m_points.begin(); } const_iterator begin() const noexcept { return m_points.begin(); } iterator end() noexcept { return m_points.end(); } const_iterator end() const noexcept { return m_points.end(); } Cartesian_point &front() override { return m_points.front(); } const Cartesian_point &front() const override { return m_points.front(); } Cartesian_point &operator[](std::size_t i) override { return m_points[i]; } const Cartesian_point &operator[](std::size_t i) const override { return m_points[i]; } Cartesian_multipoint *clone() const override { return new Cartesian_multipoint(*this); } }; /// A geographic (ellipsoidal) 2d multipoint. class Geographic_multipoint : public Multipoint { private: /// List of points in the collection. std::vector> m_points; public: typedef decltype(m_points)::value_type value_type; typedef decltype(m_points)::iterator iterator; typedef decltype(m_points)::const_iterator const_iterator; Geographic_multipoint() : m_points(Malloc_allocator( key_memory_Geometry_objects_data)) {} Coordinate_system coordinate_system() const override { return Coordinate_system::kGeographic; } bool accept(Geometry_visitor *v) override; bool is_empty() const override { for (const auto &pt : m_points) { if (!pt.is_empty()) return false; } return true; } void pop_front() override { m_points.erase(m_points.begin()); } void push_back(const Geometry &g) override; void push_back(Geometry &&g) override; bool empty() const override; std::size_t size() const override { return m_points.size(); } void resize(std::size_t count) override { m_points.resize(count); } void clear() noexcept override { m_points.clear(); } iterator begin() noexcept { return m_points.begin(); } const_iterator begin() const noexcept { return m_points.begin(); } iterator end() noexcept { return m_points.end(); } const_iterator end() const noexcept { return m_points.end(); } Geographic_point &front() override { return m_points.front(); } const Geographic_point &front() const override { return m_points.front(); } Geographic_point &operator[](std::size_t i) override { return m_points[i]; } const Geographic_point &operator[](std::size_t i) const override { return m_points[i]; } Geographic_multipoint *clone() const override { return new Geographic_multipoint(*this); } }; /// A Cartesian 2d multilinestring. class Cartesian_multilinestring : public Multilinestring { private: /// List of linestrings in the collection. std::vector> m_linestrings; public: typedef decltype(m_linestrings)::value_type value_type; typedef decltype(m_linestrings)::iterator iterator; typedef decltype(m_linestrings)::const_iterator const_iterator; Cartesian_multilinestring() : m_linestrings(Malloc_allocator( key_memory_Geometry_objects_data)) {} Coordinate_system coordinate_system() const override { return Coordinate_system::kCartesian; } bool accept(Geometry_visitor *v) override; bool is_empty() const override { for (const auto &ls : m_linestrings) { if (!ls.is_empty()) return false; } return true; } void pop_front() override { m_linestrings.erase(m_linestrings.begin()); } void push_back(const Geometry &g) override; void push_back(Geometry &&g) override; bool empty() const override; std::size_t size() const override { return m_linestrings.size(); } void resize(std::size_t count) override { m_linestrings.resize(count); } void clear() noexcept override { m_linestrings.clear(); } Cartesian_linestring &back() { return m_linestrings.back(); } const Cartesian_linestring &back() const { return m_linestrings.back(); } iterator begin() noexcept { return m_linestrings.begin(); } const_iterator begin() const noexcept { return m_linestrings.begin(); } iterator end() noexcept { return m_linestrings.end(); } const_iterator end() const noexcept { return m_linestrings.end(); } Cartesian_linestring &front() override { return m_linestrings.front(); } const Cartesian_linestring &front() const override { return m_linestrings.front(); } Cartesian_linestring &operator[](std::size_t i) override { return m_linestrings[i]; } const Geometry &operator[](std::size_t i) const override { return m_linestrings[i]; } Cartesian_multilinestring *clone() const override { return new Cartesian_multilinestring(*this); } }; /// A geographic (ellipsoidal) 2d multilinestring. class Geographic_multilinestring : public Multilinestring { private: /// List of linestrings in the collection. std::vector> m_linestrings; public: typedef decltype(m_linestrings)::value_type value_type; typedef decltype(m_linestrings)::iterator iterator; typedef decltype(m_linestrings)::const_iterator const_iterator; Geographic_multilinestring() : m_linestrings(Malloc_allocator( key_memory_Geometry_objects_data)) {} Coordinate_system coordinate_system() const override { return Coordinate_system::kGeographic; } bool accept(Geometry_visitor *v) override; bool is_empty() const override { for (const auto &ls : m_linestrings) { if (!ls.is_empty()) return false; } return true; } void pop_front() override { m_linestrings.erase(m_linestrings.begin()); } void push_back(const Geometry &g) override; void push_back(Geometry &&g) override; bool empty() const override; std::size_t size() const override { return m_linestrings.size(); } void resize(std::size_t count) override { m_linestrings.resize(count); } void clear() noexcept override { m_linestrings.clear(); } Geographic_linestring &back() { return m_linestrings.back(); } const Geographic_linestring &back() const { return m_linestrings.back(); } iterator begin() noexcept { return m_linestrings.begin(); } const_iterator begin() const noexcept { return m_linestrings.begin(); } iterator end() noexcept { return m_linestrings.end(); } const_iterator end() const noexcept { return m_linestrings.end(); } Geographic_linestring &front() override { return m_linestrings.front(); } const Geographic_linestring &front() const override { return m_linestrings.front(); } Geographic_linestring &operator[](std::size_t i) override { return m_linestrings[i]; } const Geometry &operator[](std::size_t i) const override { return m_linestrings[i]; } Geographic_multilinestring *clone() const override { return new Geographic_multilinestring(*this); } }; /// A Cartesian 2d multipolygon. class Cartesian_multipolygon : public Multipolygon { private: /// List of polygons in the collection. std::vector> m_polygons; public: typedef decltype(m_polygons)::value_type value_type; typedef decltype(m_polygons)::iterator iterator; typedef decltype(m_polygons)::const_iterator const_iterator; Cartesian_multipolygon() : m_polygons(Malloc_allocator( key_memory_Geometry_objects_data)) {} Coordinate_system coordinate_system() const override { return Coordinate_system::kCartesian; } bool accept(Geometry_visitor *v) override; bool is_empty() const override { for (const auto &py : m_polygons) { if (!py.is_empty()) return false; } return true; } void pop_front() override { m_polygons.erase(m_polygons.begin()); } void push_back(const Geometry &g) override; void push_back(Geometry &&g) override; bool empty() const override; std::size_t size() const override { return m_polygons.size(); } void resize(std::size_t count) override { m_polygons.resize(count); } void clear() noexcept override { m_polygons.clear(); } iterator begin() noexcept { return m_polygons.begin(); } const_iterator begin() const noexcept { return m_polygons.begin(); } iterator end() noexcept { return m_polygons.end(); } const_iterator end() const noexcept { return m_polygons.end(); } Cartesian_polygon &front() override { return m_polygons.front(); } const Cartesian_polygon &front() const override { return m_polygons.front(); } Cartesian_polygon &operator[](std::size_t i) override { return m_polygons[i]; } const Geometry &operator[](std::size_t i) const override { return m_polygons[i]; } Cartesian_multipolygon *clone() const override { return new Cartesian_multipolygon(*this); } }; /// A geographic (ellipsoidal) 2d multipolygon. class Geographic_multipolygon : public Multipolygon { private: /// List of polygons in the collection. std::vector> m_polygons; public: typedef decltype(m_polygons)::value_type value_type; typedef decltype(m_polygons)::iterator iterator; typedef decltype(m_polygons)::const_iterator const_iterator; Geographic_multipolygon() : m_polygons(Malloc_allocator( key_memory_Geometry_objects_data)) {} Coordinate_system coordinate_system() const override { return Coordinate_system::kGeographic; } bool accept(Geometry_visitor *v) override; bool is_empty() const override { for (const auto &py : m_polygons) { if (!py.is_empty()) return false; } return true; } void pop_front() override { m_polygons.erase(m_polygons.begin()); } void push_back(const Geometry &g) override; void push_back(Geometry &&g) override; bool empty() const override; std::size_t size() const override { return m_polygons.size(); } void resize(std::size_t count) override { m_polygons.resize(count); } void clear() noexcept override { m_polygons.clear(); } iterator begin() noexcept { return m_polygons.begin(); } const_iterator begin() const noexcept { return m_polygons.begin(); } iterator end() noexcept { return m_polygons.end(); } const_iterator end() const noexcept { return m_polygons.end(); } Geographic_polygon &front() override { return m_polygons.front(); } const Geographic_polygon &front() const override { return m_polygons.front(); } Geographic_polygon &operator[](std::size_t i) override { return m_polygons[i]; } const Geometry &operator[](std::size_t i) const override { return m_polygons[i]; } Geographic_multipolygon *clone() const override { return new Geographic_multipolygon(*this); } }; } // namespace gis #endif // SQL_GIS_GEOMETRIES_CS_H_INCLUDED