558b590810
- Aggiunta classe di calcolo per ottimizzazione ordine delle lavorazioni - Aggiunti vincoli obbligatori e dipendenze suggerite a ShortestPath.
539 lines
19 KiB
C++
539 lines
19 KiB
C++
//----------------------------------------------------------------------------
|
|
// EgalTech 2015-2015
|
|
//----------------------------------------------------------------------------
|
|
// File : ShortestPathTsp.cpp Data : 22.12.15 Versione : 1.6l4
|
|
// Contenuto : Calcolo del percorso minimo nel caso generale.
|
|
//
|
|
//
|
|
//
|
|
// Modifiche : 22.12.15 DS Creazione modulo.
|
|
//
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
//--------------------------- Include ----------------------------------------
|
|
#include "stdafx.h"
|
|
#include "DllMain.h"
|
|
#include "ShortestPath.h"
|
|
#include "/EgtDev/Include/EGnStringUtils.h"
|
|
#include <new>
|
|
|
|
using namespace std ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
#if defined( _DEBUG)
|
|
#define MY_LOG(szOut) LOG_INFO( GetENkLogger(), szOut) ;
|
|
#else
|
|
#define MY_LOG(szOut) ;
|
|
#endif
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
ShortestPath::Tsp( void)
|
|
{
|
|
// almeno un punto
|
|
if ( m_nNumPnts < 1)
|
|
return false ;
|
|
|
|
// per path aperta aggiungo un punto con distanze nulle da tutti gli altri ( per poter creare il lato nullo)
|
|
if ( m_nType == SP_OPEN) {
|
|
if ( m_nNumPnts <= MAX_SPPS) {
|
|
m_Points[m_nNumPnts].dXi = 0 ;
|
|
m_Points[m_nNumPnts].dYi = 0 ;
|
|
m_Points[m_nNumPnts].dXf = 0 ;
|
|
m_Points[m_nNumPnts].dYf = 0 ;
|
|
++ m_nNumPnts ;
|
|
}
|
|
else
|
|
return false ;
|
|
}
|
|
|
|
// alloco la matrice delle distanze
|
|
if ( m_Dists != nullptr)
|
|
delete m_Dists ;
|
|
m_Dists = new(nothrow) unsigned[ m_nNumPnts * m_nNumPnts] ;
|
|
if ( m_Dists == nullptr)
|
|
return false ;
|
|
// alloco la matrice ausiliaria
|
|
if ( m_Available != nullptr)
|
|
delete m_Available ;
|
|
m_Available = new(nothrow) bool[ m_nNumPnts * m_nNumPnts] ;
|
|
if ( m_Available == nullptr)
|
|
return false ;
|
|
// alloco la path principale
|
|
if ( m_pMain != nullptr)
|
|
delete m_pMain ;
|
|
m_pMain = new(nothrow) NODE[ m_nNumPnts] ;
|
|
if ( m_pMain == nullptr)
|
|
return false ;
|
|
// alloco la copia della path principale
|
|
if ( m_pDupl != nullptr)
|
|
delete m_pDupl ;
|
|
m_pDupl = new(nothrow) NODE[ m_nNumPnts] ;
|
|
if ( m_pDupl == nullptr)
|
|
return false ;
|
|
// alloco la copia del path per controllo dipendenze
|
|
if ( m_pCheckDep != nullptr)
|
|
delete m_pCheckDep ;
|
|
m_pCheckDep = new(nothrow) NODE[ m_nNumPnts] ;
|
|
|
|
// calcolo la matrice delle distanze
|
|
CalcDistances() ;
|
|
|
|
// organizzo percorsi
|
|
PreparePath( m_pMain) ;
|
|
PreparePath( m_pDupl) ;
|
|
PreparePath( m_pCheckDep) ;
|
|
|
|
// inizializzo minimo costo
|
|
m_nMinCost = LLONG_MAX ;
|
|
|
|
// ---- applico algoritmo NearNeighbor con miglioramenti aggiuntivi ----
|
|
long long unsigned nMinNN = NearNeighbor() ;
|
|
string sOut = "-- NearNeighbor : TotalCost = " + to_string( nMinNN) ;
|
|
MY_LOG( sOut.c_str()) ;
|
|
_printPath( m_pMain, ToString( "NN : ")) ;
|
|
// se migliora, salvo l'ordinamento
|
|
if ( nMinNN < m_nMinCost) {
|
|
MY_LOG( " Improve") ;
|
|
m_nMinCost = nMinNN ;
|
|
UpdateOrder( m_pMain) ;
|
|
}
|
|
// salvo il percorso in un duplicato
|
|
SavePath( m_pMain) ;
|
|
// miglioramenti aggiuntivi
|
|
CalculateImprovements( m_pMain) ;
|
|
|
|
// ---- Applico percorso invertito, se risultato precedente scarso ----
|
|
const double COEFF_INVERTED = 1.2 ;
|
|
const int MIN_PNTS_INVERTED = 128 ;
|
|
if ( ! ExistConstraints()) {
|
|
if ( m_nMinCost > COEFF_INVERTED * m_nTotMin || m_nNumPnts < MIN_PNTS_INVERTED) {
|
|
// inverto il percorso
|
|
NODE* pCurr = m_pDupl->pPrev ;
|
|
NODE* pPath = m_pMain ;
|
|
for ( unsigned i = 0 ; i < m_nNumPnts ; ++ i) {
|
|
pPath->nPos = pCurr->nPos ;
|
|
pPath = pPath->pNext ;
|
|
pCurr = pCurr->pPrev ;
|
|
}
|
|
// ne calcolo il risultato
|
|
long long unsigned nMinInv = TotalCost( m_pMain) ;
|
|
_printPath( m_pMain, "Inverted NN : ") ;
|
|
string sOut = "-- Inverted NN : TotalCost = " + to_string( nMinInv) ;
|
|
MY_LOG( sOut.c_str()) ;
|
|
// se migliora, salvo l'ordinamento
|
|
if ( nMinInv < m_nMinCost) {
|
|
MY_LOG( " Improve") ;
|
|
m_nMinCost = nMinInv ;
|
|
UpdateOrder( m_pMain) ;
|
|
}
|
|
// salvo il percorso in un duplicato
|
|
SavePath( m_pMain) ;
|
|
// miglioramenti aggiuntivi
|
|
CalculateImprovements( m_pMain) ;
|
|
}
|
|
else
|
|
MY_LOG( "-- Inverted NN : Not necessary") ;
|
|
}
|
|
|
|
// ---- Applico pessima partenza, se risultato precedente scarso ----
|
|
const double COEFF_FARNEIG = 1.4 ;
|
|
const int MIN_PNTS_FARNEIG = 128 ;
|
|
if ( m_nMinCost > COEFF_FARNEIG * m_nTotMin || m_nNumPnts < MIN_PNTS_FARNEIG) {
|
|
long long unsigned nMinFN = FarNeighbor() ;
|
|
_printPath( m_pMain, "FN : ") ;
|
|
string sOut = "-- FarNeighbor : TotalCost = " + to_string( nMinFN) ;
|
|
MY_LOG( sOut.c_str()) ;
|
|
// se migliora, salvo l'ordinamento
|
|
if ( nMinFN < m_nMinCost) {
|
|
MY_LOG( " Improve") ;
|
|
m_nMinCost = nMinFN ;
|
|
UpdateOrder( m_pMain) ;
|
|
}
|
|
// salvo il percorso in un duplicato
|
|
SavePath( m_pMain) ;
|
|
// miglioramenti aggiuntivi
|
|
CalculateImprovements( m_pMain) ;
|
|
}
|
|
else
|
|
MY_LOG( "-- FarNeighbor : Not necessary") ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
ShortestPath::CalculateImprovements( NODE* pPath)
|
|
{
|
|
// Ottimizzazione con movimento di singolo punto
|
|
RestorePath( pPath) ;
|
|
long long unsigned nPntOpt = PointOpt( pPath) ;
|
|
_printPath( pPath, "PointOpt : ") ;
|
|
string sOut = " PointOpt : TotalCost = " + to_string( nPntOpt) ;
|
|
MY_LOG( sOut.c_str()) ;
|
|
// se migliora, salvo l'ordinamento
|
|
if ( nPntOpt < m_nMinCost) {
|
|
MY_LOG( " Improve") ;
|
|
m_nMinCost = nPntOpt ;
|
|
UpdateOrder( pPath) ;
|
|
}
|
|
|
|
// Ottimizzazione con movimento di due punti (lanciata solo se non ci sono troppi punti)
|
|
const int MAX_NODES_2OPT = 768 ;
|
|
if ( m_nNumPnts <= MAX_NODES_2OPT) {
|
|
RestorePath( pPath) ;
|
|
long long unsigned nTwoOpt = TwoOpt( pPath) ;
|
|
_printPath( pPath, "TwoOpt : ") ;
|
|
string sOut = " TwoOpt : TotalCost = " + to_string( nTwoOpt) ;
|
|
MY_LOG( sOut.c_str()) ;
|
|
// se migliora, salvo l'ordinamento
|
|
if ( nTwoOpt < m_nMinCost) {
|
|
MY_LOG( " Improve") ;
|
|
m_nMinCost = nTwoOpt ;
|
|
UpdateOrder( pPath) ;
|
|
}
|
|
}
|
|
|
|
// Ottimizzazione ibrida (lanciata solo se non ci sono troppi punti)
|
|
const int MAX_NODES_HYBRID = 512 ;
|
|
if ( m_nNumPnts <= MAX_NODES_HYBRID) {
|
|
RestorePath( pPath) ;
|
|
long long unsigned nHybOpt = Hybrid( pPath) ;
|
|
_printPath( pPath, "Hybrid : ") ;
|
|
string sOut = " Hybrid : TotalCost = " + to_string( nHybOpt) ;
|
|
MY_LOG( sOut.c_str()) ;
|
|
// se migliora, salvo l'ordinamento
|
|
if ( nHybOpt < m_nMinCost) {
|
|
MY_LOG( " Improve") ;
|
|
m_nMinCost = nHybOpt ;
|
|
UpdateOrder( pPath) ;
|
|
}
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
unsigned
|
|
ShortestPath::GetDistance( float dDx, float dDy, float dDz, float dDh, float dDv)
|
|
{
|
|
// parte lineare
|
|
unsigned nDist = unsigned( sqrt( dDx * dDx + dDy * dDy + dDz * dDz) + 0.5) ;
|
|
// eventuali parti angolari
|
|
if ( abs( dDh) > 1 && abs( dDv) > 1)
|
|
nDist += unsigned( max( m_dAngHAdd, m_dAngVAdd) + m_dAngHMul * abs( dDh) + m_dAngVMul * abs( dDv)) ;
|
|
else if ( abs( dDh) > 1)
|
|
nDist += unsigned( m_dAngHAdd + m_dAngHMul * abs( dDh)) ;
|
|
else if ( abs( dDv) > 1)
|
|
nDist += unsigned( m_dAngVAdd + m_dAngVMul * abs( dDv)) ;
|
|
return nDist ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void
|
|
ShortestPath::CalcDistances( void)
|
|
{
|
|
// inizializzo somma delle minime distanze
|
|
m_nTotMin = 0 ;
|
|
|
|
// in generale si calcolano le distanze per tutti i punti
|
|
unsigned nLimit = m_nNumPnts ;
|
|
|
|
// nel caso di percorso aperto, ultima riga e ultima colonna si calcolano in modo speciale
|
|
if ( m_nType == SP_OPEN) {
|
|
// calcolo box dei punti
|
|
float fXmin = (float) m_Points[0].dXi ;
|
|
float fXmax = (float) m_Points[0].dXi ;
|
|
float fYmin = (float) m_Points[0].dYi ;
|
|
float fYmax = (float) m_Points[0].dYi ;
|
|
float fZmin = (float) m_Points[0].dZi ;
|
|
float fZmax = (float) m_Points[0].dZi ;
|
|
// ciclo sui punti
|
|
for ( unsigned i = 0 ; i < m_nNumPnts - 1 ; ++ i) {
|
|
// X
|
|
if ( m_Points[i].dXi < fXmin)
|
|
fXmin = (float) m_Points[i].dXi ;
|
|
if ( m_Points[i].dXi > fXmax)
|
|
fXmax = (float) m_Points[i].dXi ;
|
|
if ( m_Points[i].dXf < fXmin)
|
|
fXmin = (float) m_Points[i].dXf ;
|
|
if ( m_Points[i].dXf > fXmax)
|
|
fXmax = (float) m_Points[i].dXf ;
|
|
// Y
|
|
if ( m_Points[i].dYi < fYmin)
|
|
fYmin = (float) m_Points[i].dYi ;
|
|
if ( m_Points[i].dYi > fYmax)
|
|
fYmax = (float) m_Points[i].dYi ;
|
|
if ( m_Points[i].dYf < fYmin)
|
|
fYmin = (float) m_Points[i].dYf ;
|
|
if ( m_Points[i].dYf> fYmax)
|
|
fYmax = (float) m_Points[i].dYf ;
|
|
// Z
|
|
if ( m_Points[i].dZi < fZmin)
|
|
fZmin = (float) m_Points[i].dZi ;
|
|
if ( m_Points[i].dZi > fZmax)
|
|
fZmax = (float) m_Points[i].dZi ;
|
|
if ( m_Points[i].dZf < fZmin)
|
|
fZmin = (float) m_Points[i].dZf ;
|
|
if ( m_Points[i].dZf > fZmax)
|
|
fZmax = (float) m_Points[i].dZf ;
|
|
}
|
|
// imposto minimo di linea
|
|
unsigned nRowMinDist = INT_MAX ;
|
|
// assegno le distanze sull'ultima riga ( dal precedente all'inizio del percorso aperto) tranne ultimo elemento
|
|
for ( unsigned i = 0 ; i < m_nNumPnts - 1 ; ++ i) {
|
|
unsigned nDist ;
|
|
// il valore dipende dalla condizione imposta
|
|
switch ( m_ObStart.nF) {
|
|
case OB_NEAR_PNT : {
|
|
float dDx = float( m_ObStart.dX - m_Points[i].dXi) ;
|
|
float dDy = float( m_ObStart.dY - m_Points[i].dYi) ;
|
|
float dDz = float( m_ObStart.dZ - m_Points[i].dZi) ;
|
|
float dDh = float( m_ObStart.dH - m_Points[i].dHi) ;
|
|
float dDv = float( m_ObStart.dV - m_Points[i].dVi) ;
|
|
nDist = GetDistance( dDx, dDy, dDz, dDh, dDv) ;
|
|
} break ;
|
|
case OB_XMIN :
|
|
nDist = unsigned( m_Points[i].dXi - fXmin + 0.5) ;
|
|
break ;
|
|
case OB_XMAX :
|
|
nDist = unsigned( fXmax - m_Points[i].dXi + 0.5) ;
|
|
break ;
|
|
case OB_YMIN :
|
|
nDist = unsigned( m_Points[i].dYi - fYmin + 0.5) ;
|
|
break ;
|
|
case OB_YMAX :
|
|
nDist = unsigned( fYmax - m_Points[i].dYi + 0.5) ;
|
|
break ;
|
|
default : // OB_NONE
|
|
nDist = 0 ;
|
|
break ;
|
|
}
|
|
m_Dists[ Index( m_nNumPnts - 1, i)] = min( nDist, MAXDIST) ;
|
|
// verifico se nuovo minimo di linea
|
|
if ( nDist < nRowMinDist)
|
|
nRowMinDist = nDist ;
|
|
}
|
|
// aggiorno il totale delle minime distanze
|
|
m_nTotMin += nRowMinDist ;
|
|
// assegno le distanze sull'ultima colonna ( dalla fine del percorso aperto al successivo) tranne ultimo elemento
|
|
for ( unsigned i = 0 ; i < m_nNumPnts - 1 ; ++ i) {
|
|
unsigned nDist ;
|
|
// il valore dipende dalla condizione imposta
|
|
switch ( m_ObEnd.nF) {
|
|
case OB_NEAR_PNT : {
|
|
float dDx = float( m_ObEnd.dX - m_Points[i].dXf) ;
|
|
float dDy = float( m_ObEnd.dY - m_Points[i].dYf) ;
|
|
float dDz = float( m_ObEnd.dZ - m_Points[i].dZf) ;
|
|
float dDh = float( m_ObEnd.dH - m_Points[i].dHf) ;
|
|
float dDv = float( m_ObEnd.dV - m_Points[i].dVf) ;
|
|
nDist = GetDistance( dDx, dDy, dDz, dDh, dDv) ;
|
|
} break ;
|
|
case OB_XMIN :
|
|
nDist = unsigned( m_Points[i].dXf - fXmin + 0.5) ;
|
|
break ;
|
|
case OB_XMAX :
|
|
nDist = unsigned( fXmax - m_Points[i].dXf + 0.5) ;
|
|
break ;
|
|
case OB_YMIN :
|
|
nDist = unsigned( m_Points[i].dYf - fYmin + 0.5) ;
|
|
break ;
|
|
case OB_YMAX :
|
|
nDist = unsigned( fYmax - m_Points[i].dYf + 0.5) ;
|
|
break ;
|
|
default : // OB_NONE
|
|
nDist = 0 ;
|
|
break ;
|
|
}
|
|
m_Dists[ Index( i, m_nNumPnts - 1)] = min( nDist, MAXDIST) ;
|
|
}
|
|
// punto su diagonale principale
|
|
m_Dists[ Index( m_nNumPnts - 1, m_nNumPnts - 1)] = MAXDIST ;
|
|
// devo ancora calcolare le righe/colonne precedenti
|
|
nLimit = m_nNumPnts - 1 ;
|
|
}
|
|
|
|
// ciclo per calcolare le distanze tra tutte le coppie di nodi
|
|
bool bCalcDistances = ( m_ExtDistMat.empty()) ;
|
|
for ( unsigned i = 0 ; i < nLimit ; ++ i) {
|
|
unsigned nRowMinDist = INT_MAX ;
|
|
for ( unsigned j = 0 ; j < nLimit ; ++ j) {
|
|
// se ho già impostato una matrice delle distanze, allora uso quella
|
|
if ( ! bCalcDistances)
|
|
m_Dists[Index( i, j)] = m_ExtDistMat[i][j] ;
|
|
// altrimenti calcolo le rispettive distanze
|
|
else {
|
|
if ( i != j) {
|
|
// calcolo distanza i -> j
|
|
float dDx = float( m_Points[i].dXf - m_Points[j].dXi) ;
|
|
float dDy = float( m_Points[i].dYf - m_Points[j].dYi) ;
|
|
float dDz = float( m_Points[i].dZf - m_Points[j].dZi) ;
|
|
float dDh = float( m_Points[i].dHf - m_Points[j].dHi) ;
|
|
float dDv = float( m_Points[i].dVf - m_Points[j].dVi) ;
|
|
unsigned nDist = min( GetDistance( dDx, dDy, dDz, dDh, dDv), MAXDIST) ;
|
|
m_Dists[ Index( i, j)] = nDist ;
|
|
// verifico se nuovo minimo di linea
|
|
if ( nDist < nRowMinDist)
|
|
nRowMinDist = nDist ;
|
|
}
|
|
else
|
|
m_Dists[ Index( i, j)] = MAXDIST ;
|
|
}
|
|
}
|
|
// aggiorno il totale delle minime distanze
|
|
m_nTotMin += nRowMinDist ;
|
|
}
|
|
|
|
// nel caso di dipendenze suggerite, calcolo il coefficiente di costo massimo associato
|
|
if ( ExistSuggDependences())
|
|
m_nMaxDistSuggDep = CalcMaxDist() ;
|
|
|
|
// nel caso di percorso aperto senza vincoli, il numero delle distanze è uno meno di quello dei veri nodi
|
|
if ( m_nType == SP_OPEN &&
|
|
m_ObStart.nF == OB_NONE && m_ObEnd.nF == OB_NONE)
|
|
m_nTotMin = (long long unsigned) ( m_nTotMin / (double) nLimit * ( nLimit - 1)) ;
|
|
|
|
// stampe di debug
|
|
#if 0
|
|
MY_LOG( "----\nDistances :") ;
|
|
for ( unsigned i = 0 ; i < m_nNumPnts ; ++ i) {
|
|
string sOut ;
|
|
for ( unsigned j = 0 ; j < m_nNumPnts ; ++ j) {
|
|
sOut += ToString( int( m_Dists[ Index( i, j)]), 2) + " " ;
|
|
}
|
|
MY_LOG( sOut.c_str()) ;
|
|
}
|
|
#endif
|
|
string sOut = "MinCost = " + to_string( m_nTotMin) ;
|
|
MY_LOG( sOut.c_str()) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void
|
|
ShortestPath::PreparePath( NODE* pPath)
|
|
{
|
|
NODE* pCurr = pPath ;
|
|
for ( unsigned i = 1 ; i < m_nNumPnts ; ++ i) {
|
|
pCurr->pNext = (NODE*) ( (size_t) pCurr + sizeof( NODE)) ;
|
|
pCurr->pNext->pPrev = pCurr ;
|
|
pCurr = pCurr->pNext ;
|
|
}
|
|
pPath->pPrev = pCurr ;
|
|
pCurr->pNext = pPath ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void
|
|
ShortestPath::SavePath( NODE* pPath)
|
|
{
|
|
NODE* pCurr = m_pDupl ;
|
|
for ( unsigned i = 0 ; i < m_nNumPnts ; ++ i) {
|
|
pCurr->nPos = pPath->nPos ;
|
|
pPath = pPath->pNext ;
|
|
pCurr = pCurr->pNext ;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void
|
|
ShortestPath::RestorePath( NODE* pPath)
|
|
{
|
|
NODE* pCurr = m_pDupl ;
|
|
for ( unsigned i = 0 ; i < m_nNumPnts ; ++ i) {
|
|
pPath->nPos = pCurr->nPos ;
|
|
pPath = pPath->pNext ;
|
|
pCurr = pCurr->pNext ;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void
|
|
ShortestPath::CopyPath( NODE* pPath, NODE* pPathCopy)
|
|
{
|
|
NODE* pCurr = pPathCopy ;
|
|
for ( unsigned i = 0 ; i < m_nNumPnts ; ++ i) {
|
|
pCurr->nPos = pPath->nPos ;
|
|
pPath = pPath->pNext ;
|
|
pCurr = pCurr->pNext ;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void
|
|
ShortestPath::CopyPathAdv( NODE* pPath, NODE* pPathCopy, NODE* pLast, NODE* pFirst, NODE* pKth,
|
|
NODE** pLastCopy, NODE** pFirstCopy, NODE** pKthCopy)
|
|
{
|
|
CopyPath( pPath, pPathCopy) ;
|
|
NODE* pCurr = pPath ;
|
|
NODE* pCurrCopy = pPathCopy ;
|
|
for ( unsigned i = 0 ; i < m_nNumPnts ; ++ i) {
|
|
if ( pCurr == pLast)
|
|
*pLastCopy = pCurrCopy ;
|
|
if ( pCurr == pKth)
|
|
*pKthCopy = pCurrCopy ;
|
|
if ( pCurr == pFirst)
|
|
*pFirstCopy = pCurrCopy ;
|
|
pCurr = pCurr->pNext ;
|
|
pCurrCopy = pCurrCopy->pNext ;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
long long unsigned
|
|
ShortestPath::TotalCost( NODE* pPath)
|
|
{
|
|
// ci devono essere almeno due nodi
|
|
if ( pPath == nullptr || pPath->pNext == nullptr)
|
|
return 0 ;
|
|
// lunghezza del primo arco
|
|
long long unsigned nCost = ArcCost( pPath->nPos, pPath->pNext->nPos) ;
|
|
// ciclo sui nodi successivi (calcolo la lunghezza degli archi che li uniscono)
|
|
NODE* pCurr = pPath->pNext ;
|
|
while ( pCurr != pPath) {
|
|
nCost += ArcCost( pCurr->nPos, pCurr->pNext->nPos) ;
|
|
pCurr = pCurr->pNext ;
|
|
}
|
|
// se sono presenti delle dipendenze suggerite violate, aumento il costo
|
|
int nBreak = 0 ;
|
|
if ( ! IsPathRespectingSuggestedDependences( pPath, nBreak))
|
|
nCost += m_nMaxDistSuggDep * nBreak ;
|
|
return nCost ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void
|
|
ShortestPath::UpdateOrder( NODE* pPath)
|
|
{
|
|
// per circuiti aperti si parte dopo il nodo finale aggiunto per poter creare il lato nullo
|
|
if ( m_nType == SP_OPEN) {
|
|
NODE* pCurr = pPath ;
|
|
for ( unsigned i = 0 ; i < m_nNumPnts ; ++ i) {
|
|
if ( pCurr->nPos == m_nNumPnts - 1) {
|
|
pPath = pCurr->pNext ;
|
|
break ;
|
|
}
|
|
pCurr = pCurr->pNext ;
|
|
}
|
|
}
|
|
// assegno l'ordinamento trovato
|
|
for ( unsigned i = 0 ; i < m_nNumPnts ; ++ i) {
|
|
m_nOrder[i] = pPath->nPos ;
|
|
pPath = pPath->pNext ;
|
|
}
|
|
// stampe di debug
|
|
#if 0
|
|
MY_LOG( "Positions :") ;
|
|
string sOut ;
|
|
for ( unsigned i = 0 ; i < m_nNumPnts ; ++ i) {
|
|
sOut += ToString( (int)m_nOrder[i]) + " " ;
|
|
if ( i % 20 == 19) {
|
|
MY_LOG( sOut.c_str()) ;
|
|
sOut.clear() ;
|
|
}
|
|
}
|
|
if ( ! sOut.empty())
|
|
MY_LOG( sOut.c_str()) ;
|
|
#endif
|
|
}
|