分模候选方案
This commit is contained in:
+23
-12
@@ -1,16 +1,27 @@
|
|||||||
from fastapi import APIRouter
|
from fastapi import APIRouter
|
||||||
|
import importlib
|
||||||
|
|
||||||
from api.v1.health_router import router as health_router
|
from utils.logger import get_logger
|
||||||
from api.v1.upload_router import router as upload_router
|
|
||||||
from api.v1.task_router import router as task_router
|
logger = get_logger(__name__)
|
||||||
from api.v1.history_router import router as history_router
|
|
||||||
from api.v1.debug_router import router as debug_router
|
|
||||||
from api.v1.advanced_router import router as advanced_router
|
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
router.include_router(health_router)
|
|
||||||
router.include_router(upload_router)
|
def _safe_include(module_path: str, label: str):
|
||||||
router.include_router(task_router)
|
try:
|
||||||
router.include_router(history_router)
|
module = importlib.import_module(module_path)
|
||||||
router.include_router(debug_router)
|
router_obj = getattr(module, "router", None)
|
||||||
router.include_router(advanced_router)
|
if router_obj is None:
|
||||||
|
raise ValueError("未找到 router 对象")
|
||||||
|
router.include_router(router_obj)
|
||||||
|
logger.info(f"{label} 路由加载成功")
|
||||||
|
except Exception as exc:
|
||||||
|
logger.warning(f"{label} 路由加载失败,已跳过: {exc}")
|
||||||
|
|
||||||
|
|
||||||
|
_safe_include("api.v1.health_router", "健康检查")
|
||||||
|
_safe_include("api.v1.upload_router", "上传")
|
||||||
|
_safe_include("api.v1.task_router", "任务")
|
||||||
|
_safe_include("api.v1.history_router", "历史")
|
||||||
|
_safe_include("api.v1.debug_router", "调试")
|
||||||
|
_safe_include("api.v1.advanced_router", "高级")
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ from sqlalchemy.ext.asyncio import AsyncSession
|
|||||||
from services.auth_service import get_current_active_user
|
from services.auth_service import get_current_active_user
|
||||||
from services.processing_service import processing_service
|
from services.processing_service import processing_service
|
||||||
from models.database import User
|
from models.database import User
|
||||||
from api.routes import tasks as legacy_tasks
|
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
@@ -66,7 +65,6 @@ async def upload_stp(
|
|||||||
upload_time=str(datetime.now())
|
upload_time=str(datetime.now())
|
||||||
)
|
)
|
||||||
await redis_task_manager.set_task(task_id, task_info)
|
await redis_task_manager.set_task(task_id, task_info)
|
||||||
legacy_tasks[task_id] = task_info
|
|
||||||
|
|
||||||
# 后台处理(使用独立数据库会话,避免请求会话关闭问题)
|
# 后台处理(使用独立数据库会话,避免请求会话关闭问题)
|
||||||
background_tasks.add_task(
|
background_tasks.add_task(
|
||||||
|
|||||||
@@ -67,9 +67,13 @@ class MeshGenerator:
|
|||||||
face_vertices = []
|
face_vertices = []
|
||||||
for i in range(1, nb_nodes + 1):
|
for i in range(1, nb_nodes + 1):
|
||||||
pnt = face_triangulation.Node(i)
|
pnt = face_triangulation.Node(i)
|
||||||
# 应用位置变换
|
# 使用变换后的拷贝点,避免潜在的原地变换副作用
|
||||||
pnt.Transform(trsf)
|
transformed = pnt.Transformed(trsf)
|
||||||
face_vertices.append([float(pnt.X()), float(pnt.Y()), float(pnt.Z())])
|
face_vertices.append([
|
||||||
|
float(transformed.X()),
|
||||||
|
float(transformed.Y()),
|
||||||
|
float(transformed.Z()),
|
||||||
|
])
|
||||||
|
|
||||||
# 提取三角形索引
|
# 提取三角形索引
|
||||||
face_indices = []
|
face_indices = []
|
||||||
|
|||||||
+9
-1
@@ -127,7 +127,15 @@ try:
|
|||||||
from api.v1 import router as moldinsight_router
|
from api.v1 import router as moldinsight_router
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
moldinsight_router = None
|
moldinsight_router = None
|
||||||
print(f"[WARN] MoldInsight路由未加载: {e}")
|
print(f"[WARN] MoldInsight v1路由未加载: {e}")
|
||||||
|
|
||||||
|
if moldinsight_router is None:
|
||||||
|
try:
|
||||||
|
from api.routes import router as moldinsight_router
|
||||||
|
print("[WARN] 已回退到旧版 MoldInsight 路由")
|
||||||
|
except Exception as fallback_error:
|
||||||
|
moldinsight_router = None
|
||||||
|
print(f"[WARN] MoldInsight旧版路由也未加载: {fallback_error}")
|
||||||
|
|
||||||
if moldinsight_router is not None:
|
if moldinsight_router is not None:
|
||||||
app.include_router(moldinsight_router, prefix="/api")
|
app.include_router(moldinsight_router, prefix="/api")
|
||||||
|
|||||||
+55
-17
@@ -221,9 +221,49 @@ class HTMLGenerator:
|
|||||||
const cavityData = {json.dumps(cavity_data, indent=2) if cavity_data else 'null'};
|
const cavityData = {json.dumps(cavity_data, indent=2) if cavity_data else 'null'};
|
||||||
const pointcloudData = {json.dumps(pointcloud_data, indent=2) if pointcloud_data else 'null'};
|
const pointcloudData = {json.dumps(pointcloud_data, indent=2) if pointcloud_data else 'null'};
|
||||||
|
|
||||||
|
function toFlatArray(data) {{
|
||||||
|
if (!Array.isArray(data)) return [];
|
||||||
|
if (data.length === 0) return [];
|
||||||
|
return Array.isArray(data[0]) ? data.flat() : data;
|
||||||
|
}}
|
||||||
|
|
||||||
|
function normalizePositions(rawPositions, center) {{
|
||||||
|
const flat = toFlatArray(rawPositions);
|
||||||
|
if (!flat.length) return [];
|
||||||
|
const normalized = [];
|
||||||
|
for (let i = 0; i + 2 < flat.length; i += 3) {{
|
||||||
|
const x = Number(flat[i]);
|
||||||
|
const y = Number(flat[i + 1]);
|
||||||
|
const z = Number(flat[i + 2]);
|
||||||
|
if (Number.isFinite(x) && Number.isFinite(y) && Number.isFinite(z)) {{
|
||||||
|
normalized.push(
|
||||||
|
x - Number(center[0] || 0),
|
||||||
|
y - Number(center[1] || 0),
|
||||||
|
z - Number(center[2] || 0)
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
}}
|
||||||
|
return normalized;
|
||||||
|
}}
|
||||||
|
|
||||||
|
function fitCameraToScene() {{
|
||||||
|
const sceneBox = new THREE.Box3().setFromObject(scene);
|
||||||
|
if (sceneBox.isEmpty()) return;
|
||||||
|
const center = new THREE.Vector3();
|
||||||
|
const size = new THREE.Vector3();
|
||||||
|
sceneBox.getCenter(center);
|
||||||
|
sceneBox.getSize(size);
|
||||||
|
const maxDim = Math.max(size.x, size.y, size.z) || 100;
|
||||||
|
const distance = maxDim * 2.2;
|
||||||
|
camera.position.set(center.x + distance, center.y + distance, center.z + distance);
|
||||||
|
controls.target.copy(center);
|
||||||
|
controls.update();
|
||||||
|
}}
|
||||||
|
|
||||||
// 根据边界框创建几何体
|
// 根据边界框创建几何体
|
||||||
const bbox = geometryData.bounding_box;
|
const bbox = geometryData.bounding_box;
|
||||||
if (bbox) {{
|
if (bbox) {{
|
||||||
|
const centerOffset = bbox.center || [0, 0, 0];
|
||||||
const width = bbox.dimensions ? bbox.dimensions[0] : 100;
|
const width = bbox.dimensions ? bbox.dimensions[0] : 100;
|
||||||
const height = bbox.dimensions ? bbox.dimensions[1] : 100;
|
const height = bbox.dimensions ? bbox.dimensions[1] : 100;
|
||||||
const depth = bbox.dimensions ? bbox.dimensions[2] : 100;
|
const depth = bbox.dimensions ? bbox.dimensions[2] : 100;
|
||||||
@@ -232,12 +272,12 @@ class HTMLGenerator:
|
|||||||
if (pointcloudData && pointcloudData.points && pointcloudData.points.length > 0) {{
|
if (pointcloudData && pointcloudData.points && pointcloudData.points.length > 0) {{
|
||||||
// 创建点云几何体
|
// 创建点云几何体
|
||||||
const pointGeometry = new THREE.BufferGeometry();
|
const pointGeometry = new THREE.BufferGeometry();
|
||||||
const positions = new Float32Array(pointcloudData.points.flat());
|
const positions = new Float32Array(normalizePositions(pointcloudData.points, centerOffset));
|
||||||
pointGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
|
pointGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
|
||||||
|
|
||||||
// 添加法向量(如果有)
|
// 添加法向量(如果有)
|
||||||
if (pointcloudData.normals && pointcloudData.normals.length > 0) {{
|
if (pointcloudData.normals && pointcloudData.normals.length > 0) {{
|
||||||
const normals = new Float32Array(pointcloudData.normals.flat());
|
const normals = new Float32Array(toFlatArray(pointcloudData.normals));
|
||||||
pointGeometry.setAttribute('normal', new THREE.BufferAttribute(normals, 3));
|
pointGeometry.setAttribute('normal', new THREE.BufferAttribute(normals, 3));
|
||||||
}}
|
}}
|
||||||
|
|
||||||
@@ -286,8 +326,8 @@ class HTMLGenerator:
|
|||||||
|
|
||||||
if (cavityVerts.length > 0 && cavityFaces.length > 0) {{
|
if (cavityVerts.length > 0 && cavityFaces.length > 0) {{
|
||||||
const cavityGeometry = new THREE.BufferGeometry();
|
const cavityGeometry = new THREE.BufferGeometry();
|
||||||
const positions = new Float32Array(cavityVerts);
|
const positions = new Float32Array(normalizePositions(cavityVerts, centerOffset));
|
||||||
const indices = new Uint32Array(cavityFaces);
|
const indices = new Uint32Array(toFlatArray(cavityFaces));
|
||||||
cavityGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
|
cavityGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
|
||||||
cavityGeometry.setIndex(new THREE.BufferAttribute(indices, 1));
|
cavityGeometry.setIndex(new THREE.BufferAttribute(indices, 1));
|
||||||
cavityGeometry.computeVertexNormals();
|
cavityGeometry.computeVertexNormals();
|
||||||
@@ -331,8 +371,8 @@ class HTMLGenerator:
|
|||||||
|
|
||||||
if (coreVerts.length > 0 && coreFaces.length > 0) {{
|
if (coreVerts.length > 0 && coreFaces.length > 0) {{
|
||||||
const coreGeometry = new THREE.BufferGeometry();
|
const coreGeometry = new THREE.BufferGeometry();
|
||||||
const positions = new Float32Array(coreVerts);
|
const positions = new Float32Array(normalizePositions(coreVerts, centerOffset));
|
||||||
const indices = new Uint32Array(coreFaces);
|
const indices = new Uint32Array(toFlatArray(coreFaces));
|
||||||
coreGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
|
coreGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
|
||||||
coreGeometry.setIndex(new THREE.BufferAttribute(indices, 1));
|
coreGeometry.setIndex(new THREE.BufferAttribute(indices, 1));
|
||||||
coreGeometry.computeVertexNormals();
|
coreGeometry.computeVertexNormals();
|
||||||
@@ -364,7 +404,7 @@ class HTMLGenerator:
|
|||||||
}}
|
}}
|
||||||
|
|
||||||
// 创建分型面(红色平面)
|
// 创建分型面(红色平面)
|
||||||
const partingGeometry = new THREE.PlaneGeometry(width * 1.2, depth * 1.2);
|
const partingGeometry = new THREE.PlaneGeometry(width * 1.2, height * 1.2);
|
||||||
const partingMaterial = new THREE.MeshBasicMaterial({{
|
const partingMaterial = new THREE.MeshBasicMaterial({{
|
||||||
color: 0xF44336,
|
color: 0xF44336,
|
||||||
transparent: true,
|
transparent: true,
|
||||||
@@ -373,7 +413,6 @@ class HTMLGenerator:
|
|||||||
}});
|
}});
|
||||||
|
|
||||||
partingMesh = new THREE.Mesh(partingGeometry, partingMaterial);
|
partingMesh = new THREE.Mesh(partingGeometry, partingMaterial);
|
||||||
partingMesh.rotation.x = Math.PI / 2;
|
|
||||||
partingMesh.position.set(0, 0, 0);
|
partingMesh.position.set(0, 0, 0);
|
||||||
scene.add(partingMesh);
|
scene.add(partingMesh);
|
||||||
|
|
||||||
@@ -392,8 +431,8 @@ class HTMLGenerator:
|
|||||||
// 创建简化型腔/A板(定模,分型面以上)— 备用
|
// 创建简化型腔/A板(定模,分型面以上)— 备用
|
||||||
function createSimpleCavity(width, height, depth) {{
|
function createSimpleCavity(width, height, depth) {{
|
||||||
// A板:分型面(Z中心)以上的上半模
|
// A板:分型面(Z中心)以上的上半模
|
||||||
const halfHeight = height / 2;
|
const halfDepth = depth / 2;
|
||||||
const cavityGeometry = new THREE.BoxGeometry(width * 1.2, depth * 1.2, halfHeight + 10);
|
const cavityGeometry = new THREE.BoxGeometry(width * 1.2, height * 1.2, halfDepth + 10);
|
||||||
const cavityMaterial = new THREE.MeshPhongMaterial({{
|
const cavityMaterial = new THREE.MeshPhongMaterial({{
|
||||||
color: 0x2196F3,
|
color: 0x2196F3,
|
||||||
transparent: true,
|
transparent: true,
|
||||||
@@ -403,7 +442,7 @@ class HTMLGenerator:
|
|||||||
|
|
||||||
cavityMesh = new THREE.Mesh(cavityGeometry, cavityMaterial);
|
cavityMesh = new THREE.Mesh(cavityGeometry, cavityMaterial);
|
||||||
// Z轴开模:A板放在分型面以上
|
// Z轴开模:A板放在分型面以上
|
||||||
cavityMesh.position.set(0, 0, halfHeight / 2 + 5);
|
cavityMesh.position.set(0, 0, halfDepth / 2 + 5);
|
||||||
scene.add(cavityMesh);
|
scene.add(cavityMesh);
|
||||||
|
|
||||||
const cavityWireframe = new THREE.WireframeGeometry(cavityGeometry);
|
const cavityWireframe = new THREE.WireframeGeometry(cavityGeometry);
|
||||||
@@ -418,8 +457,8 @@ class HTMLGenerator:
|
|||||||
// 创建简化型芯/B板(动模,分型面以下)— 备用
|
// 创建简化型芯/B板(动模,分型面以下)— 备用
|
||||||
function createSimpleCore(width, height, depth) {{
|
function createSimpleCore(width, height, depth) {{
|
||||||
// B板:分型面(Z中心)以下的下半模
|
// B板:分型面(Z中心)以下的下半模
|
||||||
const halfHeight = height / 2;
|
const halfDepth = depth / 2;
|
||||||
const coreGeometry = new THREE.BoxGeometry(width * 1.2, depth * 1.2, halfHeight + 10);
|
const coreGeometry = new THREE.BoxGeometry(width * 1.2, height * 1.2, halfDepth + 10);
|
||||||
const coreMaterial = new THREE.MeshPhongMaterial({{
|
const coreMaterial = new THREE.MeshPhongMaterial({{
|
||||||
color: 0xFF9800,
|
color: 0xFF9800,
|
||||||
transparent: true,
|
transparent: true,
|
||||||
@@ -429,7 +468,7 @@ class HTMLGenerator:
|
|||||||
|
|
||||||
coreMesh = new THREE.Mesh(coreGeometry, coreMaterial);
|
coreMesh = new THREE.Mesh(coreGeometry, coreMaterial);
|
||||||
// Z轴开模:B板放在分型面以下
|
// Z轴开模:B板放在分型面以下
|
||||||
coreMesh.position.set(0, 0, -halfHeight / 2 - 5);
|
coreMesh.position.set(0, 0, -halfDepth / 2 - 5);
|
||||||
scene.add(coreMesh);
|
scene.add(coreMesh);
|
||||||
|
|
||||||
const coreWireframe = new THREE.WireframeGeometry(coreGeometry);
|
const coreWireframe = new THREE.WireframeGeometry(coreGeometry);
|
||||||
@@ -441,9 +480,8 @@ class HTMLGenerator:
|
|||||||
coreMesh.add(coreLine);
|
coreMesh.add(coreLine);
|
||||||
}}
|
}}
|
||||||
|
|
||||||
// 设置相机位置
|
// 统一按场景包围盒调整相机,避免模型错位/尺度不一致导致观感混乱
|
||||||
camera.position.set(200, 200, 200);
|
fitCameraToScene();
|
||||||
camera.lookAt(0, 0, 0);
|
|
||||||
|
|
||||||
// 动画循环
|
// 动画循环
|
||||||
function animate() {{
|
function animate() {{
|
||||||
|
|||||||
Reference in New Issue
Block a user