#include "StdAfx.h"
#include ".\spacepartition.h"
CSpacePartition::CSpacePartition(void)
: pNum(0)
, lNum(0)
, cNum(0)
, radius(1.0)
, objRadius(1.0)
, objLevel(0.499)
, iter(128)
, sum(0)
{
}
CSpacePartition::~CSpacePartition(void)
{
}
void CSpacePartition::Initialize()
{
int index , minIndex ;
// 给定平面数目截取最显著的EV事件,性能与obj面片数关系大大减小
index = 0 ;
Real minPlane = -1 ; minIndex = 0 ;
Real* avg1 = new Real[ pNum ];
for (int i = 0 ; i < pNum ; i ++)
avg1[ i ] = -1 ;
for( int i = 0; i < pObject->numOfFaces; i++ )
{
int ip1 = pObject->pFaces[i].vertIndex[0];
int ip2 = pObject->pFaces[i].vertIndex[1];
int ip3 = pObject->pFaces[i].vertIndex[2];
CVector3 p1 = pObject->pVerts[ ip1 ];
CVector3 p2 = pObject->pVerts[ ip2 ];
CVector3 p3 = pObject->pVerts[ ip3 ];
//计算这三个边的长短和周长
Real mag_p12, mag_p23, mag_p13, avg_mag;
mag_p12 = CGeometry::Mag(CGeometry::Vector(p1,p2));
mag_p23 = CGeometry::Mag(CGeometry::Vector(p2,p3));
mag_p13 = CGeometry::Mag(CGeometry::Vector(p1,p3));
avg_mag = ( mag_p12 + mag_p23 + mag_p13 ) / 3;
if ( avg_mag > minPlane ) //有限分辨率的情况,如果三角形的三边长太小,则不予考虑
{
// 计算平面数据
CVector3 n = CGeometry::plane_normal( p1 , p2 , p3 );
Real a = - p1.dotProduct ( n ) ;
// 是否与先前的平面重合,若重合则舍弃
bool flag = false ;
for (int k = 0 ; k < index && !flag; k ++)
{
Real dot = n.dotProduct( p[k].normal );
if ( abs( dot ) > 1 - CGeometry::EPS )
{
if ( ( dot > 0 ) && ( abs( p[k].intercept - a ) < CGeometry::EPS ) )
flag = true ;
else if ( ( dot < 0 ) && ( abs( p[k].intercept + a ) < CGeometry::EPS ) )
flag = true ;
}
}
// 不重合就加入数据库
if ( flag == false )
{
// 加入数据库
p[ minIndex ].normal = n ;
p[ minIndex ].intercept = a ;
avg1[ minIndex ] = avg_mag ;
if ( index < pNum )
index ++;
// 寻找最小的平面
minPlane = 1e10 ; minIndex = -1 ;
for (int j = 0 ; j < pNum ; j ++ )
{
if ( avg1[ j ] < minPlane )
{
minPlane = avg1[ j ];
minIndex = j ;
}
}
}
}
}
// 取给定数目的最长直线
// 设置直线数目
lNum = 3;
index = 0 ;
Real minLine = -1 ; minIndex = 0 ;
Real* avg2 = new Real[ lNum ];
for (int i = 0 ; i < lNum ; i ++)
avg2[ i ] = -1 ;
Real mag[3];
line edge[3];
for( int i = 0; i < pObject->numOfFaces; i++ )
{
int ip1 = pObject->pFaces[i].vertIndex[0];
int ip2 = pObject->pFaces[i].vertIndex[1];
int ip3 = pObject->pFaces[i].vertIndex[2];
CVector3 p1 = pObject->pVerts[ ip1 ];
CVector3 p2 = pObject->pVerts[ ip2 ];
CVector3 p3 = pObject->pVerts[ ip3 ];
//计算这三个边的长短
mag[0] = CGeometry::Mag(CGeometry::Vector(p1,p2)); edge[0].a = p1 ; edge[0].b = p2 ;
mag[1] = CGeometry::Mag(CGeometry::Vector(p2,p3)); edge[1].a = p2 ; edge[1].b = p3 ;
mag[2] = CGeometry::Mag(CGeometry::Vector(p1,p3)); edge[2].a = p3 ; edge[2].b = p1 ;
for (int j = 0; j < 3 ; j ++)
{
if ( mag[j] > minLine ) //有限分辨率的情况,如果三角形的三边长太小,则不予考虑
{
// 是否与先前的直线重合,若重合则舍弃
bool flag = false ;
for (int k = 0 ; k < index && !flag; k ++)
{
if ( CGeometry::Mag(CGeometry::Vector(l[k].a,edge[j].a)) < CGeometry::EPS && CGeometry::Mag(CGeometry::Vector(l[k].b,edge[j].b)) < CGeometry::EPS )
flag = true ;
else if ( CGeometry::Mag(CGeometry::Vector(l[k].b,edge[j].a)) < CGeometry::EPS && CGeometry::Mag(CGeometry::Vector(l[k].a,edge[j].b)) < CGeometry::EPS )
flag = true ;
}
// 不重合就加入数据库
if ( flag == false )
{
// 加入数据库
l[ minIndex ].a = edge[j].a ;
l[ minIndex ].b = edge[j].b ;
avg2[ minIndex ] = mag[j] ;
if ( index < lNum )
index ++;
// 寻找最短的直线
minLine = 1e10 ; minIndex = -1 ;
for (int k = 0 ; k < lNum ; k ++ )
{
if ( avg2[ k ] < minLine )
{
minLine = avg2[ k ];
minIndex = k ;
}
}
}
}
}
}
// 设置EEE事件
// 释放空间
delete[] avg1;
delete[] avg2;
// 清空链表
vecPoint.clear ();
vecCoord.clear ();
intSpace.clear ();
intStart.clear ();
intNum.clear ();
areaList.clear ();
intAdj.clear ();
// 配置参数
int areaNum = 1;
for (int i = 0 ; i < pNum + cNum; i ++)
areaNum *= 2;
for (int i = 0 ; i < areaNum; i ++)
{
intStart.push_back(0);
intNum.push_back(0);
}
pExp = areaNum ;
return ;
}
void CSpacePartition::SetIter( int ext_iter )
{
iter = ext_iter ;
return ;
}
void CSpacePartition::SetObjRadius( Real ext_obj )
{
objRadius = ext_obj ;
return ;
}
void CSpacePartition::SetModel( t3DModel* ext_pModel )
{
pModel = ext_pModel ;
pObject = & ext_pModel->pObject[0] ;
return ;
}
void CSpacePartition::SetRadius( Real extRadius )
{
radius = extRadius ;
return ;
}
void CSpacePartition::SetBar( CProgressCtrl* pBar )
{
pProgressBar = pBar ;
return ;
}
void CSpacePartition::SetEVNum( int num )
{
pNum = num ;
return ;
}
// 进行划分
void CSpacePartition::Partition()
{
int i , j , k , l ;
CVector3 vec;
CVector2 cod;
Real phi , theta ;
sum = 0 ;
pProgressBar->SetRange ( 0 , iter * iter );
pProgressBar->SetPos ( 0 );
for ( i = 0 ; i < iter ; i ++)
{
for ( j = 0 ; j < iter ; j ++)
{
// 算视点
cod.x = i ;
cod.y = j ;
phi = PI * ( 2 * i + 1 ) / ( 2 * iter );
theta = PI * ( 2 * j + 1 ) / iter ;
vec.x = radius * sin ( phi ) * cos ( theta );
vec.y = radius * sin ( phi ) * sin ( theta );
vec.z = radius * cos ( phi ) ;
// 开始归到区域中
int area , exp ;
exp = pExp; // 阶乘
area = 0; // 区域号
for ( k = 0 ; k < pNum ; k ++)
{
exp /= 2 ;
area += CalEV( vec , p[k] ) * exp ;
}
for ( k = 0 ; k < cNum ; k ++)
{
exp /= 2 ;
area += CalEEE( vec , c[k] ) * exp ;
}
// 新区域
if ( intNum.at ( area ) == 0 )
sum ++;
intNum.at ( area ) ++ ;
intSpace.push_back ( area );
vecPoint.insert ( vecPoint.begin() + intStart.at( area ) , vec );
vecCoord.insert ( vecCoord.begin() + intStart.at( area ) , cod );
vector<int>::iterator intIter = intStart.begin() + area + 1;
for ( l = area + 1 ; l < pExp ; l ++ )
{
(* intIter) ++;
intIter ++;
}
pProgressBar->SetPos( i * iter + j );
}
}
// 先占邻接矩阵的空间
for ( i = 0 ; i < sum * sum ; i ++ )
intAdj.push_back( 1 );
int index = 0;
pProgressBar->SetPos( index );
vector<CVector3>::iterator vecIter1 , vecIter2 ;
vector<CVector2>::iterator codIter ;
vector<int>::iterator numIter, sttIter;
numIter = intNum.begin();
sttIter = intStart.begin();
for ( i = 0 ; i < pExp ; i ++)
{
if ( * numIter > 0 )
{
area areaTemp ;
areaTemp.int_Num = * numIter;
areaTemp.int_Start = * sttIter;
areaTemp.int_Label = i ;
// 找形心,根据不同标准,现用的是hausdorff距离
Real dotmax = -1e10;
CVector3 vecmax;
CVector2 codmax;
vecIter1 = vecPoint.begin() + * sttIter ;
codIter = vecCoord.begin() + * sttIter ;
for ( j = 0 ; j < * numIter ; j ++)
{
CVector3 a = * vecIter1 ;
CVector2 b = * codIter ;
CVector3 c ;
Real dotsum = 1e10;
vecIter2 = vecPoint.begin() + * sttIter ;
for ( k = 0 ; k < * numIter ; k ++)
{
c = * vecIter2 ;
Real temp = a.dotProduct( c );
// dotsum += temp; // 以点积之和最大为标准
if ( temp < dotsum )
{
dotsum = temp;
if ( temp < dotmax )
break;
}
vecIter2 ++;
}
if ( dotsum > dotmax )
{
vecmax = a ;
codmax = b ;
dotmax = dotsum ;
}
index ++;
pProgressBar->SetPos( index );
vecIter1 ++;
codIter ++;
}
areaTemp.
- 1
- 2
前往页