//ROMTEAM Networks (Gabriela Dumitrascu 25/02/98)

///////////////////////////////////////////////////////////////////////////////////////////////////
// Description : NtwObj.cpp
//   
// Definition of the waypoint editors objects   
//
///////////////////////////////////////////////////////////////////////////////////////////////////
// inherit from  :	CPA_Object
//					CPA_EdMot<ACP_tdxHandleOfLink>
///////////////////////////////////////////////////////////////////////////////////////////////////
// Creation date: 1998-03-02                        Author: CPA2 Gabriela Dumitrascu
///////////////////////////////////////////////////////////////////////////////////////////////////
// Modification date:			                      Author: 
///////////////////////////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "acp_base.h"
#include "resource.h"
#include "incdpt.h"
#include "incitf.h"
#include "incgam.h"
#include "incai.h"
#include "WPObj.hpp"
//ANNECY Shaitan Nettoyage (12/05/98) {
/*
#include "WayObj.hpp"
#include "LinkObj.hpp"
*/
//ENDANNECY Shaitan Nettoyage }
#include "Inter.hpp"
#include "WPMod.hpp"
// Shaitan Correction {
#include "WPObj.hpp"
//End Shaitan Correction }
#include "NtwDia.hpp"
#include "NtwObj.hpp"
#include "NtwMod.hpp"
#include "x:\cpa\main\inc\_editid.h"


//--------------------------------------- Script definition
static char* pszGraphAction = "WPGraph";
static char* pszSommetAction = "WPSommet";

//----------------------------------------------- static variables
NtwDia* Graph::ms_poNtwDia;
CPA_List<Graph> Graph::ms_oListOfGraph;
BOOL Graph::ms_bNotifyHeader;
Waypoint_Interface* Graph::ms_poInterface;
		

DeclareTemplateStatic(WP_tdHandleOfGraph); 


void Graph::fn_vSetDialog ( NtwDia* poNtwDia )
{
	ms_poNtwDia = poNtwDia;
	ms_poNtwDia->fn_vInitDialog ();
}


WP_tdHandleOfGraph fn_hCreate ()
{
	WP_tdHandleOfGraph hGraph = WPG_fn_hCreate ("", "");
	WPG_fn_vAddGlobalGraph(hGraph);
	return hGraph;
//	return NULL;
}

void fn_vDestroy(WP_tdHandleOfGraph h)
{
	if (M_GetMainApp()->m_bLeavingApplication == TRUE)
		return;
	WPG_fn_vDestroy(h);
}


void fn_vCopy(WP_tdHandleOfGraph hDst, WP_tdHandleOfGraph hSrc)
{
	WPG_fn_vCopy(hDst, hSrc);
}

void Graph::fn_vInitObject (Waypoint_Interface* poInterface)
{
	// init Edmot
	CPA_EdMot<WP_tdHandleOfGraph>::Init (fn_hCreate, fn_vCopy, fn_vDestroy);
	ms_bNotifyHeader=FALSE;
	ms_poInterface = poInterface;
}


void Graph::fn_vRefreshGraph (void)
{
	fn_pGetDialog()->fn_vRefreshDialog();
}

Graph* Graph::fn_pGetGraph(WP_tdhWayPoint hWP)
{
	POSITION lPos;
	for (Graph* poGraph = Graph::ms_oListOfGraph.GetHeadElement(lPos); poGraph; poGraph= Graph::ms_oListOfGraph.GetNextElement(lPos))
	{
		if (poGraph->fn_bHasNode(hWP))
			return poGraph;
	}
	return NULL;
}

// to create a new instance
Graph::Graph(CPA_ObjectDLLBase *p_oDLL, CString csName, BOOL bSave) :
	CPA_SaveObject ( p_oDLL, C_szGraphTypeName, E_ss_Responsible )
{
	m_bSave=bSave;
	m_poSuperObject = NULL;
	ms_oListOfGraph.AddTail (this);

	// Set the graph reference
	char szLevelFileName [256];
	char szSectionName [SCR_CV_ui_Cfg_MaxLenName];
	fn_zsGetActualLevelFilename (szLevelFileName, "wp");
	long lSizePath = strlen(fn_szGetLevelsDataPath());
	CString csLevelName = szLevelFileName + lSizePath + 1;
	csLevelName += "^";
	csLevelName += C_SubSectionIsolateWayPointDescription;
	csLevelName += "^";
	csLevelName += C_SectionWayPointDescription;
	csLevelName += ":";
	WPG_fn_vSetReferenceSection(GetEngineStruct(), csLevelName);	
	// Init the WP_tdHandleOfGraph structure.
//	WP_tdHandleOfGraph hGraph = WPG_fn_hCreate((char*)(LPCSTR)csName, (char*)(LPCSTR)csLevelName);
//	WPG_fn_vAddGlobalGraph(hGraph);
//	SetStruct(hGraph);

	csLevelName = szLevelFileName + lSizePath + 1;
	// section object
	SetSectionData	(this) ; 	
	SetCallBackSave (fn_vCallbackSave) ; 	
	SetDataPath		(fn_szGetLevelsDataPath());	
	SCR_fn_v_RdL0_ComputeSectionName ( szSectionName, (char *)(LPCSTR)csLevelName, pszGraphAction, " ");
	SetReferencedSectionName (szSectionName);

	// name
	if ( fn_eRename (csName) != E_mc_None)
		SetDefaultValidName();

	// Set the graph name
	WPG_fn_vSetNameOfGraph(GetEngineStruct(), GetName());

	fn_vUpdateSectionName();

	SetExistingSection (FALSE);

	fn_vNotifySave ();

	// add graph to linktable
	SCR_tdst_Link_Value *pValue = SCR_fnp_st_Link_SearchValue(WPG_fnp_Graph_GetLinkTable(), (unsigned long) GetEngineStruct());
	if (pValue)
	{
		SCR_fn_v_Link_DeleteEntry(WPG_fnp_Graph_GetLinkTable(), pValue);
	}

	WPG_fn_vAddGlobalGraph(GetEngineStruct());

// Shaitan Correction {
	fn_vInitGraphicConnections();
//End Shaitan Correction }

}


// to load a graph
Graph::Graph ( CPA_ObjectDLLBase *p_oDLL, WP_tdHandleOfGraph hEngineGraph, CString csName, CString csFileName, CString csSectionName ):
	CPA_SaveObject ( p_oDLL, C_szGraphTypeName, E_ss_Responsible ),
	CPA_EdMot<WP_tdHandleOfGraph>(hEngineGraph)
{
		
	char szSectionName [SCR_CV_ui_Cfg_MaxLenName];
	m_bSave=TRUE;
	m_poSuperObject = NULL;
	ms_oListOfGraph.AddTail (this);

	// section object
	SetSectionData	( this ) ; 	
	SetCallBackSave ( fn_vCallbackSave ) ; 	
	SetDataPath		( fn_szGetLevelsDataPath() ) ;

	SCR_fn_v_RdL0_ComputeSectionName ( szSectionName, (char *)(LPCSTR)csFileName, pszGraphAction, " ");
	SetReferencedSectionName (szSectionName);

	// name
	if (fn_eRename (csName) != E_mc_None)
		SetDefaultValidName() ;
	
	fn_vUpdateSectionName() ;

	SetExistingSection(TRUE) ;

	if (!GetEditor()->GetInterface()->fn_bIsLoadingWorld())
		fn_vNotifySave ();

// Shaitan Correction {
	fn_vInitGraphicConnections();
//End Shaitan Correction }
	
}


Graph::Graph( Graph& rGraph):
	CPA_SaveObject ( ms_poInterface, C_szGraphTypeName, E_ss_Responsible ),
	CPA_EdMot<WP_tdHandleOfGraph>(rGraph)
{
	m_poSuperObject = NULL;
	m_bSave=rGraph.m_bSave;
	ms_oListOfGraph.AddTail (this);

	fn_vCopy (GetStruct(), rGraph.GetStruct());


	// section object
	SetSectionData	( this ) ; 	
	SetCallBackSave ( fn_vCallbackSave ) ; 	
	SetDataPath		( fn_szGetLevelsDataPath() ) ;	
	
	SetReferencedSectionName ( rGraph.GetReferencedSectionName() );

	// name
	if (fn_eRename (rGraph.GetName() ) != E_mc_None)
		SetDefaultValidName ( ) ;
	
	fn_vUpdateSectionName ( ) ;

	// Set the graph name
	WPG_fn_vSetNameOfGraph(GetEngineStruct(), GetName());

	fn_vNotifySave ();

	// add graph to linktable
	WPG_fn_vAddGlobalGraph(GetEngineStruct());
		
// Shaitan Correction {
	fn_vInitGraphicConnections();
//End Shaitan Correction }

}


Graph::~Graph(void)
{
	fn_vNotifyUnSave ();

	POSITION DeletePos = ms_oListOfGraph.Find(this);
	ms_oListOfGraph.RemoveAt(DeletePos);
}

Graph& Graph::operator= (Graph& rGraph)
{
	m_bSave = rGraph.m_bSave;
	fn_vCopy(GetStruct(), rGraph.GetStruct());
	return *this;
}

long Graph::GetDataType (void)
{
	return C_ucGraph;
}

tdeMissingCriteria Graph::fn_eCheckUnicity (const CString csNewName)
{ 
	return E_mc_None;
}

WayPoint* Graph::GetWaypoint(WP_tdhWayPoint hWP)
{
	CPA_BaseObject* poBaseObject = GetInterface()->GetMainWorld()->fn_p_oFindObjectWithEngine (hWP);
	ASSERT ( poBaseObject );
	return (WayPoint*)poBaseObject;
}

// Shaitan Correction {
void Graph::fn_vAddNode(WP_tdhWayPoint hWP, BOOL pBlock)
{
	WayPoint	*pNode;
	InsertNode	*pModif;

	if (fn_bHasNode(hWP))
		return;

	// get parameters
	pNode = GetWaypoint(hWP);
	// create modification
	pModif = new InsertNode(this, pNode, pBlock);
	GetInterface()->GetInterface()->GetMultiDevice()->GetEditManager()->AskFor(pModif);

/*	ModifGraph *pModif = new ModifGraph(this, GRAPH_INSERT_NODE);
	WPG_fn_lAddWayPointIfNotExists(GetEngineStruct(), hWP, 0L); // BART
	pModif->ModifSave();
//	GetInterface()->GetInterface()->GetMultiDevice()->GetEditManager()->AskFor(pModif);
*/
}

void Graph::fn_vAddNode(WayPoint *pNode, BOOL pBlock)
{
	InsertNode	*pModif;

	if (fn_bHasNode(pNode->GetStruct()))
		return;

	// create modification
	pModif = new InsertNode(this, pNode, pBlock);
	GetInterface()->GetInterface()->GetMultiDevice()->GetEditManager()->AskFor(pModif);
}

BOOL Graph::fn_bRemoveNode(int iNode, BOOL pBlock)
{
	WP_tdhWayPoint	hWayPoint = fn_hGetWayPointOfNode(iNode);
	DeleteNode		*pModif;
	WayPoint		*pNode;

	if (!fn_bHasNode(hWayPoint))
		return FALSE;

	// get parameters
	pNode = GetWaypoint(hWayPoint);
	// create modification
	pModif = new DeleteNode(this, pNode, pBlock);
	GetInterface()->GetInterface()->GetMultiDevice()->GetEditManager()->AskFor(pModif);

	return TRUE;
/*
	ModifGraph *pModif = new ModifGraph(this, GRAPH_DELETE_NODE, bGroup);
	int i ;
	WP_tdhGraphNode hNode, hNextNode ;
	WP_tdhWayPoint hWayPoint = fn_hGetWayPointOfNode(iNode);
	LST2_M_DynamicForEachMovingElementOf(&GetEngineStruct()->m_hListOfNode, hNode, hNextNode, i)
	{
		WPG_fn_lRemoveArcFromWayPoint(GetEngineStruct(), hNode->m_hWayPoint, hWayPoint);
	}
	BOOL bRet = WPG_fn_lRemoveWayPoint(GetEngineStruct(), hWayPoint) != -1;
	pModif->ModifSave();
	GetInterface()->GetInterface()->GetMultiDevice()->GetEditManager()->AskFor(pModif);
	return bRet;
*/
}

BOOL Graph::fn_bRemoveNode(WayPoint	*pNode, BOOL pBlock)
{
	DeleteNode		*pModif;

	if (!fn_bHasNode(pNode->GetStruct()))
		return FALSE;

	// create modification
	pModif = new DeleteNode(this, pNode, pBlock);
	GetInterface()->GetInterface()->GetMultiDevice()->GetEditManager()->AskFor(pModif);

	return TRUE;
}
//End Shaitan Correction }

WP_tdhWayPoint Graph::fn_hGetWayPointOfNode(int iNode)
{
  long lTypeOfWP; //BART
	ASSERT(iNode >= 0 && iNode < WPG_fn_lNumberOfWaypointOfGraph(GetEngineStruct()));
	return WPG_fn_hGetWaypointOfGraph(GetEngineStruct(), iNode, &lTypeOfWP);
}

int Graph::fn_iGetNodeOfWayPoint(WP_tdhWayPoint hWP)
{
	int i;
	WP_tdhGraphNode hNode;
	LST2_M_DynamicForEachElementOf(&GetEngineStruct()->m_hListOfNode, hNode, i)
	{
		if (hNode->m_hWayPoint == hWP)
			return i;
	}
	return -1;
}


WP_tdhGraphNode Graph::fn_hGetNode(int iNode)
{
	ASSERT(iNode >= 0 && iNode < WPG_fn_lNumberOfWaypointOfGraph(GetEngineStruct()));
	int i;
	WP_tdhGraphNode hNode;
	LST2_M_DynamicGetElementNumber(&GetEngineStruct()->m_hListOfNode, hNode, iNode, i);
	return hNode;
}

int Graph::fn_iGetNumberOfArcs(WP_tdhGraphNode hNode)
{
	ASSERT(hNode); 
	return LST2_M_DynamicGetNumberOfElements(&hNode->m_hListOfArc->m_hArc);
}

WP_tdHandleOfArc Graph::fn_hGetArc(WP_tdhGraphNode hNode, int iArc)
{
	ASSERT(iArc >= 0 && iArc < fn_iGetNumberOfArcs(hNode));
	int i;
	WP_tdHandleOfArc hArc;
	LST2_M_DynamicGetElementNumber(&hNode->m_hListOfArc->m_hArc, hArc, iArc, i);
	return hArc;
}

int Graph::fn_iGetArcOfNode(WP_tdhGraphNode hNode, WP_tdhGraphNode hArcNode)
{
	int i;
	WP_tdHandleOfArc hArc;
	LST2_M_DynamicForEachElementOf(&hNode->m_hListOfArc->m_hArc, hArc, i)
	{
		if (hArc->m_hNode == hArcNode)
			return i;
	}
	return -1;
}

// Shaitan Correction {
void Graph::fn_vAddArcToNode(WP_tdhGraphNode hNode, WP_tdhGraphNode hArcNode, BOOL pBlock)
{
	WayPoint			*pSrcNode;
	WayPoint			*pDstNode;
	InsertConnection	*pModif;

	if (fn_bNodeHasArc(hNode, hArcNode))
		return;

	// get parameters
	pSrcNode = GetWaypoint(hNode->m_hWayPoint);
	pDstNode = GetWaypoint(hArcNode->m_hWayPoint);
	// create modification
	pModif = new InsertConnection(this, pSrcNode, pDstNode, TRUE, pBlock);
	GetInterface()->GetInterface()->GetMultiDevice()->GetEditManager()->AskFor(pModif);

/*
	if (fn_bNodeHasArc(hNode, hArcNode))
		return;

	ModifGraph *pModif = new ModifGraph(this, GRAPH_INSERT_ARC);
	WPG_fn_vAddArc(hNode, hArcNode, 0, 0);
	pModif->ModifSave();
//	GetInterface()->GetInterface()->GetMultiDevice()->GetEditManager()->AskFor(pModif);
*/
}

void Graph::fn_vAddArcToNode(WayPoint *pSrcNode, WayPoint *pDstNode, BOOL bUpdate, BOOL pBlock)
{
	InsertConnection	*pModif;

	if (GetGraphicConnection(pSrcNode, pDstNode) != NULL)
		return;

	// create modification
	pModif = new InsertConnection(this, pSrcNode, pDstNode, bUpdate, pBlock);
	GetInterface()->GetInterface()->GetMultiDevice()->GetEditManager()->AskFor(pModif);
}

void Graph::fn_vRemoveArcOfNode(WP_tdhGraphNode hNode, int iArc, BOOL pBlock)
{
	WayPoint			*pSrcNode;
	WayPoint			*pDstNode;
	DeleteConnection	*pModif;

	// get parameters
	pSrcNode = GetWaypoint(hNode->m_hWayPoint);
	pDstNode = GetWaypoint(fn_hGetArc(hNode, iArc)->m_hNode->m_hWayPoint);
	// create modification
	pModif = new DeleteConnection(this, pSrcNode, pDstNode, pBlock);
	GetInterface()->GetInterface()->GetMultiDevice()->GetEditManager()->AskFor(pModif);
/*
	ModifGraph *pModif = new ModifGraph(this, GRAPH_DELETE_ARC);
	WPG_fn_vRemoveArc(hNode, fn_hGetArc(hNode, iArc)->m_hNode);
	pModif->ModifSave();
//	GetInterface()->GetInterface()->GetMultiDevice()->GetEditManager()->AskFor(pModif);
*/
}

void Graph::fn_vRemoveArcOfNode(WayPoint *pSrcNode, WayPoint *pDstNode, BOOL pBlock)
{
	DeleteConnection	*pModif;

	// create modification
	pModif = new DeleteConnection(this, pSrcNode, pDstNode, pBlock);
	GetInterface()->GetInterface()->GetMultiDevice()->GetEditManager()->AskFor(pModif);
/*
	ModifGraph *pModif = new ModifGraph(this, GRAPH_DELETE_ARC);
	WPG_fn_vRemoveArc(hNode, fn_hGetArc(hNode, iArc)->m_hNode);
	pModif->ModifSave();
//	GetInterface()->GetInterface()->GetMultiDevice()->GetEditManager()->AskFor(pModif);
*/
}
//End Shaitan Correction }

void Graph::fn_vSetDefaultArcWeight(WP_tdhGraphNode hNode, int iArc)
{
	WP_tdHandleOfArc hArc = fn_hGetArc(hNode, iArc);
	MTH3D_tdstVector m_vertex1, m_vertex2;
	WP_fnv_WayPoint_ComputeLocation(hNode->m_hWayPoint, &m_vertex1);
	WP_fnv_WayPoint_ComputeLocation(hArc->m_hNode->m_hWayPoint, &m_vertex2);
	MTH_tdxReal dx = m_vertex1.xX - m_vertex2.xX;
	MTH_tdxReal dy = m_vertex1.xY - m_vertex2.xY; 
	MTH_tdxReal dz = m_vertex1.xZ - m_vertex2.xZ;
	long lDist = (long)sqrt(dx * dx + dy * dy + dz * dz);
	WPARC_fn_lSetWeight(hArc, lDist);
}

// Shaitan NewParam {
void Graph::fn_vSetDefaultAllArcsWeight()
{
	WP_tdHandleOfArc	hArc;
	WP_tdhGraphNode		hNode;
	WayPoint			*pSrcNode, *pDstNode;
	long				lWeight;
	int					iNode, iArc;

	LST2_M_DynamicForEachElementOf(&GetEngineStruct()->m_hListOfNode, hNode, iNode)
	{
		for (iArc = 0; iArc < fn_iGetNumberOfArcs(hNode); iArc++)
		{
			hArc = fn_hGetArc(hNode, iArc);
			pSrcNode = GetWaypoint(hNode->m_hWayPoint);
			pDstNode = GetWaypoint(hArc->m_hNode->m_hWayPoint);
			lWeight = fn_lGetDefaultArcWeight(pSrcNode, pDstNode);
			SetConnectionWeight(pSrcNode, pDstNode, lWeight);
		}
	}

	// notify
	fn_vNotifySave();
}

long Graph::fn_lGetDefaultArcWeight(WayPoint* pSrcNode, WayPoint* pDstNode)
{
	MTH3D_tdstVector	stVertex1, stVertex2;
	MTH_tdxReal			dx, dy, dz;
	long				lDist;

	// compute distance
	WP_fnv_WayPoint_ComputeLocation(pSrcNode->GetStruct(), &stVertex1);
	WP_fnv_WayPoint_ComputeLocation(pDstNode->GetStruct(), &stVertex2);
	dx = stVertex1.xX - stVertex2.xX;
	dy = stVertex1.xY - stVertex2.xY; 
	dz = stVertex1.xZ - stVertex2.xZ;
	
	lDist = (long)sqrt(dx * dx + dy * dy + dz * dz);
	return lDist;
}

void Graph::fn_vSetAllArcsCapacity(long lCapacity)
{
	WP_tdHandleOfArc	hArc;
	WP_tdhGraphNode		hNode;
	WayPoint			*pSrcNode, *pDstNode;
	int					iNode, iArc;

	LST2_M_DynamicForEachElementOf(&GetEngineStruct()->m_hListOfNode, hNode, iNode)
	{
		for (iArc = 0; iArc < fn_iGetNumberOfArcs(hNode); iArc++)
		{
			hArc = fn_hGetArc(hNode, iArc);
			pSrcNode = GetWaypoint(hNode->m_hWayPoint);
			pDstNode = GetWaypoint(hArc->m_hNode->m_hWayPoint);
			SetConnectionCapacity(pSrcNode, pDstNode, lCapacity);
		}
	}
	// notify
	fn_vNotifySave();
}

//End Shaitan NewParam }

//-------------------------------------------------------------------
// SAVE
//-------------------------------------------------------------------
void Graph::fn_vNotifySave	(void)
{
	if (!m_bSave) return;
	
	if (!GetInterface()->fn_bExistWaypointSaveFile() && !ms_bNotifyHeader)
	{
		char szSectionName [SCR_CV_ui_Cfg_MaxLenName];

		// header
		SCR_fn_v_SvL1_RegisterNotify ( GetInterface()->fn_csGetWaypointSaveFileName().GetBuffer(256), WayPoint::fn_vCallbackHeader, NULL, SCR_EA_Ntfy_AddSection );

		// Isolate section
		SCR_fn_v_RdL0_ComputeSectionName
		( 
			szSectionName,
			GetInterface()->fn_csGetWaypointSaveFileName().GetBuffer(256), 
			C_SubSectionIsolateWayPointDescription, 
			" "
		);
		SCR_fn_v_SvL1_RegisterNotify ( szSectionName, WayPoint::fn_vCallbackEmptySectionWaypointIsolate, NULL, SCR_EA_Ntfy_AddSection );

		// Inway section
		SCR_fn_v_RdL0_ComputeSectionName
		( 
			szSectionName,
			GetInterface()->fn_csGetWaypointSaveFileName().GetBuffer(256), 
			C_SubSectionInWayWayPointDescription, 
			" "
		);
		SCR_fn_v_SvL1_RegisterNotify ( szSectionName, WayPoint::fn_vCallbackEmptySectionWaypointInWay, NULL, SCR_EA_Ntfy_AddSection );

		//Graph section
		SCR_fn_v_RdL0_ComputeSectionName
		( 
			szSectionName,
			GetInterface()->fn_csGetWaypointSaveFileName().GetBuffer(256), 
			C_SectionWPGraphDescription, 
			" "
		);
		SCR_fn_v_SvL1_RegisterNotify ( szSectionName, Graph::fn_vCallbackEmptySectionWPGraph, NULL, SCR_EA_Ntfy_AddSection );

		//WPSommet section
		SCR_fn_v_RdL0_ComputeSectionName
		( 
			szSectionName,
			GetInterface()->fn_csGetWaypointSaveFileName().GetBuffer(256), 
			C_SectionWPSommetDescription,
			" "
		);
		SCR_fn_v_SvL1_RegisterNotify ( szSectionName, Graph::fn_vCallbackEmptySectionWPSommet, NULL, SCR_EA_Ntfy_AddSection );

		ms_bNotifyHeader=TRUE;
	} 

	 CPA_SaveObject::fn_vNotifySave();
	  
}

void Graph::fn_vNotifyUnSave (void)
{
	if (m_bSave) CPA_SaveObject::fn_vNotifyUnSave ();
}

void Graph::fn_vNotifyRestore (void)
{
	if (m_bSave) CPA_SaveObject::fn_vNotifyRestore ();
}

void Graph::fn_vNotifyRename (void)
{
	if (m_bSave) CPA_SaveObject::fn_vNotifyRename ();
}

void Graph::fn_vUpdateReference (CPA_SaveObject *pReferencedObject)
{
	if (m_bSave) fn_vUpdateReference (pReferencedObject);
}

// create empty section for WPGraph
void Graph::fn_vCallbackEmptySectionWPGraph ( SCR_tdst_File_Description *p_stFile, char *p_szSectionName, void *_p_vData,SCR_tde_Ntfy_Action	_eAction )
{
	if (_eAction==SCR_EA_Ntfy_AddSection)
	{
		char szSectionName [SCR_CV_ui_Cfg_MaxLenName];
		strcpy ( szSectionName, C_SectionWPGraphDescription );
		strcat ( szSectionName, ":" );

		SCR_fn_v_SvL1_ToEndSection (p_stFile);
		SCR_M_SvL0_SaveBlankLine (p_stFile);
		SCR_M_SvL0_SaveBeginSection ( p_stFile, szSectionName, SCR_CC_C_Cfg_EOL );
		SCR_M_SvL0_SaveEndSection ( p_stFile, SCR_CC_C_Cfg_EOL );
	}
}

// create empty section for WPSommet
void Graph::fn_vCallbackEmptySectionWPSommet ( SCR_tdst_File_Description *p_stFile, char *p_szSectionName, void *_p_vData,SCR_tde_Ntfy_Action	_eAction )
{
	if (_eAction==SCR_EA_Ntfy_AddSection)
	{
		char szSectionName [SCR_CV_ui_Cfg_MaxLenName];
		strcpy ( szSectionName, C_SectionWPSommetDescription );
		strcat ( szSectionName, ":" );

		SCR_fn_v_SvL1_ToEndSection (p_stFile);
		SCR_M_SvL0_SaveBlankLine (p_stFile);
		SCR_M_SvL0_SaveBeginSection ( p_stFile, szSectionName, SCR_CC_C_Cfg_EOL );
		SCR_M_SvL0_SaveEndSection ( p_stFile, SCR_CC_C_Cfg_EOL );
	}
}


void Graph::fn_vCallbackSave ( SCR_tdst_File_Description *_p_stFile, char *_p_szSectionName, void *_p_vData,SCR_tde_Ntfy_Action	_eAction )
{
	fn_pGetDialog()->UpdateData();
	Graph* poGraph = (Graph*)_p_vData;
	CString ref;

	switch (_eAction)
	{
	case SCR_EA_Ntfy_AddSection :
		SCR_fn_v_SvL1_ToEndSection (_p_stFile);

	case SCR_EA_Ntfy_ModifySection :
	case SCR_EA_Ntfy_RebuildSection :
		{
			// declaration
			WP_tdHandleOfGraph hGraph;
			char szSectionName [SCR_CV_ui_Cfg_MaxLenName];
			char szObjectName [SCR_CV_ui_Cfg_MaxLenName];

			//init
			hGraph = (WP_tdHandleOfGraph)(poGraph->GetStruct());
			strcpy ( szObjectName,	poGraph->GetName() );

			SCR_fn_v_RdL0_ComputeSectionName
			( 
				szSectionName, 
				NULL,
				pszGraphAction, 
				szObjectName
			);
	
			SCR_M_SvL0_SaveBeginSection ( _p_stFile, szSectionName, SCR_CC_C_Cfg_NoChar );
			SCR_fn_v_SvL0_SaveParameters_MP( _p_stFile, SCR_EF_SvL0_Normal, 1, WPG_fn_szGetReferenceSection( hGraph ));

			for(int i = 0; i < poGraph->fn_iGetNumberOfNodes(); i++)
			{
				WP_tdhGraphNode hNode = poGraph->fn_hGetNode(i);
				strcpy ( szObjectName, GetWaypoint(hNode->m_hWayPoint)->GetName());
				SCR_fn_v_RdL0_ComputeSectionName
				( 
					szSectionName, 
					NULL,
					pszSommetAction, 
					szObjectName
				);
				SCR_g_ui_SvL0_IndentationLevel=1;
				
				long lType;
				WPG_fn_hGetWaypointOfGraph(poGraph->GetStruct(), i, &lType);

// Shaitan NewParam {
				if (lType !=0)
				{
					SCR_M_SvL0_SaveBeginSection ( _p_stFile, szSectionName, SCR_CC_C_Cfg_NoChar );
					char szType[33];
					for (int i = 31, iMask = 1; i >= 0; i--, iMask <<= 1)
						szType[i] = (lType & iMask) ? '1' : '0';
					szType[32] = '\0';
					SCR_fn_v_SvL0_SaveParameters_MP( _p_stFile, SCR_EF_SvL0_Scanf, 1, "%s", szType);
				}
				else
					SCR_M_SvL0_SaveBeginSection ( _p_stFile, szSectionName, SCR_CC_C_Cfg_EOL );
//End Shaitan NewParam }

				for(int j = 0; j < poGraph->fn_iGetNumberOfArcs(hNode); j++)
				{
					WP_tdHandleOfArc hArc = poGraph->fn_hGetArc(hNode,j);
					SCR_M_SvL0_SaveEntry( _p_stFile, (char*)(LPCSTR)GetWaypoint(hArc->m_hNode->m_hWayPoint)->GetName(), SCR_CC_C_Cfg_NoChar );
					long lWeight = WPARC_fn_lGetWeight(hArc);
					char szCapacity[33];
					int iCapacity = WPARC_fn_ulGetCapability(hArc);
					for (int i = 31, iMask = 1; i >= 0; i--, iMask <<= 1)
						szCapacity[i] = (iCapacity & iMask) ? '1' : '0';
					szCapacity[32] = '\0';
					SCR_fn_v_SvL0_SaveParameters_MP( _p_stFile, SCR_EF_SvL0_Scanf, 2, "%i,%s", lWeight, szCapacity);
				}

				SCR_M_SvL0_SaveEndSection (_p_stFile, SCR_CC_C_Cfg_EOL);
				SCR_g_ui_SvL0_IndentationLevel=0;
			}

			SCR_M_SvL0_SaveEndSection (_p_stFile, SCR_CC_C_Cfg_EOL);
			SCR_g_ui_SvL0_IndentationLevel=0;
			poGraph->fn_vSectionSaved ();

		} break;

		case SCR_EA_Ntfy_DeleteSection :
			poGraph->fn_vSectionDeleted ();
			break;

	}
}


// Shaitan Correction {
/*
Connection::Connection(CPA_EditorBase *p_oEditor, int iGraph, int iNode, int iArc)
	: Arrow3D(TRUE, p_oEditor)
{
	fn_vDoRename("Connection");
	m_iGraph = iGraph;
	m_iNode = iNode;
	m_iArc = iArc;
}
*/
//End Shaitan Correction }

//ENDROMTEAM Networks (Gabriela Dumitrascu)

// Shaitan Correction {
Connection::Connection(CPA_EditorBase *p_oEditor, Graph *pGraph, WayPoint *pSrcWP, WayPoint *pDstWP, long lCapacity, long lWeight)
	: Arrow3D(TRUE, p_oEditor)
{
	fn_vDoRename("Connection");
	m_pGraph = pGraph;
	m_pSrcWP = pSrcWP;
	m_pDstWP = pDstWP;
	m_lCapacity = lCapacity;
	m_lWeight = lWeight;
}


void Graph::fn_vInitGraphicConnections (void)
{
	WP_tdHandleOfArc	hArc;
	WP_tdhGraphNode		hSrcNode;
	CPA_SuperObject		*poArrow;
	WayPoint			*pSrcNode;
	WayPoint			*pDstNode;
	int					iNode, iArc;
	
	for (iNode = 0; iNode < fn_iGetNumberOfNodes(); iNode++)
	{
		hSrcNode = fn_hGetNode(iNode);
		pSrcNode = GetWaypoint(hSrcNode->m_hWayPoint);
		
		for (iArc = 0; iArc < fn_iGetNumberOfArcs(hSrcNode); iArc++)
		{
			hArc = fn_hGetArc(hSrcNode, iArc);
			pDstNode = GetWaypoint(hArc->m_hNode->m_hWayPoint);
			poArrow = GetInterface()->fn_pCreateConnectionGraphicObject(this, pSrcNode, pDstNode, WPARC_fn_ulGetCapability(hArc), WPARC_fn_lGetWeight(hArc));
			ms_oListOfArrows.AddTail(poArrow);
		}
	}
}

