/********************************************************************** * * GEOS - Geometry Engine Open Source * http://geos.osgeo.org * * Copyright (C) 2024 ISciences, LLC * Copyright (C) 2011 Sandro Santilli * Copyright (C) 2005 2006 Refractions Research Inc. * Copyright (C) 2001-2002 Vivid Solutions Inc. * * This is free software; you can redistribute and/or modify it under * the terms of the GNU Lesser General Public Licence as published * by the Free Software Foundation. * See the COPYING file for more information. * **********************************************************************/ #pragma once #include #include #include #include #include #include #include namespace geos { namespace geom { template class SurfaceImpl : public Surface { protected: SurfaceImpl(const SurfaceImpl& p) : Surface(p), shell(static_cast(p.shell->clone().release())), holes(p.holes.size()) { for (std::size_t i = 0; i < holes.size(); ++i) { holes[i].reset(static_cast(p.holes[i]->clone().release())); } } /** * Constructs a Surface with the given exterior * and interior boundaries. * * @param newShell the outer boundary of the new Polygon, * or null or an empty * Curve if the empty geometry * is to be created. * * @param newHoles the rings defining the inner * boundaries of the new Surface, or * null or empty Curve * if the empty geometry is to be created. * * @param newFactory the GeometryFactory used to create this geometry * * Polygon will take ownership of shell and hole curves */ SurfaceImpl(std::unique_ptr&& newShell, const GeometryFactory& newFactory) : Surface(&newFactory), shell(std::move(newShell)) { if (shell == nullptr) { shell.reset(static_cast(createEmptyRing(newFactory).release())); } } SurfaceImpl(std::unique_ptr&& newShell, std::vector>&& newHoles, const GeometryFactory& newFactory) : Surface(&newFactory), shell(std::move(newShell)), holes(std::move(newHoles)) { if (shell == nullptr) { shell.reset(static_cast(createEmptyRing(newFactory).release())); } if(shell->isEmpty() && hasNonEmptyElements(&holes)) { throw geos::util::IllegalArgumentException("shell is empty but holes are not"); } if (hasNullElements(&holes)) { throw geos::util::IllegalArgumentException("holes must not contain null elements"); } } public: const RingType* getExteriorRing() const override { return shell.get(); } RingType* getExteriorRing() override { return shell.get(); } const RingType* getInteriorRingN(std::size_t n) const override { return holes[n].get(); } RingType* getInteriorRingN(std::size_t n) override { return holes[n].get(); } size_t getNumInteriorRing() const override { return holes.size(); } /** * \brief * Take ownership of this Surface's exterior ring. * After releasing the exterior ring, the Surface should be * considered in a moved-from state and should not be accessed, * except to release the interior rings (if desired.) * @return exterior ring */ std::unique_ptr releaseExteriorRing() { return std::move(shell); } /** * \brief * Take ownership of this Surfaces's interior rings. * After releasing the rings, the Surface should be * considered in a moved-from state and should not be accessed, * except to release the exterior ring (if desired.) * @return vector of rings (may be empty) */ std::vector> releaseInteriorRings() { return std::move(holes); } protected: std::unique_ptr shell; std::vector> holes; }; } }