rhino二次开发:rhinocompute_7:dwg_base64_plugin_hops_solution

11 DWG Base64 与自定义插件/Hops 集成方案

业务系统有时会把 DWG 文件编码成 base64 字符串,通过 HTTP 请求传到服务端,然后希望在 Rhino.Compute 中完成导入、识别、参数化生成或二次处理。这个场景不要简单理解成“把 base64 字符串直接接到 Grasshopper 电池上”,因为 DWG 通常较大,而且涉及文件格式解析、插件授权、临时文件、单位、图层、块参照和安全校验。

推荐做成三层:

客户端 / 业务后端
  -> 接收 base64,做认证、大小限制、审计和任务编号
  -> Rhino.Compute 自定义插件端点
  -> 解码 DWG,导入到无界面 RhinoDoc 或转换为中间文件/结构化结果
  -> Grasshopper Hops 定义 / 自定义 GH 电池
  -> 输出几何、识别结果、3dm 文件、JSON 摘要或后续业务结果

核心原则:base64 只适合作为传输格式,不适合作为 Grasshopper 画布长期流转的数据格式。Grasshopper/Hops 更适合接收 job_iddwg_path3dm_pathlayer_filtertolerance 这类短参数。

推荐把 DWG 处理能力封装在一个 Rhino 插件中,插件内部拆成三个部分:

  • DwgImportService:核心服务,负责解码、校验、落盘、导入 DWG、提取几何和元数据。
  • Compute Endpoint:注册到 Rhino.Compute,对外提供稳定 HTTP API。
  • Grasshopper Component:自定义 GH 电池,给 Hops 定义或普通 GH 画布使用。

这样可以让同一套 DWG 处理逻辑同时服务两种入口:

入口 用途
自定义 Compute 端点 外部系统直接提交 DWG base64,返回结构化结果或中间文件引用。
自定义 GH 电池 设计师在 Grasshopper 中继续编排识别、生成、过滤、标注等参数化逻辑。
Hops 定义 把含有自定义 GH 电池的 Grasshopper 定义封装成远程函数。

推荐数据流如下:

1. 客户端上传:
   POST /api/cad/analyze
   Body: { fileName, dwgBase64, options, correlationId }

2. 业务后端校验:
   - 用户权限
   - base64 长度
   - 业务配额
   - 文件名和扩展名
   - correlation id

3. 后端调用 Rhino.Compute 自定义端点:
   POST /Rhino/CustomDwg/Prepare
   Body: { fileName, dwgBase64, options, correlationId }

4. Compute 插件执行:
   - Convert.FromBase64String
   - 写入服务端临时目录
   - 创建无界面 RhinoDoc
   - 导入 DWG
   - 提取对象、图层、块、包围盒、单位等信息
   - 可选:保存为 .3dm 或生成结构化 JSON

5. Grasshopper/Hops 继续处理:
   - 输入 job_id 或 3dm_path
   - 自定义 GH 电池读取准备好的几何或元数据
   - 下游 GH 逻辑做识别、生成、优化或导出

6. 返回结果:
   - result_id
   - objects_count
   - layers
   - bounding_box
   - errors / warnings
   - 可下载的 3dm、json、图片或业务结果

插件端点仍然按 Compute 扩展规则实现:在 Rhino 插件中定义静态类和 public static 方法,并在插件 OnLoad 中调用 Rhino.Runtime.HostUtils.RegisterComputeEndPoint

请求 DTO 建议保持清晰:

public sealed class DwgPrepareRequest
{
    public string FileName { get; set; }
    public string DwgBase64 { get; set; }
    public string CorrelationId { get; set; }
    public DwgPrepareOptions Options { get; set; }
}
 
public sealed class DwgPrepareOptions
{
    public string UnitSystem { get; set; }
    public double AbsoluteTolerance { get; set; }
    public string[] LayerAllowList { get; set; }
    public bool SaveAs3dm { get; set; }
}

端点方法示意:

static class CustomDwgComputeFunctions
{
    public static DwgPrepareResult Prepare(DwgPrepareRequest request)
    {
        // 1. 校验 fileName、base64 长度、扩展名、correlationId
        // 2. 解码 base64,写入受控临时目录
        // 3. 使用 DwgImportService 导入和提取结果
        // 4. 返回结构化摘要或 3dm/job 引用
        return DwgImportService.Prepare(request);
    }
}

注册示意:

protected override LoadReturnCode OnLoad(ref string errorMessage)
{
    Rhino.Runtime.HostUtils.RegisterComputeEndPoint(
        "Rhino.CustomDwg",
        typeof(CustomDwgComputeFunctions)
    );
 
    return base.OnLoad(ref errorMessage);
}

在 Rhino 8 中,优先使用 code-driven file IO 和无界面 RhinoDoc。它可以避免脚本命令、弹窗和活动文档依赖,更适合 Compute 服务端。

实现思路:

using var doc = Rhino.RhinoDoc.CreateHeadless(null);
 
var options = new Rhino.FileIO.FileDwgReadOptions
{
    ImportUnreferencedBlocks = true,
    ImportUnreferencedLayers = true,
    ImportUnreferencedLinetypes = true
};
 
bool ok = doc.Import(dwgPath, options.ToDictionary());
if (!ok)
    throw new InvalidOperationException("DWG import failed.");
 
