diff --git a/src/Aardvark.Data.Points.Base/Storage.cs b/src/Aardvark.Data.Points.Base/Storage.cs index 899780dd..84139397 100644 --- a/src/Aardvark.Data.Points.Base/Storage.cs +++ b/src/Aardvark.Data.Points.Base/Storage.cs @@ -46,7 +46,9 @@ public class Storage : IDisposable /// add(key, value, create) public readonly Action> f_add; - /// + /// + /// Returns null if key does not exist. + /// public readonly Func f_get; /// diff --git a/src/Aardvark.Geometry.PointSet/Octrees/Export.cs b/src/Aardvark.Geometry.PointSet/Octrees/Export.cs index 097ff4d6..f27cd7d3 100644 --- a/src/Aardvark.Geometry.PointSet/Octrees/Export.cs +++ b/src/Aardvark.Geometry.PointSet/Octrees/Export.cs @@ -84,8 +84,7 @@ public static ExportPointSetInfo ExportPointSet( if (pointSet == null) { - var (success, root) = self.TryGetPointCloudNode(pointSetId); - if (success) + if (self.TryGetPointCloudNode(pointSetId, out var root)) { var ersatzPointSetKey = Guid.NewGuid().ToString(); Report.Warn($"Created PointSet with key '{ersatzPointSetKey}'."); diff --git a/src/Aardvark.Geometry.PointSet/Octrees/IPointCloudNodeExtensions.cs b/src/Aardvark.Geometry.PointSet/Octrees/IPointCloudNodeExtensions.cs index 00ae7300..51d7fc59 100644 --- a/src/Aardvark.Geometry.PointSet/Octrees/IPointCloudNodeExtensions.cs +++ b/src/Aardvark.Geometry.PointSet/Octrees/IPointCloudNodeExtensions.cs @@ -73,7 +73,7 @@ public static void ForEachNode( var n = self.Subnodes[i]; if (n != null) { - if (n.TryGetValue(out var node)) node.ForEachNode(outOfCore, action); + if (n.TryGetFromCache(out var node)) node.ForEachNode(outOfCore, action); } } } @@ -148,7 +148,7 @@ public static void ForEachIntersectingNode( var n = self.Subnodes[i]; if (n != null) { - if (n.TryGetValue(out var node)) + if (n.TryGetFromCache(out var node)) { node.ForEachIntersectingNode(outOfCore, hull, doNotTraverseSubnodesWhenFullyInside, action, ct); } @@ -424,7 +424,7 @@ long FastCount(Guid key) var n = self.Subnodes[i]; if (n != null) { - if (n.TryGetValue(out var node)) count += node.CountNodes(outOfCore); + if (n.TryGetFromCache(out var node)) count += node.CountNodes(outOfCore); } } } @@ -455,7 +455,7 @@ public static long CountLeafNodes(this IPointCloudNode self, bool outOfCore) var n = self.Subnodes[i]; if (n != null) { - if (n.TryGetValue(out var node)) count += node.CountLeafNodes(outOfCore); + if (n.TryGetFromCache(out var node)) count += node.CountLeafNodes(outOfCore); } } } @@ -489,7 +489,7 @@ public static long GetMinimumLeafPointCount(this IPointCloudNode self, bool outO var n = self.Subnodes[i]; if (n != null) { - if (n.TryGetValue(out var node)) + if (n.TryGetFromCache(out var node)) { var x = node.GetMinimumLeafPointCount(outOfCore); if (x < min) min = x; @@ -528,7 +528,7 @@ public static long GetMaximumLeafPointCount(this IPointCloudNode self, bool outO var n = self.Subnodes[i]; if (n != null) { - if (n.TryGetValue(out var node)) + if (n.TryGetFromCache(out var node)) { var x = node.GetMinimumLeafPointCount(outOfCore); if (x > max) max = x; @@ -576,7 +576,7 @@ public static int GetMinimumTreeDepth(this IPointCloudNode self, bool outOfCore) var n = self.Subnodes[i]; if (n != null) { - if (n.TryGetValue(out var node)) + if (n.TryGetFromCache(out var node)) { var x = node.GetMinimumTreeDepth(outOfCore); if (x < min) min = x; @@ -615,7 +615,7 @@ public static int GetMaximiumTreeDepth(this IPointCloudNode self, bool outOfCore var n = self.Subnodes[i]; if (n != null) { - if (n.TryGetValue(out var node)) + if (n.TryGetFromCache(out var node)) { var x = node.GetMaximiumTreeDepth(outOfCore); if (x > max) max = x; @@ -660,7 +660,7 @@ private static void GetAverageTreeDepth(this IPointCloudNode self, bool outOfCor var n = self.Subnodes[i]; if (n != null) { - if (n.TryGetValue(out var node)) node.GetAverageTreeDepth(outOfCore, depth, ref sum, ref count); + if (n.TryGetFromCache(out var node)) node.GetAverageTreeDepth(outOfCore, depth, ref sum, ref count); } } } diff --git a/src/Aardvark.Geometry.PointSet/Octrees/Inline.cs b/src/Aardvark.Geometry.PointSet/Octrees/Inline.cs index f63aefc8..48866103 100644 --- a/src/Aardvark.Geometry.PointSet/Octrees/Inline.cs +++ b/src/Aardvark.Geometry.PointSet/Octrees/Inline.cs @@ -306,7 +306,7 @@ static IEnumerable EnumerateRecImpl(IPointCloudNode node, HashSet survive var hasColors = node.HasColors; var hasClassifications = node.HasClassifications; var hasIntensities = node.HasIntensities; - var subnodes = node.Subnodes?.Map(x => x?.TryGetValue()); + var subnodes = node.Subnodes?.Map(x => x?.Value); var isNotLeaf = !node.IsLeaf; var ps = default(V3f[]); @@ -418,7 +418,7 @@ static byte[] rescaleIntensities(int[] js32) if (config.Collapse && isNotLeaf) { if (subnodes == null) throw new Exception("Assertion failed. Error 42565d4a-2e91-4961-a310-095b503fe6f1."); - var nonEmptySubNodes = subnodes.Where(x => x.HasValue && x.Value.hasValue).Select(x => x!.Value.value!).ToArray(); + var nonEmptySubNodes = subnodes.Where(x => x != null).Select(x => x!).ToArray(); ps = nonEmptySubNodes .SelectMany(n => @@ -457,9 +457,9 @@ static byte[] rescaleIntensities(int[] js32) var guids2 = subnodes .Map(nref => { - if (nref.HasValue && nref.Value.hasValue) + if (nref != null) { - var n = nref.Value.value!; + var n = nref!; return !n.IsLeaf ? n.Id : Guid.Empty; } else @@ -471,7 +471,7 @@ static byte[] rescaleIntensities(int[] js32) var isNewLeaf = guids2.All(k => k == Guid.Empty); if (!isNewLeaf) { - subnodeGuids = subnodes.Map(x => x.HasValue && x.Value.hasValue ? x.Value.value!.Id : Guid.Empty); + subnodeGuids = subnodes.Map(x => x != null ? x.Id : Guid.Empty); foreach (var g in nonEmptySubNodes) survive.Add(g.Id); } } @@ -479,14 +479,14 @@ static byte[] rescaleIntensities(int[] js32) { if (isNotLeaf) { - subnodeGuids = subnodes.Map(x => x.HasValue && x.Value.hasValue ? x.Value.value!.Id : Guid.Empty); + subnodeGuids = subnodes.Map(x => x != null ? x.Id : Guid.Empty); } ps = node.Positions.Value!; if (hasColors) cs = node.Colors!.Value; if (hasClassifications) ks = node.Classifications!.Value; if (hasIntensities) js = rescaleIntensities(node.Intensities!.Value!); - if (isNotLeaf) subnodeGuids = subnodes.Map(x => x.HasValue && x.Value.hasValue ? x.Value.value!.Id : Guid.Empty); + if (isNotLeaf) subnodeGuids = subnodes.Map(x => x != null ? x.Id : Guid.Empty); } diff --git a/src/Aardvark.Geometry.PointSet/Octrees/PointSet.cs b/src/Aardvark.Geometry.PointSet/Octrees/PointSet.cs index cb29f2c9..8334ca36 100644 --- a/src/Aardvark.Geometry.PointSet/Octrees/PointSet.cs +++ b/src/Aardvark.Geometry.PointSet/Octrees/PointSet.cs @@ -15,6 +15,7 @@ You should have received a copy of the GNU Affero General Public License using Aardvark.Data.Points; using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text.Json; using System.Text.Json.Nodes; @@ -95,8 +96,8 @@ public PointSet(Storage storage, string pointSetId, Guid rootCellId, int splitLi Id = pointSetId ?? throw new ArgumentNullException(nameof(pointSetId)); SplitLimit = splitLimit; - Root = new PersistentRef(rootCellId.ToString(), storage.GetPointCloudNode!, - k => { var (a, b) = storage.TryGetPointCloudNode(k); return (a, b); } + Root = new PersistentRef(rootCellId.ToString(), storage.GetPointCloudNode, + storage.TryGetPointCloudNode ); } @@ -111,7 +112,7 @@ public PointSet(Storage storage, string key, IPointCloudNode root, int splitLimi Id = key ?? throw new ArgumentNullException(nameof(key)); SplitLimit = splitLimit; - Root = new PersistentRef(root.Id.ToString(), storage.GetPointCloudNode!, storage.TryGetPointCloudNode); + Root = new PersistentRef(root.Id.ToString(), storage.GetPointCloudNode, storage.TryGetPointCloudNode); } /// @@ -123,7 +124,7 @@ public PointSet(Storage storage, string key) Id = key ?? throw new ArgumentNullException(nameof(key)); SplitLimit = 0; - Root = new(id: "", _ => PointSetNode.Empty, _ => (true, PointSetNode.Empty)); + Root = new(id: Guid.Empty, PointSetNode.Empty); } #endregion @@ -156,8 +157,8 @@ public PointSet(Storage storage, string key) public JsonNode ToJson() => JsonSerializer.SerializeToNode(new { Id, - RootCellId = Root.Id, - OctreeId = Root.Id, // backwards compatibility + OctreeId = Root.Id, + RootCellId = Root.Id, // backwards compatibility SplitLimit, PartIndexRange })!; @@ -168,18 +169,22 @@ public static PointSet Parse(JsonNode json, Storage storage) { var o = json.AsObject() ?? throw new Exception($"Expected JSON object, but found {json}."); + // id + var id = (string?)o["Id"] ?? throw new Exception("Missing id. Error 71730558-699e-4128-b0f2-130fd04672e9."); + + var octreeId = (string?)o["OctreeId"] ?? (string?)o["RootCellId"]; + if (octreeId == "" || octreeId == Guid.Empty.ToString()) octreeId = null; + var octreeRef = octreeId != null - ? new PersistentRef(octreeId, storage.GetPointCloudNode!, storage.TryGetPointCloudNode) + ? new PersistentRef(octreeId, storage.GetPointCloudNode, storage.TryGetPointCloudNode) : null ; + var octree = octreeRef?.Value; // backwards compatibility: if split limit is not set, guess as number of points in root cell var splitLimit = o.TryGetPropertyValue("SplitLimit", out var x) ? (int)x! : 8192; - // id - var id = (string?)o["Id"] ?? throw new Exception("Missing id. Error 71730558-699e-4128-b0f2-130fd04672e9."); - // part index range (JsonArray) var partIndexRangeArray = (JsonArray?)o["PartIndexRange"]; var partIndexRange = partIndexRangeArray != null @@ -187,8 +192,6 @@ public static PointSet Parse(JsonNode json, Storage storage) : Range1i.Invalid ; - // - var octree = octreeRef?.Value; return new PointSet(storage, id, octree ?? PointSetNode.Empty, splitLimit).WithPartIndexRange(partIndexRange); } diff --git a/src/Aardvark.Geometry.PointSet/Octrees/PointSetNode.cs b/src/Aardvark.Geometry.PointSet/Octrees/PointSetNode.cs index 22d0e58c..f56951da 100644 --- a/src/Aardvark.Geometry.PointSet/Octrees/PointSetNode.cs +++ b/src/Aardvark.Geometry.PointSet/Octrees/PointSetNode.cs @@ -162,26 +162,26 @@ public PointSetNode( var isId = IntensitiesId; var ksId = ClassificationsId; - if (psId != null) PersistentRefs[Durable.Octree.PositionsLocal3fReference] = new PersistentRef(psId.Value, storage.GetV3fArray!, storage.TryGetV3fArray); - if (csId != null) PersistentRefs[Durable.Octree.Colors4bReference] = new PersistentRef(csId.Value, storage.GetC4bArray!, storage.TryGetC4bArray); + if (psId != null) PersistentRefs[Durable.Octree.PositionsLocal3fReference] = new PersistentRef(psId.Value, storage.GetV3fArray, storage.TryGetV3fArrayFromCache); + if (csId != null) PersistentRefs[Durable.Octree.Colors4bReference] = new PersistentRef(csId.Value, storage.GetC4bArray, storage.TryGetC4bArrayFromCache); if (kdId != null) { if (isObsoleteFormat) { PersistentRefs[Durable.Octree.PointRkdTreeFDataReference] = - new PersistentRef>(kdId.Value, LoadKdTreeObsolete, TryLoadKdTreeObsolete) + new PersistentRef>(kdId.Value, LoadKdTreeObsolete, TryLoadKdTreeObsoleteOut) ; } else { PersistentRefs[Durable.Octree.PointRkdTreeFDataReference] = - new PersistentRef>(kdId.Value, LoadKdTree, TryLoadKdTree) + new PersistentRef>(kdId.Value, LoadKdTree, TryLoadKdTreeOut) ; } } - if (nsId != null) PersistentRefs[Durable.Octree.Normals3fReference] = new PersistentRef(nsId.Value, storage.GetV3fArray!, storage.TryGetV3fArray); - if (isId != null) PersistentRefs[Durable.Octree.Intensities1iReference] = new PersistentRef(isId.Value, storage.GetIntArray!, storage.TryGetIntArray); - if (ksId != null) PersistentRefs[Durable.Octree.Classifications1bReference] = new PersistentRef(ksId.Value, storage.GetByteArray!, storage.TryGetByteArray); + if (nsId != null) PersistentRefs[Durable.Octree.Normals3fReference] = new PersistentRef(nsId.Value, storage.GetV3fArray, storage.TryGetV3fArrayFromCache); + if (isId != null) PersistentRefs[Durable.Octree.Intensities1iReference] = new PersistentRef(isId.Value, storage.GetIntArray, storage.TryGetIntArrayFromCache); + if (ksId != null) PersistentRefs[Durable.Octree.Classifications1bReference] = new PersistentRef(ksId.Value, storage.GetByteArray, storage.TryGetByteArrayFromCache); #endregion @@ -323,7 +323,7 @@ public PointSetNode( kdId = ComputeAndStoreKdTree(Storage, Positions.Value); Data = Data.Add(Durable.Octree.PointRkdTreeFDataReference, kdId); PersistentRefs[Durable.Octree.PointRkdTreeFDataReference] = - new PersistentRef>(kdId.Value, LoadKdTree, TryLoadKdTree) + new PersistentRef>(kdId.Value, LoadKdTree, TryLoadKdTreeOut) ; #else //Debugger.Break(); @@ -403,20 +403,6 @@ PointRkdTreeF LoadKdTree(string key) ); } - (bool, PointRkdTreeF?) TryLoadKdTree(string key) - { - var (ok, value) = Storage.TryGetPointRkdTreeFData(key); - if (ok == false) return (false, default); - var ps = Positions.Value!; - return (true, new PointRkdTreeF( - 3, ps.Length, ps, - (xs, i) => xs[(int)i], (v, i) => (float)v[i], - (a, b) => Vec.Distance(a, b), (i, a, b) => b - a, - (a, b, c) => Vec.DistanceToLine(a, b, c), Fun.Lerp, 1e-6f, - value - )); - } - PointRkdTreeF LoadKdTreeObsolete(string key) { var value = Storage.GetPointRkdTreeFDataFromD(key); @@ -430,18 +416,76 @@ PointRkdTreeF LoadKdTreeObsolete(string key) ); } - (bool, PointRkdTreeF?) TryLoadKdTreeObsolete(string key) + //(bool, PointRkdTreeF?) TryLoadKdTree(string key) + //{ + // var (ok, value) = Storage.TryGetPointRkdTreeFData(key); + // if (ok == false) return (false, default); + // var ps = Positions.Value!; + // return (true, new PointRkdTreeF( + // 3, ps.Length, ps, + // (xs, i) => xs[(int)i], (v, i) => (float)v[i], + // (a, b) => Vec.Distance(a, b), (i, a, b) => b - a, + // (a, b, c) => Vec.DistanceToLine(a, b, c), Fun.Lerp, 1e-6f, + // value + // )); + //} + + //(bool, PointRkdTreeF?) TryLoadKdTreeObsolete(string key) + //{ + // var (ok, value) = Storage.TryGetPointRkdTreeFDataFromD(key); + // if (ok == false) return (false, default); + // var ps = Positions.Value!; + // return (true, new PointRkdTreeF( + // 3, ps.Length, ps, + // (xs, i) => xs[(int)i], (v, i) => (float)v[i], + // (a, b) => Vec.Distance(a, b), (i, a, b) => b - a, + // (a, b, c) => Vec.DistanceToLine(a, b, c), Fun.Lerp, 1e-6f, + // value + // )); + //} + + bool TryLoadKdTreeOut(string key, [NotNullWhen(true)] out PointRkdTreeF? result) + { + var (ok, value) = Storage.TryGetPointRkdTreeFData(key); + if (ok == false) + { + result = default; + return false; + } + else + { + var ps = Positions.Value!; + result = new PointRkdTreeF( + 3, ps.Length, ps, + (xs, i) => xs[(int)i], (v, i) => (float)v[i], + (a, b) => Vec.Distance(a, b), (i, a, b) => b - a, + (a, b, c) => Vec.DistanceToLine(a, b, c), Fun.Lerp, 1e-6f, + value + ); + return true; + } + } + + bool TryLoadKdTreeObsoleteOut(string key, [NotNullWhen(true)] out PointRkdTreeF? result) { var (ok, value) = Storage.TryGetPointRkdTreeFDataFromD(key); - if (ok == false) return (false, default); - var ps = Positions.Value!; - return (true, new PointRkdTreeF( - 3, ps.Length, ps, - (xs, i) => xs[(int)i], (v, i) => (float)v[i], - (a, b) => Vec.Distance(a, b), (i, a, b) => b - a, - (a, b, c) => Vec.DistanceToLine(a, b, c), Fun.Lerp, 1e-6f, - value - )); + if (ok == false) + { + result = default; + return false; + } + else + { + var ps = Positions.Value!; + result = new PointRkdTreeF( + 3, ps.Length, ps, + (xs, i) => xs[(int)i], (v, i) => (float)v[i], + (a, b) => Vec.Distance(a, b), (i, a, b) => b - a, + (a, b, c) => Vec.DistanceToLine(a, b, c), Fun.Lerp, 1e-6f, + value + ); + return true; + } } } @@ -571,13 +615,13 @@ public PersistentRef Positions else { var ps = Array.Empty(); - return new PersistentRef(Guid.Empty, _ => ps, _ => (true, ps)); + return new PersistentRef(Guid.Empty, ps); } } else if (Data.TryGetValue(Durable.Octree.PositionsLocal3f, out o)) { var ps = (V3f[])o; - return new PersistentRef(Guid.Empty, _ => ps, _ => (true, ps)); + return new PersistentRef(Guid.Empty, ps); } else if (Data.TryGetValue(Durable.Octree.PositionsLocal3b, out o)) { @@ -588,7 +632,7 @@ public PersistentRef Positions var ps = new V3f[pCount]; for (int i = 0, j = 0; i < pCount; i++) ps[i] = new V3f(qs[j++] * step - hsize, qs[j++] * step - hsize, qs[j++] * step - hsize); - return new PersistentRef(Guid.Empty, _ => ps, _ => (true, ps)); + return new PersistentRef(Guid.Empty, ps); } else if (Data.TryGetValue(Durable.Octree.PositionsLocal3us, out o)) { @@ -599,7 +643,7 @@ public PersistentRef Positions var ps = new V3f[pCount]; for (int i = 0, j = 0; i < pCount; i++) ps[i] = new V3f(qs[j++] * step - hsize, qs[j++] * step - hsize, qs[j++] * step - hsize); - return new PersistentRef(Guid.Empty, _ => ps, _ => (true, ps)); + return new PersistentRef(Guid.Empty, ps); } else if (Data.TryGetValue(Durable.Octree.PositionsLocal3ui, out o)) { @@ -610,7 +654,7 @@ public PersistentRef Positions var ps = new V3f[pCount]; for (int i = 0, j = 0; i < pCount; i++) ps[i] = new V3f(qs[j++] * step - hsize, qs[j++] * step - hsize, qs[j++] * step - hsize); - return new PersistentRef(Guid.Empty, _ => ps, _ => (true, ps)); + return new PersistentRef(Guid.Empty, ps); } else if (Data.TryGetValue(Durable.Octree.PositionsLocal3ul, out o)) { @@ -621,11 +665,10 @@ public PersistentRef Positions var ps = new V3f[pCount]; for (int i = 0, j = 0; i < pCount; i++) ps[i] = new V3f(qs[j++] * step - hsize, qs[j++] * step - hsize, qs[j++] * step - hsize); - return new PersistentRef(Guid.Empty, _ => ps, _ => (true, ps)); + return new PersistentRef(Guid.Empty, ps); } else return null!; - //return new(id: "", _ => Array.Empty(), _ => (true, Array.Empty())); } } @@ -710,20 +753,20 @@ public PersistentRef? Colors else if (Data.TryGetValue(Durable.Octree.Colors4b, out o)) { var xs = (C4b[])o; - return new PersistentRef(Guid.Empty, _ => xs, _ => (true, xs)); + return new PersistentRef(Guid.Empty, xs); } else if (PersistentRefs.TryGetValue(Durable.Octree.Colors3bReference, out o) && ((PersistentRef)o).Id != GuidEmptyString) { // convert on the fly ... var pref = (PersistentRef)o; var xs = pref.Value.Map(c => new C4b(c)); - return new PersistentRef(Guid.Empty, _ => xs, _ => (true, xs)); + return new PersistentRef(Guid.Empty, xs); } else if (Data.TryGetValue(Durable.Octree.Colors3b, out o)) { // convert on the fly var xs = ((C3b[])o).Map(c => new C4b(c)); - return new PersistentRef(Guid.Empty, _ => xs, _ => (true, xs)); + return new PersistentRef(Guid.Empty, xs); } else { @@ -762,7 +805,7 @@ public PersistentRef? Normals else if (Data.TryGetValue(Durable.Octree.Normals3f, out o)) { var xs = (V3f[])o; - return new PersistentRef(Guid.Empty, _ => xs, _ => (true, xs)); + return new PersistentRef(Guid.Empty, xs); } else { @@ -801,7 +844,7 @@ public PersistentRef? Intensities else if (Data.TryGetValue(Durable.Octree.Intensities1i, out o)) { var xs = (int[])o; - return new PersistentRef(Guid.Empty, _ => xs, _ => (true, xs)); + return new PersistentRef(Guid.Empty, xs); } else { @@ -840,7 +883,7 @@ public PersistentRef? Classifications else if (Data.TryGetValue(Durable.Octree.Classifications1b, out o)) { var xs = (byte[])o; - return new PersistentRef(Guid.Empty, _ => xs, _ => (true, xs)); + return new PersistentRef(Guid.Empty, xs); } else { diff --git a/src/Aardvark.Geometry.PointSet/Utils/PersistentRef.cs b/src/Aardvark.Geometry.PointSet/Utils/PersistentRef.cs index 4858b420..77374c71 100644 --- a/src/Aardvark.Geometry.PointSet/Utils/PersistentRef.cs +++ b/src/Aardvark.Geometry.PointSet/Utils/PersistentRef.cs @@ -15,54 +15,67 @@ You should have received a copy of the GNU Affero General Public License using System; using System.Diagnostics.CodeAnalysis; -namespace Aardvark.Geometry.Points +namespace Aardvark.Geometry.Points; + + +/// +/// +public class PersistentRef + where T : notnull { + private readonly Func f_get; + private readonly TryGetFunc f_tryGetFromCache; + + public delegate bool TryGetFunc(string key, [NotNullWhen(true)] out T? result); /// /// - public class PersistentRef - where T : notnull + public PersistentRef(Guid id, Func get, TryGetFunc tryGetFromCache) + : this(id.ToString(), get, tryGetFromCache) { - private readonly Func f_get; - private readonly Func f_tryGet; + } - /// - /// - public PersistentRef(Guid id, Func get, Func tryGet) - : this(id.ToString(), get, tryGet) - { - } + /// + /// + public PersistentRef(string id, Func get, TryGetFunc tryGetFromCache) + { + Id = id; + f_get = get ?? throw new ArgumentNullException(nameof(get)); + f_tryGetFromCache = tryGetFromCache ?? throw new ArgumentNullException(nameof(tryGetFromCache)); + } - /// - /// - public PersistentRef(string id, Func get, Func tryGet) - { - Id = id; //?? throw new ArgumentNullException(nameof(id)); - f_get = get ?? throw new ArgumentNullException(nameof(get)); - f_tryGet = tryGet ?? throw new ArgumentNullException(nameof(tryGet)); - } - - /// - /// - public string Id { get; } - - /// - /// - public bool TryGetValue([NotNullWhen(true)]out T? value) + /// + /// + public PersistentRef(Guid id, T valueInMemory) + : this(id.ToString(), valueInMemory) + { + } + + /// + /// + public PersistentRef(string id, T valueInMemory) + { + Id = id; + f_get = _ => valueInMemory; + bool tryGetFromCache(string key, [NotNullWhen(true)] out T? result) { - bool isSome = false; - T? x = default; - (isSome, x) = f_tryGet(Id); - value = x; - return isSome; + result = valueInMemory; + return true; } + f_tryGetFromCache = tryGetFromCache; + } + + /// + /// + public string Id { get; } + + /// + /// + public T Value => f_get(Id); - /// - /// - public (bool hasValue, T? value) TryGetValue() => f_tryGet(Id); + /// + /// + public bool TryGetFromCache([NotNullWhen(true)] out T? value) + => f_tryGetFromCache(Id, out value); - /// - /// - public T? Value => f_get(Id); - } } diff --git a/src/Aardvark.Geometry.PointSet/Utils/StorageExtensions.cs b/src/Aardvark.Geometry.PointSet/Utils/StorageExtensions.cs index b69c4307..c4ea6741 100644 --- a/src/Aardvark.Geometry.PointSet/Utils/StorageExtensions.cs +++ b/src/Aardvark.Geometry.PointSet/Utils/StorageExtensions.cs @@ -226,6 +226,25 @@ public static PointRkdTreeFData BufferToPointRkdTreeFData(byte[] buffer) /// public static class StorageExtensions { + #region Generic + + /// + public static bool TryGetFromCache(this Storage storage, string key, [NotNullWhen(true)] out T? result) + { + if (storage.HasCache && storage.Cache.TryGetValue(key, out object o)) + { + result = (T)o; + return true; + } + else + { + result = default; + return false; + } + } + + #endregion + #region Stores /// @@ -306,6 +325,8 @@ public static (bool, byte[]?) TryGetByteArray(this Storage storage, string key) return (buffer != null, buffer); } + public static bool TryGetByteArrayFromCache(this Storage storage, string key, [NotNullWhen(true)] out byte[]? result) => TryGetFromCache(storage, key, out result); + /// /// Return ungzipped buffer, or original buffer if it is not gzipped. /// @@ -410,17 +431,7 @@ public static void Add(this Storage storage, string key, IList data) } /// - public static (bool, V3f[]?) TryGetV3fArray(this Storage storage, string key) - { - if (storage.HasCache && storage.Cache.TryGetValue(key, out object o)) - { - return (true, (V3f[])o); - } - else - { - return (false, default); - } - } + public static bool TryGetV3fArrayFromCache(this Storage storage, string key, [NotNullWhen(true)] out V3f[]? result) => TryGetFromCache(storage, key, out result); #endregion @@ -461,6 +472,8 @@ public static (bool, int[]?) TryGetIntArray(this Storage storage, string key) } } + public static bool TryGetIntArrayFromCache(this Storage storage, string key, [NotNullWhen(true)] out int[]? result) => TryGetFromCache(storage, key, out result); + #endregion #region C4b[] @@ -500,6 +513,8 @@ public static (bool, C4b[]?) TryGetC4bArray(this Storage storage, string key) } } + public static bool TryGetC4bArrayFromCache(this Storage storage, string key, [NotNullWhen(true)] out C4b[]? result) => TryGetFromCache(storage, key, out result); + #endregion #region PointRkdTreeDData @@ -547,6 +562,8 @@ public static PointRkdTreeD GetKdTree(this Storage storage, string k storage.GetPointRkdTreeDData(key) ); + public static bool TryGetPointRkdTreeDDataFromCache(this Storage storage, string key, [NotNullWhen(true)] out C4b[]? result) => TryGetFromCache(storage, key, out result); + #endregion #region PointRkdTreeFData @@ -602,6 +619,8 @@ public static (bool, PointRkdTreeFData?) TryGetPointRkdTreeFData(this Storage st } } + public static bool TryGetPointRkdTreeFDataFromCache(this Storage storage, string key, [NotNullWhen(true)] out C4b[]? result) => TryGetFromCache(storage, key, out result); + /// public static (bool, PointRkdTreeFData?) TryGetPointRkdTreeFDataFromD(this Storage storage, string key) { @@ -615,30 +634,7 @@ public static (bool, PointRkdTreeFData?) TryGetPointRkdTreeFDataFromD(this Stora } } - ///// - ///// - //public static PointRkdTreeF GetKdTreeF(this Storage storage, string key, V3f[] positions) - // => new PointRkdTreeF( - // 3, positions.Length, positions, - // (xs, i) => xs[(int)i], (v, i) => (float)v[i], - // (a, b) => V3f.Distance(a, b), (i, a, b) => b - a, - // (a, b, c) => VecFun.DistanceToLine(a, b, c), VecFun.Lerp, 1e-6f, - // storage.GetPointRkdTreeFData(key) - // ); - - ///// - ///// - //public static (bool, PointRkdTreeF) TryGetKdTreeF(this Storage storage, string key, V3f[] positions) - //{ - // if (storage.HasCache && storage.Cache.TryGetValue(key, out object o)) - // { - // return (true, (PointRkdTreeF)o); - // } - // else - // { - // return (false, default); - // } - //} + public static bool TryGetPointRkdTreeFDataFromDFromCache(this Storage storage, string key, [NotNullWhen(true)] out C4b[]? result) => TryGetFromCache(storage, key, out result); #endregion @@ -703,26 +699,30 @@ public static void Add(this Storage storage, string key, IPointCloudNode data) }); } - /// - public static IPointCloudNode? GetPointCloudNode(this Storage storage, Guid key) + /// + /// + public static IPointCloudNode GetPointCloudNode(this Storage storage, Guid key) => GetPointCloudNode(storage, key.ToString()); - /// - public static IPointCloudNode? GetPointCloudNode(this Storage storage, string key) + /// + /// + public static IPointCloudNode GetPointCloudNode(this Storage storage, string key) { - if (key == null) return null; - if (storage.HasCache && storage.Cache.TryGetValue(key, out object o)) { - //if (o == null) return null; if (o is not IPointCloudNode r) throw new InvalidOperationException( - $"Invariant d1cb769c-36b6-4374-8248-b8c1ca31d495. [GetPointCloudNode] Store key {key} is not IPointCloudNode." + $"Invariant d1cb769c-36b6-4374-8248-b8c1ca31d495. " + + $"[GetPointCloudNode] Store key {key} is not IPointCloudNode. " + + $"Error 7aebf7f1-3783-42fb-b405-47384e08f716." ); return r; } var buffer = storage.f_get(key); - if (buffer == null) return null; + if (buffer == null) throw new Exception( + $"PointCloudNode not found (id={key}). " + + $"Error b2ef55c1-1470-465d-80ea-034464c53638." + ); try { @@ -802,7 +802,34 @@ byte[] UnGzipBuffer(byte[] buffer) } } - /// + /// + /// + public static bool TryGetPointCloudNode(this Storage storage, string key, [NotNullWhen(true)]out IPointCloudNode? result) + { + if (storage.HasCache && storage.Cache.TryGetValue(key, out object o)) + { + result = (PointSetNode)o; + return true; + } + else + { + try + { + result = storage.GetPointCloudNode(key); + return true; + } + catch + { + result = null; + return false; + } + } + } + + /// + /// + + [Obsolete("Use TryGetPointCloudNode with out parameter instead.")] public static (bool, IPointCloudNode?) TryGetPointCloudNode(this Storage storage, string key) { if (storage.HasCache && storage.Cache.TryGetValue(key, out object o)) diff --git a/src/Aardvark.Geometry.PointSet/Views/FilteredNode.cs b/src/Aardvark.Geometry.PointSet/Views/FilteredNode.cs index e9bec598..e3fc6cf5 100644 --- a/src/Aardvark.Geometry.PointSet/Views/FilteredNode.cs +++ b/src/Aardvark.Geometry.PointSet/Views/FilteredNode.cs @@ -254,7 +254,7 @@ public PersistentRef[]? Subnodes else if (n0 != null) { var n = new FilteredNode(id, false, n0, Filter); - m_subnodes_cache[i] = new PersistentRef(id.ToString(), _ => n, _ => (true, n)); + m_subnodes_cache[i] = new PersistentRef(id, n); } } else @@ -318,7 +318,7 @@ private void EnsurePositionsAndDerived() m_cache[Octree.BoundingBoxExactLocal.Id] = bboxLocal; var kd = psLocal.BuildKdTree(); - var pRefKd = new PersistentRef>(Guid.NewGuid().ToString(), _ => kd, _ => (true, kd)); + var pRefKd = new PersistentRef>(Guid.NewGuid(), kd); m_cache[Octree.PointRkdTreeFData.Id] = pRefKd; m_ensuredPositionsAndDerived = true; @@ -531,7 +531,7 @@ public PersistentRef> KdTree var key = (Id + originalValue.Id).ToGuid().ToString(); var xs = originalValue.Value.Where((_, i) => m_activePoints.Contains(i)).ToArray(); - var result = new PersistentRef(key, _ => xs, _ => (true, xs)); + var result = new PersistentRef(key, xs); m_cache[def.Id] = result; return result; }