如何围绕3D坐标绘制多边形,同时围绕框包裹?

问题描述 投票:0回答:1

我在3D空间中绘制了点,其中四个多边形以y轴和x轴的角度切入数据立方体。

我想,对于框中的每个黑色数据点,计算出以数据点为中心的正方形顶点的坐标。使用这些坐标,我可以像现在一样绘制一个polgyon。此正方形的尺寸需要与第7行定义的宽度值相同。绘制的正方形必须倾斜,以使其恰好位于现有的绘制平面上。

有人知道接近这个的最佳方法吗?另一件困难的事情是,如果广场离开盒子,它应该绕着盒子的另一侧缠绕。盒子可以水平和垂直堆叠,使用相同的盒子,无限平铺。

我的代码可以找到(抱歉它很乱):

import matplotlib.pyplot as pyplot
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.mplot3d.art3d import Poly3DCollection

angle = np.arctan2(1,4)
xangle = np.arctan2(1,4)
width = 100/np.cos(angle)
print 'angle:', angle*(180/np.pi)
print 'xangle:', xangle*(180/np.pi)
print 'width:', width

x1       = [0, 0, 0, 0, 50, 50, 50, 50]
y1       = [50,50,50,50,50,50,50,50]
z1       = [12.5,37.5,62.5,87.5,25,50,75,0]

x2   = [0,0,0,0,0,0,0,0,50,50,50,50,50,50,50,50]
y2   = [0,50,0,50,0,50,0,50,0,50,0,50,0,50,0,50]
z2  = [0,12.5,25,37.5,50,62.5,75,87.5,12.5,25,37.5,50,62.5,75,87.5,0]

fig = pyplot.figure()
ax  = fig.add_subplot(111, projection = '3d')

ax.set_xlim(0,100)
ax.set_ylim(0,100)
ax.set_zlim(0,100)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
#ax.view_init(elev=90, azim=90)
#ax.scatter(x1, y1, z1, zdir='z', s=20, c='g') 
ax.scatter(x2, y2, z2, zdir='z', s=20, c='r') #THESE ARE RICHARD'S COORDINATES notice how they do not lie on the plane

xa = [0,100,100,0]
ya = [0,0,100,100]
za = [0,-6.25,18.75,25]
verts = [zip(xa,ya,za)]
ax.add_collection3d(Poly3DCollection(verts))

xb = [0,100,100,0]
yb = [0,0,100,100]
zb = [25,-6.25+25,18.75+25,50]
verts = [zip(xb,yb,zb)]
ax.add_collection3d(Poly3DCollection(verts))

xc = [0,100,100,0]
yc = [0,0,100,100]
zc = [50,-6.25+25*2,18.75+25*2,75]
verts = [zip(xc,yc,zc)]
ax.add_collection3d(Poly3DCollection(verts))

xd = [0,100,100,0]
yd = [0,0,100,100]
zd = [75,-6.25+25*3,18.75+25*3,100]
verts = [zip(xd,yd,zd)]
ax.add_collection3d(Poly3DCollection(verts))

#pyplot.show()     

x = [0]
y = [0]
z = [0]
for i in range(1,100):
    new_x = x[(len(x)-1)] + 50
    new_y = y[(len(y)-1)] + 12.5
    new_z = z[(len(z)-1)] 



    if new_x >= 100:
        new_x = new_x - 100
        new_z = new_z + 6.25
    if new_y >= 100:
        new_y = new_y - 100
    if new_z >= 100:
        new_z = new_z - 100

    if new_x == 0 and new_y == 0 and new_z == 0:
        print 'done!', i

    x.append(new_x)
    y.append(new_y)
    z.append(new_z)


ax.scatter(x, y, z, zdir='z', s=20, c='k', zorder=1)
pyplot.show()
matplotlib 3d point box
1个回答
0
投票

完成! (虽然没有环绕盒子..)

import matplotlib.pyplot as pyplot
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
import random

angle = np.arctan2(1,4)
xangle = np.arctan2(1,4)
width = 100/np.cos(angle)
print 'angle:', angle*(180/np.pi)
print 'xangle:', xangle*(180/np.pi)
print 'width:', width

