22 "Index of nearest element");
23 b.add_output<
decl::Bool>(
"Has Neighbor").field_source_reference_all();
28 KDTree_3d *
tree = BLI_kdtree_3d_new(
mask.size());
30 [&](
const int index) { BLI_kdtree_3d_insert(
tree, index, positions[index]); });
31 BLI_kdtree_3d_balance(
tree);
37 return BLI_kdtree_3d_find_nearest_cb_cpp(
41 [index](
const int other,
const float * ,
const float ) {
42 return index == other ? 0 : 1;
63 :
bke::GeometryFieldInput(
CPPType::get<int>(),
"Index of Nearest"),
64 positions_field_(std::move(positions_field)),
65 group_field_(std::move(group_field))
72 if (!context.attributes()) {
75 const int domain_size = context.attributes()->domain_size(context.domain());
77 evaluator.
add(positions_field_);
78 evaluator.
add(group_field_);
85 if (group_ids.is_single()) {
89 BLI_kdtree_3d_free(
tree);
95 const int groups_num = group_indexing.
size();
101 const auto get_group_index = [&](
const int i) {
102 const int group_id = group_ids_span[
i];
103 return group_indexing.
index_of(group_id);
107 IndexMask(domain_size), mask_memory, get_group_index, all_indices_by_group_id);
109 if (
mask.size() == domain_size) {
110 lookup_indices_by_group_id = all_indices_by_group_id;
111 result.reinitialize(domain_size);
119 const int avg_tree_size = domain_size / group_indexing.
size();
120 const int grain_size = std::max(8192 / avg_tree_size, 1);
122 for (
const int group_index : range) {
123 const IndexMask &tree_mask = all_indices_by_group_id[group_index];
124 const IndexMask &lookup_mask = lookup_indices_by_group_id[group_index];
127 BLI_kdtree_3d_free(
tree);
136 positions_field_.node().for_each_field_input_recursive(
fn);
137 group_field_.node().for_each_field_input_recursive(
fn);
148 return positions_field_ == other_field->positions_field_ &&
149 group_field_ == other_field->group_field_;
166 :
bke::GeometryFieldInput(
CPPType::get<bool>(),
"Has Neighbor"),
167 group_field_(std::move(group_field))
174 if (!context.attributes()) {
177 const int domain_size = context.attributes()->domain_size(context.domain());
178 if (domain_size == 1) {
183 evaluator.
add(group_field_);
193 mask.foreach_index([&](
const int i) {
195 group_span[
i], [](
int *
count) { *
count = 1; }, [](
int *
count) { (*count)++; });
204 group_field_.node().for_each_field_input_recursive(
fn);
215 return group_field_ == other_field->group_field_;
231 if (
params.output_is_required(
"Index")) {
232 params.set_output(
"Index",
233 Field<int>(std::make_shared<IndexOfNearestFieldInput>(
234 std::move(position_field), group_field)));
237 if (
params.output_is_required(
"Has Neighbor")) {
240 Field<bool>(std::make_shared<HasNeighborFieldInput>(std::move(group_field))));
249 ntype.
ui_name =
"Index of Nearest";
251 "Find the nearest element in a group. Similar to the \"Sample Nearest\" node";
#define NODE_CLASS_CONVERTER
#define GEO_NODE_INDEX_OF_NEAREST
A KD-tree for nearest neighbor search.
@ NODE_DEFAULT_INPUT_POSITION_FIELD
#define NOD_REGISTER_NODE(REGISTER_FUNC)
unsigned long long int uint64_t
static void from_groups(const IndexMask &universe, IndexMaskMemory &memory, Fn &&get_group_index, MutableSpan< IndexMask > r_masks)
const Value & lookup(const Key &key) const
auto add_or_modify(const Key &key, const CreateValueF &create_value, const ModifyValueF &modify_value) -> decltype(create_value(nullptr))
static VArray from_single(T value, const int64_t size)
static VArray from_container(ContainerT container)
int64_t index_of(const Key &key) const
int add(GField field, GVArray *varray_ptr)
const GVArray & get_evaluated(const int field_index) const
StructureType structure_type
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
std::optional< AttrDomain > try_detect_field_domain(const GeometryComponent &component, const fn::GField &field)
void node_register_type(bNodeType &ntype)
static void find_neighbors(const KDTree_3d &tree, const Span< float3 > positions, const IndexMask &mask, MutableSpan< int > r_indices)
static void node_geo_exec(GeoNodeExecParams params)
static void node_declare(NodeDeclarationBuilder &b)
static void node_register()
static int find_nearest_non_self(const KDTree_3d &tree, const float3 &position, const int index)
static KDTree_3d * build_kdtree(const Span< float3 > positions, const IndexMask &mask)
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)
VecBase< float, 3 > float3
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