lisp最小外接矩形算法_C++/Qt:最小外接矩形|二次开发objectarx-lisp|中国膜结构网|PVDF|ETFE|PTFE|进口膜材|国产膜材|膜材价格 - 中国最专业的膜结构论坛...

该博客介绍了如何使用C++/Qt实现基于LISP的最小外接矩形算法。首先,通过求凸包来获取关键点,然后利用平面几何计算点与点、点与线的距离。接着,通过遍历凸包上的边,判断是水平、垂直还是斜线情况,计算出最小外接矩形的长和宽。最后,给出了求解最小外接矩形的详细步骤及代码实现。
摘要由CSDN通过智能技术生成

一、求凸包,返回 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);

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值