Skip to content

Commit 22cf94c

Browse files
sync
1 parent 4660999 commit 22cf94c

File tree

5 files changed

+146
-62
lines changed

5 files changed

+146
-62
lines changed

src/Aardvark.Geometry.Quadtree/Builder.fs

Lines changed: 40 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ module Builder =
1313
let rec private build' (config : BuildConfig) (sampleExponent : int) (rootCell : Cell2d) (patches : LayerSet[]) =
1414

1515
if config.Verbose then
16-
printfn "[DEBUG] build' rootCell = %A, %d patches" rootCell patches.Length
16+
printfn "[build'] rootCell = %A, %d patches" rootCell patches.Length
1717

1818
for p in patches do
1919
invariantm (p.SampleExponent = sampleExponent)
@@ -29,7 +29,7 @@ module Builder =
2929
let theSinglePatch = patches[0]
3030

3131
if config.Verbose then
32-
printfn "[DEBUG] SINGLE patch (%A)" theSinglePatch.SampleWindow
32+
printfn "[build'] SINGLE patch (%A)" theSinglePatch.SampleWindow
3333

3434
Quadtree.Build BuildConfig.Default theSinglePatch.Layers
3535

@@ -43,11 +43,11 @@ module Builder =
4343
let bbWindow = patches |> Seq.map (fun patch -> patch.SampleWindow) |> Box2l
4444

4545
if config.Verbose then
46-
printfn "[DEBUG] MERGE %d patches; %A" n (bbWindow - rootBounds.Min)
46+
printfn "[build'] MERGE %d patches; %A" n (bbWindow - rootBounds.Min)
4747

4848
//if debugOutput then
4949
// for patch in patches do
50-
// printfn "[DEBUG] %A (exact %A)" (patch.SampleWindow - rootBounds.Min) (bbWindow - rootBounds.Min)
50+
// printfn "[build'] %A (exact %A)" (patch.SampleWindow - rootBounds.Min) (bbWindow - rootBounds.Min)
5151

5252
// adjust root cell for split limit
5353
let requiredRootCellSplitLimit = sampleExponent + BuildConfig.Default.SplitLimitPowerOfTwo
@@ -61,18 +61,18 @@ module Builder =
6161
"4911adf3-7b87-4234-9bcc-bc3076df846e"
6262

6363
if config.Verbose then
64-
printfn "[DEBUG] must adjust root cell %A exponent to %d" rootCell requiredRootCellSplitLimit
64+
printfn "[build'] must adjust root cell %A exponent to %d" rootCell requiredRootCellSplitLimit
6565

6666
while rootCell.Exponent < requiredRootCellSplitLimit do rootCell <- rootCell.Parent
6767

6868
if config.Verbose then
69-
printfn "[DEBUG] adjusted root cell is %A" rootCell
69+
printfn "[build'] adjusted root cell is %A" rootCell
7070

7171
let merged = LayerSet.Merge patches
7272
let qnode = QNode(Guid.NewGuid(), ebb, rootCell, BuildConfig.Default.SplitLimitPowerOfTwo, merged)
7373

7474
if config.Verbose then
75-
printfn "[DEBUG] CREATED QNode with split limit = %d" qnode.SplitLimitExponent
75+
printfn "[build'] CREATED QNode with split limit = %d" qnode.SplitLimitExponent
7676

7777
//let xs = qnode |> InMemoryNode |> Query.All Query.Config.Default |> Seq.map (fun x -> x.GetSamples<V4f>(Defs.HeightsBilinear4f)) |> Array.ofSeq |> Array.collect id
7878
//for x in xs do printfn "%A" x
@@ -92,7 +92,7 @@ module Builder =
9292

9393

9494
if config.Verbose then
95-
printfn "[DEBUG] SPLIT %d patches" n
95+
printfn "[build'] SPLIT %d patches" n
9696

9797
//for i in 0..3 do
9898
// let (subCell, subPatches) = patchesPerQuadrant[i]
@@ -106,14 +106,14 @@ module Builder =
106106

