分模候选方案

This commit is contained in:
2026-04-23 23:37:39 +08:00
parent 0bdfc7f7d5
commit c1f6b6e827
16 changed files with 1302 additions and 497 deletions
+84 -34
View File
@@ -15,6 +15,7 @@ from core.mold_generator import MoldCavityGenerator
from core.aluminum_foam_mold import AluminumFoamMoldGenerator
from core.mold_quality_inspector import AluminumFoamMoldQualityInspector
from core.mesh_generator import MeshGenerator
from core.multi_scheme_planner import MultiSchemeMoldPlanner
from services.storage_integration_rustfs import StorageIntegrationService
from services.redis_task_manager import redis_task_manager
from services.material_service import MaterialService
@@ -39,6 +40,7 @@ class ProcessingService:
self.mesh_generator = MeshGenerator(quality="medium")
self.html_generator = HTMLGenerator()
self.storage_service = StorageIntegrationService()
self.multi_scheme_planner = MultiSchemeMoldPlanner()
# ─── 对外入口 ───
@@ -127,7 +129,7 @@ class ProcessingService:
selected_material = MaterialService.get_material(requested_material)
is_foam_material = MaterialService.is_foam_material(requested_material)
cavity_mesh_data = await self._step_generate_cavity(
plan_result = await self._step_generate_cavity(
shape, selected_material, is_foam_material
)
@@ -136,19 +138,25 @@ class ProcessingService:
db_session, task_id, "processing", 60, "生成型腔详细数据"
)
detailed_cavity_json = CalculationService.build_detailed_cavity_json(
detailed_cavity_json = CalculationService.build_plan_result(
geometry_data=geometry_data,
material=selected_material,
file_path=str(file_path),
cavity_mesh_data=cavity_mesh_data,
plan_result=plan_result,
)
if cavity_mesh_data and "mold_cavities" in cavity_mesh_data:
mold_cavities = cavity_mesh_data["mold_cavities"]
logger.info(f"型腔网格数据已合并: cavity {mold_cavities.get('cavity', {}).get('vertex_count', 0)} 顶点")
best_scheme = CalculationService.get_best_scheme(detailed_cavity_json)
best_cavity_data = best_scheme.get("cavity_data", {}) if best_scheme else {}
best_key_info = best_scheme.get("key_info", {}) if best_scheme else {}
if best_cavity_data.get("mold_cavities"):
cavity_geometry = best_cavity_data["mold_cavities"].get("cavity", {})
logger.info(
f"推荐方案型腔数据已合并: cavity {cavity_geometry.get('vertex_count', 0)} 顶点"
)
# 5. 生成关键信息
cavity_key_info = detailed_cavity_json["mold_cavities"]["cavity_key_info"]
cavity_key_info = best_key_info
# 6. 保存几何数据到数据库
await self.storage_service.update_task_status(
@@ -162,12 +170,7 @@ class ProcessingService:
geometry_data.get("analysis_method", "mold_cavity"),
)
# 7. 保存模具型腔数据
await self.storage_service.save_mold_cavity_data(
db_session, stp_file_id, detailed_cavity_json
)
# 8. 生成HTML可视化
# 7. 生成HTML可视化
await self.storage_service.update_task_status(
db_session, task_id, "processing", 85, "生成可视化报告"
)
@@ -180,10 +183,26 @@ class ProcessingService:
"point_count": mesh_result.get("point_count", 0),
}
detailed_cavity_json = await self._attach_scheme_previews(
detailed_cavity_json=detailed_cavity_json,
geometry_data=geometry_data,
stp_filename=Path(file_path).name,
pointcloud_data=pointcloud_data,
)
best_scheme = CalculationService.get_best_scheme(detailed_cavity_json)
best_cavity_data = best_scheme.get("cavity_data", {}) if best_scheme else best_cavity_data
best_key_info = best_scheme.get("key_info", {}) if best_scheme else best_key_info
# 8. 保存模具型腔数据(包含方案级预览链接)
await self.storage_service.save_mold_cavity_data(
db_session, stp_file_id, detailed_cavity_json
)
html_file_path = self.html_generator.generate_and_save_visualization(
geometry_data,
Path(file_path).name,
cavity_data=detailed_cavity_json,
cavity_data=best_cavity_data,
pointcloud_data=pointcloud_data,
)
@@ -233,9 +252,12 @@ class ProcessingService:
await redis_task_manager.update_task(task_id, {
"geometry_data": geometry_data,
"analysis_result": analysis_result,
"cavity_data": detailed_cavity_json,
"key_info": detailed_cavity_json,
"html_file": f"/html/{Path(html_file_path).name}",
"plan_result": detailed_cavity_json,
"candidate_schemes": detailed_cavity_json.get("candidate_schemes", []),
"best_scheme_id": detailed_cavity_json.get("best_scheme_id"),
"cavity_data": best_cavity_data,
"key_info": best_key_info,
"html_file": best_scheme.get("html_file", f"/html/{Path(html_file_path).name}") if best_scheme else f"/html/{Path(html_file_path).name}",
"verification": verification_result,
"status": ProcessingStatus.COMPLETED,
"completed_at": str(datetime.now()),
@@ -327,28 +349,24 @@ class ProcessingService:
async def _step_generate_cavity(
self, shape, selected_material: dict, is_foam_material: bool,
) -> Optional[Dict[str, Any]]:
"""生成模具型腔数据"""
cavity_mesh_data = None
"""生成多方案分模结果"""
plan_result = None
try:
if shape:
if is_foam_material:
self.aluminum_foam_generator.set_material(selected_material["name"])
cavity_result = self.aluminum_foam_generator.generate_mold_cavities(shape)
cavity_mesh_data = self.aluminum_foam_generator.generate_detailed_cavity_json(cavity_result)
logger.info(f"使用铝泡沫模具生成器: {selected_material['name']}")
else:
cavity_result = self.mold_generator.generate_mold_cavities(shape)
cavity_mesh_data = self.mold_generator.generate_detailed_cavity_json(cavity_result)
logger.info(f"使用普通塑料模具生成器: {selected_material['name']}")
if cavity_mesh_data:
logger.info(f"型腔网格数据生成完成: {cavity_mesh_data.get('mold_cavities', {}).get('cavity', {}).get('vertex_count', 0)} 顶点")
plan_result = self.multi_scheme_planner.generate_plan(
shape=shape,
material=selected_material,
is_foam_material=is_foam_material,
)
logger.info(
f"多方案分模完成: 生成 {len(plan_result.get('candidate_schemes', []))} 套方案"
)
except Exception as cavity_err:
logger.warning(f"型腔生成失败,使用简化数据: {cavity_err}")
logger.warning(f"多方案分模失败,使用简化数据: {cavity_err}")
traceback.print_exc()
cavity_mesh_data = None
plan_result = None
return cavity_mesh_data
return plan_result
async def _step_verify(
self, file_path: str, db_session: AsyncSession,
@@ -379,6 +397,38 @@ class ProcessingService:
logger.warning(f"FreeCAD验证失败(不影响主流程): {ve}")
return {"status": "error", "error": str(ve)}
async def _attach_scheme_previews(
self,
detailed_cavity_json: Dict[str, Any],
geometry_data: Dict[str, Any],
stp_filename: str,
pointcloud_data: Optional[Dict[str, Any]] = None,
) -> Dict[str, Any]:
"""为每个候选分模方案生成独立HTML预览链接。"""
candidate_schemes = detailed_cavity_json.get("candidate_schemes", [])
if not candidate_schemes:
return detailed_cavity_json
for scheme in candidate_schemes:
cavity_data = scheme.get("cavity_data")
if not cavity_data:
continue
suffix = scheme.get("scheme_id")
html_path = self.html_generator.generate_and_save_visualization(
geometry_data,
stp_filename,
cavity_data=cavity_data,
pointcloud_data=pointcloud_data,
suffix=suffix,
)
scheme["html_file"] = f"/html/{Path(html_path).name}"
best_scheme = CalculationService.get_best_scheme(detailed_cavity_json)
if best_scheme:
detailed_cavity_json["html_file"] = best_scheme.get("html_file")
return detailed_cavity_json
# ─── 指标持久化 ───
async def _save_analysis_metrics(self, session: AsyncSession, stp_file_id: int, analysis_result: dict):