Skip to content

模型剖切


ts
import { Viewer, Clipping, ClippingMode, DrawHandler, DrawMode } from "joDVF";
import { Pane } from "tweakpane";
import {
  Cesium3DTileset,
  Cartesian3,
  HeadingPitchRange,
  Cartographic,
  Matrix4
} from "joCesium";

const { mapContainer, uiContainer } = createContainer();

const viewer = new Viewer(mapContainer);
const scene = viewer.scene;
scene.globe.depthTestAgainstTerrain = true;
const dataBaseURL = "https://data.mars3d.cn/3dtiles/max-fcfh/tileset.json";

let clipping;
let tilesetObj;
Cesium3DTileset.fromUrl(dataBaseURL).then((tileset) => {
  tilesetObj = tileset;
  viewer.scene.primitives.add(tileset);
  // 定位
  const boundingSphere = tileset.boundingSphere;
  const radius = boundingSphere.radius;
  viewer.zoomTo(tileset, new HeadingPitchRange(-1.2, -0.6, radius * 2.0));

  const cartographic = Cartographic.fromCartesian(boundingSphere.center);
  const surface = Cartesian3.fromRadians(
    cartographic.longitude,
    cartographic.latitude,
    0.0
  );
  const offset = Cartesian3.fromRadians(
    cartographic.longitude,
    cartographic.latitude,
    -40
  );
  const translation = Cartesian3.subtract(offset, surface, new Cartesian3());
  tileset.modelMatrix = Matrix4.fromTranslation(translation);

  clipping = new Clipping(viewer, {
    dimensions: 1.5
  });
  clipping.start(tileset, ClippingMode.X);
});

addUI();
function addUI() {
  const pane = new Pane({
    container: uiContainer,
    title: "参数"
  });

  // x 轴剖切
  const axisXBtn = pane.addButton({
    title: "x 轴剖切",
    label: "剖切方式:"
  });

  axisXBtn.on("click", () => {
    destroy();
    clipping = new Clipping(viewer, {
      dimensions: 1.5
    });
    clipping.start(tilesetObj, ClippingMode.X);
  });

  // y 轴剖切
  const axisYBtn = pane.addButton({
    title: "y 轴剖切",
    label: "剖切方式:"
  });

  axisYBtn.on("click", () => {
    destroy();
    clipping = new Clipping(viewer, {
      dimensions: 1.5
    });
    clipping.start(tilesetObj, ClippingMode.Y);
  });

  // z 轴剖切
  const axisZBtn = pane.addButton({
    title: "z 轴剖切",
    label: "剖切方式:"
  });

  axisZBtn.on("click", () => {
    destroy();
    clipping = new Clipping(viewer, {
      dimensions: 1.5
    });
    clipping.start(tilesetObj, ClippingMode.Z);
  });

  // 自定义线剖切
  const customLineBtn = pane.addButton({
    title: "自定义线剖切",
    label: "剖切方式:"
  });

  customLineBtn.on("click", () => {
    destroy();

    const drawHanlder = new DrawHandler(viewer, DrawMode.Line);
    drawHanlder.activate();
    const points = [];
    drawHanlder.anchorEvent.addEventListener((cartesian) => {
      points.push(cartesian[0]);
      if (points.length === 2) {
        clipping = new Clipping(viewer, {
          dimensions: 1.5
        });
        clipping.start(tilesetObj, ClippingMode.Line, points);
        drawHanlder.clear();
        drawHanlder.destroy();
      }
    });
  });

  // 取反剖切
  const reverseBtn = pane.addButton({
    title: "取反剖切",
    label: "剖切方式:"
  });

  reverseBtn.on("click", () => {
    if (clipping) clipping.setReverse();
  });

  // 清除
  const clearBtn = pane.addButton({
    title: "清除"
  });

  clearBtn.on("click", () => {
    destroy();
  });

  function destroy() {
    if (clipping && !clipping.isDestroyed()) clipping = clipping.destroy();
  }
}

function createContainer() {
  const container = document.createElement("div");
  container.style.width = "100%";
  container.style.height = "100%";

  const uiContainer = document.createElement("div");
  uiContainer.style.position = "fixed";
  uiContainer.style.top = "5px";
  uiContainer.style.left = "5px";
  document.body.appendChild(container);
  document.body.appendChild(uiContainer);

  return {
    mapContainer: container,
    uiContainer
  };
}