107107
let hasMask = subNodes |> Array.exists (fun n -> n.HasMask)
108108
if config.Verbose && hasMask then
109-
printfn "[DEBUG] has mask %A" rootCell
109+
printfn "[build'] has mask %A" rootCell
110110
let result = { Id = Guid.NewGuid(); ExactBoundingBox = ebb; Cell = rootCell; SplitLimitExponent = BuildConfig.Default.SplitLimitPowerOfTwo; HasMask = hasMask; SubNodes = subNodes }
111111
result |> InMemoryInner
112112

113113
let rec private build'' (config : BuildConfig) (rootCell : Cell2d) (patches : LayerSet[]) =
114114

115115
if config.Verbose then
116-
printfn "[DEBUG] build' rootCell = %A, %d patches" rootCell patches.Length
116+
printfn "[build''] rootCell = %A, %d patches" rootCell patches.Length
117117

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

@@ -122,14 +122,14 @@ module Builder =
122122
| 0 ->
123123

124124
if config.Verbose then
125-
printfn "[DEBUG][build''] ZERO patches"
125+
printfn "[build''] ZERO patches"
126126

127127
NoNode
128128

129129
| 1 ->
130130

131131
if config.Verbose then
132-
printfn "[DEBUG][build''] SINGLE patch (%A)" patches[0].SampleWindow
132+
printfn "[build''] SINGLE patch (%A)" patches[0].SampleWindow
133133

134134
let theSinglePatch = patches[0]
135135

@@ -138,7 +138,7 @@ module Builder =
138138
| 2 ->
139139

140140
if config.Verbose then
141-
printfn "[DEBUG][build''] TWO patches (%A, %A)" patches[0].SampleWindow patches[1].SampleWindow
141+
printfn "[build''] TWO patches (%A, %A)" patches[0].SampleWindow patches[1].SampleWindow
142142

143143
let p0 = Quadtree.Build' config patches[0]
144144
let p1 = Quadtree.Build' config patches[1]
@@ -148,7 +148,7 @@ module Builder =
148148
| n -> // n patches
149149

150150
if config.Verbose then
151-
printfn "[DEBUG][build''] n=%d patches" patches.Length
151+
printfn "[build''] MULTIPLE patches (n=%d)" patches.Length
152152

153153
let ebb = patches |> Seq.map (fun patch -> patch.BoundingBox) |> Box2d
154154

@@ -161,8 +161,17 @@ module Builder =
161161

162162
if rootBounds.Size.X <= tileSize && rootBounds.Size.Y <= tileSize then
163163

164+
// current tile size has reached the split limit:
165+
// 1. sort all patches from fine to coarse (from small to large sample exponents)
166+
// 2. flatten all patches/layers into a single patch/layer
167+
// -> resulting layer has finest resolution of all patches
168+
// -> coarser layers will be subsampled
169+
// -> a mask indicates non-defined samples
170+
164171
if config.Verbose then
165-
printfn "[DEBUG][build''] MERGE %d patches; because reached split limit" n
172+
printfn "[build''] MERGE %d patches; because reached split limit" n
173+
for patch in patches do
174+
printfn "[build''] | e=%d origin=%A size=%A" patch.SampleExponent patch.SampleWindow.Min patch.SampleWindow.Size
166175

167176
failwith "TODO"
168177

@@ -184,46 +193,49 @@ module Builder =
184193
"4911adf3-7b87-4234-9bcc-bc3076df846e"
185194

186195
if config.Verbose then
187-
printfn "[DEBUG][build''] must adjust root cell %A exponent to %d" rootCell requiredRootCellSplitLimit
196+
printfn "[build''] must adjust root cell %A exponent to %d" rootCell requiredRootCellSplitLimit
188197

189198
while rootCell.Exponent < requiredRootCellSplitLimit do rootCell <- rootCell.Parent
190199

191200
if config.Verbose then
192-
printfn "[DEBUG][build''] adjusted root cell is %A" rootCell
201+
printfn "[build''] adjusted root cell is %A" rootCell
193202

194203
let merged = LayerSet.Merge patches
195204
let qnode = QNode(Guid.NewGuid(), ebb, rootCell, config.SplitLimitPowerOfTwo, merged)
196205

