Skip to content

Commit

Permalink
structured point clouds: implementation (wip)
Browse files Browse the repository at this point in the history
  • Loading branch information
stefanmaierhofer committed Sep 21, 2023
1 parent bf5c90d commit 3b9583c
Show file tree
Hide file tree
Showing 9 changed files with 251 additions and 164 deletions.
4 changes: 3 additions & 1 deletion src/Aardvark.Data.Points.Base/Storage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@ public class Storage : IDisposable
/// <summary>add(key, value, create)</summary>
public readonly Action<string, object, Func<byte[]>> f_add;

/// <summary></summary>
/// <summary>
/// Returns null if key does not exist.
/// </summary>
public readonly Func<string, byte[]?> f_get;

/// <summary></summary>
Expand Down
3 changes: 1 addition & 2 deletions src/Aardvark.Geometry.PointSet/Octrees/Export.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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}'.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
}
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
}
}
}
Expand Down Expand Up @@ -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);
}
}
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
}
}
Expand Down
16 changes: 8 additions & 8 deletions src/Aardvark.Geometry.PointSet/Octrees/Inline.cs
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ static IEnumerable<InlinedNode> EnumerateRecImpl(IPointCloudNode node, HashSet<G
{
foreach (var x in node.Subnodes)
{
if (x != null && x.TryGetValue(out var subnode))
if (x != null && x.TryGetFromCache(out var subnode))
{
foreach (var n in EnumerateRecImpl(subnode, survive, config, processedNodeCount)) yield return n;
}
Expand Down Expand Up @@ -384,7 +384,7 @@ HashSet<Guid> 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[]);
Expand Down Expand Up @@ -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 =>
Expand Down Expand Up @@ -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
Expand All @@ -471,22 +471,22 @@ 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);
}
}
else
{
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);
}


Expand Down
27 changes: 15 additions & 12 deletions src/Aardvark.Geometry.PointSet/Octrees/PointSet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<IPointCloudNode>(rootCellId.ToString(), storage.GetPointCloudNode!,
k => { var (a, b) = storage.TryGetPointCloudNode(k); return (a, b); }
Root = new PersistentRef<IPointCloudNode>(rootCellId.ToString(), storage.GetPointCloudNode,
storage.TryGetPointCloudNode
);
}

Expand All @@ -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<IPointCloudNode>(root.Id.ToString(), storage.GetPointCloudNode!, storage.TryGetPointCloudNode);
Root = new PersistentRef<IPointCloudNode>(root.Id.ToString(), storage.GetPointCloudNode, storage.TryGetPointCloudNode);
}

/// <summary>
Expand All @@ -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
Expand Down Expand Up @@ -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
})!;
Expand All @@ -168,27 +169,29 @@ 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<IPointCloudNode>(octreeId, storage.GetPointCloudNode!, storage.TryGetPointCloudNode)
? new PersistentRef<IPointCloudNode>(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
? new Range1i((int)partIndexRangeArray[0]!, (int)partIndexRangeArray[1]!)
: Range1i.Invalid
;

//
var octree = octreeRef?.Value;
return new PointSet(storage, id, octree ?? PointSetNode.Empty, splitLimit).WithPartIndexRange(partIndexRange);
}

Expand Down
Loading

0 comments on commit 3b9583c

Please sign in to comment.