Fishnet 2.0.1
Framework for Graph-Based Analysis of GIS Vector Data
Loading...
Searching...
No Matches
VectorIO.hpp
Go to the documentation of this file.
1#pragma once
5#include <fishnet/Either.hpp>
6#include <fishnet/GISFile.hpp>
7#include <regex>
8
9namespace fishnet::__impl{
17template<typename G,VectorGISFile F, VectorLayerWriter<G,F> VectorLayerWriterType>
18class NonOverwritingVectorLayerWriter {
19private:
20 VectorLayerWriterType writer;
22public:
23 explicit NonOverwritingVectorLayerWriter(VectorLayerWriterType const& writer, fishnet::util::UnaryFunction<F,F> auto && filenameMapper)
24 : writer(std::move(writer)),filenameMapper(std::move(filenameMapper)) {}
25
26 Either<F,std::string> operator()(const VectorLayer<G> & layer, const F & destination) const {
27 F outputFile = destination;
28 if(destination.exists()){
29 outputFile = filenameMapper(destination);
30 }
31 return writer(layer, outputFile);
32 }
33};
34
35template<GISFile F>
36struct IncrementFilenameMapper {
37 F operator()(const F & file) const {
38 F output = file;
39 std::regex endsWithVersionRegex {"_(\\d+)$"};
40 const std::string & currentFilename = file.getPath().stem().string();
41 std::smatch matcher;
42 if(std::regex_search(currentFilename,matcher,endsWithVersionRegex)){
43 size_t splitIndex = currentFilename.find_last_of('_');
44 std::string filename = currentFilename.substr(0,splitIndex);
45 int version = std::stoi(matcher[1].str()) + 1;
46 output.changeFilename(filename+"_"+std::to_string(version));
47 }else {
48 output.appendToFilename("_1");
49 }
50 return output;
51 }
52};
53} // namespace fishnet::__impl
54
56
64template<geometry::AnyGeometry G>
65VectorLayer<G> empty(const OGRSpatialReference & spatialReference) {
66 return VectorLayer<G>(spatialReference);
67}
68
76template<geometry::AnyGeometry G=geometry::OGRGeometryAdapter,geometry::AnyGeometry O>
78 auto layer = empty<G>(source.getSpatialReference());
79 source.copyFields(layer);
80 return layer;
81}
82
92template<geometry::AnyGeometry G,geometry::AnyGeometry O>
93VectorLayer<G> transform(const VectorLayer<O> & source, auto && convert) {
94 auto result = emptyCopy<G>(source);
95 for(const auto & feature : source.getFeatures()){
96 auto geometry = convert(feature.getGeometry());
97 if(not geometry)
98 continue;
99 Feature<G> transformed {std::move(geometry.value())};
100 transformed.copyAttributes(feature);
101 result.addFeature(std::move(transformed));
102 }
103 return result;
104}
105
112template<geometry::OGRLayerGeometry G>
114 return transform<G>(source, [](const auto & geometry){
115 return geometry.template narrowTo<G>();
116 });
117}
118
125template<geometry::AnyGeometry O>
126requires requires(const O & geometry){ geometry.toNative(); }
127auto nativeCopy(const VectorLayer<O> & source) {
128 using G = std::remove_cvref_t<decltype(std::declval<const O&>().toNative())>;
129 return transform<G>(source, [](const auto & geometry){
130 return fishnet::Option<G>(geometry.toNative());
131 });
132}
133
134template<VectorLayerReader Reader>
135auto tryRead(const Reader & reader, const typename Reader::file_type & file) -> std::remove_cvref_t<decltype(reader(file))> {
136 return reader(file);
137}
138
139template<VectorLayerReader Reader>
140auto read(const Reader & reader, const typename Reader::file_type & file) -> std::remove_cvref_t<decltype(tryRead(reader,file).value())> {
141 using F = typename Reader::file_type;
142 using G = typename Reader::geometry_type;
143 static_assert(VectorLayerReader<Reader,F,G>, "Reader does not satisfy VectorLayerReader concept");
144 return tryRead(reader,file).value_or_throw();
145}
146
147template<geometry::OGRLayerGeometry G = geometry::OGRGeometryAdapter>
148VectorLayer<G> read(const Shapefile & shapefile) {
149 return read(ShapefileReader<G>(), shapefile);
150}
151
152template<geometry::OGRLayerGeometry G = geometry::OGRGeometryAdapter>
153VectorLayer<G> read(const GeoPackage & geopackage) {
154 return read(GeoPackageReader<G>(), geopackage);
155}
156
165template<geometry::OGRLayerGeometry G = geometry::OGRGeometryAdapter>
167 auto fileType = getGISFileType(file.getPath());
168 if (not fileType) {
169 return std::unexpected("Unsupported vector file type: " + file.getPath().string());
170 }
171 switch (fileType.value()) {
173 return tryRead(ShapefileReader<G>(), Shapefile(file.getPath()));
176 default:
177 return std::unexpected("Unsupported vector file type: " + file.getPath().string());
178 }
179}
180
189template<geometry::OGRLayerGeometry G = geometry::OGRGeometryAdapter>
191 return tryRead<G>(file).value_or_throw();
192}
193
195 return read<geometry::OGRPolygonAdapter>(vectorFile);
196}
197
198template<geometry::OGRWritableGeometry G,VectorGISFile F>
199Either<F,std::string> tryOverwrite(const VectorLayerWriter<G,F> auto & writer, const VectorLayer<G> & layer, const F & destination){
200 return writer(layer, destination);
201}
202
203template<geometry::OGRWritableGeometry G,VectorGISFile F>
204Either<F,std::string> tryWrite(const VectorLayerWriter<G,F> auto & writer, const VectorLayer<G> & layer, const F & destination){
205 auto nonOverwritingWriter = __impl::NonOverwritingVectorLayerWriter<G,F,std::remove_cvref_t<decltype(writer)>>(writer,__impl::IncrementFilenameMapper<F>());
206 return tryOverwrite(nonOverwritingWriter, layer, destination);
207}
208
209template<geometry::OGRWritableGeometry G,VectorGISFile F>
210F write(const VectorLayerWriter<G,F> auto & writer, const VectorLayer<G> & layer, const F & destination){
211 return tryWrite(writer, layer, destination).value_or_throw();
212}
213
214template<geometry::OGRWritableGeometry G,VectorGISFile F>
215F overwrite(const VectorLayerWriter<G,F> auto & writer, const VectorLayer<G> & layer, const F & destination) {
216 return tryOverwrite(writer, layer, destination).value_or_throw();
217}
218
219template<geometry::OGRWritableGeometry G>
220Shapefile write(const VectorLayer<G> & layer, const Shapefile & destination) {
221 return write(ShapefileWriter<G>(), layer, destination);
222}
223
224template<geometry::OGRWritableGeometry G>
225Shapefile overwrite(const VectorLayer<G> & layer, const Shapefile & destination) {
226 return overwrite(ShapefileWriter<G>(), layer, destination);
227}
228
229template<geometry::OGRWritableGeometry G>
230GeoPackage write(const VectorLayer<G> & layer, const GeoPackage & destination) {
231 return write(GeoPackageWriter<G>(), layer, destination);
232}
233
234template<geometry::OGRWritableGeometry G>
235GeoPackage overwrite(const VectorLayer<G> & layer, const GeoPackage & destination) {
236 return overwrite(GeoPackageWriter<G>(), layer, destination);
237}
238
248template<geometry::OGRWritableGeometry G>
249std::unique_ptr<AbstractVectorFile> write(const VectorLayer<G> & layer, const AbstractVectorFile & destination) {
250 auto fileType = getGISFileType(destination.getPath());
251 if (not fileType) {
252 throw std::runtime_error("Unsupported vector file type for writing: " + destination.getPath().string());
253 }
254 switch (fileType.value()) {
256 auto result = write(layer, Shapefile(destination.getPath()));
257 return std::make_unique<Shapefile>(result.getPath());
258 }
260 auto result = write(layer, GeoPackage(destination.getPath()));
261 return std::make_unique<GeoPackage>(result.getPath());
262 }
263 default:
264 throw std::runtime_error("Unsupported vector file type for writing: " + destination.getPath().string());
265 }
266}
267
277template<geometry::OGRWritableGeometry G>
278std::unique_ptr<AbstractVectorFile> overwrite(const VectorLayer<G> & layer, const AbstractVectorFile & destination) {
279 auto fileType = getGISFileType(destination.getPath());
280 if (not fileType) {
281 throw std::runtime_error("Unsupported vector file type for writing: " + destination.getPath().string());
282 }
283 switch (fileType.value()) {
285 auto result = overwrite(layer, Shapefile(destination.getPath()));
286 return std::make_unique<Shapefile>(result.getPath());
287 }
289 auto result = overwrite(layer, GeoPackage(destination.getPath()));
290 return std::make_unique<GeoPackage>(result.getPath());
291 }
292 default:
293 throw std::runtime_error("Unsupported vector file type for writing: " + destination.getPath().string());
294 }
295}
296
297} // namespace fishnet::VectorIO
const std::filesystem::path & getPath() const noexcept
Definition GISFile.hpp:65
Definition GISFile.hpp:131
Definition Either.hpp:11
Feature implementation storing a geometry and associated attributes.
Definition Feature.hpp:51
constexpr void copyAttributes(const Feature< O > &source) noexcept
Definition Feature.hpp:112
Definition GeoPackageIO.hpp:18
Definition GeoPackageIO.hpp:53
GeoPackage handle.
Definition GeoPackage.hpp:9
Definition Option.hpp:13
Definition ShapefileIO.hpp:18
Definition ShapefileIO.hpp:59
Shapefile handle implementation.
Definition Shapefile.hpp:14
Stores the geometries, wrapped in features (which hold the field values / attributes) Keeps track of ...
Definition VectorLayer.hpp:28
constexpr const OGRSpatialReference & getSpatialReference() const noexcept
Definition VectorLayer.hpp:91
constexpr void copyFields(VectorLayer< T > &other) const noexcept
Definition VectorLayer.hpp:201
constexpr util::view_of< Feature< G > > auto getFeatures() const noexcept
Definition VectorLayer.hpp:83
Interface for reading a VectorLayer from a file.
Definition IOConcepts.hpp:17
Definition IOConcepts.hpp:23
Definition FunctionalConcepts.hpp:9
Definition VectorIO.hpp:55
auto nativeCopy(const VectorLayer< O > &source)
Copy a layer of OGR backed geometries into one of the equivalent fishnet value types.
Definition VectorIO.hpp:127
auto tryRead(const Reader &reader, const typename Reader::file_type &file) -> std::remove_cvref_t< decltype(reader(file))>
Definition VectorIO.hpp:135
VectorLayer< G > emptyCopy(const VectorLayer< O > &source)
Creates an empty VectorLayer with the same spatial reference and fields as the source layer.
Definition VectorIO.hpp:77
VectorLayer< geometry::OGRPolygonAdapter > readPolygonLayer(const AbstractVectorFile &vectorFile)
Definition VectorIO.hpp:194
Either< F, std::string > tryWrite(const VectorLayerWriter< G, F > auto &writer, const VectorLayer< G > &layer, const F &destination)
Definition VectorIO.hpp:204
VectorLayer< G > empty(const OGRSpatialReference &spatialReference)
Creates an empty VectorLayer with the given spatial reference.
Definition VectorIO.hpp:65
VectorLayer< G > narrow(const VectorLayer< geometry::OGRGeometryAdapter > &source)
Bring a layer read without a geometry type into a layer of one.
Definition VectorIO.hpp:113
Either< F, std::string > tryOverwrite(const VectorLayerWriter< G, F > auto &writer, const VectorLayer< G > &layer, const F &destination)
Definition VectorIO.hpp:199
auto read(const Reader &reader, const typename Reader::file_type &file) -> std::remove_cvref_t< decltype(tryRead(reader, file).value())>
Definition VectorIO.hpp:140
F overwrite(const VectorLayerWriter< G, F > auto &writer, const VectorLayer< G > &layer, const F &destination)
Definition VectorIO.hpp:215
VectorLayer< G > transform(const VectorLayer< O > &source, auto &&convert)
Copy a layer into one of another geometry type, carrying its spatial reference, fields and attributes...
Definition VectorIO.hpp:93
F write(const VectorLayerWriter< G, F > auto &writer, const VectorLayer< G > &layer, const F &destination)
Definition VectorIO.hpp:210
std::function< R(const T &)> UnaryFunction_t
Definition FunctionalConcepts.hpp:12
static fishnet::Option< GISFileType > getGISFileType(const std::filesystem::path &path)
Definition GISFile.hpp:18
STL namespace.
static string to_string(fishnet::geometry::GeometryType type) noexcept
Definition GeometryBase.hpp:22