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++

#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;
}