www.pudn.com > WaterShed.rar > WaterShedDoc.cpp


// WaterShedDoc.cpp : implementation of the CWaterShedDoc class 
// 
 
#include "stdafx.h" 
#include "WaterShed.h" 
 
#include "WaterShedDoc.h" 
#include  
using namespace std; 
#include "MainFrm.h" 
#include "math.h" 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
#define MAXV 256 
// Coefficient matrix for xyz and rgb spaces 
static const int    XYZ[3][3] = { { 4125, 3576, 1804 }, 
{ 2125, 7154,  721 }, 
{  193, 1192, 9502 } }; 
static const double  RGB[3][3] = {  
	{ (float)3.2405, (float)-1.5371, (float)-0.4985 }, 
	{(float)-0.9693,  (float)1.8760,  (float)0.0416 }, 
	{ (float)0.0556, (float)-0.2040,  (float)1.0573 } }; 
	 
	// Constants for LUV transformation  
	static const float     Xn = (float)0.9505; 
	static const float     Yn = (float)1.0; 
	static const float     Zn = (float)1.0888; 
	static const float     Un_prime = (float)0.1978; 
	static const float     Vn_prime = (float)0.4683; 
	static const float     Lt = (float)0.008856; 
 
 
///////////////////////////////////////////////////////////////////////////// 
// CWaterShedDoc 
 
IMPLEMENT_DYNCREATE(CWaterShedDoc, CDocument) 
 
BEGIN_MESSAGE_MAP(CWaterShedDoc, CDocument) 
	//{{AFX_MSG_MAP(CWaterShedDoc) 
	ON_COMMAND(ID_WATERSHED, OnWatershed) 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CWaterShedDoc construction/destruction 
 
CWaterShedDoc::CWaterShedDoc() 
{ 
	// TODO: add one-time construction code here 
	imageData = NULL; 
	isImageLoaded=FALSE; 
	imageName = ""; 
	myImageObject = NULL; 
	luvData = NULL; 
} 
 
CWaterShedDoc::~CWaterShedDoc() 
{ 
	if (imageData!=NULL) 
	{ 
		delete [] imageData; 
		imageData = NULL; 
	} 
	if (luvData!=NULL) 
	{ 
		delete [] luvData; 
		luvData = NULL; 
	} 
	 
	if (myImageObject!=NULL) 
	{ 
		delete myImageObject; 
		myImageObject = NULL; 
	} 
} 
 
BOOL CWaterShedDoc::OnNewDocument() 
{ 
	if (!CDocument::OnNewDocument()) 
		return FALSE; 
 
	// TODO: add reinitialization code here 
	// (SDI documents will reuse this document) 
 
	return TRUE; 
} 
 
 
 
///////////////////////////////////////////////////////////////////////////// 
// CWaterShedDoc serialization 
 
