🐛 fix(input.py): add authorised_extensions as a static variable to ScannedObject class
✨ feat(input.py): add support for binary and ascii STL files to ScannedObject class
The ScannedObject class now has a static variable called authorised_extensions which contains a list of file extensions that are supported by the class. This improves the readability of the code and makes it easier to maintain. The ScannedObject class now also supports binary and ascii STL files, which increases the flexibility of the class and allows it to handle more file formats.
This commit is contained in:
parent
5a6be4717b
commit
5babe707c6
@ -5,6 +5,7 @@ Created on Thu Apr 20 2023
|
|||||||
@auth: Djalim Simaila
|
@auth: Djalim Simaila
|
||||||
@e-mail: djalim.simaila@inrae.fr
|
@e-mail: djalim.simaila@inrae.fr
|
||||||
"""
|
"""
|
||||||
|
import struct
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import os
|
import os
|
||||||
from utils.files.output import save_output_file
|
from utils.files.output import save_output_file
|
||||||
@ -53,6 +54,9 @@ class ScannedObject:
|
|||||||
:raises FacesNotGiven: If no faces was given
|
:raises FacesNotGiven: If no faces was given
|
||||||
:raises ResultFileNotGiven: If no result file was given
|
:raises ResultFileNotGiven: If no result file was given
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
authorised_extensions = [".obj",".stl",".xyz"]
|
||||||
|
|
||||||
def __init__(self, vertices, faces=None):
|
def __init__(self, vertices, faces=None):
|
||||||
self.vertices = np.asarray(vertices)
|
self.vertices = np.asarray(vertices)
|
||||||
self.faces = np.asarray(faces) if faces is not None else None
|
self.faces = np.asarray(faces) if faces is not None else None
|
||||||
@ -78,9 +82,27 @@ class ScannedObject:
|
|||||||
return ScannedObject.from_xyz_file(file_path, ' ',ratio, normalised)
|
return ScannedObject.from_xyz_file(file_path, ' ',ratio, normalised)
|
||||||
elif os.path.splitext(file_path)[1].lower() == ".obj":
|
elif os.path.splitext(file_path)[1].lower() == ".obj":
|
||||||
return ScannedObject.from_obj_file(file_path, ratio, normalised)
|
return ScannedObject.from_obj_file(file_path, ratio, normalised)
|
||||||
|
elif os.path.splitext(file_path)[1].lower() == ".stl":
|
||||||
|
if open(file_path, 'rb').read(5) == b'solid':
|
||||||
|
return ScannedObject.from_ascii_stl_file(file_path, ratio, normalised)
|
||||||
|
else:
|
||||||
|
return ScannedObject.from_binary_stl_file(file_path, ratio, normalised)
|
||||||
else:
|
else:
|
||||||
raise InvalidFileFormat("The file format is not supported.")
|
raise InvalidFileFormat("The file format is not supported.")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def from_triangles(triangles:list, normalised:str = '')->'ScannedObject':
|
||||||
|
"""
|
||||||
|
Create an Object from a list of triangles.
|
||||||
|
|
||||||
|
:param triangles: List of triangles
|
||||||
|
:param vertices: List of vertices
|
||||||
|
:return: A ScannedObject
|
||||||
|
"""
|
||||||
|
obj = ScannedObject([], None)
|
||||||
|
obj.update_from_faces(triangles)
|
||||||
|
obj.normalise(normalised)
|
||||||
|
return obj
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_obj_file(file_path:str, ratio:float = 1,normalised:str = '')->'ScannedObject':
|
def from_obj_file(file_path:str, ratio:float = 1,normalised:str = '')->'ScannedObject':
|
||||||
@ -165,6 +187,60 @@ class ScannedObject:
|
|||||||
z[count] -= zmin
|
z[count] -= zmin
|
||||||
return ScannedObject(list(zip(x,y,z)))
|
return ScannedObject(list(zip(x,y,z)))
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def from_binary_stl_file(file_path:str, ratio:float = 1, normalised:str = '')->'ScannedObject':
|
||||||
|
"""
|
||||||
|
Create an Object from a binary STL file.
|
||||||
|
|
||||||
|
:param file_path: Path to the STL file
|
||||||
|
:param ratio: Ratio to apply to the vertices
|
||||||
|
:param normalised: the axis to normalise
|
||||||
|
:return: A ScannedObject
|
||||||
|
"""
|
||||||
|
with open(file_path, 'rb') as f:
|
||||||
|
data = f.read(84)
|
||||||
|
n_triangles = int.from_bytes(data[80:84], byteorder='little')
|
||||||
|
triangles = []
|
||||||
|
|
||||||
|
for numero_triangles in range(n_triangles):
|
||||||
|
f.read(12)
|
||||||
|
current_triangle = []
|
||||||
|
for i in range(3):
|
||||||
|
vertex = list(struct.unpack('fff', f.read(12)))
|
||||||
|
for point in vertex:
|
||||||
|
point *= ratio
|
||||||
|
current_triangle.append(vertex)
|
||||||
|
triangles.append(current_triangle)
|
||||||
|
f.read(2)
|
||||||
|
|
||||||
|
return ScannedObject.from_triangles(triangles, normalised)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def from_ascii_stl_file(file_path:str, ratio:float = 1, normalised:str = '')->'ScannedObject':
|
||||||
|
"""
|
||||||
|
Create an Object from an STL file.
|
||||||
|
|
||||||
|
:param file_path: Path to the STL file
|
||||||
|
:param ratio: Ratio to apply to the vertices
|
||||||
|
:param normalised: the axis to normalise
|
||||||
|
:return: A ScannedObject
|
||||||
|
"""
|
||||||
|
with open(file_path, 'r', encoding='utf-8') as f:
|
||||||
|
triangles = []
|
||||||
|
vertex_buffer = []
|
||||||
|
data = f.readlines()
|
||||||
|
for line in data :
|
||||||
|
if line.startswith('vertex'):
|
||||||
|
x = float(line.split()[1]) * ratio
|
||||||
|
y = float(line.split()[2]) * ratio
|
||||||
|
z = float(line.split()[3]) * ratio
|
||||||
|
vertex_buffer.append([x,y,z])
|
||||||
|
if len(vertex_buffer) == 3:
|
||||||
|
triangles.append(vertex_buffer)
|
||||||
|
vertex_buffer = []
|
||||||
|
|
||||||
|
return ScannedObject.from_triangles(triangles, normalised)
|
||||||
|
|
||||||
def get_x(self)->list:
|
def get_x(self)->list:
|
||||||
"""
|
"""
|
||||||
Get the x coordinates of the object.
|
Get the x coordinates of the object.
|
||||||
@ -257,8 +333,10 @@ class ScannedObject:
|
|||||||
for index,_ in enumerate(sorted_vertices):
|
for index,_ in enumerate(sorted_vertices):
|
||||||
splitted_data[-1].append(sorted_vertices[index])
|
splitted_data[-1].append(sorted_vertices[index])
|
||||||
if sorted_vertices[index][2] - z > step:
|
if sorted_vertices[index][2] - z > step:
|
||||||
z = sorted_vertices[index+1][2]
|
# if you split on the very last point, dont create an empty slice
|
||||||
splitted_data.append([])
|
if index + 1 < len(sorted_vertices):
|
||||||
|
z = sorted_vertices[index+1][2]
|
||||||
|
splitted_data.append([])
|
||||||
self.old_discrete = splitted_data
|
self.old_discrete = splitted_data
|
||||||
return splitted_data
|
return splitted_data
|
||||||
|
|
||||||
@ -313,7 +391,6 @@ class ScannedObject:
|
|||||||
self.x = self.vertices[:,0]
|
self.x = self.vertices[:,0]
|
||||||
self.y = self.vertices[:,1]
|
self.y = self.vertices[:,1]
|
||||||
self.z = self.vertices[:,2]
|
self.z = self.vertices[:,2]
|
||||||
self.normalise()
|
|
||||||
|
|
||||||
def normalise(self, axis:str = 'z'):
|
def normalise(self, axis:str = 'z'):
|
||||||
"""
|
"""
|
||||||
|
@ -163,7 +163,8 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
|
|||||||
- if it exists
|
- if it exists
|
||||||
- if its extension is .obj
|
- if its extension is .obj
|
||||||
"""
|
"""
|
||||||
authorised_extensions = [".obj",".xyz"]
|
authorised_extensions = ScannedObject.authorised_extensions
|
||||||
|
|
||||||
if not os.path.isfile(self.input_file_path.toPlainText()) :
|
if not os.path.isfile(self.input_file_path.toPlainText()) :
|
||||||
ErrorPopup("Fichier d'entrée invalide: Aucun fichier selectionné, ou le fichier n'existe pas",
|
ErrorPopup("Fichier d'entrée invalide: Aucun fichier selectionné, ou le fichier n'existe pas",
|
||||||
button_label="Choisir un fichier d'entrée",
|
button_label="Choisir un fichier d'entrée",
|
||||||
|
Loading…
Reference in New Issue
Block a user