Description
Dijkstra's algorithm finds shortest paths based on weigths assigned to edges in a graph. As far as I understand it, in dijkstra3d, given a field image, a directed graph is implicitly constructed by using a voxel connectivity pattern and the edge weights are implicitly given by the value of the field image at the target of the edge (as per the readme):
For given input voxels A and B, the edge weight from A to B is B and from B to A is A.
While this covers some important use cases, it would also be interesting to allow for a more generic means of computing the edge weigths while retaining the implicit graph handling of dijkstra3d. In particular, allowing the user to specify a function taking as input the value of the field image at the edge source and edge target but also taking as input the type of edge (center->left, top-right->center, bottom->center, etc.) would be great.
I have created a simple python notebook to illustrate this concept in 2D but relying on networkx as the backend:
https://colab.research.google.com/drive/196EPtBO0BmIjYmi6RlBvLlD_JGyAE9zB?usp=sharing
I am not entirely sure how this should best be implemented in dijkstra3d but I guess one could create a functor in c++ (let's call it edgeweightfunc
). edgeweightfunc
would then be called instead of fetching only the edge target value (which seems to be done with delta = static_cast<float>(field[neighboridx]);
in dijkstra3d:
Line 310 in 48dffd9
For brainstorming purposes, a basic concept of what such an edgeweightfunc
could look like (in 2D) and in c++ is below:
#include <iostream>
#include <cmath>
#include <array>
int main()
{
// Encode edge type in 2D (xf: x forward - xb: x backward)
// There are surely better ways of doing this including using
// boolean operations to combine x, y and z modes
// see e.g. https://en.cppreference.com/w/cpp/named_req/BitmaskType
enum EdgeType : int { xf, xb, yf, yb, xfyf, xfyb, xbyf, xbyb };
// This is the functor we would pass to dijkstra::distance_field3d
auto edgeweightfunc = [](auto edgesourceval, auto edgetargetval, EdgeType edgetype ) {
constexpr std::array<double,8> edgedists2 { 1., 1., 1., 1., 2., 2., 2., 2. };
// we could also use std::hypot
auto squarefunc = [](auto x) {return x*x;};
return std::sqrt( edgedists2[edgetype] + squarefunc(edgesourceval - edgetargetval) );
};
std::cout << "Edge weight: " << edgeweightfunc(5.0,3.0,EdgeType::xbyb) << std::endl;
}
I haven't looked at how such c++ functors can be bound to python but I assume a solution can be found...
Activity