Fishnet 2.0.1
Framework for Graph-Based Analysis of GIS Vector Data
Loading...
Searching...
No Matches
Feature.hpp
Go to the documentation of this file.
1#pragma once
2#include <algorithm>
3#include <fishnet/Option.hpp>
6#include "FieldType.hpp"
7#include "FieldDefinition.hpp"
8
9namespace fishnet::__impl {
10
15class FieldValue {
16 private:
17 FieldType value;
18 int fieldID;
19 public:
20 template<FieldValueType T>
21 FieldValue(T value,int fieldID):value(value),fieldID(fieldID) {}
22
23 template<FieldValueType T>
24 T getValue() const {
25 return std::get<T>(value);
26 }
27
28 [[nodiscard]]constexpr FieldType getVariant() const noexcept {
29 return value;
30 }
31
32 [[nodiscard]]constexpr int getFieldID() const noexcept{
33 return fieldID;
34 }
35
36 constexpr bool operator==(const FieldValue & other) const noexcept{
37 return fieldID==other.fieldID && value == other.value;
38 }
39 };
40}
41
42namespace fishnet{
50template<geometry::AnyGeometry G>
51class Feature {
52private:
53 G geometry;
54 std::vector<__impl::FieldValue> attributes;
55
56 template<FieldValueType T>
57 constexpr auto getItPosOfAttribute(const FieldDefinition<T> & fieldDefinition) const noexcept{
58 return std::ranges::find_if(attributes,[&fieldDefinition](const auto & value){
59 return fieldDefinition.getFieldID() == value.getFieldID();
60 });
61 }
62
63 template<FieldValueType T>
64 constexpr auto getItPosOfAttribute(const FieldDefinition<T> & fieldDefinition) noexcept{
65 return std::ranges::find_if(attributes,[&fieldDefinition](const auto & value){
66 return fieldDefinition.getFieldID() == value.getFieldID();
67 });
68 }
69
70 template<geometry::AnyGeometry O>
71 friend class Feature;
72
73public:
74 constexpr explicit Feature(const G & geometry):geometry(geometry){}
75 constexpr explicit Feature(G && geometry):geometry(std::move(geometry)){}
76
77 template<IFieldDefinition FieldDef>
78 constexpr bool addAttribute(const FieldDef & fieldDefinition, math::convertible_without_loss<typename FieldDef::value_type> auto value) noexcept {
79 if (hasAttribute(fieldDefinition))
80 return false;
81 attributes.emplace_back(static_cast<typename FieldDef::value_type>(value), fieldDefinition.getFieldID());
82 return true;
83 }
84
85 constexpr bool hasAttribute(const IFieldDefinition auto & fieldDefinition) const noexcept {
86 return std::ranges::any_of(attributes,[&fieldDefinition](const auto & fieldValue){
87 return fieldDefinition.getFieldID() == fieldValue.getFieldID();
88 });
89 }
90
91 template<IFieldDefinition FieldDef>
92 constexpr fishnet::Option<typename FieldDef::value_type> getAttribute(const FieldDef & fieldDefinition) const noexcept {
93 using T = typename FieldDef::value_type;
94 auto valueIt = getItPosOfAttribute(fieldDefinition);
95 if(valueIt == std::ranges::end(attributes))
96 return std::nullopt;
97 return fishnet::Option<T>(valueIt->template getValue<T>());
98 }
99
100 template<IFieldDefinition FieldDef>
101 constexpr void setAttribute(const FieldDef & fieldDefinition, math::convertible_without_loss<typename FieldDef::value_type> auto value) noexcept {
102 if(not addAttribute(fieldDefinition,value)) {
103 *getItPosOfAttribute(fieldDefinition) = __impl::FieldValue(static_cast<typename FieldDef::value_type>(value), fieldDefinition.getFieldID());
104 }
105 }
106
107 constexpr void removeAttribute(const IFieldDefinition auto fieldDefinition) noexcept {
108 std::erase_if(attributes,[&fieldDefinition](const auto & value){return value.getFieldID() == fieldDefinition.getFieldID();});
109 }
110
111 template<geometry::AnyGeometry O>
112 constexpr void copyAttributes(const Feature<O> & source) noexcept {
113 std::ranges::for_each(source.attributes,[this](const auto & value){this->attributes.push_back(value);});
114 }
115
116 constexpr const G & getGeometry() const & noexcept{
117 return this->geometry;
118 }
119
120 constexpr G & getGeometry() & noexcept {
121 return this->geometry;
122 }
123
124 constexpr G && getGeometry() && noexcept {
125 return std::move(this->geometry);
126 }
127
128 constexpr bool operator==(const Feature<G> & feature) const noexcept {
129 return this->geometry == feature.getGeometry() &&
130 std::ranges::is_permutation(this->attributes, feature.attributes);
131 }
132};
133}
Feature implementation storing a geometry and associated attributes.
Definition Feature.hpp:51
constexpr bool operator==(const Feature< G > &feature) const noexcept
Definition Feature.hpp:128
constexpr void setAttribute(const FieldDef &fieldDefinition, math::convertible_without_loss< typename FieldDef::value_type > auto value) noexcept
Definition Feature.hpp:101
constexpr Feature(const G &geometry)
Definition Feature.hpp:74
constexpr const G & getGeometry() const &noexcept
Definition Feature.hpp:116
constexpr G & getGeometry() &noexcept
Definition Feature.hpp:120
constexpr fishnet::Option< typename FieldDef::value_type > getAttribute(const FieldDef &fieldDefinition) const noexcept
Definition Feature.hpp:92
constexpr G && getGeometry() &&noexcept
Definition Feature.hpp:124
constexpr Feature(G &&geometry)
Definition Feature.hpp:75
constexpr void removeAttribute(const IFieldDefinition auto fieldDefinition) noexcept
Definition Feature.hpp:107
constexpr bool addAttribute(const FieldDef &fieldDefinition, math::convertible_without_loss< typename FieldDef::value_type > auto value) noexcept
Definition Feature.hpp:78
constexpr void copyAttributes(const Feature< O > &source) noexcept
Definition Feature.hpp:112
constexpr bool hasAttribute(const IFieldDefinition auto &fieldDefinition) const noexcept
Definition Feature.hpp:85
Field definition implementation. Defines name, id and data type of a field.
Definition FieldDefinition.hpp:43
constexpr int getFieldID() const noexcept
Definition FieldDefinition.hpp:63
Definition Option.hpp:13
Defines an Interface for FieldDefinitions, which can be used as generic parameter.
Definition FieldDefinition.hpp:30
Definition NumericConcepts.hpp:10
Definition BFSClustering.hpp:5
std::variant< double, float, int, long, size_t, long long, std::string, const char * > FieldType
Definition FieldType.hpp:7
STL namespace.