UNPKG

@xeokit/xeokit-sdk

Version:

3D BIM IFC Viewer SDK for AEC engineering applications. Open Source JavaScript Toolkit based on pure WebGL for top performance, real-world coordinates and full double precision

267 lines (257 loc) 11.1 kB
import {utils} from '../../utils.js'; /** * @desc Creates a 3D line {@link Geometry}. * * ## Usage * * In the example below we'll create a {@link Mesh} with a line {@link ReadableGeometry}. * * [[Run this example](https://xeokit.github.io/xeokit-sdk/examples/scenegraph/#buildLineGeometry)] * * ````javascript * //------------------------------------------------------------------------------------------------------------------ * // Import the modules we need for this example * //------------------------------------------------------------------------------------------------------------------ * * import {buildLineGeometry, Viewer, Mesh, ReadableGeometry, PhongMaterial} from "../../dist/xeokit-sdk.min.es.js"; * * //------------------------------------------------------------------------------------------------------------------ * // Create a Viewer and arrange the camera * //------------------------------------------------------------------------------------------------------------------ * * const viewer = new Viewer({ * canvasId: "myCanvas" * }); * * viewer.camera.eye = [0, 0, 8]; * viewer.camera.look = [0, 0, 0]; * viewer.camera.up = [0, 1, 0]; * * //------------------------------------------------------------------------------------------------------------------ * // Create a mesh with simple 2d line shape * //------------------------------------------------------------------------------------------------------------------ * * new Mesh(viewer.scene, { * geometry: new ReadableGeometry(viewer.scene, buildLineGeometry({ * startPoint: [-5,-2,0], * endPoint: [-5,2,0], * })), * material: new PhongMaterial(viewer.scene, { * emissive: [0, 1,] * }) * }); * * //------------------------------------------------------------------------------------------------------------------ * // Create a mesh with simple 2d line shape with black color * //------------------------------------------------------------------------------------------------------------------ * * new Mesh(viewer.scene, { * geometry: new ReadableGeometry(viewer.scene, buildLineGeometry({ * startPoint: [-4,-2,0], * endPoint: [-4,2,0], * })), * material: new PhongMaterial(viewer.scene, { * emissive: [0, 0, 0] * }) * }); * * //------------------------------------------------------------------------------------------------------------------ * // Create a mesh with simple 2d line shape with black color and simple pattern * //------------------------------------------------------------------------------------------------------------------ * * new Mesh(viewer.scene, { * geometry: new ReadableGeometry(viewer.scene, buildLineGeometry({ * startPoint: [-3,-2,0], * endPoint: [-3,2,0], * pattern: [0.10], * })), * material: new PhongMaterial(viewer.scene, { * emissive: [0, 0, 0] * }) * }); * * //------------------------------------------------------------------------------------------------------------------ * // Create a mesh with simple 2d line shape with blue color and simple pattern extended to end * //------------------------------------------------------------------------------------------------------------------ * * new Mesh(viewer.scene, { * geometry: new ReadableGeometry(viewer.scene, buildLineGeometry({ * startPoint: [-2,-2,0], * endPoint: [-2,2,0], * pattern: [0.10], * extendToEnd: true, * })), * material: new PhongMaterial(viewer.scene, { * emissive: [0, 0, 1] * }) * }); * * //------------------------------------------------------------------------------------------------------------------ * // Create a mesh with simple 2d line shape with black color and more complex pattern * //------------------------------------------------------------------------------------------------------------------ * * new Mesh(viewer.scene, { * geometry: new ReadableGeometry(viewer.scene, buildLineGeometry({ * startPoint: [-1,-2,0], * endPoint: [-1,2,0], * pattern: [0.15, 0.05], * })), * material: new PhongMaterial(viewer.scene, { * emissive: [0, 0, 0] * }) * }); * * //------------------------------------------------------------------------------------------------------------------ * // Create a mesh with simple 2d line shape with blue color and more complex pattern extended to end * //------------------------------------------------------------------------------------------------------------------ * * new Mesh(viewer.scene, { * geometry: new ReadableGeometry(viewer.scene, buildLineGeometry({ * startPoint: [0,-2,0], * endPoint: [0,2,0], * pattern: [0.15, 0.05], * extendToEnd: true, * })), * material: new PhongMaterial(viewer.scene, { * emissive: [0, 0, 1] * }) * }); * * //------------------------------------------------------------------------------------------------------------------ * // Create a mesh with simple 2d line shape with black color and complex pattern * //------------------------------------------------------------------------------------------------------------------ * * new Mesh(viewer.scene, { * geometry: new ReadableGeometry(viewer.scene, buildLineGeometry({ * startPoint: [1,-2,0], * endPoint: [1,2,0], * pattern: [0.15, 0.05, 0.50], * })), * material: new PhongMaterial(viewer.scene, { * emissive: [0, 0, 0] * }) * }); * * //------------------------------------------------------------------------------------------------------------------ * // Create a mesh with simple 2d line shape with blue color and complex pattern extended to end * //------------------------------------------------------------------------------------------------------------------ * * new Mesh(viewer.scene, { * geometry: new ReadableGeometry(viewer.scene, buildLineGeometry({ * startPoint: [2,-2,0], * endPoint: [2,2,0], * pattern: [0.15, 0.05, 0.50], * extendToEnd: true, * })), * material: new PhongMaterial(viewer.scene, { * emissive: [0, 0, 1] * }) * }); * * //------------------------------------------------------------------------------------------------------------------ * // Create a mesh with simple 3d line shape with white color and simple pattern * //------------------------------------------------------------------------------------------------------------------ * * new Mesh(viewer.scene, { * geometry: new ReadableGeometry(viewer.scene, buildLineGeometry({ * startPoint: [3,-2,-1], * endPoint: [5,2,1], * pattern: [0.10], * })), * material: new PhongMaterial(viewer.scene, { * emissive: [1, 1, 1] * }) * }); * * //------------------------------------------------------------------------------------------------------------------ * // Create a mesh with simple 3d line shape with black color and simple dot pattern * //------------------------------------------------------------------------------------------------------------------ * * new Mesh(viewer.scene, { * geometry: new ReadableGeometry(viewer.scene, buildLineGeometry({ * startPoint: [5,-2,-1], * endPoint: [7,2,1], * pattern: [0.03], * })), * material: new PhongMaterial(viewer.scene, { * emissive: [0, 0, 0] * }) * }); * ```` * * @function buildLineGeometry * @param {*} [cfg] Configs * @param {String} [cfg.id] Optional ID, unique among all components in the parent {@link Scene}, generated automatically when omitted. * @param {Number[]} [cfg.startPoint] 3D start point (x0, y0, z0). * @param {Number[]} [cfg.endPoint] 3D end point (x1, y1, z1). * @param {Number[]} [cfg.pattern] Lengths of segments that describe a pattern. * @param {Bool} [cfg.extendToEnd] If true: it will try to make sure the line doesn't end up with a gap, as it will * extend the last segment. * @returns {Object} Configuration for a {@link Geometry} subtype. */ function buildLineGeometry(cfg = {}) { if (cfg.startPoint.length !== 3) { throw "Start point should contain 3 elements in array: x, y and z"; } if (cfg.endPoint.length !== 3) { throw "End point should contain 3 elements in array: x, y and z"; } let indices = []; let points = []; let x0 = cfg.startPoint[0]; let y0 = cfg.startPoint[1]; let z0 = cfg.startPoint[2]; let x1 = cfg.endPoint[0]; let y1 = cfg.endPoint[1]; let z1 = cfg.endPoint[2]; let lineLength = Math.sqrt((x1- x0)**2 + (y1 - y0)**2 + (z1 - z0)**2); let normalizedDirectionVectorOfLine = [(x1-x0)/lineLength, (y1-y0)/lineLength, (z1-z0)/lineLength]; if (!cfg.pattern) { indices.push(0); indices.push(1); points.push(x0, y0, z0, x1, y1, z1); } else { let patternsNumber = cfg.pattern.length; let gap = false; let segmentFilled = 0.0; let idOfCurrentPatternLength = 0; let pointIndicesCounter = 0; let currentStartPoint = [x0, y0, z0]; let currentPatternLength = cfg.pattern[idOfCurrentPatternLength]; points.push(currentStartPoint[0], currentStartPoint[1], currentStartPoint[2]); while (currentPatternLength <= (lineLength - segmentFilled)) { let vectorFromCurrentStartPointToCurrentEndPoint = [ normalizedDirectionVectorOfLine[0] * currentPatternLength, normalizedDirectionVectorOfLine[1] * currentPatternLength, normalizedDirectionVectorOfLine[2] * currentPatternLength, ]; let currentEndPoint = [ currentStartPoint[0] + vectorFromCurrentStartPointToCurrentEndPoint[0], currentStartPoint[1] + vectorFromCurrentStartPointToCurrentEndPoint[1], currentStartPoint[2] + vectorFromCurrentStartPointToCurrentEndPoint[2], ]; points.push(currentEndPoint[0], currentEndPoint[1], currentEndPoint[2]); if (!gap) { indices.push(pointIndicesCounter); indices.push(pointIndicesCounter + 1); } gap = !gap; pointIndicesCounter += 1; currentStartPoint = currentEndPoint; idOfCurrentPatternLength += 1; if (idOfCurrentPatternLength >= patternsNumber) { idOfCurrentPatternLength = 0; } segmentFilled += currentPatternLength; currentPatternLength = cfg.pattern[idOfCurrentPatternLength]; } if (cfg.extendToEnd) { points.push(x1, y1, z1); indices.push(indices.length - 2); indices.push(indices.length - 1); } } return utils.apply(cfg, { primitive: "lines", positions: points, indices: indices, }); } export {buildLineGeometry};