www.pudn.com > Poly.rar > SortPoly.cpp
// SortPoly.cpp: implementation of the CSortPoly class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "PolyTop.h"
#include "SortPoly.h"
#include "math.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
const float PI = acos(-1);
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CSortPoly::CSortPoly()
{
InitData();
}
CSortPoly::~CSortPoly()
{
}
/**********************************************************************************
*函数名称: ReadFile
*函数功能: 用来求解由点和线围成的多边形
*参数信息: filepath所读取文件的路径名称
*返回值: 成功:true;失败:false
*作者:
*完成时间: 2006.12.17
***********************************************************************************/
bool CSortPoly::ReadFile(CString filepath)
{
FILE* fp = NULL;
fp = fopen( filepath, "r" );
if ( fp == NULL )
{
AfxMessageBox( "Error Opening File!" );
return false;
}
fscanf( fp, "%d", &m_nNumberOfPoints );
Point pt;
for ( int i = 0; i < m_nNumberOfPoints; ++i )
{
fscanf( fp, "%d %d %d", &(pt.num), &(pt.x), &(pt.y) );
m_vPoints.push_back( pt );
}
fscanf( fp, "%d", &m_nNumberOfLines );
Line ln;
for ( i = 0; i < m_nNumberOfLines; ++i )
{
fscanf( fp, "%d %d %d", &(ln.num), &(ln.start), &(ln.end) );
m_vLines.push_back( ln );
}
int num;
while ( fscanf( fp, "%d", &num) != EOF )
{
m_sOuterPoints.push_back( num );
}
fclose( fp );
CalUsedTimesOfPoints();
return true;
}
/**********************************************************************************
*函数名称: CalUsedTimesOfPoints
*函数功能: 计算与某个点相连的点的所有信息,结果保存在m_vConnectedPoints中。
*参数信息: 无
*返回值: 无
*作者:
*完成时间: 2006.12.17
***********************************************************************************/
void CSortPoly::CalUsedTimesOfPoints()
{
int *num = NULL;
num = new int [ m_nNumberOfPoints ];
memset( num, 0, sizeof( int ) * m_nNumberOfPoints );
lineList::iterator iter = m_vLines.begin();
for ( ; iter < m_vLines.end(); ++iter )
{
num[ (*iter).start - 1]++;
num[ (*iter).end - 1 ]++;
}
ConnectedPoints ut;
for ( int i = 0; i < m_nNumberOfPoints; ++i )
{
ut.num = i+1;
intList templist;
templist.clear();
for ( iter = m_vLines.begin(); iter != m_vLines.end(); ++iter )
{
if ( (*iter).start == ( i + 1 ) )
templist.push_back( (*iter).end );
if ( (*iter).end == ( i + 1 ) )
templist.push_back( (*iter).start );
}
ut.m_sPoints = templist;
m_vConnectedPoints.push_back( ut );
}
delete num;
}
/**********************************************************************************
*函数名称: AngleOfTwoLines
*函数功能: 计算两条直线顺时针方向的夹角
*参数信息: start:起始点;inf:拐点;end:终止点
*返回值: 两条直线之间的夹角(弧度);10.0f则表示计算错误
*作者:
*完成时间: 2006.12.17
***********************************************************************************/
double CSortPoly::AngleOfTwoLines(Point start, Point inf, Point end)
{
double aa = ( start.x - inf.x ) * ( start.x - inf.x ) + ( start.y - inf.y ) * ( start.y - inf.y );
double bb = ( inf.x - end.x ) * ( inf.x - end.x ) + ( inf.y - end.y ) * ( inf.y - end.y );
double cc = ( start.x - end.x ) * ( start.x - end.x ) + ( start.y - end.y ) * ( start.y - end.y );
double cosValue = ( aa + bb - cc ) / ( 2 * sqrt( aa ) * sqrt( bb ) );
double angle = acos( cosValue );
double coeff1 = 0.0f, coeff2 = 0.0f;
if ( start.y != inf.y )
{
coeff1 = ( double )( inf.x - start.x ) / ( double )( start.y - inf.y );
coeff2 = ( double )( start.x * inf.y - inf.x * start.y ) / ( double )( start.y - inf.y );
if ( start.y > inf.y )
{
if ( end.x + coeff1 * end.y + coeff2 <= 0 )
{
return angle;
}
else
{
return ( PI * 2 - angle );
}
}
else if ( start.y < inf.y )
{
if ( end.x + coeff1 * end.y + coeff2 <= 0 )
{
return ( PI * 2 - angle );
}
else
{
return angle;
}
}
}
else if ( start.y == inf.y )
{
if ( inf.x > start.x )
{
if ( end.y < start.y )
{
return angle;
}
else
{
return ( PI * 2 - angle );
}
}
else if ( inf.x < start.x )
{
if ( end.y < start.y )
{
return ( PI * 2 - angle );
}
else
{
return angle;
}
}
}
return 10.0f;
}
/**********************************************************************************
*函数名称: Recursion
*函数功能: 计算与当前直线顺时针方向夹角最小的下一个点
*参数信息: num1:直线起始点;num2:直线终止点
*返回值: true:表示没有下一个点,多边形封闭;false:有下个点
*作者:
*完成时间: 2006.12.17
***********************************************************************************/
bool CSortPoly::Recursion(int num1, int num2)
{
Point pt1 = m_vPoints[ num1 - 1 ];
Point pt2 = m_vPoints[ num2 - 1 ];
int num3;
intList::iterator iter3 = m_vConnectedPoints[ num2 - 1 ].m_sPoints.begin();
intList::iterator iter3_end = m_vConnectedPoints[ num2 -1 ].m_sPoints.end();
double maxAngle = 2 * PI + 1;
for ( ; iter3 != iter3_end; ++iter3 )
{
Point pt3;
if ( *iter3 == m_nNum1 )
{
continue;
}
pt3.num = *iter3;
pt3.x = m_vPoints[ (*iter3) - 1 ].x;
pt3.y = m_vPoints[ (*iter3) - 1 ].y;
double angle = AngleOfTwoLines( pt1, pt2, pt3 );
if ( angle < maxAngle )
{
maxAngle = angle;
num3 = *iter3;
}
}
//PrintVectot(m_sResult);
//判断num3点是否在向量中
if ( !IsIn(m_sResult,num3) )
{
m_sResult.push_back( num3 );
m_vResult.push_back( num3 );
m_nNum1 = num2;
m_nNum2 = num3;
return false;
}
else
{
intList::iterator iter4 = m_vResult.begin();
for ( ; iter4 != m_vResult.end(); )
{
if ( num3 == *iter4 )
{
break;
}
else
{
m_vResult.erase( iter4 );
iter4 = m_vResult.begin();
}
}
if ( m_vResult.size() != m_sResult.size() )
{
m_sResult.clear();
iter4 = m_vResult.begin();
for ( ; iter4 != m_vResult.end(); ++iter4 )
{
m_sResult.push_back( *iter4 );
}
}
cpList::iterator iter5 = m_vConnectedPoints.begin();
cpList::iterator iter5_end = m_vConnectedPoints.end();
for ( ; m_bOnePolygon && iter5 != iter5_end; ++iter5 )
{
if ( (*iter5).m_sPoints.size() != 2)
{
m_bOnePolygon = false;
break;
}
else
{
continue;
}
}
if ( m_bOnePolygon )
{
m_sPolygons.push_back( m_sResult );
m_vPolygons.push_back( m_vResult );
m_bOnePolygon = false;
}
else if ( m_sResult != m_sOuterPoints )
{
if ( !IsIn(m_sPolygons,m_sResult) )
{
m_sPolygons.push_back( m_sResult );
m_vPolygons.push_back( m_vResult );
}
}
m_sResult.clear();
m_vResult.clear();
return true;
}
return true;
}
bool CSortPoly::IsIn(intList intlist, int num)
{
intList::iterator it;
for(it=intlist.begin();it!=intlist.end();it++)
{
int tt = *it;
if(tt==num)
return true;
}
return false;
}
bool CSortPoly::IsIn(intIntList int2list, intList intlist)
{
intIntList::iterator it;
for(it=int2list.begin();it!=int2list.end();it++)
{
intList ll = *it;
if(EquelList(ll,intlist))
return true;
}
return false;
}
/**********************************************************************************
*函数名称: SortPolygons
*函数功能: 计算多边形信息,结果保存在m_vPolygons中
*参数信息: 无
*返回值: 无
*作者:
*完成时间: 2006.12.17
***********************************************************************************/
void CSortPoly::SortPolygons()
{
pointList::iterator iter1 = m_vPoints.begin();
intIntList::iterator itpoly;
m_sResult.clear();
m_vResult.clear();
for ( ; iter1 != m_vPoints.end(); ++iter1 )
{
m_nNum1 = (*iter1).num;
intList::iterator iter2 = m_vConnectedPoints[ m_nNum1 - 1 ].m_sPoints.begin();
intList::iterator iter2_end = m_vConnectedPoints[ m_nNum1 - 1 ].m_sPoints.end();
for ( ; iter2 != iter2_end; ++iter2 )
{
m_nNum2 = *iter2;
m_sResult.push_back( m_nNum1 );
m_vResult.push_back( m_nNum1 );
m_sResult.push_back( m_nNum2 );
m_vResult.push_back( m_nNum2 );
while ( !Recursion( m_nNum1, m_nNum2 ) )
{
}
m_nNum1 = (*iter1).num;
}
}
PutLineInPolyS(m_vPolygons);
//出去边界多边形
for(itpoly=m_vPolygons.begin();itpoly!=m_vPolygons.end();itpoly++)
{
intList poly = *itpoly;
if(EquelList(poly,m_sOuterPoints))
{
m_vPolygons.erase(itpoly);
break;
}
}
m_flag = 1;
}
void CSortPoly::CheckResult()
{
int num = 0;
char str1[500],str2[500];
intIntList::iterator iter = m_vPolygons.begin();
intList::iterator iter2;
for( ; iter != m_vPolygons.end(); ++iter )
{
num++;
intList ptlist = *iter;
for( iter2 = ptlist.begin(); iter2 != ptlist.end();iter2 ++)
{
int pt = *iter2;
sprintf(str1,"%d",pt);
AfxMessageBox(str1);
}
sprintf(str2,"num :%d",num);
AfxMessageBox(str2);
}
}
void CSortPoly::PrintVectot(intList ptlist)
{
FILE* fp;
intList::iterator it;
if((fp = fopen("C:\\temp\\vectorint.txt","w"))==0) return;
for(it=ptlist.begin();it!=ptlist.end();it++)
{
int aa = *it;
fprintf(fp,"%d\n",aa);
}
fclose(fp);
}
//判断两容器是否含有相同的元素
bool CSortPoly::EquelList(intList ptlist1, intList ptlist2)
{
if(ptlist1.size()!=ptlist2.size())
return false;
intList::iterator it1;
intList::iterator it2;
for(it1=ptlist1.begin();it1!=ptlist1.end();it1++)
{
int pt1 = *it1;
int flag = 0;
for(it2=ptlist2.begin();it2!=ptlist2.end();it2++)
{
int pt2 = *it2;
if(pt2==pt1)
{
flag = 1;
}
}
if(!flag)
return false;
}
return true;
}
pointList CSortPoly::GetPtList()
{
return m_vPoints;
}
intIntList CSortPoly::GetPolyList()
{
return m_vPolygons;
}
Point CSortPoly::GetPointByNum(int num)
{
Point err;
err.num = -1;
err.x = err.y = 0;
pointList::iterator it;
for(it = m_vPoints.begin();it!=m_vPoints.end();it++)
{
Point pt = *it;
if(pt.num==num)
return pt;
}
return err;
}
void CSortPoly::InitData()
{
m_nNumberOfPoints = 0;
m_nNumberOfLines = 0;
m_bOnePolygon = true;
m_vPoints.clear();
m_vLines.clear();
m_vConnectedPoints.clear();
m_sPolygons.clear();
m_sResult.clear();
m_vResult.clear();
m_sOuterPoints.clear();
m_vPolygons.clear();
m_flag = 0;
}
bool CSortPoly::ReadMlFile(CString fileName)
{
FILE* fp;
char ss[20];
int i,j,lNum,pNum;
listMatchPoint mplist;
listMatchPoint::iterator it;
lineList lineS;
if((fp=fopen(fileName,"r"))==0) return false;
fscanf(fp,"%s",ss);
if(strcmp(ss,"box:")!=0)
{
AfxMessageBox("文件格式不正确!");
return false;
}
//读入图幅大小
fscanf(fp,"%d%d",&m_size.cx,&m_size.cy);
//读入折线点
fscanf(fp,"%s",ss);
if(strcmp(ss,"Point:")!=0)
{
AfxMessageBox("文件格式不正确!");
return false;
}
fscanf(fp,"%d",&pNum);
for(i=0;i=2)
comPt.push_back(code);
}
//将所有交叉的折线段打断,形成只相连不交叉的折线段
DisLine(lineS,comPt);
//判断边界点,形成边界折线
LineAroundBorder(lineS,width,height,borderPt) ;
//数据转换成存储格式
m_vLines = lineS;
m_nNumberOfLines = m_vLines.size();
return true;
}
/**********************************************************************************
*函数名称: DisLine
*函数功能: 将所有交叉的折线段打断,形成只相连不交叉的折线段
*参数信息: lineS 保存折线段 ptlist折线段公共点
*返回值: 无
***********************************************************************************/
bool CSortPoly::DisLine(lineList& lineS,intList ptlist)
{
int i,vex,ewr,nSum; //vex存储公共节点
lineList tempList; //中间变量
Line tempLine;
lineList::iterator itl;
intList::iterator itp;
if(lineS.empty()||ptlist.empty()) return false;
for(itl=lineS.begin();itl!=lineS.end();itl++)
{
//找到每个弧段内的公共节点
Line ll = *itl;
nSum = ll.ptlist.size();
for(i=0;i0 ; j--)
{
for(i=0;iptlist[i+1].left_y)
{
tempPoint = ptlist[i];
ptlist[i] = ptlist[i+1];
ptlist[i+1] = tempPoint;
}
}
else
{
if(ptlist[i].left_yptlist[i+1].left_x)
{
tempPoint = ptlist[i];
ptlist[i] = ptlist[i+1];
ptlist[i+1] = tempPoint;
}
}
else
{
if(ptlist[i].left_x=0;i--)
{
int pt = tempLine.ptlist[i];
if(pt==start||pt==end) continue;
extralist.push_back(pt);
}
}
}
return true;
}
//*************************************************************************