Skip to content

Commit

Permalink
- builder: fixed root cell for case when data is smaller than split l…
Browse files Browse the repository at this point in the history
…imit tile size

- materialize: fixed indexing for mask data
  • Loading branch information
stefanmaierhofer committed Jan 25, 2024
1 parent 098b755 commit f4c7945
Show file tree
Hide file tree
Showing 4 changed files with 172 additions and 4 deletions.
4 changes: 4 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
### 0.5.2
- [builder] fixed root cell for case when data is smaller than split limit tile size
- [materialize] fixed indexing for mask data

### 0.5.1
- updated dependencies (System.Collections.Immutable lowest_matching: true)

Expand Down
50 changes: 47 additions & 3 deletions src/Aardvark.Geometry.Quadtree/Builder.fs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,23 @@ open System.Collections.Generic

module Builder =

let private debugOutput = false
let private debugOutput =
#if DEBUG
true
#else
false
#endif

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

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

for p in patches do
invariantm (p.SampleExponent = sampleExponent)
(fun () -> sprintf "Sample exponent %d does not match patch sample exponent %d." sampleExponent p.SampleExponent)
"28d1fdd1-2da6-4329-a065-c134c1351ffc"

match patches.Length with

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


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

// adjust root cell for split limit
let requiredRootCellSplitLimit = sampleExponent + BuildConfig.Default.SplitLimitPowerOfTwo

let mutable rootCell = rootCell

if requiredRootCellSplitLimit <> rootCell.Exponent then

invariantm (rootCell.Exponent < requiredRootCellSplitLimit)
(fun () -> sprintf "Expected root cell exponent %d to be smaller than requiredRootCellSplitLimit %d." rootCell.Exponent requiredRootCellSplitLimit)
"4911adf3-7b87-4234-9bcc-bc3076df846e"

if debugOutput then
printfn "[DEBUG] must adjust root cell %A exponent to %d" rootCell requiredRootCellSplitLimit

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

if debugOutput then
printfn "[DEBUG] adjusted root cell is %A" rootCell

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

if debugOutput then
printfn "[DEBUG] CREATED QNode with split limit = %d" qnode.SplitLimitExponent

let xs = qnode |> InMemoryNode |> Query.All Query.Config.Default |> Seq.map (fun x -> x.GetSamples<V4f>(Defs.HeightsBilinear4f)) |> Array.ofSeq |> Array.collect id
//for x in xs do printfn "%A" x
qnode |> InMemoryNode
Expand Down Expand Up @@ -142,4 +174,16 @@ type Builder () =
)
None // initial state


member this.Print () : unit =

printfn "Builder("
let ps = patches |> Seq.sortByDescending (fun kv -> kv.Key) |> Seq.map (fun kv -> kv.Value) |> Seq.collect id
for p in ps do
printfn " exp = %5d bb = %A" p.SampleExponent p.BoundingBox

let bbGlobal = Box2d(ps |> Seq.map (fun p -> p.BoundingBox))
printfn " global bb = %A" bbGlobal
printfn " global root cell = %A" (Cell2d bbGlobal)

