diff --git a/src/Aardvark.Algodat.Tests/PartIndicesTests.cs b/src/Aardvark.Algodat.Tests/PartIndicesTests.cs
new file mode 100644
index 0000000..2aca1d4
--- /dev/null
+++ b/src/Aardvark.Algodat.Tests/PartIndicesTests.cs
@@ -0,0 +1,123 @@
+/*
+ Copyright (C) 2006-2023. Aardvark Platform Team. http://github.com/aardvark-platform.
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+*/
+using Aardvark.Base;
+using Aardvark.Data.Points;
+using NUnit.Framework;
+using System;
+using System.Collections.Generic;
+
+namespace Aardvark.Geometry.Tests;
+
+[TestFixture]
+public class PartIndicesTests
+{
+ private static bool cmp(IReadOnlyList xs, IReadOnlyList ys) where T : IEquatable
+ {
+ if (xs.Count != ys.Count) return false;
+ for (var i = 0; i < xs.Count; i++) if (!xs[i].Equals(ys[i])) return false;
+ return true;
+ }
+
+ [Test]
+ public void ConcatIndices_nulls()
+ {
+ { Assert.True( PartIndexUtils.ConcatIndices(first: null, firstCount: 0, second: null, secondCount: 0) is null); }
+ { Assert.Catch(() => PartIndexUtils.ConcatIndices(first: null, firstCount: 0, second: 1u, secondCount: 3)); }
+ { Assert.Catch(() => PartIndexUtils.ConcatIndices(first: 1u, firstCount: 3, second: null, secondCount: 0)); }
+ }
+
+ [Test]
+ public void ConcatIndices_single_identical()
+ {
+ { Assert.True(PartIndexUtils.ConcatIndices(first: 1u, firstCount: 2, second: 1u, secondCount: 3) is uint x && x == 1u ); }
+ { Assert.True(PartIndexUtils.ConcatIndices(first: 256u, firstCount: 2, second: 256u, secondCount: 3) is uint x && x == 256u ); }
+ { Assert.True(PartIndexUtils.ConcatIndices(first: 32768u, firstCount: 2, second: 32768u, secondCount: 3) is uint x && x == 32768u); }
+ }
+
+ [Test]
+ public void ConcatIndices_single_different()
+ {
+ { Assert.True(PartIndexUtils.ConcatIndices(first: 1u, firstCount: 2, second: 2u, secondCount: 3) is byte [] xs && cmp(xs, new byte [] { 1, 1, 2, 2, 2 })); }
+ { Assert.True(PartIndexUtils.ConcatIndices(first: 1u, firstCount: 2, second: 257u, secondCount: 3) is short[] xs && cmp(xs, new short[] { 1, 1, 257, 257, 257 })); }
+ { Assert.True(PartIndexUtils.ConcatIndices(first: 1u, firstCount: 2, second: 32769u, secondCount: 3) is int [] xs && cmp(xs, new int [] { 1, 1, 32769, 32769, 32769 })); }
+
+ { Assert.True(PartIndexUtils.ConcatIndices(first: 256u, firstCount: 2, second: 2u, secondCount: 3) is short[] xs && cmp(xs, new short[] { 256, 256, 2, 2, 2 })); }
+ { Assert.True(PartIndexUtils.ConcatIndices(first: 256u, firstCount: 2, second: 257u, secondCount: 3) is short[] xs && cmp(xs, new short[] { 256, 256, 257, 257, 257 })); }
+ { Assert.True(PartIndexUtils.ConcatIndices(first: 256u, firstCount: 2, second: 32769u, secondCount: 3) is int [] xs && cmp(xs, new int [] { 256, 256, 32769, 32769, 32769 })); }
+
+ { Assert.True(PartIndexUtils.ConcatIndices(first: 32768u, firstCount: 2, second: 2u, secondCount: 3) is int [] xs && cmp(xs, new int [] { 32768, 32768, 2, 2, 2 })); }
+ { Assert.True(PartIndexUtils.ConcatIndices(first: 32768u, firstCount: 2, second: 257u, secondCount: 3) is int [] xs && cmp(xs, new int [] { 32768, 32768, 257, 257, 257 })); }
+ { Assert.True(PartIndexUtils.ConcatIndices(first: 32768u, firstCount: 2, second: 32769u, secondCount: 3) is int [] xs && cmp(xs, new int [] { 32768, 32768, 32769, 32769, 32769 })); }
+ }
+
+
+ [Test]
+ public void ConcatIndices_single_and_array()
+ {
+ { Assert.True(PartIndexUtils.ConcatIndices(first: 1u, firstCount: 2, second: new byte [] { 2, 3, 4 }, secondCount: 3) is byte [] xs && cmp(xs, new byte [] { 1, 1, 2, 3, 4 })); }
+ { Assert.True(PartIndexUtils.ConcatIndices(first: 1u, firstCount: 2, second: new short[] { 2, 3, 4 }, secondCount: 3) is short[] xs && cmp(xs, new short[] { 1, 1, 2, 3, 4 })); }
+ { Assert.True(PartIndexUtils.ConcatIndices(first: 1u, firstCount: 2, second: new int [] { 2, 3, 4 }, secondCount: 3) is int [] xs && cmp(xs, new int [] { 1, 1, 2, 3, 4 })); }
+
+ { Assert.True(PartIndexUtils.ConcatIndices(first: 256u, firstCount: 2, second: new byte [] { 2, 3, 4 }, secondCount: 3) is short[] xs && cmp(xs, new short[] { 256, 256, 2, 3, 4 })); }
+ { Assert.True(PartIndexUtils.ConcatIndices(first: 256u, firstCount: 2, second: new short[] { 2, 3, 4 }, secondCount: 3) is short[] xs && cmp(xs, new short[] { 256, 256, 2, 3, 4 })); }
+ { Assert.True(PartIndexUtils.ConcatIndices(first: 256u, firstCount: 2, second: new int [] { 2, 3, 4 }, secondCount: 3) is int [] xs && cmp(xs, new int [] { 256, 256, 2, 3, 4 })); }
+
+ { Assert.True(PartIndexUtils.ConcatIndices(first: 32768u, firstCount: 2, second: new byte [] { 2, 3, 4 }, secondCount: 3) is int [] xs && cmp(xs, new int [] { 32768, 32768, 2, 3, 4 })); }
+ { Assert.True(PartIndexUtils.ConcatIndices(first: 32768u, firstCount: 2, second: new short[] { 2, 3, 4 }, secondCount: 3) is int [] xs && cmp(xs, new int [] { 32768, 32768, 2, 3, 4 })); }
+ { Assert.True(PartIndexUtils.ConcatIndices(first: 32768u, firstCount: 2, second: new int [] { 2, 3, 4 }, secondCount: 3) is int [] xs && cmp(xs, new int [] { 32768, 32768, 2, 3, 4 })); }
+ }
+
+ [Test]
+ public void ConcatIndices_array_array()
+ {
+ { Assert.True(PartIndexUtils.ConcatIndices(first: new byte [] { 2, 3 }, firstCount: 2, second: new byte [] { 4, 5 }, secondCount: 2) is byte [] xs && cmp(xs, new byte [] { 2, 3, 4, 5 })); }
+ { Assert.True(PartIndexUtils.ConcatIndices(first: new byte [] { 2, 3 }, firstCount: 2, second: new short[] { 4, 5 }, secondCount: 2) is short[] xs && cmp(xs, new short[] { 2, 3, 4, 5 })); }
+ { Assert.True(PartIndexUtils.ConcatIndices(first: new byte [] { 2, 3 }, firstCount: 2, second: new int [] { 4, 5 }, secondCount: 2) is int [] xs && cmp(xs, new int [] { 2, 3, 4, 5 })); }
+
+ { Assert.True(PartIndexUtils.ConcatIndices(first: new short[] { 2, 3 }, firstCount: 2, second: new byte [] { 4, 5 }, secondCount: 2) is short[] xs && cmp(xs, new short[] { 2, 3, 4, 5 })); }
+ { Assert.True(PartIndexUtils.ConcatIndices(first: new short[] { 2, 3 }, firstCount: 2, second: new short[] { 4, 5 }, secondCount: 2) is short[] xs && cmp(xs, new short[] { 2, 3, 4, 5 })); }
+ { Assert.True(PartIndexUtils.ConcatIndices(first: new short[] { 2, 3 }, firstCount: 2, second: new int [] { 4, 5 }, secondCount: 2) is int [] xs && cmp(xs, new int [] { 2, 3, 4, 5 })); }
+
+ { Assert.True(PartIndexUtils.ConcatIndices(first: new int [] { 2, 3 }, firstCount: 2, second: new byte [] { 4, 5 }, secondCount: 2) is int [] xs && cmp(xs, new int [] { 2, 3, 4, 5 })); }
+ { Assert.True(PartIndexUtils.ConcatIndices(first: new int [] { 2, 3 }, firstCount: 2, second: new short[] { 4, 5 }, secondCount: 2) is int [] xs && cmp(xs, new int [] { 2, 3, 4, 5 })); }
+ { Assert.True(PartIndexUtils.ConcatIndices(first: new int [] { 2, 3 }, firstCount: 2, second: new int [] { 4, 5 }, secondCount: 2) is int [] xs && cmp(xs, new int [] { 2, 3, 4, 5 })); }
+ }
+
+ [Test]
+ public void ExtendRangeBy()
+ {
+ Assert.True(PartIndexUtils.ExtendRangeBy(new Range1i(7, 11), 8u) == new Range1i(7, 11));
+ Assert.True(PartIndexUtils.ExtendRangeBy(new Range1i(7, 11), 1u) == new Range1i(1, 11));
+ Assert.True(PartIndexUtils.ExtendRangeBy(new Range1i(7, 11), 42u) == new Range1i(7, 42));
+
+ Assert.True(PartIndexUtils.ExtendRangeBy(new Range1i(7, 11), 8) == new Range1i(7, 11));
+ Assert.True(PartIndexUtils.ExtendRangeBy(new Range1i(7, 11), 1) == new Range1i(1, 11));
+ Assert.True(PartIndexUtils.ExtendRangeBy(new Range1i(7, 11), 42) == new Range1i(7, 42));
+
+ Assert.True(PartIndexUtils.ExtendRangeBy(new Range1i(7, 11), new byte[] { 2, 12 }) == new Range1i(2, 12));
+ Assert.True(PartIndexUtils.ExtendRangeBy(new Range1i(7, 11), new byte[] { 8, 10 }) == new Range1i(7, 11));
+
+ Assert.True(PartIndexUtils.ExtendRangeBy(new Range1i(7, 11), new short[] { 2, 12 }) == new Range1i(2, 12));
+ Assert.True(PartIndexUtils.ExtendRangeBy(new Range1i(7, 11), new short[] { 8, 10 }) == new Range1i(7, 11));
+
+ Assert.True(PartIndexUtils.ExtendRangeBy(new Range1i(7, 11), new int[] { 2, 12 }) == new Range1i(2, 12));
+ Assert.True(PartIndexUtils.ExtendRangeBy(new Range1i(7, 11), new int[] { 8, 10 }) == new Range1i(7, 11));
+ }
+
+ [Test]
+ public void ExtendRangeBy_Fail()
+ {
+ Assert.Catch(() => PartIndexUtils.ExtendRangeBy(new Range1i(7, 11), null!));
+ }
+}
diff --git a/src/Aardvark.Data.Points.Base/Chunk.cs b/src/Aardvark.Data.Points.Base/Chunk.cs
index a7cde68..20e2d85 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.MergeIndices(a.PartIndices, a.Count, b.PartIndices, b.Count), new Box3d(a.BoundingBox, b.BoundingBox));
+ return new Chunk(ps, cs, ns, js, ks, PartIndexUtils.ConcatIndices(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.MergeIndices(chunks.Select(x => (indices: x.PartIndices, count: x.Count))),
+ partIndices: PartIndexUtils.ConcatIndices(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.MergeIndices(PartIndices, Count, other.PartIndices, other.Count),
+ partIndices: PartIndexUtils.ConcatIndices(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 ea54ff9..6eaf397 100644
--- a/src/Aardvark.Data.Points.Base/PartIndexUtils.cs
+++ b/src/Aardvark.Data.Points.Base/PartIndexUtils.cs
@@ -18,6 +18,7 @@ limitations under the License.
using Aardvark.Base;
using System;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.Linq;
#pragma warning disable CS1591
@@ -30,14 +31,15 @@ namespace Aardvark.Data.Points;
public static class PartIndexUtils
{
///
- /// Merges part indices (null, uint, [byte|short|int] array).
+ /// Concatenates part indices (uint, [byte|short|int] array).
///
- public static object? MergeIndices(object? first, int firstCount, object? second, int secondCount)
+ public static object? ConcatIndices(
+ 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."
- );
+ // expect: both defined, or both null
+ if ((first != null && second == null) || (first == null && second != null)) throw new Exception("Invariant 7e8345fc-c993-48fd-9862-33c9928aba3f.");
checked
{
@@ -49,17 +51,29 @@ public static class PartIndexUtils
(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),
+ IReadOnlyList ys when x <= byte .MaxValue => createArray2((byte )x, firstCount, ys ),
+ IReadOnlyList ys when x <= short.MaxValue => createArray2((short)x, firstCount, b2s(ys)),
+ IReadOnlyList ys when x <= int .MaxValue => createArray2((int )x, firstCount, b2i(ys)),
+
+ IReadOnlyList ys when x <= short.MaxValue => createArray2((short)x, firstCount, ys ),
+ IReadOnlyList ys when x <= int .MaxValue => createArray2((int )x, firstCount, s2i(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
+ (_ , uint y) => first 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 <= byte .MaxValue => createArray3( xs , (byte )y, secondCount),
+ IReadOnlyList xs when y <= short.MaxValue => createArray3(b2s(xs), (short)y, secondCount),
+ IReadOnlyList xs when y <= int .MaxValue => createArray3(b2i(xs), (int )y, secondCount),
+
+ IReadOnlyList xs when y <= short.MaxValue => createArray3( xs , (short)y, secondCount),
+ IReadOnlyList xs when y <= int .MaxValue => createArray3(s2i(xs), (int )y, secondCount),
+
IReadOnlyList xs when y <= int .MaxValue => createArray3(xs, (int )y, secondCount),
+
_ => throw new Exception("Invariant 7ddfc8c0-2e66-45ef-94a9-31d21f6009f9.")
},
@@ -136,98 +150,28 @@ object createArray4(IReadOnlyList first, IReadOnlyList second) where T
}
///
- /// Merges part indices (null, uint, [byte|short|int] array).
+ /// Concatenates part indices (null, uint, [byte|short|int] array).
///
- public static object? MergeIndices(IEnumerable<(object? indices, int count)> xs)
+ public static object? ConcatIndices(IEnumerable<(object? indices, int count)> xs)
{
var (resultIndices, resultCount) = xs.FirstOrDefault();
foreach (var (xIndices, xCount) in xs.Skip(1))
{
- MergeIndices(resultIndices, resultCount, xIndices, xCount);
+ ConcatIndices(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,
- (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, 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) => 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 ?? "null"} and {second?.GetType().FullName ?? "null"}. " +
- $"Error 2f0672f5-8c6b-400b-8172-e83a30d70c28"
- )
- };
- }
- }
-
- ///
- /// Merges multiple part index ranges (uint, IList of [byte|short|int]).
- ///
- 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 = MergeRanges(result, xs[i]);
- return result;
- }
-
- ///
- /// Merges multiple part index ranges (uint, IList of [byte|short|int]).
- ///
- public static object? MergeRanges(IEnumerable