带有三维球与拾取吸附的剖切功能

点击查看功能演示

功能概览:

  1. 开启此功能后,鼠标会自动吸附到模型表面,在其吸附位置绘制一个与模型表面平行的小型圆面和一个与模型表面垂直的箭头。这个部分可以方便确定后续要出现的剖切面的准确位置。
  2. 在模型任意一点点击后,就在该位置创建剖切平面,创建的剖切平面的位置就是上面那个小型圆面的位置。
  3. 创建完剖切平面后,就出现了一个三维球,用户可以对球体上的旋转,平移,归位等把手进行各种组合操作,以此来实时联动三维球和剖切平面,方便对模型的各个部分进行操作和查看。
  4. 还提供与此相关的配套api,结束剖切与隐藏或显示剖切工具接口。

代码介绍:

在这个ts文件里暴露出了startAxialDeepCutstopAxialDeepCutshowAxialDeepCutTool这几个接口,可以用于开启轴向剖切、结束轴向剖切、和是否显示剖切工具。在这个文件里还引用了特地封装的三维球控制器useCoordinateBall这一个hooks。

三维球控制器

在三维球控制器这个文件里暴露createCoordinateBallremoveCoordinateBallresetCoordinateBallsetCoordinateBallShowsetCoordinateBallLines这个几个接口,可以用于创建三维球控制器、移除三维球控制器、重制三维球控制器、通过接口而不是鼠标的去设置三维球控制器的各个参数和显隐。

创建三维球控制器的函数签名是

ts 复制代码
const createCoordinateBall: (CoordinateBall?: CoordinateBall) => {  
    id: string;  
    emitter: EventEmitter;  
}

这个函数的核心代码片段介绍:

初始参数

ts 复制代码
const { longitude, latitude, height } = coordinate;
const centerPosition = Cartesian3.fromDegrees(longitude, latitude, height);
const initialM3 = new Matrix3();
initialQuaternion && Matrix3.fromQuaternion(initialQuaternion, initialM3);
ts 复制代码
const { line, color, name, ring, ball, square, normalize } = p;
normalizes[name] = normalize.clone();
const worldMatrix = Transforms.eastNorthUpToFixedFrame(centerPosition);
const baseCartesian3 = Cartesian3.normalize(
Cartesian3.subtract(
  Matrix4.multiplyByPoint(worldMatrix, normalize, new Cartesian3()),
  centerPosition,
  new Cartesian3()
),
new Cartesian3()
);

通过初始参数确定三维球在三维空间里的坐标和三维球的局部坐标

箭头绘制以及控制

ts 复制代码
  if (line.show) {
    lines['line' + name] = {
      color,
      material: new PolylineArrowMaterialProperty(color.withAlpha(alpha)),
      diffValue: 0,
      baseCartesian3,
      normalize,
    };
    const lineEntity = viewer.entities.add({
      name: id + '/line' + name,
      polyline: {
        positions: new CallbackProperty(() => {
          const startPosition = Cartesian3.add(
            self.current.coordinateBall[id].centerPosition,
            diffCartesian3,
            new Cartesian3()
          );
          const endPosition = Cartesian3.add(
            startPosition,
            Cartesian3.multiplyByScalar(
              self.current.coordinateBall[id].lines['line' + name].baseCartesian3,
              length,
              new Cartesian3()
            ),
            new Cartesian3()
          );
          return [startPosition, endPosition];
        }, false),
        arcType: ArcType.NONE,
        material: new PolylineArrowMaterialProperty(color.withAlpha(alpha)),
        width: 20,
      },
    });
    lines['line' + name].entity = lineEntity;
  }

默认是要绘制三个轴向的箭头,如果这个参数为否则不绘制。这里会计算出startPositionendPosition,来确定每个箭头的开始和结束位置,因为三维球会有移动的可能所以这部分的计算放在了new CallbackProperty里,可以提高动画运行效率。

箭头可以用来设置三个轴向的移动,代码为这部分:

ts 复制代码
self.current.isDownLine = true;
const line = coordinateBall.lines[name];
const { color, entity, material, baseCartesian3 } = line;
const positions = (entity!.polyline!.positions as PositionPropertyArray).getValue(new JulianDate())!;
const c0 = viewer.scene.cartesianToCanvasCoordinates(positions[0].clone());
const c1 = viewer.scene.cartesianToCanvasCoordinates(positions[1].clone());
Cartesian2.normalize(Cartesian2.subtract(c1, c0, new Cartesian2()), c2NormalVec);
self.current.pickEntity = viewer.entities.add({
  polyline: {
    positions: positions,
    arcType: ArcType.NONE,
    material: new PolylineArrowMaterialProperty(copiesColor),
    width: 20,
  },
});
self.current.pickGraphics = entity!.polyline!;
self.current.pickMateria = material;
self.current.pickGraphics.material = new PolylineArrowMaterialProperty(color);
const realCenterPosition = Cartesian3.add(centerPosition, diffCartesian3, new Cartesian3());
const startPosition = Cartesian3.add(
  realCenterPosition,
  Cartesian3.multiplyByScalar(baseCartesian3, 1500, new Cartesian3()),
  new Cartesian3()
);
const endPosition = Cartesian3.add(
  realCenterPosition,
  Cartesian3.multiplyByScalar(baseCartesian3, -1500, new Cartesian3()),
  new Cartesian3()
);
self.current.auxiliaryLine = viewer.entities.add({
  polyline: {
    positions: [startPosition, endPosition],
    material: new PolylineDashMaterialProperty({
      color: color,
      dashLength: 3,
    }),
    width: 3,
  },
});

这里会在点击的某个箭头哪里创建一条延长的虚线,以用来形象化的展示在空间里的移动的方位self.current.auxiliaryLine

在代码里:

ts 复制代码
const diffValue = distance * dot;
setCoordinateBallLines(id, name, diffValue);

监听移动的距离直接通过上面提到的setCoordinateBallLines去设置移动的类型以及移动的距离。

圆环绘制以及控制

ts 复制代码
if (ring.show) {
const minLength = ringLength * window.Math.sqrt(3);
const maxLength = length + 0.5533;
const ringEntity = viewer.entities.add({
  name: id + '/ring' + name,
  position: new CallbackProperty(() => {
    return Cartesian3.add(self.current.coordinateBall[id].centerPosition, diffCartesian3, new Cartesian3());
  }, false) as unknown as Cartesian3,
  ellipsoid: {
    radii: new Cartesian3(maxLength, maxLength, maxLength),
    innerRadii: new Cartesian3(minLength, minLength, minLength),
    minimumCone: Math.toRadians(89.5),
    maximumCone: Math.toRadians(90.5),
    material: new PolylineArrowMaterialProperty(color.withAlpha(alpha)),
  },
});
const m3 = Transforms.rotationMatrixFromPositionVelocity(baseCartesian3, baseCartesian3);
const rot90 = Matrix3.fromRotationY(Math.toRadians(90));
Matrix3.multiply(m3, rot90, m3);
const quaternion = Quaternion.fromRotationMatrix(m3);
ringEntity.orientation = new ConstantProperty(quaternion);
rings['ring' + name] = {
  entity: ringEntity,
};
}

默认是要绘制三个轴向的圆环,如果这个参数为否则不绘制。这里会计算出圆环的中心,因为三维球会有移动的可能所以这部分的计算放在了new CallbackProperty里,可以提高动画运行效率。还计算出了三个圆环在空间里的三维姿态quaternion

点击圆环或者小球会触发的代码逻辑是:

