欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Cesium for UE4中的坐标系及其转换(续)

程序员文章站 2022-06-10 23:26:07
...

常用的转换函数

由于精度问题,提供了两个版本的转换函数。当数值在10^6以内的话可以采用单精度浮点类型,即Inaccurate版本的函数,当数值在10^6以上的时候,使用双精度浮点类型版本的函数,否则误差会大于1m。

BLH->ECEF

//double
glm::dvec3 ACesiumGeoreference::TransformLongitudeLatitudeHeightToEcef(
    const glm::dvec3& longitudeLatitudeHeight) const {
  return CesiumGeospatial::Ellipsoid::WGS84.cartographicToCartesian(
      CesiumGeospatial::Cartographic::fromDegrees(
          longitudeLatitudeHeight.x,
          longitudeLatitudeHeight.y,
          longitudeLatitudeHeight.z));
}
//float
FVector ACesiumGeoreference::InaccurateTransformLongitudeLatitudeHeightToEcef(
    const FVector& longitudeLatitudeHeight) const {
  glm::dvec3 ecef = this->TransformLongitudeLatitudeHeightToEcef(glm::dvec3(
      longitudeLatitudeHeight.X,
      longitudeLatitudeHeight.Y,
      longitudeLatitudeHeight.Z));
  return FVector(ecef.x, ecef.y, ecef.z);
}

ECEF->BLH

//double
glm::dvec3 ACesiumGeoreference::TransformEcefToLongitudeLatitudeHeight(
    const glm::dvec3& ecef) const {
  std::optional<CesiumGeospatial::Cartographic> llh =
      CesiumGeospatial::Ellipsoid::WGS84.cartesianToCartographic(ecef);
  if (!llh) {
    // TODO: since degenerate cases only happen close to Earth's center
    // would it make more sense to assign an arbitrary but correct LLH
    // coordinate to this case such as (0.0, 0.0, -_EARTH_RADIUS_)?
    return glm::dvec3(0.0, 0.0, 0.0);
  }
  return glm::dvec3(
      glm::degrees(llh->longitude),
      glm::degrees(llh->latitude),
      llh->height);
}
//float
FVector ACesiumGeoreference::InaccurateTransformEcefToLongitudeLatitudeHeight(
    const FVector& ecef) const {
  glm::dvec3 llh = this->TransformEcefToLongitudeLatitudeHeight(
      glm::dvec3(ecef.X, ecef.Y, ecef.Z));
  return FVector(llh.x, llh.y, llh.z);
}

ECEF->UE

ECEF 转换 UE 相对坐标。

//double
glm::dvec3
ACesiumGeoreference::TransformEcefToUe(const glm::dvec3& ecef) const {
  
  glm::dvec3 ueAbs = this->_ecefToUeAbs * glm::vec4(ecef, 1.0);

  const FIntVector& originLocation = this->GetWorld()->OriginLocation;

  return ueAbs -
         glm::dvec3(originLocation.X, originLocation.Y, originLocation.Z);
}
//float
FVector
ACesiumGeoreference::InaccurateTransformEcefToUe(const FVector& ecef) const {
  glm::dvec3 ue = this->TransformEcefToUe(glm::dvec3(ecef.X, ecef.Y, ecef.Z));
  return FVector(ue.x, ue.y, ue.z);
}

UE->ECEF

UE相对坐标转 ECEF

//double
glm::dvec3 ACesiumGeoreference::TransformUeToEcef(const glm::dvec3& ue) const {
  const FIntVector& originLocation = this->GetWorld()->OriginLocation;

  glm::dvec4 ueAbs(
      ue.x + static_cast<double>(originLocation.X),
      ue.y + static_cast<double>(originLocation.Y),
      ue.z + static_cast<double>(originLocation.Z),
      1.0);

  return this->_ueAbsToEcef * ueAbs;
}
//float
FVector
ACesiumGeoreference::InaccurateTransformUeToEcef(const FVector& ue) const {
  glm::dvec3 ecef = this->TransformUeToEcef(glm::dvec3(ue.X, ue.Y, ue.Z));
  return FVector(ecef.x, ecef.y, ecef.z);
}

