本文思路:在凸多边形的基础上将凹多边形用向量延长线法分割成多个凸多边形,然后按照凸多边形的算法计算。凸多边形比较简单,就不介绍记录了。
几个凹多边形算法的思路:
static TArray> t_polygonDividedArr;
/*从多边形的有序的点数组获取顶点和三角面数据信息(凹凸多边形)
参数1: 顶点数组
参数2: 是否是逆时针
*/
static void GetPolygonDataFromOrderVertexs(TArray _points,bool _antiClockwise=true);
void ULcq_BlueprintFunctionLibrary::GetPolygonDataFromOrderVertexs(TArray _points, bool _antiClockwise)
{
TArray t_res;
int t_pointsNum = _points.Num();
if (t_pointsNum>3)
{
t_polygonDividedArr.Empty();
DividePolygonIfConcave(_points, _antiClockwise); //递归
if (t_polygonDividedArr.Num()>0)
{
UE_LOG(LogTemp, Warning, TEXT("多边形分割成了%d 个多边形"), t_res.Num());
}
}
else
UE_LOG(LogTemp, Error, TEXT("多边形分割失败"));
}
//分割
/*检查多边形是否是凹多边形,如果是就切割
参数1:点集
参数2:需要返回的被切割多边形1
参数2:需要返回的被切割多边形2
*/
static void DividePolygonIfConcave(TArray _points, bool _antiClockwise = true);
void ULcq_BlueprintFunctionLibrary::DividePolygonIfConcave(TArray _points, bool _antiClockwise)
{
int t_pointsNum = _points.Num();
if (_points.Num()<3)
{
return;
}
if (t_pointsNum==3)
{
t_polygonDividedArr.Add(_points);
return;
}
if (t_pointsNum>3)
{
TArray _dividePolygonA;
TArray _dividePolygonB;
float t_hei = _points[0].Z;
SetPointsZvalueBySpecify(_points,0);
FVector t_p1;
FVector t_p2;
TArray t_dirs=GetVectorArrByPointsArr(_points);
bool t_divideResult=false;
int t_indexNew=0;
for (int i=0;i0.01f&& _antiClockwise == false)
{
//UE_LOG(LogTemp, Warning, TEXT("t_rotateDir: %f"), t_rotateDir);
UE_LOG(LogTemp, Warning, TEXT("是凹多边形~~~~~~~~~~~"));
//求分割点
t_divideResult = GetRayIntersectionOfVecInVecArr(t_dirs, _points, i, i, t_pointsNum - 1, _dividePolygonA, _dividePolygonB);
if (t_divideResult == false)
{
t_divideResult = GetRayIntersectionOfVecInVecArr(t_dirs, _points, i, 0, i - 1, _dividePolygonA, _dividePolygonB);
}
if (t_divideResult == false)
{
UE_LOG(LogTemp, Error, TEXT("线段%d 没有得到分割点"), i);
}
break;
}
}
if (t_divideResult ==false)
{
SetPointsZvalueBySpecify(_points, t_hei);
t_polygonDividedArr.Add(_points);
}
else
{
if (_dividePolygonA.Num()>2)
{
SetPointsZvalueBySpecify(_dividePolygonA, t_hei);
DividePolygonIfConcave(_dividePolygonA, _antiClockwise);
}
if (_dividePolygonB.Num()>2)
{
SetPointsZvalueBySpecify(_dividePolygonB, t_hei);
DividePolygonIfConcave(_dividePolygonB, _antiClockwise);
}
}
}
}
/*给定点数组的Z值统一化
*/
static bool SetPointsZvalueBySpecify(TArray &_points, float _zValue);
bool ULcq_BlueprintFunctionLibrary::SetPointsZvalueBySpecify(TArray &_points, float _zValue)
{
if (_points.Num()>0)
{
for (int i=0;i<_points.Num();i++)
{
_points[i].Z = _zValue;
}
return true;
}
return false;
}
/*根据点数组获取向量数组
*/
static TArray GetVectorArrByPointsArr(const TArray _points);
TArray ULcq_BlueprintFunctionLibrary::GetVectorArrByPointsArr(const TArray _points)
{
TArray t_res;
int t_pointsNum = _points.Num();
if (t_pointsNum>1)
{
FVector t_p1;
FVector t_p2;
for (int i = 0; i < _points.Num(); i++)
{
t_p1 = _points[i];
if (i == t_pointsNum - 1)
{
t_p2 = _points[0];
}
else
{
t_p2 = _points[i + 1];
}
t_res.Add(t_p2 - t_p1);
}
}
return t_res;
}
/*从向量数组中获取一个向量在这个数组中的延长线与其他向量的交点
注意:顺序必须先从这个向量的下标开始,不能是0;交点不包括向量端点
参数1:方向向量数组
参数2:对应的点数组(长度需保持一致)
参数3:这个向量的下标
参数4,5:开始和结束下标
参数6,7: 根据交点被切分的两组点数组
返回值:true 为成功,反之无
*/
static bool GetRayIntersectionOfVecInVecArr(const TArray _dirs, const TArray _points, const int _vecIndex, const int _beginIndex, const int _endIndex,
TArray &_dividePolygonA, TArray &_dividePolygonB);
bool ULcq_BlueprintFunctionLibrary::GetRayIntersectionOfVecInVecArr(const TArray _dirs, const TArray _points, const int _vecIndex,const int _beginIndex,const int _endIndex,
TArray &_dividePolygonA,TArray &_dividePolygonB)
{
int t_dirsNum=_dirs.Num();
int t_pointsNum = _points.Num();
if (t_dirsNum>3&&t_pointsNum>3)
{
if (t_dirsNum==t_pointsNum)
{
if (_beginIndex>=0&&_beginIndex=0&&_endIndex 0)
{
_dividePolygonB[0] = t_intersectionPoint;
}
UE_LOG(LogTemp, Warning, TEXT("_dividePolygonB向量数组个数: %d"), _dividePolygonB.Num());
return true;
}
}
}
}
}
}
}
return false;
}