一、求凸包,返回 xjListCH
参考:凸包
二、MBR中用到的函数
//返回 点与点的平面距离
double TwoDistancePointAndPoint(const xjPoint &p1, const xjPoint &p2)
{
double x1 = p1.x, y1 = p1.y;
double x2 = p2.x, y2 = p2.y;
double dis = sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2));
return dis;
}
//返回 点(p0) 到线(p1,p2)的距离
double TwoDistancePointAndLine(const xjPoint &p0, const xjPoint &p1,const xjPoint &p2)
{
double dis12 = TwoDistancePointAndPoint(p1, p2);//线段长度
double dis01 = TwoDistancePointAndPoint(p0, p1);//p1与p0的距离
double dis02 = TwoDistancePointAndPoint(p0, p2);//p2与p0的距离
double HalfC = (dis12 + dis01 + dis02) / 2;// 半周长
double s = sqrt(HalfC * (HalfC - dis12) * (HalfC - dis01) * (HalfC - dis02));//海伦公式求面积
double xj2DisPL = 2 * s / dis12;// 返回点到线的距离(利用三角形面积公式求高)
return xj2DisPL;
}
三、最小外接矩形
/*返回 最小外接矩形点*/
/* xjListCH 凸包点 */
void xjMinimumBoundingRectangle(QList &xjListMBRpoint, double &length, double &width, QList xjListCH)
{
//外接矩形
QList xjListCH2;
int xjPcount = xjListCH.size();
for (int i = 0; i < xjPcount; i++)
{
xjListCH2.append(xjListCH.at(i));
}
qSort(xjListCH2.begin(), xjListCH2.end(), [](const xjPoint &a, const xjPoint &b) {return a.x < b.x; });
double minX = xjListCH2.at(0).x;
double maxX = xjListCH2.at(xjPcount - 1).x;
qSort(xjListCH2.begin(), xjListCH2.end(), [](const xjPoint &a, const xjPoint &b) {return a.y < b.y; });
double minY = xjListCH2.at(0).y;
double maxY = xjListCH2.at(xjPcount - 1).y;
//依次判断
double minArea = 99999999;
xjListCH.push_back(xjListCH.at(0));
for (int a = 0; a < xjListCH.size() - 1; a++)
{
xjPoint p0 = xjListCH.at(a);
xjPoint p1 = xjListCH.at(a + 1);
if ((p0.y == p1.y)|| (p0.x == p1.x)) // 水平或垂直
{
double side1 = maxY - minY;
double side0 = maxX - minX;
double xjArea = side0 * side1;
if (xjArea <= minArea)
{
length = max(side0, side1);
width = min(side0, side1);
minArea = xjArea;
//外接矩形四个点
xjPoint pLB;
pLB.x = minX;
pLB.y = minY;
pLB.z = 0;
xjPoint pRB;
pRB.x = maxX;
pRB.y = minY;
pRB.z = 0;
xjPoint pRT;
pRT.x = maxX;
pRT.y = maxY;
pRT.z = 0;
xjPoint pLT;
pLT.x = minX;
pLT.y = maxY;
pLT.z = 0;
xjListMBRpoint.clear();
xjListMBRpoint.append(pLB);
xjListMBRpoint.append(pRB);
xjListMBRpoint.append(pRT);
xjListMBRpoint.append(pLT);
}
}
else //不水平 不垂直
{
double k1 = (p1.y - p0.y) / (p1.x - p0.x);
double b1 = p0.y - k1 * p0.x;
double side0 = -3;
xjPoint Pside0;
for (int j = 0; j < xjListCH.size(); j++)
{
if ((j == a) || (j == (a + 1)))
continue;
xjPoint p = xjListCH.at(j);
double dis = abs(TwoDistancePointAndLine(p, p0, p1));
if (dis >= side0)
{
side0 = dis;
Pside0.x = p.x;
Pside0.y = p.y;
Pside0.z = p.z;
}
}
double b11 = Pside0.y - k1 * Pside0.x;
//垂直方向
double k2 = -1.0 / k1;
double bb = p0.y - k2 * p0.x;
double side1_positive = -3;
xjPoint Pside1_positive;
double side1_negative = 9999999;
xjPoint Pside1_negative;
for (int j = 0; j < xjListCH.size(); j++)
{
xjPoint p = xjListCH.at(j);
double dis = (k2*p.x - p.y + bb) / (sqrt(k2*k2 + 1));
if ((dis>=0)&&(dis >= side1_positive))
{
side1_positive = dis;
Pside1_positive.x = p.x;
Pside1_positive.y = p.y;
Pside1_positive.z = p.z;
}
if ((dis<0)&&(dis <= side1_negative))
{
side1_negative = dis;
Pside1_negative.x = p.x;
Pside1_negative.y = p.y;
Pside1_negative.z = p.z;
}
}
double b2 = Pside1_positive.y - k2 * Pside1_positive.x;
double b22 = Pside1_negative.y - k2 * Pside1_negative.x;
//面积和周长
double side1 = abs(side1_positive)+abs(side1_negative);
double xjArea = side0 * side1;
if (xjArea <= minArea)
{
length = max(side0, side1);
width = min(side0, side1);
minArea = xjArea;
//外接矩形四个点
xjPoint br0;
br0.x = (b1 - b22) / (k2 - k1);
br0.y = k1 * br0.x + b1;
xjPoint br1;
br1.x = (b11-b22) / (k2-k1);
br1.y = k1* br1.x + b11;
xjPoint br2;
br2.x = (b2-b11) / (k1-k2);
br2.y = k1* br2.x + b11;
xjPoint br3;
br3.x = (b2-b1) / (k1-k2);
br3.y = k1 * br3.x + b1;
xjListMBRpoint.clear();
xjListMBRpoint.append(br0);
xjListMBRpoint.append(br1);
xjListMBRpoint.append(br2);
xjListMBRpoint.append(br3);
}
}
}
//MBR提示信息
QString MBRinfo = "chMBR: length = " + QString::number(length, 'f', 4) + ", ";
MBRinfo += "width = " + QString::number(width, 'f', 4) + ", ";
MBRinfo += "minimum area = " + QString::number(minArea) + ", ";
MBRinfo += "circumference = " + QString::number((length + width) * 2);
}