27 .supported_type(GeometryComponent::Type::PointCloud)
33 "A curve is created for every distinct group ID. All points with the same ID are put "
34 "into the same curve");
36 "Determines the order of points in each curve");
45 const auto comparator = [&](
const int index_a,
const int index_b) {
46 const float weight_a = weights[index_a];
47 const float weight_b = weights[index_b];
48 if (
UNLIKELY(weight_a == weight_b)) {
50 return index_a < index_b;
52 return weight_a < weight_b;
56 for (const int group_index : range) {
57 MutableSpan<int> group = indices.slice(offsets[group_index]);
58 parallel_sort(group.begin(), group.end(), comparator);
71 const int curve_index = indices_of_curves[index];
72 r_indices[r_offsets[curve_index] + counts[curve_index]] = int(index);
73 counts[curve_index]++;
79 const VectorSet<int> deduplicated_groups(r_identifiers_to_indices);
82 for (int &value : r_identifiers_to_indices.slice(range)) {
83 value = deduplicated_groups.index_of(value);
86 return deduplicated_groups.size();
93 const int domain_size = weights_varray.
size();
122 const int domain_size = points.
totpoint;
123 if (domain_size == 0) {
129 evaluator.
add(group_id_field);
130 evaluator.
add(weight_field);
143 if (total_curves == 1) {
156 if (!weights_varray.is_single()) {
182 *points, group_id_field, weight_field, attribute_filter);
185 geometry_set.
keep_only({GeometryComponent::Type::Curve, GeometryComponent::Type::Edit});
188 params.set_output(
"Curves", std::move(geometry_set));
196 ntype.
ui_name =
"Points to Curves";
197 ntype.
ui_description =
"Split all points to curve by its group ID and reorder by weight";
Low-level operations for curves.
#define NODE_CLASS_GEOMETRY
#define GEO_NODE_POINTS_TO_CURVES
#define NOD_REGISTER_NODE(REGISTER_FUNC)
MutableSpan< T > as_mutable_span()
constexpr int64_t size() const
constexpr void fill(const T &value) const
constexpr IndexRange index_range() const
constexpr IndexRange index_range() const
void materialize(MutableSpan< T > r_span) const
MutableAttributeAccessor attributes_for_write()
void fill_curve_types(CurveType type)
MutableSpan< int > offsets_for_write()
int add(GField field, GVArray *varray_ptr)
const GVArray & get_evaluated(const int field_index) const
IndexRange index_range() const
void fill_index_range(MutableSpan< T > span, const T start=0)
void node_register_type(bNodeType &ntype)
void copy_attributes(const AttributeAccessor src_attributes, AttrDomain src_domain, AttrDomain dst_domain, const AttributeFilter &attribute_filter, MutableAttributeAccessor dst_attributes)
void gather_attributes(AttributeAccessor src_attributes, AttrDomain src_domain, AttrDomain dst_domain, const AttributeFilter &attribute_filter, const IndexMask &selection, MutableAttributeAccessor dst_attributes)
Curves * curves_new_nomain_single(int points_num, CurveType type)
Curves * curves_new_nomain(int points_num, int curves_num)
void foreach_real_geometry(bke::GeometrySet &geometry, FunctionRef< void(bke::GeometrySet &geometry_set)> fn)
void debug_randomize_curve_order(bke::CurvesGeometry *curves)
static void node_geo_exec(GeoNodeExecParams params)
static Curves * curve_from_points(const AttributeAccessor attributes, const VArray< float > &weights_varray, const AttributeFilter &attribute_filter)
static void find_points_by_group_index(const Span< int > indices_of_curves, MutableSpan< int > r_offsets, MutableSpan< int > r_indices)
static void grouped_sort(const OffsetIndices< int > offsets, const Span< float > weights, MutableSpan< int > indices)
static void node_declare(NodeDeclarationBuilder &b)
static Curves * curves_from_points(const PointCloud &points, const Field< int > &group_id_field, const Field< float > &weight_field, const AttributeFilter &attribute_filter)
static int identifiers_to_indices(MutableSpan< int > r_identifiers_to_indices)
static void node_register()
void build_reverse_offsets(Span< int > indices, MutableSpan< int > offsets)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
void geo_node_type_base(blender::bke::bNodeType *ntype, std::string idname, const std::optional< int16_t > legacy_type)
void keep_only(Span< GeometryComponent::Type > component_types)
void replace_curves(Curves *curves, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
const PointCloud * get_pointcloud() const
std::string ui_description
NodeGeometryExecFunction geometry_node_execute
const char * enum_name_legacy
NodeDeclareFunction declare