kshdes37's picture
Upload 50 files
91daf98 verified
import os
import sys
import numpy as np
from geometry.arc import Arc
from geometry.circle import Circle
from geometry.line import Line
from geometry import geom_utils
import pdb
class OBJParser:
"""
A class to read an OBJ file containing the sketch data
and hand it back in a form which is easy to work with.
"""
def __init__(self, pathname=None):
self.pathname = pathname
def convert_vertices(self, vertices):
"""Convert all the vertices to .obj format"""
vertex_strings = ""
for pt in vertices:
# e.g. v 0.123 0.234 0.345 1.0
vertex_string = f"v {pt[0]} {pt[1]}\n"
vertex_strings += vertex_string
return vertex_strings
def convert_curves(self, faces):
curve_strings = ""
total_curve = 0
# Faces (multiple closed regions)
for group_idx, loops in enumerate(faces):
curve_strings += f"\nface\n"
# Multiple loops (inner and outer)
for loop in loops:
if loop[0].is_outer:
curve_strings += f"out\n"
else:
curve_strings += f"in\n"
# All curves in one loop
for curve in loop:
total_curve += 1
if curve.type == 'line':
curve_strings += f"l {curve.start_idx} {curve.end_idx}\n"
elif curve.type == 'circle':
curve_strings += f"c {curve.center_idx} {curve.radius_idx}\n"
elif curve.type == 'arc':
curve_strings += f"a {curve.start_idx} {curve.mid_idx} {curve.center_idx} {curve.end_idx}\n"
return curve_strings, total_curve
def parse3d(self, point3d):
x = point3d[0]
y = point3d[1]
z = point3d[2]
return str(x)+' '+str(y)+' '+str(z)
def write_obj2(self, file, vertices, faces, meta_info, scale=None):
""" Write to .obj file """
vertex_strings = self.convert_vertices(vertices)
curve_strings, total_curve = self.convert_curves(faces)
with open(file, "w") as fh:
# Write Meta info
fh.write("# WaveFront *.obj file\n")
fh.write(f"# Vertices: {len(vertices)}\n")
fh.write(f"# Curves: {total_curve}\n")
fh.write("\n")
# Write vertex and curve
fh.write(vertex_strings)
fh.write("\n")
fh.write(curve_strings)
fh.write("\n")
#Write extrude value
fh.write("ExtrudeOperation: " + meta_info['set_op']+"\n")
extrude_string = 'Extrude '
for value in meta_info['extrude_value']:
extrude_string += str(value)+' '
fh.write(extrude_string)
fh.write("\n")
#Write refe plane transformation
p_orig = self.parse3d(meta_info['t_orig'])
x_axis = self.parse3d(meta_info['t_x'])
y_axis = self.parse3d(meta_info['t_y'])
z_axis = self.parse3d(meta_info['t_z'])
fh.write('T_origin '+p_orig)
fh.write("\n")
fh.write('T_xaxis '+x_axis)
fh.write("\n")
fh.write('T_yaxis '+y_axis)
fh.write("\n")
fh.write('T_zaxis '+z_axis)
fh.write("\n")
# Normalized object
if scale is not None:
fh.write('Scale '+str(scale))
def write_obj(self, file, curve_strings, total_curve, vertex_strings, total_v, meta_info, scale=None):
""" Write to .obj file """
#vertex_strings = self.convert_vertices(vertices)
#curve_strings, total_curve = self.convert_curves(faces)
with open(file, "w") as fh:
# Write Meta info
fh.write("# WaveFront *.obj file\n")
fh.write(f"# Vertices: {total_v}\n")
fh.write(f"# Curves: {total_curve}\n")
fh.write("\n")
# Write vertex and curve
fh.write(vertex_strings)
fh.write("\n")
fh.write(curve_strings)
fh.write("\n")
#Write extrude value
fh.write("ExtrudeOperation: " + meta_info['set_op']+"\n")
extrude_string = 'Extrude '
for value in meta_info['extrude_value']:
extrude_string += str(value)+' '
fh.write(extrude_string)
fh.write("\n")
#Write refe plane transformation
p_orig = self.parse3d(meta_info['t_orig'])
x_axis = self.parse3d(meta_info['t_x'])
y_axis = self.parse3d(meta_info['t_y'])
z_axis = self.parse3d(meta_info['t_z'])
fh.write('T_origin '+p_orig)
fh.write("\n")
fh.write('T_xaxis '+x_axis)
fh.write("\n")
fh.write('T_yaxis '+y_axis)
fh.write("\n")
fh.write('T_zaxis '+z_axis)
fh.write("\n")
# Normalized object
if scale is not None:
fh.write('Scale '+str(scale))
def parse_file(self, scale=1.0):
"""
Parse obj file
Return
vertex 2D location numpy
curve list (geometry class)
extrude parameters
"""
assert self.pathname is not None, "File is None"
assert self.pathname.exists(), "No such file"
# Parse file
vertex_list = []
loops = []
closed_loop = []
# Read vertice
with open(self.pathname) as obj_file:
for line in obj_file:
tokens = line.split()
if not tokens:
continue
line_type = tokens[0]
# Vertex
if line_type == "v":
vertex_list.append([float(x) for x in tokens[1:]])
vertices = np.array(vertex_list, dtype=np.float64) * scale
# Read curves
faces = []
loops = []
loop = []
# Read in all lines
lines = []
with open(self.pathname) as obj_file:
for line in obj_file:
lines.append(line)
# Parse all lines
faces = []
for str_idx, line in enumerate(lines):
tokens = line.split()
if not tokens:
continue
line_type = tokens[0]
# Start of a new face
if line_type == "face":
faces.append(self.read_face(lines, str_idx+1, vertices))
# Read meta data
meta_data = line.strip('# ').strip(' \n').split(' ')
meta_name = meta_data[0]
if meta_name == 'Extrude':
extrude_values = [float(x) for x in meta_data[1:]]
extrude_values = [x*scale for x in extrude_values]
elif meta_name == 'T_origin':
t_orig = [float(x) for x in meta_data[1:]]
t_orig = [x*scale for x in t_orig]
elif meta_name == 'T_xaxis':
t_x = [float(x) for x in meta_data[1:]]
elif meta_name == 'T_yaxis':
t_y = [float(x) for x in meta_data[1:]]
elif meta_name == 'T_zaxis':
t_z = [float(x) for x in meta_data[1:]]
elif meta_name == 'ExtrudeOperation:':
set_op = meta_data[1]
meta_info = {'extrude_value': extrude_values,
'set_op': set_op,
't_orig': t_orig,
't_x': t_x,
't_y': t_y,
't_z': t_z,
}
return vertices, faces, meta_info
def read_face(self, lines, str_idx, vertices):
loops = []
loop = []
for line in lines[str_idx:]:
tokens = line.split()
if not tokens:
continue
line_type = tokens[0]
if line_type == 'face':
break
# Start of a new loop
if line_type == "out" or line_type == "in":
if len(loop) > 0:
loops.append(loop)
loop = []
is_outer = (line_type == 'out')
# Line
if line_type == 'l':
c_tok = tokens[1:]
curve = Line([int(c_tok[0]), int(c_tok[1])], vertices, is_outer=is_outer)
loop.append(curve)
# Arc
if line_type == 'a':
c_tok = tokens[1:]
curve = Arc([int(c_tok[0]), int(c_tok[1]), int(c_tok[2]), int(c_tok[3])], vertices, is_outer=is_outer)
loop.append(curve)
# Circle
if line_type == 'c':
c_tok = tokens[1:]
curve = Circle([int(c_tok[0]), int(c_tok[1])], vertices, is_outer=is_outer)
loop.append(curve)
loops.append(loop)
return loops