bigdatacloud 1.0.0

Official Rust SDK for BigDataCloud APIs — IP Geolocation, Reverse Geocoding, Phone & Email Verification, Network Engineering
Documentation
use crate::models::GeoPoint;

/// Splits a flat confidence area point list into individual closed polygon rings.
///
/// The `confidence_area` field from the API may encode multiple polygons in a flat Vec.
/// Do NOT treat the entire Vec as a single polygon ring.
///
/// # Example
/// ```no_run
/// # use bigdatacloud::confidence_area::split_into_polygons;
/// let polygons = split_into_polygons(&confidence_area);
/// for (i, ring) in polygons.iter().enumerate() {
///     println!("Ring {}: {} points", i + 1, ring.len());
/// }
/// ```
pub fn split_into_polygons(points: &[GeoPoint]) -> Vec<Vec<GeoPoint>> {
    if points.is_empty() {
        return vec![];
    }

    let mut polygons: Vec<Vec<GeoPoint>> = Vec::new();
    let mut current: Vec<GeoPoint> = Vec::new();

    for point in points {
        if let Some(first) = current.first() {
            if approx_equal(first.latitude, point.latitude)
                && approx_equal(first.longitude, point.longitude)
            {
                current.push(point.clone());
                if current.len() >= 4 {
                    polygons.push(current.clone());
                }
                current.clear();
                continue;
            }
        }
        current.push(point.clone());
    }

    // Handle unclosed trailing polygon
    if current.len() >= 3 {
        current.push(current[0].clone());
        polygons.push(current);
    }

    polygons
}

/// Returns `true` when the confidence area encodes more than one polygon.
pub fn is_multi_polygon(points: &[GeoPoint]) -> bool {
    split_into_polygons(points).len() > 1
}

fn approx_equal(a: f64, b: f64) -> bool {
    (a - b).abs() < 1e-5
}