这里面有分割多边形,和判断平面位置关系两个函数

这篇博客总结了多边形分割算法的两种方法,包括原有的直接假设交点和新的求交点循环序列算法,并探讨了如何将多边形转化为三角形。同时,介绍了位置判断算法,通过共面和方向判断来确定点的位置关系。
摘要由CSDN通过智能技术生成
#include "stdafx.h"
#include "OpenGL.h"
#include "Map.h"
#include "math.h"
#include "ArrayInterTriangle.h"
#include <iostream.h>
#include <stdio.h>
#include <bitset>
extern 	unsigned int m_ID;
#include <math.h>
#include<stdexcept>
#include<time.h>
extern bool	Lbutdown;	// 鼠标左键
extern bool	Rbutdown;	// 鼠标左键
//
extern HWND	hWnd;
//定义最近的距离视点最近的鼠标物体:
//定义一个结构来保存所有的物体:
#include<list>
int TreeDepth=0;
#include<vector>
using std::bitset;
using std::list;
using std::vector;
using std::runtime_error;
using std::length_error;
vector<int> TheDividerList;
class Triangle{
public:
    float a[3];
	float b[3];
	float c[3];
};
class TheTreeObect{
	int maxlen;
	int n;
	//定义当前分割平面的索引。

	int currentFlip;

	Triangle *Triangles;
public:
   
