geo-buffer 0.2.0

This crate provides methods to buffer (to inflate or deflate) certain primitive geometric types in the GeoRust ecosystem via a straight skeleton.
Documentation
use core::fmt;

use geo_types::Polygon;

#[derive(Clone, Debug, Copy, PartialEq, PartialOrd)]
pub(crate) enum IndexType{
    PointerIndex(usize),
    RealIndex(usize),
}

impl fmt::Display for IndexType{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self{
            IndexType::PointerIndex(x) => write!(f, "Pointer index: {x}"),
            IndexType::RealIndex(x) => write!(f, "Real index: {x}"),
        }
    }
}

impl IndexType{
    pub(crate) fn get_index(&self) -> usize{
        if let IndexType::PointerIndex(res) = self{
            return *res;
        }
        panic!("Expected IndexType::PointerIndex");
    }

    pub(crate) fn get_real_index(&self) -> usize{
        if let IndexType::RealIndex(res) = self{
            return *res;
        }
        panic!("Expected IndexType::RealIndex");
    }
}

#[derive(Clone, Copy, Debug)]
pub(crate) struct Node{
    pub(crate) index: IndexType,
    pub(crate) left: IndexType,
    pub(crate) right: IndexType,
    pub(crate) done: bool,
}

#[allow(dead_code)]
impl Node{
    fn new(index: usize, left: usize, right: usize) -> Self{
        Self{index: IndexType::RealIndex(index), left: IndexType::PointerIndex(left), right: IndexType::PointerIndex(right), done: false,}
    }

    pub(crate) fn lv(&self) -> IndexType{
        self.left
    }

    pub(crate) fn rv(&self) -> IndexType{
        self.right
    }
}

#[derive(Clone, Debug)]
pub(crate) struct VertexQueue{
    pub(crate) content: Vec<Node>,
    pub(crate) start_vertex: Vec<usize>,
}

#[allow(dead_code)]
impl VertexQueue{
    pub(crate) fn new() -> Self{
        Self { content: Vec::new(), start_vertex: Vec::new(), }
    }

    pub(crate) fn initialize_from_polygon(&mut self, p: &Polygon){
        self.initialize_from_polygon_vector(&vec![p.clone()])
    }

    pub(crate) fn initialize_from_polygon_vector(&mut self, pv: &Vec<Polygon>){
        for p in pv{
            let offset = self.content.len();
            let len = p.exterior().0.len() - 1;
            self.start_vertex.push(offset);
            for i in 0..len{
                let new_node = Node::new(i+offset, (i+len-1)%len+offset, (i+1)%len+offset);
                self.content.push(new_node);
            }
            for i in 0..p.interiors().len(){
                let offset = self.content.len();
                let len = p.interiors()[i].0.len()-1;
                self.start_vertex.push(offset);
                for j in 0..len{
                    let new_node = Node::new(j+offset, (j+len-1)%len+offset, (j+1)%len+offset);
                    self.content.push(new_node);
                }
            }
        }
    }

    pub(crate) fn get_real_index(&self, cv: IndexType) -> usize{
        if let IndexType::PointerIndex(cv) = cv{
            return self.content[cv].index.get_real_index();
        }
        panic!("Expected parameter \"cv\" as IndexType::RealIndex")
    }

    pub(crate) fn lv(&self, cv: IndexType) -> IndexType{
        if let IndexType::PointerIndex(cv) = cv{
            return self.content[cv].left;
        }
        panic!("Expected parameter \"cv\" as IndexType::PointerIndex");
    }

    pub(crate) fn rv(&self, cv: IndexType) -> IndexType{
        if let IndexType::PointerIndex(cv) = cv{
            return self.content[cv].right;
        }
        panic!("Expected parameter \"cv\" as IndexType::PointerIndex");
    }

    pub(crate) fn llv(&self, cv: IndexType) -> IndexType{
        let cv = self.lv(cv);
        self.lv(cv)
    }

    pub(crate) fn rrv(&self, cv: IndexType) -> IndexType{
        let cv = self.rv(cv);
        self.rv(cv)
    }

