BIM Demo 开发文档建筑BIM参数化建模 · 交互式三维演示 · v1.9.0

BIM Demo v1.9.0 开发文档

面向钢构模块化建造的参数化建模交互式演示。前后端一体化部署于小广云主机,通过 nginx 反向代理对外提供。本文档覆盖版本演进、功能清单、技术架构、API 设计、部署架构与回撤方案。

来源:https://box.jjcl.cn/demo/ · 本文档镜像:https://bim.jjcl.cn/v1.9/

当前版本
v1.9.0
已生成 IFC 模型
58
已上传文件
36
STEP 解析引擎
OpenCascade

一、版本演进历史 1.0.0 → 1.9.0

BIM Demo 从首版参数化 IFC 生成,逐步演进为集参数建模、物理联动、构件点选、撤回/复位、STEP+BOM 双文件上传、OCP 解析与历史面板于一体的完整演示系统。全部开发与部署集中在 2026-08-10 一天内完成。

版本日期核心变更
1.0.008-10首版 MVP。滑块参数输入 + ifcopenshell 生成 IFC + xeokit 三维预览。每层 4 柱 4 墙 1 板共 9 构件。
1.1.008-10渲染引擎切换到 Three.js,替代 xeokit,统一前端三维渲染管线,预留构件独立 Mesh。
1.2.008-10拖动滑块自动生成模型,移除手动触发,参数与模型双向实时联动重新生成。
1.3.008-10新增构件点选:点击三维构件高亮选中,右侧面板展示并调整该构件参数。
1.4.008-10后端新增 STEP 上传端点骨架,预留几何解析接口,前端补齐上传 UI。
1.5.008-10STEP 上传完整落地:/api/upload-step + 网格化解析 + 优雅降级(FreeCAD 未装则仅保存文件)。
1.6.008-10STEP + BOM 双文件上传。BOM 走 openpyxl 解析 Excel,支持列名自动识别(_detect_column)。新增 /api/upload-step-bom 合并上传。
1.7.008-10双文件上传区域可见化 + BOM 联动:BOM 清单与 STEP 导入的构件建立对应关系并同步变更;后端 version 字段升级。
1.8.008-10STEP 解析底层从 FreeCAD 切换为 OpenCascade (OCP),进程内解析,移除子进程依赖,稳健性与性能提升。
1.9.008-10交互打磨:撤回 / 复位操作栈、历史面板、构件删除、物理联动(参数/构件/外部导入三维联动的联动规则)。前端 index.html 版本号升至 v1.9.0。
说明:后端 /api/health 中的 version 字段与前端 nav 品牌号需保持一致。当前前端 index.html 声明 v1.9.0,后端 health 显示 1.8.0——两者差异为版本漂移,验收时以页面品牌号为准(见第六节回撤/一致性核对)。

二、功能清单

1参数化建模

核心能力。通过滑块/输入框设定 宽 width (3~30m)、深 depth (3~30m)、层高 floor_height (2.2~5.0m)、层数 floors (1~8),后端即调用 ifcopenshell 高层 API 生成标准钢构户型 IFC 模型。每层齐平生成 4 根角柱(IfcColumn,0.3×0.3)+ 4 面外墙(IfcWall)+ 1 块楼板(IfcSlab,厚 0.15),即 9 构件/层,N 层共 9N 构件。参数输入经服务端 validate_params() 白名单校验,越界返回 400 + 中文明细。

2物理联动

参数 → 模型 → 构件的多层联动:调整主参数时,IFC 重新生成,前端 Three.js 场景整树重建;三维场景中点选/删除某构件时,状态同步到参数面板与该构件的物理属性;导入的 STEP 实体与 BOM 清单条目之间按命名/标签建立映射,BOM 条目的数量、材质联动反映到对应三维构件。

3构件点选

基于 Three.js 射线拾取(Raycaster)。点击三维构件命中后高亮描边,右侧参数面板切换为该构件的独立参数(名称、尺寸、偏移、材质、可见性),支持就地编辑并实时回写场景。取消点选恢复全局参数面板。

4撤回 / 复位

撤回:维护操作栈,可连续回退最近一次构件级或参数级变更(点选、删除、参数调整),逐步撤销恢复模型。复位:一键将全部构件与参数恢复到初始生成状态,清空历史栈。

5STEP + BOM 双文件上传

支持一次上传 STEP 几何文件(.stp/.step)与 BOM 清单(Excel,openpyxl 解析,字段名自动识别)。前端含拖拽/点击上传区、进度条、文件信息区与相对路径 /demo/api/...(规避 HTTPS 混合内容)。合并上传走 /api/upload-step-bom,两文件一次性到位并建立关联。

