Skip to content

Commit 4660999

Browse files
sync
1 parent 84b36e9 commit 4660999

File tree

4 files changed

+84
-64
lines changed

4 files changed

+84
-64
lines changed

src/Aardvark.Geometry.Quadtree/Builder.fs

Lines changed: 72 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,9 @@ open System.Diagnostics
1010

1111
module Builder =
1212

13-
let private debugOutput =
14-
#if DEBUG
15-
false
16-
#else
17-
false
18-
#endif
13+
let rec private build' (config : BuildConfig) (sampleExponent : int) (rootCell : Cell2d) (patches : LayerSet[]) =
1914

20-
let rec private build' (sampleExponent : int) (rootCell : Cell2d) (patches : LayerSet[]) =
21-
22-
if debugOutput then
15+
if config.Verbose then
2316
printfn "[DEBUG] build' rootCell = %A, %d patches" rootCell patches.Length
2417

2518
for p in patches do
@@ -35,7 +28,7 @@ module Builder =
3528

3629
let theSinglePatch = patches[0]
3730

38-
if debugOutput then
31+
if config.Verbose then
3932
printfn "[DEBUG] SINGLE patch (%A)" theSinglePatch.SampleWindow
4033

4134
Quadtree.Build BuildConfig.Default theSinglePatch.Layers
@@ -49,7 +42,7 @@ module Builder =
4942

5043
let bbWindow = patches |> Seq.map (fun patch -> patch.SampleWindow) |> Box2l
5144

52-
if debugOutput then
45+
if config.Verbose then
5346
printfn "[DEBUG] MERGE %d patches; %A" n (bbWindow - rootBounds.Min)
5447

5548
//if debugOutput then
@@ -67,18 +60,18 @@ module Builder =
6760
(fun () -> sprintf "Expected root cell exponent %d to be smaller than requiredRootCellSplitLimit %d." rootCell.Exponent requiredRootCellSplitLimit)
6861
"4911adf3-7b87-4234-9bcc-bc3076df846e"
6962

70-
if debugOutput then
63+
if config.Verbose then
7164
printfn "[DEBUG] must adjust root cell %A exponent to %d" rootCell requiredRootCellSplitLimit
7265

7366
while rootCell.Exponent < requiredRootCellSplitLimit do rootCell <- rootCell.Parent
7467

75-
if debugOutput then
68+
if config.Verbose then
7669
printfn "[DEBUG] adjusted root cell is %A" rootCell
7770

7871
let merged = LayerSet.Merge patches
7972
let qnode = QNode(Guid.NewGuid(), ebb, rootCell, BuildConfig.Default.SplitLimitPowerOfTwo, merged)
8073

81-
if debugOutput then
74+
if config.Verbose then
8275
printfn "[DEBUG] CREATED QNode with split limit = %d" qnode.SplitLimitExponent
8376

8477
//let xs = qnode |> InMemoryNode |> Query.All Query.Config.Default |> Seq.map (fun x -> x.GetSamples<V4f>(Defs.HeightsBilinear4f)) |> Array.ofSeq |> Array.collect id
@@ -98,7 +91,7 @@ module Builder =
9891
)
9992

10093

101-
if debugOutput then
94+
if config.Verbose then
10295
printfn "[DEBUG] SPLIT %d patches" n
10396

10497
//for i in 0..3 do
@@ -108,53 +101,79 @@ module Builder =
108101
let subNodes = patchesPerQuadrant |> Array.map (fun (subCell, subPatches) ->
109102
match subPatches.Length with
110103
| 0 -> NoNode
111-
| _ -> build' sampleExponent subCell subPatches
104+
| _ -> build' config sampleExponent subCell subPatches
112105
)
113106

114107
let hasMask = subNodes |> Array.exists (fun n -> n.HasMask)
115-
if debugOutput && hasMask then
108+
if config.Verbose && hasMask then
116109
printfn "[DEBUG] has mask %A" rootCell
117110
let result = { Id = Guid.NewGuid(); ExactBoundingBox = ebb; Cell = rootCell; SplitLimitExponent = BuildConfig.Default.SplitLimitPowerOfTwo; HasMask = hasMask; SubNodes = subNodes }
118111
result |> InMemoryInner
119112

120-
let rec private build'' (rootCell : Cell2d) (patches : LayerSet[]) =
113+
let rec private build'' (config : BuildConfig) (rootCell : Cell2d) (patches : LayerSet[]) =
121114

122-
if debugOutput then
115+
if config.Verbose then
123116
printfn "[DEBUG] build' rootCell = %A, %d patches" rootCell patches.Length
124117

125118
let minSampleExponent = patches |> Seq.map (fun p -> p.SampleExponent) |> Seq.min
126119

127120
match patches.Length with
128121

129-
| 0 -> NoNode
122+
| 0 ->
123+
124+
if config.Verbose then
125+
printfn "[DEBUG][build''] ZERO patches"
126+
127+
NoNode
130128

131129
| 1 ->
132130

131+
if config.Verbose then
132+
printfn "[DEBUG][build''] SINGLE patch (%A)" patches[0].SampleWindow
133+
133134
let theSinglePatch = patches[0]
134135

135-
if debugOutput then
136-
printfn "[DEBUG] SINGLE patch (%A)" theSinglePatch.SampleWindow
136+
Quadtree.Build config theSinglePatch.Layers
137137

138-
Quadtree.Build BuildConfig.Default theSinglePatch.Layers
138+
| 2 ->
139+
140+
if config.Verbose then
141+
printfn "[DEBUG][build''] TWO patches (%A, %A)" patches[0].SampleWindow patches[1].SampleWindow
142+
143+
let p0 = Quadtree.Build' config patches[0]
144+
let p1 = Quadtree.Build' config patches[1]
145+
146+
Quadtree.Merge Dominance.MoreDetailedOrSecond p0 p1
139147

140148
| n -> // n patches
141149

150+
if config.Verbose then
151+
printfn "[DEBUG][build''] n=%d patches" patches.Length
152+
142153
let ebb = patches |> Seq.map (fun patch -> patch.BoundingBox) |> Box2d
143154

155+
invariantm (config.SplitLimitPowerOfTwo >= 0)
156+
(fun () -> sprintf "Expected config.SplitLimitPowerOfTwo to be non-negative, but found %d." config.SplitLimitPowerOfTwo)
157+
"95c43529-9649-42d6-9b47-c6f8fb6da301"
158+
159+
let tileSize = 2 <<< config.SplitLimitPowerOfTwo
144160
let rootBounds = getBoundsForExponent minSampleExponent rootCell
145-
if rootBounds.Size.X <= 256 && rootBounds.Size.Y <= 256 then
161+
162+
if rootBounds.Size.X <= tileSize && rootBounds.Size.Y <= tileSize then
146163

164+
if config.Verbose then
165+
printfn "[DEBUG][build''] MERGE %d patches; because reached split limit" n
166+
167+
failwith "TODO"
168+
147169
let bbWindow = patches |> Seq.map (fun patch -> patch.SampleWindow) |> Box2l
148170

149-
if debugOutput then
150-
printfn "[DEBUG] MERGE %d patches; %A" n (bbWindow - rootBounds.Min)
151-
152171
//if debugOutput then
153172
// for patch in patches do
154173
// printfn "[DEBUG] %A (exact %A)" (patch.SampleWindow - rootBounds.Min) (bbWindow - rootBounds.Min)
155174

156175
// adjust root cell for split limit
157-
let requiredRootCellSplitLimit = minSampleExponent + BuildConfig.Default.SplitLimitPowerOfTwo
176+
let requiredRootCellSplitLimit = minSampleExponent + config.SplitLimitPowerOfTwo
158177

159178
let mutable rootCell = rootCell
160179

@@ -164,45 +183,47 @@ module Builder =
164183
(fun () -> sprintf "Expected root cell exponent %d to be smaller than requiredRootCellSplitLimit %d." rootCell.Exponent requiredRootCellSplitLimit)
165184
"4911adf3-7b87-4234-9bcc-bc3076df846e"
166185

167-
if debugOutput then
168-
printfn "[DEBUG] must adjust root cell %A exponent to %d" rootCell requiredRootCellSplitLimit
186+
if config.Verbose then
187+
printfn "[DEBUG][build''] must adjust root cell %A exponent to %d" rootCell requiredRootCellSplitLimit
169188

170189
while rootCell.Exponent < requiredRootCellSplitLimit do rootCell <- rootCell.Parent
171190

172-
if debugOutput then
173-
printfn "[DEBUG] adjusted root cell is %A" rootCell
191+
if config.Verbose then
192+
printfn "[DEBUG][build''] adjusted root cell is %A" rootCell
174193

175194
let merged = LayerSet.Merge patches
176-
let qnode = QNode(Guid.NewGuid(), ebb, rootCell, BuildConfig.Default.SplitLimitPowerOfTwo, merged)
195+
let qnode = QNode(Guid.NewGuid(), ebb, rootCell, config.SplitLimitPowerOfTwo, merged)
177196