ts 复制代码
if ((name.includes('ball') || name.includes('ring')) && !self.current.auxiliaryBall) {
    const names = name.replace('ring', 'ball');
    const ball = coordinateBall.balls[names];
    const { color, entity, material, index, baseAngle, diffAngle } = ball;
    const line = coordinateBall.lines['line' + nom[index == 0 ? 2 : index - 1]];
    const positions = (line.entity!.polyline!.positions as PositionPropertyArray).getValue(new JulianDate())!;
    const lienDiffPosition = Cartesian3.subtract(positions[1], positions[0], new Cartesian3());
    const ballP = entity!.position!.getValue(new JulianDate())!.clone();
    const c0 = viewer.scene.cartesianToCanvasCoordinates(ballP);
    const c1 = viewer.scene.cartesianToCanvasCoordinates(Cartesian3.add(ballP, lienDiffPosition, new Cartesian3()));
    Cartesian2.normalize(Cartesian2.subtract(c1, c0, new Cartesian2()), c2NormalVec);
    const startPosition = Cartesian3.add(centerPosition, diffCartesian3, new Cartesian3());
    const angle = baseAngle;
    const axis = self.current.coordinateBall[id].lines['line' + nom[index]].baseCartesian3;
    const rota = self.current.coordinateBall[id].lines['line' + nom[index == 2 ? 0 : index + 1]].baseCartesian3;
    const quaternion = Quaternion.fromAxisAngle(axis, Math.toRadians(angle - diffAngle));
    const m3 = Matrix3.fromQuaternion(quaternion);
    const ballPosition = Cartesian3.add(
      startPosition,
      Cartesian3.multiplyByScalar(
        Matrix3.multiplyByVector(m3, rota, new Cartesian3()),
        ringLength,
        new Cartesian3()
      ),
      new Cartesian3()
    );
    self.current.pickEntity = viewer.entities.add({
      position: ballPosition,
      ellipsoid: {
        radii: new Cartesian3(ballRadiiLength, ballRadiiLength, ballRadiiLength),
        material: copiesColor,
      },
    });
    self.current.pickGraphics = entity!.ellipsoid!;
    self.current.pickMateria = material;
    self.current.pickGraphics.material = new ColorMaterialProperty(color);
    self.current.auxiliaryBall = viewer.entities.add({
      name: names,
      polyline: {
        positions: new CallbackProperty(() => {
          const p = entity?.position?.getValue(new JulianDate());
          return [startPosition, p];
        }, false),
        material: new PolylineDashMaterialProperty({
          color: color,
          dashLength: 3,
        }),
        width: 3,
      },
    });
}

这里会先去获取当前圆环所在小球的坐标,或者就是所点击小球的坐标positions,然后通过viewer.scene.cartesianToCanvasCoordinatesapi计算小球三维坐标在屏幕二维空间的投影,得到一个基准点,方便后续鼠标操作的时候计算小球的偏移量,然后还会绘制一个self.current.pickEntity 小球(会高亮显示),以及绘制一条小球到三维球中心的虚线self.current.auxiliaryBall小球,新绘制的小球和虚线都会跟随鼠标的移动而移动,以用来形象化的展示在空间里的旋转的方位。

方块绘制以及控制

ts 复制代码
if (square.show) {
const position = new Cartesian3();
if (initialQuaternion) {
  Matrix3.multiplyByVector(initialM3, p.square.position, position);
  Cartesian3.multiplyByScalar(position, length / 2.5, position);
}
const squareBasePosition = Cartesian3.multiplyByScalar(p.square.position, length / 2.5, new Cartesian3());
squares['square' + name] = {
  position: initialQuaternion ? position : squareBasePosition.clone(),
  basePosition: squareBasePosition.clone(),
  planeAxis: p.square.planeAxis,
  color,
  material: new ColorMaterialProperty(color.withAlpha(alpha)),
  heading: p.square.heading,
  pitch: p.square.pitch,
  roll: p.square.roll,
};
const dimensionsLength = length / 2.5;
const dimensions = new Cartesian3(dimensionsLength, dimensionsLength, dimensionsLength);
dimensions[name.toLocaleLowerCase() as 'x' | 'y' | 'z'] = 0;
const squareEntity = viewer.entities.add({
  name: id + '/square' + name,
  position: new CallbackProperty(() => {
    const worldMatrix = Transforms.eastNorthUpToFixedFrame(
      Cartesian3.add(self.current.coordinateBall[id].centerPosition, diffCartesian3, new Cartesian3())
    );
    return Matrix4.multiplyByPoint(worldMatrix, squares['square' + name].position, new Cartesian3());
  }, false) as unknown as Cartesian3,
  box: {
    dimensions: dimensions,
    material: color.withAlpha(alpha),
  },
  orientation: new ConstantProperty(
    initialQuaternion
      ? Transforms.headingPitchRollQuaternion(
          self.current.coordinateBall[id].centerPosition,
          HeadingPitchRoll.fromQuaternion(initialQuaternion)
        )
      : Transforms.headingPitchRollQuaternion(
          self.current.coordinateBall[id].centerPosition,
          new HeadingPitchRoll()
        )
  ),
});
squares['square' + name].entity = squareEntity;
}

