I made my own ply exporter and even though it is working, it is quite slow. I'm assuming that the problem comes from specifically looping over the elements and, based on this comment, from using struct.pack
.
The challenge with exporting Nodes
is that it is a 1D vector of tuples. The challenge with exporting Faces
is that each line of int
s is preceded by a number "3" in uchar
format.
I put the entire code here since it serves as a MWE and also a reference if someone wants to use the code to export meshes in ply format.
Code:
from __future__ import division
import numpy as np
import struct
import timeit
def Timeme(funct,var,NN=10,NNN=10):
for i in xrange(NN):
start =timeit.default_timer()
for t in xrange(NNN):
funct(*var)
end =timeit.default_timer()
print str(i)+': '+str((end - start)/NNN*1000)
# This function is fictitious. In reality the
# Nodes array is imported from another module
def MakeNodes(Nr,Nc):
Nodes=np.zeros(Nr*Nc,dtype=[('x', np.float32), ('y', np.float32), ('z', np.float32)])
x = np.linspace(0, (Nc-1), Nc, dtype=np.float32)
y = np.linspace((Nr-1),0 , Nr, dtype=np.float32)
xv, yv = np.meshgrid(x, y, sparse=False, indexing='xy')
Nodes['x']=xv.flatten()
Nodes['y']=yv.flatten()
Nodes['z']=(1/2-((Nodes['x']/Nc-1/2)**2+ (Nodes['y']/Nr-1/2)**2))*Nr/2
return Nodes
# Function below explained in https://stackoverflow.com/questions/44934631
def MakeFaces(Nr,Nc):
out = np.empty((Nr-1,Nc-1,2,3),dtype=int)
r = np.arange(Nr*Nc).reshape(Nr,Nc)
l1=r[:-1,:-1]
l2=r[:-1,1:]
l3=r[1:,:-1]
l4=r[1:,1:]
out[:,:, 0,0] = l2
out[:,:, 0,1] = l1
out[:,:, 0,2] = l3
out[:,:, 1,0] = l4
out[:,:, 1,1] = l2
out[:,:, 1,2] = l3
out.shape =(-1,3)
return out
def ExportPlyBinary(Nodes,Faces,file):
LN=len(Nodes)
LF=len(Faces)
header= \
"ply\n" \
"format binary_little_endian 1.0\n" \
"element vertex "+str(LN)+"\n" \
"property float x\n" \
"property float y\n" \
"property float z\n" \
"element face "+str(LF)+"\n" \
"property list uchar int vertex_indices\n" \
"end_header\n"
with open(file, 'wb') as fp:
fp.write(header)
s = struct.Struct('<fff')
for nd in Nodes:
fp.write(s.pack(nd['x'],nd['y'],nd['z']))
s = struct.Struct('<Blll')
for fc in Faces:
fp.write(s.pack(3,fc[0],fc[1],fc[2]))
Nr=200
Nc=200
Nodes=MakeNodes(Nr,Nc)
Faces=MakeFaces(Nr,Nc)
Timeme(ExportPlyBinary,(Nodes,Faces,"Test.ply"))
Timeme(np.savez,("Test_np.ply", Nodes,Faces))
Result:
0: 366.352801235
1: 386.216017627
2: 383.307741944
3: 359.598214393
4: 363.434228045
5: 397.255473919
6: 433.967095136
7: 407.806616677
8: 393.701390596
9: 379.542319143
0: 15.5258007875
1: 13.2543344563
2: 12.8754439597
3: 24.2303215372
4: 15.9684973291
5: 14.2023306048
6: 13.7465456437
7: 13.6964054484
8: 21.27484093
9: 13.2139143373