178-
if debugOutput then
179-
printfn "[DEBUG] CREATED QNode with split limit = %d" qnode.SplitLimitExponent
197+
if config.Verbose then
198+
printfn "[DEBUG][build''] CREATED QNode with split limit = %d" qnode.SplitLimitExponent
180199

181200
//let xs = qnode |> InMemoryNode |> Query.All Query.Config.Default |> Seq.map (fun x -> x.GetSamples<V4f>(Defs.HeightsBilinear4f)) |> Array.ofSeq |> Array.collect id
182201
//for x in xs do printfn "%A" x
183202
qnode |> InMemoryNode
184203

185204
else
186-
205+
206+
if config.Verbose then
207+
printfn "[DEBUG][build''] SPLIT %d patches into quadrants of %A ... " n rootCell
208+
187209
//let bbQuadrants = rootCell.Children |> Array.map (fun subCell -> subCell.GetBoundsForExponent(sampleExponent))
188210

189211
let patchesPerQuadrant =
190212
rootCell.Children
191213
|> Array.map (fun subCell ->
192-
let bbQuadrant = subCell.GetBoundsForExponent(minSampleExponent)
193214
let subPatches =
194215
patches // TODO: ensure that bbQuadrant is in same resolution as patch ?!?
195216
|> Array.choose (fun patch ->
196-
if patch.SampleExponent <> minSampleExponent then Debugger.Break()
217+
let bbQuadrant = subCell.GetBoundsForExponent(patch.SampleExponent)
218+
//if patch.SampleExponent <> minSampleExponent then Debugger.Break()
197219
patch.WithWindow bbQuadrant
198220
)
199221

200222
(subCell, subPatches)
201223
)
202224

203-
204-
if debugOutput then
205-
printfn "[DEBUG] SPLIT %d patches" n
225+
if config.Verbose then
226+
printfn "[DEBUG][build''] SPLIT %d patches into quadrants of %A --> %A" n rootCell (patchesPerQuadrant |> Array.map(fun (_,xs) -> xs.Length))
206227

207228
//for i in 0..3 do
208229
// let (subCell, subPatches) = patchesPerQuadrant[i]
@@ -211,24 +232,20 @@ module Builder =
211232
let subNodes = patchesPerQuadrant |> Array.map (fun (subCell, subPatches) ->
212233
match subPatches.Length with
213234
| 0 -> NoNode
214-
| _ -> build'' subCell subPatches
235+
| _ -> build'' config subCell subPatches
215236
)
216237

217238
let hasMask = subNodes |> Array.exists (fun n -> n.HasMask)
218-
if debugOutput && hasMask then
219-
printfn "[DEBUG] has mask %A" rootCell
220-
let result = { Id = Guid.NewGuid(); ExactBoundingBox = ebb; Cell = rootCell; SplitLimitExponent = BuildConfig.Default.SplitLimitPowerOfTwo; HasMask = hasMask; SubNodes = subNodes }
239+
if config.Verbose && hasMask then
240+
printfn "[DEBUG][build''] has mask %A" rootCell
241+
let result = { Id = Guid.NewGuid(); ExactBoundingBox = ebb; Cell = rootCell; SplitLimitExponent = config.SplitLimitPowerOfTwo; HasMask = hasMask; SubNodes = subNodes }
221242
result |> InMemoryInner
222243

223244
/// Creates a quadtree from many small patches.
224-
let Build (patches : LayerSet seq) : QNodeRef =
245+
let Build (config : BuildConfig) (patches : LayerSet seq) : QNodeRef =
225246
let patches = patches |> Array.ofSeq
226247
let rootCell = patches |> Seq.map (fun patch -> patch.BoundingBox) |> Box2d |> Cell2d
227-
228-
//let sampleExponent = (patches |> Array.distinctBy (fun x -> x.SampleExponent) |> Array.exactlyOne).SampleExponent
229-
//build' sampleExponent rootCell patches
230-
231-
build'' rootCell patches
248+
build'' config rootCell patches
232249

233250
/// Creates a quadtree from many small patches.
234251
type Builder () =
@@ -294,15 +311,15 @@ type Builder () =
294311
for patch in patches do this.Add(patch)
295312

296313
/// Build a quadtree from all the patches that have been added to this builder.
297-
member this.Build () : QNodeRef option =
314+
member this.Build (config : BuildConfig) : QNodeRef option =
298315

