diff --git a/src/Add-on/Copy.ts b/src/Add-on/Copy.ts index 613319a69..949b6e4dc 100644 --- a/src/Add-on/Copy.ts +++ b/src/Add-on/Copy.ts @@ -1,5 +1,4 @@ import { Intent } from '@blueprintjs/core'; -import { OBB } from 'three/examples/jsm/math/OBB'; import { app } from '../ApplicationServices/Application'; import { Log, LogType } from '../Common/Log'; import { DuplicateRecordCloning } from '../Common/Status'; @@ -301,36 +300,28 @@ export class Command_Copy implements Command } else if (e instanceof HardwareCompositeEntity)//五金 { - //如果仅仅复制了五金,但是没有复制五金关联的板(复合板),我们对它进行重新关联 - let oldId = GetOldObjectId(e.Id); let oldE = oldId.Object as HardwareCompositeEntity; - let newEObb: OBB; for (let id of oldE.RelevanceBoards) { if (!id || id.IsErase) continue; - let ent = id.Object as Entity; - - if (olds.has(ent)) continue;//复制了五金 也复制了板 - - //我们求obb 如果不相交,我们不再关联它 - newEObb = newEObb || e.OBB; - let entObb = ent.OBB; - entObb.halfSize.addScalar(10); - if (!entObb.intersectsOBB(newEObb)) - continue; - - //只复制了五金 却没复制板(或复合板) - if (ent instanceof Board) + let ent = id.Object; + if (ent instanceof Board)//只复制了五金 却没复制板 { - e.RelevanceBoards.push(ent.Id); - ent.RelativeHardware.push(e.Id); + if (!olds.has(ent)) + { + e.RelevanceBoards.push(ent.Id); + ent.RelativeHardware.push(e.Id); + } } else if (ent instanceof HardwareCompositeEntity) //复合板 { - e.RelevanceBoards.push(ent.Id); - ent.RelevanceHardware.push(e.Id); + if (!olds.has(ent)) + { + e.RelevanceBoards.push(ent.Id); + ent.RelevanceHardware.push(e.Id); + } } } } diff --git a/src/Add-on/DrawDim/DimBoards.ts b/src/Add-on/DrawDim/DimBoards.ts index 5abb54b79..88d214f4b 100644 --- a/src/Add-on/DrawDim/DimBoards.ts +++ b/src/Add-on/DrawDim/DimBoards.ts @@ -11,7 +11,7 @@ import { Polyline } from "../../DatabaseServices/Entity/Polyline"; import { Region } from "../../DatabaseServices/Entity/Region"; import { TemplateRecord } from "../../DatabaseServices/Template/TemplateRecord"; import { AsVector2, ZAxis, equaln, equalnn, isParallelTo, isPerpendicularityTo, midPoint } from "../../Geometry/GeUtils"; -import { GetObbFromOcsSize } from "../../Geometry/OBB/obb"; +import { OBB } from "../../Geometry/OBB/obb"; import { BoolOpeartionType } from "../../GraphicsSystem/BoolOperateUtils"; import { ForBoardNameType } from "../../UI/Store/OptionInterface/AutoDimBrsOption"; import { TestDraw } from "../test/TestUtil"; @@ -285,7 +285,7 @@ export class DimBoards let ocs = new Matrix4().makeBasis(_x, _y, _z).setPosition(c.StartPoint.setZ(-5000)) .premultiply(spaceFrontCS); - let cuObb = GetObbFromOcsSize(ocs, new Vector3(c.Length, 20, 10000)); + let cuObb = new OBB(ocs, new Vector3(c.Length, 20, 10000)); for (let br of brs) { diff --git a/src/Common/InterfereUtil.ts b/src/Common/InterfereUtil.ts index 216832b38..61f197b14 100644 --- a/src/Common/InterfereUtil.ts +++ b/src/Common/InterfereUtil.ts @@ -1,6 +1,5 @@ import { Geom3 } from "@jscad/modeling/src/geometries/types"; import { Box3, Material, Mesh } from "three"; -import { OBB } from "three/examples/jsm/math/OBB"; import { ExtrudeHole } from "../DatabaseServices/3DSolid/ExtrudeHole"; import { SweepSolid } from "../DatabaseServices/3DSolid/SweepSolid"; import { Board } from "../DatabaseServices/Entity/Board"; @@ -12,6 +11,7 @@ import { ProcessingGroupRecord } from "../DatabaseServices/ProcessingGroup/Proce import { TemplateLatticeRecord } from "../DatabaseServices/Template/ProgramTempate/TemplateLatticeRecord"; import { TemplateWineRackRecord } from "../DatabaseServices/Template/ProgramTempate/TemplateWineRackRecord"; import { BoxIsSolid } from "../Geometry/Box"; +import { OBB } from "../Geometry/OBB/obb"; import { FuzzyFactory } from "../csg/core/FuzzyFactory"; import { CSG2Geometry2, Geometry2CSG2 } from "../csg/core/Geometry2CSG"; import { CSGIntersect } from "./CSGIntersect"; diff --git a/src/DatabaseServices/3DSolid/ExtrudeHole.ts b/src/DatabaseServices/3DSolid/ExtrudeHole.ts index 2935eb107..64ca5b1ec 100644 --- a/src/DatabaseServices/3DSolid/ExtrudeHole.ts +++ b/src/DatabaseServices/3DSolid/ExtrudeHole.ts @@ -22,6 +22,7 @@ import { GenUVForWorld } from "../Entity/GenUVForWorld"; import { Polyline } from "../Entity/Polyline"; import { PhysicalMaterialRecord } from "../PhysicalMaterialRecord"; import { Shape } from "../Shape"; +import { OBB } from './../../Geometry/OBB/obb'; import { Hole } from "./Hole"; @Factory @@ -450,6 +451,11 @@ export class ExtrudeHole extends Hole mesh.material = ColorMaterial.GetConceptualMaterial(this.ColorIndex); } } + get OBB(): OBB + { + let size = this.ContourCurve.BoundingBox.getSize(new Vector3).setZ(this.Height); + return new OBB(this.OCS, size.multiplyScalar(0.5)); + } ReadFile(file: CADFiler) { super.ReadFile(file); diff --git a/src/DatabaseServices/3DSolid/SweepSolid.ts b/src/DatabaseServices/3DSolid/SweepSolid.ts index 2d9630736..edbd54ed8 100644 --- a/src/DatabaseServices/3DSolid/SweepSolid.ts +++ b/src/DatabaseServices/3DSolid/SweepSolid.ts @@ -21,6 +21,7 @@ import { Line } from "../Entity/Line"; import { Polyline } from '../Entity/Polyline'; import { IsPointInPolyLine } from '../PointInPolyline'; import { Spline } from "../Spline"; +import { OBB } from './../../Geometry/OBB/obb'; @Factory export class SweepSolid extends Entity @@ -362,6 +363,12 @@ export class SweepSolid extends Entity return geom.boundingBox.clone().applyMatrix4(this._Matrix); } + get OBB(): OBB + { + let box = this.BoundingBox; + let size = box.getSize(new Vector3); + return new OBB(MoveMatrix(box.min), size.multiplyScalar(0.5)); + } GetObjectSnapPoints( snapMode: ObjectSnapMode, pickPoint: Vector3, diff --git a/src/DatabaseServices/Entity/Entity.ts b/src/DatabaseServices/Entity/Entity.ts index 6ae2601a5..868080f12 100644 --- a/src/DatabaseServices/Entity/Entity.ts +++ b/src/DatabaseServices/Entity/Entity.ts @@ -1,5 +1,4 @@ -import { Material, Matrix3, Matrix4, MeshStandardMaterial, Object3D, Quaternion, Vector3 } from 'three'; -import { OBB } from 'three/examples/jsm/math/OBB'; +import { Material, Matrix3, Matrix4, MeshStandardMaterial, Object3D, Vector3 } from 'three'; import { iaop } from 'xaop'; import { HostApplicationServices } from '../../ApplicationServices/HostApplicationServices'; import { DisposeThreeObj, Object3DRemoveAll } from '../../Common/Dispose'; @@ -162,17 +161,6 @@ export class Entity extends CADObject */ Explode(): Entity[] { return []; } - get OBB(): OBB - { - let ocs = this.OCSNoClone; - let box = this.BoundingBoxInOCS; - let center = box.getCenter(new Vector3); - center.applyMatrix4(ocs); - let size = box.getSize(new Vector3).multiplyScalar(0.5); - let qua = new Quaternion().setFromRotationMatrix(ocs);//因为ijk变了 所以obb 错了 - return new OBB(center, size, new Matrix3().setFromMatrix4(new Matrix4().makeRotationFromQuaternion(qua))); - } - /** * 返回对象的包围框. */ diff --git a/src/DatabaseServices/Entity/Extrude.ts b/src/DatabaseServices/Entity/Extrude.ts index 18ab23630..9f996be51 100644 --- a/src/DatabaseServices/Entity/Extrude.ts +++ b/src/DatabaseServices/Entity/Extrude.ts @@ -20,6 +20,7 @@ import { FastExtrudeEdgeGeometry, FastExtrudeEdgeGeometryOfShape, FastWireframe import { EdgesGeometry } from "../../Geometry/EdgeGeometry"; import { ExtrudeGeometryBuilder } from "../../Geometry/ExtrudeMeshGeomBuilder/ExtrudeEdgeGeometry2"; import { AsVector2, IdentityMtx4, MoveMatrix, XAxis, YAxis, ZAxis, ZeroVec, equaln, equalv2, equalv3, isIntersect, isParallelTo, isPerpendicularityTo } from "../../Geometry/GeUtils"; +import { OBB } from "../../Geometry/OBB/obb"; import { ScaleUV, ScaleUV2 } from "../../Geometry/UVUtils"; import { RenderType } from "../../GraphicsSystem/RenderType"; import { Geometry2CSG2 } from "../../csg/core/Geometry2CSG"; @@ -158,6 +159,11 @@ export class ExtrudeSolid extends Entity return new Box3Ext().setFromPoints([new Vector3, new Vector3(this.width, this.height, this.thickness)]); } + get OBB(): OBB + { + return new OBB(this.OCS, new Vector3(this.width, this.height, this.thickness).multiplyScalar(0.5)); + } + get GroovesAddLength() { return this.groovesAddLength; diff --git a/src/Geometry/OBB/obb.ts b/src/Geometry/OBB/obb.ts index d9b5fe264..f72173846 100644 --- a/src/Geometry/OBB/obb.ts +++ b/src/Geometry/OBB/obb.ts @@ -1,15 +1,249 @@ +import { Vector3, Matrix4 } from 'three'; -import { Matrix3, Matrix4, Vector3 } from 'three'; -import { OBB } from "three/examples/jsm/math/OBB"; +// Quote from: +// https://github.com/Mugen87/yume/blob/master/src/javascript/engine/etc/OBB.js +// 即obb.js(本项目中已存在) -/** - * @param ocs 坐标系 - * @param size 尺寸 - * @returns OBB - */ -export function GetObbFromOcsSize(ocs: Matrix4, size: Vector3): OBB +// Reference material: +//https://stackoverflow.com/questions/28499800/oriented-box-intersection-in-threejs +//http://www.cnblogs.com/iamzhanglei/archive/2012/06/07/2539751.html +//https://github.com/Mugen87/yume/blob/master/src/javascript/engine/etc/OBB.js + +export class OBB { - size = size.clone().multiplyScalar(0.5); - let center = size.clone().applyMatrix4(ocs); - return new OBB(center, size, new Matrix3().setFromMatrix4(ocs)); + _EPSILON = 1e-3; + + public center: Vector3; + + constructor(public ocs: Matrix4, public halfSizes: Vector3) + { + this.center = halfSizes.clone().applyMatrix4(ocs); + } + + intersectsOBB(obb: OBB, is2D?: boolean, ucsInv?: Matrix4): boolean + { + let newCenter: Vector3; + let newObbCenter: Vector3; + let cs: Matrix4; + let obbcs: Matrix4; + if (is2D) + { + let mtx1 = new Matrix4().multiplyMatrices(ucsInv, this.ocs); + let mtx2 = new Matrix4().multiplyMatrices(ucsInv, obb.ocs); + cs = mtx1; + obbcs = mtx2; + cs.elements[14] = 0; + obbcs.elements[14] = 0; + newCenter = this.halfSizes.clone().applyMatrix4(cs); + newObbCenter = obb.halfSizes.clone().applyMatrix4(obbcs); + } + let xAxisA = new Vector3(); + let yAxisA = new Vector3(); + let zAxisA = new Vector3(); + + let xAxisB = new Vector3(); + let yAxisB = new Vector3(); + let zAxisB = new Vector3(); + + let translation = new Vector3(); + + let vector = new Vector3(); + + let axisA: Vector3[] = []; + let axisB: Vector3[] = []; + let rotationMatrix = [[], [], []]; + let rotationMatrixAbs = [[], [], []]; + + let halfSizeA: number, halfSizeB: number; + let t: number, i: number; + + // extract each axis + (cs ?? this.ocs).extractBasis(xAxisA, yAxisA, zAxisA); + (obbcs ?? obb.ocs).extractBasis(xAxisB, yAxisB, zAxisB); + + // push basis vectors into arrays, so you can access them via indices + axisA.push(xAxisA, yAxisA, zAxisA); + axisB.push(xAxisB, yAxisB, zAxisB); + + // get displacement vector + vector.subVectors(newObbCenter ?? obb.center, newCenter ?? this.center); + + // express the translation vector in the coordinate frame of the current + // OBB (this) + for (i = 0; i < 3; i++) + { + translation.setComponent(i, vector.dot(axisA[i])); + } + + // generate a rotation matrix that transforms from world space to the + // OBB's coordinate space + for (i = 0; i < 3; i++) + { + for (let j = 0; j < 3; j++) + { + rotationMatrix[i][j] = axisA[i].dot(axisB[j]); + rotationMatrixAbs[i][j] = Math.abs(rotationMatrix[i][j]) + this._EPSILON; + } + } + + // test the three major axes of this OBB + for (i = 0; i < 3; i++) + { + vector.set(rotationMatrixAbs[i][0], rotationMatrixAbs[i][1], rotationMatrixAbs[i][2]); + + halfSizeA = this.halfSizes.getComponent(i); + halfSizeB = obb.halfSizes.dot(vector); + + if (Math.abs(translation.getComponent(i)) > halfSizeA + halfSizeB) + { + return false; + } + } + + // test the three major axes of other OBB + for (i = 0; i < 3; i++) + { + vector.set(rotationMatrixAbs[0][i], rotationMatrixAbs[1][i], rotationMatrixAbs[2][i]); + + halfSizeA = this.halfSizes.dot(vector); + halfSizeB = obb.halfSizes.getComponent(i); + + vector.set(rotationMatrix[0][i], rotationMatrix[1][i], rotationMatrix[2][i]); + t = translation.dot(vector); + + if (Math.abs(t) > halfSizeA + halfSizeB) + { + return false; + } + } + + // test the 9 different cross-axes + + // A.x B.x + halfSizeA = this.halfSizes.y * rotationMatrixAbs[2][0] + this.halfSizes.z * rotationMatrixAbs[1][0]; + halfSizeB = obb.halfSizes.y * rotationMatrixAbs[0][2] + obb.halfSizes.z * rotationMatrixAbs[0][1]; + + t = translation.z * rotationMatrix[1][0] - translation.y * rotationMatrix[2][0]; + + if (Math.abs(t) > halfSizeA + halfSizeB) + { + return false; + } + + // A.x < cross> B.y + halfSizeA = this.halfSizes.y * rotationMatrixAbs[2][1] + this.halfSizes.z * rotationMatrixAbs[1][1]; + halfSizeB = obb.halfSizes.x * rotationMatrixAbs[0][2] + obb.halfSizes.z * rotationMatrixAbs[0][0]; + + t = translation.z * rotationMatrix[1][1] - translation.y * rotationMatrix[2][1]; + + if (Math.abs(t) > halfSizeA + halfSizeB) + { + return false; + } + + // A.x B.z + halfSizeA = this.halfSizes.y * rotationMatrixAbs[2][2] + this.halfSizes.z * rotationMatrixAbs[1][2]; + halfSizeB = obb.halfSizes.x * rotationMatrixAbs[0][1] + obb.halfSizes.y * rotationMatrixAbs[0][0]; + + t = translation.z * rotationMatrix[1][2] - translation.y * rotationMatrix[2][2]; + + if (Math.abs(t) > halfSizeA + halfSizeB) + { + return false; + } + + // A.y B.x + halfSizeA = this.halfSizes.x * rotationMatrixAbs[2][0] + this.halfSizes.z * rotationMatrixAbs[0][0]; + halfSizeB = obb.halfSizes.y * rotationMatrixAbs[1][2] + obb.halfSizes.z * rotationMatrixAbs[1][1]; + + t = translation.x * rotationMatrix[2][0] - translation.z * rotationMatrix[0][0]; + + if (Math.abs(t) > halfSizeA + halfSizeB) + { + return false; + } + + // A.y B.y + halfSizeA = this.halfSizes.x * rotationMatrixAbs[2][1] + this.halfSizes.z * rotationMatrixAbs[0][1]; + halfSizeB = obb.halfSizes.x * rotationMatrixAbs[1][2] + obb.halfSizes.z * rotationMatrixAbs[1][0]; + + t = translation.x * rotationMatrix[2][1] - translation.z * rotationMatrix[0][1]; + + if (Math.abs(t) > halfSizeA + halfSizeB) + { + return false; + } + + // A.y B.z + halfSizeA = this.halfSizes.x * rotationMatrixAbs[2][2] + this.halfSizes.z * rotationMatrixAbs[0][2]; + halfSizeB = obb.halfSizes.x * rotationMatrixAbs[1][1] + obb.halfSizes.y * rotationMatrixAbs[1][0]; + + t = translation.x * rotationMatrix[2][2] - translation.z * rotationMatrix[0][2]; + + if (Math.abs(t) > halfSizeA + halfSizeB) + { + return false; + } + + // A.z B.x + halfSizeA = this.halfSizes.x * rotationMatrixAbs[1][0] + this.halfSizes.y * rotationMatrixAbs[0][0]; + halfSizeB = obb.halfSizes.y * rotationMatrixAbs[2][2] + obb.halfSizes.z * rotationMatrixAbs[2][1]; + + t = translation.y * rotationMatrix[0][0] - translation.x * rotationMatrix[1][0]; + + if (Math.abs(t) > halfSizeA + halfSizeB) + { + return false; + } + + // A.z B.y + halfSizeA = this.halfSizes.x * rotationMatrixAbs[1][1] + this.halfSizes.y * rotationMatrixAbs[0][1]; + halfSizeB = obb.halfSizes.x * rotationMatrixAbs[2][2] + obb.halfSizes.z * rotationMatrixAbs[2][0]; + + t = translation.y * rotationMatrix[0][1] - translation.x * rotationMatrix[1][1]; + + if (Math.abs(t) > halfSizeA + halfSizeB) + { + return false; + } + + // A.z B.z + halfSizeA = this.halfSizes.x * rotationMatrixAbs[1][2] + this.halfSizes.y * rotationMatrixAbs[0][2]; + halfSizeB = obb.halfSizes.x * rotationMatrixAbs[2][1] + obb.halfSizes.y * rotationMatrixAbs[2][0]; + + t = translation.y * rotationMatrix[0][2] - translation.x * rotationMatrix[1][2]; + + if (Math.abs(t) > halfSizeA + halfSizeB) + { + return false; + } + + // no separating axis exists, so the two OBB don't intersect + return true; + } + + // setFromObject(obj: THREE.Mesh): OBB; + // setFromAABB(aabb: THREE.Box3): OBB; + + // setFromSphere(sphere: THREE.Shape): OBB; + + // closestPoint(point: THREE.Vector3): THREE.Vector3 + // isPointContained(point: THREE.Vector3): boolean + // isAABBContained(aabb: THREE.Box3): boolean + // isLineContained(line: THREE.Line3): boolean + // isTriangleContained(tarianlg: THREE.Triangle): boolean + // intersectsAABB(box: THREE.Box3): boolean + // intersectsSphere(sphere: THREE.Sphere): boolean + // intersectsOBB(box: OBB): boolean; + // intersectsPlane(plane: Plane): boolean + // intersectsRay(ray: Ray): boolean + // intersectRay(ray: Ray): Vector3 + // intersectSphere(sphere: Sphere): Vector3 + // size(optionalTarget: Vector3): Vector3 + + // translate(offset: Vector3): OBB + + // copy(obb: OBB): OBB + // clone(obb: OBB): OBB + }