Skip to content

Commit 28ac4dd

Browse files
committed
Fix intersection on bounds for rotated grids
1 parent a77116c commit 28ac4dd

3 files changed

Lines changed: 33 additions & 17 deletions

File tree

gridkit-py/src/lib.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -954,7 +954,7 @@ impl PyO3TriGrid {
954954
) -> PyO3TriGrid {
955955
let target_loc: [f64; 2] = target_loc.into();
956956
let cell_element =
957-
CellElement::from_string(&cell_element).expect("Unsupported cell_element {}");
957+
CellElement::from_string(&cell_element).expect(&format!("Unsupported cell_element: '{}'", cell_element));
958958
let mut new_grid = self.clone();
959959
new_grid._grid.anchor_inplace(&target_loc, cell_element);
960960
new_grid
@@ -968,7 +968,7 @@ impl PyO3TriGrid {
968968
) {
969969
let target_loc: [f64; 2] = target_loc.into();
970970
let cell_element =
971-
CellElement::from_string(&cell_element).expect("Unsupported cell_element {}");
971+
CellElement::from_string(&cell_element).expect(&format!("Unsupported cell_element: '{}'", cell_element));
972972
self._grid.anchor_inplace(&target_loc, cell_element);
973973
}
974974

@@ -1145,7 +1145,7 @@ impl PyO3RectGrid {
11451145
) -> PyO3RectGrid {
11461146
let target_loc: [f64; 2] = target_loc.into();
11471147
let cell_element =
1148-
CellElement::from_string(&cell_element).expect("Unsupported cell_element {}");
1148+
CellElement::from_string(&cell_element).expect(&format!("Unsupported cell_element: '{}'", cell_element));
11491149
let mut new_grid = self.clone();
11501150
new_grid._grid.anchor_inplace(&target_loc, cell_element);
11511151
new_grid
@@ -1159,7 +1159,7 @@ impl PyO3RectGrid {
11591159
) {
11601160
let target_loc: [f64; 2] = target_loc.into();
11611161
let cell_element =
1162-
CellElement::from_string(&cell_element).expect("Unsupported cell_element {}");
1162+
CellElement::from_string(&cell_element).expect(&format!("Unsupported cell_element: '{}'", cell_element));
11631163
self._grid.anchor_inplace(&target_loc, cell_element);
11641164
}
11651165

gridkit-py/tests/test_gridkit/test_statistical_functions.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,9 @@ def test_combine_tiles(grid):
7575
HexGrid(size=1, shape="flat"),
7676
],
7777
)
78-
def test_count_data_tile(grid):
79-
grid.rotation = 12
78+
@pytest.mark.parametrize("rotation", [-12, 363, 186])
79+
def test_count_data_tile(grid, rotation):
80+
grid.rotation = rotation
8081

8182
tile1 = Tile(grid, (-2, -3), 5, 7)
8283
tile2 = Tile(grid, (1, 0), 7, 5).to_data_tile_with_value(3.2)

gridkit-rs/src/tile.rs

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -213,20 +213,35 @@ impl TileTraits for Tile {
213213
}
214214

215215
fn intersects(&self, other: &Tile) -> bool {
216+
217+
// Note: It is easier to match tiles on their ids. This seems elegant
218+
// because we don't need to care about rotation. This was how it
219+
// was first implemented but it required self and other to be on
220+
// the same grid. This was not enforced so you would get weird
221+
// results if this was not upheld. Rather than forcing the grids
222+
// to be aligned we use the tile corner coordinates. This way
223+
// any tile can be checked for intersection with any other tile
224+
// purely based on location, regardless of the host grid. This
225+
// does have the downside that we need to account for rotated
226+
// grids where the corner that was originally the on the left
227+
// side might now be the rightmost corner.
216228
let corners_self = self.corners();
217229
let corners_other = other.corners();
218230

219-
let left_self = corners_self[Ix2(3,0)];
220-
let bottom_self = corners_self[Ix2(3,1)];
221-
let right_self = corners_self[Ix2(1,0)];
222-
let top_self = corners_self[Ix2(1,1)];
223-
224-
let left_other = corners_other[Ix2(3,0)];
225-
let bottom_other = corners_other[Ix2(3,1)];
226-
let right_other = corners_other[Ix2(1,0)];
227-
let top_other = corners_other[Ix2(1,1)];
228-
return !(
229-
left_self >= right_other
231+
// Get min and max values.
232+
// Note: This is a thorn in the eye as .min() does not work
233+
// on ndarrays of dtype float because of nan and inf values.
234+
let left_self = corners_self.slice(s![..,0]).iter().cloned().reduce(f64::min).unwrap();
235+
let bottom_self = corners_self.slice(s![..,1]).iter().cloned().reduce(f64::min).unwrap();
236+
let right_self = corners_self.slice(s![..,0]).iter().cloned().reduce(f64::max).unwrap();
237+
let top_self = corners_self.slice(s![..,1]).iter().cloned().reduce(f64::max).unwrap();
238+
239+
let left_other = corners_other.slice(s![..,0]).iter().cloned().reduce(f64::min).unwrap();
240+
let bottom_other = corners_other.slice(s![..,1]).iter().cloned().reduce(f64::min).unwrap();
241+
let right_other = corners_other.slice(s![..,0]).iter().cloned().reduce(f64::max).unwrap();
242+
let top_other = corners_other.slice(s![..,1]).iter().cloned().reduce(f64::max).unwrap();
243+
244+
return !(left_self >= right_other
230245
|| right_self <= left_other
231246
|| bottom_self >= top_other
232247
|| top_self <= bottom_other

0 commit comments

Comments
 (0)