You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Rust中实现无UB的Half Edge(半边)数据结构接口?

在Rust中实现无UB的半边(Half Edge)链式接口

我已经和Rust的借用检查器、未定义行为(UB)斗争了好几天,无比沮丧。

半边(Half Edge,又称双连通边列表)是一种几何数据结构,我曾多次在C++中实现它,一直用着这样简洁的接口:

edge.next()
face.edge()
vert.edge()

这种接口允许元素直接访问关联对象,完全不需要显式引用所属的Mesh结构,可读性极强。但Rust里常见的实现方式却繁琐晦涩,我完全无法接受:

mesh.hedges[edge_id]
mesh.get_edge(edge_id)

比如链式调用edge.next().next().next(),用这种繁琐接口得写成:

mesh.get_edge(mesh.get_edge(mesh.get_edge(id).next_id).next_id)

哪怕拆分也需要多行代码,徒增心智负担。

为此我尝试用unsafe代码实现理想接口:

pub struct HEdge<'a, V, E, F>
where
    V: Clone,
    E: Clone,
    F: Clone,
{
    pub(crate) id: GeomId,

    pub(crate) next_id: GeomId,
    pub(crate) prev_id: GeomId,
    pub(crate) pair_id: GeomId,

    pub(crate) vert_id: GeomId,

    pub(crate) face_id: GeomId,

    pub data: E,

    pub(crate) mesh: *mut HalfMesh<'a, V, E, F>,
}

impl<'a, V, E, F> HEdge<'a, V, E, F>
where
    V: Clone,
    E: Clone,
    F: Clone,
{
     pub fn next_mut(&self) -> &mut HEdge<'a, V, E, F>
    {
        unsafe {
            debug_assert!(self.next_id != ABSENT);
            debug_assert!(usize::from(self.next_id) < (*self.mesh).hedges.len());

            &mut (*self.mesh).hedges[usize::from(self.next_id)]
        }
    }
}

但在示例用法的split方法中出现了段错误:

pub fn split(&mut self) -> &mut Vert<'a, V, E, F>
{
    unsafe {
        let v2_id = self.pair().prev().source().id;
        let v3_id = self.dest().id;
        let v4_id = self.prev().source().id;

        let vn_id = (*self.mesh).add_vert(self.source().data.clone());

        let e1_id = self.id;
        let e2_id = self.pair().id;
        let e3_id = self.next().id;
        let e4_id = self.prev().id;
        let e5_id = self.pair().next().id;
        let e6_id = self.pair().prev().id;

        let (e7_id, e8_id) =
            (*self.mesh).add_edge(vn_id, v2_id, self.data.clone(), self.data.clone());
        let (e9_id, e10_id) =
            (*self.mesh).add_edge(v4_id, vn_id, self.data.clone(), self.data.clone());
        println!("{}", (*self.mesh).hedges.len());
        let (e11_id, e12_id) =
            (*self.mesh).add_edge(v3_id, vn_id, self.data.clone(), self.data.clone());

        let f1_id = self.face_id;
        let f2_id = self.pair().face_id;
        let f3_id = (*self.mesh).add_face(e10_id, self.face().data.clone());
        let f4_id = (*self.mesh).add_face(e8_id, self.pair().face().data.clone());

        attach_face(
            &mut (*self.mesh).faces[f1_id.0 as usize],
            &mut (*self.mesh).hedges[e1_id.0 as usize],
            &mut (*self.mesh).hedges[e3_id.0 as usize],
            &mut (*self.mesh).hedges[e9_id.0 as usize],
        );

        attach_face(
            &mut (*self.mesh).faces[f2_id.0 as usize],
            &mut (*self.mesh).hedges[e2_id.0 as usize],
            &mut (*self.mesh).hedges[e7_id.0 as usize],
            &mut (*self.mesh).hedges[e6_id.0 as usize],
        );

        attach_face(
            &mut (*self.mesh).faces[f3_id.0 as usize],
            &mut (*self.mesh).hedges[e10_id.0 as usize],
            &mut (*self.mesh).hedges[e4_id.0 as usize],
            &mut (*self.mesh).hedges[e11_id.0 as usize],
        );

        attach_face(
            &mut (*self.mesh).faces[f4_id.0 as usize],
            &mut (*self.mesh).hedges[e8_id.0 as usize],
            &mut (*self.mesh).hedges[e12_id.0 as usize],
            &mut (*self.mesh).hedges[e5_id.0 as usize],
        );

        return &mut (*self.mesh).verts[vn_id.0 as usize];
    }
}

这个设计存在大量UB,完全无法正常工作。我查了各种资料、尝试了多种方案,始终没法在Rust中实现类似C++的edge.next()接口,所有建议最终都退化成mesh.get_edge(id)这类繁琐形式。

我的核心诉求是:把一套经过3年实战检验的C++接口适配到Rust中——实现struct Mesh与struct Edge,让Edge内部引用Mesh,支持edge.next()链式调用且无UB或运行错误。当前的实现已经崩溃。

内容的提问来源于stack exchange,提问作者Makogan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 16:05:15