Ejemplo n.º 1
0
    def test_split(self):

        for fn in ['2D/ChuteHolderPrint.DXF',
                   '2D/tray-easy1.dxf',
                   '2D/sliding-base.dxf',
                   '2D/wrench.dxf',
                   '2D/spline_1.dxf']:
            p = g.get_mesh(fn)

            # make sure something was loaded
            assert len(p.root) > 0

            # split by connected
            split = p.split()

            # make sure split parts have same area as source
            assert g.np.isclose(p.area, sum(i.area for i in split))
            # make sure concatenation doesn't break that
            assert g.np.isclose(p.area, g.np.sum(split).area)

            # check that cache didn't screw things up
            for s in split:
                assert len(s.root) == 1
                assert len(s.path_valid) == len(s.paths)
                assert len(s.paths) == len(s.discrete)
                assert s.path_valid.sum() == len(s.polygons_closed)
                g.check_path2D(s)
Ejemplo n.º 2
0
    def test_section(self):
        mesh = g.get_mesh('tube.obj')

        # check the CCW correctness with a normal in both directions
        for sign in [1.0, -1.0]:
            # get a cross section of the tube
            section = mesh.section(plane_origin=mesh.center_mass,
                                   plane_normal=[0.0, sign, 0.0])

            # Path3D -> Path2D
            planar, T = section.to_planar()

            # tube should have one closed polygon
            assert len(planar.polygons_full) == 1
            polygon = planar.polygons_full[0]
            # closed polygon should have one interior
            assert len(polygon.interiors) == 1

            # the exterior SHOULD be counterclockwise
            assert g.trimesh.path.util.is_ccw(
                polygon.exterior.coords)
            # the interior should NOT be counterclockwise
            assert not g.trimesh.path.util.is_ccw(
                polygon.interiors[0].coords)

            # should be a valid Path2D
            g.check_path2D(planar)
Ejemplo n.º 3
0
    def test_section(self):
        mesh = g.get_mesh('tube.obj')

        # check the CCW correctness with a normal in both directions
        for sign in [1.0, -1.0]:
            # get a cross section of the tube
            section = mesh.section(plane_origin=mesh.center_mass,
                                   plane_normal=[0.0, sign, 0.0])

            # Path3D -> Path2D
            planar, T = section.to_planar()

            # tube should have one closed polygon
            assert len(planar.polygons_full) == 1
            polygon = planar.polygons_full[0]
            # closed polygon should have one interior
            assert len(polygon.interiors) == 1

            # the exterior SHOULD be counterclockwise
            assert g.trimesh.path.util.is_ccw(
                polygon.exterior.coords)
            # the interior should NOT be counterclockwise
            assert not g.trimesh.path.util.is_ccw(
                polygon.interiors[0].coords)

            # should be a valid Path2D
            g.check_path2D(planar)
Ejemplo n.º 4
0
    def test_split(self):

        for fn in ['2D/ChuteHolderPrint.DXF',
                   '2D/tray-easy1.dxf',
                   '2D/sliding-base.dxf',
                   '2D/wrench.dxf',
                   '2D/spline_1.dxf']:
            p = g.get_mesh(fn)

            # make sure something was loaded
            assert len(p.root) > 0

            # split by connected
            split = p.split()

            # make sure split parts have same area as source
            assert g.np.isclose(p.area, sum(i.area for i in split))
            # make sure concatenation doesn't break that
            assert g.np.isclose(p.area, g.np.sum(split).area)

            # check that cache didn't screw things up
            for s in split:
                assert len(s.root) == 1
                assert len(s.path_valid) == len(s.paths)
                assert len(s.paths) == len(s.discrete)
                assert s.path_valid.sum() == len(s.polygons_closed)
                g.check_path2D(s)
Ejemplo n.º 5
0
    def test_circle_pattern(self):
        from trimesh.path import creation
        pattern = creation.circle_pattern(pattern_radius=1.0,
                                          circle_radius=0.1,
                                          count=4)
        assert len(pattern.entities) == 4
        assert len(pattern.polygons_closed) == 4
        assert len(pattern.polygons_full) == 4

        # should be a valid Path2D
        g.check_path2D(pattern)
Ejemplo n.º 6
0
    def test_circle_pattern(self):
        from trimesh.path import creation
        pattern = creation.circle_pattern(pattern_radius=1.0,
                                          circle_radius=0.1,
                                          count=4)
        assert len(pattern.entities) == 4
        assert len(pattern.polygons_closed) == 4
        assert len(pattern.polygons_full) == 4

        # should be a valid Path2D
        g.check_path2D(pattern)
Ejemplo n.º 7
0
    def test_circle(self):
        from trimesh.path import creation
        circle = creation.circle(radius=1.0, center=(1.0, 1.0))

        # it's a discrete circle
        assert g.np.isclose(circle.area, g.np.pi, rtol=0.01)
        # should be centered at 0
        assert g.np.allclose(circle.polygons_full[0].centroid, [1.0, 1.0],
                             atol=1e-3)
        assert len(circle.entities) == 1
        assert len(circle.polygons_closed) == 1
        assert len(circle.polygons_full) == 1

        # should be a valid Path2D
        g.check_path2D(circle)
Ejemplo n.º 8
0
    def test_multiroot(self):
        """
        Test a Path2D object containing polygons nested in
        the interiors of other polygons.
        """
        inner = g.trimesh.creation.annulus(r_min=.5, r_max=0.6, height=1.0)
        outer = g.trimesh.creation.annulus(r_min=.9, r_max=1.0, height=1.0)
        m = inner + outer

        s = m.section(plane_normal=[0, 0, 1], plane_origin=[0, 0, 0])
        p = s.to_planar()[0]

        assert len(p.polygons_closed) == 4
        assert len(p.polygons_full) == 2
        assert len(p.root) == 2
        g.check_path2D(p)
Ejemplo n.º 9
0
    def test_multiroot(self):
        """
        Test a Path2D object containing polygons nested in
        the interiors of other polygons.
        """
        inner = g.trimesh.creation.annulus(r_min=.5, r_max=.6)
        outer = g.trimesh.creation.annulus(r_min=.9, r_max=1.0)
        m = inner + outer

        s = m.section(plane_normal=[0, 0, 1],
                      plane_origin=[0, 0, 0])
        p = s.to_planar()[0]

        assert len(p.polygons_closed) == 4
        assert len(p.polygons_full) == 2
        assert len(p.root) == 2
        g.check_path2D(p)
Ejemplo n.º 10
0
    def test_circle(self):
        from trimesh.path import creation
        circle = creation.circle(radius=1.0)

        # it's a discrete circle
        assert g.np.isclose(circle.area, g.np.pi, rtol=0.01)
        # should be centered at 0
        assert g.np.allclose(
            circle.polygons_full[0].centroid, [
                0.0, 0.0], atol=1e-3)

        assert len(circle.entities) == 1
        assert len(circle.polygons_closed) == 1
        assert len(circle.polygons_full) == 1

        # should be a valid Path2D
        g.check_path2D(circle)
Ejemplo n.º 11
0
    def test_rect(self):
        from trimesh.path import creation

        # create a single rectangle
        pattern = creation.rectangle([[0, 0], [2, 3]])
        assert len(pattern.entities) == 1
        assert len(pattern.polygons_closed) == 1
        assert len(pattern.polygons_full) == 1
        assert g.np.isclose(pattern.area, 6.0)
        # should be a valid Path2D
        g.check_path2D(pattern)

        # make 10 untouching rectangles
        pattern = creation.rectangle(g.np.arange(40).reshape((-1, 2, 2)))
        assert len(pattern.entities) == 10
        assert len(pattern.polygons_closed) == 10
        assert len(pattern.polygons_full) == 10
        # should be a valid Path2D
        g.check_path2D(pattern)
Ejemplo n.º 12
0
    def test_rect(self):
        from trimesh.path import creation

        # create a single rectangle
        pattern = creation.rectangle([[0, 0], [2, 3]])
        assert len(pattern.entities) == 1
        assert len(pattern.polygons_closed) == 1
        assert len(pattern.polygons_full) == 1
        assert g.np.isclose(pattern.area, 6.0)
        # should be a valid Path2D
        g.check_path2D(pattern)

        # make 10 untouching rectangles
        pattern = creation.rectangle(
            g.np.arange(40).reshape((-1, 2, 2)))
        assert len(pattern.entities) == 10
        assert len(pattern.polygons_closed) == 10
        assert len(pattern.polygons_full) == 10
        # should be a valid Path2D
        g.check_path2D(pattern)
Ejemplo n.º 13
0
    def test_discrete(self):
        for d in g.get_2D():
            # store md5 before requesting passive functions
            md5 = d.md5()

            # make sure various methods return
            # basically the same bounds
            atol = d.scale / 1000
            for dis, pa, pl in zip(d.discrete,
                                   d.paths,
                                   d.polygons_closed):
                # bounds of discrete version of path
                bd = g.np.array([g.np.min(dis, axis=0),
                                 g.np.max(dis, axis=0)])
                # bounds of polygon version of path
                bl = g.np.reshape(pl.bounds, (2, 2))
                # try bounds of included entities from path
                pad = g.np.vstack([d.entities[i].discrete(d.vertices)
                                   for i in pa])
                bp = g.np.array([g.np.min(pad, axis=0),
                                 g.np.max(pad, axis=0)])

                assert g.np.allclose(bd, bl, atol=atol)
                assert g.np.allclose(bl, bp, atol=atol)

            # run some checks
            g.check_path2D(d)

            # copying shouldn't touch original file
            copied = d.copy()

            # these operations shouldn't have mutated anything!
            assert d.md5() == md5

            # copy should have saved the metadata
            assert set(copied.metadata.keys()) == set(d.metadata.keys())

            # file_name should be populated, and if we have a DXF file
            # the layer field should be populated with layer names
            if d.metadata['file_name'][-3:] == 'dxf':
                assert len(d.layers) == len(d.entities)

            for path in d.paths:
                verts = d.discretize_path(path)
                dists = g.np.sum((g.np.diff(verts, axis=0))**2, axis=1)**.5

                if not g.np.all(dists > g.tol_path.zero):
                    raise ValueError('{} had zero distance in discrete!',
                                     d.metadata['file_name'])

                circuit_dist = g.trimesh.util.euclidean(verts[0], verts[-1])
                circuit_test = circuit_dist < g.tol_path.merge
                if not circuit_test:
                    g.log.error('On file %s First and last vertex distance %f',
                                d.metadata['file_name'],
                                circuit_dist)
                assert circuit_test

                is_ccw = g.trimesh.path.util.is_ccw(verts)
                if not is_ccw:
                    g.log.error('discrete %s not ccw!',
                                d.metadata['file_name'])

            for i in range(len(d.paths)):
                assert d.polygons_closed[i].is_valid
                assert d.polygons_closed[i].area > g.tol_path.zero
            export_dict = d.export(file_type='dict')
            to_dict = d.to_dict()
            assert isinstance(to_dict, dict)
            assert isinstance(export_dict, dict)
            assert len(to_dict) == len(export_dict)

            export_svg = d.export(file_type='svg')  # NOQA
            simple = d.simplify()  # NOQA
            split = d.split()
            g.log.info('Split %s into %d bodies, checking identifiers',
                       d.metadata['file_name'],
                       len(split))
            for body in split:
                body.identifier

            if len(d.root) == 1:
                d.apply_obb()

            # store the X values of bounds
            ori = d.bounds.copy()
            # apply a translation
            d.apply_translation([10, 0])
            # X should have translated by 10.0
            assert g.np.allclose(d.bounds[:, 0] - 10, ori[:, 0])
            # Y should not have moved
            assert g.np.allclose(d.bounds[:, 1], ori[:, 1])

            if len(d.polygons_full) > 0 and len(d.vertices) < 150:
                g.log.info('Checking medial axis on %s',
                           d.metadata['file_name'])
                m = d.medial_axis()
                assert len(m.entities) > 0

            # shouldn't crash
            d.fill_gaps()

            # transform to first quadrant
            d.rezero()
            # run process manually
            d.process()
Ejemplo n.º 14
0
    def test_discrete(self):

        for d in g.get_2D():
            # store md5 before requesting passive functions
            md5 = d.md5()

            # make sure various methods return
            # basically the same bounds
            atol = d.scale / 1000
            for dis, pa, pl in zip(d.discrete,
                                   d.paths,
                                   d.polygons_closed):
                # bounds of discrete version of path
                bd = g.np.array([g.np.min(dis, axis=0),
                                 g.np.max(dis, axis=0)])
                # bounds of polygon version of path
                bl = g.np.reshape(pl.bounds, (2, 2))
                # try bounds of included entities from path
                pad = g.np.vstack([d.entities[i].discrete(d.vertices)
                                   for i in pa])
                bp = g.np.array([g.np.min(pad, axis=0),
                                 g.np.max(pad, axis=0)])

                assert g.np.allclose(bd, bl, atol=atol)
                assert g.np.allclose(bl, bp, atol=atol)

            # run some checks
            g.check_path2D(d)

            # copying shouldn't touch original file
            copied = d.copy()

            # these operations shouldn't have mutated anything!
            assert d.md5() == md5

            # copy should have saved the metadata
            assert set(copied.metadata.keys()) == set(d.metadata.keys())

            # file_name should be populated, and if we have a DXF file
            # the layer field should be populated with layer names
            if d.metadata['file_name'][-3:] == 'dxf':
                assert len(d.layers) == len(d.entities)

            for path in d.paths:
                verts = d.discretize_path(path)
                dists = g.np.sum((g.np.diff(verts, axis=0))**2, axis=1)**.5

                if not g.np.all(dists > g.tol_path.zero):
                    raise ValueError('{} had zero distance in discrete!',
                                     d.metadata['file_name'])

                circuit_dist = g.trimesh.util.euclidean(verts[0], verts[-1])
                circuit_test = circuit_dist < g.tol_path.merge
                if not circuit_test:
                    g.log.error('On file %s First and last vertex distance %f',
                                d.metadata['file_name'],
                                circuit_dist)
                assert circuit_test

                is_ccw = g.trimesh.path.util.is_ccw(verts)
                if not is_ccw:
                    g.log.error('discrete %s not ccw!',
                                d.metadata['file_name'])

            for i in range(len(d.paths)):
                assert d.polygons_closed[i].is_valid
                assert d.polygons_closed[i].area > g.tol_path.zero
            export_dict = d.export(file_type='dict')
            to_dict = d.to_dict()
            assert isinstance(to_dict, dict)
            assert isinstance(export_dict, dict)
            assert len(to_dict) == len(export_dict)

            export_svg = d.export(file_type='svg')  # NOQA
            simple = d.simplify()  # NOQA
            split = d.split()
            g.log.info('Split %s into %d bodies, checking identifiers',
                       d.metadata['file_name'],
                       len(split))
            for body in split:
                body.identifier

            if len(d.root) == 1:
                d.apply_obb()

            # store the X values of bounds
            ori = d.bounds.copy()
            # apply a translation
            d.apply_translation([10, 0])
            # X should have translated by 10.0
            assert g.np.allclose(d.bounds[:, 0] - 10, ori[:, 0])
            # Y should not have moved
            assert g.np.allclose(d.bounds[:, 1], ori[:, 1])

            if len(d.polygons_full) > 0 and len(d.vertices) < 150:
                g.log.info('Checking medial axis on %s',
                           d.metadata['file_name'])
                m = d.medial_axis()
                assert len(m.entities) > 0

            # shouldn't crash
            d.fill_gaps()

            # transform to first quadrant
            d.rezero()
            # run process manually
            d.process()