Skip to content

Commit bae6779

Browse files
sync
1 parent 4bb2b43 commit bae6779

File tree

5 files changed

+205
-23
lines changed

5 files changed

+205
-23
lines changed

src/Aardvark.Geometry.Quadtree/Builder.fs

Lines changed: 108 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ module Builder =
1111

1212
let private debugOutput =
1313
#if DEBUG
14-
true
14+
false
1515
#else
1616
false
1717
#endif
@@ -86,7 +86,7 @@ module Builder =
8686

8787
else
8888

89-
let bbQuadrants = rootCell.Children |> Array.map (fun subCell -> subCell.GetBoundsForExponent(sampleExponent))
89+
//let bbQuadrants = rootCell.Children |> Array.map (fun subCell -> subCell.GetBoundsForExponent(sampleExponent))
9090

9191
let patchesPerQuadrant =
9292
rootCell.Children
@@ -116,6 +116,106 @@ module Builder =
116116
let result = { Id = Guid.NewGuid(); ExactBoundingBox = ebb; Cell = rootCell; SplitLimitExponent = BuildConfig.Default.SplitLimitPowerOfTwo; HasMask = hasMask; SubNodes = subNodes }
117117
result |> InMemoryInner
118118

119+
let rec private build'' (minSampleExponent : int) (rootCell : Cell2d) (patches : LayerSet[]) =
120+
121+
if debugOutput then
122+
printfn "[DEBUG] build' rootCell = %A, %d patches" rootCell patches.Length
123+
124+
for p in patches do
125+
invariantm (p.SampleExponent >= minSampleExponent)
126+
(fun () -> sprintf "Patch sample exponent %d is smaller than specified minimum sample exponent %d." p.SampleExponent minSampleExponent)
127+
"28d1fdd1-2da6-4329-a065-c134c1351ffc"
128+
129+
match patches.Length with
130+
131+
| 0 -> NoNode
132+
133+
| 1 ->
134+
135+
let theSinglePatch = patches[0]
136+
137+
if debugOutput then
138+
printfn "[DEBUG] SINGLE patch (%A)" theSinglePatch.SampleWindow
139+
140+
Quadtree.Build BuildConfig.Default theSinglePatch.Layers
141+
142+
| n -> // n patches
143+
144+
let ebb = patches |> Seq.map (fun patch -> patch.BoundingBox) |> Box2d
145+
146+
let rootBounds = getBoundsForExponent minSampleExponent rootCell
147+
if rootBounds.Size.X <= 256 && rootBounds.Size.Y <= 256 then
148+
149+
let bbWindow = patches |> Seq.map (fun patch -> patch.SampleWindow) |> Box2l
150+
151+
if debugOutput then
152+
printfn "[DEBUG] MERGE %d patches; %A" n (bbWindow - rootBounds.Min)
153+
154+
//if debugOutput then
155+
// for patch in patches do
156+
// printfn "[DEBUG] %A (exact %A)" (patch.SampleWindow - rootBounds.Min) (bbWindow - rootBounds.Min)
157+
158+
// adjust root cell for split limit
159+
let requiredRootCellSplitLimit = minSampleExponent + BuildConfig.Default.SplitLimitPowerOfTwo
160+
161+
let mutable rootCell = rootCell
162+
163+
if requiredRootCellSplitLimit <> rootCell.Exponent then
164+
165+
invariantm (rootCell.Exponent < requiredRootCellSplitLimit)
166+
(fun () -> sprintf "Expected root cell exponent %d to be smaller than requiredRootCellSplitLimit %d." rootCell.Exponent requiredRootCellSplitLimit)
167+
"4911adf3-7b87-4234-9bcc-bc3076df846e"
168+
169+
if debugOutput then
170+
printfn "[DEBUG] must adjust root cell %A exponent to %d" rootCell requiredRootCellSplitLimit
171+
172+
while rootCell.Exponent < requiredRootCellSplitLimit do rootCell <- rootCell.Parent
173+
174+
if debugOutput then
175+
printfn "[DEBUG] adjusted root cell is %A" rootCell
176+
177+
let merged = LayerSet.Merge patches
178+
let qnode = QNode(Guid.NewGuid(), ebb, rootCell, BuildConfig.Default.SplitLimitPowerOfTwo, merged)
179+
180+
if debugOutput then
181+
printfn "[DEBUG] CREATED QNode with split limit = %d" qnode.SplitLimitExponent
182+
183+
//let xs = qnode |> InMemoryNode |> Query.All Query.Config.Default |> Seq.map (fun x -> x.GetSamples<V4f>(Defs.HeightsBilinear4f)) |> Array.ofSeq |> Array.collect id
184+
//for x in xs do printfn "%A" x
185+
qnode |> InMemoryNode
186+
187+
else
188+
189+
//let bbQuadrants = rootCell.Children |> Array.map (fun subCell -> subCell.GetBoundsForExponent(sampleExponent))
190+
191+
let patchesPerQuadrant =
192+
rootCell.Children
193+
|> Array.map (fun subCell ->
194+
let bbQuadrant = subCell.GetBoundsForExponent(minSampleExponent)
195+
let subPatches = patches |> Array.choose (fun b -> b.WithWindow bbQuadrant)
196+
(subCell, subPatches)
197+
)
198+
199+
200+
if debugOutput then
201+
printfn "[DEBUG] SPLIT %d patches" n
202+
203+
//for i in 0..3 do
204+
// let (subCell, subPatches) = patchesPerQuadrant[i]
205+
// printfn "%A%A[%d] size = %A, %d patches" rootCell ebb i bbWindow.Size subPatches.Length
206+
207+
let subNodes = patchesPerQuadrant |> Array.map (fun (subCell, subPatches) ->
208+
match subPatches.Length with
209+
| 0 -> NoNode
210+
| _ -> build'' minSampleExponent subCell subPatches
211+
)
212+
213+
let hasMask = subNodes |> Array.exists (fun n -> n.HasMask)
214+
if debugOutput && hasMask then
215+
printfn "[DEBUG] has mask %A" rootCell
216+
let result = { Id = Guid.NewGuid(); ExactBoundingBox = ebb; Cell = rootCell; SplitLimitExponent = BuildConfig.Default.SplitLimitPowerOfTwo; HasMask = hasMask; SubNodes = subNodes }
217+
result |> InMemoryInner
218+
119219
/// Creates a quadtree from many small patches.
120220
let Build (patches : LayerSet seq) : QNodeRef =
121221
let patches = patches |> Array.ofSeq
@@ -188,6 +288,8 @@ type Builder () =
188288

189289
/// Build a quadtree from all the patches that have been added to this builder.
190290
member this.Build () : QNodeRef option =
291+
292+
let mutable mergesCount = 0
191293

192294
patches
193295
// (1) sort per-resolution patch lists from coarse to fine resolution ...
@@ -198,7 +300,10 @@ type Builder () =
198300
|> Seq.fold (fun state item ->
199301
match state with
200302
| None -> Some item
201-
| Some state -> Quadtree.Merge Dominance.SecondDominates state item |> Some
303+
| Some state ->
304+
mergesCount <- mergesCount + 1
305+
printfn "[Builder.Build()] mergesCount -> %d" mergesCount
306+
Quadtree.Merge Dominance.SecondDominates state item |> Some
202307
)
203308
None // initial state
204309

src/Aardvark.Geometry.Quadtree/Layer.fs

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ open Aardvark.Data
55
open System
66
open System.Collections.Immutable
77
open System.Collections.Generic
8+
open System.Diagnostics
89

910
#nowarn "44"
1011

@@ -134,20 +135,29 @@ type Layer<'a when 'a : equality>(def : Durable.Def, data : 'a[], mapping : Data
134135
| Fail ->
135136
if inside () then
136137
let i = mapping.GetBufferIndex s
137-
data.[i]
138+
match mask with
139+
| None -> data[i]
140+
| Some mask -> if mask[i] = 1uy then data[i] else failwith "Error 79671ba5-c509-4edd-ac4b-0f8d7b5e7222."
141+
138142
else
139143
failwith <| sprintf "Position %A outside of available data [%A-%A]." s this.SampleMin this.SampleMaxIncl
144+
140145
| ClampToBorder value ->
141146
if inside () then
142147
let i = mapping.GetBufferIndex s
143-
data.[i]
148+
match mask with
149+
| None -> data[i]
150+
| Some mask -> if mask[i] = 1uy then data[i] else failwith "Error 6befcffd-3f31-465b-b37a-43137339b6f8."
144151
else
145152
value
153+
146154
| ClampToEdge ->
147155
let x = if s.X < min.X then min.X elif s.X > maxIncl.X then maxIncl.X else s.X
148156
let y = if s.Y < min.Y then min.Y elif s.Y > maxIncl.Y then maxIncl.Y else s.Y
149157
let i = mapping.GetBufferIndex(x, y)
150-
data.[i]
158+
match mask with
159+
| None -> data[i]
160+
| Some mask -> if mask[i] = 1uy then data[i] else failwith "Error 472e5d8b-aa34-4ad9-a973-75d652a57f18."
151161

152162
member this.GetSample (mode : BorderMode<'a>, globalPos : V2d) : 'a =
153163
let s = mapping.GetSampleCell globalPos
@@ -300,8 +310,6 @@ module Layer =
300310
let i = finalMapping.GetBufferIndex c
301311
let v = layer.GetSample(Fail, c)
302312

303-
//finalData.[i] <- v
304-
305313
match finalMask[i] with
306314
| 255uy ->
307315
finalData[i] <- v
@@ -342,6 +350,11 @@ module Layer =
342350
printfn "[DEBUG][Layer.mergeTyped] debugCountOccupied.Count = %d / %d ... %5.2f" coundOccupiedSamples finalMask.Length (float coundOccupiedSamples / float finalMask.Length)
343351

344352
// rewrite mask (1 ... occupied, 0 ... undefined)
353+
354+
let countOccupied = finalMask |> Array.filter (fun x -> x <> 255uy) |> Array.length
355+
let countUndefined = finalMask |> Array.filter (fun x -> x = 255uy) |> Array.length
356+
printfn "[OCCUPANCY][e = %d][%A][%A] countOccupied = %d, countUndefined = %d" e finalWindow finalWindow.Size countOccupied countUndefined
357+
345358
for i = 0 to finalMask.Length-1 do
346359
finalMask[i] <- if finalMask[i] = 255uy then 0uy else 1uy
347360

src/Aardvark.Geometry.Quadtree/Node.fs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ and QNode(uid : Guid, exactBoundingBox : Box2d, cell : Cell2d, splitLimitExp : i
4444
new (exactBoundingBox : Box2d, cell : Cell2d, splitLimitExp : int, layers : LayerSet) =
4545
QNode(Guid.NewGuid(), exactBoundingBox, cell, splitLimitExp, layers)
4646

47+
new (splitLimitExp : int, layers : LayerSet) =
48+
QNode(Guid.NewGuid(), layers.BoundingBox, layers.BoundingBox |> Cell2d, splitLimitExp, layers)
49+
4750
member _.Id with get() = uid
4851

4952
member _.Cell with get() = cell

src/Aardvark.Geometry.Quadtree/Query.fs

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ open Aardvark.Base
44
open Aardvark.Data
55
open System
66
open System.Collections.Generic
7-
open System.Threading
87
open System.Diagnostics
98

109
module Query =
@@ -77,7 +76,7 @@ module Query =
7776
let mergeDominatingT1 = Stopwatch()
7877

7978
/// xs dominate always
80-
let private mergeDominating (config : Config) (xs : Result list) (ys : Result list) (isSampleInside : Cell2d -> bool) : Result seq =
79+
let private mergeDominatingPerSample (config : Config) (xs : Result list) (ys : Result list) (isSampleInside : Cell2d -> bool) : Result seq =
8180

8281
if config.Verbose then
8382
printfn "[mergeDominating] xs:"
@@ -93,7 +92,7 @@ module Query =
9392
let yebb = y.Node.ExactBoundingBox
9493
xs |> Array.filter(fun x -> x.Node.ExactBoundingBox.Intersects(yebb))
9594

96-
seq {
95+
let resultSeq = seq {
9796

9897
mergeDominatingT0.Start();
9998

@@ -115,11 +114,17 @@ module Query =
115114
let mutable result = List<Cell2d>(8192)
116115

117116
// all dominating sample cells intersecting dominated result
118-
let zcs = zs |> Array.collect(fun z -> z.GetSampleCells() |> Array.filter(fun zc -> zc.BoundingBox.Intersects(yebb))) |> Array.map(fun c -> c.BoundingBox)
117+
let zcs0 = zs |> Array.collect(fun z -> z.GetSampleCells())
118+
let zcs1 = zcs0 |> Seq.filter(fun zc -> zc.BoundingBox.Intersects(yebb)) |> Seq.toList
119+
let zcs = zcs1 |> Seq.map(fun c -> c.BoundingBox) |> Seq.toList |> List.toArray
119120

120121
// all sample cells of dominated result
121122
let ycs = y.GetSampleCells ()
123+
124+
let mutable i = 0
122125
for yc in ycs do
126+
i <- i + 1
127+
//printfn "[resolve dominate results] %d/%d" i ycs.Length
123128
let inline isDominatedCellYcFullyCovered (bb : Box2d) =
124129
zcs |> Array.exists(fun zc -> zc.Contains(bb))
125130
let inline isDominatedCellYcInterferedWith (bb : Box2d) =
@@ -170,15 +175,18 @@ module Query =
170175
mergeDominatingT0.Stop()
171176
}
172177

173-
let private merge (config : Config) (dom : Dominance) (xs : Result list) (ys : Result list) (isSampleInside : Cell2d -> bool) : Result list =
178+
let result = resultSeq |> Seq.toArray
179+
result
180+
181+
let private mergePerSample (config : Config) (dom : Dominance) (xs : Result list) (ys : Result list) (isSampleInside : Cell2d -> bool) : Result list =
174182
match xs |> Seq.isEmpty, ys |> Seq.isEmpty with
175183
// both sequences contain values
176184
| false, false ->
177185
match dom with
178186
| FirstDominates
179-
| MoreDetailedOrFirst -> mergeDominating config xs ys isSampleInside |> Seq.toList
187+
| MoreDetailedOrFirst -> mergeDominatingPerSample config xs ys isSampleInside |> Seq.toList
180188
| SecondDominates
181-
| MoreDetailedOrSecond -> mergeDominating config ys xs isSampleInside |> Seq.toList
189+
| MoreDetailedOrSecond -> mergeDominatingPerSample config ys xs isSampleInside |> Seq.toList
182190
// xs contains values, ys is empty -> no need to merge, just return xs
183191
| false, true -> xs
184192
// xs is empty -> no need to merge, just return ys
@@ -204,8 +212,8 @@ module Query =
204212
let xs = generic a |> Seq.toList
205213
let ys = generic b |> Seq.toList
206214
//printf "merge first (%d) + second (%d) %A ... " xs.Length ys.Length a.Cell
207-
let r = merge config dom xs ys isSampleInside
208-
let foo = r |> List.collect (fun x -> x.GetSampleCells() |> Array.toList)
215+
let r = mergePerSample config dom xs ys isSampleInside
216+
//let foo = r |> List.collect (fun x -> x.GetSampleCells() |> Array.toList)
209217
//printfn "done %d" (r |> List.sumBy (fun x -> x.GetSampleCells().Length))
210218
r
211219

@@ -394,8 +402,8 @@ module Query =
394402
let result = { Node = n; Selection = FullySelected }
395403
if config.Verbose then
396404
printfn "[Generic ] fully inside (%A)" root.Cell
397-
printfn "[Generic ] YIELD %A" result
398-
for c in result.GetSampleCells() do printfn "[Generic ] Y %A" c
405+
printfn "[Generic ] YIELD %A" result.Node.Cell
406+
//for c in result.GetSampleCells() do printfn "[Generic ] Ya %A" c
399407
yield result
400408
else
401409
// partially inside
@@ -405,8 +413,8 @@ module Query =
405413
if xs.Length > 0 then
406414
let result = { Node = n; Selection = CellsSelected xs }
407415
if config.Verbose then
408-
printfn "[Generic ] YIELD %A" result
409-
for c in result.GetSampleCells() do printfn "[Generic ] Y %A" c
416+
printfn "[Generic ] YIELD %A" result.Node.Cell
417+
//for c in result.GetSampleCells() do printfn "[Generic ] Yb %A" c
410418
yield result
411419

412420
}

src/Scratch/Program.fs

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1276,7 +1276,7 @@ let builderTest_20240112 () =
12761276

12771277
let buildSerializationTest_20240202 () =
12781278

1279-
let path = Path.GetFullPath("c:/tmp/20240202_quadtreetest")
1279+
let path = Path.GetFullPath(@"c:\tmp\20240202_quadtreetest")
12801280

12811281
printfn "path = %s" path
12821282

@@ -1307,10 +1307,63 @@ let buildSerializationTest_20240202 () =
13071307

13081308
()
13091309

1310+
let cp_20240202_quadtreetest () =
1311+
1312+
let path = Path.GetFullPath(@"W:\Datasets\Vgm\Quadtree\20240202_quadtreetest")
1313+
1314+
printfn "path = %s" path
1315+
1316+
let options = SerializationOptions.NewInMemoryStore(verbose = false)
1317+
1318+
let idFile = Guid(File.ReadAllText(@"W:\Datasets\Vgm\Quadtree\20240202_quadtreetest\builder.20240202122614.638424735748032405.key.txt"))
1319+
let builderReloadedFile = Builder.Import(path, idFile)
1320+
match builderReloadedFile with
1321+
| None -> printfn "reloaded from file = None"
1322+
| Some x ->
1323+
printfn "reloaded from file, %d patches" (x.GetPatches() |> Seq.length)
1324+
1325+
let samplesCount =
1326+
x.GetPatches()
1327+
|> Seq.filter(fun patch -> patch.SampleExponent = -3)
1328+
|> Seq.sumBy(fun patch -> patch.SampleWindow.Area)
1329+
printfn("total samples count with e = -3: %d") samplesCount
1330+
1331+
match x.Build () with
1332+
| None -> failwith ""
1333+
| Some qtree ->
1334+
let makeReturnValOfQueryResults (resultChunk : seq<Query.Result>) (def : Aardvark.Data.Durable.Def) =
1335+
1336+
let samples =
1337+
resultChunk
1338+
|> Seq.collect (fun chunk -> chunk.GetSamples<V4f> def)
1339+
//|> Seq.map (fun (cell,bilParamV) -> let bilParam = BilinearSurfaceParams.FromV4f bilParamV
1340+
// (bilParam, cell))
1341+
|> Seq.toList
1342+
1343+
//posAndParams |> Seq.filter (fun pos -> (fst pos).b0.IsNaN() |> not)
1344+
// |> Seq.map (fun pos -> { originalCell = snd pos; surface = fst pos} )
1345+
1346+
//let mutable i = 0
1347+
//for s in samples do
1348+
// i <- i + 1
1349+
// printfn "%A" s
1350+
1351+
samples
1352+
1353+
let config = Query.Config.Default //{ Query.Config.Default with Verbose = true }
1354+
let resultCells = qtree |> Query.All config |> Seq.toArray
1355+
let samples = makeReturnValOfQueryResults resultCells Defs.HeightsBilinear4f
1356+
1357+
()
1358+
1359+
()
1360+
13101361
[<EntryPoint>]
13111362
let main argv =
13121363

1313-
buildSerializationTest_20240202 ()
1364+
cp_20240202_quadtreetest ()
1365+
1366+
//buildSerializationTest_20240202 ()
13141367

13151368
//builderTest_20240112 ()
13161369

0 commit comments

Comments
 (0)