27 bool has_cycle =
false;
28 auto push_curve = [&](
const int curve_i) ->
bool {
29 if ((flags[curve_i] &
Inserted) != 0) {
32 if ((flags[curve_i] &
OnStack) != 0) {
45 const int current = stack.
peek();
47 const int next = connect_to_curve[current];
48 if (range.contains(
next)) {
49 if (push_curve(
next)) {
70 for (
const int curve_i :
range) {
71 const int next = connect_to_curve[curve_i];
72 if (range.contains(
next)) {
73 is_start_curve[
next] =
false;
80 for (
const int curve_i :
range) {
81 if (is_start_curve[curve_i]) {
83 connect_to_curve, flags, curve_i, [&](
const int index) { is_reachable[index] =
true; });
91 for (
const int curve_i :
range) {
92 if (is_start_curve[curve_i] || !is_reachable[curve_i]) {
94 connect_to_curve, flags, curve_i, [&](
const int index) { sorted_curves.
append(index); });
110 const int mirror_i = span.
size() - 1 - i;
130 if (iter.
domain != domain) {
144 for (const int new_i : range) {
145 const int old_i = old_by_new_map[new_i];
146 const bool flip = flip_direction[old_i];
148 GMutableSpan dst_span = dst.span.slice(dst_offsets[new_i]);
149 array_utils::copy(src.slice(src_offsets[old_i]), dst_span);
151 reverse_order(dst_span);
166 bke::gather_attributes(src_curves.
attributes(),
167 bke::AttrDomain::Curve,
168 bke::AttrDomain::Curve,
175 offset_indices::gather_group_sizes(old_offsets, old_by_new_map, new_offsets);
176 offset_indices::accumulate_counts_to_offsets(new_offsets);
179 bke::AttrDomain::Point,
200 for (
const int dst_i : old_by_new_map.
index_range()) {
201 const int src_i = old_by_new_map[dst_i];
202 new_by_old_map[src_i] = dst_i;
205 r_joined_curve_offsets.
reserve(curves_range.
size() + 1);
208 int start_index = -1;
209 for (
const int dst_i : curves_range) {
210 const int src_i = old_by_new_map[dst_i];
213 const bool src_cyclic = cyclic[src_i];
215 if (start_index < 0) {
216 r_joined_curve_offsets.
append(0);
217 r_joined_cyclic.
append(src_cyclic);
221 ++r_joined_curve_offsets.
last();
223 const int src_connect_to = connect_to_curve[src_i];
224 const bool is_connected = curves_range.
contains(src_connect_to);
225 const int dst_connect_to = is_connected ? new_by_old_map[src_connect_to] : -1;
228 if (dst_connect_to != dst_i + 1) {
231 const bool is_chain = (is_connected || dst_i != start_index);
233 r_joined_cyclic.
last() = (dst_connect_to == start_index);
240 r_joined_curve_offsets.
append(0);
242 offset_indices::accumulate_counts_to_offsets(r_joined_curve_offsets);
249 old_curves_by_new.
size());
253 const Span<int> old_by_new_map = old_curves_by_new.
data().drop_back(1);
254 bke::gather_attributes(src_curves.
attributes(),
255 bke::AttrDomain::Curve,
256 bke::AttrDomain::Curve,
257 bke::attribute_filter_from_skip_ref({
"cyclic"}),
265 const IndexRange old_curves = old_curves_by_new[new_i];
266 new_offsets[new_i] = offset_indices::sum_group_sizes(old_points_by_curve, old_curves);
268 offset_indices::accumulate_counts_to_offsets(new_offsets);
272 bke::AttrDomain::Point,
273 bke::AttrDomain::Point,
294 src_curves, old_by_new_map, connect_to_curve, src_cyclic, joined_curve_offsets, cyclic);
297 src_curves, old_by_new_map, flip_direction);
303 return merged_curves;
#define BUFFER_FOR_CPP_TYPE_VALUE(type, variable_name)
void fill(const T &value) const
void move_assign(void *src, void *dst) const
void destruct(void *ptr) const
void default_construct(void *ptr) const
const CPPType & type() const
constexpr IndexRange drop_back(int64_t n) const
constexpr int64_t size() const
constexpr bool contains(int64_t value) const
constexpr void fill(const T &value) const
constexpr Span< T > as_span() const
constexpr IndexRange index_range() const
constexpr void copy_from(Span< T > values) const
constexpr int64_t size() const
constexpr IndexRange index_range() const
void push(const T &value)
void append(const T &value)
const T & last(const int64_t n=0) const
void reserve(const int64_t min_capacity)
void foreach_attribute(const FunctionRef< void(const AttributeIter &)> fn) const
eCustomDataType data_type
GAttributeReader get() const
OffsetIndices< int > points_by_curve() const
IndexRange curves_range() const
MutableAttributeAccessor attributes_for_write()
Span< int > offsets() const
void tag_topology_changed()
AttributeAccessor attributes() const
MutableSpan< int > offsets_for_write()
VArray< bool > cyclic() const
MutableSpan< bool > cyclic_for_write()
GSpanAttributeWriter lookup_or_add_for_write_only_span(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type)
static Vector< int > toposort_connected_curves(const Span< int > connect_to_curve)
static bke::CurvesGeometry reorder_and_flip_curves(const bke::CurvesGeometry &src_curves, const Span< int > old_by_new_map, const Span< bool > flip_direction)
static void foreach_connected_curve(const Span< int > connect_to_curve, MutableSpan< uint8_t > flags, const int start, Fn fn)
static void reorder_and_flip_attributes_group_to_group(const bke::AttributeAccessor src_attributes, const bke::AttrDomain domain, const OffsetIndices< int > src_offsets, const OffsetIndices< int > dst_offsets, const Span< int > old_by_new_map, const Span< bool > flip_direction, bke::MutableAttributeAccessor dst_attributes)
static void reverse_order(GMutableSpan span)
static bke::CurvesGeometry join_curves_ranges(const bke::CurvesGeometry &src_curves, const OffsetIndices< int > old_curves_by_new)
static void find_connected_ranges(const bke::CurvesGeometry &src_curves, const Span< int > old_by_new_map, Span< int > connect_to_curve, Span< bool > cyclic, Vector< int > &r_joined_curve_offsets, Vector< bool > &r_joined_cyclic)
bke::CurvesGeometry curves_merge_endpoints(const bke::CurvesGeometry &src_curves, Span< int > connect_to_curve, Span< bool > flip_direction, const bke::AttributeFilter &attribute_filter)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))