Finished verticalisation
This commit is contained in:
		
							parent
							
								
									af36b95e09
								
							
						
					
					
						commit
						533077d8b4
					
				| @ -193,7 +193,7 @@ def check_consistency(obj: ScannedObject, discretised_file_path: str): | ||||
|     :param obj: The object to check | ||||
|     :param discretised_file_path: The discetised file output | ||||
|     """ | ||||
|     obj.export("verification.txt") | ||||
|     obj.export_xyz("verification.txt") | ||||
|     mean_list = [] | ||||
|     moyx, moyy, moyz = parse_result_file(discretised_file_path) | ||||
|     moy = moyy | ||||
|  | ||||
							
								
								
									
										15
									
								
								main.py
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								main.py
									
									
									
									
									
								
							| @ -1,6 +1,8 @@ | ||||
| from utils.math import data_extraction | ||||
| from utils.files import output | ||||
| from utils.files.input import ScannedObject | ||||
| from utils.math.position_manipulation import verticalise | ||||
| from utils.graph3D.visplot_render import render3D | ||||
| 
 | ||||
| def get_raw_data(obj:ScannedObject, ndigits:int)->dict: | ||||
|     """ | ||||
| @ -46,7 +48,7 @@ def get_discrete_data(obj:ScannedObject, ndigits:int)->dict: | ||||
|         - Rayon moyen (en mm)       : list of mean radius values | ||||
|         - Rayon ecart type (en mm)  : list of radius standard deviation values | ||||
|     """ | ||||
|     colones = ["X moy (en mm)", "Y moy (en mm)", "Z moy (en mm)","Rayon moyen (en mm)","Rayon ecart type (en mm)"] | ||||
|     colones = ["X moy (en mm)", "Y moy (en mm)", "Z moy (en mm)","Delta z(en mm)","Rayon moyen (en mm)","Rayon ecart type (en mm)"] | ||||
|     data = {} | ||||
|     for colone in colones: | ||||
|         data[colone] = [] | ||||
| @ -55,15 +57,19 @@ def get_discrete_data(obj:ScannedObject, ndigits:int)->dict: | ||||
|         data["X moy (en mm)"].append(round(x, ndigits)) | ||||
|         data["Y moy (en mm)"].append(round(y, ndigits)) | ||||
|         data["Z moy (en mm)"].append(round(z, ndigits)) | ||||
|         first = discrete_values[0] | ||||
|         last = discrete_values[-1] | ||||
|         data["Delta z(en mm)"].append(round(last[2]-first[2],ndigits)) | ||||
|         data["Rayon moyen (en mm)"].append(round(data_extraction.get_mean_radius(discrete_values), ndigits)) | ||||
|         data["Rayon ecart type (en mm)"].append(round(data_extraction.get_radius_std(discrete_values), ndigits)) | ||||
|     return data | ||||
| 
 | ||||
| 
 | ||||
| def main(): | ||||
|     # Create an object from the given file | ||||
|     obj = ScannedObject.from_xyz_file("test_cylindre.xyz",normalised='z') | ||||
|      | ||||
|     obj = ScannedObject.from_obj_file("datasets/Barette/1 - BARETTE.obj") | ||||
|     verticalise(obj) | ||||
|     obj.normalise() | ||||
| 
 | ||||
|     # Calculate raw data and save it in a file | ||||
|     data = get_raw_data(obj, 6) | ||||
|     output.save_output_file('analyse_brute.txt', | ||||
| @ -85,6 +91,7 @@ def main(): | ||||
|                                                 ["X moy (en mm)", | ||||
|                                                 "Y moy (en mm)", | ||||
|                                                 "Z moy (en mm)", | ||||
|                                                 "Delta z(en mm)", | ||||
|                                                 "Rayon moyen (en mm)", | ||||
|                                                 "Rayon ecart type (en mm)"] )) | ||||
| 
 | ||||
|  | ||||
| @ -0,0 +1,3 @@ | ||||
| vispy==0.12.2 | ||||
| PyQt5==5.15.9 | ||||
| numpy==1.24.2 | ||||
| @ -60,15 +60,15 @@ class ScannedObject: | ||||
|     #TODO Add and test exemples | ||||
|     """ | ||||
|     def __init__(self, vertices, faces=None, result_file_path=None): | ||||
|         self.vertices = vertices | ||||
|         self.faces = faces | ||||
|         self.vertices = np.asarray(vertices) | ||||
|         self.faces = np.asarray(faces) | ||||
|         # Deprecated | ||||
|         self.result_file_path = result_file_path | ||||
|         self.bruteforce_discretization_result = None | ||||
|         # | ||||
|         self.x = [vertex[0] for vertex in vertices] | ||||
|         self.y = [vertex[1] for vertex in vertices] | ||||
|         self.z = [vertex[2] for vertex in vertices] | ||||
|         self.x = np.asarray([vertex[0] for vertex in vertices]) | ||||
|         self.y = np.asarray([vertex[1] for vertex in vertices]) | ||||
|         self.z = np.asarray([vertex[2] for vertex in vertices]) | ||||
| 
 | ||||
