📄 contourtracer.cpp
字号:
if( ySide[i-1][j] > 0 )
HandlingAfterNextPointFounded(i-1,j,FALSE);
else
HandlingAfterNextPointFounded(i-1,j+1,FALSE);
}
else if( ySide[i-1][j] == ySide[i-1][j+1] )
{
if( ySide[i-1][j] < 0 /*即ySide[i-1][j] == ySide[i-1][j+1] ==-2*/)
{
HandlingAfterNextPointFounded(i-1,j,TRUE);//下一点在对面的横边上
}
else
{
//注意:这里需要重新计算xSide[i][j],因为在上一次已经被置为-2.0
float xSideIJ = ( m_valueTracing - m_ppGridData[i][j] ) / ( m_ppGridData[i][j+1] - m_ppGridData[i][j] );
if( xSideIJ <= 0.5f )
{
HandlingAfterNextPointFounded(i-1,j,FALSE);
}
else
{
HandlingAfterNextPointFounded(i-1,j+1,FALSE);
}
}
}
else if( ySide[i-1][j] > ySide[i-1][j+1] )
{
if( ySide[i-1][j+1] > 0 )
HandlingAfterNextPointFounded(i-1,j+1,FALSE);
else
HandlingAfterNextPointFounded(i-1,j,FALSE);
}
}
//由右向左
void CContourTracer::FromRight2LeftTracing()
{
/*
横边(i+1,j-1)
xSide[i+1][j-1]
∣
∣
(i+1,j-1) ↓ (i+1,j)
|-----------|
| |
纵边(i,j-1)--→ | ·←----等前等值点(P2)
ySide[i][j-1] | |
| |
|-----------|
(i,j-1) ↑ (i,j)
∣
横边(i,j-1)
xSide[i][j-1]
*/
ASSERT( CurrentPoint.bHorV == FALSE );
int i = CurrentPoint.i;
int j = CurrentPoint.j;
if( IsHavingPoint(xSide[i][j-1]) && IsHavingPoint(xSide[i+1][j-1]) )
{
if( xSide[i][j-1] < xSide[i+1][j-1] )
{
HandlingAfterNextPointFounded(i,j-1,TRUE);//在横边(i,j-1)上
}
else if( xSide[i][j] == xSide[i+1][j-1] )
{
//注意:这里需要重新计算ySide[i][j],因为在上一次已经被置为-2.0
float ySideIJ = ( m_valueTracing - m_ppGridData[i][j]) / ( m_ppGridData[i+1][j] - m_ppGridData[i][j] );
if( /*ySide[i][j]*/ ySideIJ <= 0.5f )
{
HandlingAfterNextPointFounded(i,j-1,TRUE);//在横边(i,j-1)上
}
else
{
HandlingAfterNextPointFounded(i+1,j-1,TRUE);//在横边(i+1,j-1)上
}
}
else
{
HandlingAfterNextPointFounded(i+1,j-1,TRUE);//在横边(i+1,j-1)上
}
}
else
{
if( IsHavingPoint(xSide[i][j-1]) )
{
HandlingAfterNextPointFounded(i,j-1,TRUE);//在横边(i,j-1)上
}
else if( IsHavingPoint(xSide[i+1][j-1]) )
{
HandlingAfterNextPointFounded(i+1,j-1,TRUE);//在横边(i+1,j-1)上
}
else if( IsHavingPoint(ySide[i][j-1]) )
{//两横边上都没有
HandlingAfterNextPointFounded(i,j-1,FALSE);//在纵边(i,j-1)上
}
else
{//三边上都没有
ASSERT(FALSE);
}
}
}
//由右向左(第二版本)
void CContourTracer::FromRight2LeftTracingV2()
{/*
横边(i+1,j-1)
xSide[i+1][j-1]
∣
(i+1,j-1) ↓ (i+1,j)
|-----------|
| |
纵边(i,j-1)--→ | ·←----等前等值点(P2)
ySide[i][j-1] | |
| |
|-----------|
(i,j-1) ↑ (i,j)
∣
横边(i,j-1)
xSide[i][j-1]
*/
ASSERT( CurrentPoint.bHorV == FALSE );
int i = CurrentPoint.i;
int j = CurrentPoint.j;
if( xSide[i][j-1] < xSide[i+1][j-1] )
{
if( xSide[i][j-1] > 0 )
HandlingAfterNextPointFounded(i,j-1,TRUE);
else
HandlingAfterNextPointFounded(i+1,j-1,TRUE);
}
else if( xSide[i][j-1] == xSide[i+1][j-1] )
{
if( xSide[i][j-1] < 0 /*namely, xSide[i][j-1] == xSide[i+1][j-1] == -2.0f*/ )
{
HandlingAfterNextPointFounded(i,j-1,FALSE);
}
else
{
float ySideIJ = ( m_valueTracing - m_ppGridData[i][j]) / ( m_ppGridData[i+1][j] - m_ppGridData[i][j] );
if( ySideIJ <= 0.5f )
HandlingAfterNextPointFounded(i,j-1,TRUE);
else
HandlingAfterNextPointFounded(i+1,j-1,TRUE);
}
}
else if( xSide[i][j-1] > xSide[i+1][j-1] )
{
if( xSide[i+1][j-1] > 0 )
HandlingAfterNextPointFounded(i+1,j-1,TRUE);
else
HandlingAfterNextPointFounded(i,j-1,TRUE);
}
}
//追踪一条开等值线
void CContourTracer::TracingOneNonClosedContour()
{
CCurve* pCtrLine = new CCurve;
m_pCurveList->AddTail(pCtrLine);
m_currentCurveLine = pCtrLine;
//记录下线头所在边的i,j,横纵边标识
int startPt_i = CurrentPoint.i;
int startPt_j = CurrentPoint.j;
BOOL startPt_bHoriz = CurrentPoint.bHorV;
//验证线头在边界上
ASSERT( startPt_i == 0 || /*线头在底边界上*/
startPt_i == m_gridDataInfo.rows-1 || /*线头在上边界上*/
startPt_j == 0 || /*线头在左边界上*/
startPt_j == m_gridDataInfo.cols-1 /*线头在右边界上*/
);
CalcAndSaveOnePointCoord(startPt_i,startPt_j,startPt_bHoriz,CurrentPoint.x,CurrentPoint.y); //计算出线头的坐标并保存
if( startPt_bHoriz )
{
xSide[startPt_i][startPt_j] = -2.0f;
}
else
{
ySide[startPt_i][startPt_j] = -2.0f;
}
TracingNextPoint(); //追踪出NextPoint
PreviousPoint = CurrentPoint;
CurrentPoint = NextPoint;
int cols = m_gridDataInfo.cols;
int rows = m_gridDataInfo.rows;
//遇到网格边界就结束追踪
//------2004/03/09修改------------------
//为了不让浮点数计算的误差引起追踪结束条件的判断失误,
//我们不能用『CurrentPoint.y <= yMin』来判断是否遇到底边框,
// 也不能用『CurrentPoint.x <= xMin』来判断是否遇到左边框
BOOL bIsFinish = (CurrentPoint.i == 0 && CurrentPoint.bHorV == TRUE ) || /*遇到底边界,(注:不能仅仅用CurrentPoint.i == 0判断)*/
(CurrentPoint.i == rows-1) || /*遇到上边界*/
(CurrentPoint.j == 0 && CurrentPoint.bHorV == FALSE ) || /*遇到左边界,(注:不能仅仅用CurrentPoint.j == 0判断)*/
(CurrentPoint.j == cols-1) ; /*遇到右边界*/
while( !bIsFinish )
{
TracingNextPoint();
PreviousPoint = CurrentPoint;
CurrentPoint = NextPoint;
bIsFinish = (CurrentPoint.i == 0 && CurrentPoint.bHorV == TRUE ) ||
(CurrentPoint.i == rows-1) ||
(CurrentPoint.j == 0 && CurrentPoint.bHorV == FALSE ) ||
(CurrentPoint.j == cols-1) ;
}
}
//追踪开曲线
void CContourTracer::TracingNonClosedContour()
{//该函数的关键是找出开曲线的线头,并设置好追踪前进的方向的条件
int i,j;
int cols = m_gridDataInfo.cols;
int rows = m_gridDataInfo.rows;
//1.搜索底边框
for(j=0; j<cols-1; j++)
{
if( IsHavingPoint(xSide[0][j]) )
{
/*按自下向上的前进方向虚设前一点的i,j*/
PreviousPoint.i = -1; // 假设前一点在-1行,这样下一点到当前点的前进方向就是自下向上的
PreviousPoint.j = j;
PreviousPoint.bHorV = TRUE;
CurrentPoint.i = 0; //底边的行号为0,所以设置线头的i为0
CurrentPoint.j = j;
CurrentPoint.bHorV = TRUE; //底边是横边
TracingOneNonClosedContour();
}
}
//2.搜索左边框(左边框在第0列)
for(i=0; i<rows-1; i++)
{
if( IsHavingPoint(ySide[i][0]) )
{
/*按由左向右的前进方向虚设前一点的i,j*/
PreviousPoint.i = i;
PreviousPoint.j = -1; //假设前一点在-1列,使其满足左-->右的前进方向
PreviousPoint.bHorV = FALSE;
CurrentPoint.i = i;
CurrentPoint.j = 0; //左边框在第0列,所以设置线头的j为0
CurrentPoint.bHorV = FALSE;
TracingOneNonClosedContour();
}
}
//3.搜索上边框
float deltX = ( m_gridDataInfo.xMax-m_gridDataInfo.xMin ) / ( m_gridDataInfo.cols-1 );
float curPt_Col_X = m_gridDataInfo.xMin + CurrentPoint.j * deltX; //当前等值点所在边(i,j)的所标识的j列的X坐标
for(j=0; j<cols-1; j++)
{
if( IsHavingPoint(xSide[rows-1][j]) )
{
/*虚设出由上向下追踪的条件
由上向下追踪的条件如下:
1. Not( CurrentPoint.i > PreviousPoint.i )
2. Not( CurrentPoint.j > PreviousPoint.j )
3. CurrentPoint.x > m_gridDataInfo.xMin + CurrentPoint.j * deltX; 即:要求在横边上
*/
PreviousPoint.i = rows-1;
PreviousPoint.j = j;
PreviousPoint.bHorV = TRUE;
CurrentPoint.i = rows-1; //上边框的行号为rows-1
CurrentPoint.j = j;
CurrentPoint.bHorV = TRUE; //使其符合第三个条件
//第三个条件条件不用虚设,只要边上存在就会满足第三个条件,因为上边框是横边
// if( CurrentPoint.x < curPt_Col_X )
// {
// CurrentPoint.x = curPt_Col_X + 1; //为了保证让其满足第3个条件
// }
TracingOneNonClosedContour();
}
}
//4.搜索右边框(在第cols-1列,注意列号是从0开始计数的)
for(i=0; i<rows-1; i++)
{
if( IsHavingPoint(ySide[i][cols-1]) )
{
/*虚设出由右向左追踪的条件
由右向左追踪的条件如下:
1. Not( CurrentPoint.i > PreviousPoint.i )
2. Not( CurrentPoint.j > PreviousPoint.j )
3. Not( CurrentPoint.x > m_gridDataInfo.xMin + CurrentPoint.j * deltX ); 要求在纵边上
*/
PreviousPoint.i = i;
PreviousPoint.j = cols-1;
PreviousPoint.bHorV = FALSE;
CurrentPoint.i = i;
CurrentPoint.j = cols-1; //右边框在第cols-1列
CurrentPoint.bHorV = FALSE; //使其符合第三个条件
// //虚设出第三个条件
// CurrentPoint.x = curPt_Col_X - 1;//减去1,使之比curPt_Col_X小
TracingOneNonClosedContour();
}
}
}
void CContourTracer::TracingClosedContour()
{
int cols = m_gridDataInfo.cols;
int rows = m_gridDataInfo.rows;
//搜索所有的除了边框外的纵边,从左到右搜索每一列上的纵边,对于一列,从下到上搜索
for(int j=1; j<cols-1; j++) //j从1开始
for(int i=0; i<rows-1; i++) //i从0开始
{
if( IsHavingPoint(ySide[i][j]))
{
TracingOneClosedContour(i,j);
}
}
}
//从纵边开始追踪一条封闭等值线(注:是从纵边开始搜索)
void CContourTracer::TracingOneClosedContour(int startPt_i, int startPt_j)
{//参数i,j是该闭曲线的第一个等值点的i,j
CCurve* pCtrLine = new CCurve;
m_pCurveList->AddTail(pCtrLine);
m_currentCurveLine = pCtrLine;
//虚设前一等值点的i,j,让其满足从左向右追踪的条件
PreviousPoint.i = startPt_i;
PreviousPoint.j = 0;
PreviousPoint.bHorV = FALSE;
CurrentPoint.i = startPt_i;
CurrentPoint.j = startPt_j;
CurrentPoint.bHorV = FALSE; //是FALSE,因为是在纵边上
// float startPt_x;
// float startPt_y;
CalcAndSaveOnePointCoord(startPt_i,startPt_j,FALSE/*线头在纵边上*/,CurrentPoint.x,CurrentPoint.y);
TracingNextPoint();
PreviousPoint = CurrentPoint;
CurrentPoint = NextPoint;
BOOL bColsed = FALSE;
while(!bColsed)
{
TracingNextPoint();
PreviousPoint = CurrentPoint;
CurrentPoint = NextPoint;
//------2004/03/09修改------------------
//用等值点所在边的标识i,j来判断曲线是否封闭,不用x、y坐标来比较,因为浮点数计算会出现误差
// bColsed = (CurrentPoint.x == startPt_x) && (CurrentPoint.y == startPt_y);
bColsed = ( CurrentPoint.i == startPt_i ) &&
( CurrentPoint.j == startPt_j ) &&
( CurrentPoint.bHorV == FALSE );
}
ySide[startPt_i][startPt_j] = -2.0f; //已经追踪过
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -