Source code for tvb.adapters.uploaders.obj.parser

# -*- coding: utf-8 -*-
# TheVirtualBrain-Framework Package. This package holds all Data Management, and 
# Web-UI helpful to run brain-simulations. To use it, you also need to download
# TheVirtualBrain-Scientific Package (for simulators). See content of the
# documentation-folder for more details. See also
# (c) 2012-2023, Baycrest Centre for Geriatric Care ("Baycrest") and others
# This program is free software: you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software Foundation,
# either version 3 of the License, or (at your option) any later version.
# This program is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.  See the GNU General Public License for more details.
# You should have received a copy of the GNU General Public License along with this
# program.  If not, see <>.
# When using The Virtual Brain for scientific publications, please cite it as explained here:

Handlers for reading/writing from/into OBJ format Surfaces are defined in this module.

.. moduleauthor:: Mihai Andrei <>

from tvb.basic.logger.builder import get_logger

[docs]class ObjParser(object): """ This class reads geometry from a simple wavefront obj file. ``self.vertices``, ``self.tex_coords``, ``self.normals`` are lists of vectors represented as tuples ``self.faces`` is a list of faces. A face is a list of vertex info. Vertex info is a tuple vertex_index, tex_index, normal_index. """ def __init__(self): self.logger = get_logger(__name__) self.vertices = [] self.normals = [] self.tex_coords = [] self.faces = []
[docs] def parse_v(self, args): self.vertices.append(tuple(float(x) for x in args[:3]))
[docs] def parse_vn(self, args): self.normals.append(tuple(float(x) for x in args[:3]))
[docs] def parse_vt(self, args): self.tex_coords.append(tuple(float(x) for x in args[:3]))
[docs] def parse_f(self, args): if len(args) < 3: raise ValueError("Require at least 3 vertices per face") face = [] for v in args: indices = [] for j in v.split('/'): if j == '': indices.append(-1) else: indices.append(int(j) - 1) while len(indices) < 3: indices.append(-1) face.append(indices) self.faces.append(face)
[docs] def read(self, obj_file): line_nr = -1 try: for line_nr, line in enumerate(obj_file): line = line.strip() if line == "" or line[0] == '#': continue tokens = line.split() data_type = tokens[0] datatype_parser = getattr(self, "parse_%s" % data_type, None) if datatype_parser is not None: datatype_parser(tokens[1:]) else: self.logger.warning("Unsupported token type %s" % data_type) except ValueError as ex: raise ValueError("%s at line %d" % (ex, line_nr))
[docs]class ObjWriter(object): def __init__(self, obj_file): self.logger = get_logger(__name__) self.file = obj_file def _write_vector(self, type_code, v): v_str = ' '.join(str(e) for e in v) self.file.write('%s %s\n' % (type_code, v_str)) def _write_face(self, v_info, write_normals): fs = [] for info in v_info: info += 1 if not write_normals: s = '%d' % info else: s = '%d//%d' % (info, info) fs.append(s) self.file.write('f %s \n' % ' '.join(fs))
[docs] def write(self, vertices, faces, normals=None, comment=''): """ :param vertices:, :param normals: are lists of vectors or ndarrays of shape (n,3) :param faces: A face is a list of 3 vertex indices. Normal indices not supported. Texture uv's not supported. This method does not yet validate the input, so send valid data. """ self.file.write('# %s\n' % comment) for v in vertices: self._write_vector('v', v) self.file.write('\n') if normals is not None: for v in normals: self._write_vector('vn', v) self.file.write('\n') for f in faces: self._write_face(f, normals is not None)