diff --git a/rust/src/annotation.rs b/rust/src/annotation.rs new file mode 100644 index 0000000000..08775761a3 --- /dev/null +++ b/rust/src/annotation.rs @@ -0,0 +1,18 @@ +// Copyright (C) 2024 Intel Corporation +// +// SPDX-License-Identifier: MIT + +fn get_shoelace_area(points: Vec<(f64, f64)>) -> f64 { + let n = points.len(); + // Not a polygon + if n < 3 { + return 0.0; + } + let mut area = 0.0; + for i in 0..n { + let (x1, y1) = points[i]; + let (x2, y2) = points[(i + 1) % n]; // Next vertex, wrapping around using modulo + area += x1 * y2 - y1 * x2; + } + area.abs() / 2.0 +} diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 7863bcf287..dc804874e2 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -13,6 +13,7 @@ use pyo3::prelude::*; use crate::coco_page_mapper::CocoPageMapper; use crate::datum_page_mapper::DatumPageMapper; use crate::json_section_page_mapper::JsonSectionPageMapper; +use crate::annotations:: /// Datumaro Rust API #[pymodule] @@ -21,6 +22,7 @@ fn rust_api(_py: Python<'_>, m: &PyModule) -> PyResult<()> { m.add_class::()?; m.add_class::()?; m.add_class::()?; + m.add_function(wrap_pyfunction!(get_shoelace_area, m)?)?; Ok(()) } diff --git a/rust/tests/annotations.rs b/rust/tests/annotations.rs new file mode 100644 index 0000000000..49ee2941ed --- /dev/null +++ b/rust/tests/annotations.rs @@ -0,0 +1,17 @@ +// Copyright (C) 2024 Intel Corporation +// +// SPDX-License-Identifier: MIT + +use datumaro_rust_api::annotations::get_shoelace_area; + +#[test] +fn test_get_shoelace_area() { + // Define a polygon example + let points = vec![(0.0, 0.0), (4.0, 0.0), (4.0, 3.0), (0.0, 3.0)]; + + // Calculate the shoelace area + let area = get_shoelace_area(&points); + + // Assert that the calculated area matches the expected area (12.0 in this case) + assert_eq!(area, 12.0); +} diff --git a/src/datumaro/components/annotation.py b/src/datumaro/components/annotation.py index 2dfa6bff41..0dafb6422e 100644 --- a/src/datumaro/components/annotation.py +++ b/src/datumaro/components/annotation.py @@ -31,7 +31,7 @@ from datumaro.components.media import Image from datumaro.util.attrs_util import default_if_none, not_empty - +from datumaro.rust_api import get_shoelace_area class AnnotationType(IntEnum): unknown = 0 @@ -840,21 +840,23 @@ def __eq__(self, other): inter_area = self_polygon.intersection(other_polygon).area return abs(self_polygon.area - inter_area) < CHECK_POLYGON_EQ_EPSILONE - def _get_shoelace_area(self): - points = self.get_points() - n = len(points) - # Not a polygon - if n < 3: - return 0 - - area = 0.0 - for i in range(n): - x1, y1 = points[i] - x2, y2 = points[(i + 1) % n] # Next vertex, wrapping around using modulo - area += x1 * y2 - y1 * x2 + # def _get_shoelace_area(self): + # points = self.get_points() + # n = len(points) + # # Not a polygon + # if n < 3: + # return 0 - return abs(area) / 2.0 + # area = 0.0 + # for i in range(n): + # x1, y1 = points[i] + # x2, y2 = points[(i + 1) % n] # Next vertex, wrapping around using modulo + # area += x1 * y2 - y1 * x2 + # return abs(area) / 2.0 + def _get_shoelace_area(self): + points = self.get_points() + return get_shoelace_area(points) @attrs(slots=True, init=False, order=False) class Bbox(_Shape):