120 lines
5.2 KiB
Python
120 lines
5.2 KiB
Python
import json
|
|
import io
|
|
import http.server
|
|
from urllib.parse import quote
|
|
import math
|
|
from collections import Counter
|
|
from pathlib import Path
|
|
import tempfile
|
|
import unittest
|
|
|
|
import r2c
|
|
|
|
|
|
class DrawingReconstructionTests(unittest.TestCase):
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
cls.entities, cls.blocks, cls.raw = r2c.read_dxf(r2c.DEFAULT_DXF)
|
|
cls.model = r2c.extract_model(cls.entities, cls.raw)
|
|
cls.meshes = r2c.make_mesh(cls.model)
|
|
|
|
def test_diameter_and_dimensions_match_both_section_and_table(self):
|
|
m = self.model
|
|
self.assertEqual(m['diameter'], 1000)
|
|
self.assertAlmostEqual(m['length'], 1620)
|
|
self.assertAlmostEqual(m['width'], 1540)
|
|
self.assertAlmostEqual(m['height'], 1486)
|
|
self.assertAlmostEqual(m['axisHeight'], 666)
|
|
self.assertEqual(len(m['table']), 7)
|
|
self.assertEqual([r['D'] for r in m['table']], [700, 800, 900, 1000, 1100, 1200, 1350])
|
|
|
|
def test_inlet_is_rectangular_and_outlet_is_circular(self):
|
|
profiles = self.model['profiles']
|
|
self.assertEqual(profiles[0]['kind'], 'rectangle')
|
|
self.assertAlmostEqual(profiles[0]['halfWidth'] * 2, 1310)
|
|
self.assertAlmostEqual(profiles[0]['top'] + profiles[0]['bottom'], 1205)
|
|
self.assertEqual(profiles[2]['kind'], 'circle')
|
|
self.assertEqual(profiles[2]['radius'], 500)
|
|
self.assertEqual(profiles[2]['x'], 1400)
|
|
self.assertAlmostEqual(profiles[-1]['x'], 1620)
|
|
self.assertAlmostEqual(profiles[-1]['radius'], 615.8)
|
|
|
|
def test_pipe_is_actual_revolved_polyline(self):
|
|
self.assertEqual(self.model['evidence']['pipeProfile'], '195')
|
|
profile = self.model['pipeProfile']
|
|
self.assertAlmostEqual(max(p[0] for p in profile), 2620)
|
|
self.assertAlmostEqual(min(p[1] for p in profile), 500)
|
|
self.assertAlmostEqual(max(p[1] for p in profile), 666)
|
|
|
|
def test_closed_meshes_have_no_boundary_edges(self):
|
|
for name, mesh in self.meshes.items():
|
|
edges = Counter()
|
|
for face in mesh['faces']:
|
|
self.assertEqual(len(set(face)), len(face))
|
|
for a, b in zip(face, face[1:] + face[:1]):
|
|
edges[tuple(sorted((a, b)))] += 1
|
|
self.assertTrue(all(count == 2 for count in edges.values()), name)
|
|
self.assertTrue(all(math.isfinite(n) for p in mesh['vertices'] for n in p))
|
|
|
|
def test_r2c_bounds_match_native_drawing(self):
|
|
pts = self.meshes['r2c']['vertices']
|
|
for axis, expected in enumerate([1620, 1540, 1486]):
|
|
self.assertAlmostEqual(max(p[axis] for p in pts) - min(p[axis] for p in pts), expected, places=5)
|
|
|
|
def test_svg_preserves_curves_sections_and_korean_text(self):
|
|
svg, omitted = r2c.drawing_svg(self.entities, self.blocks)
|
|
self.assertIn('단면 A-A', svg)
|
|
self.assertIn('단면 B-B', svg)
|
|
self.assertIn('1,620', svg)
|
|
self.assertNotIn('%%C', svg)
|
|
self.assertGreater(svg.count('<polyline'), 800)
|
|
self.assertIn('HATCH', omitted)
|
|
|
|
def test_static_package_has_visible_geometry_without_javascript(self):
|
|
with tempfile.TemporaryDirectory() as directory:
|
|
m = r2c.build(output=directory, update_entry=False)
|
|
out = Path(directory)
|
|
source = (out / 'index.html').read_text()
|
|
self.assertNotIn('__INITIAL_SCENE__', source)
|
|
self.assertNotIn('__MODEL_JSON__', source)
|
|
self.assertNotIn('__DRAWING_SVG__', source)
|
|
before_script = source.split('<script')[0]
|
|
self.assertGreater(before_script.count('<polygon'), 900)
|
|
self.assertTrue((out / 'drawing' / r2c.DEFAULT_DXF.name).is_file())
|
|
self.assertEqual(json.loads((out / 'model.json').read_text())['sha256'], m['sha256'])
|
|
self.assertTrue((out / 'model.obj').read_text().startswith('# R2C'))
|
|
|
|
def test_web_handler_serves_generated_files_only(self):
|
|
class Handler(http.server.SimpleHTTPRequestHandler):
|
|
def log_message(self, *args):
|
|
pass
|
|
|
|
with tempfile.TemporaryDirectory() as directory:
|
|
r2c.build(output=directory, update_entry=False)
|
|
for path, status, content in [
|
|
('/index.html', b'200 OK', b'<polygon'),
|
|
('/model.obj', b'200 OK', b'# R2C'),
|
|
('/drawing/' + quote(r2c.DEFAULT_DXF.name), b'200 OK', b'SECTION'),
|
|
('/.git/config', b'404', b'File not found'),
|
|
]:
|
|
handler = object.__new__(Handler)
|
|
handler.directory = directory
|
|
handler.path = path
|
|
handler.command = 'GET'
|
|
handler.request_version = 'HTTP/1.1'
|
|
handler.requestline = 'GET ' + path + ' HTTP/1.1'
|
|
handler.headers = {}
|
|
handler.wfile = io.BytesIO()
|
|
handler.do_GET()
|
|
response = handler.wfile.getvalue()
|
|
self.assertIn(status, response.split(b'\r\n')[0])
|
|
self.assertIn(content, response)
|
|
|
|
def test_unrelated_drawing_does_not_produce_a_guessed_model(self):
|
|
with self.assertRaisesRegex(ValueError, '변화치수표'):
|
|
r2c.extract_model([], b'')
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|