# Move the particular grid by click of button on 3d left right top and bottom

**URL:** <https://discourse.threejs.org/t/move-the-particular-grid-by-click-of-button-on-3d-left-right-top-and-bottom/67168>\
**Category:** Questions\
**Tags:** geometry\
**Created:** [June 23, 2024, 8:39am UTC](https://discourse.threejs.org/t/move-the-particular-grid-by-click-of-button-on-3d-left-right-top-and-bottom/67168 "2024-06-23T08:39:12Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Rikin\_18\_17\_02](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/rikin_18_17_02/32/39875_2.png) [@Rikin\_18\_17\_02](https://discourse.threejs.org/u/Rikin_18_17_02)\
**Post date:** [June 23, 2024, 8:39am UTC](https://discourse.threejs.org/t/move-the-particular-grid-by-click-of-button-on-3d-left-right-top-and-bottom/67168/1 "2024-06-23T08:39:12Z")

</div>

![image](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/1/9/19978d9144806890f231923b226995c2af4931a9.jpeg)  
this green border is my grid so I want to add a button there and when I click on the buttons like left bottom right and left I want to move that grid according to the actions and load panels into it how can I do it?

```import
import { OBJLoader } from "three/examples/jsm/loaders/OBJLoader";
let v1 = new THREE.Vector3();
let raycaster = new THREE.Raycaster();

const deleteIconGeometry = new THREE.BoxGeometry(0.3, 0.3, 0.3); // small cube for delete icon
const deleteIconMaterial = new THREE.MeshStandardMaterial({ color: "red" });

export default class PanelGrid extends THREE.Object3D {
  bounds = new THREE.Box3();
  size = new THREE.Vector3();
  selectionSize = new THREE.Vector3();
  constructor({ modules, deleteObject }) {
    super();
    this.modules = modules; 
    this.selectionMesh = planeMesh.clone();
    this.add(this.selectionMesh);
    this.defaultOffset = { x: 1, y: 1 };
    this.deleteObject = deleteObject;
  }

  setSize(x, y, z) {
    this.size.set(x, y, z);
  }

  recomputeOccupancy({ targets }) {
    let s = this.size;
    let panelX = 1.4;
    let panelY = 2;

    this.occupancy = PanelGrid.raycastGrid({
      root: this.children[0],
      targets,
      step: {
        x: panelX / s.x,
        y: panelY / -s.y,
      },
      offset: this.defaultOffset,
    });
    return this.occupancy;
  }

  static raycastGrid({ root, targets, step }) {
    let down = new THREE.Vector3(0, -1, 0);
    let results = [];
    let rows = 0;
    let cols;

    let nx = (1 / step.x) | 0;
    let ny = (1 / step.y) | 0;
    let margx = (1 - nx * step.x) * 0.5;
    let margy = (1 - ny * step.y) * 0.5;

    for (let x = step.x * 0.5 + margx; x < 1 - step.x * 0.5; x += step.x) {
      cols = 0;
      for (let z = step.y * 0.5 + margy; z <= 1 - step.y * 0.5; z += step.y) {
        const origin = new THREE.Vector3(x, z, 1.1);
        root && root.localToWorld(origin);
        raycaster.set(origin, down);

        let res = {
          origin,
          object: targets[0],
        };
        results.push(res);

        const intersects = raycaster.intersectObjects(targets, true);
        if (intersects.length > 0) {
          res.point = intersects[0].point.clone();
          res.normal = intersects[0].normal.clone();
          res.object = intersects[0].object;

          const validPlanarThresholdWS = 1;
          if (res.origin.distanceTo(res.point) < validPlanarThresholdWS)
            res.isSupported = true;
        }
        cols++;
      }
      rows++;
    }

    return {
      results,
      rows,
      cols,
      root,
    };
  }

  disposeOccupancy() {
    if (!this.occupancy) return;
    let occupancy = this.occupancy;
    occupancy.results.forEach((res) => {
      res && res.indicator && res.indicator.parent.remove(res.indicator);
    });
    occupancy.results.length = 0;
  }

  redrawOccupancy() {
    let occupancy = this.occupancy;
    let results = occupancy.results;
    let normal = v1.set(0, 0, 1).applyQuaternion(occupancy.root.quaternion);
    for (const result of results) {
      if (!result) continue;
      if (!result.object.isMesh) continue;

      const { boundsTree } = result.object.geometry;
      const module = this.modules[0].clone();
      let panel = new THREE.Object3D();
      panel.position.copy(result.origin);
      panel.rotation.setFromQuaternion(occupancy.root.parent.quaternion);
      panel.updateMatrix();
      result.object.attach(panel);
      panel.updateMatrixWorld();
      let moduleIsObstructed = (module) => {
        let box = new THREE.Box3().setFromObject(module);
        return boundsTree.intersectsBox(box, panel.matrix);
      };

      let moduleIsSupported = (module) => {
        let box = new THREE.Box3().setFromObject(module);
        let panelThickness = box.max.z - box.min.z;
        const supportThickness = panelThickness;
        const supportLength = panelThickness * 20;
        let c0 = box.clone();
        c0.max.x = c0.min.x + supportThickness;
        c0.max.y = c0.min.y + supportThickness;
        c0.min.z = c0.max.z - supportLength;
        if (!boundsTree.intersectsBox(c0, panel.matrix)) return false;

        let c1 = box.clone();
        c1.min.x = c1.max.x - supportThickness;
        c1.max.y = c1.min.y + supportThickness;
        c1.min.z = c1.max.z - supportLength;
        if (!boundsTree.intersectsBox(c1, panel.matrix)) return false;

        let c2 = box.clone();
        c2.min.x = c2.max.x - supportThickness;
        c2.min.y = c2.max.y - supportThickness;
        c2.min.z = c2.max.z - supportLength;
        if (!boundsTree.intersectsBox(c2, panel.matrix)) return false;

        let c3 = box.clone();
        c3.max.x = c3.min.x + supportThickness;
        c3.min.y = c3.max.y - supportThickness;
        c3.min.z = c3.max.z - supportLength;
        if (!boundsTree.intersectsBox(c3, panel.matrix)) return false;
        return true;
      };

      if (
        !result.isSupported ||
        moduleIsObstructed(module) ||
        !moduleIsSupported(module)
      ) {
        for (let i = 1; i < this.modules.length; i++) {
          let submodule = this.modules[i].clone();
          if (!moduleIsObstructed(submodule) && moduleIsSupported(module))
            panel.add(submodule);
        }
      } else {
        module.children[0].originalMaterial = module.children[0].material;
        panel.add(module);
        panel.name = "supported";

        if (this.deleteObject) {
          const deleteIcon = this.deleteObject.clone();
          deleteIcon.name = "deleteIcon";
          const box = new THREE.Box3().setFromObject(panel);
          const panelSize = new THREE.Vector3();
          box.getSize(panelSize);
          // deleteIcon.rotation.setFromQuaternion(panel.quaternion);
          deleteIcon.updateMatrix();
          // deleteIcon.scale.set(
          // 0.0025 * panelSize.x,
          // 0.01 * panelSize.y,
          // 0.005 * panelSize.z
          // );
          deleteIcon.position.set(
            panelSize.x / 2 - deleteIcon.scale.x / 2,
            panelSize.y / 2 - deleteIcon.scale.y / 2,
            0.015
          );
          // panel.add(deleteIcon);
        }
      }

      this.attach(panel);

      result.indicator = panel;

      panel.updateMatrixWorld(true);

      panel.traverse((e) => (e.matrixAutoUpdate = false));
    }
  }
}

const baseMetal = 0.0;
const baseRough = 0.8;
PanelGrid.selectedStateMaterial = new THREE.MeshStandardMaterial({
  metalness: baseMetal,
  roughness: baseRough,
  transparent: true,
  opacity: 0.4,
  depthWrite: false,
  color: "teal",
});
PanelGrid.collidedStateMaterial = new THREE.MeshStandardMaterial({
  metalness: baseMetal,
  roughness: baseRough,
  transparent: true,
  depthWrite: false,
  opacity: 0.15,
  color: "red",
});
PanelGrid.nonCollidedStateMaterial = new THREE.MeshStandardMaterial({
  metalness: baseMetal,
  roughness: baseRough,
  transparent: true,
  depthWrite: false,
  opacity: 0.9,
  color: "green",
});
PanelGrid.deselectedStateMaterial = new THREE.MeshStandardMaterial({
  metalness: baseMetal,
  roughness: baseRough,
  transparent: true,
  depthWrite: false,
  opacity: 0.1,
  color: "blue",
});
let planeMesh = new THREE.Mesh(
  new THREE.BoxGeometry(1, 1, 1),
  PanelGrid.selectedStateMaterial
);
planeMesh.geometry.translate(0.5, 0.5, 0.5);
planeMesh.geometry.computeBoundingBox();

```

this is the panel grid code please check and let me know if anyone can help me it will be big help  
thanks

---

<div class="post-metadata">

**Author:** ![AshhadDevLab](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/ashhaddevlab/32/44111_2.png) [@AshhadDevLab](https://discourse.threejs.org/u/AshhadDevLab)\
**Post date:** [June 23, 2024, 8:41am UTC](https://discourse.threejs.org/t/move-the-particular-grid-by-click-of-button-on-3d-left-right-top-and-bottom/67168/2 "2024-06-23T08:41:52Z")

</div>

Can you make the formatting better by not adding single ` but by adding triple ``` at the end and at the start

---

<div class="post-metadata">

**Author:** ![Rikin\_18\_17\_02](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/rikin_18_17_02/32/39875_2.png) [@Rikin\_18\_17\_02](https://discourse.threejs.org/u/Rikin_18_17_02)\
**Post date:** [June 23, 2024, 8:43am UTC](https://discourse.threejs.org/t/move-the-particular-grid-by-click-of-button-on-3d-left-right-top-and-bottom/67168/3 "2024-06-23T08:43:34Z")

</div>

yes sure I am doing it

---

<div class="post-metadata">

**Author:** ![Rikin\_18\_17\_02](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/rikin_18_17_02/32/39875_2.png) [@Rikin\_18\_17\_02](https://discourse.threejs.org/u/Rikin_18_17_02)\
**Post date:** [June 23, 2024, 8:44am UTC](https://discourse.threejs.org/t/move-the-particular-grid-by-click-of-button-on-3d-left-right-top-and-bottom/67168/4 "2024-06-23T08:44:24Z")

</div>

Done now you can check it
