Reputation: 109
I have been struggling to find the bounding box for a section made using Autodesk.Section extension.
A previous post on this subject suggests that we use following functions to extract the bounding box.
const sb = viewer.getExtension('Autodesk.Section')
sb.tool.getSectionBoxValues() OR
sb.tool.utilities.getBoundingBox()
However, this value works ONLY for the default section box that appears when Section > Add Box tool is clicked. It doesn't update the bounding box when section box is moved to another location (or resized).
Is there a mechanism to correctly extract the bounding box?
I have also tried to compute bounding box using CutPlanes array as follows.
const boundingBox = new THREE.Box3(new THREE.Vector3(cp[0].x * cp[0].w, cp[1].y * cp[1].w, cp[2].z * cp[2].w),
new THREE.Vector3(cp[3].x * cp[3].w, cp[4].y * cp[4].w, cp[5].z * cp[5].w))
Unfortunately, that doesn't give me the correct value either.
Any help would be appreciated. Thanks, Bandu
Upvotes: 0
Views: 556
Reputation: 7070
Unfortunately, according to our engineering team, the values of getSectionBoxValues()
won't be updated as expected. If you want to get the final values of the planes, you can call viewer.getCutPlanes()
instead.
Here is the code snippet demonstrating this idea.
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 box = new BoxMeshHelper(new THREE.Box3().setFromPoints(pts));
this.viewer.overlays.addMesh(box, this.overlayName);
/**
* Takes two planes and returns a Line3 which represents their intersection
* use len to specify how long the line should be
* @param {THREE.Plane} pl1
* @param {THREE.Plane} pl2
* @param {*} len How long the line should be
* @returns {THREE.Line3} Intersection Line
* // ref: https://discourse.threejs.org/t/is-it-possible-to-create-a-three-box3-from-a-three-fustum/6568/4
*/
intersectPlanes(pl1, pl2, len = 100000) {
let EXTENSION = 2000000;
let cp1 = pl1.normal.clone();
cp1.normalize();
cp1.negate();
cp1.multiplyScalar(pl1.constant);
let cp2 = pl2.normal.clone();
cp2.normalize();
cp2.negate();
cp2.multiplyScalar(pl2.constant);
// calculate cross product to derive direction of intersection line
let crPl1 = pl1.normal.clone();
let crPl2 = pl2.normal.clone();
let cr = crPl1.cross(crPl2);
cr.normalize();
let dtPl1 = pl1.normal.clone();
let dtPl2 = pl2.normal.clone();
let dot = dtPl1.dot(dtPl2);
let ang = Math.acos(dot) * (180 / Math.PI);
// return null if planes are identical or parallel
if (ang == 0 || ang == 180) return null;
// project point directly if planes are perpendicular
if (ang == 90 || ang == 270) {
let intPt = new THREE.Vector3();
pl2.projectPoint(cp1, intPt);
let intA = intPt.clone();
let intB = intPt.clone();
intA.addScaledVector(cr, len / 2);
intB.addScaledVector(cr, -len / 2);
let intLn = new THREE.Line3(intA, intB);
return intLn;
}
// project origin of first plane on to second plane
let projLnAStart = new THREE.Vector3(cp1.x, cp1.y, cp1.z).normalize();
projLnAStart.multiplyScalar(EXTENSION);
let projLnAEnd = new THREE.Vector3(-projLnAStart.x, -projLnAStart.y, -projLnAStart.z);
let int1 = new THREE.Vector3();
let projLnA = new THREE.Line3(projLnAStart, projLnAEnd);
pl2.intersectLine(projLnA, int1);
// project the intersection point back to first plane along the second plane
let projVcB = new THREE.Vector3();
projVcB.subVectors(int1, cp2).normalize();
projVcB.multiplyScalar(EXTENSION);
let projLnBStart = cp2.clone();
projLnBStart.add(projVcB);
let projLnBEnd = cp2.clone();
projLnBEnd.add(projVcB.negate());
let int2 = new THREE.Vector3();
let projLnB = new THREE.Line3(projLnBStart, projLnBEnd);
pl1.intersectLine(projLnB, int2);
// use cross vector and intersecttion point to create line
let intA = int2.clone();
let intB = int2.clone();
intA.addScaledVector(cr, len / 2);
intB.addScaledVector(cr, -len / 2);
let intLn = new THREE.Line3(intA, intB);
return intLn;
}
/**
* Get intersected points of section box planes
* @param {THREE.Frustum} frustum
* @returns {THREE.Vector3[]} Intersected points of section box planes
* // ref: https://discourse.threejs.org/t/is-it-possible-to-create-a-three-box3-from-a-three-fustum/6568/4
*/
getCorners(frustum) {
let lnLT = this.intersectPlanes(frustum.planes[0], frustum.planes[1]);
let lnRT = this.intersectPlanes(frustum.planes[1], frustum.planes[2]);
let lnRB = this.intersectPlanes(frustum.planes[2], frustum.planes[3]);
let lnLB = this.intersectPlanes(frustum.planes[3], frustum.planes[0]);
let int;
int = new THREE.Vector3();
frustum.planes[4].intersectLine(lnLT, int);
let ptLTN = int.clone();
int = new THREE.Vector3();
frustum.planes[5].intersectLine(lnLT, int);
let ptLTF = int.clone();
int = new THREE.Vector3();
frustum.planes[4].intersectLine(lnRT, int);
let ptRTN = int.clone();
int = new THREE.Vector3();
frustum.planes[5].intersectLine(lnRT, int);
let ptRTF = int.clone();
int = new THREE.Vector3();
frustum.planes[4].intersectLine(lnLB, int);
let ptLBN = int.clone();
int = new THREE.Vector3();
frustum.planes[5].intersectLine(lnLB, int);
let ptLBF = int.clone();
int = new THREE.Vector3();
frustum.planes[4].intersectLine(lnRB, int);
let ptRBN = int.clone();
int = new THREE.Vector3();
frustum.planes[5].intersectLine(lnRB, int);
let ptRBF = int.clone();
let pts = [ptLTN, ptLTF, ptRTN, ptRTF, ptLBN, ptLBF, ptRBN, ptRBF];
return pts;
}
Full Code: https://gist.github.com/yiskang/d3c088f2633228a474301ce68f764c68
Demo Video: https://youtu.be/zqzyshGe3-8
Upvotes: 1