子件转换集成说明
1. 概要说明
支持对以下3D零件、装配体进行轻量化转换:
- Solidworks、Catia、Creo、NX 等主流CAD软件的零件、装配体格式。
- STEP、IGS、X_T 等主流中性格式。
子件转换模式下:装配体进行子件转换后,每个子零件会单独生成轻量化文件。支持进行子零件的局部更新,单装配体的预览加载速度会慢于模型转换。适用于 PDM/PLM 等对模型文件版本进行管理、子零件频繁更新的业务系统。


2. 集成业务场景
2.1 文件结构
业务端原始模型文件是一个zip格式的压缩包。其文件结构如下图:

- Lights:存放转换后的轻量化模型文件
- Models:存放待转换的原始模型文件
- Convert.json:与数据转换有关的参数信息
Convert.json 数据结构如下:
{
"Light": "Lights",
"Assembly": "Models\\asm0001.asm",
"Models": [
{
"Name": "Models\\asm0001.asm",
"Guid": "4C31EE9A8A544FDCA24A58D0411EA760",
"Path": "4C31EE9A8A544FDCA24A58D0411EA760"
}
]
}
字段 | 必填 | 描述 |
---|---|---|
Light | 是 | 存放轻量化文件的文件夹名称。首次转换时,其值为空;非首次转换时,其值默认为“Lights”。如果其值为空,则系统判断为首次转换。 |
Assembly | 是 | 顶层装配文件在压缩包里的相对路径。 |
Models | 是 | 装配体及其所有子装配和零件文件的相对路径及其Guid。Lights和输出文件夹里的轻量化文件以Guid命名 |
Guid | 是 | 不一定非得是GUID,只要保证独一无二即可。 |
Path | 否 | 轻量化文件的相对路径或轻量化文件的HTTP路径。如果为空,则默认同级目录Guid文件夹下路径。 |
2.2 首次转换
应用场景:装配体或零件首次独立转换时。
数据组织:Models 文件夹中存放原始模型文件,如下图。Lights 文件夹为空。

Convert.json 数据结构如下:
{
"Assembly": "Models\\asm0001.asm",
"Light": "",
"Models": [
{
"Name": "Models\\asm0001.asm",
"Guid": "4C31EE9A8A544FDCA24A58D0411EA760"
},
{
"Name": "Models\\prt0001.prt",
"Guid": "21ED1C58D5324C0C9BA4D43958336F35"
},
{
"Name": "Models\\asm0002.asm",
"Guid": "9FA1B25211B3412298A4C1692A248808"
},
{
"Name": "Models\\prt0002.prt",
"Guid": "2BB4CC323CC84E0B969A25A103C1083A"
}
]
}
2.3 新增修改转换
2.3.1 新增未转换过的模型
应用场景:顶层装配asm0001.asm 下面新增子装配asm0002.asm.2 和 零件prt0003.prt.2 。新增的子装配和零件均没有被转换过,不存在轻量化数据。需要转换新增的子装配和零件,并更新顶层装配的轻量化文件。
数据组织:Models 文件夹中存放新增的模型文件,及更新后的顶层装配文件。 Lights 文件夹中存放顶层装配体的轻量化文件 4C31EE9A8A544FDCA24A58D0411EA760 。

Convert.json 数据如下:
{
"Light": "Lights",
"Assembly": "Models\\asm0001.asm",
"Models": [
{
"Name": "Models\\asm0001.asm",
"Guid": "4C31EE9A8A544FDCA24A58D0411EA760"
},
{
"Name": "Models\\asm0002.asm.2",
"Guid": "9FA1B25211B3412298A4C1692A248808"
},
{
"Name": "Models\\prt0003.prt.2",
"Guid": "4C31EE9A8A544FDCA24A58D0411EA772"
}
]
}
2.3.2 新增已转换过的模型
应用场景:顶层装配asm0001.asm 下面新增子装配asm0002.asm.2 。新增的子装配已转换过,轻量化文件夹guid为9FA1B25211B3412298A4C1692A248808。数据转换时,不需要重新转换新增的子装配,只需要更新顶层装配的轻量化文件。
数据组织: Models 文件夹中存放新增子装配的原始模型文件,及更新后的顶层装配文件。 Lights 文件夹中存放顶层装配的轻量化文件 4C31EE9A8A544FDCA24A58D0411EA760 和 新增子装配的轻量化文件 9FA1B25211B3412298A4C1692A248808 。

Convert.json 数据如下:
{
"Light": "Lights",
"Assembly": "Models\\asm0001.asm",
"Models": [
{
"Name": "Models\\asm0001.asm",
"Guid": "4C31EE9A8A544FDCA24A58D0411EA760"
},
{
"Name": "Models\\asm0002.asm.2",
"Guid": "9FA1B25211B3412298A4C1692A248808"
}
]
}
2.3.3 模型更新-其父装配未更新
应用场景:子装配体asm0002.asm.2 下面的零件 prt0003.prt.2 有更新, 而子装配asm0002.asm.2 没有更新。数据转换时,只转换有更新的零件。
数据组织:Models 文件夹中存放更新后的原始模型文件,Lights 文件夹存为空。

Convert.json 数据如下:
{
"Assembly": "Models\\prt0003.prt.2",
"Light": "",
"Models": [
{
"Name": "Models\\prt0003.prt.2",
"Guid": "4C31EE9A8A544FDCA24A58D0411EA772"
}
]
}
2.3.4 模型更新-其父装配有更新
应用场景:子装配 asm0002.asm.2 下面的零件 prt0003.prt.2 有更新, 子装配asm0002.asm.2 也有更新。数据转换时,更新子装配和零件。
数据组织:Models 文件夹存放更新后的原始模型文件,Lights 文件夹存放子装配的轻量化文件 9FA1B25211B3412298A4C1692A248808 。

Convert.json 数据如下:
{
"Light": "Lights",
"Assembly": "Models\\asm0002.asm.2",
"Models": [
{
"Name": "Models\\asm0002.asm.2",
"Guid": "9FA1B25211B3412298A4C1692A248808"
},
{
"Name": "Models\\prt0003.prt.2",
"Guid": "4C31EE9A8A544FDCA24A58D0411EA772"
}
]
}
2.3.5 零件删除
应用场景:子装配体asm0002.asm.2 下面的零件 prt0003.prt.2 被删除。数据转换时,只需要更新对应子装配体的轻量化文件。
数据组织:Models 文件夹存放子装配的原始模型文件,Lights 文件夹存放子装配的轻量化文件。

Convert.json 数据如下:
{
"Light": "Lights",
"Assembly": "Models\\asm0002.asm.2",
"Models": [
{
"Name": "Models\\asm0002.asm.2",
"Guid": "9FA1B25211B3412298A4C1692A248808"
}
]
}
3. 接口调用
调用示例:
package com.newdim.demo;
import com.newdim.sdk.YunapiClient;
import com.newdim.sdk.models.*;
import org.json.JSONObject;
public class demo {
public static void main(String[] args) {
//本地插入文件名
String localFile = "F:\\temp\\model.zip";
//轻量化文件下载保存路径文件夹
String saveFile = "F:\\temp\\download";
//初始化celient partnerID, secretKey,apiServer
String partnerID = "xx";企业ID
String secretKey = "xx";密钥
String apiServer = "https://api.3dopen.cn";接口地址
YunapiClient yunapiClient = new YunapiClient(partnerID,secretKey,apiServer);
{
//单个子件转换任务
InsertTaskBaseRequest insertTaskRequest = new InsertTaskBaseRequest();
InsertTaskResponse res = yunapiClient.InsertPartConverTaskLocalFile(localFile,insertTaskRequest);
System.out.println(res.taskID);
if(res.taskID > 0){
try {
//查询任务
BaseTaskResponse info = yunapiClient.QueryTask(res.taskID);
while (info.getCode() == 1 && info.status < 2){
info = yunapiClient.QueryTask(res.taskID);
Thread.sleep(2*1000);
}
if(info.status == 2){
//下载轻量化数据
ResultStatus rs = yunapiClient.DownloadNdsFile(info.outputNdsFiles,saveFile);
System.out.println("下载code:"+rs.getCode() + " msg:" + rs.getMsg());
}
}catch (Exception e) {
System.out.println("error:"+e.getMessage());
}
}
}
}
调用示例:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YunApiSDK;
using YunApiSDK.Model.Request;
namespace YunApiSDKDemo
{
public class YunApiTest
{
/// <summary>
/// 基础流程
/// </summary>
/// <param name="yunapiClient"></param>
/// <param name="callbackUrl"></param>
/// <returns></returns>
public async Task Test()
{
string partnerID = "xx";企业ID
string secretKey = "xx";密钥
string apiServer = "https://api.3dopen.cn";接口地址
// 参数分别为门户网站中 开发接口-接口信息 中的企业ID、密钥、接口地址
var yunapiClient = new YunApiClient(partnerID, secretKey, apiServer);
var filePath = "F:\\model.zip";
var fileInfo = new FileInfo(filePath);
// 获取minio临时上传URL
var tempUrlRes = await yunapiClient.GetPresignedUploadUrlAsync(new GetPresignedUrlRequest { FileName = fileInfo.Name });
if (tempUrlRes.Status.Code != 1)
{
await Console.Out.WriteLineAsync(tempUrlRes.Status.Msg);
return;
}
// 使用minio临时授权URL上传文件
var uploadRes = await yunapiClient.UploadFileByNdsFileUrlAsync(tempUrlRes.Data.Url, filePath);
// 回调接口地址,如果需要回调则配置,不需要则不配置,地址为实际业务中开发的回调接口地址,本例为YunApiSDKCallbackDemo中的测试接口
// 插入任务
var insertRes = await yunapiClient.InsertPartConvertAddTaskAsync(new InsertPartConvertAddTaskRequest { InputNdsFile = tempUrlRes.Data.InputNdsFile, ReturnURL = "" });
if (insertRes.Status.Code != 1)
{
await Console.Out.WriteLineAsync(insertRes.Status.Msg);
return;
}
var taskState = 0;
var outputDataUrl = string.Empty;
// 此处使用while循环是为了得到轻量化文件下载地址,演示下载文件,实际情况可根据业务调整
while (taskState < 2)
{
// 查询接口
var queryRes = await yunapiClient.QueryTaskAsync(new QueryTaskRequest { TaskID = insertRes.Data.TaskID });
if (queryRes?.Status?.Code != 1)
{
break;
}
taskState = queryRes.Data?.Status ?? 5;
outputDataUrl = queryRes.Data?.OutputNdsFiles;
}
// 此段是演示下载轻量化文件,可根据实际情况自行调整
if (taskState == 2 && !string.IsNullOrEmpty(outputDataUrl))
{
var decodeUrl = Encoding.UTF8.GetString(Convert.FromBase64String(outputDataUrl));
// 此处是获取url中的文件名,可根据自己实际业务情况,确定要保存的文件名
Uri uri = new Uri(decodeUrl);
string fileName = System.IO.Path.GetFileName(uri.LocalPath);
// 简单使用,演示功能,最佳实践使用IHttpClientFactory.CreateClient()创建
var httpClient = new HttpClient();
using (HttpResponseMessage response = await httpClient.GetAsync(decodeUrl))
{
if (response.IsSuccessStatusCode)
{
using (var fileStream = await response.Content.ReadAsStreamAsync())
using (var outputFileStream = System.IO.File.Create(fileName))
{
await fileStream.CopyToAsync(outputFileStream);
}
Console.WriteLine("文件下载成功!");
}
else
{
Console.WriteLine("请求失败: " + response.ReasonPhrase);
}
}
}
}
}
}