void CWaterShedDoc::Serialize(CArchive& ar) 
{ 
	if (ar.IsStoring()) 
	{ 
		// TODO: add storing code here 
	} 
	else 
	{ 
		// TODO: add loading code here 
	} 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// CWaterShedDoc diagnostics 
 
#ifdef _DEBUG 
void CWaterShedDoc::AssertValid() const 
{ 
	CDocument::AssertValid(); 
} 
 
void CWaterShedDoc::Dump(CDumpContext& dc) const 
{ 
	CDocument::Dump(dc); 
} 
#endif //_DEBUG 
 
///////////////////////////////////////////////////////////////////////////// 
// CWaterShedDoc commands 
 
BOOL CWaterShedDoc::OnOpenDocument(LPCTSTR lpszPathName)  
{ 
// 	if (!CDocument::OnOpenDocument(lpszPathName)) 
// 		return FALSE; 
	 
	// TODO: Add your specialized creation code here 
	CString strPathName = lpszPathName; 
	imageName = strPathName; 
	while ( imageName.Find("\\", 0)>=0 && imageName!="")  
	{ 
		imageName.Delete(0, 1); 
	}  
	 
	myImageObject = new CImageObject(strPathName); 
	if(myImageObject==NULL) 
	{ 
		AfxMessageBox("Could not create image class!"); 
		return FALSE; 
	} 
	isImageLoaded = TRUE; 
	 
	//以下将RGB数据存入数组以备处理; 
	LONG width = myImageObject->GetWidth(); 
	LONG height = myImageObject->GetHeight(); 
	dataLen = width*height*3; 
	if ( imageData != NULL ) 
	{ 
		delete [] imageData; 
		imageData = NULL; 
	} 
	imageData = new BYTE[width*height*3]; 
	imageWidth = width; 
	imageHeight = height; 
	myImageObject->LoadDIBToBuf(imageData); 
	 
	   //以下保存LUV数据; 
	if ( luvData != NULL ) 
	{ 
		delete [] luvData; 
		luvData = NULL; 
	} 
	luvData = new MyLUV[width*height]; 
	RgbtoLuvPcm(imageData, width, height, luvData); 
 
	return TRUE; 
} 
 
void CWaterShedDoc::OnWatershed()  
{ 
	// TODO: Add your command handler code here 
 
	BeginWaitCursor(); 
 
	LONG imagelen = imageWidth*imageHeight; 
	FLOAT* deltar = new FLOAT[imagelen];//梯度模数组; 
	FLOAT* deltasita = new FLOAT[imagelen];//梯度角度数组; 
	INT*   flag = new INT[imagelen];//各点标识数组; 
	INT*  gradientfre = new INT[256];//图像中各点梯度值频率; 
	INT*  gradientadd = new INT[257];//各梯度起终位置; 
	memset( gradientfre, 0, 256*sizeof(INT)); 
	memset( gradientadd, 0, 257*sizeof(INT)); 
 
	//首先得到各点梯度; 
    GetGradient(imageData, imageWidth, imageHeight 
		, deltar, deltasita); 
 
	LONG temptime1 = GetTickCount();//初始时刻; 
	//以下统计各梯度频率; 
	MyImageGraPt*  graposarr = new MyImageGraPt[imagelen]; 
	LONG xstart, imagepos, deltapos; 
	xstart = imagepos = deltapos = 0; 
	for (INT y=0; y255) 
			{ 
				deltar[deltapos] = 255; 
			} 
			INT tempi = (INT)(deltar[deltapos]); 
			gradientfre[tempi] ++;//灰度值频率; 
		} 
	} 
 
	//统计各梯度的累加概率; 
	INT added = 0; 
	gradientadd[0] = 0;//第一个起始位置为0; 
	for (INT ii=1; ii<256; ii++) 
	{ 
		added += gradientfre[ii-1]; 
		gradientadd[ii] = added; 
	} 
	gradientadd[256] = imagelen;//最后位置; 
 
	memset( gradientfre, 0, 256*sizeof(INT));//清零,下面用作某梯度内的指针; 
	//自左上至右下sorting.... 
	for (y=0; yGetMainWnd(); 
	EndWaitCursor(); 
	pFrame->pImageView->Invalidate(FALSE);	 
	 
} 
 
