def test_dxf(self): drawings = g.get_2D() # split drawings into single body parts splits = [] for d in drawings: s = d.split() # check area of split result vs source assert g.np.isclose(sum(i.area for i in s), d.area) splits.append(s) d.export(file_obj='temp.dxf') r = g.trimesh.load('temp.dxf') assert g.np.isclose(r.area, d.area) single = g.np.hstack(splits) for p in single: p.vertices /= p.scale p.export(file_obj='temp.dxf') r = g.trimesh.load('temp.dxf') ratio = abs(p.length - r.length) / p.length if ratio > .01: g.log.error('perimeter ratio on export %s wrong! %f %f %f', p.metadata['file_name'], p.length, r.length, ratio) raise ValueError('perimeter ratio too large ({}) on {}'.format( ratio, p.metadata['file_name']))
def test_discrete(self): for d in g.get_2D(): self.assertTrue(len(d.polygons_closed) == len(d.paths)) # 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) self.assertTrue(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']) # self.assertTrue(is_ccw) for i in range(len(d.paths)): self.assertTrue(d.polygons_closed[i].is_valid) self.assertTrue(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') simple = d.simplify() 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() if 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 # transform to first quadrant d.rezero() # run process manually d.process()
def test_dxf(self): # get a path we can write temp_name = g.tempfile.NamedTemporaryFile(suffix='.dxf', delete=False).name # split drawings into single body parts splits = [] for d in g.get_2D(): s = d.split() # check area of split result vs source assert g.np.isclose(sum(i.area for i in s), d.area) splits.append(s) # export the drawing to the file d.export(file_obj=temp_name) # try using ezdxf as a simple validator # it raises exceptions aggressively if ezdxf is not None: with open(temp_name, 'r') as f: ezdxf.read(f) # export to a string text = d.export(file_type='dxf') # DXF files are always pairs of lines lines = str.splitlines(str(text)) assert (len(lines) % 2) == 0 assert all(len(L.strip()) > 0 for L in lines) # reload the file by name and by stream rc = [ g.trimesh.load(temp_name), g.trimesh.load(g.io_wrap(text), file_type='dxf') ] # compare reloaded with original for r in rc: assert g.np.isclose(r.area, d.area) assert g.np.isclose(r.length, d.length, rtol=1e-4) assert len(r.entities) == len(d.entities) single = g.np.hstack(splits) for p in single: p.vertices /= p.scale # make sure exporting by name works # use tempfile to avoid dumping file in # our working directory p.export(temp_name) r = g.trimesh.load(temp_name) ratio = abs(p.length - r.length) / p.length if ratio > .01: g.log.error('perimeter ratio on export %s wrong! %f %f %f', p.metadata['file_name'], p.length, r.length, ratio) raise ValueError('perimeter ratio too large ({}) on {}'.format( ratio, p.metadata['file_name']))
def test_dxf(self): # get a path we can write temp_name = g.tempfile.NamedTemporaryFile( suffix='.dxf', delete=False).name # split drawings into single body parts splits = [] for d in g.get_2D(): s = d.split() # check area of split result vs source assert g.np.isclose(sum(i.area for i in s), d.area) splits.append(s) # export the drawing to the file d.export(file_obj=temp_name) # export to a string text = d.export(file_type='dxf') # DXF files are always pairs of lines assert (len(str.splitlines(str(text))) % 2) == 0 # reload the file by name and by stream rc = [g.trimesh.load(temp_name), g.trimesh.load(g.io_wrap(text), file_type='dxf')] # compare reloaded with original for r in rc: assert g.np.isclose(r.area, d.area) assert g.np.isclose(r.length, d.length) assert len(r.entities) == len(d.entities) single = g.np.hstack(splits) for p in single: p.vertices /= p.scale # make sure exporting by name works # use tempfile to avoid dumping file in # our working directory p.export(temp_name) r = g.trimesh.load(temp_name) ratio = abs(p.length - r.length) / p.length if ratio > .01: g.log.error('perimeter ratio on export %s wrong! %f %f %f', p.metadata['file_name'], p.length, r.length, ratio) raise ValueError('perimeter ratio too large ({}) on {}'.format( ratio, p.metadata['file_name']))
def test_svg(self): for d in g.get_2D(): # export as svg string exported = d.export('svg') # load the exported SVG stream = g.trimesh.util.wrap_as_stream(exported) loaded = g.trimesh.load(stream, file_type='svg') # we only have line and arc primitives as SVG export and import if all(i.__class__.__name__ in ['Line', 'Arc'] for i in d.entities): # perimeter should stay the same-ish on export/inport assert g.np.isclose(d.length, loaded.length, rtol=.01)
def test_dxf(self): # get a path we can write temp_name = g.tempfile.NamedTemporaryFile( suffix='.dxf', delete=False).name # split drawings into single body parts splits = [] for d in g.get_2D(): s = d.split() # check area of split result vs source assert g.np.isclose(sum(i.area for i in s), d.area) splits.append(s) d.export(file_obj=temp_name) r = g.trimesh.load(temp_name) assert g.np.isclose(r.area, d.area) single = g.np.hstack(splits) for p in single: p.vertices /= p.scale # make sure exporting by name works # use tempfile to avoid dumping file in # our working directory p.export(temp_name) r = g.trimesh.load(temp_name) ratio = abs(p.length - r.length) / p.length if ratio > .01: g.log.error('perimeter ratio on export %s wrong! %f %f %f', p.metadata['file_name'], p.length, r.length, ratio) raise ValueError('perimeter ratio too large ({}) on {}'.format( ratio, p.metadata['file_name']))
def test_svg(self): for d in g.get_2D(): # export as svg string exported = d.export(file_type='svg') # load the exported SVG stream = g.trimesh.util.wrap_as_stream(exported) if g.np.isclose(d.area, 0.0): continue loaded = g.trimesh.load(stream, file_type='svg') # we only have line and arc primitives as SVG # export and import if all(i.__class__.__name__ in ['Line', 'Arc'] for i in d.entities): # perimeter should stay the same-ish # on export/inport assert g.np.isclose(d.length, loaded.length, rtol=.01)
def test_svg(self): for d in g.get_2D(): if g.np.isclose(d.area, 0.0): continue # export and reload the exported SVG loaded = g.trimesh.load(g.trimesh.util.wrap_as_stream( d.export(file_type='svg')), file_type='svg') # we only have line and arc primitives as SVG # export and import if all(i.__class__.__name__ in ['Line', 'Arc'] for i in d.entities): # perimeter should stay the same-ish # on export/import assert g.np.isclose(d.length, loaded.length, rtol=.01) path_str = g.trimesh.path.exchange.svg_io.export_svg( d, return_path=True) assert isinstance(path_str, str) assert len(path_str) > 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()
def setUp(self): self.drawings = g.get_2D() self.single = g.np.hstack([i.split() for i in self.drawings])