EgtNumKernel 1.6l4 :

- aggiunta gestione ShortestPath.
This commit is contained in:
Dario Sassi
2015-12-28 10:33:46 +00:00
parent d1dbe04a57
commit b71ff8c113
13 changed files with 1455 additions and 6 deletions
+5
View File
@@ -50,6 +50,11 @@ DllMain( HMODULE hModule, DWORD dwReason, LPVOID lpReserved)
// if ( IsDbgPresent)
// return 0 ;
//#endif
// se debug, imposto stampe memory leaks all'uscita
#if defined ( _DEBUG)
_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF) ;
#endif
// eseguo
s_hModule = hModule ;
EGT_TRACE( "EgtNumKernel.dll Initializing!\n") ;
}
BIN
View File
Binary file not shown.
+9
View File
@@ -195,15 +195,23 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ItemGroup>
<ClCompile Include="Complex.cpp" />
<ClCompile Include="ENkDllMain.cpp" />
<ClCompile Include="Fn.cpp" />
<ClCompile Include="Hybrid.cpp" />
<ClCompile Include="JenkinsTraub.cpp" />
<ClCompile Include="Nn.cpp" />
<ClCompile Include="Polynomial.cpp" />
<ClCompile Include="PolynomialRoots.cpp" />
<ClCompile Include="PntOpt.cpp" />
<ClCompile Include="ShortestPath.cpp" />
<ClCompile Include="ShortestPathTsp.cpp" />
<ClCompile Include="ShortestPathZigZag.cpp" />
<ClCompile Include="stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="TwoOpt.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\Include\EgnGetModuleVer.h" />
@@ -218,6 +226,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClInclude Include="DllMain.h" />
<ClInclude Include="JenkinsTraub.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="ShortestPath.h" />
<ClInclude Include="stdafx.h" />
</ItemGroup>
<ItemGroup>
+39 -6
View File
@@ -13,6 +13,12 @@
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="File di origine\Polynomial">
<UniqueIdentifier>{0e9a4d71-148b-4ec0-b1c5-b6f406e3bafe}</UniqueIdentifier>
</Filter>
<Filter Include="File di origine\ShortestPath">
<UniqueIdentifier>{7fa12653-9875-42ee-b9e1-0c088a5846c4}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="ENkDllMain.cpp">
@@ -21,17 +27,41 @@
<ClCompile Include="stdafx.cpp">
<Filter>File di origine</Filter>
</ClCompile>
<ClCompile Include="JenkinsTraub.cpp">
<Filter>File di origine</Filter>
</ClCompile>
<ClCompile Include="Complex.cpp">
<Filter>File di origine</Filter>
<Filter>File di origine\Polynomial</Filter>
</ClCompile>
<ClCompile Include="JenkinsTraub.cpp">
<Filter>File di origine\Polynomial</Filter>
</ClCompile>
<ClCompile Include="Polynomial.cpp">
<Filter>File di origine</Filter>
<Filter>File di origine\Polynomial</Filter>
</ClCompile>
<ClCompile Include="PolynomialRoots.cpp">
<Filter>File di origine</Filter>
<Filter>File di origine\Polynomial</Filter>
</ClCompile>
<ClCompile Include="ShortestPath.cpp">
<Filter>File di origine\ShortestPath</Filter>
</ClCompile>
<ClCompile Include="ShortestPathTsp.cpp">
<Filter>File di origine\ShortestPath</Filter>
</ClCompile>
<ClCompile Include="ShortestPathZigZag.cpp">
<Filter>File di origine\ShortestPath</Filter>
</ClCompile>
<ClCompile Include="Nn.cpp">
<Filter>File di origine\ShortestPath</Filter>
</ClCompile>
<ClCompile Include="PntOpt.cpp">
<Filter>File di origine\ShortestPath</Filter>
</ClCompile>
<ClCompile Include="TwoOpt.cpp">
<Filter>File di origine\ShortestPath</Filter>
</ClCompile>
<ClCompile Include="Hybrid.cpp">
<Filter>File di origine\ShortestPath</Filter>
</ClCompile>
<ClCompile Include="Fn.cpp">
<Filter>File di origine\ShortestPath</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
@@ -74,6 +104,9 @@
<ClInclude Include="..\Include\EgtNumCollection.h">
<Filter>File di intestazione</Filter>
</ClInclude>
<ClInclude Include="ShortestPath.h">
<Filter>File di intestazione</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="EgtNumKernel.rc">
+78
View File
@@ -0,0 +1,78 @@
//----------------------------------------------------------------------------
// EgalTech 2015-2015
//----------------------------------------------------------------------------
// File : NN.cpp Data : 24.12.15 Versione : 1.6l4
// Contenuto : Calcolo del percorso minimo basandosi su punto più lontano ;
// pessima stima, utile come base per miglioramenti.
//
//
// Modifiche : 24.12.15 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "ShortestPath.h"
/*-------------------------------------------------------------------------- */
unsigned
ShortestPath::FarNeighbor( void)
{
// abilito i collegamenti tra nodi diversi e disabilito gli auto-collegamenti
for ( unsigned i = 0 ; i < m_nNumPnts ; ++ i) {
for ( unsigned j = 0 ; j < m_nNumPnts ; ++ j)
m_Available[ Index( i, j)] = true ;
m_Available[ Index( i, i)] = false ;
}
// cerco il nodo con il più corto arco che se ne diparte
unsigned nCurr = 0 ;
unsigned nNew = HighArc( nCurr) ;
for ( unsigned i = 1 ; i < m_nNumPnts ; ++ i) {
unsigned j = HighArc( i) ;
if ( ArcCost( i, j) > ArcCost( nCurr, nNew)) {
nCurr = i ;
nNew = j ;
}
}
// imposto il nodo corrente come base del percorso
NODE* pPath = m_pMain ;
pPath->nPos = nCurr ;
// ciclo
do {
// imposto tutti gli archi non disponibili al nodo corrente
for ( unsigned i = 0 ; i < m_nNumPnts ; ++ i)
m_Available[ Index( i, nCurr)] = false ;
// aggiungo un nuovo nodo al percorso
pPath = pPath->pNext ;
pPath->nPos = nNew ;
// imposto il nuovo nodo come nodo corrente
nCurr = nNew ;
// cerco il nuovo nodo all'estremo dell'arco più corto dal nodo corrente
nNew = HighArc( nCurr) ;
} while ( m_Available[ Index( nCurr, nNew)]) ;
// calcolo il costo del percorso
return TotalCost( m_pMain) ;
}
/*-------------------------------------------------------------------------- */
unsigned
ShortestPath::HighArc( unsigned i)
{
// cerco la prima destinazione libera
unsigned j = 0 ;
for ( ; ( j < m_nNumPnts - 1 && ! m_Available[ Index( i, j)]) ; ++ j)
;
// cerco la migliore destinazione libera
for ( unsigned k = j + 1 ; k < m_nNumPnts - 1 ; ++ k) {
if ( m_Available[ Index( i, k)])
if ( ArcCost( i, k) > ArcCost( i, j))
j = k ;
}
return j ;
}
+89
View File
@@ -0,0 +1,89 @@
//----------------------------------------------------------------------------
// EgalTech 2015-2015
//----------------------------------------------------------------------------
// File : NN.cpp Data : 22.12.15 Versione : 1.6l4
// Contenuto : Miglioramento del percorso con metodo ibrido (ad ogni passo
// si sceglie il meglio tra i metodi Popt e TwoOpt). *
//
//
//
//
// Modifiche : 22.12.15 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "ShortestPath.h"
// ----------------------------------------------------------------------------
unsigned
ShortestPath::Hybrid( NODE* pPath)
{
const int MAX_TRY = 2048 ;
unsigned count = 1 ;
NODE* pFirst = pPath ;
unsigned nTry = 1 ;
do {
NODE* pLast = pFirst->pPrev ;
NODE* pKth = pFirst->pNext ;
do {
// Point-Opt ( D1=new, D3=original)
unsigned D1 = ArcCost( pKth->nPos, pKth->pNext->pNext->nPos) +
ArcCost( pKth->pNext->nPos, pFirst->nPos) +
ArcCost( pLast->nPos, pKth->pNext->nPos) ;
unsigned D3 = ArcCost( pLast->nPos, pFirst->nPos) +
ArcCost( pKth->nPos, pKth->pNext->nPos) +
ArcCost( pKth->pNext->nPos, pKth->pNext->pNext->nPos) ;
// Two-Opt ( D2=new, D4=original)
unsigned D2 = ArcCost( pFirst->nPos, pKth->pNext->nPos) +
ArcCost( pLast->nPos, pKth->nPos) ;
unsigned D4 = ArcCost( pLast->nPos, pFirst->nPos) +
ArcCost( pKth->nPos, pKth->pNext->nPos) ;
// Lunghezze originali e nuova del tratto intermedio che viene invertito
for ( NODE* pCurr = pFirst ; pCurr != pKth ; pCurr = pCurr->pNext) {
D4 += ArcCost( pCurr->nPos, pCurr->pNext->nPos) ;
D2 += ArcCost( pCurr->pNext->nPos, pCurr->nPos) ;
}
if ( D1 < D3 || D2 < D4) {
if ( D1 < D3 &&
( D2 >= D4 || ( D3 - D1) >= ( D4 - D2))) {
NODE* pSave = pKth->pNext ;
pKth->pNext = pKth->pNext->pNext ;
pKth->pNext->pPrev = pKth ;
pLast->pNext = pSave ;
pFirst->pPrev = pSave ;
pSave->pNext = pFirst ;
pSave->pPrev = pLast ;
}
else {
for ( NODE* pReverse = pFirst ; pReverse != pKth ;) {
NODE* pSave = pReverse->pNext ;
pReverse->pNext = pReverse->pPrev ;
pReverse->pPrev = pSave ;
pReverse = pSave ;
}
pFirst->pNext = pKth->pNext ;
pKth->pNext->pPrev = pFirst ;
pKth->pNext = pKth->pPrev ;
pKth->pPrev = pLast ;
pLast->pNext = pKth ;
}
count = 0 ;
pFirst = pLast->pNext ;
pKth = pFirst->pNext ;
}
else
pKth = pKth->pNext ;
} while ( pKth != pLast->pPrev->pPrev && count != 0) ;
if ( count != 0)
pFirst = pFirst->pNext ;
count ++ ;
nTry ++ ;
} while ( count < m_nNumPnts && nTry < MAX_TRY) ;
// ricalcolo il costo del percorso
return TotalCost( pPath) ;
}
+78
View File
@@ -0,0 +1,78 @@
//----------------------------------------------------------------------------
// EgalTech 2015-2015
//----------------------------------------------------------------------------
// File : NN.cpp Data : 22.12.15 Versione : 1.6l4
// Contenuto : Calcolo del percorso minimo basandosi su punto più vicino.
//
//
//
// Modifiche : 22.12.15 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "ShortestPath.h"
/* ------------------------------------------------------------------------- */
unsigned
ShortestPath::NearNeighbor( void)
{
// abilito i collegamenti tra nodi diversi e disabilito gli auto-collegamenti
for ( unsigned i = 0 ; i < m_nNumPnts ; ++ i) {
for ( unsigned j = 0 ; j < m_nNumPnts ; ++ j)
m_Available[ Index( i, j)] = true ;
m_Available[ Index( i, i)] = false ;
}
// cerco il nodo con il più corto arco che se ne diparte
unsigned nCurr = 0 ;
unsigned nNew = CheapArc( nCurr) ;
for ( unsigned i = 1 ; i < m_nNumPnts ; ++ i) {
unsigned j = CheapArc( i) ;
if ( ArcCost( i, j) < ArcCost( nCurr, nNew)) {
nCurr = i ;
nNew = j ;
}
}
// imposto il nodo corrente come base del percorso
NODE* pPath = m_pMain ;
pPath->nPos = nCurr ;
// ciclo
do {
// imposto tutti gli archi non disponibili al nodo corrente
for ( unsigned i = 0 ; i < m_nNumPnts ; ++ i)
m_Available[ Index( i, nCurr)] = false ;
// aggiungo un nuovo nodo al percorso
pPath = pPath->pNext ;
pPath->nPos = nNew ;
// imposto il nuovo nodo come nodo corrente
nCurr = nNew ;
// cerco il nuovo nodo all'estremo dell'arco più corto dal nodo corrente
nNew = CheapArc( nCurr) ;
} while ( m_Available[ Index( nCurr, nNew)]) ;
// calcolo il costo del percorso
return TotalCost( m_pMain) ;
}
/* ------------------------------------------------------------------------- */
unsigned
ShortestPath::CheapArc( unsigned i)
{
// cerco la prima destinazione libera
unsigned j = 0 ;
for ( ; ( j < m_nNumPnts - 1 && ! m_Available[ Index( i, j)]) ; ++ j)
;
// cerco la migliore destinazione libera
for ( unsigned k = j + 1 ; k < m_nNumPnts - 1 ; ++ k) {
if ( m_Available[ Index( i, k)])
if ( ArcCost( i, k) < ArcCost( i, j))
j = k ;
}
return j ;
}
+64
View File
@@ -0,0 +1,64 @@
//----------------------------------------------------------------------------
// EgalTech 2015-2015
//----------------------------------------------------------------------------
// File : PntOpt.cpp Data : 22.12.15 Versione : 1.6l4
// Contenuto : Miglioramento del percorso spostando un punto per volta.
//
// K Last L-1 K Last L-1
// o o-----o--<- o--o _/-o--<-
// |\/ | _|_/
// |/\ |/ |
// o o---> o o--->
// First K+1 First K+1
//
// Modifiche : 22.12.15 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "ShortestPath.h"
/* ------------------------------------------------------------------------- */
unsigned
ShortestPath::PointOpt( NODE* pPath)
{
// ciclo di tentativi di spostamento di un punto
unsigned nCount = 1 ;
NODE* pFirst = pPath ;
do {
unsigned nBestImprove = 0 ;
NODE* pBest = nullptr ;
NODE* pLast = pFirst->pPrev ;
for ( NODE* pKth = pFirst ; pKth != pLast->pPrev->pPrev ; pKth = pKth->pNext) {
unsigned nEXIST = ArcCost( pLast->pPrev->nPos, pLast->nPos) +
ArcCost( pLast->nPos, pFirst->nPos) +
ArcCost( pKth->nPos, pKth->pNext->nPos) ;
unsigned nTEST = ArcCost( pLast->pPrev->nPos, pFirst->nPos) +
ArcCost( pKth->nPos, pLast->nPos) +
ArcCost( pLast->nPos, pKth->pNext->nPos) ;
if ( nTEST < nEXIST && ( nEXIST - nTEST) > nBestImprove) {
nBestImprove = nEXIST - nTEST ;
pBest = pKth ;
}
}
if ( nBestImprove == 0) {
pFirst = pFirst->pNext ;
nCount ++ ;
}
else {
pFirst->pPrev = pLast->pPrev ;
pLast->pPrev->pNext = pFirst ;
pLast->pPrev = pBest ;
pLast->pNext = pBest->pNext ;
pBest->pNext = pLast ;
pLast->pNext->pPrev = pLast ;
nCount = 1 ;
}
} while ( nCount < m_nNumPnts) ;
// ricalcolo il costo del percorso
return TotalCost( pPath) ;
}
+237
View File
@@ -0,0 +1,237 @@
//----------------------------------------------------------------------------
// EgalTech 2015-2015
//----------------------------------------------------------------------------
// File : ShortestPath.cpp Data : 22.12.15 Versione : 1.6l3
// Contenuto : Funzioni per il calcolo del percorso minimo.
//
//
//
// Modifiche : 22.12.15 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "DllMain.h"
#include "ShortestPath.h"
#include "/EgtDev/Include/EGnStringUtils.h"
#include "/EgtDev/Include/EgtILogger.h"
#include <new>
using namespace std ;
//----------------------------------------------------------------------------
IShortestPath*
CreateShortestPath( void)
{
return static_cast<IShortestPath*> ( new(nothrow) ShortestPath) ;
}
//----------------------------------------------------------------------------
ShortestPath::ShortestPath( void)
{
m_nType = SP_NONE ;
m_bSolved = false ;
m_dAngHAdd = 1000 ;
m_dAngHMul = 10 ;
m_dAngVAdd = 2000 ;
m_dAngVMul = 40 ;
m_dStep = 100 ;
m_nNumPnts = 0 ;
m_ObStart.nF = OB_NONE ;
m_ObEnd.nF = OB_NONE ;
m_Dists = nullptr ;
m_Available = nullptr ;
m_pMain = nullptr ;
m_pDupl = nullptr ;
}
//----------------------------------------------------------------------------
ShortestPath::~ShortestPath( void)
{
if ( m_Dists != nullptr)
delete m_Dists ;
m_Dists = nullptr ;
if ( m_Available != nullptr)
delete m_Available ;
m_Available = nullptr ;
if ( m_pMain != nullptr)
delete m_pMain ;
m_pMain = nullptr ;
if ( m_pDupl != nullptr)
delete m_pDupl ;
m_pDupl = nullptr ;
}
//----------------------------------------------------------------------------
bool
ShortestPath::AddPoint( double dX, double dY)
{
return AddPoint( dX, dY, 0, 0, 0, dX, dY, 0, 0, 0) ;
}
//----------------------------------------------------------------------------
bool
ShortestPath::AddPoint( double dXi, double dYi, double dXf, double dYf)
{
return AddPoint( dXi, dYi, 0, 0, 0, dXf, dYf, 0, 0, 0) ;
}
//----------------------------------------------------------------------------
bool
ShortestPath::AddPoint( double dXi, double dYi, double dZi, double dHi, double dVi,
double dXf, double dYf, double dZf, double dHf, double dVf)
{
if ( m_nNumPnts >= MAX_SPPS)
return false ;
m_Points[m_nNumPnts].dXi = dXi ;
m_Points[m_nNumPnts].dYi = dYi ;
m_Points[m_nNumPnts].dZi = dZi ;
m_Points[m_nNumPnts].dHi = dHi ;
m_Points[m_nNumPnts].dVi = dVi ;
m_Points[m_nNumPnts].dXf = dXf ;
m_Points[m_nNumPnts].dYf = dYf ;
m_Points[m_nNumPnts].dZf = dZf ;
m_Points[m_nNumPnts].dHf = dHf ;
m_Points[m_nNumPnts].dVf = dVf ;
++ m_nNumPnts ;
return true ;
}
//----------------------------------------------------------------------------
bool
ShortestPath::SetOpenBound( bool bStartVsEnd, int nFlag, double dX, double dY)
{
return SetOpenBound( bStartVsEnd, nFlag, dX, dY, 0, 0, 0) ;
}
//----------------------------------------------------------------------------
bool
ShortestPath::SetOpenBound( bool bStartVsEnd, int nFlag, double dX, double dY, double dZ, double dH, double dV)
{
// se inizio
if ( bStartVsEnd) {
switch ( nFlag) {
case OB_NONE :
m_ObStart.nF = nFlag ;
break ;
case OB_NEAR_PNT :
m_ObStart.nF = nFlag ;
m_ObStart.dX = dX ;
m_ObStart.dY = dY ;
m_ObStart.dZ = dZ ;
m_ObStart.dH = dH ;
m_ObStart.dV = dV ;
break ;
case OB_XMIN :
case OB_XMAX :
case OB_YMIN :
case OB_YMAX :
m_ObStart.nF = nFlag ;
break ;
default :
return false ;
}
}
// altrimenti fine
else {
switch ( nFlag) {
case OB_NONE :
m_ObEnd.nF = nFlag ;
break ;
case OB_NEAR_PNT :
m_ObEnd.nF = nFlag ;
m_ObEnd.dX = dX ;
m_ObEnd.dY = dY ;
m_ObEnd.dZ = dZ ;
m_ObEnd.dH = dH ;
m_ObEnd.dV = dV ;
break ;
case OB_XMIN :
case OB_XMAX :
case OB_YMIN :
case OB_YMAX :
m_ObEnd.nF = nFlag ;
break ;
default :
return false ;
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
ShortestPath::SetAngularParams( double dAngHAdd, double dAngHMul, double dAngVAdd, double dAngVMul)
{
m_dAngHAdd = float( abs( dAngHAdd)) ;
m_dAngHMul = float( abs( dAngHMul)) ;
m_dAngVAdd = float( abs( dAngVAdd)) ;
m_dAngVMul = float( abs( dAngVMul)) ;
return true ;
}
//----------------------------------------------------------------------------
bool
ShortestPath::SetZzOwStep( double dStep)
{
m_dStep = float( abs( dStep)) ;
return true ;
}
//----------------------------------------------------------------------------
bool
ShortestPath::Calculate( int nType)
{
m_nType = nType ;
switch ( m_nType) {
case SP_CLOSED :
case SP_OPEN :
m_bSolved = Tsp() ;
break ;
case SP_ZIGZAG_X :
case SP_ZIGZAG_Y :
case SP_ONEWAY_XP :
case SP_ONEWAY_XM :
case SP_ONEWAY_YP :
case SP_ONEWAY_YM :
m_bSolved = ZigZag() ;
break ;
default :
m_bSolved = false ;
break ;
}
return m_bSolved ;
}
//----------------------------------------------------------------------------
bool
ShortestPath::GetOrder( INTVECTOR& vOrder)
{
// pulisco risultato
vOrder.clear() ;
// verifico sia stato risolto
if ( ! m_bSolved)
return false ;
// assegno risultato
unsigned nTot = ( ( m_nType == SP_OPEN) ? m_nNumPnts - 1 : m_nNumPnts) ;
vOrder.reserve( nTot) ;
for ( unsigned i = 0 ; i < nTot ; ++ i)
vOrder.push_back( m_nOrder[i]) ;
return true ;
}
//----------------------------------------------------------------------------
bool
ShortestPath::GetMinLength( double& dMinLen)
{
// verifico sia stato risolto
if ( ! m_bSolved)
return false ;
// assegno risultato
dMinLen = m_nMinCost ;
return true ;
}
+117
View File
@@ -0,0 +1,117 @@
//----------------------------------------------------------------------------
// EgalTech 2015-2015
//----------------------------------------------------------------------------
// File : ShortestPath.h Data : 22.12.15 Versione : 1.6l3
// Contenuto : Costanti, tipi e strutture per uso locale.
//
//
//
// Modifiche : 22.12.15 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
#pragma once
#include "/EgtDev/Include/ENkShortestPath.h"
//----------------------------------------------------------------------------
#define MAXCARD 1048576 // 2^20 per evitare overflow con int e 1024 somme
//----------------------------------------------------------------------------
struct SpPoint {
double dXi ;
double dYi ;
double dZi ;
double dHi ;
double dVi ;
double dXf ;
double dYf ;
double dZf ;
double dHf ;
double dVf ;
} ;
struct OpenBound {
int nF ;
double dX ;
double dY ;
double dZ ;
double dH ;
double dV ;
} ;
struct NODE {
NODE* pPrev ;
unsigned nPos ;
NODE* pNext ;
} ;
//----------------------------------------------------------------------------
class ShortestPath : public IShortestPath
{
public :
~ShortestPath( void) override ;
bool AddPoint( double dX, double dY) override ;
bool AddPoint( double dXi, double dYi, double dXf, double dYf) override ;
bool AddPoint( double dXi, double dYi, double dZi, double dHi, double dVi,
double dXf, double dYf, double dZf, double dHf, double dVf) override ;
bool SetOpenBound( bool bStartVsEnd, int nFlag, double dX, double dY) override ;
bool SetOpenBound( bool bStartVsEnd, int nFlag, double dX, double dY, double dZ, double dH, double dV) override ;
bool SetAngularParams( double dAngHAdd, double dAngHMul, double dAngVAdd, double dAngVMul) override ;
bool SetZzOwStep( double dStep) override ;
bool Calculate( int nType) override ;
bool GetOrder( INTVECTOR& vOrder) override ;
bool GetMinLength( double& dMinLen) override ;
public :
ShortestPath( void) ;
private :
bool Tsp( void) ;
bool CalculateImprovements( NODE* pPath) ;
void CalcDistances( void) ;
unsigned GetDistance( float dDx, float dDy, float dDz, float dDh, float dDv) ;
void PreparePath( NODE* pPath) ;
void SavePath( NODE* pPath) ;
void RestorePath( NODE* pPath) ;
unsigned TotalCost( NODE* pPath) ;
void UpdateOrder( NODE* pPath) ;
unsigned Index( unsigned i, unsigned j)
{ return ( i * m_nNumPnts + j) ; }
unsigned ArcCost( unsigned i, unsigned j)
{ return m_Dists[ Index( i, j)] ; }
unsigned NearNeighbor( void) ;
unsigned CheapArc( unsigned i) ;
unsigned FarNeighbor( void) ;
unsigned HighArc( unsigned i) ;
unsigned PointOpt( NODE* pPath) ;
unsigned TwoOpt( NODE* pPath) ;
unsigned Hybrid( NODE* pPath) ;
bool ZigZag( void) ;
unsigned TotalCost( void) ;
private :
static const int MAX_SPPS = 1024 ;
private :
int m_nType ;
bool m_bSolved ;
float m_dAngHAdd ;
float m_dAngHMul ;
float m_dAngVAdd ;
float m_dAngVMul ;
float m_dStep ;
unsigned m_nNumPnts ;
SpPoint m_Points[MAX_SPPS+1] ;
unsigned m_nOrder[MAX_SPPS+1] ;
OpenBound m_ObStart ;
OpenBound m_ObEnd ;
unsigned* m_Dists ;
bool* m_Available ;
NODE* m_pMain ;
NODE* m_pDupl ;
unsigned m_nTotMin ;
unsigned m_nMinCost ;
} ;
+478
View File
@@ -0,0 +1,478 @@
//----------------------------------------------------------------------------
// 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 ;
// calcolo la matrice delle distanze
CalcDistances() ;
// organizzo percorsi
PreparePath( m_pMain) ;
PreparePath( m_pDupl) ;
// inizializzo minimo costo
m_nMinCost = INT_MAX ;
// ---- applico algoritmo NearNeighbor con miglioramenti aggiuntivi ----
unsigned nMinNN = NearNeighbor() ;
string sOut = "-- NearNeighbor : TotalCost = " + ToString( (int)nMinNN) ;
MY_LOG( sOut.c_str()) ;
// 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 ( 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
unsigned nMinInv = TotalCost( m_pMain) ;
string sOut = "-- Inverted NN : TotalCost = " + ToString( (int)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) {
unsigned nMinFN = FarNeighbor() ;
string sOut = "-- FarNeighbor : TotalCost = " + ToString( (int)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) ;
unsigned nPntOpt = PointOpt( pPath) ;
string sOut = " PointOpt : TotalCost = " + ToString( (int)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) ;
unsigned nTwoOpt = TwoOpt( pPath) ;
string sOut = " TwoOpt : TotalCost = " + ToString( (int)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) ;
unsigned nHybOpt = Hybrid( pPath) ;
string sOut = " Hybrid : TotalCost = " + ToString( (int)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-1].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)] = nDist ;
// 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)] = nDist ;
}
// punto su diagonale principale
m_Dists[ Index( m_nNumPnts - 1, m_nNumPnts - 1)] = MAXCARD ;
// devo ancora calcolare le righe/colonne precedenti
nLimit = m_nNumPnts - 1 ;
}
// ciclo per calcolare le distanze tra tutte le coppie di nodi
for ( unsigned i = 0 ; i < nLimit ; ++ i) {
unsigned nRowMinDist = INT_MAX ;
for ( unsigned j = 0 ; j < nLimit ; ++ j) {
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 = GetDistance( dDx, dDy, dDz, dDh, dDv) ;
m_Dists[ Index( i, j)] = nDist ;
// verifico se nuovo minimo di linea
if ( nDist < nRowMinDist)
nRowMinDist = nDist ;
}
else
m_Dists[ Index( i, j)] = MAXCARD ;
}
// aggiorno il totale delle minime distanze
m_nTotMin += nRowMinDist ;
}
// 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 = (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 = " + ToString( int( 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 ;
}
}
//----------------------------------------------------------------------------
unsigned
ShortestPath::TotalCost( NODE* pPath)
{
// ci devono essere almeno due nodi
if ( pPath == nullptr || pPath->pNext == nullptr)
return 0 ;
// lunghezza del primo arco
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 ;
}
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
}
+181
View File
@@ -0,0 +1,181 @@
//----------------------------------------------------------------------------
// EgalTech 2015-2015
//----------------------------------------------------------------------------
// File : ShortestPathZigZag.cpp Data : 22.12.15 Versione : 1.6l4
// Contenuto : Calcolo del percorso minimo per strisce parallele.
// Le coordinate di inizio e fine di ogni punto sono considerate
// coincidenti.
//
//
// Modifiche : 22.12.15 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "DllMain.h"
#include "ShortestPath.h"
#include "/EgtDev/Include/EGnStringUtils.h"
using namespace std ;
//----------------------------------------------------------------------------
#if defined( _DEBUG)
#define MY_LOG(szOut) LOG_INFO( GetENkLogger(), szOut) ;
#else
#define MY_LOG(szOut) ;
#endif
//----------------------------------------------------------------------------
enum { SORT_NONE = 0,
SORT_X_INC = 1,
SORT_X_DEC = 2,
SORT_Y_INC = 3,
SORT_Y_DEC = 4} ;
const double LIN_TOL = 0.1 ;
//----------------------------------------------------------------------------
int
GetMainSort( int nType)
{
switch ( nType) {
case IShortestPath::SP_ZIGZAG_X :
case IShortestPath::SP_ONEWAY_XP :
case IShortestPath::SP_ONEWAY_XM :
return SORT_Y_INC ;
case IShortestPath::SP_ZIGZAG_Y :
case IShortestPath::SP_ONEWAY_YP :
case IShortestPath::SP_ONEWAY_YM :
return SORT_X_INC ;
default :
return SORT_NONE ;
}
}
//----------------------------------------------------------------------------
int
GetStepSort( int nType, int nPrevSort)
{
switch ( nType) {
case IShortestPath::SP_ZIGZAG_X :
return ( nPrevSort == SORT_X_INC) ? SORT_X_DEC : SORT_X_INC ;
case IShortestPath::SP_ZIGZAG_Y :
return ( nPrevSort == SORT_Y_INC) ? SORT_Y_DEC : SORT_Y_INC ;
case IShortestPath::SP_ONEWAY_XP :
return SORT_X_INC ;
case IShortestPath::SP_ONEWAY_XM :
return SORT_X_DEC ;
case IShortestPath::SP_ONEWAY_YP :
return SORT_Y_INC ;
case IShortestPath::SP_ONEWAY_YM :
return SORT_Y_DEC ;
default :
return SORT_NONE ;
}
}
//----------------------------------------------------------------------------
void
SortPaths( SpPoint aPoints[], unsigned aIndices[], unsigned nNumPnts, int nSort)
{
// Bubble sort
for ( unsigned i = 0 ; i < nNumPnts ; ++ i) {
for ( unsigned j = nNumPnts - 1 ; j > i ; -- j) {
bool bSwap = false ;
switch ( nSort) {
default:
case SORT_X_INC :
if ( abs( aPoints[aIndices[j]].dXi - aPoints[aIndices[j - 1]].dXi) < LIN_TOL)
bSwap = ( aPoints[aIndices[j]].dYi < aPoints[aIndices[j - 1]].dYi) ;
else
bSwap = ( aPoints[aIndices[j]].dXi < aPoints[aIndices[j - 1]].dXi) ;
break ;
case SORT_X_DEC :
if ( abs( aPoints[aIndices[j]].dXi - aPoints[aIndices[j - 1]].dXi) < LIN_TOL)
bSwap = ( aPoints[aIndices[j]].dYi < aPoints[aIndices[j - 1]].dYi) ;
else
bSwap = ( aPoints[aIndices[j]].dXi > aPoints[aIndices[j - 1]].dXi + LIN_TOL) ;
break ;
case SORT_Y_INC :
if ( abs( aPoints[aIndices[j]].dYi - aPoints[aIndices[j - 1]].dYi) < LIN_TOL)
bSwap = ( aPoints[aIndices[j]].dXi < aPoints[aIndices[j - 1]].dXi) ;
else
bSwap = ( aPoints[aIndices[j]].dYi < aPoints[aIndices[j - 1]].dYi) ;
break ;
case SORT_Y_DEC :
if ( abs( aPoints[aIndices[j]].dYi - aPoints[aIndices[j - 1]].dYi) < LIN_TOL)
bSwap = ( aPoints[aIndices[j]].dXi < aPoints[aIndices[j - 1]].dXi) ;
else
bSwap = ( aPoints[aIndices[j]].dYi > aPoints[aIndices[j - 1]].dYi) ;
break ;
}
if ( bSwap)
swap( aIndices[j], aIndices[j - 1]) ;
}
}
}
//----------------------------------------------------------------------------
bool
ShortestPath::ZigZag( void)
{
// Almeno un punto
if ( m_nNumPnts < 1)
return false ;
// Ordino i percorsi secondo la direzione di avanzamento principale
int nSort = GetMainSort( m_nType) ;
for ( unsigned i = 0 ; i < m_nNumPnts ; ++ i)
m_nOrder[i] = i ;
SortPaths( m_Points, m_nOrder, m_nNumPnts, nSort) ;
bool bGroupOnX = ( nSort == SORT_X_INC) ;
// Fino a quando non ho ordinato tutti percorsi
unsigned nCount = 0 ;
unsigned i = 0 ;
nSort = GetStepSort( m_nType, SORT_NONE) ;
while ( nCount < m_nNumPnts) {
// Cerco i percorsi che appartengono al range
if ( bGroupOnX) {
double dRange = m_Points[m_nOrder[nCount]].dXi + m_dStep ;
for ( i = nCount + 1 ; i < m_nNumPnts && m_Points[m_nOrder[i]].dXi < dRange - LIN_TOL ; ++ i)
;
}
else {
double dRange = m_Points[m_nOrder[nCount]].dYi + m_dStep ;
for ( i = nCount + 1 ; i < m_nNumPnts && m_Points[m_nOrder[i]].dYi < dRange - LIN_TOL ; ++ i)
;
}
// Ordino i percorsi trovati
SortPaths( m_Points, &m_nOrder[nCount], i - nCount, nSort) ;
nCount = i ;
nSort = GetStepSort( m_nType, nSort) ;
}
// ne calcolo il risultato
m_nMinCost = TotalCost() ;
string sOut = "-- ZigZag/OneWay : TotalCost = " + ToString( (int)m_nMinCost) ;
MY_LOG( sOut.c_str()) ;
return true ;
}
//----------------------------------------------------------------------------
unsigned
ShortestPath::TotalCost( void)
{
unsigned nCost = 0 ;
// ciclo sui nodi
for ( unsigned i = 1 ; i < m_nNumPnts ; ++ i) {
double dDx = m_Points[m_nOrder[i]].dXi - m_Points[m_nOrder[i-1]].dXi ;
double dDy = m_Points[m_nOrder[i]].dYi - m_Points[m_nOrder[i-1]].dYi ;
double dDz = m_Points[m_nOrder[i]].dZi - m_Points[m_nOrder[i-1]].dZi ;
nCost += unsigned( sqrt( dDx * dDx + dDy * dDy + dDz * dDz)) ;
}
return nCost ;
}
+80
View File
@@ -0,0 +1,80 @@
//----------------------------------------------------------------------------
// EgalTech 2015-2015
//----------------------------------------------------------------------------
// File : TwoOpt.cpp Data : 22.12.15 Versione : 1.6l4
// Contenuto : Miglioramento del percorso spezzandolo in 2 parti e
// ricollegando con una delle due parti invertite.
//
// K Last K Last
// o o--<- o--o--<-
// |\/ |
// |/\ |
// o o---> o--o--->
// First K+1 First K+1
//
// Modifiche : 22.12.15 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "ShortestPath.h"
// ----------------------------------------------------------------------------
unsigned
ShortestPath::TwoOpt( NODE* pPath)
{
const int MAX_TRY = 2048 ;
unsigned nTry = 1 ;
unsigned nCount = 1 ;
NODE* pFirst = pPath ;
do {
NODE* pLast = pFirst->pPrev ;
NODE* pKth = pFirst->pNext ;
do {
// lunghezza originale dei tratti da scambiare
unsigned nEXIST = ArcCost( pLast->nPos, pFirst->nPos) +
ArcCost( pKth->nPos, pKth->pNext->nPos) ;
// nuova lunghezza dei tratti da scambiare
unsigned nTEST = ArcCost( pFirst->nPos, pKth->pNext->nPos) +
ArcCost( pLast->nPos, pKth->nPos) ;
// lunghezze originali e nuova del tratto intermedio che viene invertito
for ( NODE* pCurr = pFirst ; pCurr != pKth ; pCurr = pCurr->pNext) {
nEXIST += ArcCost( pCurr->nPos, pCurr->pNext->nPos) ;
nTEST += ArcCost( pCurr->pNext->nPos, pCurr->nPos) ;
}
// se lo scambio fa risparmiare
if ( nTEST < nEXIST) {
// inverto il tratto intermedio
for ( NODE* pCurr = pFirst ; pCurr != pKth ;) {
NODE* pSave = pCurr->pNext ;
pCurr->pNext = pCurr->pPrev ;
pCurr->pPrev = pSave ;
pCurr = pSave ;
}
// sistemo gli estremi
pFirst->pNext = pKth->pNext ;
pKth->pNext->pPrev = pFirst ;
pKth->pNext = pKth->pPrev ;
pKth->pPrev = pLast ;
pLast->pNext = pKth ;
pFirst = pLast->pNext ;
pKth = pFirst->pNext ;
// faccio ripartire il conto
nCount = 0 ;
}
// altrimenti passo al nodo successivo
else
pKth = pKth->pNext ;
} while ( pKth != pLast->pPrev->pPrev && nCount != 0) ;
if ( nCount != 0)
pFirst = pFirst->pNext ;
nCount ++ ;
nTry ++ ;
} while ( nCount < m_nNumPnts && nTry < MAX_TRY) ;
// ricalcolo il costo del percorso
return TotalCost( pPath) ;
}