コード例 #1
0
def test_lines(view_type, options_class):
    proj = steno3d.Project()
    lines = steno3d.Line(
        project=proj,
        title='my elem',
        description='my desc',
        mesh=steno3d.Mesh1D(
            vertices=[[i / 3., i / 4, i / 5] for i in range(10)],
            segments=[[i, i + 1] for i in range(9)],
            opts={'view_type': view_type},
        ),
        opts={
            'color': 'red',
            'opacity': 0.5,
        },
    )
    proj.validate()
    view = convert.steno3d_to_view(proj)
    view.validate()
    assert len(view.contents) == 3
    lineset = find(view, spatial.ElementLineSet)
    defaults = lineset.defaults.serialize()
    assert defaults['__class__'] == options_class
    assert defaults['color']['value'] == '#FF0000'
    assert defaults['opacity']['value'] == 0.5
    assert lineset.name == 'my elem'
    assert lineset.description == 'my desc'
コード例 #2
0
def test_texture():
    try:
        dirname, _ = os.path.split(os.path.abspath(__file__))
        png_file = os.path.sep.join(dirname.split(os.path.sep) + ['temp.png'])
        s = ['110010010011', '101011010100', '110010110101', '100010010011']
        s = [[int(v) for v in val] for val in s]
        f = open(png_file, 'wb')
        w = png.Writer(len(s[0]), len(s), greyscale=True, bitdepth=16)
        w.write(f, s)
        f.close()

        proj = steno3d.Project()

        surf = steno3d.Surface(
            project=proj,
            mesh=steno3d.Mesh2DGrid(
                h1=[1., 1., 1., 1., 1.],
                h2=[1., 1., 1., 1., 1.],
            ),
            textures=[
                steno3d.Texture2DImage(
                    O=[0., 0, 0],
                    U=[5., 0, 0],
                    V=[0., 5, 0],
                    image=png_file,
                )
            ],
        )
        proj.validate()
        view = convert.steno3d_to_view(proj)
        view.validate()
        assert len(view.contents) == 3

    finally:
        os.remove(png_file)
コード例 #3
0
    def plot3D_steno(self, block,  project, plot=True, **kwargs):
        import steno3d
        import numpy as np
        steno3d.login()

        description = kwargs.get('description', 'Nothing')
        proj = steno3d.Project(
            title=project,
            description=description,
            public=True,
        )

        mesh = steno3d.Mesh3DGrid(h1=np.ones(self._data.resolution[0]) * (self._data.extent[0] - self._data.extent[1]) /
                                                                         (self._data.resolution[0] - 1),
                                  h2=np.ones(self._data.resolution[1]) * (self._data.extent[2] - self._data.extent[3]) /
                                                                         (self._data.resolution[1] - 1),
                                  h3=np.ones(self._data.resolution[2]) * (self._data.extent[4] - self._data.extent[5]) /
                                                                         (self._data.resolution[2] - 1))

        data = steno3d.DataArray(
            title='Lithologies',
            array=block)

        vol = steno3d.Volume(project=proj, mesh=mesh, data=[dict(location='CC', data=data)])
        vol.upload()

        if plot:
            return vol.plot()
コード例 #4
0
def test_volume_grid():
    proj = steno3d.Project()
    vol = steno3d.Volume(
        project=proj,
        title='my elem',
        description='my desc',
        mesh=steno3d.Mesh3DGrid(
            h1=[1., 1., 1., 1., 1.],
            h2=[1., 1., 1., 1., 1.],
            h3=[1., 1., 1., 1., 1.],
            opts={'wireframe': True},
        ),
        opts={
            'color': 'red',
            'opacity': 0.5,
        },
    )
    proj.validate()
    view = convert.steno3d_to_view(proj)
    view.validate()
    assert len(view.contents) == 1
    vol = find(view, spatial.ElementVolumeGrid)
    defaults = vol.defaults.serialize()
    assert defaults['__class__'] == 'OptionsBlockModel'
    assert defaults['color']['value'] == '#FF0000'
    assert defaults['opacity']['value'] == 0.5
    assert defaults['wireframe']['active']
    assert vol.name == 'my elem'
    assert vol.description == 'my desc'
コード例 #5
0
def test_project():
    proj = steno3d.Project(
        title='my proj',
        description='my desc',
    )
    proj.validate()
    view = convert.steno3d_to_view(proj)
    view.validate()
    assert view.name == 'my proj'
    assert view.description == 'my desc'
    assert view.contents == []
コード例 #6
0
    def test_surface_mesh2dgrid(self):
        myh1 = [5., 4., 3., 2., 1., 1., 1., 1., 2., 3., 4., 5.]
        myh2 = [1., 1., 1., 1., 2., 3., 4., 5.]

        # def f():
        P = steno3d.Project()
        S = steno3d.Surface(
            P,
            mesh=dict(h1=myh1, h2=myh2, opts={"wireframe": True}),
            opts={
                "opacity": 0.3,
                "color": "red"
            },
        )

        # self.assertRaises(KeyError, f)

        # This should be ok
        P = steno3d.Project()
        M = steno3d.Mesh2DGrid(h1=myh1, h2=myh2, opts={"wireframe": True})
        S = steno3d.Surface(P, mesh=M, opts={"opacity": 0.3, "color": "red"})

        S.validate()

        myZ = np.random.rand(10)
        S.mesh.Z = myZ
        self.assertRaises(ValueError, lambda: S.validate())

        myZ = np.random.rand((len(myh1) + 1) * (len(myh2) + 1))
        S.mesh.Z = myZ
        S.validate()

        self.assertRaises(ValueError,
                          setattr(S, 'x0', [[0., 0., 0.], [1., 1., 1.]]))

        assert len(S._dirty) == 3
        S._mark_clean()
        assert len(S._dirty) == 0
コード例 #7
0
 def test_teapot(self):
     teapot = Teapot.fetch_data(filename='teapot.json',
                                verbose=False,
                                directory='.')
     with open(teapot) as f:
         data = json.loads(f.read())
     P = steno3d.Project()
     S = steno3d.Surface(
         project=P,
         mesh=dict(vertices=data['vertices'],
                   triangles=data['triangles'],
                   opts={"wireframe": True}),
         opts={
             "opacity": 0.3,
             "color": "red"
         },
     )
     S.validate()
コード例 #8
0
def test_surfaces():
    proj = steno3d.Project()
    surf_0 = steno3d.Surface(
        project=proj,
        title='my elem',
        description='my desc',
        mesh=steno3d.Mesh2D(
            vertices=[[i / 3., i / 4, i / 5] for i in range(10)],
            triangles=[[i, i + 1, i + 2] for i in range(8)],
            opts={'wireframe': True},
        ),
        opts={
            'color': 'red',
            'opacity': 0.5,
        },
    )
    surf_1 = steno3d.Surface(
        project=proj,
        title='my elem',
        description='my desc',
        mesh=steno3d.Mesh2DGrid(
            h1=[1., 1., 1., 1., 1.],
            h2=[1., 1., 1., 1., 1.],
            Z=[1.] * 36,
            opts={'wireframe': True},
        ),
        opts={
            'color': 'red',
            'opacity': 0.5,
        },
    )
    proj.validate()
    view = convert.steno3d_to_view(proj)
    view.validate()
    assert len(view.contents) == 5
    for cls in (spatial.ElementSurface, spatial.ElementSurfaceGrid):
        surface = find(view, cls)
        defaults = surface.defaults.serialize()
        assert defaults['__class__'] == 'OptionsSurface'
        assert defaults['color']['value'] == '#FF0000'
        assert defaults['opacity']['value'] == 0.5
        assert defaults['wireframe']['active']
        assert surface.name == 'my elem'
        assert surface.description == 'my desc'
コード例 #9
0
 def test_proj_resource_link(self):
     t = np.array([[0, 1, 2], [1, 2, 3], [0, 1, 4], [0, 2, 4], [1, 3, 4],
                   [2, 3, 4]])
     v = np.array([[0, 0, 0], [0, 0, -1], [0, 1, 0], [0, 1, 1], [1, .5,
                                                                 .5]])
     m = steno3d.Mesh2D(triangles=t, vertices=v)
     p0 = steno3d.Project()
     p1 = steno3d.Project()
     p2 = steno3d.Project()
     s0 = steno3d.Surface(p0, mesh=m)
     assert len(s0.project) == 1
     assert len(p0.resources) == 1
     s0.project = [p0, p0, p2, p1, p2]
     assert len(s0.project) == 3, '{}'.format(s0.project)
     assert s0.project[0] is p0
     assert s0.project[1] is p2
     assert s0.project[2] is p1
     assert len(p0.resources) == 1
     assert len(p1.resources) == 1
     assert len(p2.resources) == 1
     s1 = steno3d.Surface(p1, mesh=m)
     assert len(s1.project) == 1
     assert len(p1.resources) == 2
     s2 = steno3d.Surface(p1, mesh=m)
     assert len(p1.resources) == 3
     s2.project += [p1]
     assert len(p1.resources) == 3
     assert len(s2.project) == 1
     p2.resources += [s0, s1, s1, s1]
     assert len(p2.resources) == 2
     assert p2.resources[0] is s0
     assert p2.resources[1] is s1
     assert len(s0.project) == 3
     assert len(s1.project) == 2
     p0.validate()
     p1.validate()
     p2.validate()
     p3 = steno3d.Project()
     p4 = steno3d.Project()
     p5 = steno3d.Project()
     p3.resources = [s0, s1, s2]
     p4.resources = p4.resources + p3.resources
     p5.resources += p3.resources
     p3.validate()
     p4.validate()
     p5.validate()
コード例 #10
0
ファイル: test_stl.py プロジェクト: Geostatistic/steno3d-stl
    def test_ascii(self):
        ascii_file = path.sep.join(self.assets + ['ascii.stl'])
        parser = steno3d.parsers.stl(ascii_file)
        projs = parser.parse()
        assert len(projs) == 1
        proj, = projs
        assert len(proj.resources) == 1
        assert isinstance(proj.resources[0], steno3d.Surface)
        assert proj.resources[0].mesh.nN == 4
        assert proj.resources[0].mesh.nC == 4

        parser = steno3d.parsers.AllParsers(ascii_file)
        projs = parser.parse()
        assert len(projs) == 1
        proj, = projs
        assert len(proj.resources) == 1
        assert isinstance(proj.resources[0], steno3d.Surface)
        assert proj.resources[0].mesh.nN == 4
        assert proj.resources[0].mesh.nC == 4

        proj = steno3d.Project()
        parser.parse(proj)
        assert len(proj.resources) == 1
コード例 #11
0
    def to_steno3d(self, project=None, as_topo=True):
        """Create a project from GridInfo

        Optional input:
            project: Preexisting Steno3D project to add .grd file components
                     to. If not provided, a new project will be created.
            verbose: Print messages and warnings during file parsing.
                     (default: True)
            as_topo: If True, add data from grid file as topography.
                     Otherwise only add the data as color on a flat surface.
                     (default: True)

        Output:
            Steno3D Project with GridInfo components
        """

        self.validate()

        if project is None:
            project = steno3d.Project(description='From surfer grid file')
        elif not isinstance(project, steno3d.Project):
            raise steno3d.parsers.ParseError('project must be Steno3D Project')

        surf = steno3d.Surface(
            project=project,
            mesh=steno3d.Mesh2DGrid(O=[self.xll, self.yll, 0],
                                    h1=np.ones(self.ncol - 1) * self.xsize,
                                    h2=np.ones(self.nrow - 1) * self.ysize),
            data=[
                dict(location='N',
                     data=steno3d.DataArray(array=self.data.flatten()))
            ])

        if as_topo:
            surf.mesh.Z = self.data.flatten()

        return project
コード例 #12
0
def test_points():
    proj = steno3d.Project()
    pts = steno3d.Point(
        project=proj,
        title='my elem',
        description='my desc',
        mesh=steno3d.Mesh0D(vertices=[[i / 3., i / 4, i / 5]
                                      for i in range(10)], ),
        opts={
            'color': 'red',
            'opacity': 0.5,
        },
    )
    proj.validate()
    view = convert.steno3d_to_view(proj)
    view.validate()
    assert len(view.contents) == 2
    pointset = find(view, spatial.ElementPointSet)
    defaults = pointset.defaults.serialize()
    assert defaults['__class__'] == 'OptionsPoints'
    assert defaults['color']['value'] == '#FF0000'
    assert defaults['opacity']['value'] == 0.5
    assert pointset.name == 'my elem'
    assert pointset.description == 'my desc'
コード例 #13
0
    def parse(self, project=None, verbose=True):
        """function parse

        Parses the .stl file (binary or ASCII) provided at parser
        instantiation into a Steno3D project.

        Optional input:
            project: Preexisting Steno3D project to add .stl file components
                     to. If not provided, a new project will be created.
            verbose: Print messages and warnings during file parsing.
                     (default: True)

        Output:
            tuple containing one Steno3D project with components parsed
            from the .stl file
        """

        warnings = set()

        if project is None:
            project = steno3d.Project(
                description='Project imported from ' + self.file_name
            )
        elif not isinstance(project, steno3d.Project):
            raise steno3d.parsers.ParseError('Only allowed input for parse is '
                                             'optional Steno3D project')

        f = open(self.file_name, 'rb')
        first_line = f.readline().split()
        f.close()
        if len(first_line) > 0 and first_line[0] == b'solid':
            (tris, verts, title) = self._parse_ascii(verbose, warnings)
        else:
            (tris, verts) = self._parse_binary(verbose, warnings)
            title = ''

        if len(tris) == 0 or len(verts) == 0:
            raise steno3d.parsers.ParseError(
                'Invalid file. No triangles or vertices extracted.'
            )
        if np.min(tris) < 0 or np.max(tris) >= len(verts):
            raise steno3d.parsers.ParseError(
                'Invalid surface geometry encountered in parsed file. '
                'Triangle indices must be between 0 and '
                '{}'.format(len(verts)-1)
            )
        steno3d.Surface(
            project=project,
            title=title,
            mesh=steno3d.Mesh2D(
                vertices=verts,
                triangles=tris
            )
        )

        if verbose and len(warnings) > 0:
            print('  If you are interested in contributing to unsupported '
                  'features, please visit\n'
                  '      https://github.com/seequent/steno3d-stl')

        return (project,)
コード例 #14
0
def test_data():
    arr = [float(val) for val in range(25)]
    arr_int = [int(val % 4) for val in range(25)]

    proj = steno3d.Project(title='Mappings proj')

    surf = steno3d.Surface(
        project=proj,
        mesh=steno3d.Mesh2DGrid(
            h1=[1., 1., 1., 1., 1.],
            h2=[1., 1., 1., 1., 1.],
        ),
        data=[
            {
                'location':
                'CC',
                'data':
                steno3d.DataArray(
                    array=arr,
                    colormap=[
                        'red',
                        'blue',
                        'black',
                        'orange',
                        'black',
                        'yellow',
                    ],
                )
            },
            {
                'location':
                'CC',
                'data':
                steno3d.DataDiscrete(array=arr,
                                     colormap=['red', 'blue', 'green'],
                                     end_values=[10., 15])
            },
            {
                'location':
                'CC',
                'data':
                steno3d.DataCategory(array=arr_int,
                                     colormap=[
                                         'yellow',
                                         'black',
                                         'brown',
                                         'green',
                                     ],
                                     categories=[
                                         'yellow!',
                                         'black!!',
                                         'brown!!!',
                                         'green!!!!',
                                     ])
            },
        ],
    )
    proj.validate()
    view = convert.steno3d_to_view(proj)
    view.validate()
    assert len(view.contents) == 12
コード例 #15
0
    def test_surface(self):
        P = steno3d.Project()
        myVerts = np.array([[0., 0, 0], [0, 1, 0], [1, 0, 0]])
        myTriangles = np.array([[0, 1, 2]])

        S = steno3d.Surface(
            project=P,
            mesh=dict(vertices=myVerts,
                      triangles=myTriangles,
                      opts={"wireframe": True}),
            opts={
                "opacity": 0.3,
                "color": "red"
            },
        )
        S.validate()

        # Make sure getattr/setattr working ok
        assert S.mesh is S.mesh
        assert S.mesh.vertices is S.mesh.vertices
        assert S.mesh.triangles is S.mesh.triangles

        # Make sure the shortcuts are working

        # assert S.vertices is S.mesh.vertices
        # assert S.triangles is S.mesh.triangles
        # assert S.vertices is not myVerts
        # assert S.triangles is not myTriangles
        assert np.array_equal(S.mesh.vertices, myVerts)
        assert np.array_equal(S.mesh.triangles, myTriangles)

        # Test options
        # ----Surface
        # --------Color
        assert S.opts.color == (255, 0, 0)
        S.opts.color = 'darkred'

        assert S.opts.opacity == 0.3
        S.opts.opacity = .1
        assert S.opts.opacity == .1
        S.opts = {"opacity": 0.5}
        assert S.opts.opacity == .5
        S.opts = {"color": '#FFF'}
        assert S.opts.opacity == 1

        assert S.mesh.opts.wireframe
        self.assertRaises(ValueError,
                          lambda: setattr(S.mesh.opts, 'wireframe', 'Wires'))
        self.assertRaises(ValueError,
                          lambda: setattr(S.mesh.opts, 'wireframe', 1))
        S.mesh.opts = {"wireframe": False}
        assert not S.mesh.opts.wireframe
        S.mesh.opts.wireframe = True
        assert S.mesh.opts.wireframe

        # Test triangles
        S.triangles = [[0, 0, 0], [1, 1, 1]]
        assert isinstance(S.mesh.triangles, np.ndarray)
        self.assertRaises(ValueError, lambda: setattr(S.mesh, 'triangles', -1))
        self.assertRaises(ValueError,
                          lambda: setattr(S.mesh, 'triangles', [[0, 0]]))
        self.assertRaises(
            ValueError,
            lambda: setattr(S.mesh, 'triangles', [[0, 0, .5], [1, 1, 1]]))
        self.assertRaises(
            ValueError, lambda: setattr(S.mesh, 'triangles', [[0], [0], [0]]))
        self.assertRaises(
            ValueError,
            lambda: setattr(S.mesh, 'triangles', 'Three isosceles, please!'))
        self.assertRaises(
            ValueError,
            lambda: setattr(S.mesh, 'triangles', [[0, 0, 1, 1], [0, 0, 0, 0]]))

        S.mesh.triangles = [[0, 0, -100], [1, 1, 1]]
        self.assertRaises(ValueError, lambda: S.validate())

        S.mesh._p_triangles = -1  # try to fake things out.
        # ensure we also call the validator
        self.assertRaises(ValueError, lambda: S.validate())

        myNewTriangles = np.array([[0, 1, 2], [1, 2, 3], [0, 1, 4], [0, 2, 4],
                                   [1, 3, 4], [2, 3, 4]])
        S.mesh.triangles = myNewTriangles
        self.assertRaises(ValueError, lambda: S.validate())
        assert np.array_equal(S.mesh.triangles, myNewTriangles)

        # Test vertices
        myNewVerts = np.array([[0, 0, 0], [0, 0, -1], [0, 1, 0], [0, 1, 1],
                               [1, .5, .5]])
        S.mesh.vertices = myNewVerts
        self.assertRaises(ValueError, lambda: setattr(S.mesh, 'vertices', -1))
        self.assertRaises(ValueError,
                          lambda: setattr(S.mesh, 'vertices', [[0, 0]]))
        self.assertRaises(ValueError,
                          lambda: setattr(S.mesh, 'vertices', [[0], [0], [0]]))
        self.assertRaises(
            ValueError,
            lambda: setattr(S.mesh, 'vertices', 'Just a few random points.'))
        self.assertRaises(
            ValueError,
            lambda: setattr(S.mesh, 'vertices', [[0, 0, 1, 1], [0, 0, 0, 0]]))

        # Other Constructor tests
        S = steno3d.Surface(P)
        self.assertRaises(ValueError, lambda: S.validate())
        S.mesh = S.mesh
        self.assertRaises(ValueError, lambda: S.validate())
        S.mesh.vertices = myVerts
        S.mesh.triangles = myTriangles
        S.validate()
        MOpts = dict(wireframe=True)
        M = steno3d.Mesh2D(vertices=myNewVerts,
                           triangles=myNewTriangles,
                           opts=MOpts)
        SOpts = dict(opacity=.5, color=[100, 100, 100])
        S = steno3d.Surface(P, mesh=M, opts=SOpts)

        assert S.mesh.vertices is not myNewVerts
        assert S.mesh.triangles is not myNewTriangles
        assert np.array_equal(S.mesh.vertices, myNewVerts)
        assert np.array_equal(S.mesh.triangles, myNewTriangles)
        assert S.opts.opacity == .5
        assert S.opts.color == (100, 100, 100)
        assert S.mesh.opts.wireframe

        # Test Data
        # This needs to be updated once data is updated
        S.mesh.triangles = myTriangles
        S.mesh.vertices = myVerts
        S.data = {'data': [0], 'location': 'face'}
        assert type(S.data) is list
        S.data = [{'data': [0], 'location': 'face'}]
        assert type(S.data) is list
        d0 = S.data[0]
        # copying the list and appending to it (not the same list!)
        S.data.append({'data': [2], 'location': 'vertex'})
        assert len(S.data) == 1
        # iadd is resetting the list and doing validation
        S.data += [{'data': [2], 'location': 'vertex'}]
        assert S.data[0] is d0
        from steno3d.surface import _SurfaceBinder
        assert isinstance(S.data[1], _SurfaceBinder)
        # surface.data[1] is the incorrect length
        self.assertRaises(Exception, lambda: S.validate())
        S.data[1].data = [0, 1, 2]
        assert S.data[1].data.title == ''
        assert S.data[1].data.description == ''
        assert np.all(S.data[1].data.array == [0, 1, 2])
        S.validate()
コード例 #16
0
    def parse(self, project=None, verbose=True):
        """function parse

        Parses the .obj file provided at parser instantiation into a
        Steno3D project.

        Optional input:
            project: Preexisting Steno3D project to add .obj file components
                     to. If not provided, a new project will be created.
            verbose: Print messages and warnings during file parsing.
                     (default: True)

        Output:
            tuple containing one Steno3D project with components parsed
            from the .obj file
        """
        if project is None:
            project = steno3d.Project(description='Project imported from ' +
                                      self.file_name)
        elif not isinstance(project, steno3d.Project):
            raise steno3d.parsers.ParseError('Only allowed input for parse is '
                                             'optional Steno3D project')

        warnings = set()
        vertices = []
        points = []
        triangles = []
        segments = []

        with open(self.file_name, 'r') as f:
            if verbose:
                print('Parsing file: {}'.format(self.file_name))
            ext_line = []
            for line in f:
                try:
                    line = ext_line + line.split()
                    # Check for comment
                    if len(line) == 0 or line[0] == '#':
                        continue

                    # Check for line continuation
                    if line[-1] == '\\':
                        ext_line = line[:-1]
                        continue
                    else:
                        ext_line = []

                    # Vertex
                    if line[0] == 'v':
                        if len(line) == 5:
                            self._warn('Unsupported feature: Vertex Weight',
                                       warnings, verbose)
                        vertices.append([float(v) for v in line[1:4]])
                        continue

                    # Surface
                    if line[0] == 'f':
                        tri = [int(v.split('/')[0]) for v in line[1:]]
                        tri = [
                            v - 1 if v > 0 else v + len(vertices) for v in tri
                        ]
                        for i in range(len(tri) - 2):
                            triangles.append([tri[0], tri[i + 1], tri[i + 2]])
                        continue

                    # Line
                    if line[0] == 'l':
                        seg = [int(v.split('/')[0]) for v in line[1:]]
                        seg = [
                            v - 1 if v > 0 else v + len(vertices) for v in seg
                        ]
                        for i in range(len(seg) - 1):
                            segments.append([seg[i], seg[i + 1]])
                        continue

                    # Point
                    if line[0] == 'p':
                        pnt = [int(v) for v in line[1:]]
                        pnt = [
                            v - 1 if v > 0 else v + len(vertices) for v in pnt
                        ]
                        for p in pnt:
                            points.append(vertices[p])
                        continue

                    # Unsupported features
                    for feat in self.unsupported:
                        if line[0] in self.unsupported[feat]:
                            self._warn('Unsupported feature: {}'.format(feat),
                                       warnings, verbose)
                            break
                    else:
                        self._warn(
                            'Skipping unknown keyword: {}'.format(line[0]),
                            warnings, verbose)

                except:
                    raise steno3d.parsers.ParseError(
                        'Bad file line encountered while '
                        'parsing {}:\n{}'.format(self.file_name,
                                                 ' '.join(line)))

        if len(points) == 0 and len(segments) == 0 and len(triangles) == 0:
            raise steno3d.parsers.ParseError(
                'No valid geometry extracted while parsing {}.\nPlease '
                'ensure this file has vertices (v) and points (p), lines (l), '
                'or faces (f).\nOther features are currently unsupported. If '
                'you would like to contribute, visit\n'
                'https://github.com/seequent/steno3d-obj'.format(
                    self.file_name))

        if len(segments) > 0:
            if np.min(segments) < 0 or np.max(segments) >= len(vertices):
                raise steno3d.parsers.ParseError(
                    'Invalid line geometry encountered in parsed file. '
                    'Segment indices must be between 0 and '
                    '{}'.format(len(vertices) - 1))
            steno3d.Line(project=project,
                         mesh=steno3d.Mesh1D(segments=segments,
                                             vertices=vertices))

        if len(triangles) > 0:
            if np.min(triangles) < 0 or np.max(triangles) >= len(vertices):
                raise steno3d.parsers.ParseError(
                    'Invalid surface geometry encountered in parsed file. '
                    'Triangle indices must be between 0 and '
                    '{}'.format(len(vertices) - 1))
            steno3d.Surface(project=project,
                            mesh=steno3d.Mesh2D(triangles=triangles,
                                                vertices=vertices))

        if len(points) > 0:
            steno3d.Point(project=project,
                          mesh=steno3d.Mesh0D(vertices=points))

        if verbose and len(warnings) > 0:
            print('  If you are interested in contributing to unsupported '
                  'features, please visit\n'
                  '      https://github.com/seequent/steno3d-obj')

        return (project, )