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

点击查看功能演示

功能概览:

  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;
    }
};

结语

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

相关推荐
m0_748248022 天前
WebAssembly与WebGL结合:高性能图形处理
webgl·wasm
程序员_三木3 天前
Three.js入门-Raycaster鼠标拾取详解与应用
开发语言·javascript·计算机外设·webgl·three.js
汪洪墩4 天前
【Mars3d】设置backgroundImage、map.scene.skyBox、backgroundImage来回切换
开发语言·javascript·python·ecmascript·webgl·cesium
m0_748234344 天前
webGL硬核知识:图形渲染管渲染流程,各个阶段对应的API调用方式
图形渲染·webgl
MossGrower4 天前
36. Three.js案例-创建带光照和阴影的球体与平面
3d图形·webgl·three.js·光照与阴影
MossGrower5 天前
34. Three.js案例-创建球体与模糊阴影
webgl·three.js·3d渲染·阴影效果
程序员_三木6 天前
Three.js资源-贴图材质网站推荐
javascript·webgl·three.js·材质·贴图
程序员_三木6 天前
React和Three.js结合-React Three Fiber
前端·javascript·react.js·前端框架·webgl·材质
MossGrower7 天前
37. Three.js案例-绘制部分球体
3d图形·webgl·three.js·球体几何体
3dconvet7 天前
3MF格式转换为STL格式
webgl·3mf转stl·3mf在线转换·3mf在线预览