autodesk-forgeautodesk-viewer

How to reproduce the sectionbox cut form revit in froge viewer?


I'm working on an app that can reproduce the section box cut from revit in forge viewer. I've got the max point and min point of section box using the code below in revit api:

BoundingBoxXYZ currentSectionBox = view3D.GetSectionBox();

double[] minPt = new double[] { 
  currentSectionBox.Transform.Origin.X + currentSectionBox.Min[0],
  currentSectionBox.Transform.Origin.Y + currentSectionBox.Min[1],
  currentSectionBox.Transform.Origin.Z + currentSectionBox.Min[2]
};

double[] maxPt = new double[] { 
  currentSectionBox.Transform.Origin.X + currentSectionBox.Max[0],
  currentSectionBox.Transform.Origin.Y + currentSectionBox.Max[1],
  currentSectionBox.Transform.Origin.Z + currentSectionBox.Max[2]
};

And it can be reproduced by this code same in the revit:

...
// View3D is the current opened 3d view in revit

View3D.SetSectionBox(new BoundingBoxXYZ() {
  Max = new XYZ(maxPt[0], maxPt[1], maxPt[2]), 
  Min = new XYZ(minPt[0], minPt[1], minPt[2]) 
});

So far so good, then I used the same max and min point in forge viewer. I expected to see the same result in revit, but it didn't. Is anything wrong in my code or I just misunderstand some concept about it?

let offset = this.Viewer3D.model.getData().globalOffset
offset = new THREE.Vector3(offset.x, offset.y, offset.y)

const sectionBoxPosition = new THREE.Box3(minPt.sub(offset), maxPt.sub(offset))
  
this.Viewer3D.loadExtension('Autodesk.Section').then(function (Section) {
  Section.setSectionBox(sectionBoxPosition)
})

Solution

  • The way you used to apply the global offset looks incorrect.

    I would advise you to do the calculation like the below using viewer.model.getModelToViewerTransform() to get the correct model to transform in the viewer. Sometimes, there are other transforms made to the model except for the global offset.

    var boxMinFromRvt = new THREE.Vector3(-20.9539269351606, -128.710696355516, -43.8630604978775); //!<<< From Revit API's BoundingBoxXYZ.Min
    var boxMaxFromRvt = new THREE.Vector3(73.7218284399634, 102.143481472216, 43.8630604978775); //!<<< From Revit API's BoundingBoxXYZ.Max
    
    var boxTransformFromRvt = new Autodesk.Viewing.Private.LmvMatrix4(true).fromArray([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 7.49058457162347, -35.3016883690933, 16.5749846091418, 1]);  //!<<< From Revit API's BoundingBoxXYZ. Transform
    
    var modelTransform = viewer.model.getModelToViewerTransform();
    
    var minOffseted = boxMinFromRvt.clone().applyMatrix4(boxTransformFromRvt).applyMatrix4(modelTransform);
    var maxOffseted = boxMaxFromRvt.clone().applyMatrix4(boxTransformFromRvt).applyMatrix4(modelTransform);
    
    var box = new THREE.Box3(minOffseted, maxOffseted);
    viewer.getExtension('Autodesk.Section').setSectionBox(box);
    

    Note. The boxTransformFromRvt is from Revit SectionBox's BoundingBox.Transform like below. The (0,0,0,1) is for w element of the transform matrix, as threejs' transform is 4x4 (xyzw), but what we get from Revit is 4x3.

    var boxTransformFromRvt = [
      Transform.BasicX.X, Transform.BasicX.Y, Transform.BasicX.Z, 0,
      Transform.BasicY.X, Transform.BasicY.Y, Transform.BasicY.Z, 0,
      Transform.BasicZ.X, Transform.BasicZ.Y, Transform.BasicZ.Z, 0,
      Transform.BasicZ.X, Transform.BasicZ.Y, Transform.BasicZ.Z, 0,
      Transform.Origin.X, Transform.Origin.Y, Transform.Origin.Z, 1
    ]
    

    Here are the snapshots of my tests: