diff --git a/.babelrc b/.babelrc index 4132556f..ada5bdb8 100644 --- a/.babelrc +++ b/.babelrc @@ -3,4 +3,4 @@ "plugins": [ "@babel/transform-runtime" ] -} +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 57d5948c..266fccdf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,7 +28,6 @@ "react": "^16.14.0", "react-aria-menubutton": "^7.0.1", "react-collapsible": "^2.8.3", - "react-compound-slider": "^3.4.0", "react-data-table-component": "^6.11.6", "react-dom": "^16.14.0", "react-graph-vis": "^1.0.5", @@ -17874,11 +17873,6 @@ "node": ">= 0.4" } }, - "node_modules/internmap": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz", - "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==" - }, "node_modules/interpret": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", @@ -26952,27 +26946,6 @@ "react-dom": ">=16.8.0" } }, - "node_modules/react-compound-slider": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/react-compound-slider/-/react-compound-slider-3.4.0.tgz", - "integrity": "sha512-KSje/rB0xSvvcb7YV0+82hkiXTV5ljSS7axKrNiXLf9AEO+rrr1Xq4MJWA+6v030YNNo/RoSoEB6D6fnoy+8ng==", - "dependencies": { - "@babel/runtime": "^7.12.5", - "d3-array": "^2.8.0", - "warning": "^4.0.3" - }, - "peerDependencies": { - "react": ">=16.9" - } - }, - "node_modules/react-compound-slider/node_modules/d3-array": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz", - "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==", - "dependencies": { - "internmap": "^1.0.0" - } - }, "node_modules/react-data-table-component": { "version": "6.11.8", "resolved": "https://registry.npmjs.org/react-data-table-component/-/react-data-table-component-6.11.8.tgz", @@ -32542,14 +32515,6 @@ "makeerror": "1.0.12" } }, - "node_modules/warning": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", - "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", - "dependencies": { - "loose-envify": "^1.0.0" - } - }, "node_modules/watchpack": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz", @@ -47100,11 +47065,6 @@ "side-channel": "^1.0.4" } }, - "internmap": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz", - "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==" - }, "interpret": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", @@ -54046,26 +54006,6 @@ "dev": true, "requires": {} }, - "react-compound-slider": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/react-compound-slider/-/react-compound-slider-3.4.0.tgz", - "integrity": "sha512-KSje/rB0xSvvcb7YV0+82hkiXTV5ljSS7axKrNiXLf9AEO+rrr1Xq4MJWA+6v030YNNo/RoSoEB6D6fnoy+8ng==", - "requires": { - "@babel/runtime": "^7.12.5", - "d3-array": "^2.8.0", - "warning": "^4.0.3" - }, - "dependencies": { - "d3-array": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz", - "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==", - "requires": { - "internmap": "^1.0.0" - } - } - } - }, "react-data-table-component": { "version": "6.11.8", "resolved": "https://registry.npmjs.org/react-data-table-component/-/react-data-table-component-6.11.8.tgz", @@ -58382,14 +58322,6 @@ "makeerror": "1.0.12" } }, - "warning": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", - "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", - "requires": { - "loose-envify": "^1.0.0" - } - }, "watchpack": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz", diff --git a/package.json b/package.json index 964658d8..1975b9cd 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,6 @@ "react": "^16.14.0", "react-aria-menubutton": "^7.0.1", "react-collapsible": "^2.8.3", - "react-compound-slider": "^3.4.0", "react-data-table-component": "^6.11.6", "react-dom": "^16.14.0", "react-graph-vis": "^1.0.5", diff --git a/src/app.tsx b/src/app.tsx index 06ef2cf8..55c43f38 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -22,7 +22,6 @@ import { Sandbox } from './pages/Sandbox'; import { SynthesisExplorer } from './pages/SynthesisExplorer'; import { MPContribsSearch } from './pages/MPContribsSearch'; import { CatalystExplorer } from './pages/CatalystExplorer'; -import { TilingVisualization } from './pages/TilingVisualization'; import { Navbar } from './components/navigation/Navbar'; import periodicTableImage from './assets/images/periodictable.png'; import { MofExplorer } from './pages/MofExplorer'; @@ -46,7 +45,6 @@ ReactDOM.render( Phase Diagram Contributions Crystal Structure - Tiling Visualization Sandbox
@@ -87,9 +85,6 @@ ReactDOM.render( - - - diff --git a/src/components/crystal-toolkit/CrystalToolkitScene/CrystalToolkitScene.tsx b/src/components/crystal-toolkit/CrystalToolkitScene/CrystalToolkitScene.tsx index ed442b73..f1858774 100644 --- a/src/components/crystal-toolkit/CrystalToolkitScene/CrystalToolkitScene.tsx +++ b/src/components/crystal-toolkit/CrystalToolkitScene/CrystalToolkitScene.tsx @@ -107,14 +107,6 @@ export interface CrystalToolkitSceneProps { */ settings?: any; - /** - * the dynamic tiling, to be updated in scene. - */ - tiling?: number[]; - /** - * the maximum size of the tiling, controls render size - */ - maxTiling?: number; /** * Hide/show nodes in scene by its name (key), value is 1 to show the node * and 0 to hide it. @@ -379,8 +371,6 @@ export const CrystalToolkitScene: React.FC = ({ props.settings, props.inletSize, props.inletPadding, - props.tiling, - props.maxTiling, (objects) => { if (props.onObjectClicked) { props.onObjectClicked(objects); @@ -443,9 +433,6 @@ export const CrystalToolkitScene: React.FC = ({ () => scene.current!.updateInsetSettings(props.inletSize!, props.inletPadding!, props.axisView), [props.inletSize, props.inletPadding, props.axisView] ); - useEffect(() => { - scene.current!.updateTiles(props.tiling); - }, [props.tiling]); useEffect(() => { scene.current!.resizeRendererToDisplaySize(); diff --git a/src/components/crystal-toolkit/scene/Scene.ts b/src/components/crystal-toolkit/scene/Scene.ts index 8a8b2dcb..b8103242 100644 --- a/src/components/crystal-toolkit/scene/Scene.ts +++ b/src/components/crystal-toolkit/scene/Scene.ts @@ -32,6 +32,7 @@ import '../CrystalToolkitScene/CrystalToolkitScene.less'; import { CameraState } from '../CameraContextProvider/camera-reducer'; const POINTER_CLASS = 'show-pointer'; +let D; export default class Scene { private settings; private renderer!: THREE.WebGLRenderer | SVGRenderer; @@ -68,9 +69,6 @@ export default class Scene { private clock = new THREE.Clock(); private animationHelper: AnimationHelper; - private tiling: any; - private maxTiling: any; - private arrayOfTileRoots: any; private cacheMountBBox(mountNode: Element) { this.cachedMountNodeSize = { width: mountNode.clientWidth, height: mountNode.clientHeight }; @@ -110,36 +108,6 @@ export default class Scene { mountNode.appendChild(this.renderer.domElement); } - /* - this function returns a 3-dimensional empty array based on the tiling array - e.g. _getTiles([1, 1, 1] === [ [ [[], []], [[], []] ], [ [[], []], [[], []] ] ] - all of the arrays are unique instances, not copies - this allows us to create an array that can store the contents of each tiles and - be accessed with the tile indices. For example: - arr = _getTiles([2, 2, 2]) - arr[0][1][2].push(scene) - scene = arr[0][1][2][0] - */ - private static getEmptyTilesArray(tiling: number[]) { - let grid = []; - for (let x = 0; x <= tiling[2]; x++) { - let arrX = []; - for (let y = 0; y <= tiling[1]; y++) { - let arrY = []; - for (let z = 0; z <= tiling[0]; z++) { - let arrZ = []; - // @ts-ignore - arrY.push(arrZ); - } - // @ts-ignore - arrX.push(arrY); - } - // @ts-ignore - grid.push(arrX); - } - return grid; - } - private configureLabelRenderer(mountNode: Element) { const labelRenderer = new CSS2DRenderer(); this.labelRenderer = labelRenderer; @@ -274,7 +242,7 @@ export default class Scene { private onClickImplementation(p, e) { let needRedraw = false; - //TODO(chab) make it more readable + //TODO(chab) make it more readale if (p && p.object) { const { object, point } = p; if (object?.sceneObject) { @@ -393,20 +361,11 @@ export default class Scene { settings, size, padding, - tiling, - maxTiling, clickCallback, private dispatch: (p: Vector3, r: Quaternion, zoom: number) => void, private debugDOMElement?, cameraState?: CameraState ) { - this.tiling = tiling; - this.maxTiling = maxTiling; - this.arrayOfTileRoots = Scene.getEmptyTilesArray([ - this.maxTiling, - this.maxTiling, - this.maxTiling - ]); this.settings = Object.assign(defaults, settings); this.objectBuilder = new ThreeBuilder(this.settings); this.cameraState = cameraState; @@ -444,23 +403,6 @@ export default class Scene { this.renderInlet(); } - /* - loop through the arrayOfTileRoots and set the visibility of each object. - In particular, set threeObject.visible = true if the x, y, and z indices - are all less than the x, y, and z indices in tiling. - */ - updateTiles(tiling) { - const [xCut, yCut, zCut] = tiling; - this.arrayOfTileRoots.forEach((arrX, x) => { - arrX.forEach((arrY, y) => { - arrY.forEach((arrZ, z) => { - arrZ[0].visible = x <= xCut && y <= yCut && z <= zCut; - }); - }); - }); - this.renderScene(); - } - public resizeRendererToDisplaySize() { const canvas = this.renderer.domElement as HTMLCanvasElement; this.cacheMountBBox(canvas.parentElement as Element); @@ -476,7 +418,7 @@ export default class Scene { } addToScene(sceneJson: SceneJsonObject, bypassRendering = false) { - // we need to clarify the current semantics + // we need to clarify the current semantics // currently, it will remove the old scene if the name is the same, // otherwise it will keep it // it will then zoom on the content of the added scene @@ -503,73 +445,15 @@ export default class Scene { console.log('The scene is a new scene:', sceneJson.name); } - const objectToAnimate = new Set(); - - /* - this function returns an array of tiles based on the tiling array - e.g. _getTiles([0, 1, 1] === [[0,0,0], [0,0,1], [0,1,1], [0,1,0]] - */ - const _getTiles = (tiling: number[]) => { - // enumerate all tiles needed for a given tiling size - let tiles: number[][] = []; - for (let x: number = 0; x <= tiling[0]; x++) { - for (let y: number = 0; y <= tiling[1]; y++) { - for (let z: number = 0; z <= tiling[2]; z++) { - tiles.push([x, y, z]); - } - } - } - return tiles; - }; - - const emptyLattice = [ - [0, 0, 0], - [0, 0, 0], - [0, 0, 0] - ]; - - /* - This function traverses through all the tiles and renders the SceneJsonObject once for each. - Each new scene is a child of root and is offset according to the SceneJsonObject.lattice. - Each scene is added to the arrayOfTilesRoots, it can be accessed by indexing through the - arrayOfTileRoots. e.g. scene = arrayOfTileRoots[x][y][z][0]. - */ - const traverseTiles = (o: SceneJsonObject, root: THREE.Object3D, tiles: number[][]) => { - // @ts-ignore - let lattice = o.lattice ? o.lattice : emptyLattice; - - for (const tile of tiles) { - const tileRootObject = new THREE.Object3D(); - tileRootObject.name = sceneJson.name!; - sceneJson.visible && (tileRootObject.visible = sceneJson.visible); - root.add(tileRootObject); - const [x, y, z] = tile; - this.arrayOfTileRoots[x][y][z].push(tileRootObject); - - let tileOffsets: number[][] = lattice.map((vector: number[], index: number) => { - return vector.map((x: number) => x * tile[index]); - }); - traverseScene(sceneJson, tileRootObject, tileOffsets, ''); - } - }; + const rootObject = new THREE.Object3D(); + rootObject.name = sceneJson.name!; + sceneJson.visible && (rootObject.visible = sceneJson.visible); - /* - This is the core rendering loop of the Scene class. This function recursively - traverses through the scene graph and render all objects that can be converted - into threeObject's. - It will apply the tileOffset to the rendered scenes, translating them relative - to the parent threeObject. - */ - const traverseScene = ( - o: SceneJsonObject, - parent: THREE.Object3D, - tileOffsets: number[][], - currentId: string - ) => { - // create root and add to + const objectToAnimate = new Set(); + // recursively visit the scene, starting with the root object + const traverse_scene = (o: SceneJsonObject, parent: THREE.Object3D, currentId: string) => { o.contents!.forEach((childObject, idx) => { if (childObject.type) { - // render the threeObject according to childObject.type and end recursion const object = this.makeObject(childObject); parent.add(object); this.threeUUIDTojsonObject[object.uuid] = childObject; @@ -579,23 +463,11 @@ export default class Scene { objectToAnimate.add(`${currentId}--${idx}`); } } else { - // create threeObject, save id, and add to arrayOfTileRoots const threeObject = new THREE.Object3D(); threeObject.name = childObject.name!; this.computeIdToThree[`${currentId}--${threeObject.name}`] = threeObject; childObject.id = `${currentId}--${threeObject.name}`; threeObject.visible = childObject.visible === undefined ? true : !!childObject.visible; - - // translate tile according to lattice vectors - for (let offset of tileOffsets) { - if (threeObject.name !== 'unit_cell') { - const tilingTranslation = new THREE.Matrix4(); - tilingTranslation.makeTranslation(...(offset as ThreePosition)); - threeObject.applyMatrix4(tilingTranslation); - } - } - - // translate tile to scene origin if (childObject.origin) { const translation = new THREE.Matrix4(); // note(chab) have a typedefinition for the JSON @@ -605,9 +477,7 @@ export default class Scene { if (!this.settings.extractAxis || threeObject.name !== 'axes') { parent.add(threeObject); } - - // recurse through Scene graph - traverseScene(childObject, threeObject, tileOffsets, `${currentId}--${threeObject.name}`); + traverse_scene(childObject, threeObject, `${currentId}--${threeObject.name}`); if (threeObject.name === 'axes') { this.axis = threeObject.clone(); this.axisJson = { ...childObject }; @@ -616,21 +486,9 @@ export default class Scene { }); }; - // set up the threeObjects and containers - const rootObject = new THREE.Object3D(); - - // set up the threeObjects and containers - rootObject.name = 'root'; - rootObject.visible = true; - const maxTilingArray = [this.maxTiling, this.maxTiling, this.maxTiling]; - // get list of tiles needed - let tiles = _getTiles(maxTilingArray); - // render all tiles - traverseTiles(sceneJson, rootObject, tiles); - // hide/show tiles as appropriate - this.updateTiles(this.tiling); - + traverse_scene(sceneJson, rootObject, ''); // can cause memory leak + //console.log('rootObject', rootObject, rootObject); this.scene.add(rootObject); this.setupCamera(rootObject); diff --git a/src/components/crystal-toolkit/scene/animation-slider.tsx b/src/components/crystal-toolkit/scene/animation-slider.tsx deleted file mode 100644 index 4c8b7e31..00000000 --- a/src/components/crystal-toolkit/scene/animation-slider.tsx +++ /dev/null @@ -1,323 +0,0 @@ -import React, { Component, Fragment } from 'react'; -import { Slider, Rail, Handles, Tracks, Ticks } from 'react-compound-slider'; -import PropTypes from 'prop-types'; - -const sliderStyle: any = { - position: 'relative', - margin: 'auto', - width: '80%', - touchAction: 'none' -}; - -const defaultDomain: any = [0, 100]; -const defaultValues: any = [0]; - -class SimpleSlider extends Component { - constructor(props: any) { - super(props); - } - - state = { - values: defaultValues.slice(), - update: defaultValues.slice() - }; - - onUpdate = (update) => { - this.props.onUpdate(update[0]); - this.setState({ update }); - }; - - onChange = (values) => { - this.props.onChange(values[0]); - this.setState({ values }); - }; - - render() { - const { - state: { values, update } - } = this; - - return ( -
- - {({ getRailProps }) => } - - {({ handles, getHandleProps }) => ( -
- {handles.map((handle) => ( - - ))} -
- )} -
- - {({ tracks, getTrackProps }) => ( -
- {tracks.map(({ id, source, target }) => ( - - ))} -
- )} -
- - {({ ticks }) => ( -
- {ticks.map((tick) => ( - - ))} -
- )} -
-
-
- ); - } -} - -// ******************************************************* -// RAIL -// ******************************************************* -const railOuterStyle = { - position: 'absolute', - width: '100%', - height: 42, - transform: 'translate(0%, -50%)', - borderRadius: 7, - cursor: 'pointer' - // border: '1px solid white', -}; - -const railInnerStyle: any = { - position: 'absolute', - width: '100%', - height: 14, - transform: 'translate(0%, -50%)', - borderRadius: 7, - pointerEvents: 'none', - backgroundColor: 'rgb(155,155,155)' -}; - -export function SliderRail({ getRailProps }) { - return ( - -
-
- - ); -} - -SliderRail.propTypes = { - getRailProps: PropTypes.func.isRequired -}; - -// ******************************************************* -// HANDLE COMPONENT -// ******************************************************* -export function Handle({ - domain: [min, max], - handle: { id, value, percent }, - disabled, - getHandleProps -}) { - return ( - -
-
- - ); -} - -Handle.propTypes = { - domain: PropTypes.array.isRequired, - handle: PropTypes.shape({ - id: PropTypes.string.isRequired, - value: PropTypes.number.isRequired, - percent: PropTypes.number.isRequired - }).isRequired, - getHandleProps: PropTypes.func.isRequired, - disabled: PropTypes.bool -}; - -Handle.defaultProps = { - disabled: false -}; - -// ******************************************************* -// KEYBOARD HANDLE COMPONENT -// Uses a button to allow keyboard events -// ******************************************************* -export function KeyboardHandle({ - domain: [min, max], - handle: { id, value, percent }, - disabled, - getHandleProps -}) { - return ( -