📄 cmath.cpp.svn-base
字号:
// CMath.cpp: implementation of the CMath class.
//
//////////////////////////////////////////////////////////////////////
//#include "stdafx.h"
#include "CMath.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CMath::CMath()
{}
CMath::~CMath()
{}
/////////////////////////////
bool CMath::IsLineSegmentCutByPolygon(VERTEX v1 ,VERTEX v2,VERTEX* pv,int num)
{
if(num<3)return false;
PLANE plane;
plane=GetPlaneEquation(pv,num);
///////////如果两点在同一侧
if((ClassifyPointPlane(v1,plane)*ClassifyPointPlane(v2,plane))> 0)
return false;
//////////////获得线段与平面的交点
VERTEX intersection;
intersection=GetIntersection(v1,v2,plane);
///////////包围盒粗略判断
float maxx,minx, maxy,miny, maxz,minz;
maxx=minx=pv[0].xpos;
maxy=miny=pv[0].ypos;
maxz=minz=pv[0].zpos;
for(int i=1;i<num;i++)
{
if(pv[i].xpos>maxx)maxx=pv[i].xpos;
if(pv[i].xpos<minx)minx=pv[i].xpos;
if(pv[i].ypos>maxy)maxy=pv[i].ypos;
if(pv[i].ypos<miny)miny=pv[i].ypos;
if(pv[i].zpos>maxz)maxz=pv[i].zpos;
if(pv[i].zpos<minz)minz=pv[i].zpos;
}
if(intersection.xpos>maxx || intersection.xpos<minx)
return false;
if(intersection.ypos>maxy || intersection.ypos<miny)
return false;
if(intersection.zpos>maxz || intersection.zpos<minz)
return false;
//////////////找一个过交点intersection且与某一坐标轴垂直的平面
PLANE p(0,0,0,0);
float absA,absB,absC;
if(plane.A<0)absA=-plane.A;
else absA=plane.A;
if(plane.B<0)absB=-plane.B;
else absB=plane.B;
if(plane.C<0)absC=-plane.C;
else absC=plane.C;
if(absA<=absB && absA<=absC)
{
///////////平面与X轴接近平行(当与某一分量小到0时,就完全平行)
p.A=1;
p.D=-intersection.xpos;
///////////////////////////////////////////
if(absB>absC)
{ //////比较 Z 轴坐标
VERTEX sect[6];/////可能有重复的交点,如顶点
int index=0;
for( i=0;i<(num-1);i++)
{
if(ClassifyPointPlane(pv[i],p)!=ClassifyPointPlane(pv[i+1],p))
{
sect[index]=GetIntersection(pv[i],pv[i+1],p);
index++;
}
}
if(ClassifyPointPlane(pv[0],p)!=ClassifyPointPlane(pv[num-1],p))
{
sect[index]=GetIntersection(pv[0],pv[num-1],p);
index++;
}
/////////////////////////////
float maxzz,minzz;
maxzz=minzz=sect[0].zpos;
for(i=0;i<index;i++)
{
if(sect[i].zpos>maxzz)maxzz=sect[i].zpos;
if(sect[i].zpos<minzz)minzz=sect[i].zpos;
}
if(intersection.zpos>maxzz || intersection.zpos<minzz)return false;
else
return true;
}
else
{ //////比较 Y 轴坐标
VERTEX sect[6];/////可能有重复的交点,如顶点
int index=0;
for( i=0;i<(num-1);i++)
{
if(ClassifyPointPlane(pv[i],p)!=ClassifyPointPlane(pv[i+1],p))
{
sect[index]=GetIntersection(pv[i],pv[i+1],p);
index++;
}
}
if(ClassifyPointPlane(pv[0],p)!=ClassifyPointPlane(pv[num-1],p))
{
sect[index]=GetIntersection(pv[0],pv[num-1],p);
index++;
}
/////////////////////////////
float maxyy,minyy;
maxyy=minyy=sect[0].ypos;
for(i=0;i<index;i++)
{
if(sect[i].ypos>maxyy)maxyy=sect[i].ypos;
if(sect[i].ypos<minyy)minyy=sect[i].ypos;
}
if(intersection.ypos>maxyy || intersection.ypos<minyy)return false;
else
return true;
}
}
else if(absB<=absA && absB<=absC)
{
///////////平面与Y轴接近平行
p.B=1;
p.D=-intersection.ypos;
///////////////////////////////////////////
if(absA>absC)
{ //////比较 Z 轴坐标
VERTEX sect[6];/////可能有重复的交点,如顶点
int index=0;
for( i=0;i<(num-1);i++)
{
if(ClassifyPointPlane(pv[i],p)!=ClassifyPointPlane(pv[i+1],p))
{
sect[index]=GetIntersection(pv[i],pv[i+1],p);
index++;
}
}
if(ClassifyPointPlane(pv[0],p)!=ClassifyPointPlane(pv[num-1],p))
{
sect[index]=GetIntersection(pv[0],pv[num-1],p);
index++;
}
/////////////////////////////
float maxzz,minzz;
maxzz=minzz=sect[0].zpos;
for(i=0;i<index;i++)
{
if(sect[i].zpos>maxzz)maxzz=sect[i].zpos;
if(sect[i].zpos<minzz)minzz=sect[i].zpos;
}
if(intersection.zpos>maxzz || intersection.zpos<minzz)return false;
else
return true;
}
else
{ //////比较 X 轴坐标
VERTEX sect[6];/////可能有重复的交点,如顶点
int index=0;
for( i=0;i<(num-1);i++)
{
if(ClassifyPointPlane(pv[i],p)!=ClassifyPointPlane(pv[i+1],p))
{
sect[index]=GetIntersection(pv[i],pv[i+1],p);
index++;
}
}
if(ClassifyPointPlane(pv[0],p)!=ClassifyPointPlane(pv[num-1],p))
{
sect[index]=GetIntersection(pv[0],pv[num-1],p);
index++;
}
/////////////////////////////
float maxxx,minxx;
maxxx=minxx=sect[0].xpos;
for(i=0;i<index;i++)
{
if(sect[i].xpos>maxxx)maxxx=sect[i].xpos;
if(sect[i].xpos<minxx)minxx=sect[i].xpos;
}
if(intersection.xpos>maxxx || intersection.xpos<minxx)return false;
else
return true;
}
}
else //(absC<absA && absC<absB)
{
///////////平面与Z轴接近平行
p.C=1;
p.D=-intersection.zpos;
///////////////////////////////////////////
if(absA>absB)
{ //////比较 Y 轴坐标
VERTEX sect[6];/////可能有重复的交点,如顶点
int index=0;
for( i=0;i<(num-1);i++)
{
if(ClassifyPointPlane(pv[i],p)!=ClassifyPointPlane(pv[i+1],p))
{
sect[index]=GetIntersection(pv[i],pv[i+1],p);
index++;
}
}
if(ClassifyPointPlane(pv[0],p)!=ClassifyPointPlane(pv[num-1],p))
{
sect[index]=GetIntersection(pv[0],pv[num-1],p);
index++;
}
/////////////////////////////
float maxyy,minyy;
maxyy=minyy=sect[0].ypos;
for(i=0;i<index;i++)
{
if(sect[i].ypos>maxyy)maxyy=sect[i].ypos;
if(sect[i].ypos<minyy)minyy=sect[i].ypos;
}
if(intersection.ypos>maxyy || intersection.ypos<minyy)return false;
else
return true;
}
else
{ //////比较 X 轴坐标
VERTEX sect[6];/////可能有重复的交点,如顶点
int index=0;
for( i=0;i<(num-1);i++)
{
if(ClassifyPointPlane(pv[i],p)!=ClassifyPointPlane(pv[i+1],p))
{
sect[index]=GetIntersection(pv[i],pv[i+1],p);
index++;
}
}
if(ClassifyPointPlane(pv[0],p)!=ClassifyPointPlane(pv[num-1],p))
{
sect[index]=GetIntersection(pv[0],pv[num-1],p);
index++;
}
/////////////////////////////
float maxxx,minxx;
maxxx=minxx=sect[0].xpos;
for(i=0;i<index;i++)
{
if(sect[i].xpos>maxxx)maxxx=sect[i].xpos;
if(sect[i].xpos<minxx)minxx=sect[i].xpos;
}
if(intersection.xpos>maxxx || intersection.xpos<minxx)return false;
else
return true;
}
}
return true;
}
bool CMath::IsLineSegmentCutBy3DBoundary(VERTEX *v1 ,VERTEX *v2,BOUNDARY_3D *bd)
{
if(v1->xpos>bd->maxx && v2->xpos>bd->maxx)return false;
if(v1->xpos<bd->minx && v2->xpos<bd->minx)return false;
if(v1->ypos>bd->maxy && v2->ypos>bd->maxy)return false;
if(v1->ypos<bd->miny && v2->ypos<bd->miny)return false;
if(v1->zpos>bd->maxz && v2->zpos>bd->maxz)return false;
if(v1->zpos<bd->minz && v2->zpos<bd->minz)return false;
/////////////
VERTEX v[8];
v[0]=VERTEX(bd->minx,bd->miny,bd->minz);
v[1]=VERTEX(bd->maxx,bd->miny,bd->minz);
v[2]=VERTEX(bd->maxx,bd->maxy,bd->minz);
v[3]=VERTEX(bd->minx,bd->maxy,bd->minz);
v[4]=VERTEX(bd->minx,bd->miny,bd->maxz);
v[5]=VERTEX(bd->maxx,bd->miny,bd->maxz);
v[6]=VERTEX(bd->maxx,bd->maxy,bd->maxz);
v[7]=VERTEX(bd->minx,bd->maxy,bd->maxz);
///////////////
if(IsLineSegmentCutByStardQuad(*v1,*v2, v[0],v[1],v[2],v[3]))return true;
if(IsLineSegmentCutByStardQuad(*v1,*v2, v[4],v[5],v[6],v[7]))return true;
if(IsLineSegmentCutByStardQuad(*v1,*v2, v[2],v[3],v[7],v[6]))return true;
if(IsLineSegmentCutByStardQuad(*v1,*v2, v[1],v[0],v[4],v[5]))return true;
if(IsLineSegmentCutByStardQuad(*v1,*v2, v[1],v[2],v[6],v[5]))return true;
if(IsLineSegmentCutByStardQuad(*v1,*v2, v[0],v[3],v[7],v[4]))return true;
///////////////
return false;
}
bool CMath::IsLineSegmentCutBy3DBoundary(VERTEX v1 ,VERTEX v2,BOUNDARY_3D bd)
{
if(v1.xpos>bd.maxx && v2.xpos>bd.maxx)return false;
if(v1.xpos<bd.minx && v2.xpos<bd.minx)return false;
if(v1.ypos>bd.maxy && v2.ypos>bd.maxy)return false;
if(v1.ypos<bd.miny && v2.ypos<bd.miny)return false;
if(v1.zpos>bd.maxz && v2.zpos>bd.maxz)return false;
if(v1.zpos<bd.minz && v2.zpos<bd.minz)return false;
/////////////
VERTEX v[8];
v[0]=VERTEX(bd.minx,bd.miny,bd.minz);
v[1]=VERTEX(bd.maxx,bd.miny,bd.minz);
v[2]=VERTEX(bd.maxx,bd.maxy,bd.minz);
v[3]=VERTEX(bd.minx,bd.maxy,bd.minz);
v[4]=VERTEX(bd.minx,bd.miny,bd.maxz);
v[5]=VERTEX(bd.maxx,bd.miny,bd.maxz);
v[6]=VERTEX(bd.maxx,bd.maxy,bd.maxz);
v[7]=VERTEX(bd.minx,bd.maxy,bd.maxz);
///////////////
if(IsLineSegmentCutByStardQuad(v1,v2, v[0],v[1],v[2],v[3]))return true;
if(IsLineSegmentCutByStardQuad(v1,v2, v[4],v[5],v[6],v[7]))return true;
if(IsLineSegmentCutByStardQuad(v1,v2, v[2],v[3],v[7],v[6]))return true;
if(IsLineSegmentCutByStardQuad(v1,v2, v[1],v[0],v[4],v[5]))return true;
if(IsLineSegmentCutByStardQuad(v1,v2, v[1],v[2],v[6],v[5]))return true;
if(IsLineSegmentCutByStardQuad(v1,v2, v[0],v[3],v[7],v[4]))return true;
///////////////
return false;
}
bool CMath::IsLineSegmentCutByStardQuad(VERTEX v1 ,VERTEX v2,VERTEX va,VERTEX vb,VERTEX vc,VERTEX vd)
{
PLANE plane;
plane=GetPlaneEquation(va,vb,vc);
///////////如果两点在同一侧
if((ClassifyPointPlane(v1,plane)*ClassifyPointPlane(v2,plane))>=0)
return false;
//////////////获得线段与平面的交点
VERTEX intersection;
intersection=GetIntersection(v1,v2,plane);
///////////包围盒判断,仅对aabb包围盒有效
float maxx,minx, maxy,miny, maxz,minz;
maxx=minx=va.xpos;
maxy=miny=va.ypos;
maxz=minz=va.zpos;
if(vb.xpos>maxx)maxx=vb.xpos;
if(vb.xpos<minx)minx=vb.xpos;
if(vb.ypos>maxy)maxy=vb.ypos;
if(vb.ypos<miny)miny=vb.ypos;
if(vb.zpos>maxz)maxz=vb.zpos;
if(vb.zpos<minz)minz=vb.zpos;
if(vc.xpos>maxx)maxx=vc.xpos;
if(vc.xpos<minx)minx=vc.xpos;
if(vc.ypos>maxy)maxy=vc.ypos;
if(vc.ypos<miny)miny=vc.ypos;
if(vc.zpos>maxz)maxz=vc.zpos;
if(vc.zpos<minz)minz=vc.zpos;
if(vd.xpos>maxx)maxx=vd.xpos;
if(vd.xpos<minx)minx=vd.xpos;
if(vd.ypos>maxy)maxy=vd.ypos;
if(vd.ypos<miny)miny=vd.ypos;
if(vd.zpos>maxz)maxz=vd.zpos;
if(vd.zpos<minz)minz=vd.zpos;
if(intersection.xpos>maxx || intersection.xpos<minx)
return false;
if(intersection.ypos>maxy || intersection.ypos<miny)
return false;
if(intersection.zpos>maxz || intersection.zpos<minz)
return false;
return true;
}
bool CMath::IsLineSegmentCutByStardQuad(VERTEX v1 ,VERTEX v2,VERTEX *pv)
{
return IsLineSegmentCutByStardQuad(v1,v2,pv[0],pv[1],pv[2],pv[3]);
}
bool CMath::IsVertexInsideCube(VERTEX vertex , CUBE cube )
{
if(vertex.xpos < cube.V0.xpos)return false;
if(vertex.xpos > cube.V1.xpos)return false;
if(vertex.ypos < cube.V0.ypos)return false;
if(vertex.ypos > cube.V4.ypos)return false;
if(vertex.zpos < cube.V3.zpos)return false;
if(vertex.zpos > cube.V0.zpos)return false;
return true;
}
bool CMath::IsVertexInsideCube(VERTEX *vertex , BOUNDARY_3D *boundary)
{
if(vertex->xpos > boundary->maxx || vertex->xpos < boundary->minx)return false;
if(vertex->ypos > boundary->maxy || vertex->ypos < boundary->miny)return false;
if(vertex->zpos > boundary->maxz || vertex->zpos < boundary->minz)return false;
return true;
}
bool CMath::IsCubeCutByQuad(CUBE cube , QUAD quad)
{
////////////// 1.如果Quad上有一个点在cube内,则相交
if(IsVertexInsideCube(quad.V0,cube))return true;
if(IsVertexInsideCube(quad.V1,cube))return true;
if(IsVertexInsideCube(quad.V2,cube))return true;
if(IsVertexInsideCube(quad.V3,cube))return true;
////////////// 2. 如果quad的四个点都在cube的某一点的外侧,则不相交
if(quad.V0.xpos < cube.V0.xpos &&
quad.V1.xpos < cube.V0.xpos &&
quad.V2.xpos < cube.V0.xpos &&
quad.V3.xpos < cube.V0.xpos )return false;
if(quad.V0.xpos > cube.V1.xpos &&
quad.V1.xpos > cube.V1.xpos &&
quad.V2.xpos > cube.V1.xpos &&
quad.V3.xpos > cube.V1.xpos )return false;
if(quad.V0.ypos < cube.V0.ypos &&
quad.V1.ypos < cube.V0.ypos &&
quad.V2.ypos < cube.V0.ypos &&
quad.V3.ypos < cube.V0.ypos )return false;
if(quad.V0.ypos > cube.V4.ypos &&
quad.V1.ypos > cube.V4.ypos &&
quad.V2.ypos > cube.V4.ypos &&
quad.V3.ypos > cube.V4.ypos )return false;
if(quad.V0.zpos < cube.V2.zpos &&
quad.V1.zpos < cube.V2.zpos &&
quad.V2.zpos < cube.V2.zpos &&
quad.V3.zpos < cube.V2.zpos )return false;
if(quad.V0.zpos > cube.V1.zpos &&
quad.V1.zpos > cube.V1.zpos &&
quad.V2.zpos > cube.V1.zpos &&
quad.V3.zpos > cube.V1.zpos )return false;
/////////////// 3.现在判断cube上的8个点是否在Quad的同一侧
int side[8];
side[0] = ClassifyPointPlane(cube.V0,quad.plane);
side[1] = ClassifyPointPlane(cube.V1,quad.plane);
side[2] = ClassifyPointPlane(cube.V2,quad.plane);
side[3] = ClassifyPointPlane(cube.V3,quad.plane);
side[4] = ClassifyPointPlane(cube.V4,quad.plane);
side[5] = ClassifyPointPlane(cube.V5,quad.plane);
side[6] = ClassifyPointPlane(cube.V6,quad.plane);
side[7] = ClassifyPointPlane(cube.V7,quad.plane);
int count = 0;
int index = 0;
for(int i=0;i<8;i++)
{
// if(side[i] !=0 )
{
count+=side[i];
index++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -