boolmesh 0.1.8

Robust 3D mesh boolean library
Documentation
//--- Copyright (C) 2025 Saki Komikado <komietty@gmail.com>,
//--- This Source Code Form is subject to the terms of the Mozilla Public License v.2.0.
#![allow(clippy::needless_range_loop)]

use crate::{Half, Real, Vec3, Vec4};
use super::kernel01::{intersect, shadows, shadows01};

pub struct Kernel11<'a> {
    pub ps_p: &'a [Vec3],
    pub ps_q: &'a [Vec3],
    pub hs_p: &'a [Half],
    pub hs_q: &'a [Half],
    pub ns: &'a [Vec3],
    pub expand: Real,
}

impl<'a> Kernel11<'a> {
    pub fn op (&self, p1: usize, q1: usize) -> Option<(i32, Vec4)> {
        let mut k = 0;
        let mut p_rl = [Vec3::ZERO; 2];
        let mut q_rl = [Vec3::ZERO; 2];
        let mut shadow_ = false;
        let mut s11 = 0;

        let p0 = [self.hs_p[p1].tail, self.hs_p[p1].head];
        let q0 = [self.hs_q[q1].tail, self.hs_q[q1].head];

        for i in 0..2 {
            if let Some((s, yz)) = shadows01(
                p0[i], q1,
                self.ps_p,
                self.ps_q,
                self.hs_q,
                self.ns,
                self.expand,
                false
            ) {
                s11 += s * if i == 0 { -1 } else { 1 };
                if k < 2 && (k == 0 || (s != 0) != shadow_) {
                    shadow_ = s != 0;
                    p_rl[k] = self.ps_p[p0[i]];
                    q_rl[k] = Vec3::new(p_rl[k].x, yz.x, yz.y);
                    k += 1;
                }
            }
        }

        for i in 0..2 {
            if let Some((s, yz)) = shadows01(
                q0[i], p1,
                self.ps_q,
                self.ps_p,
                self.hs_p,
                self.ns,
                self.expand,
                true
            ) {
                s11 += s * if i == 0 { -1 } else { 1 };
                if k < 2 && (k == 0 || (s != 0) != shadow_) {
                    shadow_ = s != 0;
                    q_rl[k] = self.ps_q[q0[i]];
                    p_rl[k] = Vec3::new(q_rl[k].x, yz.x, yz.y);
                    k += 1;
                }
            }
        }

        if s11 == 0 { return None; }

        assert_eq!(k, 2, "Boolean manifold error: s11");
        let xyzz11 = intersect(p_rl[0], p_rl[1], q_rl[0], q_rl[1]);
        let p1s = self.hs_p[p1].tail;
        let p1e = self.hs_p[p1].head;
        let d1  = self.ps_p[p1s] - Vec3::new(xyzz11.x, xyzz11.y, xyzz11.z);
        let d2  = self.ps_p[p1e] - Vec3::new(xyzz11.x, xyzz11.y, xyzz11.z);
        let b2  = d1.length_squared();
        let e2  = d2.length_squared();
        let dir = if b2 < e2 {self.ns[p1s].z} else {self.ns[p1e].z};

        if !shadows(xyzz11.z, xyzz11.w, self.expand * dir) { s11 = 0; }
        Some((s11, xyzz11))
    }
}