一只大白鹅蛋 2022-04-09 18:11 采纳率: 80%
浏览 810
已结题

cesium 圆锥体绕某一个点翻转一个角度如何实现

问题遇到的现象和发生背景

Cesium.Transforms.headingPitchRollQuaternion(origin, hpr)的origin可以设置为(x,y,z)吗,这个点就是绕着旋转的点吗?

问题相关代码,请勿粘贴截图
            var positioncone = Cesium.Cartesian3.fromDegrees(locs[0], locs[1], locs[2]/2)
            var position = Cesium.Cartesian3.fromDegrees(locs[0], locs[1], locs[2])
            var headingcone = Cesium.Math.toRadians(0)
            var pitchcone = Cesium.Math.toRadians(0)
            var rollcone = Cesium.Math.toRadians(0)
            var hprcone = new Cesium.HeadingPitchRoll(headingcone, pitchcone, rollcone)
            //镜头对准方法:
            var orientationcone = Cesium.Transforms.headingPitchRollQuaternion(
              position,
              hprcone
            );
            var entitycone = viewer.entities.add({
              name: 'Red cone',
              position: positioncone,
              orientation: orientationcone,
              cylinder: {
                length: locs[2],
                topRadius: 0.0,
                bottomRadius: 100.0,
                material: Cesium.Color.BLUE.withAlpha(0.9),
                disableDepthTestDistance: 0,
              },
            });
运行结果及报错内容
我的解答思路和尝试过的方法

origin设置为([0], [1], [2])没用,圆锥还是绕着它自己的中心点旋转

我想要达到的结果

圆锥可以绕着自己的顶点转动一个角度

  • 写回答