void Graph::fn_vUpdateConnection (CPA_SuperObject *pConnection, BOOL bUpdate)
{
	GEO_tdxHandleToMatrix	hLocalMatrix;
	POS_tdstCompletePosition stInvertMatrix;
	MTH3D_tdstMatrix		stRotZMatrix, stRotXMatrix, stScaleMatrix;
	MTH3D_tdstVector		stVertex1, stVertex2, stVertexZ, stTransVect;
	MTH_tdxReal				cx, cy, cz, d, dist;
	Connection				*pLinkObject = (Connection *) pConnection->GetObject();
	WayPoint				*pSrcWP = pLinkObject->GetSrcWayPoint();
	WayPoint				*pDstWP = pLinkObject->GetDstWayPoint();

	hLocalMatrix = HIE_fn_hGetSuperObjectMatrix (pConnection->GetStruct());

	// compute arrow direction
	WP_fnv_WayPoint_ComputeLocation((WP_tdhWayPoint)pSrcWP->GetEngineStruct(), &stVertex1);
	WP_fnv_WayPoint_ComputeLocation((WP_tdhWayPoint)pDstWP->GetEngineStruct(), &stVertex2);
	MTH3D_M_vSubVector( &stVertex2,&stVertex2,&stVertex1 );
	dist = MTH3D_M_xNormVector(&stVertex2);
	stVertex2.xZ = -stVertex2.xZ;

	// compute rotation matrix
	MTH3D_M_vNormalizeVector(&stVertex2,&stVertex2);
	if ((stVertex2.xX == 0 && stVertex2.xY ==0))
	{
		stVertex2.xX = 0.01f;
		stVertex2.xY = 0.01f;
	}

	cx = MTH3D_M_xGetXofVector(&stVertex2);
	cy = MTH3D_M_xGetYofVector(&stVertex2);
	cz = MTH3D_M_xGetZofVector(&stVertex2);
	d  = (float)sqrt(cx * cx + cy * cy);

	MTH3D_M_vSetVectorElements(&stRotZMatrix.stCol_0, cy/d, -cx/d, 0);
	MTH3D_M_vSetVectorElements(&stRotZMatrix.stCol_1, cx/d,  cy/d, 0);
	MTH3D_M_vSetVectorElements(&stRotZMatrix.stCol_2,    0,     0, 1);
	MTH3D_M_vSetVectorElements(&stRotXMatrix.stCol_0, 1,  0,  0);
	MTH3D_M_vSetVectorElements(&stRotXMatrix.stCol_1, 0, cz,  d);
	MTH3D_M_vSetVectorElements(&stRotXMatrix.stCol_2, 0, -d, cz);
	MTH3D_M_vMulMatrixMatrix(&stRotXMatrix, &stRotZMatrix, &stRotXMatrix);
	MTH3D_M_vInverMatrix(&stRotZMatrix, &stRotZMatrix);
	MTH3D_M_vMulMatrixMatrix(&stRotXMatrix, &stRotXMatrix, &stRotZMatrix);

	MTH3D_M_vSetVectorElements(&stVertexZ, 0, 0, 1);
	MTH3D_M_vMulMatrixVector(&stVertexZ, &stRotXMatrix, &stVertexZ);
	if (stVertex2.xX * stVertexZ.xX > 0)
		MTH3D_M_vMulScalarVector(&stRotXMatrix.stCol_0, -1,&stRotXMatrix.stCol_0);
	if (stVertex2.xY * stVertexZ.xY > 0)
		MTH3D_M_vMulScalarVector(&stRotXMatrix.stCol_1, -1,&stRotXMatrix.stCol_1);
	if (stVertex2.xZ * stVertexZ.xZ >= 0)
		MTH3D_M_vMulScalarVector(&stRotXMatrix.stCol_2, -1,&stRotXMatrix.stCol_2);

	POS_fn_vSetRotationMatrix(hLocalMatrix , &stRotXMatrix.stCol_0, &stRotXMatrix.stCol_1, &stRotXMatrix.stCol_2);
	POS_fn_vNormalizeMatrix(hLocalMatrix);

	// Translate arrow to waypoint
	MTH3D_M_vSetVectorElements(&stTransVect, stVertex2.xX * dist, stVertex2.xY * dist, -stVertex2.xZ * dist);
	POS_fn_vSetTranslationVector(hLocalMatrix, &stTransVect);

	// for dynamic WPs : update matrix with WP matrix
	POS_fn_vInvertMatrix(&stInvertMatrix, HIE_fn_hGetSuperObjectGlobalMatrix(pSrcWP->GetSuperObject()->GetStruct()));
	MTH3D_M_vSetVectorElements(&stVertex1, 0.0f, 0.0f, 0.0f);
	POS_fn_vSetTranslationVector(&stInvertMatrix, &stVertex1);
	POS_fn_vMulMatrixMatrix(hLocalMatrix, &stInvertMatrix, hLocalMatrix);
	POS_fn_vNormalizeMatrix(hLocalMatrix);

	// scale the arrow.
	MTH3D_M_vSetVectorElements(&stScaleMatrix.stCol_0, 0.3f,    0,         0);
	MTH3D_M_vSetVectorElements(&stScaleMatrix.stCol_1,    0, 0.3f,         0);
	MTH3D_M_vSetVectorElements(&stScaleMatrix.stCol_2,    0,    0,    dist/1.2f);
	POS_fn_vSetScaleMatrix(hLocalMatrix , &stScaleMatrix.stCol_0, &stScaleMatrix.stCol_1, &stScaleMatrix.stCol_2);

	if (bUpdate)
		GetInterface()->GetInterface()->fn_vUpdateAll (E_mc_JustDraw);
}

void Graph::fn_vDisplayConnection (CPA_SuperObject *pConnection, BOOL bUpdate)
{
	Connection	*pLinkObject = (Connection *) pConnection->GetObject();
	WayPoint	*pSrcWP = pLinkObject->GetSrcWayPoint();

	// create the connection arrow
	pConnection->SetSuperObjectOwner(pSrcWP->GetSuperObject());	
	pSrcWP->GetSuperObject()->AddTail(pConnection);

	// update position
	fn_vUpdateConnection(pConnection, bUpdate);

}

