gpt4 book ai didi

c# - 基本双重轮廓理论

转载 作者:可可西里 更新时间:2023-11-01 01:20:43 25 4
gpt4 key购买 nike

我一直在谷歌上搜索,但找不到任何基本的东西。在最基本的形式中,双轮廓(对于体素地形)是如何实现的?我知道它的作用和原因,但不明白如何去做。 JS或C#(最好)都好。有没有人用过Dual contouring,能简单介绍一下吗?

最佳答案

好的。所以今晚我很无聊,决定尝试一下自己实现双重轮廓。正如我在评论中所说,所有相关 Material 都在以下论文的第 2 节中:

特别是,网格的拓扑在以下部分的 2.2 部分中进行了描述,引用:

  1. For each cube that exhibits a sign change, generate a vertex positioned at the minimizer of the quadratic function of equation 1.

  2. For each edge that exhibits a sign change, generate a quad connecting the minimizing vertices of the four cubes containing the edge.

这就是它的全部!您解决线性最小二乘问题以获得每个立方体的顶点,然后将相邻顶点与四边形连接。因此,使用这个基本思想,我使用 numpy 在 python 中编写了一个双等高线等值面提取器(部分原因是为了满足我自己对它如何工作的病态好奇心)。这是代码:

import numpy as np
import numpy.linalg as la
import scipy.optimize as opt
import itertools as it

#Cardinal directions
dirs = [ [1,0,0], [0,1,0], [0,0,1] ]

#Vertices of cube
cube_verts = [ np.array([x, y, z])
for x in range(2)
for y in range(2)
for z in range(2) ]

#Edges of cube
cube_edges = [
[ k for (k,v) in enumerate(cube_verts) if v[i] == a and v[j] == b ]
for a in range(2)
for b in range(2)
for i in range(3)
for j in range(3) if i != j ]

#Use non-linear root finding to compute intersection point
def estimate_hermite(f, df, v0, v1):
t0 = opt.brentq(lambda t : f((1.-t)*v0 + t*v1), 0, 1)
x0 = (1.-t0)*v0 + t0*v1
return (x0, df(x0))

#Input:
# f = implicit function
# df = gradient of f
# nc = resolution
def dual_contour(f, df, nc):

#Compute vertices
dc_verts = []
vindex = {}
for x,y,z in it.product(range(nc), range(nc), range(nc)):
o = np.array([x,y,z])

#Get signs for cube
cube_signs = [ f(o+v)>0 for v in cube_verts ]

if all(cube_signs) or not any(cube_signs):
continue

#Estimate hermite data
h_data = [ estimate_hermite(f, df, o+cube_verts[e[0]], o+cube_verts[e[1]])
for e in cube_edges if cube_signs[e[0]] != cube_signs[e[1]] ]

#Solve qef to get vertex
A = [ n for p,n in h_data ]
b = [ np.dot(p,n) for p,n in h_data ]
v, residue, rank, s = la.lstsq(A, b)

#Throw out failed solutions
if la.norm(v-o) > 2:
continue

#Emit one vertex per every cube that crosses
vindex[ tuple(o) ] = len(dc_verts)
dc_verts.append(v)

#Construct faces
dc_faces = []
for x,y,z in it.product(range(nc), range(nc), range(nc)):
if not (x,y,z) in vindex:
continue

#Emit one face per each edge that crosses
o = np.array([x,y,z])
for i in range(3):
for j in range(i):
if tuple(o + dirs[i]) in vindex and tuple(o + dirs[j]) in vindex and tuple(o + dirs[i] + dirs[j]) in vindex:
dc_faces.append( [vindex[tuple(o)], vindex[tuple(o+dirs[i])], vindex[tuple(o+dirs[j])]] )
dc_faces.append( [vindex[tuple(o+dirs[i]+dirs[j])], vindex[tuple(o+dirs[j])], vindex[tuple(o+dirs[i])]] )

return dc_verts, dc_faces

它不是很快,因为它使用 SciPy 的通用非线性求根方法来查找等值面上的边缘点。但是,它似乎确实以相当通用的方式工作得相当好。为了测试它,我使用以下测试用例(在 Mayavi2 可视化工具包中)运行它:

import enthought.mayavi.mlab as mlab

center = np.array([16,16,16])
radius = 10

def test_f(x):
d = x-center
return np.dot(d,d) - radius**2

def test_df(x):
d = x-center
return d / sqrt(np.dot(d,d))

verts, tris = dual_contour(f, df, n)

mlab.triangular_mesh(
[ v[0] for v in verts ],
[ v[1] for v in verts ],
[ v[2] for v in verts ],
tris)

这将球体定义为隐式方程,并通过双等高线求解 0 等值面。当我在工具包中运行它时,结果是这样的:

enter image description here

总之,它似乎有效。

关于c# - 基本双重轮廓理论,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6485908/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com