//---------------------------------------------------------
bool CSG_Rects::Add(const CSG_Rect &Rect)
{
	m_Rects				= (CSG_Rect **)SG_Realloc(m_Rects, (m_nRects + 1) * sizeof(CSG_Rect *));
	m_Rects[m_nRects]	= new CSG_Rect(Rect);
	m_nRects++;

	return( true );
}
Beispiel #2
0
//---------------------------------------------------------
int CSG_Shape_Points::_Add_Part(void)
{
	m_pParts			= (CSG_Shape_Part **)SG_Realloc(m_pParts , (m_nParts + 1) * sizeof(CSG_Shape_Part *));
	m_pParts[m_nParts]	= _Get_Part();

	m_nParts++;

	return( m_nParts );
}
Beispiel #3
0
//---------------------------------------------------------
char * CSG_Table_DBase::asString(int iField)
{
	if( bOpen && iField >= 0 && iField < nFields )
	{
		if( FieldDesc[iField].Type != DBF_FT_DATE )
		{
			int		i			= FieldDesc[iField].Width;
			Result_String		= (char *)SG_Realloc(Result_String, (i + 1) * sizeof(char));
			memcpy(Result_String, Record + FieldOffset[iField], FieldDesc[iField].Width);

			Result_String[i--]	= '\0';

			while( i >= 0 && Result_String[i] == ' ' )
			{
				Result_String[i--]	= '\0';
			}
		}
		else // if( FieldDesc[iField].Type == DBF_FT_DATE )	// SAGA(DD.MM.YYYY) from DBASE(YYYYMMDD)
		{
			char	*s	= Record + FieldOffset[iField];

			Result_String		= (char *)SG_Realloc(Result_String, (10 + 1) * sizeof(char));

			Result_String[0]	= s[6];	// D1
			Result_String[1]	= s[7];	// D2
			Result_String[2]	= '.';
			Result_String[3]	= s[4];	// M1
			Result_String[4]	= s[5];	// M2
			Result_String[5]	= '.';
			Result_String[6]	= s[0];	// Y1
			Result_String[7]	= s[1];	// Y2
			Result_String[8]	= s[2];	// Y3
			Result_String[9]	= s[3];	// Y4
			Result_String[2]	= '\0';
		}

		return( Result_String );
	}

	return( "" );
}
Beispiel #4
0
//---------------------------------------------------------
bool CSG_Matrix::Add_Rows(int nRows)
{
	if( nRows > 0 && m_nx > 0 )
	{
		m_ny	+= nRows;

		m_z		= (double **)SG_Realloc(m_z   , m_ny        * sizeof(double *));
		m_z[0]	= (double  *)SG_Realloc(m_z[0], m_ny * m_nx * sizeof(double  ));

		for(int y=1; y<m_ny; y++)
		{
			m_z[y]	= m_z[y - 1] + m_nx;
		}

		memset(m_z[m_ny - nRows], 0, nRows * m_nx * sizeof(double));

		return( true );
	}

	return( false );
}
//---------------------------------------------------------
bool CWKSP_Data_Buttons::_Add_Item(CWKSP_Base_Manager *pItem)
{
	if( pItem )
	{
		m_Items	= (CWKSP_Data_Button **)SG_Realloc(m_Items, (m_nItems + 1) * sizeof(CWKSP_Data_Button *));
		m_Items[m_nItems++]	= new CWKSP_Data_Button(this, pItem);

		return( true );
	}

	return( false );
}
//---------------------------------------------------------
bool CVIEW_Table_Control::Add_Record(void)
{
	if( !FIXED_ROWS && m_pTable->Get_ObjectType() == DATAOBJECT_TYPE_Table )
	{
		AppendRows();

		m_pRecords	= (CSG_Table_Record **)SG_Realloc(m_pRecords, GetNumberRows() * sizeof(CSG_Table_Record *));

		_Set_Record(GetNumberRows() - 1, m_pTable->Add_Record());

		return( true );
	}

	return( false );
}
//---------------------------------------------------------
bool CSG_PointCloud::_Add_Field(const SG_Char *Name, TSG_Data_Type Type, int iField)
{
    if( !Name || PC_GET_NBYTES(Type) <= 0 )
    {
        return( false );
    }

    m_Field_Name	= (CSG_String            **)SG_Realloc(m_Field_Name  , (m_nFields + 1) * sizeof(CSG_String *));
    m_Field_Type	= (TSG_Data_Type          *)SG_Realloc(m_Field_Type  , (m_nFields + 1) * sizeof(TSG_Data_Type));
    m_Field_Stats	= (CSG_Simple_Statistics **)SG_Realloc(m_Field_Stats , (m_nFields + 1) * sizeof(CSG_Simple_Statistics *));
    m_Field_Offset	= (int                    *)SG_Realloc(m_Field_Offset, (m_nFields + 1) * sizeof(int));

    m_Field_Name  [m_nFields]	= new CSG_String(Name);
    m_Field_Type  [m_nFields]	= Type;
    m_Field_Stats [m_nFields]	= new CSG_Simple_Statistics();
    m_Field_Offset[m_nFields]	= m_nFields == 0 ? 1 : m_Field_Offset[m_nFields - 1] + PC_GET_NBYTES(m_Field_Type[m_nFields - 1]);

    if( m_nFields == 0 )
    {
        m_nPointBytes	= 1;
    }

    m_nPointBytes	+= PC_GET_NBYTES(m_Field_Type[m_nFields]);
    m_nFields		++;

    m_Shapes.Add_Field(Name, Type);

    for(int i=0; i<Get_Count(); i++)
    {
        m_Points[i]	= (char *)SG_Realloc(m_Points[i], m_nPointBytes * sizeof(char));
    }

    Set_Modified();

    return( true );
}
//---------------------------------------------------------
bool CSG_Translator::Create(class CSG_Table *pTranslations, int iText, int iTranslation, bool bCmpNoCase)
{
	SG_UI_Msg_Lock(true);

	Destroy();

	if( iText != iTranslation && pTranslations && pTranslations->Get_Field_Count() > iText && pTranslations->Get_Field_Count() > iTranslation && pTranslations->Get_Record_Count() > 0 )
	{
		int		i;

		m_bCmpNoCase	= bCmpNoCase;

		if( m_bCmpNoCase )
		{
			for(i=0; i<pTranslations->Get_Record_Count(); i++)
			{
				CSG_Table_Record	*pRecord	= pTranslations->Get_Record(i);

				CSG_String	s	= pRecord->asString(iText);

				pRecord->Set_Value(iText, s.Make_Lower().c_str());
			}
		}

		pTranslations->Set_Index(iText, TABLE_INDEX_Ascending);

		m_Translations	= (CSG_Translation **)SG_Malloc(pTranslations->Get_Record_Count() * sizeof(CSG_Translation *));

		for(i=0; i<pTranslations->Get_Record_Count(); i++)
		{
			CSG_Table_Record	*pRecord	= pTranslations->Get_Record_byIndex(i);

			if( *pRecord->asString(iText) && *pRecord->asString(iTranslation) )
			{
				m_Translations[m_nTranslations++]	= new CSG_Translation(pRecord->asString(iText), pRecord->asString(iTranslation));
			}
		}

		if( m_nTranslations < pTranslations->Get_Record_Count() )
		{
			m_Translations	= (CSG_Translation **)SG_Realloc(m_Translations, m_nTranslations * sizeof(CSG_Translation *));
		}
	}

	SG_UI_Msg_Lock(false);

	return( m_nTranslations > 0 );
}
Beispiel #9
0
//---------------------------------------------------------
void CSAGA_Frame::Top_Window_Push(wxWindow *pWindow)
{
	if( pWindow )
	{
		for(int i=0; i<m_nTopWindows; i++)
		{
			if( m_pTopWindows[i] == pWindow )
			{
				return;
			}
		}

		m_pTopWindows	= (wxWindow **)SG_Realloc(m_pTopWindows, (m_nTopWindows + 1) * sizeof(wxWindow *));
		m_pTopWindows[m_nTopWindows++]	= pWindow;
	}
}
Beispiel #10
0
//---------------------------------------------------------
CSG_MetaData * CSG_MetaData::Add_Child(void)
{
	if( (m_nChildren + 1) >= m_nBuffer )
	{
		CSG_MetaData	**pChildren	= (CSG_MetaData **)SG_Realloc(m_pChildren, (m_nBuffer + GET_GROW_SIZE(m_nBuffer)) * sizeof(CSG_MetaData *));

		if( pChildren )
		{
			m_pChildren	= pChildren;
			m_nBuffer	+= GET_GROW_SIZE(m_nBuffer);
		}
		else
		{
			return( false );
		}
	}

	return( m_pChildren[m_nChildren++]	= new CSG_MetaData(this) );
}
Beispiel #11
0
//---------------------------------------------------------
int CSG_Shape_Points::Del_Part(int del_Part)
{
	if( del_Part >= 0 && del_Part < m_nParts )
	{
		delete(m_pParts[del_Part]);

		m_nParts--;

		for(int iPart=del_Part; iPart<m_nParts; iPart++)
		{
			m_pParts[iPart]	= m_pParts[iPart + 1];
		}

		m_pParts	= (CSG_Shape_Part **)SG_Realloc(m_pParts , m_nParts * sizeof(CSG_Shape_Part *));

		_Invalidate();
	}

	return( m_nParts );
}
Beispiel #12
0
//---------------------------------------------------------
bool CSG_Points_Int::Add(int x, int y)
{
	if( m_nPoints >= m_nBuffer - 1 )
	{
		TSG_Point_Int	*Points	= (TSG_Point_Int *)SG_Realloc(m_Points, (m_nBuffer + BUFFER_SIZE_GROW(m_nBuffer)) * sizeof(TSG_Point_Int));

		if( Points == NULL )
		{
			return( false );
		}

		m_Points	 = Points;
		m_nBuffer	+= BUFFER_SIZE_GROW(m_nBuffer);
	}

	m_Points[m_nPoints].x	= x;
	m_Points[m_nPoints].y	= y;
	m_nPoints++;

	return( true );
}
Beispiel #13
0
//---------------------------------------------------------
bool CSG_Points_Z::Add(double x, double y, double z)
{
	if( m_nPoints >= m_nBuffer - 1 )
	{
		TSG_Point_Z	*Points	= (TSG_Point_Z *)SG_Realloc(m_Points, (m_nBuffer + BUFFER_SIZE_GROW(m_nBuffer)) * sizeof(TSG_Point_Z));

		if( Points == NULL )
		{
			return( false );
		}

		m_Points	 = Points;
		m_nBuffer	+= BUFFER_SIZE_GROW(m_nBuffer);
	}

	m_Points[m_nPoints].x	= x;
	m_Points[m_nPoints].y	= y;
	m_Points[m_nPoints].z	= z;
	m_nPoints++;

	return( true );
}
Beispiel #14
0
//---------------------------------------------------------
void CSAGA_Frame::Top_Window_Pop(wxWindow *pWindow)
{
	if( pWindow )
	{
		int		i, j;

		for(i=j=0; j<m_nTopWindows; i++, j++)
		{
			if( m_pTopWindows[i] == pWindow )
				j++;

			if( i < j && j < m_nTopWindows )
				m_pTopWindows[i]	= m_pTopWindows[j];
		}

		if( i < j )
		{
			m_nTopWindows--;
			m_pTopWindows	= (wxWindow **)SG_Realloc(m_pTopWindows, m_nTopWindows * sizeof(wxWindow *));
		}
	}
}
Beispiel #15
0
//---------------------------------------------------------
bool CSG_MetaData::Del_Child(int Index)
{
	if( Index >= 0 && Index < m_nChildren )
	{
		delete(m_pChildren[Index]);

		m_nChildren--;

		if( (m_nChildren - 1) < m_nBuffer - GET_GROW_SIZE(m_nBuffer) )
		{
			CSG_MetaData	**pChildren	= (CSG_MetaData **)SG_Realloc(m_pChildren, (m_nBuffer - GET_GROW_SIZE(m_nBuffer)) * sizeof(CSG_MetaData *));

			if( pChildren )
			{
				m_pChildren	= pChildren;
				m_nBuffer	-= GET_GROW_SIZE(m_nBuffer);
			}
		}

		return( true );
	}

	return( false );
}
Beispiel #16
0
//---------------------------------------------------------
bool CSG_Table_DBase::Header_Read(void)
{
	bool	Result	= false;
	char	buf[16];

	if( bOpen )
	{
		//-------------------------------------------------
		// Initializations...

		fseek(hFile, 0, SEEK_SET);


		//-------------------------------------------------
		// Bytes 0-31: File Header...

		fread(&FileType			, sizeof(char),  1, hFile);	// 00		FoxBase+, FoxPro, dBaseIII+, dBaseIV, no memo	- 0x03
															//			FoxBase+, dBaseIII+ with memo					- 0x83
															//			FoxPro with memo								- 0xF5
															//			dBaseIV with memo								- 0x8B
															//			dBaseIV with SQL Table							- 0x8E
		fread(&LastUpdate		, sizeof(char),  3, hFile);	// 01-03	Last update, format YYYYMMDD   **correction: it is YYMMDD**
		fread(&nRecords			, sizeof(char),  4, hFile);	// 04-07	Number of records in file (32-bit number)
		fread(&nHeaderBytes		, sizeof(char),  2, hFile);	// 08-09	Number of bytes in header (16-bit number)
		fread(&nRecordBytes		, sizeof(char),  2, hFile);	// 10-11	Number of bytes in record (16-bit number)
		fread( buf				, sizeof(char),  2, hFile);	// 12-13	Reserved, fill with 0x00
		fread(&Transaction		, sizeof(char),  1, hFile);	// 14		dBaseIV flag, incomplete transaction
															//			Begin Transaction sets it to					- 0x01
															//			End Transaction or RollBack reset it to			- 0x00
		fread(&bEncrypted		, sizeof(char),  1, hFile);	// 15		Encryption flag, encrypted 0x01 else 0x00
															//			Changing the flag does not encrypt or decrypt the records
		fread( buf				, sizeof(char), 12, hFile);	// 16-27	dBaseIV multi-user environment use
		fread(&ProductionIdx	, sizeof(char),  1, hFile);	// 28		Production index exists - 0x01 else 0x00
		fread(&LanguageDrvID	, sizeof(char),  1, hFile);	// 29		dBaseIV language driver ID
		fread( buf				, sizeof(char),  2, hFile);	// 30-31	Reserved fill with 0x00


		//-------------------------------------------------
		// Bytes 32-n: Field Descriptor Array...

		while(	ftell(hFile) < (long)nHeaderBytes - 1 && !feof(hFile) )
		{
			FieldDesc	= (TFieldDesc *)SG_Realloc(FieldDesc, (nFields + 1) * sizeof(TFieldDesc));

			fread( FieldDesc[nFields].Name			, sizeof(char), 11, hFile);	// 0-10		Field Name ASCII padded with 0x00
			fread(&FieldDesc[nFields].Type			, sizeof(char),  1, hFile);	// 11		Field Type Identifier (see table)
			fread(&FieldDesc[nFields].Displacement	, sizeof(char),  4, hFile);	// 12-15	Displacement of field in record
			fread(&FieldDesc[nFields].Width			, sizeof(char),  1, hFile);	// 16		Field length in bytes
			fread(&FieldDesc[nFields].Decimals		, sizeof(char),  1, hFile);	// 17		Field decimal places
			fread( buf								, sizeof(char),  2, hFile);	// 18-19	Reserved
			fread(&FieldDesc[nFields].WorkAreaID	, sizeof(char),  1, hFile);	// 20		dBaseIV work area ID
			fread( buf								, sizeof(char), 10, hFile);	// 21-30	Reserved
			fread(&FieldDesc[nFields].ProductionIdx	, sizeof(char),  1, hFile);	// 31	 	Field is part of production index - 0x01 else 0x00

			FieldDesc[nFields].Name[11]	= '\0';

			nFields++;
		}


		//-------------------------------------------------
		// Byte n+1: Header Record Terminator (0x0D)...
		fread( buf				, sizeof(char),  1, hFile);

		if( buf[0] == 0x0d )
		{
			Init_Record();
			Move_First();

			Result	= true;
		}
	}

	//-----------------------------------------------------
	if( !Result )
	{
		fclose(hFile);
		hFile	= NULL;
		bOpen	= false;
		Close();
	}

	return( Result );
}
//---------------------------------------------------------
bool CVIEW_Table_Control::_Set_Records(bool bSelection_To_Top)
{
	BeginBatch();

	//-----------------------------------------------------
	if( m_bSelOnly && m_pTable->Get_Selection_Count() <= 0 )
	{
		m_bSelOnly	= false;
	}

	int	Difference, nRecords	= m_bSelOnly ? m_pTable->Get_Selection_Count() : m_pTable->Get_Count();

	if( (Difference = nRecords - GetNumberRows()) > 0 )
	{
		AppendRows(Difference);
	}
	else if( Difference < 0 && (Difference = -Difference < GetNumberRows() ? -Difference : GetNumberRows()) > 0 )
	{
		DeleteRows(0, Difference);
	}

	m_pRecords	= (CSG_Table_Record **)SG_Realloc(m_pRecords, nRecords * sizeof(CSG_Table_Record *));

	ClearSelection();

	//-----------------------------------------------------
	if( m_bSelOnly )
	{
	//	#pragma omp parallel for
		for(int iRecord=0; iRecord<nRecords; iRecord++)
		{
			_Set_Record(iRecord, m_pTable->Get_Selection(iRecord));
		}
	}
	else if( !bSelection_To_Top )
	{
	//	#pragma omp parallel for
		for(int iRecord=0; iRecord<nRecords; iRecord++)
		{
			_Set_Record(iRecord, m_pTable->Get_Record_byIndex(iRecord));
		}
	}
	else // if( bSelection_To_Top && m_pTable->Get_Selection_Count() > 0 )
	{
		for(int iRecord=0, iSel=0, iNoSel=m_pTable->Get_Selection_Count(); iRecord<nRecords && PROGRESSBAR_Set_Position(iRecord, nRecords); iRecord++)
		{
			CSG_Table_Record	*pRecord	= m_pTable->Get_Record_byIndex(iRecord);

			if( pRecord->is_Selected() )
			{
				_Set_Record(iSel  ++, pRecord);
			}
			else
			{
				_Set_Record(iNoSel++, pRecord);
			}
		}

		PROCESS_Set_Okay();
	}

	//-----------------------------------------------------
	EndBatch();

	_Update_Views();

	return( true );
}
Beispiel #18
0
//---------------------------------------------------------
void CChannelNetwork::Set_Channel_Route(int x, int y)
{
	const int	BUFFER_GROWSIZE	= 256;

	int		xStart, yStart, i, ix, iy, goDir, m, n, nDiv;

	double	z, dz, dzMin, Length;

	//-----------------------------------------------------
	if( pStart->asChar(x,y) && !pChannelRoute->asChar(x,y) )
	{
		Lock_Create();

		n		= 0;
		nDiv	= 0;
		Length	= 0;
		xStart	= x;
		yStart	= y;

		do
		{
			//---------------------------------------------
			// 1. Divergence ?!...

			if( pConvergence )
			{
				if( pConvergence->asDouble(x,y) > -1.0 )
				{
					nDiv++;
				}
				else
				{
					nDiv	= 0;
				}
			}

			if( pConvergence && nDiv > maxDivCells )
			{
				goDir	= -1;
			}
			else
			{
				//-----------------------------------------
				// 2. Is there any channel around ?!...

				goDir	= 0;
				z		= pDTM->asDouble(x,y);

				for(i=1; i<=8; i++)
				{
					ix		= Get_xTo(i,x);
					iy		= Get_yTo(i,y);

					if( pDTM->is_InGrid(ix,iy) && !is_Locked(ix,iy) && pChannelRoute->asChar(ix,iy) )
					{
						dz		= (z - pDTM->asDouble(ix,iy)) / Get_Length(i);

						if( goDir <= 0 || dzMin < dz )
						{
							goDir	= i;
							dzMin	= dz;
						}
					}
				}

				if( goDir <= 0 )	// ...if not then go as usual...
				{
					goDir	= pChannels->asInt(x,y);
				}


				//-----------------------------------------
				// 3. Go to Drainage Direction !...

				if(	goDir > 0 )
				{
					Lock_Set(x,y);

					x		= Get_xTo(goDir,x);
					y		= Get_yTo(goDir,y);

					Length	+= Get_UnitLength(goDir);

					if( n >= Direction_Buffer )
					{
						Direction_Buffer	+= BUFFER_GROWSIZE;
						Direction			= (int *)SG_Realloc(Direction, Direction_Buffer * sizeof(int));
					}

					Direction[n++]	= goDir;
				}
			}
		}
		while( goDir > 0 && pDTM->is_InGrid(x,y) && !is_Locked(x,y) && !pChannelRoute->asChar(x,y) );


		//-------------------------------------------------
		if( Length >= minLength )
		{
			x	= xStart;
			y	= yStart;

			if( goDir < 0 )
			{
				n	-= nDiv;
			}

			for(m=0; m<n; m++)
			{
				goDir	= Direction[m];

				pChannelRoute->Set_Value(x,y,goDir);

				for(i=0; i<8; i++)	// Don't start new channels beside existing ones...
				{
					ix		= Get_xTo(i,x);
					iy		= Get_yTo(i,y);

					if( pDTM->is_InGrid(ix,iy) )
					{
						pStart->Set_Value(ix,iy,0);
					}
				}

				x	= Get_xTo(goDir,x);
				y	= Get_yTo(goDir,y);
			}
		}
	}
}
//---------------------------------------------------------
bool CSG_TIN::_Triangulate(CSG_TIN_Node **Points, int nPoints, TTIN_Triangle *Triangles, int &nTriangles)
{
	int			i, j, k, inside, trimax,
				nedge		= 0,
				emax		= 200,
				status		= 0,
				*complete	= NULL;

	double		dmax, xp, yp, x1, y1, x2, y2, x3, y3, xc, yc, r;

	TTIN_Edge	*edges		= NULL;

	//-----------------------------------------------------
	// Update extent...
	if( nPoints >= 3 )
	{
		TSG_Rect	r;

		m_Extent.Assign(
			Points[0]->Get_X(), Points[0]->Get_Y(),
			Points[0]->Get_X(), Points[0]->Get_Y()
		);

		for(i=1; i<nPoints; i++)
		{
			r.xMin	= r.xMax	= Points[i]->Get_X();
			r.yMin	= r.yMax	= Points[i]->Get_Y();

			m_Extent.Union(r);
		}
	}
	else
	{
		return( false );
	}

	//-----------------------------------------------------
	// Allocate memory for the completeness list, flag for each triangle
	trimax	= 4 * nPoints;
	if( (complete	= (int       *)SG_Malloc(trimax * sizeof(int))) == NULL )
	{
		status	= 1;
		goto skip;
	}

	//-----------------------------------------------------
	// Allocate memory for the edge list
	if( (edges		= (TTIN_Edge *)SG_Malloc(emax   * sizeof(TTIN_Edge))) == NULL )
	{
		status	= 2;
		goto skip;
	}

	//-----------------------------------------------------
	//	Find the maximum and minimum vertex bounds.
	//	This is to allow calculation of the bounding triangle
	//	Set up the supertriangle
	//	This is a triangle which encompasses all the sample points.
	//	The supertriangle coordinates are added to the end of the
	//	vertex list. The supertriangle is the first triangle in
	//	the triangle list.

	dmax	= m_Extent.Get_XRange() > m_Extent.Get_YRange() ? m_Extent.Get_XRange() : m_Extent.Get_YRange();

	Points[nPoints + 0]->m_Point.x	= m_Extent.Get_XCenter() - 20 * dmax;
	Points[nPoints + 1]->m_Point.x	= m_Extent.Get_XCenter();
	Points[nPoints + 2]->m_Point.x	= m_Extent.Get_XCenter() + 20 * dmax;

	Points[nPoints + 0]->m_Point.y	= m_Extent.Get_YCenter() -      dmax;
	Points[nPoints + 1]->m_Point.y	= m_Extent.Get_YCenter() + 20 * dmax;
	Points[nPoints + 2]->m_Point.y	= m_Extent.Get_YCenter() -      dmax;

	Triangles[0].p1	= nPoints;
	Triangles[0].p2	= nPoints + 1;
	Triangles[0].p3	= nPoints + 2;

	complete [0]	= false;

	nTriangles		= 1;

	//-----------------------------------------------------
	//	Include each point one at a time into the existing mesh
	for(i=0; i<nPoints && SG_UI_Process_Set_Progress(i, nPoints); i++)
	{
		xp		= Points[i]->Get_X();
		yp		= Points[i]->Get_Y();
		nedge	= 0;

		//-------------------------------------------------
		//	Set up the edge buffer.
		//	If the point (xp,yp) lies inside the circumcircle then the
		//	three edges of that triangle are added to the edge buffer
		//	and that triangle is removed.
		for(j=0; j<nTriangles; j++)
		{
			if( complete[j] )
			{
				continue;
			}

			x1		= Points[Triangles[j].p1]->Get_X();
			y1		= Points[Triangles[j].p1]->Get_Y();
			x2		= Points[Triangles[j].p2]->Get_X();
			y2		= Points[Triangles[j].p2]->Get_Y();
			x3		= Points[Triangles[j].p3]->Get_X();
			y3		= Points[Triangles[j].p3]->Get_Y();

			inside	= _CircumCircle(xp, yp, x1, y1, x2, y2, x3, y3, &xc, &yc, &r);

			if( xc + r < xp )
			{
				complete[j]	= true;
			}

			if( inside )
			{
				// Check that we haven't exceeded the edge list size
				if( nedge + 3 >= emax )
				{
					emax	+= 100;

					if( (edges = (TTIN_Edge *)SG_Realloc(edges, emax * sizeof(TTIN_Edge))) == NULL )
					{
						status	= 3;
						goto skip;
					}
				}

				edges[nedge + 0].p1	= Triangles[j].p1;
				edges[nedge + 0].p2	= Triangles[j].p2;
				edges[nedge + 1].p1	= Triangles[j].p2;
				edges[nedge + 1].p2	= Triangles[j].p3;
				edges[nedge + 2].p1	= Triangles[j].p3;
				edges[nedge + 2].p2	= Triangles[j].p1;

				nedge	+= 3;

				Triangles[j]	= Triangles[nTriangles - 1];
				complete [j]	= complete [nTriangles - 1];

				nTriangles--;
				j--;
			}
		}

		//-------------------------------------------------
		//	Tag multiple edges
		//	Note: if all triangles are specified anticlockwise then all
		//	      interior edges are opposite pointing in direction.
		for(j=0; j<nedge-1; j++)
		{
			for(k=j+1; k<nedge; k++)
			{
				if( (edges[j].p1 == edges[k].p2) && (edges[j].p2 == edges[k].p1) )
				{
					edges[j].p1 = -1;
					edges[j].p2 = -1;
					edges[k].p1 = -1;
					edges[k].p2 = -1;
				}

				// Shouldn't need the following, see note above
				if( (edges[j].p1 == edges[k].p1) && (edges[j].p2 == edges[k].p2) )
				{
					edges[j].p1 = -1;
					edges[j].p2 = -1;
					edges[k].p1 = -1;
					edges[k].p2 = -1;
				}
			}
		}

		//-------------------------------------------------
		//	Form new triangles for the current point
		//	Skipping over any tagged edges.
		//	All edges are arranged in clockwise order.
		for(j=0; j<nedge; j++)
		{
			if( edges[j].p1 < 0 || edges[j].p2 < 0 )
			{
				continue;
			}

			if( nTriangles >= trimax )
			{
				status	= 4;
				goto skip;
			}

			Triangles[nTriangles].p1	= edges[j].p1;
			Triangles[nTriangles].p2	= edges[j].p2;
			Triangles[nTriangles].p3	= i;
			complete [nTriangles]		= false;
			nTriangles++;
		}
	}

	//-----------------------------------------------------
	//	Remove triangles with supertriangle vertices
	//	These are triangles which have a vertex number greater than nPoints
	for(i=0; i<nTriangles; i++)
	{
		if(	Triangles[i].p1 >= nPoints
		||	Triangles[i].p2 >= nPoints
		||	Triangles[i].p3 >= nPoints )
		{
			Triangles[i] = Triangles[nTriangles - 1];
			nTriangles--;
			i--;
		}
	}

	//-----------------------------------------------------
	skip:

	if( edges )
	{
		SG_Free(edges);
	}

	if( complete )
	{
		SG_Free(complete);
	}

	return( status == 0 );
}