Fishnet 2.0.1
Framework for Graph-Based Analysis of GIS Vector Data
Loading...
Searching...
No Matches
Edge.hpp
Go to the documentation of this file.
1#pragma once
2#include <sstream>
3#include <concepts>
5
6namespace fishnet::graph{
7
8template<typename N>
9concept Node = std::equality_comparable<N>;
10
11template<typename NodeType,typename N>
12concept UniversalNodeRef = std::same_as<N,std::remove_cvref_t<NodeType>>;
13
20template<typename E, typename N=E::node_type>
21concept Edge = fishnet::util::HasHashMethod<E> && std::equality_comparable<E> && requires(const E & e, const E & o, const N & cNodeRef /*, N&& nodeRval*/){
22 {E(cNodeRef,cNodeRef)};
23 /*{E(nodeRval,nodeRval)};*/
24 {E::isDirected()} -> std::convertible_to<bool>;
25 {e.getFrom()} -> std::same_as<const N &>;
26 {e.getTo()} -> std::same_as<const N &>;
27 typename E::node_type;
28 typename E::hash_function;
29 typename E::equality_predicate;
30};
31
32template<typename A>
34
35template<typename F, typename N, typename A>
37
46template<typename E, typename N= E::node_type, typename A=E::annotation_type, typename W=E::weight_function>
47concept WeightedEdge = Edge<E,N> && WeightFunction<W,N,A> && requires (const E & e, const N & cNodeRef, const A & constARef, A&& ARval ){
48 {E(cNodeRef,cNodeRef,constARef)};
49 {E(cNodeRef,cNodeRef,ARval)};
50 {e.getWeight()} -> std::convertible_to<A>;
51 {e.unweighted()} -> std::convertible_to<E>;
52 typename E::annotation_type;
53 typename E::weight_function;
54};
55}
56
57namespace fishnet::graph::__impl{
66 template<Node N,bool Directed, fishnet::util::HashFunction<N> Hash = std::hash<N>, fishnet::util::BiPredicate<N> Equal = std::equal_to<N>>
67 class BaseEdge {
68 protected:
69 N from;
70 N to;
71 static inline Equal eq = Equal();
72 static inline Hash hasher = Hash();
73 public:
74 using node_type = N;
75 using hash_function = Hash;
76 using equality_predicate = Equal;
77
78 constexpr static bool isDirected(){
79 return Directed;
80 }
81
82 BaseEdge(const N & from, const N & to):from(from),to(to){}
83
84 BaseEdge( N && from, N && to):from(std::move(from)),to(std::move(to)){}
85
86 const N & getFrom()const {
87 return from;
88 }
89
90 const N & getTo() const{
91 return to;
92 }
93
94 bool operator==( const BaseEdge<N,false,Hash,Equal> & other)const{
95 if constexpr(not Directed){
96 return (eq(from, other.getFrom()) and eq(to,other.getTo())) or
97 (eq(from, other.getTo()) and eq(to, other.getFrom()));
98 }
99 return false; // directed edge != undirected edge
100 }
101
102 bool operator==(const BaseEdge<N,true,Hash,Equal> & other) const {
103 if constexpr(Directed){
104 return eq(from,other.getFrom()) && eq(to, other.getTo());
105 }
106 return false; // directed edge != undirected edge
107 }
108
109 size_t inline hash()const{
110 if constexpr(Directed){
111 size_t hashFrom = hasher(from);
112 size_t hashTo = hasher(to);
113 constexpr size_t shift = sizeof(size_t) *4;
114 return (hashFrom << shift) | hashTo;
115 }else{
116 return hasher(from) ^ hasher(to);
117 }
118 }
119
120 std::string toString() const noexcept requires fishnet::util::HasToString<N>{
121 std::ostringstream oss;
122 oss << "(" << this->from.toString() << ")";
123 if constexpr(Directed){
124 oss << "->";
125 }else {
126 oss << "-";
127 }
128 oss << "(" << this->to.toString() << ")";
129 return oss.str();
130 }
131 };
132
140 template<Edge E,Annotation A,WeightFunction<typename E::node_type,A> W>
141 class WeightedEdgeDecorator: public E{
142 private:
143 A weight;
144 using N=typename E::node_type;
145 public:
146 using annotation_type=A;
147 using weight_function=W;
148
149 WeightedEdgeDecorator(const N & from, const N & to, const A & weight): E(from,to),weight(weight){};
150
151 WeightedEdgeDecorator(const N & from, const N & to):E(from,to){
152 this->weight = W()(from,to);
153 }
154
155 WeightedEdgeDecorator(const N & from, const N & to, A &&weight): E(from,to),weight(std::move(weight)){};
156
157 WeightedEdgeDecorator( E && edge ):WeightedEdgeDecorator(edge.getFrom(),edge.getTo()){}
158
159 WeightedEdgeDecorator(const E & edge ):WeightedEdgeDecorator(edge.getFrom(),edge.getTo()){}
160
161 void setWeight(const A & weight){
162 this->weight = weight;
163 }
164
165 const A& getWeight()const{
166 return weight;
167 }
168
169 E inline unweighted()const {
170 return E(this->getFrom(),this->getTo());
171 }
172
173 bool operator==(const WeightedEdgeDecorator<E,A,W> & other) const {
174 return this->unweighted() == other.unweighted() && this->weight == other.getWeight();
175 }
176
177 size_t inline hash() const{
178 return this->unweighted().hash() + std::hash<A>{}(weight);
179 }
180 };
181}
182
183namespace fishnet::graph{
184
185template<Node N, fishnet::util::HashFunction<N> Hash = std::hash<N>, fishnet::util::BiPredicate<N> Equal = std::equal_to<N>>
186using UndirectedEdge = __impl::BaseEdge<N,false,Hash,Equal>;
187
188template<Node N, fishnet::util::HashFunction<N> Hash = std::hash<N>, fishnet::util::BiPredicate<N> Equal = std::equal_to<N>>
189using DirectedEdge = __impl::BaseEdge<N,true,Hash,Equal>;
190
191template<Edge E, Annotation A , WeightFunction<typename E::node_type,A> W>
192using WeightEdge = __impl::WeightedEdgeDecorator<E,A,W>;
193}
Definition Edge.hpp:33
Interface for an Edge.
Definition Edge.hpp:21
Definition Edge.hpp:9
Definition Edge.hpp:12
Definition Edge.hpp:36
Interface for a weighted Edge.
Definition Edge.hpp:47
Definition NumericConcepts.hpp:7
Definition FunctionalConcepts.hpp:15
Helper concept which checks whether a class has a hash method.
Definition ObjectConcepts.hpp:22
Definition AdjacencyContainer.hpp:4
__impl::BaseEdge< N, true, Hash, Equal > DirectedEdge
Definition Edge.hpp:189
__impl::BaseEdge< N, false, Hash, Equal > UndirectedEdge
Definition Edge.hpp:186
__impl::WeightedEdgeDecorator< E, A, W > WeightEdge
Definition Edge.hpp:192
Definition BFSClustering.hpp:5
STL namespace.