void CWaterShedDoc::GetGradient(BYTE *image, INT width, INT height, FLOAT *deltar, FLOAT *deltasita) 
{ 
	//下面计算各像素在水平和垂直方向上的梯度,边缘点梯度计为0; 
	INT* deltaxarr; 
	INT* deltayarr; 
	INT grawidth = width; 
	INT graheight = height; 
	INT deltacount = grawidth * graheight; 
	deltaxarr = new INT[deltacount]; 
	deltayarr = new INT[deltacount]; 
	 
    //暂不计算边缘点; 
	for (INT y=1; yCreateDIBFromBits(imageWidth, imageHeight, imageData); 
} 
 
void CWaterShedDoc::FloodVincent(MyImageGraPt *imiarr, INT *graddarr, INT minh, INT maxh, INT *flagarr, INT &outrgnumber) 
{ 
	const INT INIT = -2; 
	const INT MASK = -1; 
	const INT WATERSHED = 0; 
	INT h = 0; 
	INT imagelen = imageWidth * imageHeight; 
	for (INT i=0; i myqueue; 
	INT curlabel = 0;//各盆地标记; 
 
	for (h=minh; h<=maxh; h++) 
	{ 
		INT stpos = graddarr[h]; 
		INT edpos = graddarr[h+1]; 
		for (INT ini=stpos; ini=0)  
			{ 
				if (flagarr[left]>=0) 
				{ 
					imd[ipos] = 1; 
					myqueue.push(ipos);//点位置压入fifo; 
					continue; 
				}				 
			} 
			INT right = ipos + 1; 
			if (x+1=0)  
				{ 
					imd[ipos] = 1; 
					myqueue.push(ipos);//点位置压入fifo; 
					continue; 
				} 
			} 
			INT up = ipos - imageWidth; 
			if (y-1>=0)  
			{ 
				if (flagarr[up]>=0) 
				{ 
					imd[ipos] = 1; 
					myqueue.push(ipos);//点位置压入fifo; 
					continue; 
				}				 
			} 
			INT down = ipos + imageWidth; 
			if (y+1=0)  
				{ 
					imd[ipos] = 1; 
					myqueue.push(ipos);//点位置压入fifo; 
					continue; 
				}			 
			} 
		} 
 
    	//以下根据先进先出队列扩展现有盆地; 
		INT curdist = 1; myqueue.push(-99);//特殊标记; 
		while (TRUE) 
		{ 
			INT p = myqueue.front(); 
			myqueue.pop(); 
			if (p == -99) 
			{ 
				if ( myqueue.empty() ) 
				{ 
					break; 
				}else 
				{ 
					myqueue.push(-99); 
					curdist = curdist + 1; 
					p = myqueue.front(); 
					myqueue.pop(); 
				} 
			} 
 
			//以下找p的邻域; 
			INT y = (INT) (p/imageWidth); 
			INT x = p - y*imageWidth; 
			INT left = p - 1; 
			if  (x-1>=0) 
			{ 
				if ( ( (imd[left]0) 
					|| (flagarr[left]==0) )  
				{ 
					if ( flagarr[left]>0 ) 
					{ 
						//ppei属于某区域(不是分水岭); 
						if ( (flagarr[p]==MASK)  
							|| (flagarr[p]==WATERSHED) ) 
						{ 
							//将其设为邻点所属区域; 
							flagarr[p] = flagarr[left]; 
						}else if (flagarr[p]!=flagarr[left]) 
						{ 
							//原来赋的区与现在赋的区不同,设为分水岭; 
							//flagarr[p] = WATERSHED; 
						} 
					}else if (flagarr[p]==MASK)//ppei为分岭; 
					{ 
						flagarr[p] = WATERSHED; 
					} 
				}else if ( (flagarr[left]==MASK) && (imd[left]==0) ) 
				//ppei中已MASK的点,但尚未标记(即不属某区也不是分水岭); 
				{ 
					imd[left] = curdist + 1; myqueue.push(left); 
				} 
			} 
			 
			INT right = p + 1; 
			if (x+10) 
					|| (flagarr[right]==0) ) 
				{ 
					if ( flagarr[right]>0 ) 
					{ 
						//ppei属于某区域(不是分水岭); 
						if ( (flagarr[p]==MASK)  
							|| (flagarr[p]==WATERSHED) ) 
						{ 
							//将其设为邻点所属区域; 
							flagarr[p] = flagarr[right]; 
						}else if (flagarr[p]!=flagarr[right]) 
						{ 
							//原来赋的区与现在赋的区不同,设为分水岭; 
							//flagarr[p] = WATERSHED; 
						} 
					}else if (flagarr[p]==MASK)//ppei为分岭; 
					{ 
						flagarr[p] = WATERSHED; 
					} 
				}else if ( (flagarr[right]==MASK) && (imd[right]==0) ) 
					//ppei中已MASK的点,但尚未标记(即不属某区也不是分水岭); 
				{ 
					imd[right] = curdist + 1; myqueue.push(right); 
				} 
			} 
			 
			INT up = p - imageWidth; 
			if (y-1>=0)  
			{ 
				if ( ( (imd[up]0) 
					|| (flagarr[up]==0) ) 
				{ 
					if ( flagarr[up]>0 ) 
					{ 
						//ppei属于某区域(不是分水岭); 
						if ( (flagarr[p]==MASK)  
							|| (flagarr[p]==WATERSHED) ) 
						{ 
							//将其设为邻点所属区域; 
							flagarr[p] = flagarr[up]; 
						}else if (flagarr[p]!=flagarr[up]) 
						{ 
							//原来赋的区与现在赋的区不同,设为分水岭; 
							//flagarr[p] = WATERSHED; 
						} 
					}else if (flagarr[p]==MASK)//ppei为分岭; 
					{ 
						flagarr[p] = WATERSHED; 
					} 
				}else if ( (flagarr[up]==MASK) && (imd[up]==0) ) 
					//ppei中已MASK的点,但尚未标记(即不属某区也不是分水岭); 
				{ 
					imd[up] = curdist + 1; myqueue.push(up); 
				} 
			} 
			 
			INT down = p + imageWidth; 
			if (y+10) 
					|| (flagarr[down]==0) ) 
				{ 
					if ( flagarr[down]>0 ) 
					{ 
						//ppei属于某区域(不是分水岭); 
						if ( (flagarr[p]==MASK)  
							|| (flagarr[p]==WATERSHED) ) 
						{ 
							//将其设为邻点所属区域; 
							flagarr[p] = flagarr[down]; 
						}else if (flagarr[p]!=flagarr[down]) 
						{ 
							//原来赋的区与现在赋的区不同,设为分水岭; 
							//flagarr[p] = WATERSHED; 
						} 
					}else if (flagarr[p]==MASK)//ppei为分岭; 
					{ 
						flagarr[p] = WATERSHED; 
					} 
				}else if ( (flagarr[down]==MASK) && (imd[down]==0) ) 
					//ppei中已MASK的点,但尚未标记(既不属某区也不是分水岭); 
				{ 
					imd[down] = curdist + 1; myqueue.push(down); 
				}	 
			} 
 
		}//以上现有盆地的扩展; 
 
		//以下处理新发现的盆地; 
		for (ini=stpos; ini=0) && (flagarr[ppeileft]==MASK) ) 
					{ 
						myqueue.push(ppeileft);//点位置压入fifo; 
						flagarr[ppeileft] = curlabel; 
					} 
					INT ppeiright = ppei + 1; 
					if ( (ppeix+1=0) && (flagarr[ppeiup]==MASK) ) 
					{ 
						myqueue.push(ppeiup);//点位置压入fifo; 
						flagarr[ppeiup] = curlabel; 
					} 
					INT ppeidown = ppei + imageWidth; 
					if ( (ppeiy+1SaveToFile( lpszPathName ); 
		SetModifiedFlag(FALSE); 
	}	 
	return TRUE; 
} 
 
	////////////////////////////////////////////////////////////////////////// 
	//1、建立各区的邻域数组; 
	//2、依次扫描各区域,寻找极小区域; 
	//3、对每个极小区(A),在相邻区中找到最相似者; 
	//4、与相似区(B)合并(各种信息刷新),在极小区(A)的邻域中 
	//   删除相似区(B),在邻域数组中删除相似区(B)对应的项,将 
	//   相似区(B)的相邻区s加到极小区(A)的邻域中去; 
	//5、记录合并信息,设一数组专门存放该信息,该数组的第A个元素值设为B; 
	//6、判断是否仍为极小区,若是则返回3; 
	//7、是否所有区域都已处理完毕,若非则返回2; 
	// 
	//   由于各区的相邻区不会太多,因此采用邻接数组作为存储结构; 
	////////////////////////////////////////////////////////////////////////// 
