📄 mathsubs.cpp
字号:
if (A==0) //水平线段,则过鼠标点的垂线为垂直线
{
x0 = pox;
y0 = p1y;
if (p1x < p2x)
{
if (pox<p1x || pox>p2x)
continue;
}
else
{
if (pox<p2x || pox>p1x)
continue;
}
ipos = j;
smin = (float)s;
issel = true;
}
else if (B==0)
{
x0 = p1x;
y0 = poy;
if (p1y < p2y)
{
if (poy<p1y || poy>p2y)
continue;
}
else
{
if (poy<p2y || poy>p1y)
continue;
}
ipos = j;
smin = (float)s;
issel = true;
}
else
{
//点斜式
xk = B/A;
A2 = xk;
B2 = -1;
C2 = poy - xk * pox;
if (A *B2-A2*B==0)
{
j=j;
}
x0 = - (C *B2-C2*B )/(A *B2-A2*B );
y0 = - (C2*A -C *A2)/(A *B2-A2*B );
if (p1x < p2x)
{
if (x0<p1x || x0>p2x)
continue;
}
else
{
if (x0<p2x || x0>p1x)
continue;
}
if (p1y < p2y)
{
if (y0<p1y || y0>p2y)
continue;
}
else
{
if (y0<p2y || y0>p1y)
continue;
}
ipos = j;
smin = (float)s;
issel = true;
} //end of dip-line
} //end for
return issel;
}
/*
分离的X,Y double浮点数组版本
*/
BOOL isVCrossAtLine(double pox, double poy, double psx[], double psy[],
int nps, double &smin, int &ipos,
double &x0, double &y0)
{
double p1x, p1y;
double p2x, p2y;
double A2,B2,C2;
double s;
double xk;
double A,B,C;
int issel = 0;
nps--;
for (int j=0; j<nps; j++)
{
p1x = psx[j];
p1y = psy[j];
p2x = psx[j+1];
p2y = psy[j+1];
A = p1y - p2y;
B = p2x - p1x;
if (A==0 && B==0)
{
if (pox == p1x && poy==p1y)
{
ipos = j;
smin = 0;
return true;
}
continue;
}
C = -p1x*A - p1y*B;
//点到直线的距离:
s = fabs(A*pox + B*poy +C)/sqrt( B*B+ A*A);
if (s>=smin ) continue;
if (A==0) //水平线段,则过鼠标点的垂线为垂直线
{
x0 = pox;
y0 = p1y;
if (p1x < p2x)
{
if (pox<p1x || pox>p2x)
continue;
}
else
{
if (pox<p2x || pox>p1x)
continue;
}
ipos = j;
smin = (float)s;
issel = true;
}
else if (B==0)
{
x0 = p1x;
y0 = poy;
if (p1y < p2y)
{
if (poy<p1y || poy>p2y)
continue;
}
else
{
if (poy<p2y || poy>p1y)
continue;
}
ipos = j;
smin = (float)s;
issel = true;
}
else
{
//点斜式
xk = B/A;
A2 = xk;
B2 = -1;
C2 = poy - xk * pox;
if (A *B2-A2*B==0)
{
j=j;
}
x0 = - (C *B2-C2*B )/(A *B2-A2*B );
y0 = - (C2*A -C *A2)/(A *B2-A2*B );
if (p1x < p2x)
{
if (x0<p1x || x0>p2x)
continue;
}
else
{
if (x0<p2x || x0>p1x)
continue;
}
if (p1y < p2y)
{
if (y0<p1y || y0>p2y)
continue;
}
else
{
if (y0<p2y || y0>p1y)
continue;
}
ipos = j;
smin = (float)s;
issel = true;
} //end of dip-line
} //end for
return issel;
}
BOOL isVCrossAtLine(CPoint po, CPoint ps[], int nps)
{
//int* smin ;
//smin = (int *)malloc(sizeof(int));
int smin = MIN_DISTANCE;
int ipos = 0;
//ipos = (int *)malloc(sizeof(int));
double x0 = 0.0;
//x0 = (double *)malloc(sizeof(double));
double y0 =0.0 ;
//y0 = (double *)malloc(sizeof(double));
return isVCrossAtLine(po,ps,nps,smin,ipos,x0,y0);
}
//如果返回0表是没有找到相应点,找到几个点就返回其数值 retPt[4]
//周围没有点,就手工加上四个点,好在后面画出一个圆出来
//如果一个方向的点与另一个方向的近点相同,就不要此近点,继续找次近点,这样以免出现直线的情况所有点位小于一个阀值
int FindRoundDot(CPoint *XYP, int N, int x, int y, CPoint *retPt)
{
UINT nMax = 99999999;
// UINT rs[4]={nMax,nMax,nMax,nMax};
UINT tmp;
UINT nRadius = nMax;
for (int i=0; i<N; i++)
{
// BOOL bOneDirection = FALSE;
if(XYP[i].x != x || XYP[i].y != y)
{
tmp = (int)sqrt((XYP[i].x - x)*(XYP[i].x -x) + (XYP[i].y - y)*(XYP[i].y - y));
nRadius = min(nRadius,tmp);
}
/*
if(XYP[i].x > x)
{//计算右方
if(tmp<rs[0])
{
// bOneDirection = TRUE;
retPt[0] = XYP[i];
rs[0] = tmp;
//retPt[0].y = XYP[i].y;
}
}
else if(XYP[i].x < x)
{//计算左方
if(tmp<rs[2])
{
// bOneDirection = TRUE;
retPt[2] = XYP[i];
rs[2] = tmp;
//retPt[1].y = XYP[i].y;
}
}
// if(!bOneDirection)
// {//保证一个点只用于一个方向,虽然先判断X,但这样也可以相对好用,用户可以手工再调整
if(XYP[i].y > y)
{//计算上方
if(tmp<rs[1])
{
retPt[1] = XYP[i];
rs[1] = tmp;
//retPt[2].y = XYP[i].y;
}
}
else if(XYP[i].y < y)
{//计算下方
if(tmp<rs[3])
{
retPt[3] = XYP[i];
rs[3] = tmp;
//retPt[3].y = XYP[i].y;
}
}
// }
*/
}
if(nRadius>150)
nRadius = 150;
else if(nRadius<50)
nRadius = 50;
//nCount = 0;
for(int j=0; j<4; j++)
{
//if(rs[j] != nMax) nCount++;
// if(rs[j] == nMax)
// {
switch(j)
{
case 0:
retPt[j] = CPoint(x+nRadius,y);
break;
case 2:
retPt[j] = CPoint(x-nRadius,y);
break;
case 1:
retPt[j] = CPoint(x,y+nRadius);
break;
default:
retPt[j] = CPoint(x,y-nRadius);
}
// }
}
return 4;
}
BOOL GetMidDot(CPoint *XYP, int N, int x, int y, CPoint *retPt)
{
for (int i=0; i<N; i++)
{
retPt[i].x = (XYP[i].x + x)/2;
retPt[i].y = (XYP[i].y + y)/2;
}
return TRUE;
}
//返回计算后多边形的点数,点位存储于retPt ,0表是不能生成一个多边形
//这里计算两个四边形最大X或Y相连接后组成新的多边形
//算法:用一个多边形的一点去连接另一个多边形上的点,设XY1上的四点(a1,b1,c1,d1)XY2上的四点(a2,b2,c2,d2)
// a1.x<a2.x且 a1.y<a2.y,a1与a2连接时,
// 判断XY1上点x>a1.x且y>a1.y上的点所在边线与连接线是否相交,如相交这条线不能连接
// 同理判断 XY2上的点;判断第二条线也是这样的方法,同时还判断与前面一条线是否相交,
// 然后将组成的多边形求面积,求出全部可能多边形取最大面积的一个连接方法,
// 两个线不能连接到同一点(也就是说不能a1a2,b1a2这样的连接),
//新算法:找与多边形中两点与井点连线角度最大的
int CalcPolygon2(CPoint* XY1,int N1,CPoint*XY2,int N2,CPoint pt1,CPoint pt2,CPoint *&retPt)
{
int i,j;
int p1x, p1y;
int p2x, p2y;
double A,B,C;
double va1,va2,tmp ;
CPoint onept1,onept2,twopt1,twopt2;
int nCount ,index;
nCount = index = 0;
va1 = va2 = 2;
tmp = 0;
for( i=0; i<N1-1; i++)
{
p1x = XY1[i].x;
p1y = XY1[i].y;
for( j=i+1; j<N1; j++)
{
p2x = XY1[j].x;
p2y = XY1[j].y;
A = sqrt( (p1x-p2x)*(p1x-p2x) + (p1y-p2y)*(p1y-p2y) );
B = sqrt( (p1x-pt2.x)*(p1x-pt2.x) + (p1y-pt2.y)*(p1y-pt2.y) );
C = sqrt( (p2x-pt2.x)*(p2x-pt2.x) + (p2y-pt2.y)*(p2y-pt2.y) );
tmp = (B*B + C*C -A*A)/(2*B*C);
if(tmp <va1)
{
onept1.x = p1x;
onept1.y = p1y;
onept2.x = p2x;
onept2.y = p2y;
}
}
}
for( i=0; i<N2-1; i++)
{
p1x = XY2[i].x;
p1y = XY2[i].y;
for( j=i+1; j<N2; j++)
{
p2x = XY2[j].x;
p2y = XY2[j].y;
A = sqrt( (p1x-p2x)*(p1x-p2x) + (p1y-p2y)*(p1y-p2y) );
B = sqrt( (p1x-pt1.x)*(p1x-pt1.x) + (p1y-pt1.y)*(p1y-pt1.y) );
C = sqrt( (p2x-pt1.x)*(p2x-pt1.x) + (p2y-pt1.y)*(p2y-pt1.y) );
tmp = (B*B + C*C -A*A)/(2*B*C);
if(tmp <va2)
{
twopt1.x = p1x;
twopt1.y = p1y;
twopt2.x = p2x;
twopt2.y = p2y;
}
}
}
//开始判断其,把点不在这四个点合成的多边形内的点加起来,在内的不处理了
long xc,yc;
CArray<class CPoint,class CPoint> ArrPt1;
CArray<class CPoint,class CPoint> ArrPt2;
CRgn rgn;
CPoint tmpPt,tmpPt1,tmpPt2;
CPoint *newpt = new CPoint[4];
if(0 != testCross(onept1.x,onept1.y,twopt1.x,twopt1.y,onept2.x,onept2.y,twopt2.x,twopt2.y,xc,yc))
{
tmpPt = twopt1;
twopt1 = twopt2;
twopt2 = tmpPt;
}
newpt[0] = onept1;
newpt[1] = onept2;
newpt[2] = twopt2;
newpt[3] = twopt1;
rgn.CreatePolygonRgn(newpt,4,ALTERNATE);
for( i=0; i<N1; i++)
{
if(!rgn.PtInRegion(XY1[i]) && onept1 != XY1[i] && onept2 != XY1[i])
{//插入到新数组中
ArrPt1.Add(XY1[i]);
}
}
for( i=0; i<N2; i++)
{
if(!rgn.PtInRegion(XY2[i]) && twopt1 != XY2[i] && twopt2 != XY2[i])
{//插入到新数组中
ArrPt2.Add(XY2[i]);
}
}
if(ArrPt1.GetSize()>1)
{//大于1的情况就只能是2 计算,这两个点只会是在onept1与onept2连线的一边,这里的第1点与第2点分别与onept1与onept2连接,判断是否相交
tmpPt1 = ArrPt1.GetAt(0);
tmpPt2 = ArrPt1.GetAt(1);
if(0 != testCross(onept1.x,onept1.y,tmpPt1.x,tmpPt1.y,onept2.x,onept2.y,tmpPt2.x,tmpPt2.y,xc,yc))
{
ArrPt1.RemoveAt(0);
ArrPt1.Add(tmpPt1);
}
}
if(ArrPt2.GetSize()>1)
{//大于1的情况就只能是2 计算,这两个点只会是在twopt1与twopt2连线的一边,这里的第1点与第2点分别与twopt1与twopt2连接,判断是否相交
tmpPt1 = ArrPt2.GetAt(0);
tmpPt2 = ArrPt2.GetAt(1);
if(0 != testCross(twopt1.x,twopt1.y,tmpPt1.x,tmpPt1.y,twopt2.x,twopt2.y,tmpPt2.x,tmpPt2.y,xc,yc))
{
ArrPt2.RemoveAt(0);
ArrPt2.Add(tmpPt1);
}
}
nCount = ArrPt1.GetSize() + ArrPt2.GetSize() + 4;
retPt = new CPoint[nCount];
index = 0;
retPt[index] = onept1;
for(i=0; i<ArrPt1.GetSize(); i++)
{
index++;
retPt[index] = ArrPt1.GetAt(i);
}
index++;
retPt[index] = onept2;
index++;
retPt[index] = twopt2;
for(i=ArrPt2.GetSize()-1; i>=0; i--)
{
index++;
retPt[index] = ArrPt2.GetAt(i);
}
index++;
retPt[index] = twopt1;
return nCount ;
}
/*
BOOL CalcPolygon2(CPoint *XY,int N,int x1,int y1,int x2,int y2)
{
int ret = 0;
float xc,yc;
for(int i=0 ;i<N-1; i++)
{
float myx1 = XY[i].x;
float myy1 = XY[i].y;
float myx2 = XY[i+1].x;
float myy2 = XY[i+1].y;
ret=testCrossEnd(myx1,myy1,myx2,myy2,x1,y1,x2,y2,&xc,&yc);
if(ret == 0) return FALSE
}
//int ret = crossXY(x,y,x1,y1,x2,y2,&xc,&yc,N);
if(ret==1) return TRUE;
return FALSE;
}
//交点在两条线的端点就返回1,否则返回0
int testCrossEnd(float xa, float ya, float xb, float yb,
float xA, float yA, float xB, float yB,
float &xc, float &yc)
{
// if ((xA==xa && yA==ya) || (xA==xb && yA==yb)) return 0;
// if ((xA==xb && yA==yb) || (xA==xb && yA==yb)) return 0;
if (! testCrossed( xa, ya, xb, yb, xA, yA, xB, yB, xc, yc)) return 0;
if (xc==xa && yc==ya) return 1;
if (xc==xb && yc==yb) return 1;
if (xc==xA && yc==yA) return 1;
if (xc==xB && yc==yB) return 1;
return 0;
}
*/
//计算两个多边形线的交点,计算相交后的多边形,取并集
//算法:生成一个多边形,然后判断另一个点集中的两点,如两点中一个在多边形内,另一个不在,就计算连线与多边形上的交点
// 得到交点,所有的都判断完后,再将所有的点合成到一个多边形,合成时,点在多边形内的不考虑,在外的在合成范围内
// (判断一个多边形上的点是否在另一个多边形内就有点在多边形外的情况),刚才计算的交点也在范围内
// 同时,也要判断第一个多边形上的点是否在第二个多边形内,判断方式与前面相同,这样两个多边形相交的点都能去除
//参数:XY1Array多边形A,XY2多边形B,N2是多边形B的顶点个数,*retPt是新的多边形C
//返回:新多边形顶点个数
int CalcPolygon3(CArray<class CPoint,class CPoint> &XY1Array,CPoint*XY2,int N2,CPoint *&retPt)
{
int i,j,itmp;
int iCnt;
CRgn rgn1,rgn2;
long xc,yc;
CPoint onePt1,onePt2,twoPt1,twoPt2;
CTypedPtrList<CObList,CSideLine*> m_PtList1;
CTypedPtrList<CObList,CSideLine*> m_PtList2;
CArray<class CPoint,class CPoint> oneArray;
BOOL b1,b2,bIns ;
b1 = b2 = bIns = FALSE;
CSideLine *sline = new CSideLine;
rgn2.CreatePolygonRgn(XY2,N2,ALTERNATE);
iCnt = XY1Array.GetSize();
for(i=0; i<iCnt-1; i++)
{
int inum = 0;
b1 = b2 = FALSE;
onePt1 = XY1Array.GetAt(i);
onePt2 = XY1Array.GetAt(i+1);
if(rgn2.PtInRegion(onePt1))
{
b1 = TRUE;
inum++;
}
if(rgn2.PtInRegion(onePt2))
{
b2 = TRUE;
inum++;
}
if(inum==0)
{
bIns = TRUE;
sline->m_pointArray.Add(onePt1);
}
else if(inum==1)
{//计算相交线
bIns = TRUE;
for (j=0; j<N2; j++)
{
twoPt1 = XY2[j];
if(j != N2-1)
{
twoPt2 = XY2[j+1];
}
else
{
twoPt2 = XY2[0];
}
int t= testCross(
onePt1.x, onePt1.y,
onePt2.x, onePt2.y,
twoPt1.x, twoPt1.y,
twoPt2.x, twoPt2.y,
xc, yc);
if (t)
{//存储交点 xc yc
//XY1Array.InsertAt(i,CPoint(xc,yc));
break;//因为只有一个交点,所以跳出循环
}
}
if(!b1)
{
sline->m_pointArray.Add(onePt1);
sline->m_pointArray.Add(CPoint(xc,yc));
m_PtList1.AddTail(sline);
bIns = FALSE;
sline = new CSideLine;
}
else
{
sline->m_pointArray.Add(CPoint(xc,yc));
sline->m_pointArray.Add(onePt2);
}
}
}
if(bIns)
{
m_PtList1.AddTail(sline);
}
//分割第二个数组
CPoint *XY1 = new CPoint[iCnt];
for(i=0; i<iCnt; i++)
{
XY1[i] = XY1Array.GetAt(i);
}
sline = new CSideLine;
rgn1.CreatePolygonRgn(XY1,iCnt,ALTERNATE);
for(i=0; i<N2-1; i++)
{
int inum = 0;
b1 = b2 = FALSE;
twoPt1 = XY2[i];
twoPt2 = XY2[i+1];
if(rgn1.PtInRegion(twoPt1))
{
b1 = TRUE;
inum++;
}
if(rgn1.PtInRegion(twoPt2))
{
b2 = TRUE;
inum++;
}
if(inum==0)
{
bIns = TRUE;
sline->m_pointArray.Add(twoPt1);
}
else if(inum==1)
{//计算相交线
bIns = TRUE;
for (j=0; j<iCnt; j++)
{
onePt1 = XY1[j];
if(j != iCnt-1)
{
onePt2 = XY1[j+1];
}
else
{
onePt2 = XY1[0];
}
int t= testCross(
twoPt1.x, twoPt1.y,
twoPt2.x, twoPt2.y,
onePt1.x, onePt1.y,
onePt2.x, onePt2.y,
xc, yc);
if (t)
{//存储交点 xc yc
break;//因为只有一个交点,所以跳出循环
}
}
if(!b1)
{
sline->m_pointArray.Add(twoPt1);
sline->m_pointArray.Add(CPoint(xc,yc));
m_PtList2.AddTail(sline);
bIns = FALSE;
sline = new CSideLine;
}
else
{
sline->m_pointArray.Add(CPoint(xc,yc));
sline->m_pointArray.Add(twoPt2);
}
}
}
if(bIns)
{
m_PtList2.AddTail(sline);
}
//下面是将两个list中的对象合成一个,合成时对比交点就可以了,交点相通说明其应是连接的点
POSITION pos = m_PtList1.GetHeadPosition();
BOOL bFind = FALSE;
while( pos!= NULL)
{
sline = m_PtList1.GetNext(pos);
onePt1 = sline->m_pointArray.GetAt(0);
POSITION pos2 = m_PtList2.GetHeadPosition();
while(pos2 != NULL)
{
CSideLine *sline2 = m_PtList2.GetNext(pos2);
itmp = sline2->m_pointArray.GetSize();
twoPt1 = sline2->m_pointArray.GetAt(0);
twoPt2 = sline2->m_pointArray.GetAt(itmp-1);
if(onePt1 == twoPt1)
{
for(i=1; i<itmp; i++)//相等的点就不再插入
{
sline->m_pointArray.Add(sline2->m_pointArray.GetAt(i));
}
break;
}
else if(onePt1 == twoPt2)
{
for(i=itmp-2; i>=0; i--)//相等的点就不再插入
{
sline->m_pointArray.Add(sline2->m_pointArray.GetAt(i));
}
break;
}
}
oneArray.Append(sline->m_pointArray);
}
itmp = oneArray.GetSize();
retPt = new CPoint[itmp];
for(i=0; i<itmp; i++)
{
onePt1 = oneArray.GetAt(i);
retPt[i] = onePt1 ;
}
return itmp;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -