refactor: 전체 코드 정리, 중복 로직 헬퍼 공통화, 미사용 임포트/변수 제거 및 리소스 정리
This commit is contained in:
1 parent
af65700afd
commit
3cc9afeac8
5 files changed
+45
-50
No files matched your search
@@ -1,5 +1,4 @@
|
|||||||
import os
|
import os
|
||||||
import json
|
|
||||||
import tempfile
|
import tempfile
|
||||||
from flask import Flask, request, jsonify, send_file, Response
|
from flask import Flask, request, jsonify, send_file, Response
|
||||||
from flask_cors import CORS
|
from flask_cors import CORS
|
||||||
@@ -17,6 +16,27 @@ current_drawing_data = None
|
|||||||
current_model_data = None
|
current_model_data = None
|
||||||
|
|
||||||
|
|
||||||
|
def _resolve_classification(drawing_name, manual_type=None):
|
||||||
|
"""도면명 기반 분류 및 사용자 수동 오버라이드 객체 생성 헬퍼"""
|
||||||
|
res = cad_parser.classify_drawing_by_name(drawing_name)
|
||||||
|
selected_type = manual_type if manual_type in ('GENERAL', 'REBAR') else res['auto_type']
|
||||||
|
label_map = {
|
||||||
|
'GENERAL': '일반도',
|
||||||
|
'REBAR': '배근도/구조도',
|
||||||
|
'UNCLASSIFIED': '미분류 (수동 선택 필요)'
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
'autoType': res['auto_type'],
|
||||||
|
'autoLabel': res['auto_label'],
|
||||||
|
'matchedKeyword': res['matched_keyword'],
|
||||||
|
'reason': res['reason'],
|
||||||
|
'needsManualSelection': res['needs_manual_selection'],
|
||||||
|
'selectedType': selected_type,
|
||||||
|
'selectedLabel': label_map.get(selected_type, res['auto_label']),
|
||||||
|
'isManualOverride': bool(manual_type and manual_type != res['auto_type'])
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
def index():
|
def index():
|
||||||
return send_file('index.html')
|
return send_file('index.html')
|
||||||
@@ -62,24 +82,7 @@ def api_classify():
|
|||||||
drawing_name = body.get('drawingName', '')
|
drawing_name = body.get('drawingName', '')
|
||||||
manual_type = body.get('manualType') # Optional: 'GENERAL' or 'REBAR'
|
manual_type = body.get('manualType') # Optional: 'GENERAL' or 'REBAR'
|
||||||
|
|
||||||
res = cad_parser.classify_drawing_by_name(drawing_name)
|
classification_obj = _resolve_classification(drawing_name, manual_type)
|
||||||
selected_type = manual_type if manual_type in ('GENERAL', 'REBAR') else res['auto_type']
|
|
||||||
label_map = {
|
|
||||||
'GENERAL': '일반도',
|
|
||||||
'REBAR': '배근도/구조도',
|
|
||||||
'UNCLASSIFIED': '미분류 (수동 선택 필요)'
|
|
||||||
}
|
|
||||||
|
|
||||||
classification_obj = {
|
|
||||||
'autoType': res['auto_type'],
|
|
||||||
'autoLabel': res['auto_label'],
|
|
||||||
'matchedKeyword': res['matched_keyword'],
|
|
||||||
'reason': res['reason'],
|
|
||||||
'needsManualSelection': res['needs_manual_selection'],
|
|
||||||
'selectedType': selected_type,
|
|
||||||
'selectedLabel': label_map.get(selected_type, res['auto_label']),
|
|
||||||
'isManualOverride': bool(manual_type and manual_type != res['auto_type'])
|
|
||||||
}
|
|
||||||
|
|
||||||
# Update active drawing classification in memory and regenerate 3D model
|
# Update active drawing classification in memory and regenerate 3D model
|
||||||
for d in current_drawings_list:
|
for d in current_drawings_list:
|
||||||
@@ -135,12 +138,19 @@ def api_upload():
|
|||||||
|
|
||||||
# 2. Parse each uploaded DWG file
|
# 2. Parse each uploaded DWG file
|
||||||
parsed_drawings = []
|
parsed_drawings = []
|
||||||
for filename, temp_path in saved_files:
|
try:
|
||||||
try:
|
for filename, temp_path in saved_files:
|
||||||
drawing_data = cad_parser.parse_dwg(temp_path, custom_filename=filename)
|
drawing_data = cad_parser.parse_dwg(temp_path, custom_filename=filename)
|
||||||
parsed_drawings.append(drawing_data)
|
parsed_drawings.append(drawing_data)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return jsonify({'status': 'error', 'message': f'도면 분석 중 오류 발생 ({filename}): {str(e)}'}), 500
|
return jsonify({'status': 'error', 'message': f'도면 분석 중 오류 발생: {str(e)}'}), 500
|
||||||
|
finally:
|
||||||
|
for _, temp_path in saved_files:
|
||||||
|
try:
|
||||||
|
if os.path.exists(temp_path):
|
||||||
|
os.remove(temp_path)
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
|
||||||
global current_drawing_data, current_model_data, current_drawings_list
|
global current_drawing_data, current_model_data, current_drawings_list
|
||||||
if reset_flag or current_drawings_list is None:
|
if reset_flag or current_drawings_list is None:
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import math
|
import math
|
||||||
import json
|
|
||||||
import ezdwg
|
import ezdwg
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+1
-2
@@ -1,6 +1,5 @@
|
|||||||
import math
|
import math
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import json
|
|
||||||
import rebar_model
|
import rebar_model
|
||||||
|
|
||||||
|
|
||||||
@@ -122,7 +121,6 @@ def get_wingwall_mesh(side='LEFT', custom_params=None, culvert_params=None, num_
|
|||||||
pos_str = 'START_RIGHT'
|
pos_str = 'START_RIGHT'
|
||||||
|
|
||||||
is_left_side = ('LEFT' in pos_str)
|
is_left_side = ('LEFT' in pos_str)
|
||||||
is_start = ('START' in pos_str)
|
|
||||||
|
|
||||||
cp = custom_params or {}
|
cp = custom_params or {}
|
||||||
culv = culvert_params or {}
|
culv = culvert_params or {}
|
||||||
@@ -554,6 +552,7 @@ def generate_full_model(params=None, drawings_list=None):
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
import json
|
||||||
res = generate_full_model()
|
res = generate_full_model()
|
||||||
print("Full model generated:")
|
print("Full model generated:")
|
||||||
print(" Total volume:", res['summary']['total_volume'], "m3")
|
print(" Total volume:", res['summary']['total_volume'], "m3")
|
||||||
|
|||||||
+10
-23
@@ -887,27 +887,10 @@ class Viewer3D {
|
|||||||
new THREE.Vector3(d2.x, d2.y, zDim + tickLen)
|
new THREE.Vector3(d2.x, d2.y, zDim + tickLen)
|
||||||
);
|
);
|
||||||
|
|
||||||
const geom = new THREE.BufferGeometry().setFromPoints(linePoints);
|
// 치수선 및 텍스트 렌더링
|
||||||
const mat = new THREE.LineBasicMaterial({
|
|
||||||
color: 0xffffff, // Requirement 4: 모든 치수선 흰색
|
|
||||||
linewidth: 2,
|
|
||||||
depthTest: false,
|
|
||||||
transparent: true,
|
|
||||||
opacity: 0.95
|
|
||||||
});
|
|
||||||
const lineSegs = new THREE.LineSegments(geom, mat);
|
|
||||||
lineSegs.renderOrder = 999;
|
|
||||||
this.dimensionGroup.add(lineSegs);
|
|
||||||
|
|
||||||
// 치수값 텍스트 라벨 (수평 치수선 상단 중앙 배치)
|
|
||||||
const mid = new THREE.Vector3().addVectors(d1, d2).multiplyScalar(0.5);
|
const mid = new THREE.Vector3().addVectors(d1, d2).multiplyScalar(0.5);
|
||||||
const spritePos = new THREE.Vector3(mid.x, mid.y, zDim + 0.28);
|
const spritePos = new THREE.Vector3(mid.x, mid.y, zDim + 0.28);
|
||||||
|
this._renderDimensionEntry(linePoints, spritePos, text);
|
||||||
const sprite = this.createDimensionTextSprite(text);
|
|
||||||
sprite.position.copy(spritePos);
|
|
||||||
sprite.renderOrder = 1000;
|
|
||||||
this.scene.add(sprite);
|
|
||||||
this.dimensionSprites.push(sprite);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 높이 측정용 3D 치수선 생성 (Requirement 3 & 4: 흰색 치수선 및 간소화 표기)
|
// 높이 측정용 3D 치수선 생성 (Requirement 3 & 4: 흰색 치수선 및 간소화 표기)
|
||||||
@@ -936,6 +919,14 @@ class Viewer3D {
|
|||||||
linePoints.push(d1.clone().addScaledVector(tickDir, tickLen), d1.clone().addScaledVector(tickDir, -tickLen));
|
linePoints.push(d1.clone().addScaledVector(tickDir, tickLen), d1.clone().addScaledVector(tickDir, -tickLen));
|
||||||
linePoints.push(d2.clone().addScaledVector(tickDir, tickLen), d2.clone().addScaledVector(tickDir, -tickLen));
|
linePoints.push(d2.clone().addScaledVector(tickDir, tickLen), d2.clone().addScaledVector(tickDir, -tickLen));
|
||||||
|
|
||||||
|
// 치수값 텍스트 라벨 (치수선 외측 중앙에 명확히 대응되도록 배치)
|
||||||
|
const mid = new THREE.Vector3().addVectors(d1, d2).multiplyScalar(0.5);
|
||||||
|
const spritePos = mid.clone().addScaledVector(offsetDir.clone().normalize(), 0.32);
|
||||||
|
this._renderDimensionEntry(linePoints, spritePos, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 치수선 LineSegments 및 텍스트 Sprite 씬 등록 공통 헬퍼
|
||||||
|
_renderDimensionEntry(linePoints, spritePos, text) {
|
||||||
const geom = new THREE.BufferGeometry().setFromPoints(linePoints);
|
const geom = new THREE.BufferGeometry().setFromPoints(linePoints);
|
||||||
const mat = new THREE.LineBasicMaterial({
|
const mat = new THREE.LineBasicMaterial({
|
||||||
color: 0xffffff, // Requirement 4: 모든 치수선 흰색
|
color: 0xffffff, // Requirement 4: 모든 치수선 흰색
|
||||||
@@ -948,10 +939,6 @@ class Viewer3D {
|
|||||||
lineSegs.renderOrder = 999;
|
lineSegs.renderOrder = 999;
|
||||||
this.dimensionGroup.add(lineSegs);
|
this.dimensionGroup.add(lineSegs);
|
||||||
|
|
||||||
// 치수값 텍스트 라벨 (치수선 외측 중앙에 명확히 대응되도록 배치)
|
|
||||||
const mid = new THREE.Vector3().addVectors(d1, d2).multiplyScalar(0.5);
|
|
||||||
const spritePos = mid.clone().addScaledVector(offsetDir.clone().normalize(), 0.32);
|
|
||||||
|
|
||||||
const sprite = this.createDimensionTextSprite(text);
|
const sprite = this.createDimensionTextSprite(text);
|
||||||
sprite.position.copy(spritePos);
|
sprite.position.copy(spritePos);
|
||||||
sprite.renderOrder = 1000;
|
sprite.renderOrder = 1000;
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,6 @@ Verifies 2D drawing classification, DWG parsing, 3D solid & rebar modeling,
|
|||||||
mesh watertightness, exporter functionality, and Flask API endpoints.
|
mesh watertightness, exporter functionality, and Flask API endpoints.
|
||||||
"""
|
"""
|
||||||
import os
|
import os
|
||||||
import sys
|
|
||||||
import json
|
import json
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
@@ -156,6 +155,7 @@ class Test3DDrawingPipeline(unittest.TestCase):
|
|||||||
# 1. 메인 웹페이지
|
# 1. 메인 웹페이지
|
||||||
r_index = self.flask_app.get('/')
|
r_index = self.flask_app.get('/')
|
||||||
self.assertEqual(r_index.status_code, 200)
|
self.assertEqual(r_index.status_code, 200)
|
||||||
|
r_index.close()
|
||||||
|
|
||||||
# 2. 기본 도면 데이터 조회 API
|
# 2. 기본 도면 데이터 조회 API
|
||||||
r_def = self.flask_app.get('/api/default-drawing')
|
r_def = self.flask_app.get('/api/default-drawing')
|
||||||
|
|||||||
Reference in new issue
Block a user