	void SetAsNode(int currentFlip){
	   Triangle temp=Triangles[currentFlip];
	   delete [] Triangles;
       Triangles=new Triangle(temp);
	}
	void deleteALL(){
	  delete[] Triangles;
      Triangles=NULL;
	  n=0;
	}
	void resetTriangle(Triangle *Triangles,int n){
		delete[] this->Triangles;
	    this->Triangles=Triangles; 
		this->n=n;
		this->maxlen=n;
	}
	TheTreeObect(){
	Triangles= new Triangle[10];
		maxlen=10;
		n=0;
	}
    int add(Triangle triangle)
	{	  
	      if(n==maxlen){
			Triangle* temp=Triangles;
			Triangles=new Triangle[n+10];
			for(int i=0;i<n;i++){
			  for(int j=0;j<3;j++){
				Triangles[i].a[j]=temp[i].a[j];
				Triangles[i].b[j]=temp[i].b[j];
				Triangles[i].c[j]=temp[i].c[j];
			  }
			}
			delete [] temp;
		  }
		  for(int j=0;j<3;j++){
              Triangles[n].a[j]=triangle.a[j];
			  Triangles[n].b[j]=triangle.b[j];
			  Triangles[n].c[j]=triangle.c[j];
		  }
		  n++;
		  return n;
	}
	int getFlip(){
	 return currentFlip;
	}
	int getN(){
	return n;
	}
	Triangle *getTriangles()
	{
	  return Triangles;
	}
    TheTreeObect(float (*triangle)[3][3],int n1)
	{
        Triangles= new Triangle[n1];
		n=n1;
		for(int i=0;i<n;i++){
			for(int j=0;j<3;j++){
			//第二维表示点的索引,第三维表示,xyz坐标
		      Triangles[i].a[j]=triangle[i][0][j];
			  Triangles[i].b[j]=triangle[i][1][j];
			  Triangles[i].c[j]=triangle[i][2][j];
			}			  
		}
	}
};
//而叉树节点是一个特殊的物体。。它只有一个平面。
class BSPNode:public TheTreeObect{
public:
    BSPNode(){
	IsLeaf=true;
	}
	//是否为分割面。或是是物体,或者是分割面。
	bool IsLeaf;
	bool IsWithObject;
	void setIsWithObject(bool is)
	{
	     IsWithObject=is;
	}
	BSPNode(TheTreeObect& obj):TheTreeObect(obj){
	}
	void set(bool Front)
	{
	    IsFront=Front;
	}
	bool IsNode;
	bool IsFront;
    TheTreeObect* pBackChild;
	TheTreeObect* pFrontChild;
	//查看物体的第index个三角形是否与既定面共面。
  void outPutSanjiao(Triangle triangle)
	{
	             float *a=triangle.a;
				 float a0=a[0];
				 float a1=a[1];
				 float a2=a[2];
				 cout<<endl<<a0<<"  "<<a1<<"  "<<a2<<"  "<<endl;
				 float *b=triangle.b;
				 float b0=b[0];
				 float b1=b[1];
				 float b2=b[2];
				  cout<<b0<<"  "<<b1<<"  "<<b2<<"  "<<endl;
				 float *c=triangle.c;
				 float c0=c[0];
				 float c1=c[1];
				 float c2=c[2];
				 cout<<c0<<"  "<<c1<<"  "<<c2<<"  "<<endl;
	}
	void outPutSanJiaos(Triangle* pTriangle,int n)
	{
	        for(int i=0;i<n;i++)
			{
			      outPutSanjiao(pTriangle[i]);   
			}
	}
	void outPutVector(char *p,float *pf,int n)
	{
		   for(int j=0;p[j]!='\0';p++)
		   {
				cout<<p[j];
		   }
		   cout<<":"<<endl;
	       for(int i=0;i<n;i++)
			{
			      cout<<pf[i]<<endl;
			}   
	}
	//函数功能:判断一个三角形来自另外一个三角形所在平面的何方。
	//功能描述:如果共面,则same为true,divided为false,方向相同则返回true,否则返回false;
	 //         如果不共面,则根据在前还是后,还是divided ,进行返回。
	bool IsFomFront(TheTreeObect obj,int index,int currentFlip,bool &same,bool &divied){
        divied=false;
		same=false;
		bitset<3> position[3];
		float dir[3];
		bool Front[3];
		bool IsNotInFlat[3];
	    float point[3];
		memcpy(point,obj.getTriangles()[index].a,3*sizeof(float));
		//int currentFlip=getFlip();
		VectBinus(obj.getTriangles()[currentFlip].a,point,dir);
		outPutVector("射线原点",point,3);
		outPutVector("射线终点",obj.getTriangles()[currentFlip].a,3);
	    outPutVector("射线方向",dir,3);
		IsNotInFlat[0]=IsIntersectWithTriangle(
			point,
			dir,
			obj.getTriangles()[currentFlip].a,
			obj.getTriangles()[currentFlip].b,
			obj.getTriangles()[currentFlip].c,
			point,
			Front[0]
			);

		cout<<"********************开始射线检测****************************************"<<endl;
		
		cout<<"分割面为"<<endl;
        outPutSanjiao(obj.getTriangles()[currentFlip]);
        if(!IsNotInFlat[0])cout<<"射线在平面上"<<endl;
		else if(Front[0])cout<<"射线从前方穿过"<<endl;
		else cout<<"射线从后方穿过"<<endl;
        cout<<"********************检测结束****************************************"<<endl;
        memcpy(point,obj.getTriangles()[index].b,3*sizeof(float));
		VectBinus(obj.getTriangles()[currentFlip].b,point,dir);
		IsNotInFlat[1]=IsIntersectWithTriangle(
			point,
			dir,
			obj.getTriangles()[currentFlip].a,
			obj.getTriangles()[currentFlip].b,
			obj.getTriangles()[currentFlip].c,
			point,
			Front[1]
			);

			cout<<"********************开始射线检测****************************************"<<endl;
		outPutVector("射线原点",point,3);
	    outPutVector("射线方向",dir,3);
		cout<<"分割面为"<<endl;
        outPutSanjiao(obj.getTriangles()[currentFlip]);
        if(!IsNotInFlat[1])cout<<"射线在平面上"<<endl;
		else if(Front[1])cout<<"射线从前方穿过"<<endl;
		else cout<<"射线从后方穿过"<<endl;
        cout<<"********************检测结束****************************************"<<endl;
        memcpy(point,obj.getTriangles()[index].c,3*sizeof(float));
		VectBinus(obj.getTriangles()[currentFlip].c,point,dir);
		IsNotInFlat[2]=IsIntersectWithTriangle(
			point,
			dir,
			obj.getTriangles()[currentFlip].a,
			obj.getTriangles()[currentFlip].b,
			obj.getTriangles()[currentFlip].c,
			point,
			Front[2]
			);
			cout<<"********************开始射线检测****************************************"<<endl;
		outPutVector("射线原点",point,3);
	    outPutVector("射线方向",dir,3);
		cout<<"分割面为"<<endl;
        outPutSanjiao(obj.getTriangles()[currentFlip]);
        if(!IsNotInFlat[2])cout<<"射线在平面上"<<endl;
		else if(Front[2])cout<<"射线从前方穿过"<<endl;
		else cout<<"射线从后方穿过"<<endl;
        cout<<"********************检测结束****************************************"<<endl;

        for(int i=0;i<3;i++)
		{
		    if(!IsNotInFlat[i])position[i].set(0);else
				if(Front[i])position[i].set(1);else
					position[i].set(2);
		}
		for(i=0;i<3;i++)
		{
			 cout<<"i:顶点"<<i<<endl;
		     cout<<position[i][0];
			 cout<<position[i][1];
			 cout<<position[i][2];
		}
		//每个点的三个状态对应为 position[0],position[1],position[2];
		bitset<3> positi=position[0]&position[1]&position[2];

		for(i=0;i<3;i++)
		{
			cout<<"综合:";
		   cout<<positi[i]<<endl;
		}
		//查看是否共面
		//分析结果为:
		cout<<"经过分析,三角形与平面的关系为:"<<endl;
		if(positi[0])
		{   cout<<"这是一个相同的平面"<<endl;
			same=true;
			//查看方向是否相同
            //求得他们的发线:
           float flat_3_flip[3];
		   float flat_3_temp[3];
            qiuFaXiangLiang(
				getTriangles()[currentFlip].a,
				getTriangles()[currentFlip].b,
				getTriangles()[currentFlip].c,
				flat_3_flip);
			 qiuFaXiangLiang(
				getTriangles()[index].a,
				getTriangles()[index].b,
				getTriangles()[index].c,
				flat_3_temp);
			 float dotval=DotProduct(flat_3_flip,flat_3_temp);
			 if(dotval<0){
				 //点积为负值
			    return false;
			 }else
				 //点积为正值
				 return true;
		}else {
			positi=position[0]|position[1]|position[2];
				//不共面并且没有在后面的点!!
			if(!positi[2])
			{
				cout<<"前面"<<endl;
				return true;
			}
				//不共面没有前面的点
			else if(!positi[1])
			{
				cout<<"后面"<<endl;
				return false;
			}else 
			{	
				//不共面,既有前面的点,也有后面的点。
				cout<<"被分割的面"<<endl;
				divied=true;
				return false;
			}
		}
	}
	//函数功能:从所有的备选三角形列表中找到一个最佳的分割平面。

	int getTheBestDivider(vector<int> TheDividerList,bool &found, TheTreeObect obj){

		       cout<<"×××××××××寻找最佳分割面开始××××××××××××××"<<endl;
			   cout<<"当前的树深为"<<endl;
			   cout<<TreeDepth<<endl;
			   cout<<"要检测的三角集合为:"<<endl;
			   outPutSanJiaos(obj.getTriangles(),obj.getN());
               //定义评估数组
			   int *pingguvalue=new int[TheDividerList.size()];
		       //是否找到
		       found=false;
			   //定义最佳评估值
		       int theOptimizedValue;
			   //最佳的评估值对应的三角形编号(对应于theDividerList)
			   int theOpTriagl;
			   //评估值是否初始化
			   bool IsInit=false;
			   //判断是否为凸空间,默认为凸                    
			   bool AllFront=true;
			   bool AllBack=true;
			   for(int flip=0;flip<TheDividerList.size();flip++){
				   cout<<"-------------------第"<<flip<<"个分割面评估值检测开始-------------------"<<endl;
				    cout<<"第"<<flip<<"个待定分割面为"<<endl;
					cout<<"第"<<TheDividerList[flip]<<"个三角形"<<endl;
                    outPutSanjiao(obj.getTriangles()[TheDividerList[flip]]);
				    int N_FRONT=0;
					int N_BACK=0;
					int N_DIVIDE=0;
					if(
					 !IsTriangle(
					   obj.getTriangles()[TheDividerList[flip]].a,
					   obj.getTriangles()[TheDividerList[flip]].b,
					   obj.getTriangles()[TheDividerList[flip]].c
					   )
					 )
					{
						cout<<"它不是一个平面!"<<endl;
						continue;
					}else
					{
					    cout<<"它是一个平面!"<<endl;    
					}
					for(int index=0;index<obj.getN();index++){
						bool front;
						bool same;
						bool divided;
						front=IsFomFront(obj,index,flip,same,divided);
						if(divided){
							N_DIVIDE++;
							AllBack=false;
							AllFront=false;
						}
						else if(front){
							AllBack=false;
							N_FRONT++;
						}else {
							N_BACK++;
							AllFront=false;
						}
					}
					//不是所有的平面都在后面,也不是都在前面
					if(!AllBack&&!AllFront){
					   cout<<"找到了这样的平面";
					   found=true;
					}
					else{
					   cout<<"没有找到!";
					   found=false;
					}
					cout<<"在它前面的三角形个数为"<<N_FRONT<<endl;
	                cout<<"在它后面的三角形个数为"<<N_BACK<<endl;
					cout<<"被它分割的三角形个数为"<<N_DIVIDE<<endl;
					//说明需要可以找到这样的分割面
					//found=true;			
					pinggu_value[flip]=fabs(N_FRONT-N_BACK)+N_DIVIDE;
					cout<<"评估值为"<<pinggu_value[flip]<<endl;
					if(!IsInit){
						theOpTriagl=flip;
						theOptimizedValue=pinggu_value[flip];
						IsInit=true;
					}
					//没有初始化并且小于目前的评估值
					else if(pinggu_value[flip]<theOptimizedValue){ 
							theOpTriagl=flip;
							theOptimizedValue=pinggu_value[flip];
					}
					cout<<"评估结果为:"<<endl;
					cout<<"树深为"<<endl;
					cout<<TreeDepth<<endl;
					   cout<<"要检测的三角集合为:"<<endl;
			   outPutSanJiaos(obj.getTriangles(),obj.getN());
					if(AllBack){
					cout<<"它在所有平面的后面"<<endl;
					}
					else if(AllFront
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值