UNPKG

@polygonjs/polygonjs

Version:

node-based WebGL 3D engine https://polygonjs.com

181 lines (180 loc) 5.99 kB
"use strict"; import { TetSopNode } from "./_BaseTet"; import { NodeParamsConfig, ParamConfig } from "../utils/params/ParamsConfig"; import { SopType } from "../../poly/registers/nodes/types/Sop"; import { stringToIndices } from "../../../core/String"; import { isBooleanTrue } from "../../../core/Type"; import { Vector3 } from "three"; import { tetCenter } from "../../../core/geometry/modules/tet/utils/tetCenter"; import { isPositionInsideMesh } from "../../../core/geometry/modules/tet/utils/tetInsideMesh"; import { ThreeMeshBVHHelper } from "../../../core/geometry/bvh/ThreeMeshBVHHelper"; import { findNonDelaunayTetsFromMultiplePointsCheck } from "../../../core/geometry/modules/tet/utils/findNonDelaunayTets"; import { tetRemoveUnusedPoints } from "../../../core/geometry/modules/tet/utils/tetRemoveUnusedPoints"; import { tetQuality } from "../../../core/geometry/modules/tet/utils/tetQuality"; import { arrayPushItems } from "../../../core/ArrayUtils"; const _tetCenter = new Vector3(); const _indices = []; class TetDeleteSopParamsConfig extends NodeParamsConfig { constructor() { super(...arguments); this.byQuality = ParamConfig.BOOLEAN(0); this.minQuality = ParamConfig.FLOAT(0.5, { range: [0, 1], rangeLocked: [true, true], visibleIf: { byQuality: 1 } }); this.byIds = ParamConfig.BOOLEAN(0, { separatorBefore: true }); this.ids = ParamConfig.STRING("0", { visibleIf: { byIds: 1 } }); this.byIndex = ParamConfig.BOOLEAN(0, { separatorBefore: true }); this.index = ParamConfig.INTEGER(-1, { range: [0, 100], rangeLocked: [true, false], visibleIf: { byIndex: 1 } }); this.byIndexRange = ParamConfig.BOOLEAN(0, { separatorBefore: true }); this.indexRangeStart = ParamConfig.INTEGER(0, { range: [0, 2e3], rangeLocked: [true, false], visibleIf: { byIndexRange: 1 } }); this.indexRangeEnd = ParamConfig.INTEGER(2e3, { range: [0, 2e3], rangeLocked: [true, false], visibleIf: { byIndexRange: 1 } }); this.byDelaunay = ParamConfig.BOOLEAN(0, { separatorBefore: true }); this.byBoundingObject = ParamConfig.BOOLEAN(0, { separatorBefore: true }); this.invert = ParamConfig.BOOLEAN(0, { separatorBefore: true }); } } const ParamsConfig = new TetDeleteSopParamsConfig(); export class TetDeleteSopNode extends TetSopNode { constructor() { super(...arguments); this.paramsConfig = ParamsConfig; } static type() { return SopType.TET_DELETE; } initializeNode() { this.io.inputs.setCount(1, 2); } async cook(inputCoreGroups) { const tetObjects = inputCoreGroups[0].tetObjects(); if (tetObjects) { for (const tetObject of tetObjects) { this._deleteTets(tetObject, inputCoreGroups); } this.setObjects(tetObjects); } else { this.setObjects([]); } } _deleteTets(tetObject, inputCoreGroups) { var _a; const selectedIds = []; if (isBooleanTrue(this.pv.byQuality)) { this._findTetsByQuality(tetObject, selectedIds); } if (isBooleanTrue(this.pv.byIds)) { this._findTetsById(selectedIds); } if (isBooleanTrue(this.pv.byIndex)) { this._findTetsByIndex(tetObject, selectedIds); } if (isBooleanTrue(this.pv.byIndexRange)) { this._findTetsByIndexRange(tetObject, selectedIds); } if (isBooleanTrue(this.pv.byDelaunay)) { this._findTetsByDelaunay(tetObject, selectedIds); } if (isBooleanTrue(this.pv.byBoundingObject)) { const boundingObject = (_a = inputCoreGroups[1]) == null ? void 0 : _a.threejsObjectsWithGeo()[0]; if (boundingObject) { this._findTetsByBoundingObject(tetObject, boundingObject, selectedIds); } } if (isBooleanTrue(this.pv.invert)) { const nonSelectedIds = []; const selectedIdsSet = new Set(selectedIds); tetObject.geometry.tetrahedrons.forEach((_, tetId) => { if (!selectedIdsSet.has(tetId)) { nonSelectedIds.push(tetId); } }); tetObject.geometry.removeTets(nonSelectedIds); } else { tetObject.geometry.removeTets(selectedIds); } tetRemoveUnusedPoints(tetObject.geometry); } _findTetsByQuality(tetObject, selectedIds) { tetObject.geometry.tetrahedrons.forEach((_, tetId) => { if (tetQuality(tetObject.geometry, tetId) < this.pv.minQuality) { selectedIds.push(tetId); } }); } _findTetsById(selectedIds) { stringToIndices(this.pv.ids, _indices); arrayPushItems(_indices, selectedIds); } _findTetsByIndex(tetObject, selectedIds) { const index = this.pv.index; if (index == -1) { const lastId = tetObject.geometry.lastAddedTetId(); if (lastId != null) { selectedIds.push(lastId); } } else { let i = 0; tetObject.geometry.tetrahedrons.forEach((_, tetId) => { if (i == index) { selectedIds.push(tetId); } i++; }); } } _findTetsByIndexRange(tetObject, selectedIds) { const min = this.pv.indexRangeStart; const max = this.pv.indexRangeEnd; let i = 0; tetObject.geometry.tetrahedrons.forEach((_, tetId) => { if (i >= min && i <= max) { selectedIds.push(tetId); } i++; }); } _findTetsByDelaunay(tetObject, selectedIds) { const invalidTets = []; findNonDelaunayTetsFromMultiplePointsCheck(tetObject.geometry, invalidTets); selectedIds.push(...invalidTets); } _findTetsByBoundingObject(tetObject, boundingObject, selectedIds) { ThreeMeshBVHHelper.assignDefaultBVHIfNone(boundingObject); const tetGeometry = tetObject.geometry; tetGeometry.tetrahedrons.forEach((_, tetId) => { tetCenter(tetGeometry, tetId, _tetCenter); const isInside = isPositionInsideMesh(_tetCenter, boundingObject, 1e-3); if (isInside) { selectedIds.push(tetId); } }); } }