123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107 |
- /*
- * BooleanOperator.js
- *
- * @author realor
- */
- import { ObjectBuilder } from './ObjectBuilder.js'
- import { SolidBuilder } from './SolidBuilder.js'
- import { SolidGeometry } from '../core/SolidGeometry.js'
- import { Solid } from '../core/Solid.js'
- import { BSP } from '../core/BSP.js'
- import * as THREE from '../lib/three.module.js'
- class BooleanOperator extends SolidBuilder {
- static UNION = 'union'
- static INTERSECT = 'intersect'
- static SUBTRACT = 'subtract'
- constructor(operation) {
- super()
- this.operation = operation || BooleanOperator.SUBTRACT
- }
- performBuild(solid) {
- const solids = []
- this.findSolids(solid, solids)
- if (solids.length === 0) return true
- const matrix = new THREE.Matrix4()
- const createBSP = child => {
- matrix.copy(child.matrix)
- let parent = child.parent
- while (parent && parent !== solid) {
- matrix.premultiply(parent.matrix)
- parent = parent.parent
- }
- const bsp = new BSP()
- bsp.fromSolidGeometry(child.geometry, matrix)
- return bsp
- }
- let resultBSP = createBSP(solids[0])
- for (let i = 1; i < solids.length; i++) {
- let solid = solids[i]
- if (solid.isValid()) {
- let otherBSP = createBSP(solid)
- switch (this.operation) {
- case BooleanOperator.UNION:
- resultBSP = resultBSP.union(otherBSP)
- break
- case BooleanOperator.INTERSECT:
- resultBSP = resultBSP.intersect(otherBSP)
- break
- case BooleanOperator.SUBTRACT:
- resultBSP = resultBSP.subtract(otherBSP)
- break
- }
- }
- }
- let geometry = resultBSP.toSolidGeometry()
- geometry.smoothAngle = this.calculateSmoothAngle(solids)
- solid.updateGeometry(geometry, true)
- return true
- }
- copy(source) {
- this.operation = source.operation
- return this
- }
- calculateSmoothAngle(solids) {
- let smoothAngle = 0
- for (let solid of solids) {
- if (solid.geometry.smoothAngle > smoothAngle) {
- smoothAngle = solid.geometry.smoothAngle
- }
- }
- return smoothAngle
- }
- findSolids(object, solids) {
- const children = object.children
- const start = object instanceof Solid ? 2 : 0
- for (let i = start; i < children.length; i++) {
- let child = children[i]
- if (child instanceof Solid) {
- child.visible = false
- child.edgesVisible = false
- child.facesVisible = false
- solids.push(child)
- } else {
- this.findSolids(child, solids)
- }
- }
- }
- }
- ObjectBuilder.addClass(BooleanOperator)
- export { BooleanOperator }
|