void Graph::fn_vDisplayAllLinks (BOOL bDisplay, BOOL bUpdate)
{
	CPA_SuperObject *pConnection;
	POSITION		pos;

	for (pConnection = ms_oListOfArrows.GetHeadElement(pos); pConnection; pConnection = ms_oListOfArrows.GetNextElement(pos))
	{
		if (bDisplay)
			fn_vDisplayConnection(pConnection, FALSE);
		else
			pConnection->IsolateChild();
	}
	
	if (bUpdate)
		GetInterface()->GetInterface()->fn_vUpdateAll (E_mc_JustDraw);
}

void Graph::fn_vDisplayOutLinks (WayPoint* pSrcNode, BOOL bUpdate)
{
	CPA_SuperObject *pConnection;
	Connection		*pLinkObject;
	POSITION		pos;

	for (pConnection = ms_oListOfArrows.GetHeadElement(pos); pConnection; pConnection = ms_oListOfArrows.GetNextElement(pos))
	{
		pLinkObject = (Connection *) pConnection->GetObject();
		if (pLinkObject->GetSrcWayPoint() == pSrcNode)
			fn_vDisplayConnection(pConnection, FALSE);
		else
			pConnection->IsolateChild();
	}

	if (bUpdate)
		GetInterface()->GetInterface()->fn_vUpdateAll (E_mc_JustDraw);
}

void Graph::fn_vDisplayInLinks (WayPoint* pDstNode, BOOL bUpdate)
{
	CPA_SuperObject *pConnection;
	Connection		*pLinkObject;
	POSITION		pos;

	for (pConnection = ms_oListOfArrows.GetHeadElement(pos); pConnection; pConnection = ms_oListOfArrows.GetNextElement(pos))
	{
		pLinkObject = (Connection *) pConnection->GetObject();
		if (pLinkObject->GetDstWayPoint() == pDstNode)
			fn_vDisplayConnection(pConnection, FALSE);
		else
			pConnection->IsolateChild();
	}

	if (bUpdate)
		GetInterface()->GetInterface()->fn_vUpdateAll (E_mc_JustDraw);
}

void Graph::fn_vUpdateConnections (WayPoint *pMovedWP, BOOL bUpdate)
{
	CPA_SuperObject *pConnection;
	Connection		*pLinkObject;
	POSITION		pos;

	for (pConnection = ms_oListOfArrows.GetHeadElement(pos); pConnection; pConnection = ms_oListOfArrows.GetNextElement(pos))
	{
		pLinkObject = (Connection *) pConnection->GetObject();
		if ((pLinkObject->GetDstWayPoint() == pMovedWP) || (pLinkObject->GetSrcWayPoint() == pMovedWP))
			fn_vUpdateConnection(pConnection, FALSE);
	}
	if (bUpdate)
		GetInterface()->GetInterface()->fn_vUpdateAll (E_mc_JustDraw);
}


void Graph::fn_vAddGraphicConnection (CPA_SuperObject *pConnection)
{
	POSITION pos;
	
	pos = ms_oListOfArrows.Find(pConnection);
	if (!pos)
		ms_oListOfArrows.AddTail(pConnection);
}

void Graph::fn_vRemoveGraphicConnection	(CPA_SuperObject *pConnection)
{
	POSITION pos;
	
	pos = ms_oListOfArrows.Find(pConnection);
	if (pos)
		ms_oListOfArrows.RemoveAt(pos);
	pConnection->IsolateChild();
}

CPA_SuperObject * Graph::GetGraphicConnection (WayPoint* pSrcNode, WayPoint* pDstNode)
{
	CPA_SuperObject *pConnection;
	Connection		*pLinkObject;
	POSITION		pos;

	for (pConnection = ms_oListOfArrows.GetHeadElement(pos); pConnection; pConnection = ms_oListOfArrows.GetNextElement(pos))
	{
		pLinkObject = (Connection *) pConnection->GetObject();
		if ((pLinkObject->GetDstWayPoint() == pDstNode) && (pLinkObject->GetSrcWayPoint() == pSrcNode))
			return pConnection;
	}
	return NULL;
}

void Graph::GetConnectionsToWaypoint (WayPoint *pNode, int iType, CPA_List<CPA_SuperObject> *pListToFill)
{
	CPA_SuperObject *pConnection;
	Connection		*pLinkObject;
	POSITION		pos;

	if (!pListToFill)
		return;

	for (pConnection = ms_oListOfArrows.GetHeadElement(pos); pConnection; pConnection = ms_oListOfArrows.GetNextElement(pos))
	{
		pLinkObject = (Connection *) pConnection->GetObject();
		if ((pLinkObject->GetDstWayPoint() == pNode) && (iType <= 0))
			pListToFill->AddTail(pConnection);
		if ((pLinkObject->GetSrcWayPoint() == pNode) && (iType >= 0))
			pListToFill->AddTail(pConnection);
	}
}

void Graph::SetConnectionCapacity (WayPoint *pSrcNode, WayPoint *pDstNode, long lCapacity)
{
	WP_tdHandleOfArc	hArc;
	WP_tdhGraphNode		hSrcNode, hDstNode;
	CPA_SuperObject		*pConnection;
	Connection			*pLinkObject;
	int					iSrcNode, iDstNode, iArc;

	// get corresponding connection
	pConnection = GetGraphicConnection(pSrcNode, pDstNode);
	if (!pConnection)
		return;
	pLinkObject = (Connection *) pConnection->GetObject();

	// update editor connection
	pLinkObject->SetCapacity(lCapacity);

	// update engine connection
	iSrcNode = fn_iGetNodeOfWayPoint(pSrcNode->GetStruct());
	hSrcNode = fn_hGetNode(iSrcNode);
	iDstNode = fn_iGetNodeOfWayPoint(pDstNode->GetStruct());
	hDstNode = fn_hGetNode(iDstNode);
	// register arc parameters
	iArc = fn_iGetArcOfNode(hSrcNode, hDstNode);
	hArc = fn_hGetArc(hSrcNode, iArc);
	WPARC_fn_lSetCapability(hArc, (unsigned long)lCapacity);

// Shaitan NewParam {
	// notify
	fn_vNotifySave();
//End Shaitan NewParam }
}