197206
if config.Verbose then
198-
printfn "[DEBUG][build''] CREATED QNode with split limit = %d" qnode.SplitLimitExponent
207+
printfn "[build''] CREATED QNode with split limit = %d" qnode.SplitLimitExponent
199208

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

204213
else
205214

206-
if config.Verbose then
207-
printfn "[DEBUG][build''] SPLIT %d patches into quadrants of %A ... " n rootCell
208-
209-
//let bbQuadrants = rootCell.Children |> Array.map (fun subCell -> subCell.GetBoundsForExponent(sampleExponent))
215+
// current tile size is still above split limit:
216+
// we sort all patches into the current cell's quadrants, and
217+
// if a patch overlaps multiple quadrants, then we split the patch (according to the quadrants)
210218

219+
if config.Verbose then
220+
printfn "[build''] SPLIT %d patches into quadrants of %A ..." n rootCell
221+
211222
let patchesPerQuadrant =
212223
rootCell.Children
213224
|> Array.map (fun subCell ->
214225
let subPatches =
215-
patches // TODO: ensure that bbQuadrant is in same resolution as patch ?!?
226+
patches
216227
|> Array.choose (fun patch ->
217228
let bbQuadrant = subCell.GetBoundsForExponent(patch.SampleExponent)
218-
//if patch.SampleExponent <> minSampleExponent then Debugger.Break()
219-
patch.WithWindow bbQuadrant
229+
let r = patch.WithWindow bbQuadrant
230+
if config.Verbose && r.IsSome then
231+
printfn "[build''] | subCell=%A patch.Window=%A bbQuadrant=%A" subCell patch.SampleWindow r.Value.SampleWindow
232+
r
220233
)
221-
222234
(subCell, subPatches)
223235
)
224236

225237
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))
238+
printfn "[build''] SPLIT %d patches into quadrants of %A --> %A" n rootCell (patchesPerQuadrant |> Array.map(fun (_,xs) -> xs.Length))
227239

228240
//for i in 0..3 do
229241
// let (subCell, subPatches) = patchesPerQuadrant[i]
@@ -237,7 +249,7 @@ module Builder =
237249

238250
let hasMask = subNodes |> Array.exists (fun n -> n.HasMask)
239251
if config.Verbose && hasMask then
240-
printfn "[DEBUG][build''] has mask %A" rootCell
252+
printfn "[build''] has mask %A" rootCell
241253
let result = { Id = Guid.NewGuid(); ExactBoundingBox = ebb; Cell = rootCell; SplitLimitExponent = config.SplitLimitPowerOfTwo; HasMask = hasMask; SubNodes = subNodes }
242254
result |> InMemoryInner
243255

src/Aardvark.Geometry.Quadtree/Node.fs