6OCP 解析(OpenCascade STEP)

后端内置 _parse_step_ocp():使用 OpenCascade 的 STEPControl_Reader 读取 STEP,BRepMesh_IncrementalMesh 网格化,TopExp_Explorer 遍历三角面片,输出与 Three.js 兼容的扁平顶点/索引数组(parts),附边界盒 bbox 与三角面数统计。进程内运行,无需子进程/FreCAD。

7历史面板

右侧面板集中展示会话内全部操作与导入记录:参数生成记录(含各次 IFC id 与构件数)、STEP/BOM 导入记录(文件名、大小、解析结果)、构件点选与删除动作。便于审计当前模型的变更轨迹。

8删除

对构件级对象提供删除动作:删除后该构件从三维场景与构件树移除,物理联动同步失效,删除动作记入操作栈可被撤回还原,并在历史面板留痕。

三、技术架构

层技术职责
前端Three.js三维场景渲染、Raycaster 构件点选、Mesh 独立管理、历史/构件树/参数面板
后端Flask (Python)REST API:IFC 生成、STEP/BOM 上传解析、模型/文件下载、健康检查;绑定 0.0.0.0:8200
几何内核ifcopenshell高层 API ifcopenshell.api.run() 创建 IFC4 项目/场地/建筑/楼层/构件,输出标准化 .ifc
STEP 解析cadquery / OCPOpenCascade 绑定(pythonocc/OCP)读取 STEP 并网格化,替代原有 FreeCAD 子进程方案
BOM 解析openpyxl读取 Excel BOM 清单,列名/字段关键词自动识别
网关nginx (xiaoguang-nginx)静态文件服务 + 反向代理,Docker bridge 网关 172.17.0.1:8200 转发到宿主机 Flask

关键工程决策

四、数据库 / API 设计

数据存储(无数据库,文件系统模型)

当前实现不依赖数据库,状态全部落于文件系统与前端内存:
  • MODEL_DIR = /var/www/box/demo/models/ — 生成/下载的 .ifc 模型文件(uuid8 命名)。
  • UPLOAD_DIR = /var/www/box/demo/uploads/ — 用户上传的 STEP 源文件。
  • 历史面板操作栈、构件树、撤回栈 — 前端 JS 内存状态。
这符合轻量演示定位;后续若需持久化多会话历史,宜引入 SQLite(table:generations / uploads / operations)。

REST API

方法路径入参说明
GET/api/health—状态、模型数 models、上传数 uploads、step_parser、openpyxl 布尔、version
POST/api/generateJSON:width/depth/floor_height/floors/name参数化生成 IFC,返回 id、elements 数、ifc_url
GET/models/<mid>.ifc—下载指定 IFC 模型
POST/api/upload-stepmultipart:file (.stp/.step), quality上传 STEP 并 OCP 解析返回网格 parts
GET/uploads/<filename>—取回已上传 STEP 源文件
POST/api/upload-bommultipart:excelopenpyxl 解析 BOM,字段关键词识别
POST/api/upload-step-bommultipart:step + bomSTEP + BOM 合并上传并建立联动
POST/api/upload-excelmultipart:file通用 Excel 上传入口

请求 / 响应示例

# 健康检查
GET /api/health
→ {"models":58,"uploads":36,"step_parser":"opencascade","openpyxl":true,"version":"1.8.0"}

# 参数化建模
POST /api/generate  {"width":10,"depth":8,"floor_height":3,"floors":2}
→ {"success":true,"data":{"id":"ab12cd34","elements":18,
   "ifc_url":"/models/ab12cd34.ifc","parameters":{...}}}

# 参数越界 → 400
POST /api/generate  {"width":9999}
→ {"error":"参数校验失败","details":["width: 必须在 3.0 ~ 30.0 之间,当前值 9999.0"]}

STEP 解析(OCP)返回结构

parts[] 每项与 Three.js 兼容:vertices(扁平坐标数组)、faces(扁平三角索引)、num_faces/num_edges/num_vertexes/num_solids、label;汇总含 total_parts/total_faces/total_triangles/bbox。读取 STEP 失败/无法识别/网格化失败均返回中文明细;可读但无网格(纯产品壳)返回空模型优雅处理。

五、部署架构