void CWaterShedDoc::MergeRgs(MyRgnInfo *rginfoarr, INT rgnumber, INT *flag, INT width, INT height, INT *outmerge, INT &rgnum) 
{ 
 
	CString* neiarr = new CString[rgnumber+1];//第一个不用; 
	INT* mergearr = outmerge;//记录合并情况数组; 
	 
	//建立邻域数组; 
	for (INT y=0; y255) r=255; 
		else if(r<0) r=0; 
		 
		if(g>255) g=255; 
		else if(g<0) g=0; 
		 
		if(b>255) b=255; 
		else if(b<0) b=0; 
	} 
	 
	return TRUE; 
} 
 
//刷新当前点的所有相邻区; 
void CWaterShedDoc::AddNeiOfCur(INT curid, INT left, INT right, INT up, INT down, INT *flag, CString *neiarr) 
{ 
	INT leftid, rightid, upid, downid; 
	leftid = rightid = upid = downid = curid; 
	if (left>=0) 
	{ 
		leftid = flag[left]; 
		if (leftid!=curid) 
		{ 
			//邻点属于另一区, 加邻域点信息; 
			AddNeiRgn(curid, leftid, neiarr); 
		} 
	} 
	if (right>0) 
	{ 
		rightid = flag[right]; 
		if (rightid!=curid) 
		{ 
			//邻点属于另一区, 加邻域点信息; 
			AddNeiRgn(curid, rightid, neiarr); 
		} 
	} 
	if (up>=0) 
	{ 
		upid = flag[up]; 
		if (upid!=curid) 
		{ 
			//邻点属于另一区, 加邻域点信息; 
			AddNeiRgn(curid, upid, neiarr); 
		} 
	} 
	if (down>0) 
	{ 
		downid = flag[down]; 
		if (downid!=curid) 
		{ 
			//邻点属于另一区, 加邻域点信息; 
			AddNeiRgn(curid, downid, neiarr); 
		} 
	} 
} 
 
