Skip to content

Commit f4c7945

Browse files
- builder: fixed root cell for case when data is smaller than split limit tile size
- materialize: fixed indexing for mask data
1 parent 098b755 commit f4c7945

File tree

4 files changed

+172
-4
lines changed

4 files changed

+172
-4
lines changed

RELEASE_NOTES.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
### 0.5.2
2+
- [builder] fixed root cell for case when data is smaller than split limit tile size
3+
- [materialize] fixed indexing for mask data
4+
15
### 0.5.1
26
- updated dependencies (System.Collections.Immutable lowest_matching: true)
37

src/Aardvark.Geometry.Quadtree/Builder.fs

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,23 @@ open System.Collections.Generic
66

77
module Builder =
88

9-
let private debugOutput = false
9+
let private debugOutput =
10+
#if DEBUG
11+
true
12+
#else
13+
false
14+
#endif
1015

1116
let rec private build' (sampleExponent : int) (rootCell : Cell2d) (patches : LayerSet[]) =
1217

1318
if debugOutput then
1419
printfn "[DEBUG] build' rootCell = %A, %d patches" rootCell patches.Length
1520

21+
for p in patches do
22+
invariantm (p.SampleExponent = sampleExponent)
23+
(fun () -> sprintf "Sample exponent %d does not match patch sample exponent %d." sampleExponent p.SampleExponent)
24+
"28d1fdd1-2da6-4329-a065-c134c1351ffc"
25+
1626
match patches.Length with
1727

1828
| 0 -> NoNode
@@ -38,13 +48,35 @@ module Builder =
3848
if debugOutput then
3949
printfn "[DEBUG] MERGE %d patches; %A" n (bbWindow - rootBounds.Min)
4050

41-
4251
//if debugOutput then
4352
// for patch in patches do
4453
// printfn "[DEBUG] %A (exact %A)" (patch.SampleWindow - rootBounds.Min) (bbWindow - rootBounds.Min)
4554

55+
// adjust root cell for split limit
56+
let requiredRootCellSplitLimit = sampleExponent + BuildConfig.Default.SplitLimitPowerOfTwo
57+
58+
let mutable rootCell = rootCell
59+
60+
if requiredRootCellSplitLimit <> rootCell.Exponent then
61+
62+
invariantm (rootCell.Exponent < requiredRootCellSplitLimit)
63+
(fun () -> sprintf "Expected root cell exponent %d to be smaller than requiredRootCellSplitLimit %d." rootCell.Exponent requiredRootCellSplitLimit)
64+
"4911adf3-7b87-4234-9bcc-bc3076df846e"
65+
66+
if debugOutput then
67+
printfn "[DEBUG] must adjust root cell %A exponent to %d" rootCell requiredRootCellSplitLimit
68+
69+
while rootCell.Exponent < requiredRootCellSplitLimit do rootCell <- rootCell.Parent
70+
71+
if debugOutput then
72+
printfn "[DEBUG] adjusted root cell is %A" rootCell
73+
4674
let merged = LayerSet.Merge patches
4775
let qnode = QNode(Guid.NewGuid(), ebb, rootCell, BuildConfig.Default.SplitLimitPowerOfTwo, merged)
76+
77+
if debugOutput then
78+
printfn "[DEBUG] CREATED QNode with split limit = %d" qnode.SplitLimitExponent
79+
4880
let xs = qnode |> InMemoryNode |> Query.All Query.Config.Default |> Seq.map (fun x -> x.GetSamples<V4f>(Defs.HeightsBilinear4f)) |> Array.ofSeq |> Array.collect id
4981
//for x in xs do printfn "%A" x
5082
qnode |> InMemoryNode
@@ -142,4 +174,16 @@ type Builder () =
142174
)
143175
None // initial state
144176