项值
主机小广 · 腾讯云 114.132.93.176(SSH 用户 ubuntu / WireGuard 10.0.0.20 两路可达)
演示域名https://box.jjcl.cn/demo/
文档域名bim.jjcl.cn(本文档 /v1.9/),nginx root /var/www/box/bim2
前端静态 index.html → /var/www/box/demo/index.html(nginx serve)
后端宿主机 Flask server.py,监听 0.0.0.0:8200(ubuntu 用户 nohup/systemd-run 启动)
网关Docker 容器 xiaoguang-nginx,39 同 server 块加 location 反代
数据目录/var/www/box/demo/models/、/var/www/box/demo/uploads/、/var/www/box/demo/versions/

nginx 反向代理配置

在 box.jjcl.cn 的 80 与 443 两个 server 块内均需加入(最长前缀优先于 /demo/ 静态 location):

location /demo/api/   { proxy_pass http://172.17.0.1:8200/api/;   proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_read_timeout 30s; }
location /demo/models/ { proxy_pass http://172.17.0.1:8200/models/; proxy_set_header Host $host; }

完整请求链路

浏览器 ──HTTPS──▶ nginx(xiaoguang-nginx)  ──location /demo/*──▶ 172.17.0.1:8200 (宿主机 Flask)
                         │ static /demo/index.html
                         └──http──▶ /var/www/box/demo/index.html

后端启动(ifcopenshell/OCP 装在 ubuntu 用户 ~/.local,须切用户)

su - ubuntu -c 'cd /var/www/box/demo && nohup python3 -u server.py >> server.log 2>&1 &' &
sleep 2; ss -tlnp | grep 8200   # 确认 0.0.0.0:8200 监听
注:若用 systemd-run:systemd-run --unit=bim-demo-v1.7 --uid=ubuntu /bin/bash -c '...'。改 server.py 后须重启该 unit,root 启动会报 ifcopenshell 模块缺失。

六、回撤方案 · 版本备份路径

版本快照(易回滚)

每个历史版本的前端 index.html 与后端 server.py 均在 /var/www/box/demo/versions/ 留有快照:

路径内容
versions/v1.2.0.html … v1.9.0.html各版本前端 index.html 快照(v1.9.0.html = 81242B)
versions/server_v1.4.0.py, server_v1.6.0.py, server_v1.7.0.py.bak各版本后端 server.py 快照
versions/v1.7.0_backup.html, v1.8.0_backup.html部署前覆盖备份

回撤命令

# 前端回退到 v1.9.0 快照(示例目标版本)
sudo cp /var/www/box/demo/versions/v1.9.0.html /var/www/box/demo/index.html

# 后端回退(以 v1.6.0 为例)
sudo cp /var/www/box/demo/versions/server_v1.6.0.py /var/www/box/demo/server.py
# 重启后端(切 ubuntu 用户)
su - ubuntu -c 'pkill -f "python3 -u server.py"; cd /var/www/box/demo && nohup python3 -u server.py >> server.log 2>&1 &' &

# 验证
curl -s -o /dev/null -w '%{http_code}' https://box.jjcl.cn/demo/          # 200
curl -s https://box.jjcl.cn/demo/api/health                               # version + status ok

铁律:备份再覆盖 + 验证 200

  1. 覆盖前必须备份旧版:先 cp 原文件 原文件.bak.版本,再写新文件。顺序不能反——若先覆盖再 cp 备份,备份到的是新内容、旧版已丢。
  2. md5 佐证:md5sum 当前文件 vs 备份文件——备份的 md5 必须不等于当前文件(证明抓到的是旧版)。
  3. 验证两层:SSH 侧 curl 127.0.0.1/... 带 Host 确认 200 + grep -c 关键版本标记;公网侧 curl -s -o /dev/null -w '%{http_code}' 验证 HTTP 200 + Content-Length 与本地一致(防截断)。
  4. 版本文档同步更新:升级后更新 demo/VERSIONS.md(版本表 + 回撤命令 + 部署记录)。
  5. 前后端版本一致性:index.html 的 nav 品牌号与 server.py 的 /api/health.version 应一致;不一致时按页面品牌号就地修 sed -i 's/"version": "1.8.0"/"version": "1.9.0"/' server.py 并重启。

本文档部署位置与备份

本文档部署于 bim.jjcl.cn/v1.9/(实际目录 /var/www/box/bim2/v1.9/index.html)。覆盖 bim.jjcl.cn 根 /var/www/box/bim2/index.html 前,已先备份原「建筑BIM生产管理平台 2.0 开发文档(V2.0 业务驱动版)」至 bim2/index.html.bak.bim2-v2doc。若需恢复原 2.0 文档:

sudo cp /var/www/box/bim2/index.html.bak.bim2-v2doc /var/www/box/bim2/index.html
curl -s -o /dev/null -w '%{http_code}' https://bim.jjcl.cn/   # 期望 200