void CWaterShedDoc::AddNeiRgn(INT curid, INT neiid, CString *neiarr) 
//增加neiid为curid的相邻区 
{ 
	CString tempneis = neiarr[curid];//当前的相邻区; 
	CString toaddstr; 
	toaddstr.Format("%d ", neiid); 
	 
	INT temppos = tempneis.Find(toaddstr, 0); 
	while (temppos>0 && neiarr[curid].GetAt(temppos-1)!=' ') 
	{ 
		temppos = neiarr[curid].Find(toaddstr, temppos+1); 
	} 
	 
	if ( temppos<0 ) 
	{ 
		//当前相邻区中没有tempneis,则加入 
		neiarr[curid] += toaddstr; 
	} 
} 
 
//找到idint最终所合并到的区号; 
int CWaterShedDoc::FindMergedRgn(INT idint, INT *mergearr) 
{ 
	INT outid = idint; 
	while ( mergearr[outid] > 0 ) 
	{ 
		outid = mergearr[outid]; 
	} 
	return outid; 
} 
 
int CWaterShedDoc::FindNearestNei(INT curid, CString neistr, MyRgnInfo *rginfoarr, INT *mergearr) 
//寻找neistr中与curid最接近的区,返回该区id号; 
{ 
	INT outid = -1; 
	DOUBLE mindis = 999999; 
	FLOAT cl, cu, cv; 
	cl = rginfoarr[curid].l;//当前区的LUV值; 
	cu = rginfoarr[curid].u; 
	cv = rginfoarr[curid].v; 
	 
	CString tempstr = neistr;//用于本函数内部处理; 
	while (tempstr.GetLength()>0) 
	{ 
		INT pos = tempstr.Find(" "); 
		ASSERT(pos>=0); 
		CString idstr = tempstr.Left(pos); 
		tempstr.Delete(0, pos+1); 
		 
		INT idint = (INT) strtol(idstr, NULL, 10); 
		//判断该区是否已被合并,若是,则一直找到该区当前的区号; 
		idint = FindMergedRgn(idint, mergearr); 
		if (idint==curid) 
		{ 
			continue;//这个邻区已被合并到当前区,跳过; 
		} 
		FLOAT tl, tu, tv; 
		tl = rginfoarr[idint].l;//当前处理的邻区的LUV值; 
		tu = rginfoarr[idint].u; 
		tv = rginfoarr[idint].v; 
		DOUBLE tempdis = pow(tl-cl, 2)  
			+ pow(tu-cu, 2) + pow(tv-cv, 2); 
		if (tempdis0 && neiarr[curid].GetAt(temppos-1)!=' ') 
	{ 
	temppos = neiarr[curid].Find(tempstr, temppos+1); 
	} 
	if (temppos>=0) 
	{ 
	//否则邻近区为合并过来的区,忽略; 
	neiarr[curid].Delete(temppos, tempstr.GetLength()); 
	} 
	*/ 
    //将nearid的邻区依次加到curid的邻区中去; 
	CString neistr = neiarr[nearid]; 
	CString curstr = neiarr[curid]; 
	//一般说来,极小区的邻域应该较少,因此,为着提高合并速度,将 
	//curstr加到neistr中去,然后将结果赋给neiarr[curid]; 
	while ( curstr.GetLength()>0 ) 
	{ 
		INT pos = curstr.Find(" ");		 
		ASSERT(pos>=0); 
		CString idstr = curstr.Left(pos); 
        curstr.Delete(0, pos+1); 
		INT idint = (INT) strtol(idstr, NULL, 10); 
		idint = FindMergedRgn(idint, mergearr); 
		idstr += " "; 
		if ( (idint == curid) || (idint == nearid) ) 
		{ 
			continue;//本区不与本区相邻; 
		}else 
		{ 
			if ( neistr.Find(idstr, 0) >= 0 ) 
			{ 
				continue; 
			}else 
			{ 
				neistr += idstr;//加到邻区中去; 
			} 
		}		 
	} 
	neiarr[curid] = neistr; 
	/* 
	CString toaddneis = neiarr[nearid]; 
	while (toaddneis.GetLength()>0) 
	{ 
	INT pos = toaddneis.Find(" ");		 
	ASSERT(pos>=0); 
	CString idstr = toaddneis.Left(pos); 
	toaddneis.Delete(0, pos+1); 
	INT idint = (INT) strtol(idstr, NULL, 10); 
	idint = FindMergedRgn(idint, mergearr); 
	idstr += " "; 
	if ( (idint == curid) || (idint == nearid) ) 
	{ 
	continue;//本区不与本区相邻; 
	}else 
	{ 
	if ( neiarr[curid].Find(idstr, 0) >= 0 ) 
	{ 
				continue; 
				}else 
				{ 
				neiarr[curid] += idstr;//加到邻区中去; 
				} 
				}		 
				} 
	*/ 
} 
 
#define NearMeasureBias 200.0//判定区域颜色相似的阈值; 
void CWaterShedDoc::MergeNearest(INT curid, MyRgnInfo *rginfoarr, CString *neiarr, INT *mergearr) 
//合并相似区域; 
{ 
	//依次处理各个邻域,若相似,则合并; 
	//CString neistr = neiarr[curid]; 
	FLOAT cl, cu, cv; 
	cl = rginfoarr[curid].l;//当前区的LUV值; 
	cu = rginfoarr[curid].u; 
	cv = rginfoarr[curid].v; 
	BOOL loopmerged = TRUE;//一次循环中是否有合并操作发生,若无,则退出循环; 
	 
	while (loopmerged) 
	{ 
		loopmerged = FALSE; 
		CString tempstr = neiarr[curid];//用于本函数内部处理; 
		while (tempstr.GetLength()>0) 
		{ 
			INT pos = tempstr.Find(" "); 
			ASSERT(pos>=0); 
			CString idstr = tempstr.Left(pos); 
			tempstr.Delete(0, pos+1); 
			 
			INT idint = (INT) strtol(idstr, NULL, 10); 
			//判断该区是否已被合并,若是,则一直找到该区当前的区号; 
			idint = FindMergedRgn(idint, mergearr); 
			if (idint==curid) 
			{ 
				continue;//这个邻区已被合并到当前区,跳过; 
			} 
			FLOAT tl, tu, tv; 
			tl = rginfoarr[idint].l;//当前处理的邻区的LUV值; 
			tu = rginfoarr[idint].u; 
			tv = rginfoarr[idint].v; 
			DOUBLE tempdis = pow(tl-cl, 2)  
				+ pow(tu-cu, 2) + pow(tv-cv, 2); 
			if (tempdis  Lt)  l_star = my_pow[(int)(tval*255+0.5)]; 
		else  l_star = (FLOAT) ( 903.3 * tval ); 
		 
		my_temp = x + 15 * y + 3 * z; 
		if(my_temp) 
		{ 
			u_prime = (float)(x << 2) / (float)(my_temp); 
			v_prime = (float)(9 * y) / (float)(my_temp); 
		} 
		else 
		{ 
			u_prime = 4.0; 
			v_prime = (FLOAT) ( 9.0/15.0 ); 
		} 
		 
		tval = 13*l_star; 
		u_star = tval * (u_prime - Un_prime); // Un_prime = 0.1978 
		v_star = tval * (v_prime - Vn_prime); // Vn_prime = 0.4683 
		 
		luvbuff[j].l = l_star; 
		luvbuff[j].u = u_star; 
		luvbuff[j].v = v_star; 
	} 
	 
	delete [] my_pow; 
	delete [] A22; delete [] A21; delete [] A20; 
	delete [] A12; delete [] A11; delete [] A10; 
	delete [] A02; delete [] A01; delete [] A00; 
	 
	return TRUE; 
}