foreach (var obj in doc.Objects)
{
    var geometry = obj.Geometry;
    var layerIndex = obj.Attributes.LayerIndex;
    // 提取曲线、块、文字、标注、包围盒或转成业务 DTO
}

如果使用 Rhino 7,需要单独评估 DWG 导入路径。常见选择是:

  • 在 Compute 前置服务中先把 DWG 转为 DXF 或 3dm。
  • 使用 ODA Drawings SDK、ODA Architecture SDK、Autodesk RealDWG 等受授权的 DWG 解析能力。
  • 使用已有公司插件导入 DWG,但必须确认它能在无界面 Compute 子进程中运行,不能依赖弹窗、鼠标选择或命令行交互。

自定义 GH 电池不要直接接收超长 base64 字符串作为常规输入。推荐输入:

输入名 类型 说明
job_id Text 由后端或插件端点生成的任务编号。
dwg_path Text 服务端受控目录中的 DWG 文件路径。只用于可信内网/本机调试。
model_3dm_path Text 已由插件端点转换好的 3dm 文件路径。
layer_filter Text/List 需要处理的图层名或规则。
tolerance Number 几何识别容差。
run Boolean 控制是否执行,避免画布反复求解。

推荐输出:

输出名 类型 说明
curves Curve/List 可直接进入后续 GH 逻辑的曲线。
breps Brep/List 可选的面或实体。
metadata Text/JSON 图层、块、单位、对象数量、警告信息。
result_id Text 后续下载或查询结果的编号。

GH 电池内部调用同一个 DwgImportService,或者读取端点已经生成的 3dm/JSON。不要让 GH 电池自己管理用户认证、HTTP 上传、base64 解码和全局临时目录清理。

在 Hops 中使用时,建议把含有自定义 GH 电池的定义保存为独立 .gh 文件,例如:

dwg_prepare_and_analyze.gh

定义结构:

Context Get: job_id / model_3dm_path / layer_filter / tolerance / run
  -> 自定义 GH 电池:ReadPreparedDwg
  -> 后续识别或参数化逻辑
Context Print: metadata / result_id / warnings
Context Bake 或普通输出:curves / breps

调用侧 Hops 组件只需要把 Path 指向这个 .gh 文件或远程 REST URL。Hops 会根据 Context Get 和 Context Print/Bake 自动生成输入输出。自定义 GH 电池必须安装在所有 Compute 子进程能加载到的位置。

  • DWG base64 会比原始文件更大,容易触发请求体大小限制。
  • Hops 的优势是函数化求解,不是文件上传和安全网关。
  • 长字符串会影响缓存、日志、调试导出和错误定位。
  • DWG 导入失败通常需要文件级日志、临时目录和授权诊断,放在插件端点更容易治理。
  • 生产环境不能让浏览器前端直接持有 Compute API Key,也不应让前端决定服务端文件路径。

只有在内网调试、小文件、一次性验证时,才可以临时把 base64 作为 Text 输入传给 Hops;生产方案应改成预上传或插件端点接收。

  • 限制 base64 解码后的最大字节数。
  • 只接受 .dwg,不要信任客户端传来的文件名,服务端应重新生成安全文件名。
  • 临时文件写入固定根目录,例如 C:\ProgramData\YourCompany\ComputeJobs,禁止客户端传任意绝对路径。
  • 每个请求使用独立任务目录,目录名使用 correlation_id 或服务端生成的 GUID。
  • 记录导入耗时、对象数量、图层数量、失败原因和 Compute 子进程编号。
  • 任务完成后按 TTL 清理 DWG、3dm、日志和中间 JSON。
  • 插件依赖 DLL、授权文件、DWG 解析库必须部署到 Compute 服务器,并在 /sdk 和最小请求中验证。
  1. 在普通 Rhino 中安装插件并运行最小 DWG 导入测试。
  2. 启动本地 Rhino.Compute,访问 /sdk,确认 Rhino.CustomDwg 端点出现。
  3. 用一个很小的 DWG base64 调用 Prepare,确认能返回对象数量和图层摘要。
  4. 用损坏 base64、错误扩展名、超大文件、空文件分别测试错误处理。
  5. 在 Grasshopper 中放置自定义 GH 电池,使用 job_id3dm_path 读取准备好的结果。
  6. 把该 GH 定义封装成 Hops 函数,检查 Context Get/Print 命名和远程 Compute 配置。
  7. 部署到 IIS/生产服务器后,重新验证插件授权、临时目录权限、请求体大小和超时设置。

推荐按以下顺序落地:

  1. 先做插件核心服务:能在普通 Rhino 中把 DWG 导入并提取对象摘要。
  2. 再注册 Compute 自定义端点:能接收 base64 并返回结构化结果。
  3. 再做 GH 电池:读取 job_id3dm_path,输出曲线、图层和元数据。
  4. 最后做 Hops 定义:把 GH 电池和业务参数化逻辑封装成远程函数。

这样每一步都能单独测试,出错时也能判断是上传、插件导入、Compute 加载、Grasshopper 求解还是 Hops 调用的问题。

该主题尚不存在

您访问的页面并不存在。如果允许,您可以使用创建该页面按钮来创建它。

  • rhino二次开发/rhinocompute_7/dwg_base64_plugin_hops_solution.txt
  • 最后更改: 2026/06/08 09:12
  • 张叶安