void Graph::SetConnectionWeight (WayPoint *pSrcNode, WayPoint *pDstNode, long lWeight)
{
	WP_tdHandleOfArc	hArc;
	WP_tdhGraphNode		hSrcNode, hDstNode;
	CPA_SuperObject		*pConnection;
	Connection			*pLinkObject;
	int					iSrcNode, iDstNode, iArc;

	// get corresponding connection
	pConnection = GetGraphicConnection(pSrcNode, pDstNode);
	if (!pConnection)
		return;
	pLinkObject = (Connection *) pConnection->GetObject();

	// update editor connection
	pLinkObject->SetWeight(lWeight);

	// update engine connection
	iSrcNode = fn_iGetNodeOfWayPoint(pSrcNode->GetStruct());
	hSrcNode = fn_hGetNode(iSrcNode);
	iDstNode = fn_iGetNodeOfWayPoint(pDstNode->GetStruct());
	hDstNode = fn_hGetNode(iDstNode);
	// register arc parameters
	iArc = fn_iGetArcOfNode(hSrcNode, hDstNode);
	hArc = fn_hGetArc(hSrcNode, iArc);
	WPARC_fn_lSetWeight(hArc, lWeight);

// Shaitan NewParam {
	// notify
	fn_vNotifySave();
//End Shaitan NewParam }
}

long Graph::GetConnectionCapacity (WayPoint *pSrcNode, WayPoint *pDstNode)
{
	CPA_SuperObject		*pConnection;
	Connection			*pLinkObject;

	// get corresponding connection
	pConnection = GetGraphicConnection(pSrcNode, pDstNode);
	pLinkObject = (Connection *) pConnection->GetObject();

	// update editor connection
	return pLinkObject->GetCapacity();
}

long Graph::GetConnectionWeight (WayPoint *pSrcNode, WayPoint *pDstNode)
{
	CPA_SuperObject		*pConnection;
	Connection			*pLinkObject;

	// get corresponding connection
	pConnection = GetGraphicConnection(pSrcNode, pDstNode);
	pLinkObject = (Connection *) pConnection->GetObject();

	// update editor connection
	return pLinkObject->GetWeight();
}

void Graph::fn_vShowWaypoints (BOOL bShow)
{
	WP_tdhGraphNode		hNode;
	WayPoint			*pNode;
	int					iNode;
	
	for (iNode = 0; iNode < fn_iGetNumberOfNodes(); iNode++)
	{
		hNode = fn_hGetNode(iNode);
		pNode = GetWaypoint(hNode->m_hWayPoint);
		if (pNode->GetSuperObject()->GetLocalColor() == E_lc_NoColor)
		{
			pNode->GetRealGraphic()->SetLocalColor((bShow) ? E_lc_Violet : E_lc_NoColor);
			pNode->GetSymbolicalGraphic()->SetLocalColor((bShow) ? E_lc_Violet : E_lc_NoColor);
		}
	}
}

//End Shaitan Correction }


// Shaitan NewParam {
void Graph::SetNodeType (WayPoint *pSrcNode, long lType)
{
	// set engine type
	lType = WPG_fn_lChangeTypeOfWP (GetStruct(), pSrcNode->GetStruct(), lType); 
	
	// notify the change
	fn_vNotifySave ();
}

long Graph::GetNodeType (WayPoint *pSrcNode)
{
	WP_tdhWayPoint	hWP;
	long			lType;
	int				iSrcNode;

	// get index of node
	iSrcNode = fn_iGetNodeOfWayPoint(pSrcNode->GetStruct());
	// get engine type
	hWP = WPG_fn_hGetWaypointOfGraph (GetStruct(), iSrcNode, &lType); 
	
	return (hWP ? lType : -1);
}


WayPoint * Graph::GetPrevNode (WayPoint *pSrcNode)
{
	WP_tdhWayPoint	hWP;
	int				iNode;
	
	iNode = fn_iGetNodeOfWayPoint(pSrcNode->GetStruct());
	if (iNode > 0)
	{
		hWP = fn_hGetWayPointOfNode(iNode - 1);
		return GetWaypoint(hWP);
	}
	else
		return NULL;
}

WayPoint * Graph::GetNextNode (WayPoint *pSrcNode)
{
	WP_tdhWayPoint	hWP;
	int				iNode;
	
	iNode = fn_iGetNodeOfWayPoint(pSrcNode->GetStruct());
	if (iNode < fn_iGetNumberOfNodes() -1 )
	{
		hWP = fn_hGetWayPointOfNode(iNode + 1);
		return GetWaypoint(hWP);
	}
	else
		return NULL;
}

WayPoint * Graph::GetPrevConnection (WayPoint *pSrcNode, WayPoint *pDstNode)
{
	WP_tdHandleOfArc hArc;
	WP_tdhGraphNode  hNode, hArcNode;
	int				 iNode, iArcNode, iArc;
	
	iNode = fn_iGetNodeOfWayPoint(pSrcNode->GetStruct());
	hNode = fn_hGetNode(iNode);

	if (pDstNode)
	{
		iArcNode = fn_iGetNodeOfWayPoint(pDstNode->GetStruct());
		hArcNode = fn_hGetNode(iArcNode);

		iArc = fn_iGetArcOfNode(hNode, hArcNode);
		hArc = fn_hGetArc(hNode, iArc);
		
		if (iArc > 0)
		{
			hArc = fn_hGetArc(hNode, iArc - 1);
			return GetWaypoint(hArc->m_hNode->m_hWayPoint);
		}
		else
			return NULL;
	}
	else 
	{
		if (fn_iGetNumberOfArcs(hNode) > 0)
		{
			hArc = fn_hGetArc(hNode, fn_iGetNumberOfArcs(hNode) - 1);
			return GetWaypoint(hArc->m_hNode->m_hWayPoint);
		}
		else
			return NULL;
	}
}

WayPoint * Graph::GetNextConnection (WayPoint *pSrcNode, WayPoint *pDstNode)
{
	WP_tdHandleOfArc hArc;
	WP_tdhGraphNode  hNode, hArcNode;
	int				 iNode, iArcNode, iArc;
	
	iNode = fn_iGetNodeOfWayPoint(pSrcNode->GetStruct());
	hNode = fn_hGetNode(iNode);


	if (pDstNode)
	{
		iArcNode = fn_iGetNodeOfWayPoint(pDstNode->GetStruct());
		hArcNode = fn_hGetNode(iArcNode);

		iArc = fn_iGetArcOfNode(hNode, hArcNode);
		hArc = fn_hGetArc(hNode, iArc);
		
		if (iArc < fn_iGetNumberOfArcs(hNode) - 1)
		{
			hArc = fn_hGetArc(hNode, iArc + 1);
			return GetWaypoint(hArc->m_hNode->m_hWayPoint);
		}
		else
			return NULL;
	}
	else 
	{
		if (fn_iGetNumberOfArcs(hNode) > 0)
		{
			hArc = fn_hGetArc(hNode, 0);
			return GetWaypoint(hArc->m_hNode->m_hWayPoint);
		}
		else
			return NULL;
	}
}
//End Shaitan NewParam }

