UNPKG

@polygonjs/polygonjs

Version:

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

143 lines (142 loc) 5.29 kB
"use strict"; import { QuadHalfEdge } from "./QuadHalfEdge"; import { QuadNode } from "./QuadNode"; import { quadHalfEdgeIndices, NEIGHBOUR_INDICES } from "./QuadGraphCommon"; import { addToMapAtEntry, getMapElementAtEntry } from "../../../../../core/MapUtils"; import { PrimitiveGraph } from "../../../entities/primitive/PrimitiveGraph"; import { setToArray } from "../../../../SetUtils"; const _indices = { index0: 0, index1: 0 }; const _neighbourIdsSet = /* @__PURE__ */ new Set(); const _neighbourIdsArray = []; export class QuadGraph extends PrimitiveGraph { constructor() { super(...arguments); this._quadsById = /* @__PURE__ */ new Map(); this._edgesByIndex = /* @__PURE__ */ new Map(); this._halfEdgeByHalfEdge = /* @__PURE__ */ new Map(); this._halfEdgeByQuadId = /* @__PURE__ */ new Map(); this._quadIdsByPointIndex = /* @__PURE__ */ new Map(); } addQuad(quadId, quadIndices) { const quadNode = new QuadNode(quadId, quadIndices); this._quadsById.set(quadId, quadNode); for (let i = 0; i < 4; i++) { quadHalfEdgeIndices(quadIndices, i, _indices); const edge = new QuadHalfEdge({ quadId, index0: _indices.index0, index1: _indices.index1, sideIndex: i }); addToMapAtEntry(this._edgesByIndex, _indices.index0, _indices.index1, edge); const oppositeHalfEdge = getMapElementAtEntry(this._edgesByIndex, _indices.index1, _indices.index0); if (oppositeHalfEdge) { this._halfEdgeByHalfEdge.set(edge, oppositeHalfEdge); this._halfEdgeByHalfEdge.set(oppositeHalfEdge, edge); addToMapAtEntry(this._halfEdgeByQuadId, quadNode.id, oppositeHalfEdge.quadId, edge); addToMapAtEntry(this._halfEdgeByQuadId, oppositeHalfEdge.quadId, quadNode.id, oppositeHalfEdge); } } for (const index of quadIndices) { let quadIds = this._quadIdsByPointIndex.get(index); if (!quadIds) { quadIds = /* @__PURE__ */ new Set(); this._quadIdsByPointIndex.set(index, quadIds); } quadIds.add(quadId); } return quadNode; } quadNode(quadId) { return this._quadsById.get(quadId); } quadIdsByPointIndex(pointIndex) { return this._quadIdsByPointIndex.get(pointIndex); } neighbourData(quadId, sideIndex, target) { const quadNode = this._quadsById.get(quadId); if (!quadNode) { target.quadNode = null; target.neighbourIndex = null; return; } quadHalfEdgeIndices(quadNode.indices, sideIndex, _indices); const halfEdge = getMapElementAtEntry(this._edgesByIndex, _indices.index0, _indices.index1); const oppositeHalfEdge = this._halfEdgeByHalfEdge.get(halfEdge); if (!oppositeHalfEdge) { target.quadNode = null; target.neighbourIndex = null; return; } const oppositeQuadId = oppositeHalfEdge.quadId; target.quadNode = this._quadsById.get(oppositeQuadId); target.neighbourIndex = oppositeHalfEdge.sideIndex; } // private _hasNeighbourSharingEdge(quadId: number, sideIndex: NeighbourIndex): boolean { // const quadNode = this._quadsById.get(quadId); // if (!quadNode) { // return false; // } // quadHalfEdgeIndices(quadNode.indices, sideIndex, _indices); // const halfEdge = getMapElementAtEntry(this._edgesByIndex, _indices.index0, _indices.index1)!; // return this._halfEdgeByHalfEdge.has(halfEdge); // } neighbourIdsSharingEdge(quadId, target) { target.length = 0; const quadNode = this._quadsById.get(quadId); if (!quadNode) { return; } _neighbourIdsSet.clear(); for (const i of NEIGHBOUR_INDICES) { quadHalfEdgeIndices(quadNode.indices, i, _indices); const halfEdge = getMapElementAtEntry(this._edgesByIndex, _indices.index0, _indices.index1); const oppositeHalfEdge = this._halfEdgeByHalfEdge.get(halfEdge); if (oppositeHalfEdge) { const oppositeQuadId = oppositeHalfEdge.quadId; _neighbourIdsSet.add(oppositeQuadId); } } setToArray(_neighbourIdsSet, target); } neighbourIdsSharingPoint(quadId, target) { target.length = 0; const quadNode = this._quadsById.get(quadId); if (!quadNode) { return; } _neighbourIdsSet.clear(); const indices = quadNode.indices; for (const index of indices) { const neighbourIndices = this._quadIdsByPointIndex.get(index); if (neighbourIndices) { for (const neighbourIndex of neighbourIndices) { if (neighbourIndex != quadId) { _neighbourIdsSet.add(neighbourIndex); } } } } setToArray(_neighbourIdsSet, target); } neighbourIndex(quadId, neighbourIndex, withSharedEdge) { if (withSharedEdge == true) { this.neighbourIdsSharingEdge(quadId, _neighbourIdsArray); } else { this.neighbourIdsSharingPoint(quadId, _neighbourIdsArray); } const neighbourId = _neighbourIdsArray[neighbourIndex]; if (neighbourId != null) { return neighbourId; } return -1; } neighboursCount(quadId, withSharedEdge) { if (withSharedEdge == true) { this.neighbourIdsSharingEdge(quadId, _neighbourIdsArray); } else { this.neighbourIdsSharingPoint(quadId, _neighbourIdsArray); } return _neighbourIdsArray.length; } }