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));
}
上一篇: 慢性鼻炎饮食指南 慢性鼻炎饮食注意事项
下一篇: 别跟俺套近乎