将三维多边形转换为二维,执行剪切,然后转换回三维

2024-05-16 08:52:30 发布

您现在位置:Python中文网/ 问答频道 /正文

我的问题是我有两个墙,在三维空间中用二维平面表示,(wallA和{})。这些墙是重叠的。我需要把它转换成三个墙段,一个用于wallA.intersect(wallB),一个用于wallA.diff(wallB),一个用于wallB.diff(wallA)。在

我想我需要做的是将它们都旋转到二维空间中,而不改变它们的重叠,执行剪切以确定差异和相交,然后将新墙旋转回原始平面。在

墙不一定是垂直的,否则问题可能更简单。在

使用pyclipper在2D中很容易解决问题的裁剪部分。我遇到的问题是如何将墙恢复到二维

据我所知,与this question中的步骤类似但不完全相同的东西。我已经看了^{},它看起来很有用,但是我不太明白我需要使用哪个函数,或者什么函数的组合来重现这个算法。在

这里有一个我想要实现的例子,用一个非常简单的例子,一对2x2的垂直曲面在一个角上有一个重叠的1x1正方形。在

import pyclipper as pc

wallA= [(0,0,2), (2,0,2), (2,0,0), (0,0,0)]
wallB = [(1,0,3), (3,0,3), (3,0,1), (1,0,1)]
expected_overlaps = [[(1,0,2), (2,0,2), (2,0,1), (1,0,1)]]

wallA_2d = transform_to_2D(wallA, <whatever else is needed>)
wallB_2d = transform_to_2D(wallB, <whatever else is needed>)

scaledA = pc.scale_to_clipper(wallA_2d)
scaledB = pc.scale_to_clipper(wallB_2d)
clipper = pc.Pyclipper()
clipper.AddPath(scaledA, poly_type=pc.PT_SUBJECT, closed=True)
clipper.AddPath(scaledB, poly_type=pc.PT_CLIP, closed=True)

# just showing the intersection - differences are handled similarly
intersections = clipper.Execute(
    pc.CT_INTERSECTION, pc.PFT_NONZERO, pc.PFT_NONZERO)

intersections = [pc.scale_from_clipper(i) for i in intersections]
overlaps = [transform_to_3D(i, <whatever else is needed>) for i in intersections]

assert overlaps  == expected_overlaps

我想要的是对编写transform_to_2dtransform_to_3d所需步骤的说明。在


Tags: toistransformdiffelse平面scalepc
1条回答
网友
1楼 · 发布于 2024-05-16 08:52:30

而不是旋转,你可以简单地投射。关键是将三维空间映射到二维平面上,然后可以反转。(当您向后映射时,由投影产生的任何扭曲都将撤消。)为此,您应该首先找到包含两个墙的平面。下面是一些示例代码:

wallA = [(0,0,2), (2,0,2), (2,0,0), (0,0,0)]
wallB = [(1,0,3), (3,0,3), (3,0,1), (1,0,1)]
v = (0, 1, 0) # the normal vector
a = 0 # a number so that v[0] * x + v[1] * y + v[2] * z = a is the equation of the plane containing your walls

# To calculate the normal vector in general, 
# you would take the cross product of any two 
# vectors in the plane of your walls, e.g.
# (wallA[1] - wallA[0]) X (wallA[2] - wallA[0]).
# You can then solve for a.

proj_axis = max(range(3), key=lambda i: abs(v[i])) 
# this just needs to be any number such that v[proj_axis] != 0

def project(x):
    # Project onto either the xy, yz, or xz plane. (We choose the one that avoids degenerate configurations, which is the purpose of proj_axis.)
    # In this example, we would be projecting onto the xz plane.
    return tuple(c for i, c in enumerate(x) if i != proj_axis)

def project_inv(x):
    # Returns the vector w in the walls' plane such that project(w) equals x.
    w = list(x)
    w[proj_axis:proj_axis] = [0.0]
    c = a
    for i in range(3):
        c -= w[i] * v[i]
    c /= v[proj_axis]
    w[proj_axis] = c
    return tuple(w)

projA = [project(x) for x in wallA]
projB = [project(x) for x in wallB]
proj_intersection = intersection(projA, projB) # use your 2d algorithm here
intersection = [project_inv(x) for x in proj_intersection] # this is your intersection in 3d; you can do similar things for the other pieces

相关问题 更多 >