mirror of
https://github.com/quickwit-oss/tantivy.git
synced 2025-12-23 02:29:57 +00:00
Triangulation is not just a conversion.
The triangulation function in `triangle.rs` is now called `delaunay_to_triangles` and it accepts the output of a Delaunay triangulation from `i_triangle` and not a GeoRust multi-polygon. The translation of user polygons to `i_triangle` polygons and subsequent triangulation will take place outside of `triangle.rs`.
This commit is contained in:
committed by
Paul Masurel
parent
ccdf399cd7
commit
d3049cb323
@@ -5,9 +5,7 @@
|
||||
//! contain an additional vertex and packed reconstruction metadata, allowing exact triangle
|
||||
//! recovery when needed.
|
||||
|
||||
use geo_types::MultiPolygon;
|
||||
use i_triangle::i_overlay::i_float::int::point::IntPoint;
|
||||
use i_triangle::int::triangulatable::IntTriangulatable;
|
||||
use i_triangle::advanced::delaunay::IntDelaunay;
|
||||
use robust::{orient2d, Coord};
|
||||
|
||||
const MINY_MINX_MAXY_MAXX_Y_X: i32 = 0;
|
||||
@@ -303,65 +301,37 @@ impl Triangle {
|
||||
}
|
||||
}
|
||||
|
||||
/// Triangulates a geographic polygon into encoded triangles for block kd-tree indexing.
|
||||
/// Encodes the triangles of a Delaunay triangulation into block kd-tree triangles.
|
||||
///
|
||||
/// This function is used by applications to convert a `MultiPolygon` into triangles for indexing
|
||||
/// in the block kd-tree. Once triangulated, the encoded triangles can be inserted into the block
|
||||
/// kd-tree and queries against the block kd-tree will return the associated `doc_id`.
|
||||
/// Takes the output of a Delaunay triangulation from `i_triangle` and encodes each triangle into
|
||||
/// the normalized triangle used by the block kd-tree. Each triangle includes its bounding box,
|
||||
/// vertex coordinates, and boundary edge flags that distinguish original polygon edges from
|
||||
/// internal tessellation edges.
|
||||
///
|
||||
/// Takes a polygon with floating-point lat/lon coordinates, converts to integer coordinates with
|
||||
/// millimeter precision (using 2^32 scaling), performs constrained Delaunay triangulation, and
|
||||
/// encodes the resulting triangles with boundary edge information.
|
||||
///
|
||||
/// Handles polygons with holes correctly, preserving which triangle edges lie on the original
|
||||
/// polygon boundaries versus internal tessellation edges.
|
||||
pub fn triangulate<G>(doc_id: u32, geometry: G, triangles: &mut Vec<Triangle>)
|
||||
where G: Into<MultiPolygon<f64>> {
|
||||
let multi = geometry.into();
|
||||
for polygon in multi {
|
||||
let exterior: Vec<IntPoint> = polygon
|
||||
.exterior()
|
||||
.coords()
|
||||
.map(|coord| {
|
||||
let lat = (coord.y / (180.0 / (1i64 << 32) as f64)).floor() as i32;
|
||||
let lon = (coord.x / (360.0 / (1i64 << 32) as f64)).floor() as i32;
|
||||
IntPoint::new(lon, lat)
|
||||
})
|
||||
.collect();
|
||||
let mut i_polygon = vec![exterior];
|
||||
for interior in polygon.interiors() {
|
||||
let hole: Vec<IntPoint> = interior
|
||||
.coords()
|
||||
.map(|coord| {
|
||||
let lat = (coord.y / (180.0 / (1i64 << 32) as f64)).floor() as i32;
|
||||
let lon = (coord.x / (360.0 / (1i64 << 32) as f64)).floor() as i32;
|
||||
IntPoint::new(lon, lat)
|
||||
})
|
||||
.collect();
|
||||
i_polygon.push(hole);
|
||||
}
|
||||
let delaunay = i_polygon.triangulate().into_delaunay();
|
||||
for (_, triangle) in delaunay.triangles.iter().enumerate() {
|
||||
let bounds = [
|
||||
triangle.neighbors[0] == usize::MAX,
|
||||
triangle.neighbors[1] == usize::MAX,
|
||||
triangle.neighbors[2] == usize::MAX,
|
||||
];
|
||||
let v0 = &delaunay.points[triangle.vertices[0].index];
|
||||
let v1 = &delaunay.points[triangle.vertices[1].index];
|
||||
let v2 = &delaunay.points[triangle.vertices[2].index];
|
||||
triangles.push(Triangle::new(
|
||||
doc_id,
|
||||
[v0.y, v0.x, v1.y, v1.x, v2.y, v2.x],
|
||||
bounds,
|
||||
))
|
||||
}
|
||||
/// The boundary edge information provided by the `i_triangle` Delaunay triangulation is essential
|
||||
/// for CONTAINS and WITHIN queries to work correctly.
|
||||
pub fn delaunay_to_triangles(doc_id: u32, delaunay: &IntDelaunay, triangles: &mut Vec<Triangle>) {
|
||||
for triangle in delaunay.triangles.iter() {
|
||||
let bounds = [
|
||||
triangle.neighbors[0] == usize::MAX,
|
||||
triangle.neighbors[1] == usize::MAX,
|
||||
triangle.neighbors[2] == usize::MAX,
|
||||
];
|
||||
let v0 = &delaunay.points[triangle.vertices[0].index];
|
||||
let v1 = &delaunay.points[triangle.vertices[1].index];
|
||||
let v2 = &delaunay.points[triangle.vertices[2].index];
|
||||
triangles.push(Triangle::new(
|
||||
doc_id,
|
||||
[v0.y, v0.x, v1.y, v1.x, v2.y, v2.x],
|
||||
bounds,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use geo_types::polygon;
|
||||
use i_triangle::i_overlay::i_float::int::point::IntPoint;
|
||||
use i_triangle::int::triangulatable::IntTriangulatable;
|
||||
|
||||
use super::*;
|
||||
|
||||
@@ -437,11 +407,15 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn triangulate_box() {
|
||||
let polygon = polygon![
|
||||
(x: 0.0, y: 0.0), (x: 10.0, y: 0.0), (x: 10.0, y: 10.0), (x: 0.0, y: 10.0)
|
||||
];
|
||||
let i_polygon = vec![vec![
|
||||
IntPoint::new(0, 0),
|
||||
IntPoint::new(10, 0),
|
||||
IntPoint::new(10, 10),
|
||||
IntPoint::new(0, 10),
|
||||
]];
|
||||
let mut triangles = Vec::new();
|
||||
triangulate(1, polygon, &mut triangles);
|
||||
let delaunay = i_polygon.triangulate().into_delaunay();
|
||||
delaunay_to_triangles(1, &delaunay, &mut triangles);
|
||||
assert_eq!(triangles.len(), 2);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user