八叉树 判断长立方体是否在物体内
2014-06-30 16:44
295 查看
八叉树判断子长方体的8个点是否在物体内,可判断这8个点是不是在整个物体所有面的内侧。注:(1)但如果物体不是凸壳呢,而是凹体呢???可能某个点在一个面外,但它仍在物体内。??????????(2)每个子长方体里的Object* oo;对象都是该物体的完整模型,该物体的面片并不会被分解。 参考源代码如下:(octtree.h、octtree.cpp、main.cpp)下载地址:http://download.csdn.net/download/gdf420/28747521、 octtree.h
http://blog.csdn.net/tmljs1988/article/details/7995088
#ifndef OCTTREE_H #define OCTTREE_H #include <vector> using namespace std; /* 三维空间点类 */ struct Point{ public: double x,y,z; void setPoint(double _x,double _y,double _z){ x = _x; y = _y; z = _z; } bool equals(Point* p){//判断2个点是否相等 if(x != p->x)return false; if(y != p->y)return false; if(z != p->z)return false; return true; } }; /* 平面方程类 void setFormula(Point* p[]):计算4个参数(a,b,c,d) bool formpos(Point* p):在平面某一侧的正负 */ struct Formula{ double a,b,c,d; void setFormula(Point* p[]){ a=(p[1]->y-p[0]->y)*(p[2]->z-p[0]->z)-(p[2]->y-p[0]->y)*(p[1]->z-p[0]->z); b=(p[1]->x-p[0]->x)*(p[2]->z-p[0]->z)-(p[2]->x-p[0]->x)*(p[1]->z-p[0]->z); b=-(b); c=(p[1]->x-p[0]->x)*(p[2]->y-p[0]->y)-(p[2]->x-p[0]->x)*(p[1]->y-p[0]->y); d=-(a*p[0]->x+b*p[0]->y+c*p[0]->z); } bool formpos(Point* p){//点在面的内侧或外侧 double tmp; tmp = a*p->x + b*p->y + c*p->z +d; if(tmp > 0)return true; else return false; }//代入方程后值的正负 }; /* 多边形面类 bool hasPoint(Point* p):是否在平面顶点组里 */ struct Face{ Point** vp; //顶点指针数组 int num; //顶点个数 Formula form; //平面方程 bool forminsidepos; //在多边形内的点带入方程的正负 bool hasPoint(Point* p){ for(int i = 0;i < num;i++){ if(vp[i]->equals(p))return true; } return false; } }; /* 物体类 bool isInside(Point* p)判断一个点是否在物体内 */ struct Object{ Face** vf;//初始化还要包括每个面的正负情况 int num; bool isInside(Point* p){ for(int i = 0;i < num;i++){//如果某点在面的外侧,则返回false if(vf[i]->form.formpos(p) != vf[i]->forminsidepos){ return false; } } return true; } }; /* 八叉树节点 init:初始化八叉树 */ struct Node{ Node* np[8]; bool isfull; //该节点被填充 bool isempty; //该节点没有被填充 bool isdiv; //该节点部分被填充 double xmin,ymin,zmin,length; int depth; bool inside[27];//构成空间的27个顶点是否都在物体内部 Object* oo; //物体(子长方体仍然使用不变的Object,即物体面片不会被分割) void init(Object* o,double x,double y,double z,double l,int d); }; #endif――――――――――――――2、octtree.cpp:
#include <iostream> using namespace std; #include "octtree.h" const int MAXDEP = 3; void Node::init(Object* o,double x,double y,double z,double l,int d){ //初始化 for(int m = 0;m < 8;m++){ np[m] = NULL; } isfull = false; isempty = false; isdiv = false; //分到了极限 if(d > MAXDEP){ isfull = true; oo = o; xmin = x; ymin = y; zmin = z; length = l; depth = d; } //能继续分或者是空 else{ oo = o; xmin = x; ymin = y; zmin = z; length = l; depth = d; int num = 0,lentmp = length/2; Point ptmp; //考虑构成八叉树的各个立方体的27个顶点 for(int i = 0;i < 3;i++){ for(int j = 0;j < 3;j++){ for(int k = 0;k < 3;k++){ ptmp.setPoint(xmin+i*lentmp,ymin+j*lentmp,zmin+k*lentmp); inside[num] = oo->isInside(&ptmp); num++; } } } //对于每个多变型考虑情况 //1 isempty = true; if(inside[0] && inside[1] && inside[3] && inside[4] && inside[9] && inside[10] && inside[12] && inside[13]){ isempty = false; isfull = true; np[0] = NULL; } else if(inside[0] || inside[1] || inside[3] || inside[4] || inside[9] || inside[10] || inside[12] || inside[13]){ isempty = false; np[0] = new Node(); np[0]->init(o,xmin,ymin,zmin,length/2,d+1); } //2 if(inside[18] && inside[19] && inside[21] && inside[22] && inside[9] && inside[10] && inside[12] && inside[13]){ isempty = false; isfull = true; np[1] = NULL; } else if(inside[18] || inside[19] || inside[21] || inside[22] || inside[9] || inside[10] || inside[12] || inside[13]){ isempty = false; np[1] = new Node(); np[1]->init(o,xmin+length/2,ymin,zmin,length/2,d+1); } //3 if(inside[6] && inside[7] && inside[3] && inside[4] && inside[15] && inside[16] && inside[12] && inside[13]){ isempty = false; isfull = true; np[2] = NULL; } else if(inside[6] || inside[7] || inside[3] || inside[4] || inside[15] || inside[16] || inside[12] || inside[13]){ isempty = false; np[2] = new Node(); np[2]->init(o,xmin,ymin+length/2,zmin,length/2,d+1); } //4 if(inside[15] && inside[16] && inside[24] && inside[25] && inside[21] && inside[22] && inside[12] && inside[13]){ isempty = false; isfull = true; np[3] = NULL; } else if(inside[15] || inside[16] || inside[24] || inside[25] || inside[21] || inside[22] || inside[12] || inside[13]){ isempty = false; np[3] = new Node(); np[3]->init(o,xmin+length/2,ymin+length/2,zmin,length/2,d+1); } //5 if(inside[2] && inside[1] && inside[5] && inside[4] && inside[11] && inside[10] && inside[14] && inside[13]){ isempty = false; isfull = true; np[4] = NULL; } else if(inside[2] || inside[1] || inside[5] || inside[4] || inside[11] || inside[10] || inside[14] || inside[13]){ isempty = false; np[4] = new Node(); np[4]->init(o,xmin,ymin,zmin+length/2,length/2,d+1); } //6 if(inside[10] && inside[13] && inside[11] && inside[14] && inside[19] && inside[20] && inside[22] && inside[23]){ isempty = false; isfull = true; np[5] = NULL; } else if(inside[10] || inside[13] || inside[11] || inside[14] || inside[19] || inside[20] || inside[22] || inside[23]){ isempty = false; np[5] = new Node(); np[5]->init(o,xmin+length/2,ymin,zmin+length/2,length/2,d+1); } //7 if(inside[4] && inside[5] && inside[7] && inside[8] && inside[13] && inside[14] && inside[16] && inside[17]){ isempty = false; isfull = true; np[6] = NULL; } else if(inside[4] || inside[5] || inside[7] || inside[8] || inside[13] || inside[14] || inside[16] || inside[17]){ isempty = false; np[6] = new Node(); np[6]->init(o,xmin,ymin+length/2,zmin+length/2,length/2,d+1); } //8 if(inside[13] && inside[13] && inside[16] && inside[17] && inside[22] && inside[23] && inside[25] && inside[26]){ isempty = false; isfull = true; np[7] = NULL; } else if(inside[13] || inside[13] || inside[16] || inside[17] || inside[22] || inside[23] || inside[25] || inside[26]){ isempty = false; np[7] = new Node(); np[7]->init(o,xmin+length/2,ymin+length/2,zmin+length/2,length/2,d+1); } if(isempty == false)isdiv = true; } } /*end of node*/―――――――――――――――――――3、main.cpp:
/* 文件名:main.cpp 功能:测试八叉树,单击改变显示模式 */ #include <iostream> #include <cstdlib> #include <stack> using namespace std; #include "GL/glut.h" #include "octtree.h" enum STATUS {DRAW_ALL=0,DRAW_POINT,DRAW_CUBE}; Point parray[6]; Face face[8]; Object o; Node top; int status; //定义函数 void init(); void display(); void mouse(int button,int state,int x,int y); void initdata(); void idle(); void destory(); int main(int argc,char ** argv){ glutInit(&argc,argv); glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB); glutInitWindowSize(800,600); glutInitWindowPosition(100,100); glutCreateWindow("octtree"); init(); glutDisplayFunc(display); glutMouseFunc(mouse); glutMainLoop(); destory(); return 0; } void init(){ initdata(); //opengl glClearColor(0,0,0,0); } void display(){ glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT); glLoadIdentity (); gluLookAt(0,0,200,0,0,0,0,1,0); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-100,100,-100,100,50,300); int i,j; switch(status){ case DRAW_ALL://只是画线轮廓 glColor3f(1,1,1); for(i = 0;i < 5;i++){ for(j = i+1;j <6;j++){ glBegin(GL_LINES); glVertex3f(parray[i].x,parray[i].y,parray[i].z); glVertex3f(parray[j].x,parray[j].y,parray[j].z); glEnd(); } } break; case DRAW_POINT://把分成的多边形的每一个顶点都画出来 { glColor3f(1,1,1); glBegin(GL_POINTS); stack<Node*> no; no.push(&top); while(!no.empty()){ Node* tmp = no.top(); no.pop(); if(tmp == NULL)continue; if(tmp->isfull){ glVertex3f(tmp->xmin+tmp->length,tmp->ymin+tmp->length,tmp->zmin+tmp->length); glVertex3f(tmp->xmin+tmp->length,tmp->ymin+tmp->length,tmp->zmin); glVertex3f(tmp->xmin+tmp->length,tmp->ymin,tmp->zmin+tmp->length); glVertex3f(tmp->xmin+tmp->length,tmp->ymin,tmp->zmin); glVertex3f(tmp->xmin,tmp->ymin+tmp->length,tmp->zmin+tmp->length); glVertex3f(tmp->xmin,tmp->ymin+tmp->length,tmp->zmin); glVertex3f(tmp->xmin,tmp->ymin,tmp->zmin+tmp->length); glVertex3f(tmp->xmin,tmp->ymin,tmp->zmin); } else if(tmp->isempty){ } else{ for(int i = 0;i < 8;i++){ no.push(tmp->np[i]); } } } glEnd(); } break; case DRAW_CUBE://把分成的多边形都画出来 { glColor3f(1,1,1); glBegin(GL_QUADS); stack<Node*> no; no.push(&top); while(!no.empty()){ Node* tmp = no.top(); no.pop(); if(tmp == NULL)continue; if(tmp->isfull){ glVertex3f(tmp->xmin+tmp->length,tmp->ymin+tmp->length,tmp->zmin+tmp->length); glVertex3f(tmp->xmin+tmp->length,tmp->ymin+tmp->length,tmp->zmin); glVertex3f(tmp->xmin+tmp->length,tmp->ymin,tmp->zmin+tmp->length); glVertex3f(tmp->xmin+tmp->length,tmp->ymin,tmp->zmin); glVertex3f(tmp->xmin,tmp->ymin+tmp->length,tmp->zmin+tmp->length); glVertex3f(tmp->xmin,tmp->ymin+tmp->length,tmp->zmin); glVertex3f(tmp->xmin,tmp->ymin,tmp->zmin+tmp->length); glVertex3f(tmp->xmin,tmp->ymin,tmp->zmin); } else if(tmp->isempty){ } else{ for(int i = 0;i < 8;i++){ no.push(tmp->np[i]); } } } glEnd(); } break; } glutSwapBuffers(); } void mouse(int button,int state,int x,int y){ cout << button << ' ' << state << ' ' << x << ' ' << y << endl; if(state ==0){ status++; status%=3; glutPostRedisplay(); } } void initdata(){ //point parray[0].setPoint(50,50,0); parray[1].setPoint(50,50,100); parray[2].setPoint(50,0,50); parray[3].setPoint(50,100,50); parray[4].setPoint(0,50,50); parray[5].setPoint(100,50,50); //~point //face1 face[0].num = 3; face[0].vp = new Point*[3]; face[0].vp[0] = parray; face[0].vp[1] = parray+2; face[0].vp[2] = parray+5; face[0].form.setFormula(face[0].vp); face[1].num = 3; face[1].vp = new Point*[3]; face[1].vp[0] = parray; face[1].vp[1] = parray+2; face[1].vp[2] = parray+4; face[1].form.setFormula(face[1].vp); face[2].num = 3; face[2].vp = new Point*[3]; face[2].vp[0] = parray; face[2].vp[1] = parray+3; face[2].vp[2] = parray+4; face[2].form.setFormula(face[2].vp); face[3].num = 3; face[3].vp = new Point*[3]; face[3].vp[0] = parray; face[3].vp[1] = parray+3; face[3].vp[2] = parray+5; face[3].form.setFormula(face[3].vp); face[4].num = 3; face[4].vp = new Point*[3]; face[4].vp[0] = parray+1; face[4].vp[1] = parray+2; face[4].vp[2] = parray+5; face[4].form.setFormula(face[4].vp); face[5].num = 3; face[5].vp = new Point*[3]; face[5].vp[0] = parray+1; face[5].vp[1] = parray+2; face[5].vp[2] = parray+4; face[5].form.setFormula(face[5].vp); face[6].num = 3; face[6].vp = new Point*[3]; face[6].vp[0] = parray+1; face[6].vp[1] = parray+3; face[6].vp[2] = parray+5; face[6].form.setFormula(face[6].vp); face[7].num = 3; face[7].vp = new Point*[3]; face[7].vp[0] = parray+1; face[7].vp[1] = parray+3; face[7].vp[2] = parray+4; face[7].form.setFormula(face[7].vp); //~face init over int i,j; //object init begin o.num = 8; o.vf = new Face*[8]; for(i = 0;i < 8;i++){ o.vf[i] = &(face[i]); } //init frompos //the 7th face for(j = 0;j < o.vf[0]->num;j++){ if(o.vf[7]->hasPoint(o.vf[0]->vp[j]))continue; else{ o.vf[7]->forminsidepos = o.vf[7]->form.formpos(o.vf[0]->vp[j]); break; } } //计算某个面A的相邻面B的点在A的哪侧,从而可确定内外侧。 for(i = 0;i < 7;i++){ for(j = 0;j < o.vf[i]->num;j++){ if(o.vf[i]->hasPoint(o.vf[i+1]->vp[j]))continue; else{ o.vf[i]->forminsidepos = o.vf[i]->form.formpos(o.vf[i+1]->vp[j]); break; } } } cout << "object init over" << endl; for(i = 0;i < o.num;i++){ cout << "face" << i << endl; for(j = 0;j < o.vf[i]->num;j++){ cout << "num of point" << endl; cout << o.vf[i]->vp[j]->x <<" "<< o.vf[i]->vp[j]->y << " " << o.vf[i]->vp[j]->z << endl; } cout << "formulation" << endl; cout << o.vf[i]->form.a <<" "<< o.vf[i]->form.b <<" "<< o.vf[i]->form.c <<" "<< o.vf[i]->form.d <<endl; cout << o.vf[i]->forminsidepos << endl; } //~object init over //ok //node init top.init(&o,0,0,0,100,0); //~node init over cout << "initover" << endl; stack<Node*> no; no.push(&top); while(!no.empty()){//输出显示子节点 Node* tmp = no.top(); no.pop(); if(tmp == NULL)continue; if(tmp->isfull){ cout << "full" << endl; cout << tmp->xmin << ' ' << tmp->ymin << ' ' << tmp->zmin << ' ' << tmp->length << endl; } else if(tmp->isempty){ cout << "empty" << endl; cout << tmp->xmin << ' ' << tmp->ymin << ' ' << tmp->zmin << ' ' << tmp->length << endl; } else{ cout << "isdiv" << endl; cout << tmp->xmin << ' ' << tmp->ymin << ' ' << tmp->zmin << ' ' << tmp->length << endl; for(int i = 0;i < 8;i++){ no.push(tmp->np[i]); } } } } void destory(){ stack<Node*> no; no.push(&top); while(!no.empty()){ Node* tmp = no.top(); no.pop(); if(tmp == NULL)continue; if(tmp->isfull){ delete tmp; } else if(tmp->isempty){ delete tmp; } else{ for(int i = 0;i < 8;i++){ no.push(tmp->np[i]); } delete tmp; } } };
http://blog.csdn.net/tmljs1988/article/details/7995088
相关文章推荐
- 八叉树 判断长立方体是否在物体内???????
- [unity3d]判断物体是否在视角内(巧妙!)
- 判断两个物体之间是否有气其他Collider阻挡
- 判断物体是否在视角内(巧妙!)
- 判断两立方体体积是否相等
- 判断物体是否在摄像机内
- Unith3D判断物体是否在视角内
- Unity判断一个物体是否在屏幕内外
- unity3d点击屏幕判断是否击中场景中物体
- 【Unity3D自学记录】判断物体是否在镜头内
- unity3D基础学习 通过判断鼠标点击的是否是目标物体,物体旋转,滑动滚轮缩放拉近视角
- Unity 物体跟随鼠标点击移动,判断物体是否在移动
- 【Unity3D自学记录】判断物体是否在镜头内
- 判断物体是否在摄像机视野中
- 判断物体是否在摄像机中显示
- unity 怎么判断凹凸不平地面 物体是否出现在视野之内
- BOX 判断是否能够形成立方体
- Unity 判断是否点击在3D物体上
- 【Unity3D】判断是否鼠标点击物体与血条制作
- unity使用手势时,通过射线判断是否触碰到了某物体