Fishnet 2.0.1
Framework for Graph-Based Analysis of GIS Vector Data
Loading...
Searching...
No Matches
VectorLayer.hpp
Go to the documentation of this file.
1#pragma once
2#include <ranges>
3#include <utility>
4#include <vector>
5#include <algorithm>
6#include <expected>
7
12#include <fishnet/Either.hpp>
13
14#include "FieldType.hpp"
15#include "Feature.hpp"
16
17#include <gdal/ogr_spatialref.h>
18
19
20namespace fishnet {
27template<geometry::AnyGeometry G>
29private:
30 OGRSpatialReference spatialRef;
31 std::vector<Feature<G>> features;
32
37 std::unordered_map<std::string,FieldDefinitionVariant> fields;
38
39 using error_type = std::string; // error type for std::expected
40
46 constexpr void remove(util::Predicate<Feature<G>> auto && predicate)noexcept {
47 const auto removed = std::ranges::remove_if(this->features,predicate);
48 this->features.erase(removed.begin(),removed.end());
49 }
50
51 template<geometry::AnyGeometry T>
52 friend class VectorLayer; // allow other VectorLayers to access the private members
53
54public:
55 using geometry_type = G;
57
62 VectorLayer() = default;
63
69 explicit VectorLayer(OGRSpatialReference spatialReference):spatialRef(std::move(spatialReference)){}
70
71 constexpr size_t size() const noexcept {
72 return this->features.size();
73 }
74
75 constexpr bool isEmpty() const noexcept {
76 return this->size() == 0;
77 }
78
79 constexpr util::view_of<G> auto getGeometries() const noexcept {
80 return std::views::all(features) | std::views::transform([](const auto & feature){return feature.getGeometry();});
81 }
82
83 constexpr util::view_of<Feature<G>> auto getFeatures() const noexcept {
84 return std::views::all(features);
85 }
86
87 constexpr util::view_of<Feature<G>> auto getFeatures() noexcept {
88 return std::views::all(features);
89 }
90
91 constexpr const OGRSpatialReference & getSpatialReference() const noexcept {
92 return this->spatialRef;
93 }
94
95 constexpr void setSpatialReference(const OGRSpatialReference & spatialReference) noexcept {
96 this->spatialRef = spatialReference;
97 }
98
99 constexpr void addGeometry(const G & g) noexcept {
101 }
102
103 constexpr void addGeometry(G && g) noexcept {
104 addFeature(Feature<G>(std::move(g)));
105 }
106
107 constexpr void addAllGeometry(util::forward_range_of<G> auto && geometries) noexcept {
108 for(auto && geometry:geometries){
109 this->addGeometry(std::forward<G>(geometry));
110 }
111 }
112
120 constexpr bool containsGeometry(const G & g) const noexcept {
121 return std::ranges::find_if(this->features,[&g](const auto & feature){return feature.getGeometry() == g;}) != std::ranges::end(this->features);
122 }
123
124
125 constexpr void removeGeometry(const G & g) noexcept {
126 remove( [&g](const auto & feature){return feature.getGeometry() == g;});
127 }
128
129 constexpr void addFeature(Feature<G> && feature) noexcept {
130 features.push_back(std::forward<Feature<G>>(feature));
131 }
132
133 constexpr void addFeature(const Feature<G> & feature) noexcept {
134 features.push_back(feature);
135 }
136
137 constexpr void addFeatures(util::forward_range_of<Feature<G>> auto && features) noexcept {
138 for(auto && feature:features){
139 this->addFeature(std::forward<Feature<G>>(feature));
140 }
141 }
142
143 constexpr bool containsFeature(const Feature<G> & feature) noexcept {
144 return std::ranges::contains(this->features, feature);
145 }
146
147 constexpr void removeFeature(const Feature<G> & feature) noexcept {
148 remove([&feature](const auto & f){return f==feature;});
149 }
150
159 template<FieldValueType T>
160 [[nodiscard]] constexpr fishnet::Either<FieldDefinition<T>,error_type> addField(const std::string & fieldName, const std::optional<int> & fieldID = std::nullopt) noexcept {
161 if(fieldName.length() > 10){
162 return std::unexpected("Field name \""+ fieldName+"\" must not exceed a length of 10 characters");
163 }
164 if(this->fields.contains(fieldName))
165 return std::unexpected("Field \"" + fieldName + "\" already exists");
166
167 FieldDefinition<T> field = fieldID.transform([&fieldName](int id) { return FieldDefinition<T>(fieldName, id); }).value_or(FieldDefinition<T>(fieldName));
168 this->fields.emplace(fieldName, field);
169 return field;
170 }
171
172 constexpr fishnet::Either<FieldDefinition<int>,error_type> addIntegerField(const std::string & fieldName, const std::optional<int> & fieldID = std::nullopt) noexcept {
173 return addField<int>(fieldName,fieldID);
174 }
175
176 constexpr fishnet::Either<FieldDefinition<double>,error_type> addDoubleField(const std::string & fieldName, const std::optional<int> & fieldID = std::nullopt) noexcept {
177 return addField<double>(fieldName,fieldID);
178 }
179
180 constexpr fishnet::Either<FieldDefinition<std::string>,error_type> addTextField(const std::string & fieldName, const std::optional<int> & fieldID = std::nullopt) noexcept {
181 return addField<std::string>(fieldName,fieldID);
182 }
183
184 constexpr fishnet::Either<FieldDefinition<size_t>,error_type> addSizeField(const std::string & fieldName, const std::optional<int> & fieldID = std::nullopt) noexcept {
185 return addField<size_t>(fieldName,fieldID);
186 }
187
188 constexpr bool hasField(const std::string & fieldName) const noexcept {
189 return this->fields.contains(fieldName);
190 }
191
192 constexpr void removeField(const std::string & fieldName) noexcept {
193 this->fields.erase(fieldName);
194 }
195
196 constexpr void clearFields() noexcept {
197 fields.clear();
198 }
199
200 template<geometry::AnyGeometry T>
201 constexpr void copyFields(VectorLayer<T> & other) const noexcept {
202 for(auto [fieldName,fieldVariant]:fields){
203 other.fields.try_emplace(fieldName,fieldVariant);
204 }
205 }
206
207 template<FieldValueType T>
208 constexpr fishnet::Either<FieldDefinition<T>,error_type> getField(const std::string & fieldName) const noexcept {
209 fishnet::Either<FieldDefinition<T>,error_type> optFieldDef = std::unexpected(std::string("Field \"" + fieldName + "\" does not exist"));
210 if(not fields.contains(fieldName)) {
211 return optFieldDef;
212 }
213 // test whether the FieldVariant with name == fieldName has the correct value_type
214 std::visit([&optFieldDef](auto && fieldVariant){
215 using U = typename std::decay_t<decltype(fieldVariant)>::value_type;
216 if constexpr(std::same_as<T,U>){
217 optFieldDef = fieldVariant;
218 }
219 },fields.at(fieldName));
220 return optFieldDef;
221 }
222
223 constexpr fishnet::Either<FieldDefinition<double>,error_type> getDoubleField(const std::string & fieldName) const noexcept {
224 return getField<double>(fieldName);
225 }
226
227 constexpr fishnet::Either<FieldDefinition<int>,error_type> getIntegerField(const std::string & fieldName) const noexcept {
228 return getField<int>(fieldName);
229 }
230
231 constexpr fishnet::Either<FieldDefinition<size_t>,error_type> getSizeField(const std::string & fieldName) const noexcept {
232 return getField<size_t>(fieldName);
233 }
234
235 constexpr fishnet::Either<FieldDefinition<std::string>,error_type> getTextField(const std::string & fieldName) const noexcept {
236 return getField<std::string>(fieldName);
237 }
238
239 constexpr const std::unordered_map<std::string,FieldDefinitionVariant> & getFieldsMap() const noexcept {
240 return this->fields;
241 }
242};
243}
Definition Either.hpp:11
Feature implementation storing a geometry and associated attributes.
Definition Feature.hpp:51
Field definition implementation. Defines name, id and data type of a field.
Definition FieldDefinition.hpp:43
Stores the geometries, wrapped in features (which hold the field values / attributes) Keeps track of ...
Definition VectorLayer.hpp:28
constexpr void setSpatialReference(const OGRSpatialReference &spatialReference) noexcept
Definition VectorLayer.hpp:95
constexpr fishnet::Either< FieldDefinition< T >, error_type > addField(const std::string &fieldName, const std::optional< int > &fieldID=std::nullopt) noexcept
Add a field of generic type T to the layer. A field is referenced exclusively by its name.
Definition VectorLayer.hpp:160
constexpr void addAllGeometry(util::forward_range_of< G > auto &&geometries) noexcept
Definition VectorLayer.hpp:107
constexpr fishnet::Either< FieldDefinition< T >, error_type > getField(const std::string &fieldName) const noexcept
Definition VectorLayer.hpp:208
constexpr bool isEmpty() const noexcept
Definition VectorLayer.hpp:75
constexpr fishnet::Either< FieldDefinition< std::string >, error_type > addTextField(const std::string &fieldName, const std::optional< int > &fieldID=std::nullopt) noexcept
Definition VectorLayer.hpp:180
constexpr void removeFeature(const Feature< G > &feature) noexcept
Definition VectorLayer.hpp:147
constexpr void removeGeometry(const G &g) noexcept
Definition VectorLayer.hpp:125
G geometry_type
Definition VectorLayer.hpp:55
constexpr util::view_of< G > auto getGeometries() const noexcept
Definition VectorLayer.hpp:79
constexpr void clearFields() noexcept
Definition VectorLayer.hpp:196
constexpr bool hasField(const std::string &fieldName) const noexcept
Definition VectorLayer.hpp:188
constexpr fishnet::Either< FieldDefinition< size_t >, error_type > addSizeField(const std::string &fieldName, const std::optional< int > &fieldID=std::nullopt) noexcept
Definition VectorLayer.hpp:184
constexpr fishnet::Either< FieldDefinition< double >, error_type > addDoubleField(const std::string &fieldName, const std::optional< int > &fieldID=std::nullopt) noexcept
Definition VectorLayer.hpp:176
constexpr fishnet::Either< FieldDefinition< size_t >, error_type > getSizeField(const std::string &fieldName) const noexcept
Definition VectorLayer.hpp:231
constexpr size_t size() const noexcept
Definition VectorLayer.hpp:71
constexpr const OGRSpatialReference & getSpatialReference() const noexcept
Definition VectorLayer.hpp:91
constexpr void addGeometry(G &&g) noexcept
Definition VectorLayer.hpp:103
constexpr void addFeature(Feature< G > &&feature) noexcept
Definition VectorLayer.hpp:129
constexpr void addFeatures(util::forward_range_of< Feature< G > > auto &&features) noexcept
Definition VectorLayer.hpp:137
constexpr util::view_of< Feature< G > > auto getFeatures() noexcept
Definition VectorLayer.hpp:87
constexpr const std::unordered_map< std::string, FieldDefinitionVariant > & getFieldsMap() const noexcept
Definition VectorLayer.hpp:239
constexpr void addGeometry(const G &g) noexcept
Definition VectorLayer.hpp:99
constexpr fishnet::Either< FieldDefinition< int >, error_type > addIntegerField(const std::string &fieldName, const std::optional< int > &fieldID=std::nullopt) noexcept
Definition VectorLayer.hpp:172
constexpr fishnet::Either< FieldDefinition< int >, error_type > getIntegerField(const std::string &fieldName) const noexcept
Definition VectorLayer.hpp:227
constexpr bool containsFeature(const Feature< G > &feature) noexcept
Definition VectorLayer.hpp:143
constexpr bool containsGeometry(const G &g) const noexcept
checks if any geometry is equal to the passed geometry WARNING: this method might be slow,...
Definition VectorLayer.hpp:120
constexpr fishnet::Either< FieldDefinition< double >, error_type > getDoubleField(const std::string &fieldName) const noexcept
Definition VectorLayer.hpp:223
constexpr void removeField(const std::string &fieldName) noexcept
Definition VectorLayer.hpp:192
constexpr fishnet::Either< FieldDefinition< std::string >, error_type > getTextField(const std::string &fieldName) const noexcept
Definition VectorLayer.hpp:235
VectorLayer()=default
Construct a new incomplete Vector Layer object.
constexpr void addFeature(const Feature< G > &feature) noexcept
Definition VectorLayer.hpp:133
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
VectorLayer(OGRSpatialReference spatialReference)
Construct a new empty Vector Layer object.
Definition VectorLayer.hpp:69
Definition FunctionalConcepts.hpp:36
Definition CollectionConcepts.hpp:27
Definition CollectionConcepts.hpp:45
Definition BFSClustering.hpp:5
STL namespace.