I would like to know how could I restore a SectionBox from Forge back to Revit.
In Forge Viwer, I have a SectionBox defined by its 6 planes. As far as I know, for clipping in a Revit 3d view we need to define a BoudingBox (not planes). Is that correct ?
I could manage in the other way around like this :
private List<double[]> GetCutPlanes(BoundingBoxXYZ bbox)
{
List<double[]> planesList = new List<double[]>();
Autodesk.Revit.DB.Transform t = bbox.Transform;
XYZ min = bbox.Min;
XYZ max = bbox.Max;
// Conversion factor from feet to meters
const double conversionFactor = 0.3048;
// Local helper function to create a plane in the [nx, ny, nz, d] format.
double[] CreatePlane(XYZ normal, XYZ point)
{
// Transform the point and the normal using the bounding box's transform.
XYZ pt = t.OfPoint(point);
XYZ n = normal;
double d = -(n.X * pt.X + n.Y * pt.Y + n.Z * pt.Z) * conversionFactor;
return new double[] { -normal.X, -normal.Y, -normal.Z, d };
}
// Corrected reference points for each plane
planesList.Add(CreatePlane(new XYZ(-1, 0, 0), new XYZ(min.X, min.Y, min.Z))); // X-min
planesList.Add(CreatePlane(new XYZ(1, 0, 0), new XYZ(max.X, min.Y, min.Z))); // X-max
planesList.Add(CreatePlane(new XYZ(0, -1, 0), new XYZ(min.X, min.Y, max.Z))); // Y-min
planesList.Add(CreatePlane(new XYZ(0, 1, 0), new XYZ(min.X, max.Y, max.Z))); // Y-max
planesList.Add(CreatePlane(new XYZ(0, 0, -1), new XYZ(min.X, min.Y, min.Z))); // Z-min
planesList.Add(CreatePlane(new XYZ(0, 0, 1), new XYZ(min.X, min.Y, max.Z))); // Z-max
return planesList;
}
How could I go from Forge to Revit ?
We can convert the viewer's section box to a Revit one like the following.
const cutPlanes = this.viewer.getCutPlanes();
if (cutPlanes.length <= 6) return;
let planes = cutPlanes.map(p => new THREE.Plane().setComponents(p.x, p.y, p.z, p.w))
let frustum = new THREE.Frustum(
planes[3],
planes[1],
planes[0],
planes[4],
planes[5],
planes[2]
);
let pts = this.getCorners(frustum);
let boundingBox = new THREE.Box3().setFromPoints(pts); //!<<< Bounding box of the viwer section box
// Do necessary coordinate mapping here. e.g., to Revit space apply the `model.getInverseModelToViewerTransform()` to `boundingBox.max` and `boundingBox.min`
let model = viewer.getAllModels()[0];
let boundingBoxInRevitSpace = boundingBoxapplyMatrix4 (model.getInverseModelToViewerTransform());
let boundingBoxStringInRevitSpace = JSON.stringfy(boundingBoxInRevitSpace);
In Revit, we set bounding box like this way
// Suppose we can a custom class for mapping BoundingBox from APS Viewer called ApsBoundingBox
var boundingBox = JsonConvert.DeserializeObject<ApsBoundingBox>(boundingBoxStringInRevitSpace);
view3D.SetSectionBox(new BoundingBoxXYZ() {
Max = new XYZ(boundingBox.Max.X, boundingBox.Max.Y, boundingBox.Max.Z),
Min = new XYZ(boundingBox.Min.X, boundingBox.Min.Y, boundingBox.Min.Z)
});
Related readings: