循环依赖(Voronoi Halfedge)

Circular Dependency (Voronoi Halfedge)

我知道,"circular dependency is a bad design",但我认为在这种情况下是有必要的。

构建 voronoi 图时,单元格被划分为所谓的 "half edges",这使您可以方便地遍历图。

无论如何,为了实例化 halfedge,我必须指定 halfedge 的镜像或双胞胎。

这在任何语言中都很时髦,但在 Kotlin 中它更令人讨厌,因为我必须使用可为 null 的 var 而不是 val,就像我更喜欢的那样。

现在我正在做这种我不喜欢的时髦;

val mirrorEdge: HalfEdge
    get() = halfEdge!!

private var halfEdge: HalfEdge? = null

fun setMirror(halfEdge: HalfEdge) {
    this.halfEdge = halfEdge
}

//别处

newEdge.setMirror(newEdge2)
newEdge2.setMirror(newEdge)

半边镜像永远不能为空,应该是不可变的,但我看不出如何在我的代码中传达这种意图。

如果没有看到 HalfEdge 的完整定义,这可能行不通,但请考虑以下几点:

interface HalfEdge {
    val mirrorHalf: HalfEdge
}

class HalfEdges {
    private inner class First : HalfEdge {
        override val mirrorHalf: HalfEdge
            get() = second
    }

    private inner class Second : HalfEdge {
        override val mirrorHalf: HalfEdge
            get() = first
    }

    val first: HalfEdge = First()
    val second: HalfEdge = Second()

    operator fun component1() = first
    operator fun component2() = second
}

用法:

val (newEdge, newEdge2) = HalfEdges()
check(newEdge == newEdge2.mirrorHalf)
check(newEdge.mirrorHalf == newEdge2)

您必须同时创建两半,尽管您可能永远不会直接保留对它的引用,但两半边缘都保持对其整个边缘容器的引用,以便它们可以相互访问。上面的实现可以很容易地适应将数据传递到两个半边 and/or 将数据与整个边相关联。

同样的原则也可以通过父 "Graph" 或 "Network" class 实现,具有内部双向映射,其边缘相互镜像。