| 
 | ||||
|     @staticmethod | ||||
| @ -225,16 +225,56 @@ class ScannedObject: | ||||
|                 L.append([]) | ||||
|         return L | ||||
|      | ||||
| 
 | ||||
|     def get_faces(self)->list: | ||||
|     def get_faces(self,resolved:bool = False)->list: | ||||
|         """ | ||||
|         Get the faces of the object. | ||||
|         :return: faces | ||||
|         """ | ||||
|         if self.faces is None: | ||||
|             raise FacesNotGiven('No faces was given') | ||||
|         if resolved: | ||||
|             return self.vertices[self.faces] | ||||
|         return self.faces | ||||
| 
 | ||||
|     def update_from_faces(self,faces:list): | ||||
|         """ | ||||
|         Update the object from the faces. | ||||
|         :param faces: Faces to update the object from | ||||
|         """ | ||||
|         cpt = 0 | ||||
|         vertex_dict = {} | ||||
|         new_vertices = [] | ||||
|         new_faces = [] | ||||
|         for face in faces: | ||||
|             new_faces.append([]) | ||||
|             for vertex in face: | ||||
|                 vertex = tuple(vertex) | ||||
|                 if vertex not in vertex_dict: | ||||
|                     vertex_dict[vertex] = cpt | ||||
|                     cpt += 1 | ||||
|                     new_vertices.append(vertex) | ||||
|                 new_faces[-1].append(vertex_dict[vertex]) | ||||
| 
 | ||||
|         self.vertices = np.asarray(new_vertices) | ||||
|         self.faces = np.asarray(new_faces) | ||||
|         self.x = self.vertices[:,0] | ||||
|         self.y = self.vertices[:,1] | ||||
|         self.z = self.vertices[:,2] | ||||
|         self.normalise() | ||||
|      | ||||
|     def normalise(self, axis:str = 'z'): | ||||
|         """ | ||||
|         Normalise the object. | ||||
|         :param axis: Axis to normalise | ||||
|         """ | ||||
|         if 'x' in axis: | ||||
|             self.x -= min(self.x) | ||||
|         if 'y' in axis: | ||||
|             self.y -= min(self.y) | ||||
|         if 'z' in axis: | ||||
|             self.z -= min(self.z) | ||||
|         self.vertices = np.asarray(list(zip(self.x,self.y,self.z)))  | ||||
| 
 | ||||
