@@ -11,7 +11,7 @@ module Builder =
11
11
12
12
let private debugOutput =
13
13
#if DEBUG
14
- true
14
+ false
15
15
#else
16
16
false
17
17
#endif
@@ -86,7 +86,7 @@ module Builder =
86
86
87
87
else
88
88
89
- let bbQuadrants = rootCell.Children |> Array.map ( fun subCell -> subCell.GetBoundsForExponent( sampleExponent))
89
+ // let bbQuadrants = rootCell.Children |> Array.map (fun subCell -> subCell.GetBoundsForExponent(sampleExponent))
90
90
91
91
let patchesPerQuadrant =
92
92
rootCell.Children
@@ -116,6 +116,106 @@ module Builder =
116
116
let result = { Id = Guid.NewGuid(); ExactBoundingBox = ebb; Cell = rootCell; SplitLimitExponent = BuildConfig.Default.SplitLimitPowerOfTwo; HasMask = hasMask; SubNodes = subNodes }
117
117
result |> InMemoryInner
118
118
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
+
119
219
/// Creates a quadtree from many small patches.
120
220
let Build ( patches : LayerSet seq ) : QNodeRef =
121
221
let patches = patches |> Array.ofSeq
@@ -188,6 +288,8 @@ type Builder () =
188
288
189
289
/// Build a quadtree from all the patches that have been added to this builder.
190
290
member this.Build () : QNodeRef option =
291
+
292
+ let mutable mergesCount = 0
191
293
192
294
patches
193
295
// (1) sort per-resolution patch lists from coarse to fine resolution ...
@@ -198,7 +300,10 @@ type Builder () =
198
300
|> Seq.fold ( fun state item ->
199
301
match state with
200
302
| 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
202
307
)
203
308
None // initial state
204
309
0 commit comments