如何无需Forge Viewer通过服务端API创建BIM 360 Pushpin问题?
无需前端Viewer,批量创建BIM 360带Pushpin的问题
我明白你想要纯服务端批量生成数百个关联文档的Pushpin问题,不用每次打开Viewer——这完全可行,核心是用Model Derivative API获取必要的图纸信息,再程序化构造Pushpin的位置和视图状态参数。下面一步步拆解:
一、获取图纸GUID(sheetGuid)
对于BIM 360中的2D图纸,sheetGuid其实是该文档衍生出来的2D视图的GUID,可以通过Model Derivative API从服务端获取:
- 首先调用
GET /modelderivative/v2/designdata/{urn}/metadata,获取文档的元数据结构,拿到根节点的guid(记为modelGuid)。 - 接着调用
GET /modelderivative/v2/designdata/{urn}/metadata/{modelGuid}/views,这个接口会返回该文档所有的视图列表——2D图纸对应的就是type为2d的条目,它的guid就是你需要的sheetGuid。
如果是3D模型,is3D设为true,sheetGuid可以直接用模型根节点的guid。
二、程序化生成position和viewerState
1. issue.position(Pushpin位置)
对于2D图纸,position是一个包含x、y、z的对象:
z值固定为0即可(因为是2D平面)x和y可以基于图纸的边界范围计算:
从GET /modelderivative/v2/designdata/{urn}/metadata/{modelGuid}/views/{sheetGuid}接口可以拿到图纸的boundingBox(包含min和max坐标),比如取中心位置:
如果有具体的点位需求,也可以直接传入自定义的坐标值(只要在图纸范围内即可)。const boundingBox = viewData.boundingBox; const position = { x: (boundingBox.min.x + boundingBox.max.x) / 2, y: (boundingBox.min.y + boundingBox.max.y) / 2, z: 0 };
对于3D模型,position就是模型空间中的三维坐标,同样可以通过模型的边界或自定义点位生成。
2. issue.viewerState(视图状态)
视图状态是描述Viewer视角的JSON对象,对于2D图纸,你可以程序化构造一个基础的状态,确保Pushpin位置在视图中心:
const viewerState = { type: '2d', viewport: { name: 'Default View', zoom: 1, position: { x: 0, y: 0 }, target: { x: position.x, y: position.y, z: 0 } }, seedUrn: '<你的文档URN>', sheetGuid: sheetGuid };
如果需要更精准的视角,也可以参考Viewer中导出的viewerState结构,调整zoom、position等参数即可。
三、Node.js代码示例
下面是完整的服务端流程示例,包含获取sheetGuid、构造参数、调用问题创建接口:
const axios = require('axios'); // 配置参数 const FORGE_CLIENT_ID = '你的Client ID'; const FORGE_CLIENT_SECRET = '你的Client Secret'; const CONTAINER_ID = 'BIM 360项目的Container ID'; const DOCUMENT_URN = 'BIM 360文档的URN(注意要Base64编码)'; // 第一步:获取访问令牌 async function getAccessToken() { const response = await axios.post( 'https://developer.api.autodesk.com/authentication/v2/token', new URLSearchParams({ grant_type: 'client_credentials', scope: 'data:read data:write bucket:create bucket:read' }), { auth: { username: FORGE_CLIENT_ID, password: FORGE_CLIENT_SECRET } } ); return response.data.access_token; } // 第二步:获取图纸的sheetGuid async function getSheetGuid(accessToken) { // 获取模型元数据 const metadataRes = await axios.get( `https://developer.api.autodesk.com/modelderivative/v2/designdata/${DOCUMENT_URN}/metadata`, { headers: { Authorization: `Bearer ${accessToken}` } } ); const modelGuid = metadataRes.data.data.metadata[0].guid; // 获取视图列表 const viewsRes = await axios.get( `https://developer.api.autodesk.com/modelderivative/v2/designdata/${DOCUMENT_URN}/metadata/${modelGuid}/views`, { headers: { Authorization: `Bearer ${accessToken}` } } ); // 取第一个2D视图的guid作为sheetGuid(根据你的需求调整) const sheetView = viewsRes.data.data.find(view => view.type === '2d'); return sheetView.guid; } // 第三步:创建Pushpin问题 async function createPushpinIssue(accessToken, sheetGuid, position, viewerState) { const issueData = { title: '批量生成的Pushpin问题', description: '通过服务端API自动创建的关联文档问题', status: 'open', issueType: 'quality', position: { type: 'TwoDVectorPushpin', sheetMetadata: { is3D: false, sheetGuid: sheetGuid, sheetName: '图纸名称(可从元数据获取)' }, pushpinAttributes: { location: position, viewerState: viewerState } } }; const response = await axios.post( `https://developer.api.autodesk.com/issues/v1/containers/${CONTAINER_ID}/quality-issues`, issueData, { headers: { Authorization: `Bearer ${accessToken}` } } ); return response.data; } // 主流程 async function run() { try { const token = await getAccessToken(); const sheetGuid = await getSheetGuid(token); // 获取图纸边界,构造position const viewRes = await axios.get( `https://developer.api.autodesk.com/modelderivative/v2/designdata/${DOCUMENT_URN}/metadata/${sheetGuid}/views/${sheetGuid}`, { headers: { Authorization: `Bearer ${token}` } } ); const boundingBox = viewRes.data.data.boundingBox; const position = { x: (boundingBox.min.x + boundingBox.max.x) / 2, y: (boundingBox.min.y + boundingBox.max.y) / 2, z: 0 }; // 构造viewerState const viewerState = { type: '2d', viewport: { zoom: 1, position: { x: 0, y: 0 }, target: { x: position.x, y: position.y, z: 0 } }, seedUrn: DOCUMENT_URN, sheetGuid: sheetGuid }; // 批量创建示例(这里循环创建10个,你可以调整为数百个) for (let i = 0; i < 10; i++) { const issue = await createPushpinIssue(token, sheetGuid, position, viewerState); console.log(`创建成功的问题ID: ${issue.id}`); } } catch (error) { console.error('出错了:', error.response?.data || error.message); } } run();
注意事项:
- 确保你的Client ID拥有
data:read和data:write的权限,并且已经关联到目标BIM 360项目。 - 批量创建时建议加入适当的延迟,避免触发API速率限制。
内容的提问来源于stack exchange,提问作者Ahmad Hisham
相关产品推荐
相关产品推荐

