Skip to content

二元线性分段函数 ​

BivariateLinearPiecewiseFunction 表示定义在三角剖分上的分片平面。每个单元包含三个顶点 (xtk,ytk,ztk)。

求解器数学模型 ​

令 st∈{0,1} 选择三角形,λtk∈[0,1] 为该三角形的重心权重。两种实现都强制恰好一个三角形激活且其权重之和为一,并把坐标表示为所有顶点的加权和:

∑tst=1,x=∑t,kxtkλtk,y=∑t,kytkλtk,z=∑t,kztkλtk.

Rust 用每个三角形的等式 ∑k=02λtk=st 把权重组绑定到选择变量,并把 z 关系注册为显式等式行。Kotlin 则组合全局行 ∑t,kλtk=1 与每个三角形的 SOS2 风格行 ∑k=02λtk≤3st,并把 z=∑t,kztkλtk 直接作为 resultPolynomial 暴露;在 st 为二值变量时两种编码描述同一可行域。

只有一个三角形可以具有非零权重。该模型不是所有顶点的无约束凸包,因此能够保留非共面单元之间的分段曲面。

直接求值 ​

求值器对每个三角形计算重心坐标 (λ0,λ1,λ2)。两种实现使用相同的几何容差 1e-12,允许权重低至 -1e-12。第一个满足所有权重在该容差内的三角形包含输入点,此时

z=λ0z0+λ1z1+λ2z2.

输入不属于任何三角形时返回 null/None。两种实现都会在构造时拒绝坐标非有限或二维行列式绝对值不大于 1e-12 的三角形,因此退化三角形无法进入求值。

Kotlin/Rust 示例 ​

kotlin
val surface = BivariateLinearPiecewiseFunction(
    x = xPolynomial,
    y = yPolynomial,
    triangles = triangles,
    converter = IntoValue.Identity,
    name = "surface"
)
rust
let surface = BivariateLinearPiecewiseFunction::new(
    1,
    "surface",
    x_input,
    y_input,
    vec![Triangle3::new(
        Point3::new(0.0, 0.0, 0.0),
        Point3::new(1.0, 0.0, 10.0),
        Point3::new(0.0, 1.0, 20.0),
    )],
);
assert_eq!(surface.selector_variables().len(), 1);

测试与参考 ​