其他逻辑和上述的一样,再特别说明一下三维空间里的计算会大量用到坐标全局和局部的转换Transforms.eastNorthUpToFixedFrame和旋转姿态四元数的计算Transforms.headingPitchRollQuaternion

点击方块会触发的代码逻辑是:

ts 复制代码
if (name.includes('square') && !self.current.auxiliarySquare) {
    emitter!.emit('coordinateBall/' + id, {
      id,
      type: 'clickSquare',
      name,
    });
    if (squareMove) {
      self.current.auxiliarySquare = { lines: [] };
      const square = coordinateBall.squares[name];
      const { color, planeAxis, entity, material, heading, pitch, roll, position } = square;
      const worldMatrix = Transforms.eastNorthUpToFixedFrame(
        Cartesian3.add(centerPosition, diffCartesian3, new Cartesian3())
      );
      self.current.pickEntity = viewer.entities.add({
        position: Matrix4.multiplyByPoint(worldMatrix, position, new Cartesian3()),
        box: {
          dimensions: new Cartesian3(length / 3.5, 0.1, length / 3.5),
          material: copiesColor,
        },
        orientation: new ConstantProperty(
          Transforms.headingPitchRollQuaternion(
            centerPosition,
            new HeadingPitchRoll(Math.toRadians(heading), Math.toRadians(pitch), Math.toRadians(roll))
          )
        ),
      });
      self.current.pickMateria = material;
      self.current.pickGraphics = entity!.box!;
      self.current.pickGraphics.material = new ColorMaterialProperty(color);
      planeAxis.forEach((p) => {
        const color = coordinateBall.lines['line' + p].color;
        const realCenterPosition = Cartesian3.add(centerPosition, diffCartesian3, new Cartesian3());
        const [_, key] = name.split('line');
        const worldMatrix = Transforms.eastNorthUpToFixedFrame(realCenterPosition);
        const startPosition = Matrix4.multiplyByPoint(
          worldMatrix,
          Cartesian3.multiplyByScalar(normalizes[key], 1500, new Cartesian3()),
          new Cartesian3()
        );
        const endPosition = Matrix4.multiplyByPoint(
          worldMatrix,
          Cartesian3.multiplyByScalar(normalizes[key], -1500, new Cartesian3()),
          new Cartesian3()
        );
        const line = viewer.entities.add({
          polyline: {
            positions: [startPosition, endPosition],
            material: new PolylineDashMaterialProperty({
              color: color,
              dashLength: 3,
            }),
            width: 3,
          },
        });
        self.current.auxiliarySquare?.lines.push(line);
      });
    }
}

这里主要做的逻辑是确定点击的是三块方块中的那一块const square = coordinateBall.squares[name],然后计算出对应的全局坐标worldMatrix,然后把点击的小方块self.current.pickEntity和三维球的三个箭头planeAxis.forEach的姿态都变换到与点击方块对应的轴向平面上。

重制三维球控制器

ts 复制代码
const resetCoordinateBall = (id: string) => {
self.current.coordinateBall[id].diffCartesian3 = new Cartesian3(0, 0, 0);
self.current.coordinateBall[id].fixedDiffCartesian3 = new Cartesian3(0, 0, 0);
const keys = ['X', 'Y', 'Z'];
keys.forEach((key) => {
  self.current.coordinateBall[id].balls['ball' + key].baseAngle = 0;
  self.current.coordinateBall[id].balls['ball' + key].diffAngle = 0;
  const normalize = (self.current.coordinateBall[id].normalizes[key] = normNormalizes[key].clone());
  const { centerPosition } = self.current.coordinateBall[id];
  const worldMatrix = Transforms.eastNorthUpToFixedFrame(centerPosition);
  const baseCartesian3 = Cartesian3.normalize(
    Cartesian3.subtract(
      Matrix4.multiplyByPoint(worldMatrix, normalize, new Cartesian3()),
      centerPosition,
      new Cartesian3()
    ),
    new Cartesian3()
  );
  self.current.coordinateBall[id].lines['line' + key].baseCartesian3 = baseCartesian3;
  const rotationMatrix = Transforms.rotationMatrixFromPositionVelocity(baseCartesian3, baseCartesian3);
  const rot90 = Matrix3.fromRotationY(Math.toRadians(90));
  Matrix3.multiply(rotationMatrix, rot90, rotationMatrix);
  const quaternion = Quaternion.fromRotationMatrix(rotationMatrix);
  self.current.coordinateBall[id].rings['ring' + key].entity!.orientation = new ConstantProperty(quaternion);
  const square = self.current.coordinateBall[id].squares['square' + key];
  if (square) {
    square.position = square.basePosition.clone();
    square.entity!.orientation = new ConstantProperty(
      Transforms.headingPitchRollQuaternion(centerPosition, new HeadingPitchRoll())
    );
  }
});
};

传入通过createCoordinateBall返回的id,可以重置对应三维球的三维姿态。

设置三维球控制器的偏移参数

ts 复制代码
const setCoordinateBallLines = (id: string, key: string, diffValue: number) => {
const coordinateBall = self.current.coordinateBall[id];
const lines = coordinateBall.lines;
const baseCartesian3 = lines[key].baseCartesian3;
const diffCartesian3 = coordinateBall.fixedDiffCartesian3;
Cartesian3.add(
  diffCartesian3,
  Cartesian3.multiplyByScalar(baseCartesian3, diffValue, new Cartesian3()),
  diffCartesian3
);
lines[key].diffValue += diffValue;
};

设置三维球的显隐

ts 复制代码
const setCoordinateBallShow = (id: string, show: boolean) => {
forEach(self.current.coordinateBall[id].balls, (value) => {
  if (value.entity) {
    value.entity.show = show;
  }
});
forEach(self.current.coordinateBall[id].lines, (value) => {
  if (value.entity) {
    value.entity.show = show;
  }
});
forEach(self.current.coordinateBall[id].squares, (value) => {
  if (value.entity) {
    value.entity.show = show;
  }
});
forEach(self.current.coordinateBall[id].rings, (value) => {
  if (value.entity) {
    value.entity.show = show;
  }
});
};

剖切功能代码介绍

这里再次回到本文的剖切功能这里。

剖切功能初始化

ts 复制代码
self.current.clippingPlanes = new ClippingPlaneCollection({
  planes: [new ClippingPlane(new Cartesian3(0.0, 0.0, -1.0), 0.0)],
  unionClippingRegions: true,
  enabled: false,
});
tileset.clippingPlanes = self.current.clippingPlanes;
const boundingSphere = tileset.boundingSphere;
const radius = boundingSphere.radius;
Cartesian3.add(boundingSphere.center, new Cartesian3(), self.current.diffDistance);
self.current.planeEntity = viewer.entities.add({
  position: new CallbackProperty(() => {
    return self.current.diffDistance;
  }, false) as unknown as Cartesian3,
  plane: {
    dimensions: new Cartesian2(radius * 1.2, radius * 1.2),
    material: Color.WHITE.withAlpha(0.5),
    plane: new ClippingPlane(new Cartesian3(0.0, 0.0, 1.0), 0.0),
    outline: true,
    outlineColor: Color.WHITE,
    fill: true,
  },
});

使用cesium原生apinew ClippingPlaneCollection创建真实的剖切平面,然后再手动绘制一个可见的平面self.current.planeEntity,因为平面会随时更改方位,所以这里用变量self.current.diffDistance设置在position: new CallbackProperty中,这样改变变量就能改变平面位置。

