diff --git a/src/Aardvark.Data.Points.Base/Chunk.cs b/src/Aardvark.Data.Points.Base/Chunk.cs
index 6641caa..a7cde68 100644
--- a/src/Aardvark.Data.Points.Base/Chunk.cs
+++ b/src/Aardvark.Data.Points.Base/Chunk.cs
@@ -161,7 +161,7 @@ public static Chunk ImmutableMerge(Chunk a, Chunk b)
}
}
- return new Chunk(ps, cs, ns, js, ks, PartIndexUtils.Union(a.PartIndices, b.PartIndices), new Box3d(a.BoundingBox, b.BoundingBox));
+ return new Chunk(ps, cs, ns, js, ks, PartIndexUtils.MergeIndices(a.PartIndices, a.Count, b.PartIndices, b.Count), new Box3d(a.BoundingBox, b.BoundingBox));
}
public static Chunk ImmutableMerge(params Chunk[] chunks)
@@ -196,7 +196,7 @@ public static Chunk ImmutableMerge(params Chunk[] chunks)
if (ps == null) throw new Exception("Invariant 4cc7d585-9a46-4ba2-892a-95fce9ed06da.");
return new Chunk(ps, cs, ns, js, ks,
- partIndices: PartIndexUtils.Union(chunks.Select(x => x.PartIndices)),
+ partIndices: PartIndexUtils.MergeIndices(chunks.Select(x => (indices: x.PartIndices, count: x.Count))),
bbox: new Box3d(chunks.Select(x => x.BoundingBox))
);
}
@@ -378,7 +378,7 @@ public Chunk Union(Chunk other)
Append(Normals, other.Normals),
Append(Intensities, other.Intensities),
Append(Classifications, other.Classifications),
- partIndices: PartIndexUtils.Union(PartIndices, other.PartIndices),
+ partIndices: PartIndexUtils.MergeIndices(PartIndices, Count, other.PartIndices, other.Count),
Box.Union(BoundingBox, other.BoundingBox)
);
}
diff --git a/src/Aardvark.Data.Points.Base/PartIndexUtils.cs b/src/Aardvark.Data.Points.Base/PartIndexUtils.cs
index 681c4c9..ea54ff9 100644
--- a/src/Aardvark.Data.Points.Base/PartIndexUtils.cs
+++ b/src/Aardvark.Data.Points.Base/PartIndexUtils.cs
@@ -30,41 +30,169 @@ namespace Aardvark.Data.Points;
public static class PartIndexUtils
{
///
- /// Returns union of two part indices (uint, IList of [byte|short|int]).
+ /// Merges part indices (null, uint, [byte|short|int] array).
///
- public static object? Union(object? first, object? second)
+ public static object? MergeIndices(object? first, int firstCount, object? second, int secondCount)
+ {
+ // expect: both ranges are defined, or both ranges are null
+ if ((first == null && second != null) || (first != null && second == null)) throw new Exception(
+ "Invariant 874c2220-4779-41f0-9f3e-1c0ef4988da9."
+ );
+
+ checked
+ {
+ return (first, second) switch
+ {
+ (null , null ) => null,
+
+ (uint x, uint y) => (x == y) ? x : createArray1(x, firstCount, y, secondCount),
+
+ (uint x, _ ) => second switch
+ {
+ IReadOnlyList ys when x <= byte .MaxValue => createArray2((byte )x, firstCount, ys),
+ IReadOnlyList ys when x <= short.MaxValue => createArray2((short)x, firstCount, ys),
+ IReadOnlyList ys when x <= int .MaxValue => createArray2((int )x, firstCount, ys),
+ _ => throw new Exception("Invariant 588fea29-4daa-4356-92a4-369f64ac5778.")
+ },
+
+ (_ , uint y) => second switch
+ {
+ IReadOnlyList xs when y <= byte .MaxValue => createArray3(xs, (byte )y, secondCount),
+ IReadOnlyList xs when y <= short.MaxValue => createArray3(xs, (short)y, secondCount),
+ IReadOnlyList xs when y <= int .MaxValue => createArray3(xs, (int )y, secondCount),
+ _ => throw new Exception("Invariant 7ddfc8c0-2e66-45ef-94a9-31d21f6009f9.")
+ },
+
+ (IReadOnlyList xs, IReadOnlyList ys) => createArray4( xs , ys ),
+ (IReadOnlyList xs, IReadOnlyList ys) => createArray4(b2s(xs), ys ),
+ (IReadOnlyList xs, IReadOnlyList ys) => createArray4(b2i(xs), ys ),
+ (IReadOnlyList xs, IReadOnlyList ys) => createArray4( xs , b2s(ys)),
+ (IReadOnlyList xs, IReadOnlyList ys) => createArray4( xs , ys ),
+ (IReadOnlyList xs, IReadOnlyList ys) => createArray4(s2i(xs), ys ),
+ (IReadOnlyList xs, IReadOnlyList ys) => createArray4( xs , b2i(ys)),
+ (IReadOnlyList xs, IReadOnlyList ys) => createArray4( xs , s2i(ys)),
+ (IReadOnlyList xs, IReadOnlyList ys) => createArray4( xs , ys ),
+
+ _ => throw new Exception(
+ $"Unexpected part indices types {first?.GetType().FullName ?? "null"} and {second?.GetType().FullName ?? "null"}. " +
+ $"Error 2f0672f5-8c6b-400b-8172-e83a30d70c28"
+ )
+ };
+
+ object createArray1(uint first, int firstCount, uint second, int secondCount)
+ {
+ var count = firstCount + secondCount;
+ return Math.Max(first, second) switch
+ {
+ uint max when max <= byte .MaxValue => create((byte )first, (byte )second),
+ uint max when max <= short.MaxValue => create((short)first, (short)second),
+ uint max when max <= int .MaxValue => create((int )first, (int )second),
+ _ => throw new Exception("Invariant 129edb1c-066d-4ff2-8edf-8c5a67191dea.")
+ };
+
+ object create(T x0, T x1) where T : unmanaged
+ {
+ var xs = new T[count];
+ for (var i = 0; i < firstCount; i++) xs[i] = x0;
+ for (var i = firstCount; i < count; i++) xs[i] = x1;
+ return xs;
+ }
+ }
+
+ object createArray2(T first, int firstCount, IReadOnlyList second) where T : unmanaged
+ {
+ var count = firstCount + second.Count;
+ var xs = new T[count];
+ int j = 0;
+ for (var i = 0; i < firstCount ; i++) xs[j++] = first;
+ for (var i = 0; i < second.Count; i++) xs[j++] = second[i];
+ return xs;
+ }
+
+ object createArray3(IReadOnlyList first, T second, int secondCount) where T : unmanaged
+ {
+ var count = first.Count + secondCount;
+ var xs = new T[count];
+ int j = 0;
+ for (var i = 0; i < first.Count; i++) xs[j++] = first[i];
+ for (var i = 0; i < secondCount; i++) xs[j++] = second;
+ return xs;
+ }
+
+ object createArray4(IReadOnlyList first, IReadOnlyList second) where T : unmanaged
+ {
+ var count = first.Count + second.Count;
+ var xs = new T[count];
+ int j = 0;
+ for (var i = 0; i < first .Count; i++) xs[j++] = first[i];
+ for (var i = 0; i < second.Count; i++) xs[j++] = second[i];
+ return xs;
+ }
+
+ short[] b2s(IReadOnlyList xs) { var ys = new short[xs.Count]; for (var i = 0; i < xs.Count; i++) ys[i] = xs[i]; return ys; }
+ int [] b2i(IReadOnlyList xs) { var ys = new int [xs.Count]; for (var i = 0; i < xs.Count; i++) ys[i] = xs[i]; return ys; }
+ int [] s2i(IReadOnlyList xs) { var ys = new int [xs.Count]; for (var i = 0; i < xs.Count; i++) ys[i] = xs[i]; return ys; }
+ }
+ }
+
+ ///
+ /// Merges part indices (null, uint, [byte|short|int] array).
+ ///
+ public static object? MergeIndices(IEnumerable<(object? indices, int count)> xs)
+ {
+ var (resultIndices, resultCount) = xs.FirstOrDefault();
+ foreach (var (xIndices, xCount) in xs.Skip(1))
+ {
+ MergeIndices(resultIndices, resultCount, xIndices, xCount);
+ resultCount += xCount;
+ }
+ return resultIndices;
+ }
+
+ ///
+ /// Merges part index ranges (null, (u)int, Range1[bsi]).
+ ///
+ public static object? MergeRanges(object? first, object? second)
{
checked
{
return (first, second) switch
{
(null, null) => null,
- (object x, null) => x,
- (null, object y) => y,
+ (uint x, null) => x,
+ (int x, null) => x,
+ (Range1b x, null) => x,
+ (Range1s x, null) => x,
+ (Range1i x, null) => x,
+ (null, uint y) => y,
+ (null, int y) => y,
+ (null, Range1b y) => y,
+ (null, Range1s y) => y,
+ (null, Range1i y) => y,
(uint x, uint y) => (x == y) ? x : new Range1i(new[] { (int)x, (int)y }),
(uint x, IList ys) => ((Range1i)new Range1b(ys)).ExtendedBy((int)x),
(uint x, IList ys) => ((Range1i)new Range1s(ys)).ExtendedBy((int)x),
(uint x, IList ys) => new Range1i(ys).ExtendedBy((int)x),
- (IList xs, uint y) => ((Range1i)new Range1b(xs)).ExtendedBy((int)y),
- (IList xs, uint y) => ((Range1i)new Range1s(xs)).ExtendedBy((int)y),
- (IList xs, uint y) => new Range1i(xs).ExtendedBy((int)y),
+ //(IList xs, uint y) => ((Range1i)new Range1b(xs)).ExtendedBy((int)y),
+ //(IList xs, uint y) => ((Range1i)new Range1s(xs)).ExtendedBy((int)y),
+ //(IList xs, uint y) => new Range1i(xs).ExtendedBy((int)y),
- (IList xs, IList ys) => (Range1i)new Range1b(xs.Concat(ys)),
- (IList xs, IList ys) => (Range1i)new Range1s(xs.Select(x => (short)x).Concat(ys)),
- (IList xs, IList ys) => new Range1i(xs.Select(x => (int)x).Concat(ys)),
+ //(IList xs, IList ys) => (Range1i)new Range1b(xs.Concat(ys)),
+ //(IList xs, IList ys) => (Range1i)new Range1s(xs.Select(x => (short)x).Concat(ys)),
+ //(IList xs, IList ys) => new Range1i(xs.Select(x => (int)x).Concat(ys)),
- (IList xs, IList ys) => (Range1i)new Range1s(xs.Concat(ys.Select(x => (short)x))),
- (IList xs, IList ys) => (Range1i)new Range1s(xs.Concat(ys)),
- (IList xs, IList ys) => new Range1i(xs.Select(x => (int)x).Concat(ys)),
+ //(IList xs, IList ys) => (Range1i)new Range1s(xs.Concat(ys.Select(x => (short)x))),
+ //(IList xs, IList ys) => (Range1i)new Range1s(xs.Concat(ys)),
+ //(IList xs, IList ys) => new Range1i(xs.Select(x => (int)x).Concat(ys)),
- (IList xs, IList ys) => new Range1i(xs.Concat(ys.Select(x => (int)x))),
- (IList xs, IList ys) => new Range1i(xs.Concat(ys.Select(x => (int)x))),
- (IList xs, IList ys) => new Range1i(xs.Concat(ys)),
+ //(IList xs, IList ys) => new Range1i(xs.Concat(ys.Select(x => (int)x))),
+ //(IList xs, IList ys) => new Range1i(xs.Concat(ys.Select(x => (int)x))),
+ //(IList xs, IList ys) => new Range1i(xs.Concat(ys)),
_ => throw new Exception(
- $"Unexpected part indices types {first.GetType().FullName} and {second.GetType().FullName}. " +
+ $"Unexpected part indices types {first?.GetType().FullName ?? "null"} and {second?.GetType().FullName ?? "null"}. " +
$"Error 2f0672f5-8c6b-400b-8172-e83a30d70c28"
)
};
@@ -72,38 +200,38 @@ public static class PartIndexUtils
}
///
- /// Returns union of part indices (uint, IList of [byte|short|int]).
+ /// Merges multiple part index ranges (uint, IList of [byte|short|int]).
///
- public static object? Union(params object?[] xs)
+ public static object? MergeRanges(params object?[] xs)
{
if (xs.Length == 0) return null;
var result = xs[0];
- for (var i = 1; i < xs.Length; i++) result = Union(result, xs[i]);
+ for (var i = 1; i < xs.Length; i++) result = MergeRanges(result, xs[i]);
return result;
}
///
- /// Returns union of part indices (uint, IList of [byte|short|int]).
+ /// Merges multiple part index ranges (uint, IList of [byte|short|int]).
///
- public static object? Union(IEnumerable