2 #ifndef ANDRES_GRAPH_LIFTING_HXX
3 #define ANDRES_GRAPH_LIFTING_HXX
13 #include "grid-graph.hxx"
23 template<
class INPUT_GRAPH,
class OUTPUT_GRAPH>
26 const INPUT_GRAPH& inputGraph,
27 OUTPUT_GRAPH& outputGraph,
28 const std::size_t distanceUpperBound,
29 const std::size_t distanceLowerBound = 0
31 typedef std::size_t size_type;
33 if(outputGraph.numberOfVertices() != 0)
34 throw std::runtime_error(
"output graph is not empty.");
36 outputGraph.insertVertices(inputGraph.numberOfVertices());
39 std::vector<std::size_t> visited;
40 std::vector<std::size_t> vertices;
42 for (size_type v = 0; v < inputGraph.numberOfVertices(); ++v)
47 [&](size_type w, size_type depth,
bool& proceed,
bool& add)
52 if (depth <= distanceUpperBound)
54 if (depth + 1 <= distanceUpperBound)
60 if (depth > distanceLowerBound)
61 vertices.push_back(w);
64 breadthFirstSearchData
67 std::sort(vertices.begin(), vertices.end());
69 for (
auto w : vertices)
70 outputGraph.insertEdge(v, w);
75 for (
auto w : visited)
83 template<
class INPUT_GRAPH_VISITOR,
class OUTPUT_GRAPH>
87 OUTPUT_GRAPH& outputGraph,
88 const std::size_t distanceUpperBound,
89 const std::size_t distanceLowerBound = 0,
94 typedef std::size_t size_type;
95 typedef typename INPUT_GRAPH::VertexCoordinate VertexCoordinate;
97 const size_type distanceUpperBoundSquared = distanceUpperBound * distanceUpperBound;
98 const size_type distanceLowerBoundSquared = distanceLowerBound * distanceLowerBound;
100 if(outputGraph.numberOfVertices() != 0)
101 throw std::runtime_error(
"output graph is not empty.");
113 const std::size_t row0 = cv[1] < distanceUpperBound ? 0 : cv[1] - distanceUpperBound;
114 std::size_t offsetY = 1;
117 for(std::size_t yPlus = cv[1]; yPlus > row0; --yPlus, ++offsetY)
119 const std::size_t offsetX = (metric == LiftingMetric::PathLength) ?
120 distanceUpperBound - offsetY:
121 ::floor(::sqrt(distanceUpperBoundSquared - offsetY * offsetY));
123 const std::size_t col0 = cv[0] < offsetX ? 0 : cv[0] - offsetX;
124 std::size_t colN = cv[0] + offsetX;
125 if(colN > inputGraph.
shape(0) - 1)
126 colN = inputGraph.
shape(0) - 1;
128 for (std::size_t x = col0; x <= colN; ++x)
130 if (metric == LiftingMetric::PathLength)
132 const std::size_t distance = ::abs(x - cv[0]) + ::abs(yPlus - 1 - cv[1]);
134 if (distance > distanceLowerBound)
136 const size_type w = inputGraph.
vertex({{x, yPlus - 1}});
137 outputGraph.insertEdge(v, w);
142 const std::size_t sqaredDistance = (x - cv[0]) * (x - cv[0]) + (yPlus - 1 - cv[1]) * (yPlus - 1 - cv[1]);
144 if (sqaredDistance > distanceLowerBoundSquared)
146 const size_type w = inputGraph.
vertex({{x, yPlus - 1}});
147 outputGraph.insertEdge(v, w);
156 const std::size_t offsetX = distanceUpperBound;
157 const std::size_t y = cv[1];
158 const std::size_t col0 = cv[0] < offsetX ? 0 : cv[0] - offsetX;
159 std::size_t colN = cv[0] + offsetX;
161 if (colN > inputGraph.
shape(0) - 1)
162 colN = inputGraph.
shape(0) - 1;
164 if (cv[0] > distanceLowerBound)
165 for (std::size_t x = col0; x <= cv[0] - distanceLowerBound - 1; ++x)
167 const size_type& w = inputGraph.
vertex({{x, y}});
168 outputGraph.insertEdge(v, w);
171 for (std::size_t x = cv[0] + distanceLowerBound + 1; x <= colN; ++x)
173 const size_type& w = inputGraph.
vertex({{x, y}});
174 outputGraph.insertEdge(v, w);
179 if (cv[1] < inputGraph.
shape(1) - 1)
181 const std::size_t row0 = cv[1] + 1;
182 std::size_t rowN = cv[1] + distanceUpperBound;
184 if (cv[1] + distanceUpperBound > inputGraph.
shape(1) - 1)
185 rowN = inputGraph.
shape(1) - 1;
187 std::size_t offsetY = 1;
188 for (std::size_t y = row0; y <= rowN; ++y, ++offsetY)
190 const std::size_t offsetX = (metric == LiftingMetric::PathLength) ?
191 distanceUpperBound - offsetY :
192 ::floor(::sqrt(distanceUpperBoundSquared - offsetY * offsetY));
194 const std::size_t col0 = cv[0] < offsetX ? 0 : cv[0] - offsetX;
195 std::size_t colN = cv[0] + offsetX;
197 if (colN > inputGraph.
shape(0) - 1)
198 colN = inputGraph.
shape(0) - 1;
200 for (std::size_t x = col0; x <= colN; ++x)
202 if (metric == LiftingMetric::PathLength)
204 const std::size_t distance = ::abs(x - cv[0]) + ::abs(y - cv[1]);
206 if (distance > distanceLowerBound)
208 const size_type w = inputGraph.
vertex({{x, y}});
209 outputGraph.insertEdge(v, w);
214 const std::size_t sqaredDistance = (x - cv[0]) * (x - cv[0]) + (y - cv[1]) * (y - cv[1]);
216 if (sqaredDistance > distanceLowerBoundSquared)
218 const size_type w = inputGraph.
vertex({{x, y}});
219 outputGraph.insertEdge(v, w);
231 #endif // #ifndef ANDRES_GRAPH_LIFTING_HXX