22 b.add_output<
decl::Int>(
"Next Vertex Index").field_source().reference_pass_all();
23 b.add_output<
decl::Float>(
"Total Cost").field_source().reference_pass_all();
38 std::priority_queue<VertPriority, std::vector<VertPriority>, std::greater<>> queue;
41 r_cost[start_vert_i] = 0.0f;
42 queue.emplace(0.0f, start_vert_i);
49 for (const int vert_i : range) {
50 for (const int edge_i : vert_to_edge.offsets[vert_i]) {
51 other_vertex[edge_i] = bke::mesh::edge_other_vert(edges[vert_to_edge.data[edge_i]],
57 while (!queue.empty()) {
58 const float cost_i = queue.top().first;
59 const int vert_i = queue.top().second;
61 if (visited[vert_i]) {
64 visited[vert_i] =
true;
65 for (
const int index : vert_to_edge.offsets[vert_i]) {
66 const int edge_i = vert_to_edge.data[index];
67 const int neighbor_vert_i = other_vertex[index];
68 if (visited[neighbor_vert_i]) {
71 const float edge_cost = std::max(0.0f, input_cost[edge_i]);
72 const float new_neighbor_cost = cost_i + edge_cost;
73 if (new_neighbor_cost < r_cost[neighbor_vert_i]) {
74 r_cost[neighbor_vert_i] = new_neighbor_cost;
75 r_next_index[neighbor_vert_i] = vert_i;
76 queue.emplace(new_neighbor_cost, neighbor_vert_i);
89 :
bke::MeshFieldInput(
CPPType::get<int>(),
"Shortest Edge Paths Next Vertex Field"),
90 end_selection_(end_selection),
102 edge_evaluator.
add(cost_);
108 point_evaluator.
add(end_selection_);
117 return mesh.attributes().adapt_domain<
int>(
125 edges, mesh.verts_num, vert_to_edge_offset_data, vert_to_edge_indices);
126 shortest_paths(mesh, vert_to_edge, end_selection, input_cost, next_index, cost);
129 for (const int i : range) {
130 if (next_index[i] == -1) {
135 return mesh.attributes().adapt_domain<
int>(
141 end_selection_.node().for_each_field_input_recursive(
fn);
142 cost_.node().for_each_field_input_recursive(
fn);
155 return other_field->end_selection_ == end_selection_ && other_field->cost_ == cost_;
162 return AttrDomain::Point;
173 :
bke::MeshFieldInput(
CPPType::get<
float>(),
"Shortest Edge Paths Cost Field"),
174 end_selection_(end_selection),
186 edge_evaluator.
add(cost_);
192 point_evaluator.
add(end_selection_);
197 return mesh.attributes().adapt_domain<
float>(
208 edges, mesh.verts_num, vert_to_edge_offset_data, vert_to_edge_indices);
209 shortest_paths(mesh, vert_to_edge, end_selection, input_cost, next_index, cost);
212 for (const int i : range) {
213 if (cost[i] == FLT_MAX) {
218 return mesh.attributes().adapt_domain<
float>(
224 end_selection_.node().for_each_field_input_recursive(
fn);
225 cost_.node().for_each_field_input_recursive(
fn);
238 return other_field->end_selection_ == end_selection_ && other_field->cost_ == cost_;
245 return AttrDomain::Point;
255 std::make_shared<ShortestEdgePathsNextVertFieldInput>(end_selection, cost)};
256 Field<float> cost_field{std::make_shared<ShortestEdgePathsCostFieldInput>(end_selection, cost)};
257 params.set_output(
"Next Vertex Index", std::move(next_vert_field));
258 params.set_output(
"Total Cost", std::move(cost_field));
267 ntype.
ui_name =
"Shortest Edge Paths";
269 "Find the shortest paths along mesh edges to selected end vertices, with customizable cost "
#define GEO_NODE_INPUT_SHORTEST_EDGE_PATHS
#define NOD_REGISTER_NODE(REGISTER_FUNC)
unsigned long long int uint64_t
static VArray from_single(T value, const int64_t size)
static VArray from_container(ContainerT container)
IndexRange index_range() const
int add(GField field, GVArray *varray_ptr)
IndexMask get_evaluated_as_mask(int field_index)
const GVArray & get_evaluated(const int field_index) const
void foreach_index(Fn &&fn) const
void fill_index_range(MutableSpan< T > span, const T start=0)
GroupedSpan< int > build_vert_to_edge_map(Span< int2 > edges, int verts_num, Array< int > &r_offsets, Array< int > &r_indices)
void node_register_type(bNodeType &ntype)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
uint64_t get_default_hash(const T &v, const Args &...args)
void geo_node_type_base(blender::bke::bNodeType *ntype, std::string idname, const std::optional< int16_t > legacy_type)
std::string ui_description
NodeGeometryExecFunction geometry_node_execute
const char * enum_name_legacy
NodeDeclareFunction declare
IndexRange index_range() const