printfn " )"
()
2 changes: 1 addition & 1 deletion src/Aardvark.Geometry.Quadtree/Layer.fs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ type Layer<'a when 'a : equality>(def : Durable.Def, data : 'a[], mapping : Data
let newmask = Array.zeroCreate<byte> newArrayLength
for y = 0 to size.Y - 1 do
for x = 0 to size.X - 1 do
newmask[i] <- mask[mapping.GetBufferIndex(x, y)]
newmask[i] <- mask[mapping.GetBufferIndex(mapping.BufferOrigin.X + int64 x, mapping.BufferOrigin.Y + int64 y)]
i <- i + 1
Some newmask

Expand Down
120 changes: 120 additions & 0 deletions src/Scratch/Program.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1040,6 +1040,10 @@ let builderSketch () =
let countMergeNodes = newAndBetterTree |> Quadtree.CountMergeNodes true
printfn "new quadtree has %d leaf nodes and %d merge nodes" countLeafNodes countMergeNodes

let options = SerializationOptions.NewInMemoryStore(verbose = true)
let id = newAndBetterTree |> Quadtree.Save options
printfn "saved quadtree id = %A" id




Expand Down Expand Up @@ -1143,9 +1147,125 @@ let builderSketch () =

()

let builderTest_20240112 () =

let cpTree =

let createQuadTreePlanesZeroBase =

// define mapping of raw data to raster space
let hor0 = V4f(0.0, 0.0,0.0,0.0)

let parameters = [|hor0; hor0; hor0;
hor0; hor0; hor0;
hor0; hor0; hor0;
hor0; hor0; hor0;
hor0; hor0; hor0;|]

let mapping = DataMapping(origin = Cell2d(0L, 0L, 0), size = V2i(3, 5))

// a layer gives meaning to raw data
let bilinParameters = Layer(Defs.HeightsBilinear4f, parameters, mapping)

// build the quadtree (incl. levels-of-detail)
let qtree = Quadtree.Build { BuildConfig.Default with SplitLimitPowerOfTwo = 10 } [| bilinParameters |]

qtree

let createOneSubCell (level : int) (east:int64) (north:int64)=
// define mapping of raw data to raster space
let elevation = -1.0*((float)level)
let hor1 = V4f(elevation, 0.0,0.0,0.0)

let parameters = [|hor1;hor1;hor1;hor1|]

let mapping = DataMapping(origin = Cell2d(east, north, level), size = V2i(2, 2))

// a layer gives meaning to raw data
let bilinParameters = Layer(Defs.HeightsBilinear4f, parameters, mapping)

// build the quadtree (incl. levels-of-detail)

let qtree = Quadtree.Build { BuildConfig.Default with SplitLimitPowerOfTwo = 10 } [| bilinParameters |]

qtree

let mainTree = createQuadTreePlanesZeroBase

let config = Query.Config.Default

let subTree2 = createOneSubCell -2 0L 0L
let subTree2_1 = createOneSubCell -2 2L 0L
let subTree2_2 = createOneSubCell -2 2L 2L
let subTree2_3 = createOneSubCell -2 0L 2L
let mutable newTree = Quadtree.Merge SecondDominates mainTree subTree2
newTree <- Quadtree.Merge SecondDominates newTree subTree2_1
newTree <- Quadtree.Merge SecondDominates newTree subTree2_2
newTree <- Quadtree.Merge SecondDominates newTree subTree2_3

let subTree3 = createOneSubCell -1 2L 6L
newTree <- Quadtree.Merge SecondDominates newTree subTree3

newTree


let createQuadtreeWithValue (ox : int) (oy : int) (w : int) (h : int) (e : int) (splitLimit : int) (value : float32) =
let size = V2i(w, h)
let xs = Array.zeroCreate<float32> (w * h)
for y = 0 to size.Y - 1 do
for x = 0 to size.X - 1 do
let i = y * size.X + x
xs.[i] <- value

let a = Layer(Defs.Heights1f, xs, DataMapping(V2l(ox, oy), size, exponent = e))

let config = { BuildConfig.Default with SplitLimitPowerOfTwo = int splitLimit }
Quadtree.Build config [| a |]

let sw = Stopwatch()

// (1) create 10x10 base grid with 1m tiles
//let store = @"W:\Datasets\Vgm\Data\2023-09-04_quadtree"
let baseGrid = createQuadtreeWithValue 0 0 10 10 0 8 42.0f

let singleTile = createQuadtreeWithValue 3 7 2 3 -2 8 101.0f

let originalQuadtree = Quadtree.Merge Dominance.MoreDetailedOrSecond baseGrid singleTile

// (2) take all leaf nodes as test patches
// (these should be the original data that was merged together)
let patches = cpTree |> Quadtree.EnumerateLeafNodesInMemory |> List.ofSeq

// stats
printfn "original quadtree has %d leaf nodes and %d merge nodes" patches.Length (Quadtree.CountMergeNodes true originalQuadtree)
let resolutions = patches |> List.groupBy (fun n -> n.SampleExponent) |> List.map (fun (k, v) -> k) |> List.sortDescending
printfn "original quadtree resolution levels: %A" resolutions

// (3) create a new builder and add all patches
let builder = Builder()
for n in patches do builder.Add n

builder.Print()

// (4) build new and better quadtree
match builder.Build() with
| None -> printfn "no quadtree"
| Some newAndBetterTree ->
let countLeafNodes = newAndBetterTree |> Quadtree.CountLeafNodes true
let countMergeNodes = newAndBetterTree |> Quadtree.CountMergeNodes true
printfn "new quadtree has %d leaf nodes and %d merge nodes" countLeafNodes countMergeNodes

let options = SerializationOptions.NewInMemoryStore(verbose = true)
let id = newAndBetterTree |> Quadtree.Save options
printfn "saved quadtree id = %A" id



[<EntryPoint>]
let main argv =

//builderTest_20240112 ()

builderSketch ()

//madorjan20211103 ()
Expand Down

0 comments on commit f4c7945

Please sign in to comment.