UE ->BLH

UE->ECEF->BLH

//double
glm::dvec3 ACesiumGeoreference::TransformUeToLongitudeLatitudeHeight(
    const glm::dvec3& ue) const {
  glm::dvec3 ecef = this->TransformUeToEcef(ue);
  return this->TransformEcefToLongitudeLatitudeHeight(ecef);
}
//float
FVector ACesiumGeoreference::InaccurateTransformUeToLongitudeLatitudeHeight(
    const FVector& ue) const {
  glm::dvec3 llh =
      this->TransformUeToLongitudeLatitudeHeight(glm::dvec3(ue.X, ue.Y, ue.Z));
  return FVector(llh.x, llh.y, llh.z);
}



BLH ->UE

BLH->ECEF->UE

//double
glm::dvec3 ACesiumGeoreference::TransformLongitudeLatitudeHeightToUe(
    const glm::dvec3& longitudeLatitudeHeight) const {
  glm::dvec3 ecef =
      this->TransformLongitudeLatitudeHeightToEcef(longitudeLatitudeHeight);
  return this->TransformEcefToUe(ecef);
}
//float
FVector ACesiumGeoreference::InaccurateTransformLongitudeLatitudeHeightToUe(
    const FVector& longitudeLatitudeHeight) const {
  glm::dvec3 ue = this->TransformLongitudeLatitudeHeightToUe(glm::dvec3(
      longitudeLatitudeHeight.X,
      longitudeLatitudeHeight.Y,
      longitudeLatitudeHeight.Z));
  return FVector(ue.x, ue.y, ue.z);
}

ENU->ECEF 旋转变换矩阵

计算参考椭球上一点的ENU。

//double
glm::dmat3
ACesiumGeoreference::ComputeEastNorthUpToEcef(const glm::dvec3& ecef) const {
  return glm::dmat3(
      CesiumGeospatial::Transforms::eastNorthUpToFixedFrame(ecef));
}
//float
FMatrix ACesiumGeoreference::InaccurateComputeEastNorthUpToEcef(
    const FVector& ecef) const {
  glm::dmat3 enuToEcef =
      this->ComputeEastNorthUpToEcef(glm::dvec3(ecef.X, ecef.Y, ecef.Z));

  return FMatrix(
      FVector(enuToEcef[0].x, enuToEcef[0].y, enuToEcef[0].z),
      FVector(enuToEcef[1].x, enuToEcef[1].y, enuToEcef[1].z),
      FVector(enuToEcef[2].x, enuToEcef[2].y, enuToEcef[2].z),
      FVector(0.0, 0.0, 0.0));
}

ENU->UE 旋转变换矩阵

ENU->ECEF->UE

//double
glm::dmat3
ACesiumGeoreference::ComputeEastNorthUpToUnreal(const glm::dvec3& ue) const {
  glm::dvec3 ecef = this->TransformUeToEcef(ue);
  glm::dmat3 enuToEcef = this->ComputeEastNorthUpToEcef(ecef);

  // Camera Axes = ENU
  // Unreal Axes = controlled by Georeference
  glm::dmat3 rotationCesium =
      glm::dmat3(this->_ecefToGeoreferenced) * enuToEcef;

  return glm::dmat3(CesiumTransforms::unrealToOrFromCesium) * rotationCesium *
         glm::dmat3(CesiumTransforms::unrealToOrFromCesium);
}
//float
FMatrix ACesiumGeoreference::InaccurateComputeEastNorthUpToUnreal(
    const FVector& ue) const {
  glm::dmat3 enuToUnreal =
      this->ComputeEastNorthUpToUnreal(glm::dvec3(ue.X, ue.Y, ue.Z));

  return FMatrix(
      FVector(enuToUnreal[0].x, enuToUnreal[0].y, enuToUnreal[0].z),
      FVector(enuToUnreal[1].x, enuToUnreal[1].y, enuToUnreal[1].z),
      FVector(enuToUnreal[2].x, enuToUnreal[2].y, enuToUnreal[2].z),
      FVector(0.0, 0.0, 0.0));
}
相关标签: UE4 UE4 Cesium