299316
let mutable mergesCount = 0
300317

301318
patches
302319
// (1) sort per-resolution patch lists from coarse to fine resolution ...
303320
|> Seq.sortByDescending (fun kv -> kv.Key) |> Seq.map (fun kv -> kv.Value)
304321
// (2) create a quadtree for each resolution ...
305-
|> Seq.map Builder.Build
322+
|> Seq.map (Builder.Build config)
306323
// (3) merge quadtrees with finer resolution always dominating ...
307324
|> Seq.fold (fun state item ->
308325
match state with
@@ -315,14 +332,10 @@ type Builder () =
315332
None // initial state
316333

317334
/// Build a quadtree from all the patches that have been added to this builder.
318-
member this.Build2 () : QNodeRef option =
319-
320-
let mutable mergesCount = 0
321-
335+
member this.Build2 (config : BuildConfig) : QNodeRef option =
322336
let allPatches = this.GetPatches()
323-
Builder.Build allPatches |> Some
337+
Builder.Build config allPatches |> Some
324338

325-
326339
/// Enumerate all patches.
327340
member this.GetPatches () : seq<LayerSet> =
328341
patches |> Seq.map (fun kv -> kv.Value) |> Seq.collect id

src/Aardvark.Geometry.Quadtree/Layer.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,7 @@ type LayerSet(layers : ILayer[]) =
422422
member this.SampleWindowAtChildLevel with get() = layers.[0].SampleWindowAtChildLevel
423423

424424
/// Returns 2.0 ^ SampleExponent.
425-
member this.SampleSize with get() = 2.0 ** float(layers.[0].Mapping.BufferOrigin.Exponent)
425+
member this.SampleSize with get() = 2.0 ** float(this.SampleExponent)
426426

427427
member this.TryGetLayer (semantic : Durable.Def) : ILayer option =
428428
layers |> Array.tryFind (fun x -> x.Def.Id = semantic.Id)

src/Aardvark.Geometry.Quadtree/Quadtree.fs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@ open System.Collections.Generic
1515
type BuildConfig = {
1616
/// Node is split if width and/or height is greater than 2^SplitLimitPowerOfTwo.
1717
SplitLimitPowerOfTwo : int
18+
Verbose : bool
1819
}
1920
with
20-
static member Default = { SplitLimitPowerOfTwo = 8 }
21+
static member Default = { SplitLimitPowerOfTwo = 8; Verbose = false }
2122

2223
module Quadtree =
2324

@@ -242,6 +243,11 @@ module Quadtree =
242243

243244
build config rootCell layers
244245

246+
/// At least 1 layer is required, and
247+
/// all layers must have the same sample exponent and sample window.
248+
let Build' (config : BuildConfig) (layerSet : LayerSet) =
249+
Build config layerSet.Layers
250+
245251
/// Returns new merged quadtree. Immutable merge.
246252
let Merge (domination : Dominance) (first : QNodeRef) (second : QNodeRef) =
247253
Merge.merge domination first second

src/Scratch/Program.fs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,7 +1033,7 @@ let builderSketch () =
10331033
for n in patches do builder.Add n
10341034

10351035
// (4) build new and better quadtree
1036-
match builder.Build() with
1036+
match builder.Build BuildConfig.Default with
10371037
| None -> printfn "no quadtree"
10381038
| Some newAndBetterTree ->
10391039
let countLeafNodes = newAndBetterTree |> Quadtree.CountLeafNodes true
@@ -1253,7 +1253,7 @@ let builderTest_20240112 () =
12531253
builder.Print()
12541254

12551255
// (4) build new and better quadtree
1256-
match builder.Build() with
1256+
match builder.Build BuildConfig.Default with
12571257
| None -> printfn "no quadtree"
12581258
| Some newAndBetterTree ->
12591259
let countLeafNodes = newAndBetterTree |> Quadtree.CountLeafNodes true
@@ -1328,7 +1328,8 @@ let cp_20240202_quadtreetest () =
13281328
|> Seq.sumBy(fun patch -> patch.SampleWindow.Area)
13291329
printfn("total samples count with e = -3: %d") samplesCount
13301330

1331-
match x.Build2 () with
1331+
let buildConfig = { BuildConfig.Default with Verbose = true }
1332+
match x.Build2 buildConfig with
13321333
| None -> failwith ""
13331334
| Some qtree ->
13341335
let makeReturnValOfQueryResults (resultChunk : seq<Query.Result>) (def : Aardvark.Data.Durable.Def) =

0 commit comments

Comments
 (0)