⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 contourtracer.cpp

📁 二维规则网格数据的等值线追踪
💻 CPP
📖 第 1 页 / 共 3 页
字号:
		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 + -