|     def get_data(self)->dict: | ||||
|         """ | ||||
|         Get the data of the object. | ||||
| @ -258,7 +298,7 @@ class ScannedObject: | ||||
|         verticies = self.get_vertices(sort=True) | ||||
|         position = 0 | ||||
|         while position < len(verticies): | ||||
|             print(position/len(verticies)*100,end="\r") | ||||
|             print('progression :',position/len(verticies)*100,end="\r") | ||||
|             x = verticies[position][0] | ||||
|             y = verticies[position][1] | ||||
|             z = verticies[position][2] | ||||
| @ -277,7 +317,7 @@ class ScannedObject: | ||||
|         self.bruteforce_discretization_result = splitted_data | ||||
|         return splitted_data | ||||
| 
 | ||||
|     def export(self, file_path:str,separator:str="\t"): | ||||
|     def export_xyz(self, file_path:str,separator:str="\t"): | ||||
|         """ | ||||
|         Export the object in a file. | ||||
|         :param file_path: Path of the file | ||||
| @ -292,6 +332,25 @@ class ScannedObject: | ||||
|                 string+=f"{x}{separator}{y}{separator}{z}\n" | ||||
|         save_output_file(file_path,string) | ||||
| 
 | ||||
|     def export_obj(self,file_path): | ||||
|         """ | ||||
|         Export the object in a file. | ||||
|         :param file_path: Path of the file | ||||
|         """ | ||||
|         string = '' | ||||
|         with open(file_path, "w") as f: | ||||
|             for vertex in self.get_vertices(): | ||||
|                 x = round(vertex[0], 6) | ||||
|                 y = round(vertex[1], 6) | ||||
|                 z = round(vertex[2], 6) | ||||
|                 string+=f"v {x} {y} {z}\n" | ||||
|             for face in self.get_faces(): | ||||
|                 string+="f " | ||||
|                 for vertex in face: | ||||
|                     string+=f"{vertex+1} " | ||||
|                 string+="\n" | ||||
|         save_output_file(file_path,string) | ||||
| 
 | ||||
| 
 | ||||