Lines changed: 49 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,15 @@ and
136136
First : QNodeRef
137137
Second : QNodeRef
138138
}
139+
and
140+
QMultiMergeNode = {
141+
Id : Guid
142+
ExactBoundingBox : Box2d
143+
Cell : Cell2d
144+
SplitLimitExponent : int
145+
HasMask : bool
146+
Nodes : QNodeRef[]
147+
}
139148
and
140149
QLinkedNode = {
141150
Id : Guid
@@ -157,6 +166,7 @@ and
157166
| OutOfCoreNode of QOutOfCoreNode
158167
| InMemoryInner of QInnerNode
159168
| InMemoryMerge of QMergeNode
169+
| MultiMerge of QMultiMergeNode
160170
| LinkedNode of QLinkedNode
161171
with
162172

@@ -167,6 +177,7 @@ and
167177
| InMemoryNode n -> n.Id
168178
| InMemoryInner n -> n.Id
169179
| InMemoryMerge n -> n.Id
180+
| MultiMerge n -> n.Id
170181
| OutOfCoreNode n -> n.Load().Id
171182
| LinkedNode n -> n.Id
172183

@@ -177,6 +188,7 @@ and
177188
| InMemoryNode n -> n.Cell
178189
| InMemoryInner n -> n.Cell
179190
| InMemoryMerge n -> n.Cell
191+
| MultiMerge n -> n.Cell
180192
| OutOfCoreNode n -> n.Load().Cell
181193
| LinkedNode n -> n.Target.Cell
182194

@@ -187,6 +199,7 @@ and
187199
| InMemoryNode n -> n.ExactBoundingBox
188200
| InMemoryInner n -> n.ExactBoundingBox
189201
| InMemoryMerge n -> n.ExactBoundingBox
202+
| MultiMerge n -> n.ExactBoundingBox
190203
| OutOfCoreNode n -> n.Load().ExactBoundingBox
191204
| LinkedNode n -> n.Target.ExactBoundingBox
192205

@@ -197,53 +210,59 @@ and
197210
| InMemoryNode n -> n.SplitLimitExponent
198211
| InMemoryInner n -> n.SplitLimitExponent
199212
| InMemoryMerge n -> n.SplitLimitExponent
213+
| MultiMerge n -> n.SplitLimitExponent
200214
| OutOfCoreNode n -> n.Load().SplitLimitExponent
201215
| LinkedNode n -> n.Target.SplitLimitExponent
202216

203217
member this.GetFirstNonEmptySubNode() : QNodeRef option =
204218
match this with
205219
| NoNode -> None
220+
| InMemoryNode _ -> None
206221
| InMemoryInner n -> n.SubNodes |> Array.tryFind (fun sn -> match sn with | NoNode -> false | _ -> true)
207222
| InMemoryMerge n -> Some n.First
208-
| InMemoryNode _ -> None
223+
| MultiMerge n -> Some n.Nodes[0]
209224
| OutOfCoreNode n -> n.Load().GetFirstNonEmptySubNode()
210225
| LinkedNode n -> n.Target.GetFirstNonEmptySubNode()
211226

212227
member this.ContainsLayer (semantic : Durable.Def) =
213228
match this with
214229
| NoNode -> false
230+
| InMemoryNode n -> n.ContainsLayer semantic
215231
| InMemoryInner _ -> match this.GetFirstNonEmptySubNode() with
216232
| Some n -> n.ContainsLayer(semantic)
217233
| None -> failwith "Invariant 0a85f195-7feb-4ecb-912d-7fd4e7024951."
218234
| InMemoryMerge _ -> false
219-
| InMemoryNode n -> n.ContainsLayer semantic
235+
| MultiMerge _ -> false
220236
| OutOfCoreNode n -> n.Load().ContainsLayer semantic
221237
| LinkedNode n -> n.Target.ContainsLayer semantic
222238

223239
member this.LayerSet with get() : LayerSet option =
224240
match this with
225241
| NoNode -> None
242+
| InMemoryNode n -> Some(n.LayerSet)
226243
| InMemoryInner _ -> None
227244
| InMemoryMerge _ -> None
228-
| InMemoryNode n -> Some(n.LayerSet)
245+
| MultiMerge _ -> None
229246
| OutOfCoreNode n -> n.Load().LayerSet
230247
| LinkedNode n -> n.Target.LayerSet
231248

232249
member this.IsLeafNode with get() =
233250
match this with
234251
| NoNode -> false
252+
| InMemoryNode _ -> true
235253
| InMemoryInner _ -> false
236254
| InMemoryMerge _ -> false
237-
| InMemoryNode _ -> true
255+
| MultiMerge _ -> false
238256
| OutOfCoreNode _ -> true
239257
| LinkedNode n -> n.Target.IsLeafNode
240258

241259
member this.HasMask with get() =
242260
match this with
243261
| NoNode -> false
262+
| InMemoryNode n -> n.HasMask
244263
| InMemoryInner n -> n.HasMask
245264
| InMemoryMerge n -> n.HasMask
246-
| InMemoryNode n -> n.HasMask
265+
| MultiMerge n -> n.HasMask
247266
| OutOfCoreNode n -> n.HasMask
248267
| LinkedNode n -> n.Target.HasMask
249268

@@ -278,6 +297,15 @@ and
278297
let updatedNode = { n with First = q1; Second = q2 }
279298
(true, InMemoryMerge updatedNode)
280299

300+
| MultiMerge n ->
301+
let ns = n.Nodes |> Array.map (fun x -> x.UpdateLayerSemantic(oldSemantic, newSemantic))
302+
let isNotChanged = ns |> Array.forall (fun (x, _) -> x = false)
303+
if isNotChanged then
304+
unchanged
305+
else
306+
let updatedNode = { n with Nodes = ns |> Array.map snd }
307+
(true, MultiMerge updatedNode)
308+
281309
| InMemoryNode n ->
282310
match n.UpdateLayerSemantic(oldSemantic, newSemantic) with
283311
| Some qnode -> (true, InMemoryNode qnode)
@@ -292,42 +320,46 @@ and
292320
match this with
293321
| NoNode
294322
| InMemoryInner _
295-
| InMemoryMerge _ -> sprintf "Layer not found. %A. Error 2c634f5f-d359-4523-b87a-a96d2522c018." def |> failwith
296-
| InMemoryNode n -> n.LayerSet.GetLayer def
323+
| InMemoryMerge _
324+
| MultiMerge _ -> sprintf "Layer not found. %A. Error 2c634f5f-d359-4523-b87a-a96d2522c018." def |> failwith
325+
| InMemoryNode n -> n.LayerSet.GetLayer def
297326
| OutOfCoreNode n -> n.Load().LayerSet.Value.GetLayer def
298-
| LinkedNode n -> n.Target.GetLayer def
327+
| LinkedNode n -> n.Target.GetLayer def
299328

300329
/// Throws if no such layer.
301330
member this.GetLayer<'a when 'a : equality> def =
302331
match this with
303332
| NoNode
304333
| InMemoryInner _
305-
| InMemoryMerge _ -> sprintf "Layer not found. %A. Error f33f39a9-2394-473f-8dae-76bd8baaaafb." def |> failwith
306-
| InMemoryNode n -> n.LayerSet.GetLayer<'a> def
334+
| InMemoryMerge _
335+
| MultiMerge _ -> sprintf "Layer not found. %A. Error f33f39a9-2394-473f-8dae-76bd8baaaafb." def |> failwith
336+
| InMemoryNode n -> n.LayerSet.GetLayer<'a> def
307337
| OutOfCoreNode n -> n.Load().LayerSet.Value.GetLayer<'a> def
308-
| LinkedNode n -> n.Target.GetLayer<'a> def
338+
| LinkedNode n -> n.Target.GetLayer<'a> def
309339

310340
member this.TryGetLayer def =
311341
match this with
312342
| NoNode
313343
| InMemoryInner _
314-
| InMemoryMerge _ -> None
315-
| InMemoryNode n -> n.LayerSet.TryGetLayer def
344+
| InMemoryMerge _
345+
| MultiMerge _ -> None
346+
| InMemoryNode n -> n.LayerSet.TryGetLayer def
316347
| OutOfCoreNode n -> match n.Load().LayerSet with
317348
| Some ls -> ls.TryGetLayer def
318349
| None -> None
319-
| LinkedNode n -> n.Target.TryGetLayer def
350+
| LinkedNode n -> n.Target.TryGetLayer def
320351

321352
member this.TryGetLayer<'a when 'a : equality> def =
322353
match this with
323354
| NoNode
324355
| InMemoryInner _
325-
| InMemoryMerge _ -> None
326-
| InMemoryNode n -> n.LayerSet.TryGetLayer<'a> def
356+
| InMemoryMerge _
357+
| MultiMerge _ -> None
358+
| InMemoryNode n -> n.LayerSet.TryGetLayer<'a> def
327359
| OutOfCoreNode n -> match n.Load().LayerSet with
328360
| Some ls -> ls.TryGetLayer<'a> def
329361
| None -> None
330-
| LinkedNode n -> n.Target.TryGetLayer<'a> def
362+
| LinkedNode n -> n.Target.TryGetLayer<'a> def
331363

332364
module QNode =
333365

0 commit comments

Comments
 (0)