绑定三维球控制器和剖切平面

ts 复制代码
const { id, emitter } = createCoordinateBall({
  coordinate: {
    longitude: cesiumMath.toDegrees(longitude),
    latitude: cesiumMath.toDegrees(latitude),
    height: carHeight,
  },
  shows: [
    { line: true, ball: true, ring: true, square: true },
    { line: true, ball: true, ring: true, square: true },
    { line: true, ball: true, ring: true, square: true },
  ],
  zoomShow: false,
  squareMove: false,
  initialQuaternion: !!self.current.pickState ? initialQuaternion : undefined,
});
self.current.coordinateBallId = id;

通过三维球箭头控制平面位移

ts 复制代码
if (data.name.includes('line')) {
    Cartesian3.add(boundingSphere.center, data.diffCartesian3, self.current.diffDistance);
    if (self.current.clippingPlanes) {
      self.current.clippingPlanes.modelMatrix = computeModelMatrix();
    }
    }

通过三维球小球控制平面旋转

ts 复制代码
if (data.name.includes('ball')) {
    const [_, key]: [any, 'X' | 'Y' | 'Z'] = data.name.split('ball');
    const diffAngle = data.angle - self.current.angle[key];
    const quaternionEntity = Quaternion.fromAxisAngle(
      self.current.axisPosition[key],
      cesiumMath.toRadians(diffAngle)
    );
    Quaternion.multiply(self.current.quaternion, quaternionEntity, self.current.quaternion);
    self.current.planeEntity!.orientation = new ConstantProperty(self.current.quaternion);
    if (self.current.pickState) {
      const modelMatrix = self.current.planeEntity!.computeModelMatrix(new JulianDate());
      const vecZ = Matrix4.multiplyByPoint(modelMatrix, new Cartesian3(0, 0, 1), new Cartesian3());
      const normalVec = Cartesian3.normalize(
        Cartesian3.subtract(vecZ, self.current.diffDistance, new Cartesian3()),
        new Cartesian3()
      );
      const worldMatrix = Transforms.eastNorthUpToFixedFrame(self.current.diffDistance);
      const worldToLocalMatrix = Matrix4.inverse(worldMatrix, new Matrix4());
      const c3 = Cartesian3.normalize(
        Matrix4.multiplyByPoint(
          worldToLocalMatrix,
          Cartesian3.add(self.current.diffDistance, normalVec, new Cartesian3()),
          new Cartesian3()
        ),
        new Cartesian3()
      );
      self.current.clippingPlanes!.get(0).normal = Cartesian3.multiplyByScalar(c3, -1, new Cartesian3());
    } else {
      const quaternionClipping = Quaternion.fromAxisAngle(
        self.current.axisCliPosition[key],
        cesiumMath.toRadians(diffAngle)
      );
      Quaternion.multiply(self.current.clippingQuaternion, quaternionClipping, self.current.clippingQuaternion);
    }
    self.current.angle[key] = data.angle;
    if (self.current.clippingPlanes) {
      self.current.clippingPlanes.modelMatrix = computeModelMatrix();
    }
  }

通过三维球方块控制平面归位

ts 复制代码
if (data.type == 'clickSquare') {
    self.current.pickState = undefined;
    const [_, key]: [any, 'X' | 'Y' | 'Z'] = data.name.split('square');
    resetCoordinateBall(id);
    Cartesian3.add(boundingSphere.center, new Cartesian3(0, 0, 0), self.current.diffDistance);
    self.current.angle = {
      X: 0,
      Y: 0,
      Z: 0,
    };
    self.current.clippingQuaternion = Quaternion.IDENTITY.clone();
    let planeNormalVec = new Cartesian3();
    if (key === 'X') {
      planeNormalVec = new Cartesian3(-1, 0, 0);
    } else if (key === 'Y') {
      planeNormalVec = new Cartesian3(0, 1, 0);
    } else if (key === 'Z') {
      planeNormalVec = new Cartesian3(0, 0, -1);
    }
    computeAxisAndPlaneQuaternion(key);
    if (self.current.planeEntity && self.current.clippingPlanes) {
      self.current.planeEntity.orientation = new ConstantProperty(self.current.quaternion);
      self.current.clippingPlanes.get(0).normal = planeNormalVec;
      self.current.clippingPlanes.modelMatrix = computeModelMatrix();
    }
  }

结束剖切

销毁三维球控制器,销毁剖切平面,以及重置代码里的各个参数

ts 复制代码
const stopAxialDeepCut = () => {
if (self.current.planeEntity) {
  removeCoordinateBall();
  viewer.entities.remove(self.current.planeEntity);
  if (self.current.tileset && self.current.tileset.clippingPlanes && self.current.clippingPlanes) {
    self.current.clippingPlanes.enabled = false;
    self.current.clippingPlanes.modelMatrix = Matrix4.fromTranslationQuaternionRotationScale(
      new Cartesian3(10000000, 10000000, 10000000),
      Quaternion.IDENTITY,
      new Cartesian3(0.000001, 0.000001, 0.000001)
    );
    self.current.clippingPlanes = undefined;
  }
  self.current = {
    diffDistance: new Cartesian3(),
    distanceX: 0,
    distanceY: 0,
    distanceZ: 0,
    rotateMatrix: Matrix4.clone(Matrix4.IDENTITY),
    angle: {
      X: 0,
      Y: 0,
      Z: 0,
    },
    axisPosition: {
      X: new Cartesian3(0, 1, 0),
      Y: new Cartesian3(1, 0, 0),
      Z: new Cartesian3(0, 0, 1),
    },
    axisCliPosition: {
      X: new Cartesian3(1, 0, 0),
      Y: new Cartesian3(0, -1, 0),
      Z: new Cartesian3(0, 0, 1),
    },
    p0: new Cartesian3(1, 0, 0),
    normalVec: new Cartesian3(1, 0, 0),
    quaternion: Quaternion.IDENTITY.clone(),
    clippingQuaternion: Quaternion.IDENTITY.clone(),
    baseComputeModelMatrix: Matrix4.IDENTITY.clone(),
    pickState: undefined,
    deepCutToolShow: false,
  };
} else {
  fatal('`stopAxialDeepCut` 还未开始进行轴向剖切!');
  return;
}
};

是否显示剖切工具

ts 复制代码
const showAxialDeepCutTool = (show: boolean) => {
    if (!self.current.planeEntity) {
      fatal('`showAxialDeepCutTool` 还未开始进行轴向剖切!');
      return;
    }
    if (self.current.deepCutToolShow != show) {
      self.current.planeEntity.show = show;
      self.current.coordinateBallId && setCoordinateBallShow(self.current.coordinateBallId, show);
      self.current.deepCutToolShow = show;
    }
};

结语

这个功能涉及到的模块多,代码量多,而且计算也非常多,还有录屏里的吸附功能模块等,暂时还未一一介绍。

相关推荐
小猪努力学前端9 小时前
基于PixiJS的小游戏广告开发
前端·webgl·游戏开发
光影少年2 天前
WebGIS 和GIS学习路线图
学习·前端框架·webgl
DBBH2 天前
Cesium源码分析之渲染3DTile的一点思考
图形渲染·webgl·cesium.js
Robet3 天前
TS2d渲染引擎
webgl
Robet3 天前
WebGL2D渲染引擎
webgl
goodName4 天前
如何实现精准操控?Cesium模型移动旋转控件实现
webgl·cesium
丫丫7237346 天前
Three.js 模型树结构与节点查询学习笔记
javascript·webgl
allenjiao9 天前
WebGPU vs WebGL:WebGPU什么时候能完全替代WebGL?Web 图形渲染的迭代与未来
前端·图形渲染·webgl·threejs·cesium·webgpu·babylonjs
mapvthree9 天前
mapvthree Engine 设计分析——二三维一体化的架构设计
webgl·数字孪生·mapvthree·jsapi2d·jsapigl·引擎对比
GISer_Jing10 天前
3D Cesium渲染架剖析
javascript·3d·webgl