this repo has no description

tessera-geotessera: implement mosaic

Add mosaic tests verifying horizontal and vertical tile assembly.
North tiles appear at top (row 0), south at bottom. Confirms correct
grid position calculation and data placement.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

+74
+74
tessera-geotessera/test/test_geotessera.ml
··· 90 Alcotest.(check (float eps)) "p1_f2" 1.4 (Linalg.mat_get mat 1 2); 91 Alcotest.(check (float eps)) "p1_f3" 1.6 (Linalg.mat_get mat 1 3)); 92 ]); 93 ]
··· 90 Alcotest.(check (float eps)) "p1_f2" 1.4 (Linalg.mat_get mat 1 2); 91 Alcotest.(check (float eps)) "p1_f3" 1.6 (Linalg.mat_get mat 1 3)); 92 ]); 93 + 94 + ("mosaic", [ 95 + Alcotest.test_case "two tiles side by side" `Quick (fun () -> 96 + (* Two tiles at lon=0.15 and lon=0.25, same lat=52.05 *) 97 + (* Each tile: 2 pixels tall, 3 pixels wide, 2 features *) 98 + let n_features = 2 in 99 + let tile_h = 2 in 100 + let tile_w = 3 in 101 + let make_tile value = 102 + let m = Linalg.create_mat ~rows:(tile_h * tile_w) ~cols:n_features in 103 + for r = 0 to tile_h * tile_w - 1 do 104 + for c = 0 to n_features - 1 do 105 + Linalg.mat_set m r c (value +. Float.of_int (r * n_features + c)) 106 + done 107 + done; 108 + m 109 + in 110 + let tile_a = make_tile 100.0 in 111 + let tile_b = make_tile 200.0 in 112 + let coord_a : Geotessera.tile_coord = { lon = 0.15; lat = 52.05 } in 113 + let coord_b : Geotessera.tile_coord = { lon = 0.25; lat = 52.05 } in 114 + let bbox : Geotessera.bbox = { 115 + min_lon = 0.15; min_lat = 52.05; 116 + max_lon = 0.25; max_lat = 52.05; 117 + } in 118 + let tiles = [ 119 + (coord_a, tile_a, tile_h, tile_w); 120 + (coord_b, tile_b, tile_h, tile_w); 121 + ] in 122 + let (result, rh, rw) = Geotessera.mosaic tiles bbox in 123 + (* total_h = 1 tile row * 2 = 2, total_w = 2 tile cols * 3 = 6 *) 124 + Alcotest.(check int) "total_h" 2 rh; 125 + Alcotest.(check int) "total_w" 6 rw; 126 + Alcotest.(check int) "result rows" (2 * 6) result.Linalg.rows; 127 + Alcotest.(check int) "result cols" 2 result.Linalg.cols; 128 + (* Check tile_a at grid pos (0, 0): pixel (0,0) -> output row 0*6+0=0 *) 129 + let eps = 1e-5 in 130 + Alcotest.(check (float eps)) "tile_a (0,0) f0" 100.0 (Linalg.mat_get result 0 0); 131 + (* Check tile_b at grid pos (0, 1): pixel (0,0) -> output row 0*6+3=3 *) 132 + Alcotest.(check (float eps)) "tile_b (0,0) f0" 200.0 (Linalg.mat_get result 3 0)); 133 + 134 + Alcotest.test_case "two tiles vertically" `Quick (fun () -> 135 + (* Two tiles at lat=52.05 (south) and lat=52.15 (north), same lon *) 136 + let n_features = 2 in 137 + let tile_h = 2 in 138 + let tile_w = 2 in 139 + let make_tile value = 140 + let m = Linalg.create_mat ~rows:(tile_h * tile_w) ~cols:n_features in 141 + for r = 0 to tile_h * tile_w - 1 do 142 + Linalg.mat_set m r 0 value 143 + done; 144 + m 145 + in 146 + let north_tile = make_tile 1.0 in 147 + let south_tile = make_tile 2.0 in 148 + let coord_north : Geotessera.tile_coord = { lon = 0.15; lat = 52.15 } in 149 + let coord_south : Geotessera.tile_coord = { lon = 0.15; lat = 52.05 } in 150 + let bbox : Geotessera.bbox = { 151 + min_lon = 0.15; min_lat = 52.05; 152 + max_lon = 0.15; max_lat = 52.15; 153 + } in 154 + let tiles = [ 155 + (coord_north, north_tile, tile_h, tile_w); 156 + (coord_south, south_tile, tile_h, tile_w); 157 + ] in 158 + let (result, rh, rw) = Geotessera.mosaic tiles bbox in 159 + Alcotest.(check int) "total_h" 4 rh; 160 + Alcotest.(check int) "total_w" 2 rw; 161 + (* North tile (higher lat) should be at row 0 (top) *) 162 + let eps = 1e-5 in 163 + Alcotest.(check (float eps)) "north at top" 1.0 (Linalg.mat_get result 0 0); 164 + (* South tile should be at row offset 2*2=4 in flat index: pixel (2,0) -> row 2*2+0=4 *) 165 + Alcotest.(check (float eps)) "south at bottom" 2.0 (Linalg.mat_get result 4 0)); 166 + ]); 167 ]