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
|
||||
|
||||
13
main.py
13
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,14 +57,18 @@ 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)
|
||||
@ -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