根据 Revit 坐标(最小和最大 X、Y、Z)从锻造查看器裁剪特定 room/area
crop particular room/area from the forge viewer based on Revit coordinates(min and max X, Y, Z)
我们在我们的网络应用程序中使用 forge viewer(v7)。
我们的要求是从 forge 查看器中裁剪特定的 room/area。例如,如果我们在 forge 查看器中显示了一个房屋模型,那么如果用户 select 一个厨房(来自菜单或导航栏),那么查看器应该只显示厨房区域(包括它的所有对象,如橱柜、燃烧器、冰箱, sink 等)和所有其他 objects/sections 应该被隐藏。同样适用于卧室、浴室等。它仅供在 运行 时查看,不用于任何自动化。
在以下使用 forge API(使用 Revit 引擎)的帮助下,我们正在获取房间坐标(最小和最大 X、Y、Z)。
GeometryElement geoElement = room.ClosedShell;
BoundingBoxXYZ boundingBox = geoElement.GetBoundingBox();
XYZ min = boundingBox.Min;
XYZ max = boundingBox.Max;
我们正在使用 viewer.setCutPlanes 函数在查看器中绘制切面。
var minPt = new THREE.Vector3(x,y,z); //!<<< put your point here
var maxPt = new THREE.Vector3(x,y,z); //!<<< put your point here
const normals = [
new THREE.Vector3(1, 0, 0),
new THREE.Vector3(0, 1, 0),
new THREE.Vector3(0, 0, 1),
new THREE.Vector3(-1, 0, 0),
new THREE.Vector3(0, -1, 0),
new THREE.Vector3(0, 0, -1)
];
const bbox = new THREE.Box3(minPt, maxPt);
const cutPlanes = [];
for (let i = 0; i < normals.length; i++) {
const plane = new THREE.Plane(normals[i], -1 * maxPt.dot(normals[i]));
// offset plane with negative normal to form an octant
if (i > 2) {
const ptMax = plane.orthoPoint(bbox.max);
const ptMin = plane.orthoPoint(bbox.min);
const size = new THREE.Vector3().subVectors(ptMax, ptMin);
plane.constant -= size.length();
}
const n = new THREE.Vector4(plane.normal.x, plane.normal.y, plane.normal.z, plane.constant);
cutPlanes.push(n);
}
viewer.setCutPlanes(cutPlanes);
但是当我们将这些坐标(为 API 获得)传递给此前端 JS 代码时,切割平面将在不正确的 position/points 处创建。例如,当我们传递厨房的坐标时,它会裁剪屋顶的一小部分并且与所有其他房间相同。
可能的原因是Revit和forge viewer坐标不一样
有没有人知道我们如何使用 Forge 查看器映射这些 Revit 坐标并绘制切面?
我有另一个解决方案。手动修改模型,如剖切面、隐藏、隔离元素以检索要显示的视图。然后使用方法 var data = viewer.getState()
并将该数据存储到您的数据库中。然后使用 viewer.restoreState(data)
回顾您的观点。
如果您按照 Forge Viewer tutorial 加载模型,则需要从房间边界框的端点减去全局偏移,如下所示:
var minPt = new THREE.Vector3(x,y,z); //!<<< put your point here
var maxPt = new THREE.Vector3(x,y,z); //!<<< put your point here
var offsetMatrix = viewer.model.getData().placementWithOffset;
var offsetMinPt = minPt.applyMatrix4(offsetMatrix);
var offsetMaxPt = maxPt.applyMatrix4(offsetMatrix);
我们在我们的网络应用程序中使用 forge viewer(v7)。
我们的要求是从 forge 查看器中裁剪特定的 room/area。例如,如果我们在 forge 查看器中显示了一个房屋模型,那么如果用户 select 一个厨房(来自菜单或导航栏),那么查看器应该只显示厨房区域(包括它的所有对象,如橱柜、燃烧器、冰箱, sink 等)和所有其他 objects/sections 应该被隐藏。同样适用于卧室、浴室等。它仅供在 运行 时查看,不用于任何自动化。
在以下使用 forge API(使用 Revit 引擎)的帮助下,我们正在获取房间坐标(最小和最大 X、Y、Z)。
GeometryElement geoElement = room.ClosedShell;
BoundingBoxXYZ boundingBox = geoElement.GetBoundingBox();
XYZ min = boundingBox.Min;
XYZ max = boundingBox.Max;
我们正在使用 viewer.setCutPlanes 函数在查看器中绘制切面。
var minPt = new THREE.Vector3(x,y,z); //!<<< put your point here
var maxPt = new THREE.Vector3(x,y,z); //!<<< put your point here
const normals = [
new THREE.Vector3(1, 0, 0),
new THREE.Vector3(0, 1, 0),
new THREE.Vector3(0, 0, 1),
new THREE.Vector3(-1, 0, 0),
new THREE.Vector3(0, -1, 0),
new THREE.Vector3(0, 0, -1)
];
const bbox = new THREE.Box3(minPt, maxPt);
const cutPlanes = [];
for (let i = 0; i < normals.length; i++) {
const plane = new THREE.Plane(normals[i], -1 * maxPt.dot(normals[i]));
// offset plane with negative normal to form an octant
if (i > 2) {
const ptMax = plane.orthoPoint(bbox.max);
const ptMin = plane.orthoPoint(bbox.min);
const size = new THREE.Vector3().subVectors(ptMax, ptMin);
plane.constant -= size.length();
}
const n = new THREE.Vector4(plane.normal.x, plane.normal.y, plane.normal.z, plane.constant);
cutPlanes.push(n);
}
viewer.setCutPlanes(cutPlanes);
但是当我们将这些坐标(为 API 获得)传递给此前端 JS 代码时,切割平面将在不正确的 position/points 处创建。例如,当我们传递厨房的坐标时,它会裁剪屋顶的一小部分并且与所有其他房间相同。
可能的原因是Revit和forge viewer坐标不一样
有没有人知道我们如何使用 Forge 查看器映射这些 Revit 坐标并绘制切面?
我有另一个解决方案。手动修改模型,如剖切面、隐藏、隔离元素以检索要显示的视图。然后使用方法 var data = viewer.getState()
并将该数据存储到您的数据库中。然后使用 viewer.restoreState(data)
回顾您的观点。
如果您按照 Forge Viewer tutorial 加载模型,则需要从房间边界框的端点减去全局偏移,如下所示:
var minPt = new THREE.Vector3(x,y,z); //!<<< put your point here
var maxPt = new THREE.Vector3(x,y,z); //!<<< put your point here
var offsetMatrix = viewer.model.getData().placementWithOffset;
var offsetMinPt = minPt.applyMatrix4(offsetMatrix);
var offsetMaxPt = maxPt.applyMatrix4(offsetMatrix);