    pub(crate) fn remove(&mut self, cv: IndexType) -> IndexType{
        let tl = self.lv(cv);
        let tr = self.rv(cv);
        self.content[tl.get_index()].right = tr;
        self.content[tr.get_index()].left = tl;
        self.content[cv.get_index()].done = true;
        tr
    }

    pub(crate) fn remove_and_set(&mut self, cv: IndexType, nv: IndexType) -> IndexType{
        let cv = self.remove(cv);
        if let IndexType::RealIndex(_) = nv{
            self.content[cv.get_index()].index = nv;
        }
        else {panic!("Expected parameter \"nv\" as IndexType::RealIndex");}
        cv
    }

    pub(crate) fn split_and_set(&mut self, cv: IndexType, sv: IndexType, nv1: IndexType, nv2: IndexType) -> (IndexType, IndexType){
        let new_node = Node::new(0, sv.get_index(), self.rv(cv).get_index());
        let new_index = IndexType::PointerIndex(self.content.len());
        self.content.push(new_node);
        if let IndexType::RealIndex(_) = nv1{
            self.content[cv.get_index()].index = nv1;
        }
        else {panic!("Expected parameter \"nv1\" as IndexType::RealIndex");}
        if let IndexType::RealIndex(_) = nv2{
            self.content[new_index.get_index()].index = nv2;
        }
        else {panic!("Expected parameter \"nv2\" as IndexType::RealIndex");}
        let svx = self.rv(sv); // right of sv (split vertex)
        let cvx = self.rv(cv); // right of cv (current (anchor) vertex)
        self.content[cvx.get_index()].left = new_index;
        self.content[sv.get_index()].right = new_index;
        self.content[cv.get_index()].right = svx;
        self.content[svx.get_index()].left = cv;
        self.start_vertex.push(cv.get_index());
        self.start_vertex.push(new_index.get_index());
        (cv, new_index)
    }

    pub(crate) fn cleanup(&mut self){
        let mut sv_idx = 0;
        let mut visit = vec![false; self.content.len()];
        while sv_idx < self.start_vertex.len(){
            let mut cur = self.start_vertex[sv_idx];
            while self.content[cur].done == true && visit[cur] == false{
                visit[cur] = true;
                cur = self.content[cur].right.get_index();
            }
            if visit[cur] == true || self.content[cur].left.get_index() == self.content[cur].right.get_index(){
                self.start_vertex.swap_remove(sv_idx);
                continue;
            }
            self.start_vertex[sv_idx] = cur;
            visit[cur] = true;
            cur = self.content[cur].right.get_index();
            while cur != self.start_vertex[sv_idx] {
                if visit[cur] {
                    panic!("Something Worng in cleanup phase: cur {} from {}, sv {:?}", cur, sv_idx, self.start_vertex);
                }
                visit[cur] = true;
                cur = self.content[cur].right.get_index();
            }
            sv_idx += 1;
        }
    }

    pub(crate) fn iter<'a>(&'a self) -> Iter<'a> {
        Iter { item: self, sv_idx: 0, idx: usize::MAX, }
    }
}

impl fmt::Display for VertexQueue{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "[").unwrap();
        for (e, ee, eee) in self.iter(){
            let ee = ee.get_index();
            write!(f, "({}, {}, {}), ", e, ee, eee).unwrap();
        }
        write!(f, "]")
    }
}

pub(crate) struct Iter<'a> {
    item: &'a VertexQueue,
    sv_idx: usize,
    idx: usize,
}

impl<'a> Iterator for Iter<'a>{
    type Item = (usize, IndexType, usize);

    fn next(&mut self) -> Option<Self::Item>{
        if self.idx == usize::MAX{
            if self.sv_idx >= self.item.start_vertex.len() {return None;}
            self.idx = self.item.start_vertex[self.sv_idx];
        }
        let ret = match self.item.content[self.idx].index{
            IndexType::RealIndex(rv) => rv,
            _ => panic!("Expected IndexType::RealIndex"),
        };
        let ret = (self.sv_idx, IndexType::PointerIndex(self.idx), ret);
        self.idx = self.item.content[self.idx].right.get_index();
        if self.item.start_vertex[self.sv_idx] == self.idx{
            self.sv_idx += 1;
            self.idx = usize::MAX;
        }
        Some(ret)
    }
}