| def parse_result_file(file_path: str, separator: str = "\t")-> tuple: | ||||
|     """ | ||||
|  | ||||
							
								
								
									
										90
									
								
								utils/math/position_manipulation.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								utils/math/position_manipulation.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,90 @@ | ||||
| import numpy as np | ||||
| from utils.files.input import ScannedObject | ||||
| from utils.math.data_extraction import get_mean | ||||
| 
 | ||||
| 
 | ||||
| def get_mass_properties(obj:ScannedObject): | ||||
|     ''' | ||||
|     Evaluate and return a tuple with the following elements: | ||||
|         - the volume | ||||
|         - the position of the center of gravity (COG) | ||||
|         - the inertia matrix expressed at the COG | ||||
| 
 | ||||
|     Documentation can be found here: | ||||
|     http://www.geometrictools.com/Documentation/PolyhedralMassProperties.pdf | ||||
|     ''' | ||||
| 
 | ||||
|     verts = np.asarray(obj.get_vertices()) | ||||
|     faces = np.asarray(obj.get_faces()) | ||||
|     faces = verts[faces] | ||||
|     x = np.asarray([[point[0] for point in faces] for faces in faces]) | ||||
|     y = np.asarray([[point[1] for point in faces] for faces in faces]) | ||||
|     z = np.asarray([[point[2] for point in faces] for faces in faces]) | ||||
| 
 | ||||
|     def subexpression(x): | ||||
|         w0, w1, w2 = x[:, 0], x[:, 1], x[:, 2] | ||||
|         temp0 = w0 + w1 | ||||
|         f1 = temp0 + w2 | ||||
|         temp1 = w0 * w0 | ||||
|         temp2 = temp1 + w1 * temp0 | ||||
|         f2 = temp2 + w2 * f1 | ||||
|         f3 = w0 * temp1 + w1 * temp2 + w2 * f2 | ||||
|         g0 = f2 + w0 * (f1 + w0) | ||||
|         g1 = f2 + w1 * (f1 + w1) | ||||
|         g2 = f2 + w2 * (f1 + w2) | ||||
|         return f1, f2, f3, g0, g1, g2 | ||||
| 
 | ||||
|     x0, x1, x2 = x[:, 0], x[:, 1], x[:, 2] | ||||
|     y0, y1, y2 = y[:, 0], y[:, 1], y[:, 2] | ||||
|     z0, z1, z2 = z[:, 0], z[:, 1], z[:, 2] | ||||
|     a1, b1, c1 = x1 - x0, y1 - y0, z1 - z0 | ||||
|     a2, b2, c2 = x2 - x0, y2 - y0, z2 - z0 | ||||
|     d0, d1, d2 = b1 * c2 - b2 * c1, a2 * c1 - a1 * c2, a1 * b2 - a2 * b1 | ||||
| 
 | ||||
|     f1x, f2x, f3x, g0x, g1x, g2x = subexpression(x) | ||||
|     f1y, f2y, f3y, g0y, g1y, g2y = subexpression(y) | ||||
|     f1z, f2z, f3z, g0z, g1z, g2z = subexpression(z) | ||||
| 
 | ||||
|     intg = np.zeros((10)) | ||||
|     intg[0] = sum(d0 * f1x) | ||||
|     intg[1:4] = sum(d0 * f2x), sum(d1 * f2y), sum(d2 * f2z) | ||||
|     intg[4:7] = sum(d0 * f3x), sum(d1 * f3y), sum(d2 * f3z) | ||||
|     intg[7] = sum(d0 * (y0 * g0x + y1 * g1x + y2 * g2x)) | ||||
|     intg[8] = sum(d1 * (z0 * g0y + z1 * g1y + z2 * g2y)) | ||||
|     intg[9] = sum(d2 * (x0 * g0z + x1 * g1z + x2 * g2z)) | ||||
|     intg /= np.array([6, 24, 24, 24, 60, 60, 60, 120, 120, 120]) | ||||
|     volume = intg[0] | ||||
|     cog = intg[1:4] / volume | ||||
|     cogsq = cog ** 2 | ||||
|     inertia = np.zeros((3, 3)) | ||||
|     inertia[0, 0] = intg[5] + intg[6] - volume * (cogsq[1] + cogsq[2]) | ||||
|     inertia[1, 1] = intg[4] + intg[6] - volume * (cogsq[2] + cogsq[0]) | ||||
|     inertia[2, 2] = intg[4] + intg[5] - volume * (cogsq[0] + cogsq[1]) | ||||
|     inertia[0, 1] = inertia[1, 0] = -(intg[7] - volume * cog[0] * cog[1]) | ||||
|     inertia[1, 2] = inertia[2, 1] = -(intg[8] - volume * cog[1] * cog[2]) | ||||
|     inertia[0, 2] = inertia[2, 0] = -(intg[9] - volume * cog[2] * cog[0]) | ||||
|     return volume, cog, inertia | ||||
| 
 | ||||
| def verticalise(obj:ScannedObject): | ||||
|     cog = get_mass_properties(obj) | ||||
|     cog, inertia = get_mass_properties(obj)[1:] | ||||
|     [val,vect] = np.linalg.eig(inertia) | ||||
| 
 | ||||
|     if np.linalg.det(vect) < 0: | ||||
|         vect[:,2] = - vect[:,2] | ||||
| 
 | ||||
|     rot = vect.T | ||||
|     faces = obj.get_faces(True) | ||||
| 
 | ||||
|     theta = -np.pi/2 | ||||
| 
 | ||||
|     R_y = np.array([[np.cos(theta), 0, np.sin(theta)], | ||||
|                     [0, 1, 0], | ||||
|                     [-np.sin(theta), 0, np.cos(theta)]]) | ||||
|      | ||||
|     for face,_ in enumerate(faces): | ||||
|         for vertex in range(3): | ||||
|             faces[face][vertex] = rot@(faces[face][vertex] - cog) | ||||
|             faces[face][vertex] = R_y@(faces[face][vertex]) | ||||
| 
 | ||||
|     obj.update_from_faces(faces) | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user