def totuple(a):
    try:
        return tuple(totuple(i) for i in a)
    except TypeError:
        return a

def plotSquare(ax,cx,cy,cz, yaw, pitch, diameter):

    colour1 = random.randint(0,255)/256.0
    colour2 = random.randint(0,255)/256.0
    colour3 = random.randint(0,255)/256.0

    centre = np.array([cx,cy,cz])
    radius = diameter/2
    #0,0,0 to 100,25,125 diff
    #100,25,125 /2
    #50,12.5,62.5 /50
    #1.0,0.25,1.25
    d1offset = np.array([np.cos(pitch)*radius,(np.cos(yaw)*radius)+(np.sin(pitch)*radius),np.sin(yaw)*radius])

    c1 = centre - d1offset
    c2 = centre + d1offset

    #100,0,25 to 0,25,100 diff
    #-100,25,75 /2
    #-50,12.5,37.5 /50
    #-1.0,0.25,0.75
    d2offset = np.array([-np.cos(yaw)*radius,(np.cos(pitch)*radius)-(np.sin(yaw)*radius),np.sin(pitch)*radius])

    c3 = centre - d2offset
    c4 = centre + d2offset

    verts = [[totuple(c1),totuple(c3),totuple(c2),totuple(c4)]]
    ax.add_collection3d(Poly3DCollection(verts, facecolors=[colour1,colour2,colour3])) 

x1       = [0, 0, 0, 0, 50, 50, 50, 50]
y1       = [50,50,50,50,50,50,50,50]
z1       = [12.5,37.5,62.5,87.5,25,50,75,0]

x2   = [0,0,0,0,0,0,0,0,50,50,50,50,50,50,50,50]
y2   = [0,50,0,50,0,50,0,50,0,50,0,50,0,50,0,50]
z2  = [0,12.5,25,37.5,50,62.5,75,87.5,12.5,25,37.5,50,62.5,75,87.5,0]

fig = pyplot.figure()
ax  = fig.add_subplot(111, projection = '3d')

ax.set_xlim(0,100)
ax.set_ylim(0,100)
ax.set_zlim(0,100)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
#ax.view_init(elev=90, azim=90)
#ax.scatter(x1, y1, z1, zdir='z', s=20, c='g') 
ax.scatter(x2, y2, z2, zdir='z', s=20, c='r') #EXISTING COORDINATES notice how they do not lie on the plane

xa = [0,100,100,0]
ya = [0,0,100,100]
za = [0,-6.25,18.75,25]
verts = [zip(xa,ya,za)]
ax.add_collection3d(Poly3DCollection(verts))

xb = [0,100,100,0]
yb = [0,0,100,100]
zb = [25,-6.25+25,18.75+25,50]
verts = [zip(xb,yb,zb)]
ax.add_collection3d(Poly3DCollection(verts))

xc = [0,100,100,0]
yc = [0,0,100,100]
zc = [50,-6.25+25*2,18.75+25*2,75]
verts = [zip(xc,yc,zc)]
ax.add_collection3d(Poly3DCollection(verts))

xd = [0,100,100,0]
yd = [0,0,100,100]
zd = [75,-6.25+25*3,18.75+25*3,100]
verts = [zip(xd,yd,zd)]
ax.add_collection3d(Poly3DCollection(verts))

x = [0]
y = [0]
z = [0]
for i in range(1,100):
    new_x = x[(len(x)-1)] + 50
    new_y = y[(len(y)-1)] + 12.5
    new_z = z[(len(z)-1)] 

    if new_x >= 100:
        new_x = new_x - 100
        new_z = new_z + 6.25
        #new_y = new_y + (50-12.5)
    if new_y >= 100:
        new_y = new_y - 100
    if new_z >= 100:
        new_z = new_z - 100

    if new_x == 0 and new_y == 0 and new_z == 0:
        print 'done!', i

    x.append(new_x)
    y.append(new_y)
    z.append(new_z)


ax.scatter(x, y, z, zdir='z', s=20, c='k', zorder=1)

storedcoordinates = zip(x,y,z)
for x,y,z in storedcoordinates:
    plotSquare(ax,x,y,z,xangle,angle, width/2)

pyplot.show()
© www.soinside.com 2019 - 2024. All rights reserved.