145-
177+
member this.Print () : unit =
178+
179+
printfn "Builder("
180+
let ps = patches |> Seq.sortByDescending (fun kv -> kv.Key) |> Seq.map (fun kv -> kv.Value) |> Seq.collect id
181+
for p in ps do
182+
printfn " exp = %5d bb = %A" p.SampleExponent p.BoundingBox
183+
184+
let bbGlobal = Box2d(ps |> Seq.map (fun p -> p.BoundingBox))
185+
printfn " global bb = %A" bbGlobal
186+
printfn " global root cell = %A" (Cell2d bbGlobal)
187+
188+
printfn " )"
189+
()

src/Aardvark.Geometry.Quadtree/Layer.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ type Layer<'a when 'a : equality>(def : Durable.Def, data : 'a[], mapping : Data
9797
let newmask = Array.zeroCreate<byte> newArrayLength
9898
for y = 0 to size.Y - 1 do
9999
for x = 0 to size.X - 1 do
100-
newmask[i] <- mask[mapping.GetBufferIndex(x, y)]
100+
newmask[i] <- mask[mapping.GetBufferIndex(mapping.BufferOrigin.X + int64 x, mapping.BufferOrigin.Y + int64 y)]
101101
i <- i + 1
102102
Some newmask
103103

src/Scratch/Program.fs

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1040,6 +1040,10 @@ let builderSketch () =
10401040
let countMergeNodes = newAndBetterTree |> Quadtree.CountMergeNodes true
10411041
printfn "new quadtree has %d leaf nodes and %d merge nodes" countLeafNodes countMergeNodes
10421042

1043+
let options = SerializationOptions.NewInMemoryStore(verbose = true)
1044+
let id = newAndBetterTree |> Quadtree.Save options
1045+
printfn "saved quadtree id = %A" id
1046+
10431047

10441048

10451049

@@ -1143,9 +1147,125 @@ let builderSketch () =
11431147

11441148
()
11451149

1150+
let builderTest_20240112 () =
1151+
1152+
let cpTree =
1153+
1154+
let createQuadTreePlanesZeroBase =
1155+
1156+
// define mapping of raw data to raster space
1157+
let hor0 = V4f(0.0, 0.0,0.0,0.0)
1158+
1159+
let parameters = [|hor0; hor0; hor0;
1160+
hor0; hor0; hor0;
1161+
hor0; hor0; hor0;
1162+
hor0; hor0; hor0;
1163+
hor0; hor0; hor0;|]
1164+
1165+
let mapping = DataMapping(origin = Cell2d(0L, 0L, 0), size = V2i(3, 5))
1166+
1167+
// a layer gives meaning to raw data
1168+
let bilinParameters = Layer(Defs.HeightsBilinear4f, parameters, mapping)
1169+
1170+
// build the quadtree (incl. levels-of-detail)
1171+
let qtree = Quadtree.Build { BuildConfig.Default with SplitLimitPowerOfTwo = 10 } [| bilinParameters |]
1172+
1173+
qtree
1174+
1175+
let createOneSubCell (level : int) (east:int64) (north:int64)=
1176+
// define mapping of raw data to raster space
1177+
let elevation = -1.0*((float)level)
1178+
let hor1 = V4f(elevation, 0.0,0.0,0.0)
1179+
1180+
let parameters = [|hor1;hor1;hor1;hor1|]
1181+
1182+
let mapping = DataMapping(origin = Cell2d(east, north, level), size = V2i(2, 2))
1183+
1184+
// a layer gives meaning to raw data
1185+
let bilinParameters = Layer(Defs.HeightsBilinear4f, parameters, mapping)
1186+
1187+
// build the quadtree (incl. levels-of-detail)
1188+
1189+
let qtree = Quadtree.Build { BuildConfig.Default with SplitLimitPowerOfTwo = 10 } [| bilinParameters |]
1190+
1191+
qtree
1192+
1193+
let mainTree = createQuadTreePlanesZeroBase
1194+
1195+
let config = Query.Config.Default
1196+
1197+
let subTree2 = createOneSubCell -2 0L 0L
1198+
let subTree2_1 = createOneSubCell -2 2L 0L
1199+
let subTree2_2 = createOneSubCell -2 2L 2L
1200+
let subTree2_3 = createOneSubCell -2 0L 2L
1201+
let mutable newTree = Quadtree.Merge SecondDominates mainTree subTree2
1202+
newTree <- Quadtree.Merge SecondDominates newTree subTree2_1
1203+
newTree <- Quadtree.Merge SecondDominates newTree subTree2_2
1204+
newTree <- Quadtree.Merge SecondDominates newTree subTree2_3
1205+
1206+
let subTree3 = createOneSubCell -1 2L 6L
1207+
newTree <- Quadtree.Merge SecondDominates newTree subTree3
1208+
1209+
newTree
1210+
1211+
1212+
let createQuadtreeWithValue (ox : int) (oy : int) (w : int) (h : int) (e : int) (splitLimit : int) (value : float32) =
1213+
let size = V2i(w, h)
1214+
let xs = Array.zeroCreate<float32> (w * h)
1215+
for y = 0 to size.Y - 1 do
1216+
for x = 0 to size.X - 1 do
1217+
let i = y * size.X + x
1218+
xs.[i] <- value
1219+
1220+
let a = Layer(Defs.Heights1f, xs, DataMapping(V2l(ox, oy), size, exponent = e))
1221+
1222+
let config = { BuildConfig.Default with SplitLimitPowerOfTwo = int splitLimit }
1223+
Quadtree.Build config [| a |]
1224+
1225+
let sw = Stopwatch()
1226+
1227+
// (1) create 10x10 base grid with 1m tiles
1228+
//let store = @"W:\Datasets\Vgm\Data\2023-09-04_quadtree"
1229+
let baseGrid = createQuadtreeWithValue 0 0 10 10 0 8 42.0f
1230+
1231+
let singleTile = createQuadtreeWithValue 3 7 2 3 -2 8 101.0f
1232+
1233+
let originalQuadtree = Quadtree.Merge Dominance.MoreDetailedOrSecond baseGrid singleTile
1234+
1235+
// (2) take all leaf nodes as test patches
1236+
// (these should be the original data that was merged together)
1237+
let patches = cpTree |> Quadtree.EnumerateLeafNodesInMemory |> List.ofSeq
1238+
1239+
// stats
1240+
printfn "original quadtree has %d leaf nodes and %d merge nodes" patches.Length (Quadtree.CountMergeNodes true originalQuadtree)
1241+
let resolutions = patches |> List.groupBy (fun n -> n.SampleExponent) |> List.map (fun (k, v) -> k) |> List.sortDescending
1242+
printfn "original quadtree resolution levels: %A" resolutions
1243+
1244+
// (3) create a new builder and add all patches
1245+
let builder = Builder()
1246+
for n in patches do builder.Add n
1247+
1248+
builder.Print()
1249+
1250+
// (4) build new and better quadtree
1251+
match builder.Build() with
1252+
| None -> printfn "no quadtree"
1253+
| Some newAndBetterTree ->
1254+
let countLeafNodes = newAndBetterTree |> Quadtree.CountLeafNodes true
1255+
let countMergeNodes = newAndBetterTree |> Quadtree.CountMergeNodes true
1256+
printfn "new quadtree has %d leaf nodes and %d merge nodes" countLeafNodes countMergeNodes
1257+
1258+
let options = SerializationOptions.NewInMemoryStore(verbose = true)
1259+
let id = newAndBetterTree |> Quadtree.Save options
1260+
printfn "saved quadtree id = %A" id
1261+
1262+
1263+
11461264
[<EntryPoint>]
11471265
let main argv =
11481266

1267+
//builderTest_20240112 ()
1268+
11491269
builderSketch ()
11501270

11511271
//madorjan20211103 ()

0 commit comments

Comments
 (0)