17
|
1 # Rotate ply file to normalized position
|
|
2 # based at points on symmetry axis
|
|
3 # MB
|
|
4
|
|
5 import math
|
|
6 from math import *
|
|
7 import sys
|
|
8 import numpy
|
|
9
|
|
10 # Main function
|
|
11 def main():
|
|
12 # input user .ply file
|
|
13 name_file_ply = sys.argv[1]
|
|
14 # input user symmetry points file
|
|
15 sym_points_file = sys.argv[2]
|
|
16
|
|
17 # to function 'extracting header', return header features
|
|
18 var_header,var_vertex_nm,var_face_nm, var_col = extracting_header(name_file_ply)
|
|
19
|
|
20 # to function 'extracting symmetry points', return symmetry points and list with new vertex
|
|
21 listsym,listtotal_vertex = extracting_symmetry_points(sym_points_file)
|
|
22
|
|
23 # to function 'extracting coordiantes', return list vertex and colors
|
|
24 listtotal_vertex, listtotal_colors = extracting_coordinates(name_file_ply,
|
|
25 var_header,var_vertex_nm,var_face_nm,
|
|
26 listtotal_vertex, var_col)
|
|
27 # to function 'shift to zero'
|
|
28 shift_to_zero(listsym,listtotal_vertex)
|
|
29
|
|
30 # to function 'write ply file'
|
|
31 write_ply_file(name_file_ply, var_header,var_vertex_nm,var_face_nm,
|
|
32 listtotal_colors, listtotal_vertex)
|
|
33
|
|
34
|
|
35 # Function to extract all the values of the header of the ply file
|
|
36 def extracting_header(name_file_ply):
|
|
37 file_ply = open(name_file_ply) # open ply file
|
|
38 var_col = 0 # color variable
|
|
39 count = 0 # counter
|
|
40
|
|
41 # for the first lines of the ply file
|
|
42 for line in range(0, 40):
|
|
43 readheader = file_ply.readline().strip().split()
|
|
44 if len(readheader) != 0:
|
|
45 if readheader[0] == 'end_header':
|
|
46 var_header = count
|
|
47
|
|
48 # If there are colors in the ply file
|
|
49 if 'red' in readheader:
|
|
50 var_col += 1
|
|
51 if 'blue' in readheader:
|
|
52 var_col += 1
|
|
53 if 'green' in readheader:
|
|
54 var_col += 1
|
|
55
|
|
56 # extracting number of vertexen
|
|
57 if readheader[0] == "element" and readheader[1] == "vertex":
|
|
58 var_vertex_nm = readheader[2]
|
|
59
|
|
60 # extracting number of faces
|
|
61 if readheader[0] == "element" and readheader[1] == "face":
|
|
62 var_face_nm = readheader[2]
|
|
63 count += 1
|
|
64 else:
|
|
65 continue
|
|
66
|
|
67 file_ply.close() # closing ply file
|
|
68 return var_header, var_vertex_nm,var_face_nm, var_col # return values to main
|
|
69
|
|
70 # Function for extracting the values of the symmetry points file
|
|
71 def extracting_symmetry_points(sym_points_file):
|
|
72 sympoints = open(sym_points_file) # open symmetry file
|
|
73 symlines = sympoints.readlines() # read all the lines of file
|
|
74 listsym = [] # symmetry points
|
|
75 listtotal_vertex = [] # vertexen
|
|
76 # every line in the sym file
|
|
77 for sym in range(0,len(symlines)):
|
|
78 symline_1 = symlines[sym].strip().split()
|
|
79 listsym.append(symlines[sym].strip().split()) #add symmetry points
|
|
80 listtotal_vertex.append(symlines[sym].strip().split()) # add symmetry points
|
|
81
|
|
82 sympoints.close() # close symmetry file
|
|
83 return listsym,listtotal_vertex # return symmetry points list and vertex list
|
|
84
|
|
85
|
|
86 # Function to extract the coordinates of the ply file
|
|
87 def extracting_coordinates(name_file_ply, var_header,var_vertex_nm,var_face_nm, listtotal_vertex, var_col):
|
|
88 file1 = open(name_file_ply) # open ply file
|
|
89
|
|
90 sub_list = [] #sublist coordinates
|
|
91 listtotal_colors = [] # color list
|
|
92 sub_colors = [] # sublist color
|
|
93
|
|
94 # coordinates of ply file to list
|
|
95 for coordinates_ln in range(0, (int(var_header) + int(var_vertex_nm) + int(var_face_nm) + 1)):
|
|
96 line = file1.readline().strip().split()
|
|
97 if (int(var_header) < coordinates_ln < (int(var_vertex_nm)+ int(var_header)+1)):
|
|
98 rayx = sub_list.append(line[0])
|
|
99 rayy = sub_list.append(line[1])
|
|
100 rayz = sub_list.append(line[2])
|
|
101 listtotal_vertex.append(sub_list) #x y z coordinates to list
|
|
102 sub_list = []
|
|
103 if var_col != 0: #if color code is not 0
|
|
104 color_x = sub_colors.append(line[3])
|
|
105 color_y = sub_colors.append(line[4])
|
|
106 color_z = sub_colors.append(line[5])
|
|
107 listtotal_colors.append(sub_colors) #colors to list
|
|
108 sub_colors = []
|
|
109
|
|
110 return listtotal_vertex, listtotal_colors # return coordinates (vertexen) and color lists
|
|
111
|
|
112
|
|
113 # Function to calculate the values in the Z rotation matrix
|
|
114 def Rz_matrix(z_angle): # Rz rotation matrix
|
|
115 return [[cos(math.radians(z_angle)), -sin(math.radians(z_angle)), 0.0],[sin(math.radians(z_angle)),cos(math.radians(z_angle)),0.0],[0.0, 0.0, 1.0]]
|
|
116
|
|
117 # Function to calculate the new coordinates rotated with Z rotation matrix
|
|
118 def Z_rotation(point2, z_angle): # multiplication rotation matrix and coordinates
|
|
119 r_z = Rz_matrix(z_angle)
|
|
120 rotated_z = []
|
|
121 for i in range(3):
|
|
122 rotated_z.append((sum([r_z[i][j] * point2[j] for j in range(3)])))
|
|
123 return rotated_z
|
|
124
|
|
125 # Function to calculate the values in the X rotation matrix
|
|
126 def Rx_matrix(x_angle): #rotation matrix x-axis
|
|
127 return [[1, 0, 0],[0,cos(math.radians(x_angle)),-sin(math.radians(x_angle))],[0,sin(math.radians(x_angle)),cos(math.radians(x_angle))]]
|
|
128
|
|
129 # Function to calculate the new coordinates rotated with X rotation matrix
|
|
130 def X_rotation(point3, x_angle): #multiplication rotation matrix and coordinates
|
|
131 r_x = Rx_matrix(x_angle)
|
|
132 rotated_x = []
|
|
133 for i in range(3):
|
|
134 rotated_x.append((sum([r_x[i][j] * point3[j] for j in range(3)])))
|
|
135 return rotated_x
|
|
136
|
|
137 # Function to calculate the values in the Y rotation matrix
|
|
138 def Ry_matrix(y_angle): # Ry rotation matrix
|
|
139 return [[cos(math.radians(y_angle)), 0.0, sin(math.radians(y_angle))],[0.0, 1.0, 0.0],[-sin(math.radians(y_angle)),0.0, cos(math.radians(y_angle))]]
|
|
140
|
|
141 # Function to calculate the new coordinates rotated with Y rotation matrix
|
|
142 def Y_rotation(point4, y_angle): #multiplication rotation matrix and coordinates
|
|
143 r_y = Ry_matrix(y_angle)
|
|
144 rotated_y = []
|
|
145 for i in range(3):
|
|
146 rotated_y.append((sum([r_y[i][j] * point4[j] for j in range(3)])))
|
|
147 return rotated_y
|
|
148
|
|
149 #Function to shift the object to the zeropoint
|
|
150 def shift_to_zero(listsym, listtotal_vertex):
|
|
151 sym3 = listsym[2]
|
|
152 zeropoint = sym3
|
|
153 list2 = [] # sublist coordinates
|
|
154 listdata3 = [] # new coordinates
|
|
155 # every coordinate minus the sym3 coordinates
|
|
156 for vertex in range(0,len(listtotal_vertex)):
|
|
157 list2.append(float(listtotal_vertex[vertex][0]) - float(zeropoint[0]))
|
|
158 list2.append(float(listtotal_vertex[vertex][1]) - float(zeropoint[1]))
|
|
159 list2.append(float(listtotal_vertex[vertex][2]) - float(zeropoint[2]))
|
|
160 listdata3.append(list2) # add new coordinates to list
|
|
161 list2 = []
|
|
162
|
|
163 # to function 'rotate z axis'
|
|
164 rotate_z_axis(listdata3)
|
|
165
|
|
166 # Function for rotating the object around z axis
|
|
167 def rotate_z_axis(listdata3):
|
|
168 # If object is upside down, 180 degrees rotation around the Z axis is needed.
|
|
169 listdatatemp = []
|
|
170 # check if object is upside down
|
|
171 if listdata3[0][1] < listdata3[2][1]:
|
|
172 angle = 180
|
|
173 # rotate 180 degrees.
|
|
174 for coordinates in range(0,len(listdata3)):
|
|
175 listdatatemp.append(Z_rotation(listdata3[coordinates], angle))
|
|
176 listdata3 = listdatatemp # new coordinates
|
|
177
|
|
178
|
|
179 # calculate angle rotation z
|
|
180 len_z_a = listdata3[0][0] - listdata3[2][0]
|
|
181 len_z_b = listdata3[0][1] - listdata3[2][1]
|
|
182 z_angle = (math.degrees(math.atan(len_z_a/len_z_b)))
|
|
183
|
|
184 # calculate new coordinates with rotation matrix of Z
|
|
185 listdata4 = []
|
|
186 for coordinates in range(0, len(listdata3)):
|
|
187 listdata4.append(Z_rotation(listdata3[coordinates], z_angle)) # add new coordinates to list
|
|
188 listdata3 = []
|
|
189
|
|
190 # to function 'rotate x axis'
|
|
191 rotate_x_axis(listdata4)
|
|
192
|
|
193 # Function for rotating the object around x axis
|
|
194 def rotate_x_axis(listdata4):
|
|
195 #calculate angle rotation x
|
|
196 len_x_a = listdata4[0][2] - listdata4[2][0]
|
|
197 len_x_b = listdata4[0][1] - listdata4[2][0]
|
|
198 x_angle = -(math.degrees(math.atan(len_x_a/len_x_b)))
|
|
199
|
|
200 # calculate new coordinates with rotation matrix of X
|
|
201 listdata5 = []
|
|
202 for coordinates in range(0, len(listdata4)):
|
|
203 listdata5.append(X_rotation(listdata4[coordinates], x_angle)) # add new coordinates to list
|
|
204 listdata4 = []
|
|
205
|
|
206 # to function 'rotate y axis'
|
|
207 rotate_y_axis(listdata5)
|
|
208
|
|
209 # Function for rotating the object around y axis
|
|
210 def rotate_y_axis(listdata5):
|
|
211 #calculate angle rotation y
|
|
212 len_y_a = (listdata5[1][0] - listdata5[2][0])
|
|
213 len_y_b = (listdata5[1][2] - listdata5[2][2])
|
|
214 y_angle = -(math.degrees(math.atan(len_y_a/len_y_b)))
|
|
215
|
|
216 # calculate new coordinates with rotation matrix of Y
|
|
217 listdata6 = []
|
|
218 for coordinates in range(0, len(listdata5)):
|
|
219 listdata6.append(Y_rotation(listdata5[coordinates], y_angle))
|
|
220
|
|
221 listdata5 = []
|
|
222 #Rotate 180 degrees around y axis when object is backwards.#
|
|
223 listdatatemp = []
|
|
224 if listdata6[1][0] < listdata6[3][0]: #point sym2_x < point sym 3
|
|
225 angle = 180
|
|
226 for coordinates in range(0,len(listdata6)):
|
|
227 listdatatemp.append(Y_rotation(listdata6[coordinates], angle)) # add new coordinates to list
|
|
228 listdata6 = listdatatemp
|
|
229
|
|
230 # to function 'write new coordinates'
|
|
231 write_new_coordinates(listdata6)
|
|
232
|
|
233 # Function write the new coordinates to outputfile.
|
|
234 def write_new_coordinates(listdata6):
|
|
235 file_outputname4 = 'outputrotate_points.ply' # sub outputfile
|
|
236 output4 = open(file_outputname4, 'w')
|
|
237
|
|
238 # write every coordinate to output file
|
|
239 for line in range(0,len(listdata6)):
|
|
240 output4.write("%.7f %.7f %.7f\n"%(listdata6[line][0], listdata6[line][1], listdata6[line][2]))
|
|
241
|
|
242 # Function to write the new ply file with
|
|
243 def write_ply_file(name_file_ply, var_header,var_vertex_nm,var_face_nm, listtotal_colors, listtotal_vertex):
|
|
244 outfile_rotating2 = open(sys.argv[3], 'w') #create new file
|
|
245 pointsfile = open('outputrotate_points.ply', 'r') #new points
|
|
246 file2= open(name_file_ply) #original ply file
|
|
247 counter = 0 # counter for color
|
|
248
|
|
249 # writing all the parts of the new ply file
|
|
250 for line in range(0,(int(var_header) + int(var_vertex_nm) + int(var_face_nm) + 1)):
|
|
251 line2 = file2.readline()
|
|
252 readline2 = line2.strip().split()
|
|
253 if line <= (int(var_header)): #header writing
|
|
254 outfile_rotating2.write('%s'%(line2))
|
|
255 if line == int(var_header): #new coordinates writing
|
|
256 line2 = file2.readline()
|
|
257 readline2 = line2.strip().split()
|
|
258 for vertex in range(0,len(listtotal_vertex)):
|
|
259 line3 = pointsfile.readline().strip()
|
|
260 if vertex >= 4: #from point 4, because they were extra edit to the list in the beginning
|
|
261 outfile_rotating2.write('%s %s %s %s\n'%
|
|
262 (line3, listtotal_colors[counter][0],
|
|
263 listtotal_colors[counter][1], listtotal_colors[counter][2]))
|
|
264 counter += 1
|
|
265 if line == (int(var_vertex_nm) + int(var_header)-1): #write the faces
|
|
266 for face in range(0, int(var_face_nm)):
|
|
267 line2 = file2.readline()
|
|
268 outfile_rotating2.write('%s'%(line2))
|
|
269 counter = 0
|
|
270
|
|
271 outfile_rotating2.close() # outputfile close
|
|
272
|
|
273 main()
|