2条回答 默认 最新

  • 前端人丶 2022-04-10 13:11
    关注

    几何体旋转都是以几何原点为基准旋转的 cesium提供的圆锥体几何原点是几何体中心不是圆锥顶点,这里可以使用primitive-geometry重新构建出以顶点为原点的几何体进行绘制 然后进行旋转变换;
    提供一个我仿照cesium圆锥构建的类
    `
    import { BoundingSphere, Cartesian2, Cartesian3, Math as CesiumMath, defaultValue, defined, DeveloperError, Geometry, Primitive, PrimitiveType, VertexFormat, GeometryAttribute, ComponentDatatype, IndexDatatype, GeometryAttributes } from "cesium";
    function arrayFill(array: any[] | Uint8Array, value: any, start?: number, end?: number) {
    if (typeof array.fill === "function") {
    return array.fill(value, start, end);
    }

    const length = array.length >>> 0;
    const relativeStart = defaultValue(start, 0);
    // If negative, find wrap around position
    let k =
    relativeStart < 0
    ? Math.max(length + relativeStart, 0)
    : Math.min(relativeStart, length);
    const relativeEnd = defaultValue(end, length);
    // If negative, find wrap around position
    const last =
    relativeEnd < 0
    ? Math.max(length + relativeEnd, 0)
    : Math.min(relativeEnd, length);

    // Fill array accordingly
    while (k < last) {
    array[k] = value;
    k++;
    }
    return array;
    }

    function computePositions(length: number, topRadius: number, bottomRadius: number, slices: number, fill: boolean) {
    const topZ = 0;
    const bottomZ = -length;

    const twoSlice = slices + slices;
    const size = fill ? 2 * twoSlice : twoSlice;
    const positions = new Float64Array(size * 3);
    let i;
    let index = 0;
    let tbIndex = 0;
    const bottomOffset = fill ? twoSlice * 3 : 0;
    const topOffset = fill ? (twoSlice + slices) * 3 : slices * 3;

    for (i = 0; i < slices; i++) {
    const angle = (i / slices) * CesiumMath.TWO_PI;
    const x = Math.cos(angle);
    const y = Math.sin(angle);
    const bottomX = x * bottomRadius;
    const bottomY = y * bottomRadius;
    const topX = x * topRadius;
    const topY = y * topRadius;

    positions[tbIndex + bottomOffset] = bottomX;
    positions[tbIndex + bottomOffset + 1] = bottomY;
    positions[tbIndex + bottomOffset + 2] = bottomZ;
    
    positions[tbIndex + topOffset] = topX;
    positions[tbIndex + topOffset + 1] = topY;
    positions[tbIndex + topOffset + 2] = topZ;
    tbIndex += 3;
    if (fill) {
      positions[index++] = bottomX;
      positions[index++] = bottomY;
      positions[index++] = bottomZ;
      positions[index++] = topX;
      positions[index++] = topY;
      positions[index++] = topZ;
    }
    

    }

    return positions;
    };

    type ConeGeometryOption = {
    length: number;
    topRadius?: number;
    bottomRadius: number;
    slices?: number;
    vertexFormat?: VertexFormat;
    numberOfVerticalLines?: number;
    offsetAttribute?: number;
    }

    function createGeometry(options: ConeGeometryOption) {
    let length = options.length;
    const topRadius = options.topRadius || 0;
    const bottomRadius = options.bottomRadius;
    const vertexFormat = options.vertexFormat as VertexFormat;
    const slices = options.slices as number;
    const offsetAttribute = options.offsetAttribute;

    if (
    length <= 0 ||
    topRadius < 0 ||
    bottomRadius < 0 ||
    (topRadius === 0 && bottomRadius === 0)
    ) {
    return;
    }

    const twoSlices = slices + slices;
    const threeSlices = slices + twoSlices;
    const numVertices = twoSlices + twoSlices;

    const positions = computePositions(length, topRadius, bottomRadius, slices, true);

    const st = vertexFormat.st ? new Float32Array(numVertices * 2) : undefined;
    const normals = vertexFormat.normal ? new Float32Array(numVertices * 3) : undefined;
    const tangents = vertexFormat.tangent ? new Float32Array(numVertices * 3) : undefined;
    const bitangents = vertexFormat.bitangent ? new Float32Array(numVertices * 3) : undefined;

    let i;
    const computeNormal = vertexFormat.normal || vertexFormat.tangent || vertexFormat.bitangent;

    if (computeNormal) {
    const computeTangent = vertexFormat.tangent || vertexFormat.bitangent;

    let normalIndex = 0;
    let tangentIndex = 0;
    let bitangentIndex = 0;
    
    const theta = Math.atan2(bottomRadius - topRadius, length);
    const normal = new Cartesian3();
    normal.z = Math.sin(theta);
    const normalScale = Math.cos(theta);
    let tangent = new Cartesian3();
    let bitangent = new Cartesian3();
    
    for (i = 0; i < slices; i++) {
      const angle = (i / slices) * CesiumMath.TWO_PI;
      const x = normalScale * Math.cos(angle);
      const y = normalScale * Math.sin(angle);
      if (computeNormal) {
        normal.x = x;
        normal.y = y;
    
        if (computeTangent) {
          tangent = Cartesian3.normalize(
            Cartesian3.cross(Cartesian3.UNIT_Z, normal, tangent),
            tangent
          );
        }
    
        if (normals) {
          normals[normalIndex++] = normal.x;
          normals[normalIndex++] = normal.y;
          normals[normalIndex++] = normal.z;
          normals[normalIndex++] = normal.x;
          normals[normalIndex++] = normal.y;
          normals[normalIndex++] = normal.z;
        }
    
        if (tangents) {
          tangents[tangentIndex++] = tangent.x;
          tangents[tangentIndex++] = tangent.y;
          tangents[tangentIndex++] = tangent.z;
          tangents[tangentIndex++] = tangent.x;
          tangents[tangentIndex++] = tangent.y;
          tangents[tangentIndex++] = tangent.z;
        }
    
        if (bitangents) {
          bitangent = Cartesian3.normalize(
            Cartesian3.cross(normal, tangent, bitangent),
            bitangent
          );
          bitangents[bitangentIndex++] = bitangent.x;
          bitangents[bitangentIndex++] = bitangent.y;
          bitangents[bitangentIndex++] = bitangent.z;
          bitangents[bitangentIndex++] = bitangent.x;
          bitangents[bitangentIndex++] = bitangent.y;
          bitangents[bitangentIndex++] = bitangent.z;
        }
      }
    }
    
    for (i = 0; i < slices; i++) {
      if (normals) {
        normals[normalIndex++] = 0;
        normals[normalIndex++] = 0;
        normals[normalIndex++] = -1;
      }
      if (tangents) {
        tangents[tangentIndex++] = 1;
        tangents[tangentIndex++] = 0;
        tangents[tangentIndex++] = 0;
      }
      if (bitangents) {
        bitangents[bitangentIndex++] = 0;
        bitangents[bitangentIndex++] = -1;
        bitangents[bitangentIndex++] = 0;
      }
    }
    
    for (i = 0; i < slices; i++) {
      if (normals) {
        normals[normalIndex++] = 0;
        normals[normalIndex++] = 0;
        normals[normalIndex++] = 1;
      }
      if (tangents) {
        tangents[tangentIndex++] = 1;
        tangents[tangentIndex++] = 0;
        tangents[tangentIndex++] = 0;
      }
      if (bitangents) {
        bitangents[bitangentIndex++] = 0;
        bitangents[bitangentIndex++] = 1;
        bitangents[bitangentIndex++] = 0;
      }
    }
    

    }

    const numIndices = 12 * slices - 12;
    // @ts-ignore
    const indices = IndexDatatype.createTypedArray(numVertices, numIndices);
    let index = 0;
    let j = 0;
    for (i = 0; i < slices - 1; i++) {
    indices[index++] = j;
    indices[index++] = j + 2;
    indices[index++] = j + 3;

    indices[index++] = j;
    indices[index++] = j + 3;
    indices[index++] = j + 1;
    
    j += 2;
    

    }

    indices[index++] = twoSlices - 2;
    indices[index++] = 0;
    indices[index++] = 1;
    indices[index++] = twoSlices - 2;
    indices[index++] = 1;
    indices[index++] = twoSlices - 1;

    for (i = 1; i < slices - 1; i++) {
    indices[index++] = twoSlices + i + 1;
    indices[index++] = twoSlices + i;
    indices[index++] = twoSlices;
    }

    for (i = 1; i < slices - 1; i++) {
    indices[index++] = threeSlices;
    indices[index++] = threeSlices + i;
    indices[index++] = threeSlices + i + 1;
    }

    let textureCoordIndex = 0;
    if (st) {
    const rad = Math.max(topRadius, bottomRadius);
    for (i = 0; i < numVertices; i++) {
    // @ts-ignore
    const position = Cartesian3.fromArray(positions, i * 3, new Cartesian3());
    st[textureCoordIndex++] = (position.x + rad) / (2.0 * rad);
    st[textureCoordIndex++] = (position.y + rad) / (2.0 * rad);
    }
    }

    const attributes = new GeometryAttributes();
    if (vertexFormat.position) {
    attributes.position = new GeometryAttribute({
    componentDatatype: ComponentDatatype.DOUBLE,
    componentsPerAttribute: 3,
    values: positions,
    });
    }

    if (vertexFormat.normal) {
    attributes.normal = new GeometryAttribute({
    componentDatatype: ComponentDatatype.FLOAT,
    componentsPerAttribute: 3,
    values: normals,
    });
    }

    if (vertexFormat.tangent) {
    attributes.tangent = new GeometryAttribute({
    componentDatatype: ComponentDatatype.FLOAT,
    componentsPerAttribute: 3,
    values: tangents,
    });
    }

    if (vertexFormat.bitangent) {
    attributes.bitangent = new GeometryAttribute({
    componentDatatype: ComponentDatatype.FLOAT,
    componentsPerAttribute: 3,
    values: bitangents,
    });
    }

    if (vertexFormat.st) {
    attributes.st = new GeometryAttribute({
    componentDatatype: ComponentDatatype.FLOAT,
    componentsPerAttribute: 2,
    values: st,
    });
    }
    const radiusScratch = new Cartesian2();
    radiusScratch.x = length * 0.5;
    radiusScratch.y = Math.max(bottomRadius, topRadius);

    const boundingSphere = new BoundingSphere(
    Cartesian3.ZERO,
    Cartesian2.magnitude(radiusScratch)
    );

    if (defined(offsetAttribute)) {
    length = positions.length;
    const applyOffset = new Uint8Array(length / 3);
    const offsetValue = offsetAttribute === 0 ? 0 : 1;
    arrayFill(applyOffset, offsetValue);
    // @ts-ignore
    attributes.applyOffset = new GeometryAttribute({
    componentDatatype: ComponentDatatype.UNSIGNED_BYTE,
    componentsPerAttribute: 1,
    values: applyOffset,
    });
    }
    return {
    attributes: attributes,
    indices: indices,
    primitiveType: PrimitiveType.TRIANGLES,
    boundingSphere: boundingSphere,
    // @ts-ignore
    offsetAttribute: offsetAttribute,
    };
    }

    /**

    • 圆锥-ptimiotive
    • 以顶点为中心圆锥
    • /
      class ConeGeometry extends Geometry {
      constructor(options: ConeGeometryOption) {
      options.slices = defaultValue(options.slices, 128);
      const vertexFormat = defaultValue(options.vertexFormat, VertexFormat.DEFAULT);
      options.vertexFormat = VertexFormat.clone(vertexFormat);
      if (defined(options.offsetAttribute) && options.offsetAttribute === 1) {
      throw new DeveloperError("GeometryOffsetAttribute.TOP is not a supported options.offsetAttribute for this geometry.");
      
      }
      options.offsetAttribute = options.offsetAttribute;
      const geometryOption = createGeometry(options) as {
      attributes: GeometryAttributes;
      primitiveType?: PrimitiveType;
      indices?: Uint16Array | Uint32Array;
      boundingSphere?: BoundingSphere;
      
      };
      super(geometryOption);
      }
      }

    export default ConeGeometry;

    viewer.scene.primitives.add(new Primitive({
    geometryInstances: new GeometryInstance({
    geometry: new ConeGeometry({
    length: 10000,
    bottomRadius: 2000,
    })
    }),
    modelMatrix: modelMatrix,
    asynchronous: false,
    appearance: new MaterialAppearance({
    closed: true,
    material: Material.fromType('Color', {
    color: Color.RED
    })
    }),
    }))
    });

    `

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 4月18日
  • 已采纳回答 4月10日
  • 创建了问题 4月9日

悬赏问题

  • ¥15 网络爬虫 在北京新发地抓取数据
  • ¥15 在centos7安装conda
  • ¥15 c#调用yolo3 dll文件获取的数据对不上
  • ¥20 WPF 如何实现多语言,label 和cs(live Charts)中是否都能翻译
  • ¥15 STM32F103上电短路问题
  • ¥15 关于#单片机#的问题:以ATMEGA128或相近型号单片机为控制器设计直流电机调速的闭环控制系统(相关搜索:设计报告|软件设计|流程图)
  • ¥15 打开软件提示错误:failed to get wglChoosePixelFormatARB
  • ¥15 (标签-python|关键词-char)
  • ¥15 python+selenium,在新增时弹出了一个输入框
  • ¥15 苹果验机结果的api接口哪里有??单次调用1毛钱及以下。