You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
457 lines
9.1 KiB
C++
457 lines
9.1 KiB
C++
#include "MLFuncom.h"
|
|
#include "MLVector.h"
|
|
|
|
MLFuncom::MLFuncom()
|
|
{
|
|
}
|
|
|
|
|
|
MLFuncom::~MLFuncom()
|
|
{
|
|
}
|
|
|
|
void swap(double& a, double& b)
|
|
{
|
|
double tmp;
|
|
tmp = a;
|
|
a = b;
|
|
b = tmp;
|
|
}
|
|
|
|
|
|
//判断两个浮点数据是否相等
|
|
bool Equ(double dVal1, double dVal2)
|
|
{
|
|
if (abs(dVal2 - dVal1) < DOUBLE_ERROR)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
bool Equ(double dVal1, double dVal2, int dot)
|
|
{
|
|
if (dot == 0)
|
|
{
|
|
return Equ(dVal1, dVal2);
|
|
}
|
|
|
|
double error = 1.0;
|
|
for (int i = 0; i < dot; i++)
|
|
{
|
|
error *= 0.1;
|
|
}
|
|
|
|
if (fabs(dVal1 - dVal2) <= error)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
double GetDistance(const MLPlNode& dpt1, const MLPlNode& dpt2)
|
|
{
|
|
double dxa = dpt2.x - dpt1.x;
|
|
double dya = dpt2.y - dpt1.y;
|
|
return sqrt(dxa * dxa + dya * dya);
|
|
}
|
|
|
|
double GetDistance(double dx1, double dy1, double dx2, double dy2)
|
|
{
|
|
return sqrt(pow(dx2 - dx1, 2) + pow(dy2 - dy1, 2));
|
|
}
|
|
|
|
|
|
double GetDistance(const MLPlNode& dpt, const MLPlNode& dpt1, const MLPlNode& dpt2, MLPlNode& dptDest)
|
|
{
|
|
MLPoint ptDest;
|
|
double dis = GetDistance(dpt.toPoint(), dpt1.toPoint(), dpt2.toPoint(), ptDest);
|
|
dptDest = ptDest.toPlNode();
|
|
return dis;
|
|
}
|
|
|
|
double GetDistance(const MLPoint& dpt, const MLPoint& dpt1, const MLPoint& dpt2, MLPoint& dptDest)
|
|
{
|
|
if (Equ(dpt1.x, dpt2.x) && Equ(dpt1.y, dpt2.y))
|
|
{
|
|
dptDest.x = (dpt1.x + dpt2.x) / 2.0;
|
|
dptDest.y = (dpt1.y + dpt2.y) / 2.0;
|
|
}
|
|
else if (Equ(dpt1.x, dpt2.x))
|
|
{
|
|
dptDest.x = (dpt1.x + dpt2.x) / 2.0;
|
|
dptDest.y = dpt.y;
|
|
}
|
|
else if (Equ(dpt1.y, dpt2.y))
|
|
{
|
|
dptDest.x = dpt.x;
|
|
dptDest.y = (dpt1.y + dpt2.y) / 2.0;
|
|
}
|
|
else
|
|
{
|
|
double slope1 = (dpt2.y - dpt1.y) / (dpt2.x - dpt1.x);
|
|
double slope2 = -1.0 / slope1; // 垂线斜率等于直线斜率的负倒数
|
|
dptDest.x = (dpt.y - dpt1.y + slope1 * dpt1.x - slope2 * dpt.x) / (slope1 - slope2);
|
|
dptDest.y = slope1 * (dptDest.x - dpt1.x) + dpt1.y;
|
|
}
|
|
|
|
if (abs(dpt2.x - dpt1.x) > abs(dpt2.y - dpt1.y))
|
|
{
|
|
if (dpt1.x > dpt2.x)
|
|
{
|
|
if (dptDest.x < dpt2.x)
|
|
dptDest = dpt2;
|
|
else if (dptDest.x > dpt1.x)
|
|
dptDest = dpt1;
|
|
}
|
|
else
|
|
{
|
|
if (dptDest.x < dpt1.x)
|
|
dptDest = dpt1;
|
|
else if (dptDest.x > dpt2.x)
|
|
dptDest = dpt2;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (dpt1.y > dpt2.y)
|
|
{
|
|
if (dptDest.y < dpt2.y)
|
|
dptDest = dpt2;
|
|
else if (dptDest.y > dpt1.y)
|
|
dptDest = dpt1;
|
|
}
|
|
else
|
|
{
|
|
if (dptDest.y < dpt1.y)
|
|
dptDest = dpt1;
|
|
else if (dptDest.y > dpt2.y)
|
|
dptDest = dpt2;
|
|
}
|
|
}
|
|
return GetDistance(dpt, dptDest);
|
|
}
|
|
|
|
int LineLine(double L1x1, double L1y1, double L1x2, double L1y2, double* L2x1, double* L2y1, double* L2x2, double* L2y2, bool bExtend1 /*= false*/)
|
|
{
|
|
/*
|
|
0 两条直线段不相交
|
|
1 两条直线段有一个交点,交点坐标通过(*L2x1,*L2y1)返回
|
|
2 两第直线段部分后重合,重合段的起终坐标分别通过(*L2x1,*L2y1)和(*L2x2,*L2y2)返回
|
|
*/
|
|
|
|
double xx1, xx2, yy1, yy2;
|
|
double x1, x2, y1, y2, n1, n2, n3, n4;
|
|
double k1, k2;
|
|
|
|
double oldx = *L2x1;
|
|
double oldy = *L2y1;
|
|
|
|
//以下第一条直线段的两个顶点按横越坐标由小到大放置在点(xx1,yy1)和(xx2,yy2)中
|
|
if (L1x1 > L1x2)
|
|
{
|
|
xx1 = L1x2;
|
|
xx2 = L1x1;
|
|
yy1 = L1y2;
|
|
yy2 = L1y1;
|
|
}
|
|
else
|
|
{
|
|
xx1 = L1x1;
|
|
xx2 = L1x2;
|
|
yy1 = L1y1;
|
|
yy2 = L1y2;
|
|
}
|
|
|
|
if (fabs(xx1 - xx2) <= 0. && fabs(yy1 - yy2) < 0.) //如果第一直线段两个顶相同,函数返回0 (不相交)
|
|
return 0;
|
|
|
|
//以下第二第直线段的两个顶点按横坐标由小到大放置在点(x1,y1)和(x2,y2)中
|
|
if (*L2x1 > *L2x2)
|
|
{
|
|
x1 = *L2x2;
|
|
x2 = *L2x1;
|
|
y1 = *L2y2;
|
|
y2 = *L2y1;
|
|
}
|
|
else
|
|
{
|
|
x1 = *L2x1;
|
|
x2 = *L2x2;
|
|
y1 = *L2y1;
|
|
y2 = *L2y2;
|
|
}
|
|
|
|
if (fabs(x1 - x2) <= 0. && fabs(y1 - y2) < 0.) //如果第二直线段两个顶相同,函数返回0 (不相交)
|
|
return 0;
|
|
|
|
if (fabs(x1 - x2) <= 0. && fabs(xx1 - xx2) <= 0.)//如果两条直线都是坚直线
|
|
{
|
|
if (x1 != xx1) // 两个平行坚直线的横坐标不同,两条直线不相交
|
|
return 0;
|
|
|
|
*L2x1 = x1; //得到交点的横坐标
|
|
n1 = MIN(yy1, yy2); //第一条直线段的最小纵坐标
|
|
n2 = MAX(yy1, yy2); //第一条直线段的最大纵坐标
|
|
n3 = MIN(y1, y2); //第二条直线段的最小纵坐标
|
|
n4 = MAX(y1, y2); //第二条直线段的最大纵坐标
|
|
|
|
if (n1 > n4 || n2 < n3) //如果两条横坐标相同的坚直线纵坐标没有交叉,两条直线不相交
|
|
return 0;
|
|
|
|
else if (n1 == n4 || n2 == n3) //如果两条横坐标相同的坚直线纵坐标有一点相交(连续)
|
|
{
|
|
if (n1 == n4) //如果第一条直线的开如点与第二条直线的终点相同
|
|
{
|
|
*L2y1 = n1;
|
|
return 1;
|
|
}
|
|
if (n2 == n3) //如果第一条直线的终点与第二条直线的起点相同
|
|
{
|
|
*L2y1 = n2;
|
|
return 1;
|
|
}
|
|
}
|
|
else //如果两条直线的纵坐标重叠
|
|
{
|
|
*L2x2 = x1;
|
|
|
|
*L2y1 = MAX(n1, n3); //重叠直线段的起点坐标
|
|
*L2y2 = MIN(n2, n4); //重叠直线段的终点坐标
|
|
return 2;
|
|
}
|
|
}
|
|
else if (fabs(x1 - x2) <= 0. && xx1 != xx2) //如果第一条直线是斜线,第二条直线是坚直线
|
|
{
|
|
*L2x1 = x1; //得到交点的横坐标
|
|
|
|
//if (!(x1 >= xx1 && x1 <= xx2) || !bExtend1) //如果交点横坐标没有在第一条直线段的横坐标范围内,相不交
|
|
// return 0;
|
|
if (!(x1 >= xx1 && x1 <= xx2) || &bExtend1) //如果交点横坐标没有在第一条直线段的横坐标范围内,相不交
|
|
return 0;
|
|
|
|
*L2y1 = yy1 + (x1 - xx1) / (xx2 - xx1)*(yy2 - yy1);//计算得到交点的纵坐标
|
|
|
|
if ((*L2y1 >= y1 && *L2y1 <= y2 || *L2y1 >= y2 && *L2y1 <= y1))//交点纵坐标在第二条直线段坐标范围内
|
|
return 1;
|
|
else
|
|
{
|
|
// 要恢复一下,因为下一个函数有可能要用到
|
|
*L2x1 = oldx;
|
|
*L2y1 = oldy;
|
|
return 0;
|
|
}
|
|
|
|
}
|
|
else if ((x1 != x2) && fabs(xx1 - xx2) <= 0.)
|
|
{
|
|
*L2x1 = xx1;
|
|
if (!(xx1 >= x1 && xx1 <= x2)) //如果交点横坐标没有在第二条直线段的横坐标范围内,相不交
|
|
return 0;
|
|
|
|
*L2y1 = y1 + (xx1 - x1) / (x2 - x1)*(y2 - y1);//计算得到交点的纵坐标
|
|
|
|
if (bExtend1)
|
|
{
|
|
return 1;
|
|
}
|
|
if ((*L2y1 >= yy1 && *L2y1 <= yy2 || *L2y1 >= yy2 && *L2y1 <= yy1))//交点纵坐标在第一条直线段坐标范围内
|
|
return 1;
|
|
else
|
|
{
|
|
// 要恢复一下,因为下一个函数有可能要用到
|
|
*L2x1 = oldx;
|
|
*L2y1 = oldy;
|
|
return 0;
|
|
}
|
|
|
|
}
|
|
else //如果两条都是斜线
|
|
{
|
|
//得到两条直线的斜率
|
|
k1 = (y2 - y1) / (x2 - x1);
|
|
k2 = (yy2 - yy1) / (xx2 - xx1);
|
|
if (k1 == k2) //如果两条直线平行
|
|
{
|
|
if (x1 > xx2 || x2 < xx1) //两条直线横坐标不重叠
|
|
return 0;
|
|
else
|
|
{
|
|
//以下分别得到同一横坐标x1下,在两条直线上的纵坐标
|
|
n1 = y1 + (0 - x1)*k1;
|
|
n2 = yy1 + (0 - x1)*k2;
|
|
if (n1 != n2)
|
|
return 0;
|
|
else
|
|
{
|
|
n3 = MAX(xx1, x1);
|
|
n4 = MIN(xx2, x2);
|
|
*L2x1 = n3;
|
|
*L2y1 = y1 + (n3 - x1)*k1;
|
|
if (n3 == n4)
|
|
return 1;
|
|
else
|
|
{
|
|
*L2x2 = n4;
|
|
*L2y2 = y1 + (n4 - x1)*k1;
|
|
return 2;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else ////如果两条直线不平行
|
|
{
|
|
*L2x1 = (yy1 - y1 + x1 * k1 - xx1 * k2) / (k1 - k2); //交点横坐标
|
|
*L2y1 = y1 + (*L2x1 - x1)*k1; //交点纵坐标
|
|
|
|
if (bExtend1)//如果第一直线段允许延长 交点横坐标在第二直线段内
|
|
{
|
|
if (*L2x1 >= x1 && *L2x1 <= x2)
|
|
return 1;
|
|
}
|
|
|
|
//如果交点横坐标在两条直线段的横坐标范围内
|
|
if ((*L2x1 >= x1 && *L2x1 <= x2) && (*L2x1 >= xx1 && *L2x1 <= xx2))
|
|
return 1;
|
|
else
|
|
{
|
|
// 要恢复一下,因为下一个函数有可能要用到
|
|
*L2x1 = oldx;
|
|
*L2y1 = oldy;
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
bool ptInRect(const MLRect& Rect, double dbx, double dby)
|
|
{
|
|
if (dbx > Rect.left&& dbx <Rect.right && dby > Rect.bottom && dby < Rect.top)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
//查找
|
|
int bs(double dbKey, MLPline& pline, int nKey/*=3*/)
|
|
{
|
|
int num = pline.getCount();
|
|
int i1, i2, i;
|
|
i1 = 0; i2 = num - 1;
|
|
|
|
if (nKey == 3)
|
|
{
|
|
if (pline.getTailPt().l >= pline.getHeadPt().l)
|
|
{
|
|
if (dbKey > pline.getTailPt().l)return num + 100;
|
|
if (dbKey < pline.getHeadPt().l)return -100;
|
|
}
|
|
else if (pline.getTailPt().l < pline.getHeadPt().l)
|
|
{
|
|
if (dbKey < pline.getTailPt().l)return num + 100;
|
|
if (dbKey > pline.getHeadPt().l)return -100;
|
|
}
|
|
if (fabs(dbKey - pline.getHeadPt().l) < 1e-10)return 0;
|
|
if (fabs(dbKey - pline.getTailPt().l) < 1e-10)return i2 - 1;
|
|
|
|
while (i2 - i1 > 1)
|
|
{
|
|
i = (i1 + i2) / 2;
|
|
if ((dbKey - pline[i].l)*(dbKey - pline[i2].l) > 1e-10)
|
|
i2 = i;
|
|
else
|
|
i1 = i;
|
|
}
|
|
}
|
|
return i1;
|
|
}
|
|
|
|
double CZ(double x0, double x1, double x2, double y1, double y2)
|
|
{
|
|
double s;
|
|
s = x2 - x1;
|
|
if (fabs(s) < 1e-30)
|
|
return y1;
|
|
|
|
s = y1 + (y2 - y1) / s * (x0 - x1);
|
|
|
|
return s;
|
|
}
|
|
|
|
double cz(double dbKey, int nIndex, MLPline& pline, int nKey1, int nKey2)
|
|
{
|
|
double dbVable1 = 0.0, dbVable2 = 0.0;
|
|
double dbKey1 = 0.0, dbKey2 = 0.0;
|
|
|
|
int nKey = nIndex;
|
|
|
|
if (nKey1 == 3)
|
|
{
|
|
dbKey1 = pline[nKey].l;
|
|
dbKey2 = pline[nKey + 1].l;
|
|
}
|
|
/*if(nKey1 ==4)
|
|
{
|
|
dbKey1 = pline[nKey].s;
|
|
dbKey2 = pline[nKey+1].s;
|
|
}*/
|
|
|
|
if (nKey2 == 0)
|
|
{
|
|
dbVable1 = pline[nKey].x;
|
|
dbVable2 = pline[nKey + 1].x;
|
|
}
|
|
if (nKey2 == 1)
|
|
{
|
|
dbVable1 = pline[nKey].y;
|
|
dbVable2 = pline[nKey + 1].y;
|
|
}
|
|
|
|
return CZ(dbKey, dbKey1, dbKey2, dbVable1, dbVable2);
|
|
}
|
|
|
|
|
|
// 判断两矩形之间关系
|
|
bool CrossRtRt(const MLRect& rect1, const MLRect& rect2)
|
|
{
|
|
int nx1, ny1, nx2, ny2;
|
|
int nx3, ny3, nx4, ny4;
|
|
|
|
nx1 = rect1.left;
|
|
ny1 = rect1.top;
|
|
nx2 = rect1.right;
|
|
ny2 = rect1.bottom;
|
|
|
|
nx3 = rect2.left;
|
|
ny3 = rect2.top;
|
|
nx4 = rect2.right;
|
|
ny4 = rect2.bottom;
|
|
|
|
int m = (nx1 > nx4) | (nx2 < nx3);
|
|
int n = (ny2 > ny3) | (ny1 < ny4);
|
|
|
|
if (m | n)
|
|
return false; //不相交
|
|
else
|
|
return true; //相交
|
|
|
|
//return false;
|
|
}
|
|
|
|
QString ToString(int nVal)
|
|
{
|
|
QString strVal = QString("%1").arg(nVal);
|
|
return strVal;
|
|
}
|
|
|
|
QString ToString(double dVal)
|
|
{
|
|
QString strVal = QString("%1").arg(dVal);
|
|
return strVal;
|
|
}
|
|
|
|
QString ToString(double dVal, int nDotNum)
|
|
{
|
|
QString strVal = QString("%1").arg(dVal, 0, 'f', nDotNum);
|
|
return strVal;
|
|
}
|