[UE]常见数学和插值

UE常见数学和插值

  • 参考
  • unreal中的Transform基础
    • FMatrix、FMatrix44f、FMatrix44d
    • FTranslationMatrix
    • FRotationMatrix
    • TRotator<T>
    • FQuat
    • FScaleMatrix
    • FTransform
  • 关于旋转的几个常见示例
    • 1. 将不限范围的角度转换到[0, 360)
    • 2.A位置的actor看向B位置
    • 3.RotateVector和UnrotateVector
  • 插值相关
    • 旋转插值Math.RInterpTo
    • 标量插值Math.FInterpTo
    • FMath::Lerp/FMath::FInterpConstantTo
    • UKismetMathLibrary::Ease
  • Debug相关
  • KismetMathLibrary
  • GameplayStatics
  • Python的Math
    • atan2和atan

参考

Unreal Transformation
游戏中的旋转变换——四元数和欧拉角
UE4 三种旋转 (一)
UE4_源码浅析篇_矩阵

unreal中的Transform基础

Unreal Transformation
UE4 三种旋转 (一)

父空间坐标转局部空间坐标。
FTransform.InverseTransformLocation(FVector Location)局部空间坐标转父空间坐标。
FTransform.TransformLocation(FVector Location)局部空间旋转转父空间旋转。
FTransform.TransformRotation(FRotator Rotator)获取使当前坐标系X轴旋转到X_V向量的Rotator。
MakeRotFromX(FVector X_V)
template<typename T>
TMatrix<T> TRotationMatrix<T>::MakeFromX(TVector<T> const& XAxis)
{TVector<T> const NewX = XAxis.GetSafeNormal();// try to use up if possibleTVector<T> const UpVector = (FMath::Abs(NewX.Z) < (1.f - UE_KINDA_SMALL_NUMBER)) ? TVector<T>(0, 0, 1.f) : TVector<T>(1.f, 0, 0);const TVector<T> NewY = (UpVector ^ NewX).GetSafeNormal();const TVector<T> NewZ = NewX ^ NewY;return TMatrix<T>(NewX, NewY, NewZ, TVector<T>::ZeroVector);
}实际上就是MakeRotFromX(Target-Start)FindLookAtRotation(FVector Start,FVector Target)// RotationMatrix.h
// 保证FRotationMatrix的X轴指向给定方向X时,也保证了FRotationMatrix的Y轴约束在给定的方向X和方向Y的平面上,而TRotationMatrix::MakeFromX只指定X轴指向给定方向X,但是Y的方向并没有约束
FRotationMatrix::MakeFromXYtemplate<typename T>
TMatrix<T> TRotationMatrix<T>::MakeFromXY(TVector<T> const& XAxis, TVector<T> const& YAxis)
{// 1. 计算单位向量TVector<T> NewX = XAxis.GetSafeNormal();TVector<T> Norm = YAxis.GetSafeNormal();// if they're almost same, we need to find arbitrary vectorif (FMath::IsNearlyEqual(FMath::Abs(NewX | Norm), T(1.f))){// make sure we don't ever pick the same as NewXNorm = (FMath::Abs(NewX.Z) < (1.f - UE_KINDA_SMALL_NUMBER)) ? TVector<T>(0, 0, 1.f) : TVector<T>(1.f, 0, 0);}// 2. NewZ = NewX 叉乘 Norm//    NewY = NewZ 叉乘 NewX const TVector<T> NewZ = (NewX ^ Norm).GetSafeNormal();const TVector<T> NewY = NewZ ^ NewX;return TMatrix<T>(NewX, NewY, NewZ, TVector<T>::ZeroVector);
}FRotationMatrix::MakeFromXZ
template<typename T>
TMatrix<T> TRotationMatrix<T>::MakeFromXZ(TVector<T> const& XAxis, TVector<T> const& ZAxis)
{TVector<T> const NewX = XAxis.GetSafeNormal();TVector<T> Norm = ZAxis.GetSafeNormal();// if they're almost same, we need to find arbitrary vectorif (FMath::IsNearlyEqual(FMath::Abs(NewX | Norm), T(1.f))){// make sure we don't ever pick the same as NewXNorm = (FMath::Abs(NewX.Z) < (1.f - UE_KINDA_SMALL_NUMBER)) ? TVector<T>(0, 0, 1.f) : TVector<T>(1.f, 0, 0);}const TVector<T> NewY = (Norm ^ NewX).GetSafeNormal();const TVector<T> NewZ = NewX ^ NewY;return TMatrix<T>(NewX, NewY, NewZ, TVector<T>::ZeroVector);
}

FMatrix、FMatrix44f、FMatrix44d

// Matrix.h, Matrix.inl
TMatrix<T>// MathFwd.h
using FMatrix 		= UE::Math::TMatrix<double>;		// UE_DECLARE_LWC_TYPE(Matrix, 44);

FMatrix是unreal中表示3D变换的一个4x4的浮点数矩阵,其中前三列代表旋转和缩放,第四列代表平移。
FMatrix的元素排列方式为列主序(column-major order),即按列顺序依次填写。
下面是一个示例,展示了如何填写一个包含平移、旋转和缩放的变换矩阵:

float ScaleX = 1;
float ScaleY = 2;
float ScaleZ = 3;
float RotationPitch = 4;
float RotationYaw = 5;
float RotationRoll = 6;
float TranslationX = 7;
float TranslationY = 8;
float TranslationZ = 9;FMatrix/FMatrix44f/FMatrix44d TransformMatrix;
TransformMatrix.M[0][0] = ScaleX * FMath::Cos(RotationYaw) * FMath::Cos(RotationRoll);
TransformMatrix.M[0][1] = ScaleX * FMath::Sin(RotationYaw) * FMath::Cos(RotationRoll);
TransformMatrix.M[0][2] = -ScaleX * FMath::Sin(RotationRoll);
TransformMatrix.M[0][3] = 0.0f;
TransformMatrix.M[1][0] = ScaleY * (FMath::Cos(RotationYaw) * FMath::Sin(RotationRoll) * FMath::Sin(RotationPitch) - FMath::Sin(RotationYaw) * FMath::Cos(RotationPitch));
TransformMatrix.M[1][1] = ScaleY * (FMath::Sin(RotationYaw) * FMath::Sin(RotationRoll) * FMath::Sin(RotationPitch) + FMath::Cos(RotationYaw) * FMath::Cos(RotationPitch));
TransformMatrix.M[1][2] = ScaleY * FMath::Cos(RotationRoll) * FMath::Sin(RotationPitch);
TransformMatrix.M[1][3] = 0.0f;
TransformMatrix.M[2][0] = ScaleZ * (FMath::Cos(RotationYaw) * FMath::Sin(RotationRoll) * FMath::Cos(RotationPitch) + FMath::Sin(RotationYaw) * FMath::Sin(RotationPitch));
TransformMatrix.M[2][1] = ScaleZ * (FMath::Sin(RotationYaw) * FMath::Sin(RotationRoll) * FMath::Cos(RotationPitch) - FMath::Cos(RotationYaw) * FMath::Sin(RotationPitch));
TransformMatrix.M[2][2] = ScaleZ * FMath::Cos(RotationRoll) * FMath::Cos(RotationPitch);
TransformMatrix.M[2][3] = 0.0f;
TransformMatrix.M[3][0] = TranslationX;
TransformMatrix.M[3][1] = TranslationY;
TransformMatrix.M[3][2] = TranslationZ;
TransformMatrix.M[3][3] = 1.0f;
其中,TransformMatrix.M[i][j]表示矩阵中第i列第j行的元素值。

FMatrix、FMatrix44f、FMatrix44d

相同点

三者都可以用于表示3D空间中的变换。
都支持矩阵乘法、加法、减法、转置、求逆等操作。
都可以相互转换。

不同点:

数据类型不同:FMatrix使用单精度浮点数,FMatrix44f使用单精度浮点数,FMatrix44d使用双精度浮点数。
计算精度不同:FMatrix使用单精度浮点数,精度较低;FMatrix44f使用单精度浮点数,精度较高但是内存占用较大;FMatrix44d使用双精度浮点数,精度最高但是内存占用最大。
相互转换时需要进行类型转换。
可以使用强制类型转换来相互转换

FTranslationMatrix

平移矩阵,用于表示沿x、y、z轴的平移变换,一个只有平移变换的矩阵。
构造函数接受一个FVector类型的参数,表示需要进行平移的向量

FRotationMatrix

一个只有旋转变换的矩阵

// RotationMatrix.h
TRotationMatrix<T>

FRotationMatrix比较特殊,只能在纯C++中使用,不能用UFUNCTION等暴露给蓝图,见:Unable to find ‘class’, ‘delegate’, ‘enum’, or ‘struct’ with name ‘FRotationMatrix’

// 编译报错
UFUNCTION(BlueprintCallable)
FRotationMatrix Convert(const FRotator& Rot);// 修改成FMatrix
UFUNCTION(BlueprintCallable)
FMatrix Convert(const FRotator& Rot);
// 函数实现内部可以按照如下方式转换
FMatrix myRotationMatrix=FRotationMatrix::Make(FRotator(0,0,0));

FRotationMatrix与FRotator、FQuat的转换

// 1.FRotator==>FRotationMatrix
FRotator Rotation(roll, pitch, yaw); //其中roll、pitch和yaw分别表示绕x、y和z轴的旋转角度。
FMatrix RotationMatrix = FRotationMatrix(Rotation);
// 2.FRotationMatrix==>FRotator
FRotationMatrix RotationMatrix = ...;
FRotator Rotation = RotationMatrix.Rotator();// 3.FQuat==>FRotationMatrix
FQuat QuatRotation = ...;
FRotationMatrix RotationMatrix = FRotationMatrix(QuatRotation.Rotator());
// 4.FRotationMatrix==>FQuat
FRotationMatrix RotationMatrix = ...;
FQuat RotationQuat = RotationMatrix.ToQuat();
FQuat QuatRotation = FQuat(RotationMatrix);

TRotator

欧拉角,FRotator是一个包含三个浮点数Pitch、Yaw、Roll的结构体,用于表示3D旋转。

TRotator<T>: Rotator.h
// 注意FRotator的构造函数中参数顺序是 Pitch, Yaw, Roll
// Pitch:俯仰角,即绕Y轴旋转;
// Yaw:偏角,即绕Z轴旋转;
// Roll:滚角,即绕X轴旋转。
FORCEINLINE TRotator( T InPitch, T InYaw, T InRoll );
// UKismetMathLibrary::MakeRotator中的顺序是Roll, Pitch, Yaw
FRotator UKismetMathLibrary::MakeRotator(float Roll, float Pitch, float Yaw)
{return FRotator(Pitch,Yaw,Roll);
}// MathFwd.h
using FRotator 		= UE::Math::TRotator<double>;		// UE_DECLARE_LWC_TYPE(Rotator, 3);// 使用示例
//绕`z`轴旋转10度
FRotator rotator(0, 10, 0); 
AActorT->SetActorRotation(rotator);

FQuat

四元数,x、y、z、w。用于表示3D旋转。四元数比欧拉角更加高效. FQuat通常用于表示游戏角色的旋转。避免万向锁,以及更方便做差值计算。

FQuat(FVector Axis, float AngleRad)struct FQuat 
{public:/** The quaternion's X-component. */float X;/** The quaternion's Y-component. */float Y;/** The quaternion's Z-component. */float Z;/** The quaternion's W-component. */float W;
}// 构造函数: 创建和初始化一个新的四元数(根据给定轴旋转 a 弧度)
FQuat(FVector Axis, float AngleRad)//绕z轴旋转45度
FQuat quat = FQuat(FVector(0, 0, 1), PI / 4.f); 
GetOwner()->SetActorRotation(quat);FQuat axisRot(FVector::RightVector, FMath::DegreesToRadians(90));
SetActorRotation((GetActorRotation().Quaternion() * axisRot).Rotator());FQuat axisRot(FVector::UpVector, FMath::DegreesToRadians(90);
SetActorRotation((axisRot * GetActorRotation().Quaternion()).Rotator());

FScaleMatrix

缩放矩阵,用于表示沿x、y、z轴的缩放变换,一个只有缩放变换的矩阵。

FTransform

FTranslationMatrix、FRotationMatrix、FScaleMatrix来构建一个FTransform

FVector ScaleVector = FVector(2.f, 3.f, 4.f);
FScaleMatrix ScaleMatrix(ScaleVector);FRotator Rotation(0.f, 45.f, 0.f);
FRotationMatrix RotationMatrix = FRotationMatrix(Rotation);FVector Translation(100.0f, 200.0f, 300.0f);
FTranslationMatrix TranslationMatrix(Translation);FTransform Transform(RotationMatrix.ToQuat(), TranslationMatrix.GetOrigin(), ScaleMatrix.GetScaleVector());

关于旋转的几个常见示例

1. 将不限范围的角度转换到[0, 360)

UKismetMathLibrary::ClampAxis

// KismetMathLibrary.cpp
float UKismetMathLibrary::ClampAxis(float Angle)
{return FRotator::ClampAxis(Angle);
}
// Rotator.h
template<typename T>
FORCEINLINE T TRotator<T>::ClampAxis( T Angle )
{// returns Angle in the range (-360,360)Angle = FMath::Fmod(Angle, (T)360.0);if (Angle < (T)0.0){// shift to [0,360) rangeAngle += (T)360.0;}return Angle;
}

2.A位置的actor看向B位置

A位置的actor看向B位置,实际就是将A位置的actor的forward vector转向A->B
2.1 KismetMathLibrary.FindLookAtRotation/UKismetMathLibrary::MakeRotFromX/KismetMathLibrary.MakeRotFromXY

// 解释
KismetMathLibrary.FindLookAtRotation 等价于 UKismetMathLibrary::MakeRotFromX 等价于
TVector<T>::ToOrientationRotator()// MakeRotFromXY相比MakeRotFromX,除了使forward vector指向X外,还约束了right vector在XY平面上,
KismetMathLibrary.MakeRotFromXY
KismetMathLibrary.MakeRotFromXZ// 示例
FVector LookDirection = target->GetActorLocation() - GetOwner()->GetActorLocation(); 
FMatrix LookRotationMatrix = FRotationMatrix::MakeFromXZ(LookDirection, GetOwner()->GetActorUpVector()); 
GetOwner()->SetActorRotation(LookRotationMatrix.Rotator());// 源码KismetMathLibrary.inl
FRotator UKismetMathLibrary::FindLookAtRotation(const FVector& Start, const FVector& Target)
{return MakeRotFromX(Target - Start);
}
FRotator UKismetMathLibrary::MakeRotFromX(const FVector& X)
{return FRotationMatrix::MakeFromX(X).Rotator();
}FRotator UKismetMathLibrary::MakeRotFromXY(const FVector& X, const FVector& Y)
{return FRotationMatrix::MakeFromXY(X, Y).Rotator();
}FRotator UKismetMathLibrary::MakeRotFromXZ(const FVector& X, const FVector& Z)
{return FRotationMatrix::MakeFromXZ(X, Z).Rotator();
}

2.2 UKismetMathLibrary::Conv_VectorToRotator

// 求出令forward vector和InVec同向的FRotator
FRotator UKismetMathLibrary::Conv_VectorToRotator(FVector InVec)// KismetMathLibrary.inl
KISMET_MATH_FORCEINLINE
FRotator UKismetMathLibrary::Conv_VectorToRotator(FVector InVec)
{return InVec.ToOrientationRotator();
}
// UnrealMath.cpp
template<typename T>
UE::Math::TRotator<T> UE::Math::TVector<T>::ToOrientationRotator() const
{UE::Math::TRotator<T> R;// Find yaw.R.Yaw = FMath::RadiansToDegrees(FMath::Atan2(Y, X));// Find pitch.R.Pitch = FMath::RadiansToDegrees(FMath::Atan2(Z, FMath::Sqrt(X*X + Y*Y)));// Find roll.R.Roll = 0;
#if ENABLE_NAN_DIAGNOSTIC || (DO_CHECK && !UE_BUILD_SHIPPING)if (R.ContainsNaN()){logOrEnsureNanError(TEXT("TVector::Rotation(): Rotator result %s contains NaN! Input FVector = %s"), *R.ToString(), *this->ToString());R = UE::Math::TRotator<T>::ZeroRotator;}
#endifreturn R;
}

3.RotateVector和UnrotateVector

旋转矩阵是正交矩阵,逆等于转置, 旋转矩阵(Rotate Matrix)的性质分析

RotateVector: 将世界坐标系下的向量转换到旋转矩阵表示的局部坐标系下
UnrotateVector: 将向量从旋转矩阵表示的局部坐标系下转换到世界坐标系下
使用示例1:让A点绕B点旋转:UE4之A点绕B点旋转
使用示例2:ALS中相机镜头控制部分的插值逻辑 AALSPlayerCameraManager::CalculateAxisIndependentLag

// 关于RotateVector和UnrotateVector的作用,在ALS的相机镜头控制中使用示例如下
// 先用RotateVector转换到相机旋转矩阵表示的局部坐标系下,然后在局部坐标系下的三个轴分别插值
// 然后将插值结果用UnrotateVector局部坐标系下转换到世界坐标系下
// 区别直接在世界坐标系下的三个轴插值分别插值,
FVector AALSPlayerCameraManager::CalculateAxisIndependentLag(FVector CurrentLocation, FVector TargetLocation,FRotator CameraRotation, FVector LagSpeeds,float DeltaTime)
{CameraRotation.Roll = 0.0f;CameraRotation.Pitch = 0.0f;const FVector UnrotatedCurLoc = CameraRotation.UnrotateVector(CurrentLocation);const FVector UnrotatedTargetLoc = CameraRotation.UnrotateVector(TargetLocation);const FVector ResultVector(FMath::FInterpTo(UnrotatedCurLoc.X, UnrotatedTargetLoc.X, DeltaTime, LagSpeeds.X),FMath::FInterpTo(UnrotatedCurLoc.Y, UnrotatedTargetLoc.Y, DeltaTime, LagSpeeds.Y),FMath::FInterpTo(UnrotatedCurLoc.Z, UnrotatedTargetLoc.Z, DeltaTime, LagSpeeds.Z));return CameraRotation.RotateVector(ResultVector);
}
dir_rot.RotateVector(ue.Vector(-150, 30, 20))
// Rotator.h
CORE_API TVector<T> RotateVector( const UE::Math::TVector<T>& V ) const;
// UnrealMath.cpp
template<typename T>
UE::Math::TVector<T> UE::Math::TRotator<T>::UnrotateVector(const UE::Math::TVector<T>& V) const
{return UE::Math::TRotationMatrix<T>(*this).GetTransposed().TransformVector( V );
}	template<typename T>
UE::Math::TVector<T> UE::Math::TRotator<T>::RotateVector(const UE::Math::TVector<T>& V) const
{return UE::Math::TRotationMatrix<T>(*this).TransformVector( V );
}	// Quat.h
template<typename T>
FORCEINLINE TVector<T> TQuat<T>::RotateVector(TVector<T> V) const
{	// http://people.csail.mit.edu/bkph/articles/Quaternions.pdf// V' = V + 2w(Q x V) + (2Q x (Q x V))// refactor:// V' = V + w(2(Q x V)) + (Q x (2(Q x V)))// T = 2(Q x V);// V' = V + w*(T) + (Q x T)const TVector<T> Q(X, Y, Z);const TVector<T> TT = 2.f * TVector<T>::CrossProduct(Q, V);const TVector<T> Result = V + (W * TT) + TVector<T>::CrossProduct(Q, TT);return Result;
}template<typename T>
FORCEINLINE TVector<T> TQuat<T>::UnrotateVector(TVector<T> V) const
{	const TVector<T> Q(-X, -Y, -Z); // Inverseconst TVector<T> TT = 2.f * TVector<T>::CrossProduct(Q, V);const TVector<T> Result = V + (W * TT) + TVector<T>::CrossProduct(Q, TT);return Result;
}

插值相关

旋转插值Math.RInterpTo

// UnrealMath.cpp
// 注意,插值速度小于等于0时,直接返回的是Target
在这里插入图片描述

标量插值Math.FInterpTo

// 注意,插值速度小于等于0时,直接返回的是Target

// UnrealMathUtility.h/** Interpolate float from Current to Target. Scaled by distance to Target, so it has a strong start speed and ease out. */template<typename T1, typename T2 = T1, typename T3 = T2, typename T4 = T3>UE_NODISCARD static auto FInterpTo( T1  Current, T2 Target, T3 DeltaTime, T4 InterpSpeed ){using RetType = decltype(T1() * T2() * T3() * T4());// If no interp speed, jump to target valueif( InterpSpeed <= 0.f ){return static_cast<RetType>(Target);}// Distance to reachconst RetType Dist = Target - Current;// If distance is too small, just set the desired locationif( FMath::Square(Dist) < UE_SMALL_NUMBER ){return static_cast<RetType>(Target);}// Delta Move, Clamp so we do not over shoot.const RetType DeltaMove = Dist * FMath::Clamp<RetType>(DeltaTime * InterpSpeed, 0.f, 1.f);return Current + DeltaMove;				}

FMath::Lerp/FMath::FInterpConstantTo

TickComponent: 中TargetYaw = 90FRotator OpenDoor(0.f,TargetYaw,0.f);OpenDoor.Yaw = FMath::Lerp(CurrentYaw, TargetYaw,0.02f);// 插值的速度与帧率无关OpenDoor.Yaw = FMath::FInterpConstantTo(CurrentYaw, TargetYaw,DeltaTime,45);

FMath::Lerp线性插值的问题。OpenDoor.Yaw会一直接近90度,但是不会到达90度。同时电脑帧率快慢会影响OpenDoor.Yaw插值的速度

UKismetMathLibrary::Ease

UKismetMathLibrary::Ease
提供了多种内置的缓动插值方式

Debug相关

Unreal engine 4 C 一些调试用的绘制函数

// 头文件
#include "DrawDebugHelpers.h"// 几个示例
点:  DrawDebugPoint(GetWorld(), LocationOne, 200, FColor(52,220,239), true, 999);
球体:DrawDebugSphere(GetWorld(), LocationTwo, 200, 26, FColor(181,0,0), true, 999, 0, 2);
圆:  DrawDebugCircle(GetWorld(), CircleMatrix, 200, 50, FColor(0,104,167), true, 999, 0, 10);DrawDebugCircle(GetWorld(), LocationFour, 200, 50, FColor(0,0,0), true, 999, 0, 10);DrawDebugSolidBox(GetWorld(), MyBox, FColor(20, 100, 240), MyTransform, true, 999);
盒:  DrawDebugBox(GetWorld(), LocationFive, FVector(100,100,100), FColor::Purple, true, 999, 0, 10);
线:  DrawDebugLine(GetWorld(), LocationTwo, LocationThree, FColor::Emerald, true, 999, 0, 10);
方向箭头:DrawDebugDirectionalArrow(GetWorld(), FVector(-300, 600, 600), FVector(-300, -600, 600), 120.f, FColor::Magenta, true, 999, 0, 5.f);
交叉准星:DrawDebugCrosshairs(GetWorld(), FVector(0,0,1000), FRotator(0,0,0), 500.f, FColor::White, true, 999, 0);

KismetMathLibrary

KismetMathLibrary库为常用的数学使用库,包含了对向量、矩阵等数学变量的常规操作;

// 头文件
#include "Kismet/KismetMathLibrary.h"// 一些常用示例
KismetMathLibrary.ClampAxisKismetMathLibrary.FindLookAtRotation
KismetMathLibrary.Conv_VectorToRotator
KismetMathLibrary.MakeRotFromZX
KismetMathLibrary.MakeRotFromZY
KismetMathLibrary.MakeRotFromZXKismetMathLibrary.DegAcos
KismetMathLibrary.DegreesToRadians
KismetMathLibrary.FMod

GameplayStatics

UGameplayStatics类实用分析

GameplayStatics库为常用的Gameplay操作库,包含Gameplay操作的各类静态函数

// 头文件
#include "Kismet/GameplayStatics.h"

Python的Math

atan2和atan

python中 math模块下 atan 和 atan2的区别
在这里插入图片描述

atan2(y, x) 返回射线从原点到点 (x, y) 与正 x 轴之间的角度 θ,限制为 (−π, π]。

在这里插入图片描述

在这里插入图片描述
从 −π 到 +π 的切函数图,带有相应的 y/x 符号。绿色箭头指向 atan2(−1, −1) 和 atan2(1, 1) 的结果。

如果 x > 0,则所需的角度测量值为 atan2(y, x)=arctan(y/x),但是,当 x < 0 时,角度与所需角度 arctan(y/x)截然相反,并且必须添加±π(半圈)才能将点放置在正确的象限中。 [1] 使用该 atan2 函数可以消除这种更正,简化代码和数学公式

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/132893.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

特斯拉的困境:增长与竞争

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 总结&#xff1a; 虽然特斯拉(TSLA)股票仍有很大的上涨潜力;但从全球电动汽车市场的最新发展来看&#xff0c;特斯拉在“电动汽车统治”的道路上仍然面临着很多挑战。 在本文中&#xff0c;猛兽财经将分析我们对特斯拉&…

C语言——字符函数和字符串函数_学习笔记

本文目录 一、字符函数1.1 字符分类函数常见的字符分类函数介绍应用举例 1.2 字符转换函数函数介绍toupper 函数举例 二、字符串函数2.1 常用的字符串函数介绍2.2 应用举例① strlen② strcpy③ strcat④ strcmp⑤ strncpy⑥ strncat⑦ strncmp⑧ strstr⑨ strtok 关于一些字符…

2023Web前端面试题及答案(一)

答案仅供参考&#xff0c;每人的理解不一样。 文章目录 1、简单说一说事件流原理 事件流: &#xff08;1&#xff09;事件流是指页面 接收事件的顺序; &#xff08;2&#xff09;假设页面中的元素都具备相同的事件,并且这些个元素之间是相互嵌套的 关系. &#xff08;3&#xf…

Postman使用_接口导入导出

文章目录 Postman导入数据Collections导出数据Environments导出数据Postman导出所有数据 Postman导入数据 可以导入collections&#xff08;接口集&#xff09;、Environments&#xff08;环境配置&#xff09;通过分享的链接或导出的JSON文件导入数据&#xff08;还可以从第三…

视频监控/安防监控/AI视频分析/边缘计算/TSINGSEE青犀AI算法智慧仓储解决方案

随着全球经济与科学技术的双重推动&#xff0c;我国的仓储管理已经进入了高速发展时期&#xff0c;物流仓储也由简单的储藏仓库向智能化仓储转变。TSINGSEE青犀AI智慧仓储解决方案是利用先进的信息技术和物联网技术来提高仓储管理效率、降低成本的一种仓储管理模式。 方案功能 …

家政服务预约小程序,推拿spa上门预约系统

家政服务预约小程序&#xff0c;用户直接发布需求下单&#xff0c;师傅入驻抢单派单&#xff0c;多商家入驻&#xff0c;上门预约服务流程清晰&#xff0c;适合家政公司或需要预约场景的团队公司使用&#xff0c;支持多种行业上门预约服务场景&#xff1a;家政保洁维修上门服务…

代码随想录--链表-反转链表

题意&#xff1a;反转一个单链表。 示例: 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL 双指针 public class Main {public static class ListNode {int val;ListNode next;ListNode(int x) {val x;}}public ListNode reverseList(L…

Docker从认识到实践再到底层原理(五)|Docker镜像

前言 那么这里博主先安利一些干货满满的专栏了&#xff01; 首先是博主的高质量博客的汇总&#xff0c;这个专栏里面的博客&#xff0c;都是博主最最用心写的一部分&#xff0c;干货满满&#xff0c;希望对大家有帮助。 高质量博客汇总 然后就是博主最近最花时间的一个专栏…

VisualStudio Code 支持C++11插件配置

问题 Visual Studio Code中的插件: Code Runner 支持运行C、C、Java、JS、PHP、Python等多种语言。 但是它不支持C11特性的一些使用&#xff0c;比如类似错误&#xff1a; binarySearch.cpp:26:17: error: non-aggregate type ‘vector’ cannot be initialized with an ini…

Qt For OpenHarmony

本文转载自 OpenHarmony TSC 官方微信公众号《峰会回顾第29期 | Qt For OpenHarmony 》 演讲嘉宾 | 蔡万苍 回顾整理 | 廖 涛 排版校对 | 李萍萍 嘉宾简介 蔡万苍&#xff0c;13 年 C/Qt 开发相关工作经验&#xff0c;曾任职 Qt 公司&#xff0c;担任技术支持、Qt 咨询师…

windows系统docker中将vue项目网站部署在nginx上

一、首先在windows系统上下载并安装docker&#xff0c;要下载windows版本 https://www.docker.com/products/docker-desktop/ PS&#xff1a;安装过程中需要WSL&#xff0c;我的是win11系统&#xff0c;直接提示了我安装就可以下一步了。其他windows系统版本我不知道是否需要单…

C++下标运算符详解

C++ 规定,下标运算符[ ]必须以成员函数的形式进行重载。该重载函数在类中的声明格式如下: 返回值类型 & operator[ ] (参数); const 返回值类型 & operator[ ] (参数) const; 使用第一种声明方式,[ ]不仅可以访问元素,还可以修改元素。使用第二种声明方式,[ ]只…

postgresql-通用表达式

postgresql-通用表达式 入门案例简单CTE递归 CTE案例1案例2 入门案例 -- 通用表达式 with t(n) as (select 2) select * from t;简单CTE WITH cte_name (col1, col2, ...) AS (cte_query_definition ) sql_statement;WITH 表示定义 CTE&#xff0c;因此 CTE 也称为 WITH 查询…

河北省图书馆典藏《乡村振兴振兴战略下传统村落文化旅游设计》许少辉八一新著

河北省图书馆典藏《乡村振兴振兴战略下传统村落文化旅游设计》许少辉八一新著

Nginx(动静分离、分配缓冲区、资源缓存、防盗链、资源压缩、IP黑白名单、大文件传输配置、跨域配置、高可用、性能优化)

Nginx&#xff0c;负载均衡&#xff0c;Http反向代理服务器&#xff0c;支持大部分协议&#xff0c;如TCP、UDP、SMTP、HTTPS 环境搭建 Nginx反向代理-负载均衡 首先通过SpringBootFreemarker快速搭建一个WEB项目&#xff1a;springboot-web-nginx&#xff0c;然后在该项目中&…

FastJSON将对象转JSON字符串引发的血案

问题&#xff1a;最近工作中需要将一个将近两百页的pdf的base64作为value转成JSON字符串&#xff0c;而代码中使用的方案就是JSONObject.toJSONString(obj); 而结果就是引发了OOM内存溢出。 翻阅源码找到一段关键点&#xff1a; 也就是说FastJSON内部设置了一个阈值&#xff…

C++模版基础

代码地址 gitgithub.com:CHENLitterWhite/CPPWheel.git 专栏介绍 本专栏会持续更新关于STL中的一些概念&#xff0c;会先带大家补充一些基本的概念&#xff0c;再慢慢去阅读STL源码中的需要用到的一些思想&#xff0c;有了一些基础之后&#xff0c;再手写一些STL代码。 (如果你…

深入了解MySQL中的JSON_ARRAYAGG和JSON_OBJECT函数

在MySQL数据库中&#xff0c;JSON格式的数据处理已经变得越来越常见。JSON&#xff08;JavaScript Object Notation&#xff09;是一种轻量级的数据交换格式&#xff0c;它可以用来存储和表示结构化的数据。MySQL提供了一些功能强大的JSON函数&#xff0c;其中两个关键的函数是…

奶牛个体识别 奶牛身份识别

融合YOLOv5s与通道剪枝算法的奶牛轻量化个体识别方法 Light-weight recognition network for dairy cows based on the fusion of YOLOv5s and channel pruning algorithm 论文链接 知网链接 DOI链接 该文章讨论了奶牛花斑、光照条件、不同剪枝方法、不同剪枝率对准确率的影响…

类和对象(3)

文章目录 1.回顾上节2. 拷贝构造3. 运算符重载&#xff08;非常重要&#xff09;4. 赋值运算符重载 1.回顾上节 默认成员函数&#xff1a;我们不写&#xff0c;编译器自动生成。我们不写&#xff0c;编译器不会自动生成 默认生成构造和析构&#xff1a; 对于内置类型不做处理对…