基元形状拟合插件用户手册
Fit Primitive Shapes - User Manual
Dragonfly Prototype Apps · Fit Primitive Shapes...
版本 Version 1.0 · 2026-07-04
第一部分 中文手册
目录
1. 简介
2. 适用场景
3. 安装与启用
4. 运行环境与首次配置
5. 界面说明
6. 使用步骤
7. 参数说明
8. 输出结果
9. 常见问题与故障排除
10. 注意事项与已知限制
11. 参考资料
1. 简介
Fit Primitive Shapes(基元形状拟合) 是 Dragonfly 的 Prototype Apps 插件之一,用于把标准几何基元(平面、球、圆柱、圆锥、长方体、三维圆、直线/轴线)最佳拟合到场景中某个网格(Mesh)的顶点上。拟合完成后,插件会报告基元的几何参数(中心、半径、轴向、半角、尺寸等)与拟合误差(RMS 偏差、最大偏差、内点比例),并可把理想拟合基元作为一个新的网格对象发布到场景中,与原始网格叠加对比,直观查看偏差。
插件的拟合计算不在 Dragonfly 自带的 Python 中运行,而是在一个专用虚拟环境(venv)里以子进程方式执行,通过 JSON 文件交换数据。这样重量级第三方库与 Dragonfly 完全隔离,不会污染 Dragonfly 的 Python 环境。
底层拟合引擎(全部为宽松开源许可证):
- pyRANSAC-3D(MIT 许可证)- RANSAC 随机采样一致性拟合:平面、球、圆柱、长方体、三维圆、直线;
- trimesh(MIT 许可证)- 最小二乘球拟合、最小包络球、有向包围盒(OBB)、最小二乘平面拟合;同时用于生成理想基元的三角网格;
- numpy / scipy(BSD 许可证)- 圆锥的最小二乘拟合(闭式初值 + Levenberg-Marquardt 精化)。
插件本身的代码与 DragonflyPrototypeLabs 完整安装包同条款发布;所有拟合引擎均为 MIT/BSD 宽松许可证,可放心用于商业环境。
2. 适用场景
- 逆向工程:判断扫描件的某段表面到底是圆柱、圆锥还是球,并直接读出其半径、轴向、半角等参数,供 CAD 重建使用;
- 计量与质检:把加工件的网格与理想基元(如设计半径的圆柱)对比,通过 RMS/最大偏差和内点比例评估加工误差;
- 几何分析:提取孔、轴、销等特征的轴线方向(Line/axis 拟合)或截面圆(Circle 拟合);
- 可视化对比:发布出的理想基元网格可与原始网格在 3D 视图中叠加显示,直观定位偏差最大的区域。
本插件与 Compute Vertex Measurements(顶点测量) 插件的“相对最佳拟合球/平面偏差”功能互补:顶点测量插件把逐顶点偏差写回网格标量槽做彩色显示,而本插件报告基元的整体参数并发布理想基元本体。
3. 安装与启用
本插件随 Prototype Labs & Apps 完整安装包(Full Package) 分发,安装步骤如下:
1. 把安装包 zip 解压到任意较短路径(例如 C:\PL\,避免过深的目录导致 Windows 260 字符路径限制);
2. 双击 `Install_FullPackage.bat` 启动安装器;
3. 在弹出的组件对话框中勾选 “Fit Primitive Shapes...”。注意:所有插件默认不勾选,必须手动勾选本插件才会安装;
4. 点击 Install,等待控制台完成;
5. 完全退出并重启 Dragonfly(菜单只在启动时扫描一次)。
重启后,菜单入口出现在 Prototype Apps ▸ Fit Primitive Shapes...(位于 Measurements & Analysis 分组),点击后打开一个可停靠/可浮动的面板窗口。
以后想启用或停用本插件,最方便的方式是在 Dragonfly 里打开 Developer ▸ Prototype Labs... ▸ Menu Item Manager,在底部 “Prototype Apps (Full Package)” 列表中勾选或取消 “Fit Primitive Shapes...”,然后重启 Dragonfly 生效。停用不会删除已搭建好的运行环境(venv),重新启用后立即可用。也可以随时重跑安装器:即使解压目录已删除,仍可运行 %LOCALAPPDATA%\DragonflyPrototypeLabs\FullPackage\installer\Install_FullPackage.bat。
卸载:双击 Uninstall_FullPackage.bat 会移除所有 Full Package 菜单项与插件,但保留每个插件的环境(venv);结束时会列出这些路径,需要磁盘空间时可手动删除。整个安装过程均在当前用户目录(%LOCALAPPDATA%)下进行,不需要管理员权限。
4. 运行环境与首次配置
插件安装本身不下载任何内容。首次使用前需要一次性搭建拟合环境:打开面板,点击 Setup Environment 按钮。该按钮会:
1. 选择一个基础 Python 来创建虚拟环境。默认(Base Python 输入框留空时)优先使用 Dragonfly 自带的 Python,无需另装 Python;若不可用,则自动依次探测系统中的 CPython(py 启动器、PATH 中的 python、常见安装目录),要求带有可用的 pip;
2. 在插件代码目录内创建 venv,位置为 %LOCALAPPDATA%\comet\<Dragonfly版本>\pythonUserExtensions\GenericMenuItems\FitPrimitiveShapes\venv;
3. 通过 pip 从官方 PyPI 源安装 4 个依赖:numpy、scipy、pyransac3d、trimesh(在 CPython 3.9-3.12 上均为纯 wheel 包,无需编译,无 CUDA);
4. 对每个库做导入冒烟检查,成功后把 venv 的 Python 路径记入插件配置文件 fitprim_config.json,面板 Status 显示 Ready。
- 联网:需要联网一次(下载 pip 包),典型耗时约 1-2 分钟;之后拟合本身完全离线;
- GPU:不需要,全部为 CPU 计算;
- WSL:不需要;
- 重复点击安全:若 venv 已存在且 pip 可用,Setup 会直接复用现有环境,只重新核对依赖。
失败时的替代方案:若日志提示找不到可用的基础 Python 或 pip 不可用,请在面板的 Base Python 输入框中手动填入一个 CPython 3.9 以上解释器的完整路径(例如 C:\Python312\python.exe),再次点击 Setup Environment。若 pip 安装超时或失败,请检查网络连接(需能访问 PyPI)后重试。
5. 界面说明
面板自上而下分为标题说明、两个分组框、操作按钮行、结果区和日志区。
5.1 Input & shape(输入与形状)分组
- Mesh 下拉框 + Refresh 按钮:列出当前场景中的所有网格对象(FaceVertexMesh / Mesh),每项显示 “标题 (顶点数 v)”。新建或导入网格后点 Refresh 刷新列表;
- Shape 下拉框:选择要拟合的基元,共 7 种 - Plane(平面)、Sphere(球)、Cylinder(圆柱)、Cone(圆锥)、Cuboid / box(长方体)、Circle (3D)(三维圆)、Line / axis(直线/轴线);
- Method (library) 下拉框:选择拟合方法(底层库)。可选项随 Shape 联动变化,详见 5.3 节的形状-方法对照表;
- 参数区:随 Shape 动态生成。除 Cone 外的所有形状都有一个 Inlier distance(内点距离) 数值框(默认 0.1,范围 0.0001-1000,步进 0.05,4 位小数);Cone 没有可调参数。
5.2 Environment (fitting venv)(环境)分组
- Base Python 输入框:留空 = 使用本 Dragonfly 自带的 Python 作为 venv 基础;也可填入某个 Python 解释器的路径。该值保存在插件配置中,下次打开面板自动恢复;
- Output 下拉框:两个选项 - Publish fitted primitive mesh(默认,拟合后把理想基元作为新网格发布到场景)和 Report only(只报告参数与误差,不发布网格);
- Status 标签:显示 Ready(环境已就绪)或 Not set up - click 'Setup Environment'.(尚未搭建环境)。
5.3 按钮、结果与日志
- Setup Environment 按钮:一次性搭建/复用拟合 venv(见第 4 章);
- Fit 按钮(蓝色):对所选网格执行拟合。运行期间两个按钮均置灰,后台线程工作,不阻塞 Dragonfly 界面;
- 结果区(等宽字体):显示一行参数摘要(例如
Sphere center=(x,y,z) r=...)及第二行指标RMS=... max dev=... inliers=n/N (百分比); - 日志区(只读):滚动显示环境搭建输出、拟合进度(Loading points / Fitting ...)和错误信息。
形状 Shape | 可选方法 Method (library) | 报告的参数 |
Plane(平面) | pyRANSAC-3D (RANSAC);trimesh (least-squares) | 过点 point、法向 normal(RANSAC 另有平面方程常数 d) |
Sphere(球) | pyRANSAC-3D (RANSAC);trimesh (least-squares);trimesh (min enclosing) | 球心 center、半径 radius |
Cylinder(圆柱) | pyRANSAC-3D (RANSAC) | 中心 center、轴向 axis、半径 radius、高度 height |
Cone(圆锥) | scipy (least-squares) | 锥顶 apex、轴向 axis、半角 half_angle_deg(度)、高度 height |
Cuboid / box(长方体) | trimesh (oriented bbox);pyRANSAC-3D (RANSAC) | OBB:三向尺寸 extents 与位姿变换;RANSAC:包围平面组 planes 与 extents |
Circle (3D)(三维圆) | pyRANSAC-3D (RANSAC) | 圆心 center、法向 axis、半径 radius |
Line / axis(直线) | pyRANSAC-3D (RANSAC) | 过点 point、方向 direction、跨度 length |
6. 使用步骤
6.1 首次使用(一次性)
1. 确认本机可联网(需访问 PyPI);
2. 打开 Prototype Apps ▸ Fit Primitive Shapes...;
3. Base Python 留空(推荐,使用 Dragonfly 自带 Python),点击 Setup Environment;
4. 观察日志区:venv 创建 → pip 安装 numpy/scipy/pyransac3d/trimesh → 冒烟检查 → Setup complete.;
5. 确认 Status 变为 Ready。
6.2 拟合一个基元(端到端)
1. 准备输入:确保场景中已有一个网格(Mesh 或 FaceVertexMesh)对象,例如由 ROI 生成的表面网格或导入的扫描网格,顶点数不少于 8;
2. 在 Mesh 下拉框中选择目标网格(列表为空时点 Refresh);
3. 在 Shape 中选择要拟合的基元类型(如 Cylinder);
4. 在 Method (library) 中选择拟合方法;每种形状的第一项为推荐默认;
5. 按网格的坐标单位调整 Inlier distance:该值是判定某个顶点属于“内点”的最大允许偏差,应与预期表面噪声同数量级(Cone 无此参数);
6. 在 Output 中选择是否发布理想基元网格(默认发布);
7. 点击 Fit。插件读取网格顶点,写入临时作业目录,在 venv 中运行拟合(单次作业超时上限 600 秒);
8. 查看结果:结果区显示基元参数摘要与 RMS/最大偏差/内点比例;若选择了发布,场景中会出现一个新网格,命名为 Fit <形状名> - <原网格名>,可与原网格叠加对比。
提示:同一份数据可尝试多种形状/方法并比较 RMS 与内点比例——数值最小的 RMS 与最高的内点比例通常对应最合理的基元假设。RANSAC 拟合使用固定随机种子,同样输入重复运行结果可复现。
7. 参数说明
参数 | 默认值 | 说明 |
Mesh | (场景第一个网格) | 被拟合的网格对象;仅使用其顶点坐标。每项显示标题与顶点数。 |
Shape | Plane | 要拟合的基元类型,7 选 1:Plane / Sphere / Cylinder / Cone / Cuboid-box / Circle (3D) / Line-axis。 |
Method (library) | 随形状而定(列表第一项) | 拟合算法后端:pyRANSAC-3D (RANSAC)、trimesh (least-squares / min enclosing / oriented bbox)、scipy (least-squares,仅圆锥)。 |
Inlier distance | 0.1(范围 0.0001-1000,步进 0.05) | 内点距离阈值,单位与网格坐标一致。RANSAC 用它筛选内点;所有形状的内点比例统计也用它。值太小会导致内点比例极低,太大会把噪声计入内点。Cone 形状无此参数。 |
Base Python | (空) | 留空 = 用本 Dragonfly 自带 Python 建 venv;或填某个 CPython 3.9+ 的 python.exe 路径。仅在 Setup Environment 时使用。 |
Output | Publish fitted primitive mesh | 拟合后是否把理想基元发布为新网格;选 Report only 则只在面板中报告参数与误差。 |
固定的内部行为(不可在界面调整):随机种子固定为 0(RANSAC 结果可复现);单次拟合作业超时 600 秒;输入顶点数下限 8;圆锥拟合以三条主轴方向做闭式初值,再用 Levenberg-Marquardt 最小二乘精化,取 RMS 最小的解。
8. 输出结果
一次成功的拟合产生以下输出:
- 理想基元网格(Output 选默认项时):以
FaceVertexMesh对象发布到当前场景,自动命名为Fit <形状名> - <原网格标题>(例如Fit Sphere - MyScan)。像普通网格一样出现在对象列表中,可在 3D 视图中与原始网格叠加、调透明度、着色对比; - 参数摘要(面板结果区第一行):人类可读的基元参数,如
Cylinder axis=(x,y,z) r=... h=...; - 误差指标(结果区第二行):
RMS(所有顶点到基元表面距离的均方根)、max dev(最大偏差)、inliers=n/N (百分比)(距离不超过 Inlier distance 的顶点数与比例); - 日志:完整运行记录保留在日志区,包含进度与(出错时的)回溯信息。
各形状发布的可视化网格:球=icosphere 球面;圆柱=圆柱面;圆锥=圆锥面(锥顶对准拟合 apex);平面=以内点中心为中心的方形贴片;长方体=有向包围盒;三维圆=很薄的圆盘;直线=很细的长圆柱(便于在 3D 中看到轴线)。
拟合过程中的中间文件(顶点数组、配置、结果 JSON、基元网格 npz)写在 Windows 用户临时目录下一个 fitprim_ 开头的作业文件夹中,仅供本次运行使用,可随系统临时文件清理。
9. 常见问题与故障排除
问 1:点 Fit 提示 “ERROR: environment not set up. Click 'Setup Environment' first.”?
答:拟合 venv 尚未搭建(或已被删除)。点击 Setup Environment,等待 Status 变为 Ready 再拟合。
问 2:Mesh 下拉框是空的 / 日志显示 “No meshes found in the scene.”?
答:插件只列出场景中的网格类对象(FaceVertexMesh / Mesh)。请先在 Dragonfly 中生成或导入一个网格(例如从 ROI 生成表面网格),再点 Refresh。Channel、ROI 本身不会出现在列表里。
问 3:Setup Environment 失败,提示找不到基础 Python 或 pip 不可用?
答:在 Base Python 输入框填入一个带 pip 的 CPython 3.9+ 完整路径(如 C:\Python312\python.exe)后重试。若 pip 下载失败,请确认能访问 PyPI(公司代理环境可能需要配置代理)。
问 4:圆锥拟合报错 “could not fit a cone: the point cloud has no cone-like radial growth along any principal axis”?
答:这是明确的算法性失败:所选网格的顶点沿任何主轴方向都没有“半径随轴向线性增长”的圆锥特征(例如数据其实是平面、等半径圆柱或各向同性的点云)。请换一种形状假设(如 Cylinder 或 Plane)重新拟合。
问 5:RANSAC 拟合的内点比例很低或参数明显不合理?
答:最常见原因是 Inlier distance 与网格单位不匹配。该阈值使用网格坐标的原始单位——若网格以微米计而阈值仍是默认 0.1,几乎没有顶点会被算作内点。请把阈值调到与表面噪声同数量级后重试;也可换用最小二乘类方法(trimesh/scipy)对比。
问 6:拟合很久后提示 “processing timed out”?
答:单次拟合作业上限 600 秒。超大网格(数百万顶点)上的 RANSAC 可能超时;可先对网格做简化/抽稀再拟合,或改用最小二乘类方法(计算量更小)。
10. 注意事项与已知限制
- 只用顶点:拟合基于网格的顶点坐标,不使用面片信息,也不在表面上重采样。顶点分布不均匀(局部很密)会让该区域在拟合中权重偏大;
- 顶点数下限:少于 8 个顶点的网格会直接报错;
- 单基元:每次只拟合一个基元;不支持把整个网格自动分割成多个平面/圆柱/圆锥(多基元分割属于未来可能的扩展方向);
- Cuboid 的 RANSAC 方法:该方法报告 RANSAC 求得的包围平面与内点数,但 RMS 与 max dev 显示为 0(此后端不计算距离指标),发布的盒体为有向包围盒;需要距离指标时请用 trimesh (oriented bbox) 方法;
- Circle / Line 的可视化:发布的三维圆是一个很薄的圆盘,直线是一根很细的长圆柱——它们是便于观察的可视化体,不是零厚度的理想几何;报告的参数才是精确结果;
- 方向的符号:轴向/法向向量的正负号在数学上不唯一(轴线取 a 或 -a 等价),对比外部数据时请注意;
- 单位:所有长度类参数(半径、高度、尺寸、RMS 等)都使用网格坐标的原始单位,插件不做单位换算;
- 停用/更新安全:通过 Menu Item Manager 停用插件或用安装器更新代码都不会删除 venv 和 fitprim_config.json 配置。
11. 参考资料
- pyRANSAC-3D(MIT,RANSAC 基元拟合):https://github.com/leomariga/pyRANSAC-3D
- trimesh(MIT,球/包围盒/平面拟合与网格生成):https://github.com/mikedh/trimesh
- numpy / scipy(BSD):圆锥最小二乘拟合所用的数值计算与优化库
- 配套插件:Compute Vertex Measurements(逐顶点“相对最佳拟合球/平面偏差”彩色显示)
Part II English Manual
Contents
1. Overview
2. Use cases
3. Installation and enabling
4. Runtime environment and first-run setup
5. User interface
6. Step-by-step usage
7. Parameter reference
8. Outputs
9. FAQ and troubleshooting
10. Notes and known limitations
11. References
1. Overview
Fit Primitive Shapes is a Dragonfly Prototype Apps plugin that best-fits a standard geometric primitive (plane, sphere, cylinder, cone, cuboid/box, 3D circle, line/axis) to the vertices of a mesh in the scene. After the fit, the plugin reports the primitive's geometric parameters (centre, radius, axis, half-angle, extents, ...) together with the fit error (RMS deviation, max deviation, inlier ratio), and can publish the ideal fitted primitive as a new mesh object so you can overlay it on the original mesh for visual comparison and deviation inspection.
The fitting itself never runs inside Dragonfly's own Python. It executes as a subprocess in a dedicated virtual environment (venv) and exchanges data through JSON files, so the third-party fitting libraries stay fully isolated from Dragonfly's Python environment.
Fitting engines (all permissively licensed):
- pyRANSAC-3D (MIT) - RANSAC fitting for plane, sphere, cylinder, cuboid, 3D circle and line;
- trimesh (MIT) - least-squares sphere fit, minimum enclosing sphere, oriented bounding box (OBB), least-squares plane fit; also used to build the triangle mesh of the ideal primitive;
- numpy / scipy (BSD) - the least-squares cone fit (closed-form initialisation + Levenberg-Marquardt refinement).
The plugin code ships under the same terms as the DragonflyPrototypeLabs Full Package; every fitting engine is MIT/BSD, safe for commercial use.
2. Use cases
- Reverse engineering: decide whether a scanned surface patch is really a cylinder, a cone or a sphere, and read its radius / axis / half-angle directly - as input for CAD reconstruction;
- Metrology and quality control: compare a machined part's mesh against the ideal primitive and quantify the manufacturing error via RMS / max deviation and the inlier ratio;
- Geometric analysis: extract the axis direction of holes, shafts or pins (Line/axis fit) or a cross-section circle (Circle fit);
- Visual comparison: the published ideal-primitive mesh can be overlaid on the original mesh in the 3D view to localise where the deviation is largest.
The plugin complements the Compute Vertex Measurements plugin's 'deviation from a best-fit sphere/plane' measures: that plugin writes per-vertex deviations back into mesh scalar slots for colour display, while this plugin reports the primitive's global parameters and publishes the ideal primitive itself.
3. Installation and enabling
The plugin is distributed with the Prototype Labs & Apps Full Package. To install:
1. Unzip the package to any short path (e.g. C:\PL\; avoid deeply nested folders because of the Windows 260-character path limit);
2. Double-click `Install_FullPackage.bat`;
3. In the component dialog, tick "Fit Primitive Shapes...". Note: all plugins are unticked by default - you must tick this plugin explicitly;
4. Click Install and wait for the console to finish;
5. Fully quit and restart Dragonfly (menus are scanned only at startup).
After the restart the menu entry appears under Prototype Apps ▸ Fit Primitive Shapes... (in the Measurements & Analysis section) and opens a dockable / floatable panel window.
To enable or disable the plugin later, the easiest way is inside Dragonfly: open Developer ▸ Prototype Labs... ▸ Menu Item Manager and tick/untick "Fit Primitive Shapes..." in the "Prototype Apps (Full Package)" list at the bottom, then restart Dragonfly. Disabling never deletes the plugin's environment (venv) - re-enabling is instant. Alternatively re-run the installer at any time; even after deleting the unzipped folder you can run %LOCALAPPDATA%\DragonflyPrototypeLabs\FullPackage\installer\Install_FullPackage.bat.
Uninstall: double-click Uninstall_FullPackage.bat. It removes all Full Package menu items and plugins but keeps every plugin environment (venv); the paths are listed at the end so you can delete them manually to reclaim disk space. Everything installs per-user under %LOCALAPPDATA% - no administrator rights are needed.
4. Runtime environment and first-run setup
Installing the plugin downloads nothing. Before the first fit you must build the fitting environment once: open the panel and click Setup Environment. This button:
1. Chooses a base Python for the venv. By default (Base Python field left blank) it prefers Dragonfly's own bundled Python - no separate Python installation needed; if that is unavailable it automatically probes system CPythons (the py launcher, python on PATH, common install locations), requiring a working pip;
2. Creates the venv inside the installed plugin code folder at %LOCALAPPDATA%\comet\<Dragonfly version>\pythonUserExtensions\GenericMenuItems\FitPrimitiveShapes\venv;
3. Pip-installs the 4 dependencies from the default PyPI index: numpy, scipy, pyransac3d, trimesh (pure wheels on CPython 3.9-3.12, nothing to compile, no CUDA);
4. Runs an import smoke check for each library and, on success, records the venv's Python path in the plugin config file fitprim_config.json; the panel Status turns Ready.
- Internet: required once (to download the pip packages); typically about 1-2 minutes. Fitting itself is fully offline afterwards;
- GPU: not needed - everything is CPU-only;
- WSL: not needed;
- Safe to re-run: if the venv already exists and its pip works, Setup reuses it and only re-checks the dependencies.
If setup fails: when the log says no usable base Python / pip was found, type the full path of a CPython 3.9+ interpreter (e.g. C:\Python312\python.exe) into the Base Python field and click Setup Environment again. If the pip install fails or times out, check that the machine can reach PyPI (corporate proxies may need configuration) and retry.
5. User interface
From top to bottom the panel shows a title line, two group boxes, the action-button row, the result area and the log area.
5.1 Input & shape group
- Mesh dropdown + Refresh button: lists all mesh objects in the current scene (FaceVertexMesh / Mesh), each shown as "title (vertex count v)". Click Refresh after creating or importing a mesh;
- Shape dropdown: the primitive to fit - 7 choices: Plane, Sphere, Cylinder, Cone, Cuboid / box, Circle (3D), Line / axis;
- Method (library) dropdown: the fitting backend. The available entries change with the selected Shape - see the shape/method table in 5.3;
- Parameter area: generated dynamically per shape. Every shape except Cone has one Inlier distance spinbox (default 0.1, range 0.0001-1000, step 0.05, 4 decimals); Cone has no tunable parameter.
5.2 Environment (fitting venv) group
- Base Python field: blank = use this Dragonfly's own Python as the venv base; or type a path to a Python interpreter. The value is saved in the plugin config and restored next time;
- Output dropdown: two options - Publish fitted primitive mesh (default: publish the ideal primitive as a new mesh after the fit) and Report only (report parameters and error only, publish nothing);
- Status label: shows Ready (environment available) or Not set up - click 'Setup Environment'.
5.3 Buttons, result and log
- Setup Environment button: one-time build (or reuse) of the fitting venv (see chapter 4);
- Fit button (blue): runs the fit on the selected mesh. Both buttons grey out while a job runs; the work happens on a background thread so the Dragonfly UI stays responsive;
- Result area (monospace): one summary line of primitive parameters (e.g.
Sphere center=(x,y,z) r=...) plus a second lineRMS=... max dev=... inliers=n/N (percent); - Log area (read-only): scrolling output of the environment setup, fit progress (Loading points / Fitting ...) and error messages.
Shape | Available methods (library) | Reported parameters |
Plane | pyRANSAC-3D (RANSAC); trimesh (least-squares) | point on plane, normal (RANSAC also reports the plane-equation constant d) |
Sphere | pyRANSAC-3D (RANSAC); trimesh (least-squares); trimesh (min enclosing) | center, radius |
Cylinder | pyRANSAC-3D (RANSAC) | center, axis, radius, height |
Cone | scipy (least-squares) | apex, axis, half_angle_deg (degrees), height |
Cuboid / box | trimesh (oriented bbox); pyRANSAC-3D (RANSAC) | OBB: extents + pose transform; RANSAC: bounding planes + extents |
Circle (3D) | pyRANSAC-3D (RANSAC) | center, axis (normal), radius |
Line / axis | pyRANSAC-3D (RANSAC) | point, direction, length (extent along the line) |
6. Step-by-step usage
6.1 First use (one time)
1. Make sure the machine is online (PyPI must be reachable);
2. Open Prototype Apps ▸ Fit Primitive Shapes...;
3. Leave Base Python blank (recommended - uses Dragonfly's own Python) and click Setup Environment;
4. Watch the log: venv creation → pip install of numpy/scipy/pyransac3d/trimesh → smoke check → Setup complete.;
5. Confirm that Status now reads Ready.
6.2 Fitting a primitive (end to end)
1. Prepare the input: the scene must contain a mesh object (Mesh or FaceVertexMesh) - e.g. a surface mesh generated from an ROI or an imported scan - with at least 8 vertices;
2. Pick the target mesh in the Mesh dropdown (click Refresh if the list is empty);
3. Choose the primitive type in Shape (e.g. Cylinder);
4. Choose the fitting backend in Method (library); the first entry per shape is the recommended default;
5. Tune Inlier distance to your mesh's coordinate units: it is the maximum deviation for a vertex to count as an inlier and should be of the same order as the expected surface noise (Cone has no such parameter);
6. Choose in Output whether to publish the ideal primitive mesh (default: publish);
7. Click Fit. The plugin reads the mesh vertices, writes them to a temporary job folder and runs the fit inside the venv (per-job timeout: 600 seconds);
8. Read the results: the result area shows the parameter summary plus RMS / max deviation / inlier ratio; if publishing was selected, a new mesh named Fit <Shape> - <original mesh title> appears in the scene, ready to overlay on the original mesh.
Tip: try several shapes/methods on the same data and compare RMS and inlier ratio - the lowest RMS and highest inlier ratio usually indicate the most plausible primitive hypothesis. RANSAC runs use a fixed random seed, so repeated runs on the same input are reproducible.
7. Parameter reference
Parameter | Default | Description |
Mesh | (first mesh in the scene) | The mesh to fit; only its vertex coordinates are used. Each entry shows the title and the vertex count. |
Shape | Plane | The primitive to fit, one of 7: Plane / Sphere / Cylinder / Cone / Cuboid-box / Circle (3D) / Line-axis. |
Method (library) | per shape (first list entry) | Fitting backend: pyRANSAC-3D (RANSAC), trimesh (least-squares / min enclosing / oriented bbox), scipy (least-squares, cone only). |
Inlier distance | 0.1 (range 0.0001-1000, step 0.05) | Inlier distance threshold in the mesh's own coordinate units. RANSAC uses it to select inliers; the reported inlier ratio uses it for every shape. Too small = almost no inliers; too large = noise counted as inliers. Not present for Cone. |
Base Python | (blank) | Blank = build the venv from this Dragonfly's own Python; or the path of a CPython 3.9+ python.exe. Used only by Setup Environment. |
Output | Publish fitted primitive mesh | Whether to publish the ideal fitted primitive as a new mesh; choose Report only to just show parameters and error in the panel. |
Fixed internal behaviour (not adjustable in the UI): the random seed is fixed to 0 (RANSAC results are reproducible); a fitting job times out after 600 seconds; at least 8 input vertices are required; the cone fit initialises from the three principal axes in closed form, refines each with Levenberg-Marquardt least squares and keeps the solution with the lowest RMS.
8. Outputs
A successful fit produces:
- The ideal primitive mesh (with the default Output choice): published into the current scene as a
FaceVertexMesh, automatically namedFit <Shape> - <original mesh title>(e.g.Fit Sphere - MyScan). It appears in the object list like any other mesh and can be overlaid on the original in the 3D view with transparency / colouring for comparison; - The parameter summary (first line of the result area): human-readable primitive parameters such as
Cylinder axis=(x,y,z) r=... h=...; - The error metrics (second line):
RMS(root-mean-square of all vertex distances to the primitive surface),max dev(largest deviation) andinliers=n/N (percent)(vertices within the Inlier distance); - The log: the full run record stays in the log area, including progress and - on failure - the traceback.
Visualisation meshes per shape: sphere = icosphere; cylinder = cylindrical surface; cone = cone surface with its tip at the fitted apex; plane = a square patch centred on the inlier centroid; cuboid = the oriented bounding box; 3D circle = a very thin disc; line = a very thin elongated cylinder (so the axis is visible in 3D).
Intermediate job files (vertex array, config, result JSON, primitive-mesh npz) are written to a fitprim_-prefixed job folder in the Windows per-user temp directory; they only serve the current run and may be removed with normal temp-file cleanup.
9. FAQ and troubleshooting
Q1: Fit says "ERROR: environment not set up. Click 'Setup Environment' first."?
A: The fitting venv has not been built yet (or was deleted). Click Setup Environment and wait until Status shows Ready before fitting.
Q2: The Mesh dropdown is empty / the log says "No meshes found in the scene."?
A: The plugin lists only mesh-type objects (FaceVertexMesh / Mesh). First create or import a mesh in Dragonfly (e.g. generate a surface mesh from an ROI), then click Refresh. Channels and ROIs themselves never appear in this list.
Q3: Setup Environment fails - no base Python found, or pip is unusable?
A: Type the full path of a CPython 3.9+ interpreter with a working pip (e.g. C:\Python312\python.exe) into the Base Python field and retry. If the pip download fails, make sure PyPI is reachable (corporate proxies may need configuration).
Q4: The cone fit fails with "could not fit a cone: the point cloud has no cone-like radial growth along any principal axis"?
A: This is a deliberate, clear algorithmic failure: along none of the principal axes do the vertices show the 'radius grows linearly with axial position' signature of a cone (the data may actually be planar, a constant-radius cylinder, or an isotropic cloud). Re-fit with a different shape hypothesis such as Cylinder or Plane.
Q5: A RANSAC fit returns a very low inlier ratio or clearly wrong parameters?
A: The most common cause is an Inlier distance that does not match the mesh units - the threshold uses the mesh's raw coordinate units, so if the mesh is in micrometres and the threshold is still the default 0.1, almost nothing counts as an inlier. Set the threshold to the order of the surface noise and retry; you can also cross-check with a least-squares method (trimesh/scipy).
Q6: A long-running fit ends with "processing timed out"?
A: A single fitting job is capped at 600 seconds. RANSAC on very large meshes (millions of vertices) can exceed that; decimate/simplify the mesh first, or switch to a least-squares backend (much cheaper).
10. Notes and known limitations
- Vertices only: the fit uses the mesh's vertex coordinates; faces are ignored and the surface is not resampled. Uneven vertex density (locally very dense areas) gives those regions more weight in the fit;
- Minimum size: meshes with fewer than 8 vertices are rejected with an error;
- Single primitive: each run fits exactly one primitive; automatic multi-primitive segmentation of a whole mesh (many planes/cylinders/cones at once) is not supported - it is a possible future extension;
- Cuboid via RANSAC: this backend reports the RANSAC bounding planes and inlier count, but RMS and max dev are shown as 0 (no distance metrics are computed for it) and the published box is the oriented bounding box; use the trimesh (oriented bbox) method when you need distance metrics;
- Circle / Line visualisation: the published 3D circle is a very thin disc and the line a very thin cylinder - visualisation aids, not zero-thickness ideal geometry; the reported parameters are the exact result;
- Sign of directions: the sign of axis/normal vectors is mathematically non-unique (an axis a and -a are equivalent) - keep this in mind when comparing with external data;
- Units: all length-type outputs (radius, height, extents, RMS, ...) are in the mesh's raw coordinate units; the plugin performs no unit conversion;
- Safe disable/update: disabling the plugin in the Menu Item Manager or refreshing its code via the installer never deletes the venv or the fitprim_config.json settings.
11. References
- pyRANSAC-3D (MIT, RANSAC primitive fitting): https://github.com/leomariga/pyRANSAC-3D
- trimesh (MIT, sphere / bounding-box / plane fits and mesh creation): https://github.com/mikedh/trimesh
- numpy / scipy (BSD): numerical and optimisation libraries used by the least-squares cone fit
- Companion plugin: Compute Vertex Measurements (per-vertex 'deviation from best-fit sphere/plane' colour display)