commit 89d5b97c8ebf6b345dc8cd4414d2b66a04fe49e1 Author: Gerardo Date: Sun Apr 5 23:54:23 2020 +0200 Versión inicial en v2017 entrega Valoriza version 2.0.0.3 diff --git a/Licencia/OliviaTasks.lic b/Licencia/OliviaTasks.lic new file mode 100644 index 0000000..c7711a6 Binary files /dev/null and b/Licencia/OliviaTasks.lic differ diff --git a/Olivia.sln b/Olivia.sln new file mode 100644 index 0000000..7db8439 --- /dev/null +++ b/Olivia.sln @@ -0,0 +1,41 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.28307.329 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Olivia", "Olivia\Olivia.vcxproj", "{192BCB82-D8B4-4FB0-807A-7CC9B6EA623B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OliviaTasks", "OliviaTasks\OliviaTasks.vcxproj", "{A8C66186-EDEF-4041-B7DD-B4FAFCC528EA}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {192BCB82-D8B4-4FB0-807A-7CC9B6EA623B}.Debug|Win32.ActiveCfg = Debug|Win32 + {192BCB82-D8B4-4FB0-807A-7CC9B6EA623B}.Debug|Win32.Build.0 = Debug|Win32 + {192BCB82-D8B4-4FB0-807A-7CC9B6EA623B}.Debug|x64.ActiveCfg = Debug|x64 + {192BCB82-D8B4-4FB0-807A-7CC9B6EA623B}.Debug|x64.Build.0 = Debug|x64 + {192BCB82-D8B4-4FB0-807A-7CC9B6EA623B}.Release|Win32.ActiveCfg = Release|Win32 + {192BCB82-D8B4-4FB0-807A-7CC9B6EA623B}.Release|Win32.Build.0 = Release|Win32 + {192BCB82-D8B4-4FB0-807A-7CC9B6EA623B}.Release|x64.ActiveCfg = Release|x64 + {192BCB82-D8B4-4FB0-807A-7CC9B6EA623B}.Release|x64.Build.0 = Release|x64 + {A8C66186-EDEF-4041-B7DD-B4FAFCC528EA}.Debug|Win32.ActiveCfg = Debug|Win32 + {A8C66186-EDEF-4041-B7DD-B4FAFCC528EA}.Debug|Win32.Build.0 = Debug|Win32 + {A8C66186-EDEF-4041-B7DD-B4FAFCC528EA}.Debug|x64.ActiveCfg = Debug|x64 + {A8C66186-EDEF-4041-B7DD-B4FAFCC528EA}.Debug|x64.Build.0 = Debug|x64 + {A8C66186-EDEF-4041-B7DD-B4FAFCC528EA}.Release|Win32.ActiveCfg = Release|Win32 + {A8C66186-EDEF-4041-B7DD-B4FAFCC528EA}.Release|Win32.Build.0 = Release|Win32 + {A8C66186-EDEF-4041-B7DD-B4FAFCC528EA}.Release|x64.ActiveCfg = Release|x64 + {A8C66186-EDEF-4041-B7DD-B4FAFCC528EA}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {4CAC4A77-AD66-4285-A26F-4551AB036F5C} + EndGlobalSection +EndGlobal diff --git a/Olivia/Msmain.cpp b/Olivia/Msmain.cpp new file mode 100644 index 0000000..5c6be61 --- /dev/null +++ b/Olivia/Msmain.cpp @@ -0,0 +1,129 @@ +#include "StdAfx.h" +#include "Msmain.h" +#include "_log.h" +#include "olv.h" +//******************************************************************************************* +Msmain::Msmain(void) +{ + pirate =false; +} +//******************************************************************************************* +Msmain::~Msmain(void) +{ +} +//******************************************************************************************* +bool Msmain::Despacha_log() +{ + StrArray msgs; + if(log.dame(msgs)) + { +#if _DEBUG + //logea mensages(); + for(int i = 0; i0) + { + ms = "echo " + std::string(st2); + system(ms.c_str()); + } + st2 = 0; + } + } + + if(st2) + { + ms = "echo " + std::string(st2); + system(ms.c_str()); + } + } +#endif + return true; + } + return false; + +} +//******************************************************************************************* +void Msmain::Despacha() +{ + MSG msg; + + while (!pirate) + { + while ( PeekMessage (&msg,NULL,NULL,NULL, + PM_NOREMOVE) ) + { + PeekMessage (&msg,NULL,NULL,NULL, + PM_REMOVE); + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + if(!Despacha_log()) + Sleep(100); + if(olv->isDebug && (olv->tarea == OLV_TAREA_FIN_SEC || olv->tarea == OLV_TAREA_FIN_PLANIF)) + { + //C_log::log("Msmain", olv->msg_proce); + olv->cancela(); + } + + } +} +//******************************************************************************************* +void Msmain::log_ext( __time64_t tiemp, char *modulo, char *fmt ) +{ + char tiem[32]; + char str[1024]; + strftime(tiem, 20, "%Y-%m-%d %H:%M:%S", localtime(&tiemp)); + sprintf_s(str,1024, "%s %-12s %s\r\n", + (char *) LPCTSTR (tiem), + (char *) LPCTSTR (modulo), + (char *) LPCTSTR (fmt)); + log.pon(str); +} +//******************************************************************************************* +bool Cstr_Msg::dame( StrArray& stout ) +{ + if(n_i<=0) + return false; + + if(stout.ind) + free(stout.ind); + if(stout.str) + free(stout.str); + lock_cola.entro(); + + stout.ind=ind; + stout.str=str; + stout.m_str=m_str; + stout.m_i=m_i; + stout.n_str=n_str; + stout.n_i=n_i; + + m_str=m_i=n_i=n_str=0; + str=NULL; + ind=NULL; + lock_cola.salgo(); + return true; +} +//************************************************************************************ +void Cstr_Msg::pon( char* str) +{ + lock_cola.entro(); + add(str); + lock_cola.salgo(); +} +//************************************************************************************ \ No newline at end of file diff --git a/Olivia/Msmain.h b/Olivia/Msmain.h new file mode 100644 index 0000000..22ade4d --- /dev/null +++ b/Olivia/Msmain.h @@ -0,0 +1,45 @@ +#pragma once +#include "olv_dll.h" +#include "gcola.h" +#include "lock.h" +#include "StrArray.h" + +typedef struct Msdata{ + UINT id; + WPARAM wParam; + LPARAM lParam; + bool *proces; +}Msdata; + +//! Clase extendida para manejo de la cola de mensajes del log +/** + * Clase extendida para manejo de la cola de mensajes del log + */ +class Cstr_Msg: public StrArray +{ + Clock lock_cola;//lock de la cola +public: + bool dame(StrArray& stout); + void pon(char* str); +}; +class COlivia; + +//! Clase manager de mensajes enviados para el main +/** + * Clase manager de mensajes enviados para el main + */ +class OLV_EXPORT Msmain +{ + Cstr_Msg log; +public: + COlivia *olv; + + bool pirate; + Msmain(void); + ~Msmain(void); + void log_ext( __time64_t tiemp, char *modulo, char *fmt ); + void Despacha(); + bool Despacha_log(); + +private: +}; diff --git a/Olivia/Olivia.cpp b/Olivia/Olivia.cpp new file mode 100644 index 0000000..d8d91fe --- /dev/null +++ b/Olivia/Olivia.cpp @@ -0,0 +1,50 @@ +// Olivia.cpp : Defines the initialization routines for the DLL. +// + +#include "stdafx.h" +#include "Olivia.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#endif + +/** +* @file Olivia.cpp +* DLL creada por IGT para VSM con el fin de independizar el código +* fuente del software Olivia +* en fecha abril de 2018 +*/ + +// COliviaApp + +BEGIN_MESSAGE_MAP(COliviaApp, CWinApp) +END_MESSAGE_MAP() + + +// COliviaApp construction + +COliviaApp::COliviaApp() +{ + +} + + +// The one and only COliviaApp object + +COliviaApp theApp; + + +// COliviaApp initialization + +BOOL COliviaApp::InitInstance() +{ + CWinApp::InitInstance(); + + if (!AfxSocketInit()) + { + AfxMessageBox(IDP_SOCKETS_INIT_FAILED); + return FALSE; + } + + return TRUE; +} diff --git a/Olivia/Olivia.def b/Olivia/Olivia.def new file mode 100644 index 0000000..537504b --- /dev/null +++ b/Olivia/Olivia.def @@ -0,0 +1,6 @@ +; Olivia.def : Declares the module parameters for the DLL. + +LIBRARY "Olivia" + +EXPORTS + ; Explicit exports can go here diff --git a/Olivia/Olivia.h b/Olivia/Olivia.h new file mode 100644 index 0000000..498ced2 --- /dev/null +++ b/Olivia/Olivia.h @@ -0,0 +1,28 @@ +// Olivia.h : main header file for the Olivia DLL +// + + +#pragma once + +#ifndef __AFXWIN_H__ + #error "include 'stdafx.h' before including this file for PCH" +#endif + +#include "resource.h" // main symbols + +/** +* @file Olivia.h +* DLL de Olivia +*/ + +class COliviaApp : public CWinApp +{ +public: + COliviaApp(); + +// Overrides +public: + virtual BOOL InitInstance(); + + DECLARE_MESSAGE_MAP() +}; \ No newline at end of file diff --git a/Olivia/Olivia.rc b/Olivia/Olivia.rc new file mode 100644 index 0000000..4088185 --- /dev/null +++ b/Olivia/Olivia.rc @@ -0,0 +1,140 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#ifndef APSTUDIO_INVOKED +#include "targetver.h" +#endif +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 2,0,0,3 + PRODUCTVERSION 2,0,0,3 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040a04e4" + BEGIN + VALUE "CompanyName", "VSM" + VALUE "FileDescription", "Librería de la aplicación Olivia" + VALUE "FileVersion", "2.0.0.3" + VALUE "InternalName", "Olivia.dll" + VALUE "LegalCopyright", "OLIVIA (c) VSM 2020. All rights reserved." + VALUE "OriginalFilename", "Olivia.dll" + VALUE "ProductName", "OLIVIA" + VALUE "ProductVersion", "2.0.0.3" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x40a, 1252 + END +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Spanish resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ESN) +#ifdef _WIN32 +LANGUAGE LANG_SPANISH, SUBLANG_SPANISH_MODERN +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#ifndef APSTUDIO_INVOKED\r\n" + "#include ""targetver.h""\r\n" + "#endif\r\n" + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "#define _AFX_NO_SPLITTER_RESOURCES\r\n" + "#define _AFX_NO_OLE_RESOURCES\r\n" + "#define _AFX_NO_TRACKER_RESOURCES\r\n" + "#define _AFX_NO_PROPERTY_RESOURCES\r\n" + "\r\n" + "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n" + "LANGUAGE 9, 1\r\n" + "#pragma code_page(1252)\r\n" + "#include ""res\\Olivia.rc2"" // non-Microsoft Visual C++ edited resources\r\n" + "#include ""afxres.rc"" // Standard components\r\n" + "#endif\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // Spanish resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// +#define _AFX_NO_SPLITTER_RESOURCES +#define _AFX_NO_OLE_RESOURCES +#define _AFX_NO_TRACKER_RESOURCES +#define _AFX_NO_PROPERTY_RESOURCES + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE 9, 1 +#pragma code_page(1252) +#include "res\Olivia.rc2" // non-Microsoft Visual C++ edited resources +#include "afxres.rc" // Standard components +#endif + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/Olivia/Olivia.vcxproj b/Olivia/Olivia.vcxproj new file mode 100644 index 0000000..c211e87 --- /dev/null +++ b/Olivia/Olivia.vcxproj @@ -0,0 +1,397 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {192BCB82-D8B4-4FB0-807A-7CC9B6EA623B} + Olivia + MFCDLLProj + + + + DynamicLibrary + v141 + Dynamic + NotSet + true + + + DynamicLibrary + v141 + Dynamic + NotSet + + + DynamicLibrary + v141 + Dynamic + NotSet + true + + + DynamicLibrary + v141 + Dynamic + NotSet + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>15.0.28127.55 + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + true + MinimumRecommendedRules.ruleset + + + + + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + true + MinimumRecommendedRules.ruleset + + + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + false + MinimumRecommendedRules.ruleset + + + + + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + false + MinimumRecommendedRules.ruleset + + + + + + copy ..\..\bin\$(IntDir)utiles.dll ..\bin\$(IntDir) +copy ..\..\lib\$(IntDir)utiles.lib ..\bin\$(IntDir) +copy ..\..\bin\$(IntDir)LicUtiles.dll ..\bin\$(IntDir) +copy ..\..\lib\$(IntDir)LicUtiles.lib ..\bin\$(IntDir) +copy ..\..\bin\$(IntDir)ClientLic.dll ..\bin\$(IntDir) +copy ..\..\ib\$(IntDir)ClientLic.lib ..\bin\$(IntDir) +copy ..\..\bin\$(IntDir)FileTransfer.dll ..\bin\$(IntDir) +copy ..\..\lib\$(IntDir)FileTransfer.lib ..\bin\$(IntDir) +copy ..\..\bin\$(IntDir)sqlite3.dll ..\bin\$(IntDir) +copy ..\..\lib\$(IntDir)sqlite3.lib ..\bin\$(IntDir) + +copy ..\bin\$(IntDir)utiles.dll $(OutDir) +copy ..\lib\$(IntDir)utiles.lib $(OutDir) +copy ..\bin\$(IntDir)LicUtiles.dll $(OutDir) +copy ..\lib\$(IntDir)LicUtiles.lib $(OutDir) +copy ..\bin\$(IntDir)ClientLic.dll $(OutDir) +copy ..\lib\$(IntDir)ClientLic.lib $(OutDir) +copy ..\bin\$(IntDir)FileTransfer.dll $(OutDir) +copy ..\lib\$(IntDir)FileTransfer.lib $(OutDir) +copy ..\bin\$(IntDir)sqlite3.dll $(OutDir) +copy ..\lib\$(IntDir)sqlite3.lib $(OutDir) + + + _DEBUG;%(PreprocessorDefinitions) + false + + + Disabled + ..\includes\Utiles;..\includes\olivia;..\includes\ClientLic;..\includes\FileTransfer;..\includes\LicUtiles + WIN32;_WINDOWS;_DEBUG;_USRDLL;OLIVIA_COMPILA;OLIVIA_NSENS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + Use + Level3 + EditAndContinue + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + $(IntDir);%(AdditionalIncludeDirectories) + + + utiles.lib;%(AdditionalDependencies) + ..\lib\$(Configuration);%(AdditionalLibraryDirectories) + .\Olivia.def + true + Windows + MachineX86 + + + copy $(OutDir)$(TargetFileName) ..\bin\$(IntDir) +copy $(OutDir)Olivia.lib ..\lib\$(IntDir) + + + + + copy ..\..\bin\$(IntDir)utiles.dll ..\bin\$(IntDir) +copy ..\..\lib\$(IntDir)utiles.lib ..\bin\$(IntDir) +copy ..\..\bin\$(IntDir)LicUtiles.dll ..\bin\$(IntDir) +copy ..\..\lib\$(IntDir)LicUtiles.lib ..\bin\$(IntDir) +copy ..\..\bin\$(IntDir)ClientLic.dll ..\bin\$(IntDir) +copy ..\..\ib\$(IntDir)ClientLic.lib ..\bin\$(IntDir) +copy ..\..\bin\$(IntDir)FileTransfer.dll ..\bin\$(IntDir) +copy ..\..\lib\$(IntDir)FileTransfer.lib ..\bin\$(IntDir) +copy ..\..\bin\$(IntDir)sqlite3.dll ..\bin\$(IntDir) +copy ..\..\lib\$(IntDir)sqlite3.lib ..\bin\$(IntDir) + +copy ..\bin\$(IntDir)utiles.dll $(OutDir) +copy ..\lib\$(IntDir)utiles.lib $(OutDir) +copy ..\bin\$(IntDir)LicUtiles.dll $(OutDir) +copy ..\lib\$(IntDir)LicUtiles.lib $(OutDir) +copy ..\bin\$(IntDir)ClientLic.dll $(OutDir) +copy ..\lib\$(IntDir)ClientLic.lib $(OutDir) +copy ..\bin\$(IntDir)FileTransfer.dll $(OutDir) +copy ..\lib\$(IntDir)FileTransfer.lib $(OutDir) +copy ..\bin\$(IntDir)sqlite3.dll $(OutDir) +copy ..\lib\$(IntDir)sqlite3.lib $(OutDir) + + + _DEBUG;%(PreprocessorDefinitions) + false + X64 + + + Disabled + ..\includes\Utiles;..\includes\olivia;..\includes\ClientLic;..\includes\FileTransfer;..\includes\LicUtiles + WIN32;_WINDOWS;_DEBUG;_USRDLL;OLIVIA_COMPILA;OLIVIA_NSENS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + Use + Level3 + EditAndContinue + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + $(IntDir);%(AdditionalIncludeDirectories) + + + utiles.lib;%(AdditionalDependencies) + ..\lib\x64\$(Configuration);%(AdditionalLibraryDirectories) + .\Olivia.def + true + Windows + MachineX64 + + + copy $(OutDir)$(TargetFileName) ..\bin\$(IntDir) +copy $(OutDir)Olivia.lib ..\lib\$(IntDir) + + + + + copy ..\..\bin\$(IntDir)utiles.dll ..\bin\$(IntDir) +copy ..\..\lib\$(IntDir)utiles.lib ..\bin\$(IntDir) +copy ..\..\bin\$(IntDir)LicUtiles.dll ..\bin\$(IntDir) +copy ..\..\lib\$(IntDir)LicUtiles.lib ..\bin\$(IntDir) +copy ..\..\bin\$(IntDir)ClientLic.dll ..\bin\$(IntDir) +copy ..\..\ib\$(IntDir)ClientLic.lib ..\bin\$(IntDir) +copy ..\..\bin\$(IntDir)FileTransfer.dll ..\bin\$(IntDir) +copy ..\..\lib\$(IntDir)FileTransfer.lib ..\bin\$(IntDir) +copy ..\..\bin\$(IntDir)sqlite3.dll ..\bin\$(IntDir) +copy ..\..\lib\$(IntDir)sqlite3.lib ..\bin\$(IntDir) + +copy ..\bin\$(IntDir)utiles.dll $(OutDir) +copy ..\lib\$(IntDir)utiles.lib $(OutDir) +copy ..\bin\$(IntDir)LicUtiles.dll $(OutDir) +copy ..\lib\$(IntDir)LicUtiles.lib $(OutDir) +copy ..\bin\$(IntDir)ClientLic.dll $(OutDir) +copy ..\lib\$(IntDir)ClientLic.lib $(OutDir) +copy ..\bin\$(IntDir)FileTransfer.dll $(OutDir) +copy ..\lib\$(IntDir)FileTransfer.lib $(OutDir) +copy ..\bin\$(IntDir)sqlite3.dll $(OutDir) +copy ..\lib\$(IntDir)sqlite3.lib $(OutDir) + + + NDEBUG;%(PreprocessorDefinitions) + false + + + MaxSpeed + true + ..\includes\Utiles;..\includes\olivia;..\includes\ClientLic;..\includes\FileTransfer;..\includes\LicUtiles + WIN32;_WINDOWS;NDEBUG;_USRDLL;OLIVIA_COMPILA;OLIVIA_NSENS;%(PreprocessorDefinitions) + MultiThreadedDLL + true + Use + Level3 + ProgramDatabase + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + $(IntDir);%(AdditionalIncludeDirectories) + + + utiles.lib;%(AdditionalDependencies) + ..\lib\$(Configuration);%(AdditionalLibraryDirectories) + .\Olivia.def + true + Windows + true + true + MachineX86 + + + copy $(OutDir)$(TargetFileName) ..\bin\$(IntDir) +copy $(OutDir)Olivia.lib ..\lib\$(IntDir) + + + + + copy ..\..\bin\$(IntDir)utiles.dll ..\bin\$(IntDir) +copy ..\..\lib\$(IntDir)utiles.lib ..\bin\$(IntDir) +copy ..\..\bin\$(IntDir)LicUtiles.dll ..\bin\$(IntDir) +copy ..\..\lib\$(IntDir)LicUtiles.lib ..\bin\$(IntDir) +copy ..\..\bin\$(IntDir)ClientLic.dll ..\bin\$(IntDir) +copy ..\..\ib\$(IntDir)ClientLic.lib ..\bin\$(IntDir) +copy ..\..\bin\$(IntDir)FileTransfer.dll ..\bin\$(IntDir) +copy ..\..\lib\$(IntDir)FileTransfer.lib ..\bin\$(IntDir) +copy ..\..\bin\$(IntDir)sqlite3.dll ..\bin\$(IntDir) +copy ..\..\lib\$(IntDir)sqlite3.lib ..\bin\$(IntDir) + +copy ..\bin\$(IntDir)utiles.dll $(OutDir) +copy ..\lib\$(IntDir)utiles.lib $(OutDir) +copy ..\bin\$(IntDir)LicUtiles.dll $(OutDir) +copy ..\lib\$(IntDir)LicUtiles.lib $(OutDir) +copy ..\bin\$(IntDir)ClientLic.dll $(OutDir) +copy ..\lib\$(IntDir)ClientLic.lib $(OutDir) +copy ..\bin\$(IntDir)FileTransfer.dll $(OutDir) +copy ..\lib\$(IntDir)FileTransfer.lib $(OutDir) +copy ..\bin\$(IntDir)sqlite3.dll $(OutDir) +copy ..\lib\$(IntDir)sqlite3.lib $(OutDir) + + + NDEBUG;%(PreprocessorDefinitions) + false + X64 + + + MaxSpeed + true + ..\includes\Utiles;..\includes\olivia;..\includes\ClientLic;..\includes\FileTransfer;..\includes\LicUtiles + WIN32;_WINDOWS;NDEBUG;_USRDLL;OLIVIA_COMPILA;OLIVIA_NSENS;%(PreprocessorDefinitions) + MultiThreadedDLL + true + Use + Level3 + ProgramDatabase + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + $(IntDir);%(AdditionalIncludeDirectories) + + + utiles.lib;%(AdditionalDependencies) + ..\lib\x64\$(Configuration);%(AdditionalLibraryDirectories) + .\Olivia.def + true + Windows + true + true + MachineX64 + + + copy $(OutDir)$(TargetFileName) ..\bin\$(IntDir) +copy $(OutDir)Olivia.lib ..\lib\$(IntDir) + + + + + + + + + + + + + + + + + + + Create + Create + Create + Create + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Olivia/Olivia.vcxproj.filters b/Olivia/Olivia.vcxproj.filters new file mode 100644 index 0000000..81ecd35 --- /dev/null +++ b/Olivia/Olivia.vcxproj.filters @@ -0,0 +1,137 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Source Files + + + Resource Files + + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Resource Files + + + \ No newline at end of file diff --git a/Olivia/Olivia.vcxproj.user b/Olivia/Olivia.vcxproj.user new file mode 100644 index 0000000..be25078 --- /dev/null +++ b/Olivia/Olivia.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Olivia/OlvAsync_cola.h b/Olivia/OlvAsync_cola.h new file mode 100644 index 0000000..86fba02 --- /dev/null +++ b/Olivia/OlvAsync_cola.h @@ -0,0 +1,43 @@ +#pragma once +#include "th_cola.h" +template +class DataOlvAsync_cola{ +public: + int id; + T data; +}; + +template +class OlvAsync_cola : public Cth_cola> +{ + + void (*func_proc)( int, OlvAsync_cola

*, P *); +public: + OlvAsync_cola(void){}; + ~OlvAsync_cola(void){}; + + void inicia(int miliseconds,void (*func)( int, OlvAsync_cola

*, P *), int fin =-1, char* nombre=NULL) + { + func_proc =func; + time_sleep = miliseconds; + pirate=FALSE; + lanza(nombre); + } + + virtual void procesa(DataOlvAsync_cola

&t)//override de procesado que hay que sobreescribir + { + func_proc(t.id,this,&t.data); + }; + void encola(int tarea, P *argumentos, BOOL forzar) + { + DataOlvAsync_cola

t; + t.id = tarea; + if(argumentos) + t.data = *argumentos; + (*this)+t; + } + void termina() + { + fin(); + } +}; diff --git a/Olivia/ReadMe.txt b/Olivia/ReadMe.txt new file mode 100644 index 0000000..91c7cb8 --- /dev/null +++ b/Olivia/ReadMe.txt @@ -0,0 +1,60 @@ +======================================================================== + MICROSOFT FOUNDATION CLASS LIBRARY : Olivia Project Overview +======================================================================== + + +AppWizard has created this Olivia DLL for you. This DLL not only +demonstrates the basics of using the Microsoft Foundation classes but +is also a starting point for writing your DLL. + +This file contains a summary of what you will find in each of the files that +make up your Olivia DLL. + +Olivia.vcproj + This is the main project file for VC++ projects generated using an Application Wizard. + It contains information about the version of Visual C++ that generated the file, and + information about the platforms, configurations, and project features selected with the + Application Wizard. + +Olivia.h + This is the main header file for the DLL. It declares the + COliviaApp class. + +Olivia.cpp + This is the main DLL source file. It contains the class COliviaApp. + +Olivia.rc + This is a listing of all of the Microsoft Windows resources that the + program uses. It includes the icons, bitmaps, and cursors that are stored + in the RES subdirectory. This file can be directly edited in Microsoft + Visual C++. + +res\Olivia.rc2 + This file contains resources that are not edited by Microsoft + Visual C++. You should place all resources not editable by + the resource editor in this file. + +Olivia.def + This file contains information about the DLL that must be + provided to run with Microsoft Windows. It defines parameters + such as the name and description of the DLL. It also exports + functions from the DLL. + +///////////////////////////////////////////////////////////////////////////// +Other standard files: + +StdAfx.h, StdAfx.cpp + These files are used to build a precompiled header (PCH) file + named Olivia.pch and a precompiled types file named StdAfx.obj. + +Resource.h + This is the standard header file, which defines new resource IDs. + Microsoft Visual C++ reads and updates this file. + +///////////////////////////////////////////////////////////////////////////// +Other notes: + +AppWizard uses "TODO:" to indicate parts of the source code you +should add to or customize. + +///////////////////////////////////////////////////////////////////////////// diff --git a/Olivia/Resource.h b/Olivia/Resource.h new file mode 100644 index 0000000..9d2a6bf --- /dev/null +++ b/Olivia/Resource.h @@ -0,0 +1,17 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Olivia.rc +// +#define IDP_SOCKETS_INIT_FAILED 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS + +#define _APS_NEXT_RESOURCE_VALUE 1000 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 1000 +#define _APS_NEXT_COMMAND_VALUE 32771 +#endif +#endif diff --git a/Olivia/olv.cpp b/Olivia/olv.cpp new file mode 100644 index 0000000..163ea40 --- /dev/null +++ b/Olivia/olv.cpp @@ -0,0 +1,608 @@ +#include "stdafx.h" +#ifdef OLIVIA_COMPILA +//olivia +#include "olv.h" +#include "olv_limp.h" +#include "olv_sock.h" +#include "olv_limp_thr.h" +#include "olv_reco.h" +#include "olv_tasks_def.h" +//utiles +#include "ini_file.h" +#include "_error.h" +#include "lock.h" +#include "Msmain.h" +#include "utl.h" + +/** +* Una vez configurada la herramienta OLIVIA a través del Addin para ArcGIS desarrollado +* a tal efecto en c# vc2010, se llama al proceso OliviaTasks.exe que se encontrará en el directorio +* de instalación "\bin" +*/ + +/** +* @file olv.cpp +* Archivo de implementaciones generales de la herramienta Olivia de OliviaTasks. +*/ + +COlivia::COlivia(void) +{ + isDebug = false; + tipo_oliv = OliviaDef::GeneralDef::OlivNoDef; + memset(&paths, 0, &paths.pfin-(char*)&paths); + olv_limp = NULL; + ya_config=FALSE; + fin=FALSE; + tarea=progreso=0; + rellena_tareas(); //Rellena los textos de las tareas + msg_proce[0]=0; + modo_ejec=OLV_EJEC_NDEBUG; + olv_reco=NULL; + olv_sock = new Colv_sock(this); + lock = new Clock(); + strcpy_s(paths.path_cfg_geo,"C:\\olivia\\cfg_geo.ini"); + + modo_multitask=FALSE; + memset(&infotask,0,sizeof(InfoIniTask)); + log.l_lisener = this; +} + +COlivia::~COlivia(void) +{ + if(olv_limp) + delete olv_limp; + if(olv_reco) + delete olv_reco; + + delete (olv_sock); + delete (lock); +} +//************************************************************************************* +/** + * Rellena la matriz de textos de tareas + */ +void COlivia::rellena_tareas() +{ + sprintf_s(tareas_str[OLV_TAREA_CALC],OLV_MAX_TAREA,"Conectado, comenzando cálculos\n"); + sprintf_s(tareas_str[OLV_TAREA_IMP],OLV_MAX_TAREA,"Importando datos\n"); + sprintf_s(tareas_str[OLV_TAREA_SENS],OLV_MAX_TAREA,"Leyendo información de carga de los sensores\n"); + sprintf_s(tareas_str[OLV_TAREA_UNE_NW_AMB],OLV_MAX_TAREA,"Uniendo ámbitos a red navegable\n"); + sprintf_s(tareas_str[OLV_TAREA_TOPO_NW],OLV_MAX_TAREA,"Generando topologías en la red\n"); + sprintf_s(tareas_str[OLV_TAREA_COST_AMB],OLV_MAX_TAREA,"Calculando matriz de costes entre ámbitos\n"); + sprintf_s(tareas_str[OLV_TAREA_GUARD_MAT],OLV_MAX_TAREA,"Guardando matrices\n"); + sprintf_s(tareas_str[OLV_TAREA_MULTITASK],OLV_MAX_TAREA,"Calculando costes entre ámbitos en multitask...\n"); + sprintf_s(tareas_str[OLV_TAREA_SECTORIZ],OLV_MAX_TAREA,"Sectorizando\n"); + sprintf_s(tareas_str[OLV_TAREA_CALC_SEC],OLV_MAX_TAREA,"Calculando número de sectores\n"); + sprintf_s(tareas_str[OLV_TAREA_PERMU],OLV_MAX_TAREA,"Calculando permutaciones para mejorar...Puede tardar unos minutos\n"); + sprintf_s(tareas_str[OLV_TAREA_LEE_SECTO],OLV_MAX_TAREA,"Leyendo sectorización\n"); + sprintf_s(tareas_str[OLV_TAREA_PLANIF],OLV_MAX_TAREA,"Planificando\n"); + sprintf_s(tareas_str[OLV_TAREA_FIN_SEC],OLV_MAX_TAREA,OliviaDef::GeneralDef::SockSectFin); + sprintf_s(tareas_str[OLV_TAREA_FIN_PLANIF],OLV_MAX_TAREA,OliviaDef::GeneralDef::SockPlanFin); + sprintf_s(tareas_str[OLV_TAREA_FIN_OK],OLV_MAX_TAREA,OliviaDef::GeneralDef::SockFinOk); + sprintf_s(tareas_str[OLV_TAREA_FIN_NOK],OLV_MAX_TAREA,OliviaDef::GeneralDef::SockFinNOk); +} +//************************************************************************************* +/** + * Función llamada por el mainframe para delete el socket ppal + */ +void COlivia::destruye_socket(LPARAM lp) +{ + delete ((Colv_sock*)lp); +} +//************************************************************************************* +/** + * Dada la línea de comandos, la divide en los parámetros necesarios + */ +BOOL COlivia::coge_param(char *param) +{ + char *token; + int j; + + //los parámetros son: + //\olivia \tipo_oliv \cfg.ini \ip \puerto \toutsock + token = strtok(param, OliviaDef::GeneralDef::EjecGeoParamSep); + + //Lee parámetros + j=0; + while (token != NULL) + { + if(strstr(token,OliviaDef::GeneralDef::GG_tipo)) + { + if(!dame_param(token,&tipo_oliv)) + break; + } + else if(strstr(token,OliviaDef::GeneralDef::GG_ip)) + { + if(!dame_param(token, olv_sock->ip,sizeof(olv_sock->ip))) + break; + } + else if(strstr(token,OliviaDef::GeneralDef::GG_port)) + { + if(!dame_param(token, &olv_sock->puerto)) + break; + } + else if(strstr(token,OliviaDef::GeneralDef::GG_tout)) + { + int t_out; + if(!dame_param(token, &t_out)) + break; + olv_sock->pon_tout(t_out); + } + else if(strstr(token,OliviaDef::GeneralDef::GG_pt)) + { + if(!dame_param(token, paths.path_temp,sizeof(paths.path_temp))) + break; + } + else if(strstr(token,OliviaDef::GeneralDef::GG_pcfg)) + { + if(!dame_param(token, paths.path_cfg_geo,sizeof(paths.path_cfg_geo))) + break; + } + else if(strstr(token, "debug")) + isDebug = true; + else + break; + token = strtok(NULL, OliviaDef::GeneralDef::EjecGeoParamSep); + j++; + } + if(jlog.path,&fils); + fils.filtra(&filsa,".log"); + n = filsa.size()-1; + + //borra log antiguo----------------------- + while(n>=0) + { + buf.n_i = buf.n_str =0; + f =filsa.get(n--); + if(Cutl::stringSplit(f,"_", &buf)->n_i<5) + continue; + if(!strstr(buf.get(0),C_app::GetApp()->log.nombre)) + continue; + + i=atoi(buf.get(1)); + if(iano) + continue; + + //busca mes----------------- + i=atoi(buf.get(2)); + if(imes) + continue; + + //busca dia-------------------- + if(atoi(buf.get(3))pon_escucha(olv_sock->ip,olv_sock->puerto)) + { + olv_sock->cierra(); + sprintf_s(err,nerr,"Error al iniciar OliviaTasks para OLIVIA:\nError al iniciar socket"); + ret=FALSE; + } + } + + return ret; +} +//************************************************************************************* +/** + * Devuelve la tarea por la que se va ejecutando + */ +int COlivia::dame_tarea() +{ + return tarea; +} +//************************************************************************************* +/** + * Devuelve el progreso de ejecución de la tarea, de 0 a 100 + */ +int COlivia::dame_progre() +{ + return progreso; +} +//************************************************************************************* +/** + * Pone las opciones de configuración de lo que recibe por el socket + */ +BOOL COlivia::pon_config(char *config) +{ + BOOL ret=FALSE; + + ya_config=TRUE; + + if(strstr(config,OliviaDef::GeneralDef::SockConfPlan)) + modo_ejec=OLV_EJEC_PLAN; + else if(strstr(config,OliviaDef::GeneralDef::SockConfTodo)) + modo_ejec=OLV_EJEC_TODO; + else if(strstr(config,OliviaDef::GeneralDef::SockConf)) + modo_ejec=OLV_EJEC_SECT; + + switch(tipo_oliv) + { + case OliviaDef::GeneralDef::OlivLimp: + if(olv_limp->pon_config(config)==OliviaDef::GeneralDef::ParamLimpN) + ret = olv_limp->inicia(); + break; + case OliviaDef::GeneralDef::OlivResi: + if(olv_reco->pon_config(config)==OliviaDef::GeneralDef::ParamRecoN) + ret = olv_reco->inicia(); + break; + default: + break; + } + + return ret; +} +//************************************************************************************* +/** + * Cancela el proceso, borra archivos temporales y cierra + */ +void COlivia::cancela() +{ + + switch(tipo_oliv) + { + case OliviaDef::GeneralDef::OlivLimp: + olv_limp->cancela(); + break; + default: + break; + } + + /*if(olv_limp && olv_limp->thr_limp && !olv_limp->thr_limp->fin_permu) + { + //manda cerrar + //SendMessage(mfrm,WM_CLOSE,0,0); + mfrm->pirate = true; + }*/ + mfrm->pirate = true; +} +//************************************************************************************* +/** + * Devuelve el parámetro, char* + */ +BOOL COlivia::dame_param(char *token, char *param, int sizeparam) +{ + char *c; + int ss; + + c=strstr(token,OliviaDef::GeneralDef::EjecGeoParamIgual); + if(!c) + return FALSE; + + strcpy_s(param,sizeparam,(c+1)); + + ss=(int)strlen(param); + param[ss-1]=0; + + return TRUE; +} +//************************************************************************************* +/** + * Devuelve el parámetro, int + */ +BOOL COlivia::dame_param(char *token, int *param) +{ + char *c; + + c=strstr(token,OliviaDef::GeneralDef::EjecGeoParamIgual); + if(!c) + return FALSE; + + *param=atoi(c+1); //el valor está a continuación del separador + + return TRUE; +} +//************************************************************************************* +/** + * Devuelve el parámetro, double + */ +BOOL COlivia::dame_param(char *token, double *param) +{ + char *c; + + c=strstr(token,OliviaDef::GeneralDef::EjecGeoParamIgual); + if(!c) + return FALSE; + + *param=atof(c+1); //el valor está a continuación del separador + + return TRUE; +} +//************************************************************************************* +/** + * Función de ejecución de prueba para Debug + */ +void COlivia::prueba() +{ + int i; + const int max_char_cap=3048; + char config[max_char_cap]; + + /////////////////// + //solo para debug elena olivia + i=1; + + if(fin) + { + //cerrar_cartografia(); + if(tipo_oliv==0) + { + delete olv_limp; + olv_limp = new Colv_limp(this); + } + else + { + delete olv_reco; + olv_reco = new Colv_reco(this); + } + } + + switch(i) + { + case 1://coor_inst_x:542996.13 /coor_inst_y:4624509.22 + sprintf_s(config, max_char_cap,"/CONFIG_TODO /t_tto:2900 /restr_cir:0 /u_tto:1 /v_despl:3 /t_conv:480 /t_descan:30 /t_despl:30 /t_carg:30 /aislados:0 "\ + "/h_inicio:450 /trafico:80 "\ + "/n_ptsctrl:3 /n_secdef:2 /anch_med:0 /coor_inst_x:0 /coor_inst_y:0 /path_data:C:\\Proyectos\\Olivia\\Instal\\data_barrMix2Ejes_Todo\\data_T05_20190605_234043.shp "\ + "/path_nw:C:\\Proyectos\\Olivia\\Instal\\data_barrMix2Ejes_Todo\\nw_20190605_234043.shp "\ + "/cons_obser:OBSERVACIONES /cons_anch_tip:ANCHO_TIPO /cons_tipolo:TIPOLOGIA /cons_tip_ent:NOM_TIPO_ENTIDAD "\ + "/atr_aparc:Banda Aparcamiento /atr_bord:Bordillo Libre /atr_acera:Aceras /atr_peat:Peatonales"\ + "/atr_ap_lin:Linea /atr_ap_bat:Bateria /cons_onew:ONEWAY /cons_kph:KPH /cons_fow:FOW "\ + "/cons_name:NAME /atr_TF:TF /atr_FT:FT /atr_N:N /atr_pedes:14 /str_tto:Barrido_mixto "); + break; + case 2: + sprintf_s(config, max_char_cap,"/CONFIG_TODO /campo_capaci:CAPACIDAD /kg_max:11500 /campo_kgrecog:KGRECO /campo_uds:UNIDADES "\ + "/recogida_kg:200 /carga_cont:-1 /densidad:-1 /t_conv:480 /t_descan:30 /t_vacia:60 /t_descarg:20 /t_sallleg:5 /h_inicio:420 "\ + "/trafico:80 /n_ptsctrl:3 /n_secdef:3 /anch_vehi:2,5 /giro_vehi:175 /coor_inst_x:545024,4974 /coor_inst_y:4623840,8944 "\ + "/coor_desc_x:545024,4974 /coor_desc_y:4623840,8944 /sens_id: /sens_url: /sens_fechai: /sens_fechaf: /md_pet:-1 "\ + "/aislados:0 /lateralidad:-1 /cons_onew:ONEWAY /cons_kph:KPH /cons_fow:FOW /cons_name:NAME /atr_TF:TF /atr_FT:FT "\ + "/atr_N:N /atr_pedes:14 /str_tto:Resto /path_data:C:\\Proyectos\\Olivia\\Instal\\data_reco\\data_F01_C06_T1603_20190624_130559.shp "\ + "/path_nw:C:\\Proyectos\\Olivia\\Instal\\data_reco\\nw_20190624_130559.shp "); + break; + case 3: //coor_inst_x:542996.13 /coor_inst_y:4624509.22 + sprintf_s(config, max_char_cap,"/CONFIG_TODO /t_tto:2900 /restr_cir:0 /u_tto:3 /v_despl:5 /t_conv:480 /t_descan:30 /t_despl:25 /t_carg:40 /h_inicio:420" + "/trafico:80 /n_ptsctrl:3 /n_secdef:4 /anch_med:2 /coor_inst_x:0 /coor_inst_y:0 /aislados:0 /cons_obser:OBSERVACIONES /cons_anch_tip:ANCHO_TIPO " + "/cons_tipolo:TIPOLOGIA /cons_tip_ent:NOM_TIPO_ENTIDAD /atr_aparc:Banda Aparcamiento /atr_bord:Bordillo Libre /atr_acera:Aceras /atr_peat:Peatonales " + "/atr_ap_lin:Linea /atr_ap_bat:Bateria /cons_onew:ONEWAY /cons_kph:KPH /cons_fow:FOW /cons_name:NAME /atr_TF:TF /atr_FT:FT /atr_N:N /atr_pedes:14 " + "/str_tto:Barrido_manual /path_data:C:\\Proyectos\\Olivia\\Instal\\data_limp_grande\\data_T00_A04050607_NNivel3_20191020_01228.shp " + "/path_nw:C:\\Proyectos\\Olivia\\Instal\\data_limp_grande\\nw_20191020_01228.shp "); + break; + case(4):///coor_inst_x:545184,9643 /coor_inst_y:4624026,7103 + sprintf_s(config, max_char_cap,"/CONFIG_TODO /t_tto:5600 /restr_cir:1 /u_tto:3 /v_despl:15 /t_conv:480 /t_descan:30 /t_despl:25 /t_carg:40 /h_inicio:420 /trafico:80 "\ + "/n_ptsctrl:3 /n_secdef:2 /anch_med:2 /coor_inst_x:545184,9643 /coor_inst_y:4624026,7103 /aislados:0 /cons_obser:OBSERVACIONES /cons_anch_tip:ANCHO_TIPO "\ + "/cons_tipolo:TIPOLOGIA /cons_tip_ent:NOM_TIPO_ENTIDAD /atr_aparc:Banda Aparcamiento /atr_bord:Bordillo Libre /atr_acera:Aceras /atr_peat:Peatonales "\ + "/atr_ap_lin:Linea /atr_ap_bat:Bateria /cons_onew:ONEWAY /cons_kph:KPH /cons_fow:FOW /cons_name:NAME /atr_TF:TF /atr_FT:FT /atr_N:N /atr_pedes:14 "\ + "/str_tto:Barrido_mixto /path_data:C:\\Proyectos\\Olivia\\Instal\\data_barrmix\\data_T05_A01030405_NVehículosSatelite_20191019_120727.shp "\ + "/path_nw:C:\\Proyectos\\Olivia\\Instal\\data_barrmix\\nw_20191019_120727.shp "); + break; + case(5):///coor_desc_x:543385,702 /coor_desc_y:4622930,4 + sprintf_s(config, max_char_cap,"/CONFIG_TODO /campo_capaci:CAPACIDAD /kg_max:850 /campo_kgrecog:KGRECO /campo_uds:UNIDADES /recogida_kg:200 "\ + "/carga_cont:-1 /densidad:-1 /t_conv:480 /t_descan:30 /t_vacia:60 /t_descarg:20 /t_sallleg:5 /h_inicio:420 /trafico:80 /n_ptsctrl:3 "\ + "/n_secdef:2 /anch_vehi:2,5 /giro_vehi:175 /coor_inst_x:545184,9643 /coor_inst_y:4624026,7103 /coor_desc_x:543385,702 /coor_desc_y:4622930,4 "\ + "/sens_id: /sens_url: /sens_fechai: /sens_fechaf: /md_pet:-1 /aislados:0 /lateralidad:-1 /cons_onew:ONEWAY /cons_kph:KPH /cons_fow:FOW /cons_name:NAME "\ + "/atr_TF:TF /atr_FT:FT /atr_N:N /atr_pedes:14 /str_tto:Resto /path_data:C:\\Proyectos\\Olivia\\Instal\\data_reco\\data_F01_C06_TVehículosSatelite_20191019_120001.shp "\ + "/path_nw:C:\\Proyectos\\Olivia\\Instal\\data_reco\\nw_20191019_120001.shp "); + break; + case(6):///coor_desc_x:543385,702 /coor_desc_y:4622930,4 + sprintf_s(config, max_char_cap,"/CONFIG_TODO /campo_capaci:CAPACIDAD /kg_max:850 /campo_kgrecog:KGRECO /campo_uds:UNIDADES /recogida_kg:200 "\ + "/carga_cont:-1 /densidad:-1 /t_conv:480 /t_descan:30 /t_vacia:60 /t_descarg:20 /t_sallleg:5 /h_inicio:420 /trafico:80 /n_ptsctrl:3 "\ + "/n_secdef:3 /anch_vehi:2,5 /giro_vehi:175 /coor_inst_x:545184,9643 /coor_inst_y:4624026,7103 /coor_desc_x:543385,702 /coor_desc_y:4622930,4 "\ + "/sens_id: /sens_url: /sens_fechai: /sens_fechaf: /md_pet:-1 /aislados:0 /lateralidad:-1 /cons_onew:ONEWAY /cons_kph:KPH /cons_fow:FOW /cons_name:NAME "\ + "/atr_TF:TF /atr_FT:FT /atr_N:N /atr_pedes:14 /str_tto:Resto /path_data:C:\\Proyectos\\Olivia\\Instal\\data_comp_reco\\data_F01_C01_TNivel3_20191026_234244.shp "\ + "/path_nw:C:\\Proyectos\\Olivia\\Instal\\data_comp_reco\\nw_20191026_234244.shp "); + break; + case(51): //ger + strcpy(config, "/CONFIG_TODO /campo_capaci:CAPACIDAD /kg_max:8500 " + "/campo_kgrecog:KGRECO /campo_uds:UNIDADES /recogida_kg:200 /carga_cont:-1 " + "/densidad:-1 /t_conv:480 /t_descan:30 /t_vacia:60 /t_descarg:20 " + "/t_sallleg:5 /h_inicio:420 /trafico:80 /n_ptsctrl:3 /n_secdef:2 " + "/anch_vehi:2,5 /giro_vehi:175 /coor_inst_x:545184,9643 " + "/coor_inst_y:4624026,7103 /coor_desc_x:545184,9643 /coor_desc_y:4624026,7103 " + "/sens_id: /sens_url: /sens_fechai: /sens_fechaf: /md_pet:-1 /aislados:0 " + "/lateralidad:-1 /cons_onew:ONEWAY /cons_kph:KPH /cons_fow:FOW /cons_name:NAME " + "/atr_TF:TF /atr_FT:FT /atr_N:N /atr_pedes:14 /str_tto:Resto " + "/path_data:D:\\DatosOlivia\\data_reco\\data_F01_C06_TVehículosSatelite_20191019_120001.shp " + "/path_nw:D:\\DatosOlivia\\data_reco\\nw_20191019_120001.shp "); + break; +case(52): //ger + strcpy(config, "/CONFIG /t_tto:2900 /restr_cir:0 /u_tto:3 /v_despl:5 /t_conv:480 " + "/t_descan:30 /t_despl:25 /t_carg:40 /h_inicio:420 /trafico:80 /n_ptsctrl:3 /n_secdef:2 " + "/anch_med:2 /coor_inst_x:0 /coor_inst_y:0 /aislados:0 /cons_obser:OBSERVACIONES /cons_anch_tip:ANCHO_TIPO" + " /cons_tipolo:TIPOLOGIA /cons_tip_ent:NOM_TIPO_ENTIDAD /atr_aparc:Banda Aparcamiento /atr_bord:Bordillo Libre" + " /atr_acera:Aceras /atr_peat:Peatonales /atr_ap_lin:Linea /atr_ap_bat:Bateria /cons_onew:ONEWAY /cons_kph:KPH" + " /cons_fow:FOW /cons_name:NAME /atr_TF:TF /atr_FT:FT /atr_N:N /atr_pedes:14 /str_tto:Barrido_manual " + "/path_data:D:\\DatosOlivia\\data_limp\\data_T00_A04050607_NVehiculosSatelite_20191019_115600.shp " + "/path_nw:D:\\DatosOlivia\\data_limp\\nw_20191019_115600.shp "); + break; + +case(53): //ger + strcpy(config, "/CONFIG /t_tto:2900 /restr_cir:0 /u_tto:3 /v_despl:5 " + "/t_conv:480 /t_descan:30 /t_despl:25 /t_carg:40 /h_inicio:420 " + "/trafico:80 /n_ptsctrl:3 /n_secdef:3 /anch_med:2 /coor_inst_x:0 " + "/coor_inst_y:0 /aislados:0 /cons_obser:OBSERVACIONES /cons_anch_tip:ANCHO_TIPO " + "/cons_tipolo:TIPOLOGIA /cons_tip_ent:NOM_TIPO_ENTIDAD " + "/atr_aparc:Banda Aparcamiento /atr_bord:Bordillo Libre /atr_acera:Aceras " + "/atr_peat:Peatonales /atr_ap_lin:Linea /atr_ap_bat:Bateria /cons_onew:ONEWAY " + "/cons_kph:KPH /cons_fow:FOW /cons_name:NAME /atr_TF:TF /atr_FT:FT /atr_N:N " + "/atr_pedes:14 /str_tto:Barrido_manual " + "/path_data:D:\\DatosOlivia\\data_limp_grande\\data_T00_A04050607_NNivel3_20191020_01228.shp " + "/path_nw:D:\\DatosOlivia\\data_limp_grande\\nw_20191020_01228.shp "); + break; + } + + /////////////////////////////////////////////// + /*CoptiMemo oo; + int nvect = oo.calc_nvect_master(20000); + BOOL is = oo.is_multi(20000,8,12); */ + /////////////////////////////////////////////// + + + modo_ejec=OLV_EJEC_DEBUG_SIGUE; + pon_config(config); + + if(!fin) + fin=TRUE; +} +//************************************************************************************* +BOOL COlivia::creaSocProces( Colv_limp *olv_limp ) +{ + //SendMessage(mfrm,WMS_CMD,WMS_CMD_OLV_CREA_SOCK_MULTI, (LPARAM)olv_limp); + return olv_limp->soc != NULL; + //crea socket +} +//************************************************************************************* +BOOL COlivia::destruyeSocProces( Colv_limp *olv_limp ) +{ + //SendMessage(mfrm,WMS_CMD,WMS_CMD_OLV_DEST_SOCK_MULTI, (LPARAM)olv_limp); + return olv_limp->soc != NULL; + //crea socket +} +//************************************************************************************* +/** + * Funcion llamada por el mainframe para crear el socket multitask + */ +void COlivia::crea_socket_multi( LPARAM lp ) +{ + /* + Colv_limp *limp = (Colv_limp*)lp; + limp->soc = new Csock_sv(); + limp->soc->escucha=(Cescucha_sock_sv*)limp->olv_tasks; + if(!limp->soc->Create(TASKS_PORT, + SOCK_STREAM,FD_ACCEPT | FD_READ | FD_CLOSE, + limp->olv->olv_sock->ip)) + { + goto mal; + } + if(!limp->soc->Listen()) + goto mal; + return; +mal: + limp->soc->Close(); + delete limp->soc; + limp->soc=NULL;*/ +} +//************************************************************************************* +//************************************************************************************* +/** + * Funcion llamada por el mainframe para delete el socket multitask + */ +void COlivia::destruye_socket_multi( LPARAM lp ) +{ + /* + Colv_limp *olv_limp = (Colv_limp*)lp; + olv_limp->soc->Close(); + delete olv_limp->soc; + olv_limp->soc=NULL;*/ + +} +//************************************************************************************* +void COlivia::log_ext( __time64_t tiemp, char *modulo, char *fmt ) +{ + if(mfrm) + mfrm->log_ext( tiemp, modulo, fmt ); + /* + class CMsgdocOlv : public CObject + { + public: + // Construction.... + CMsgdocOlv(){}; + ~CMsgdocOlv(){}; + + // Attributes.... + CString m_modulo; + CString m_texto; + int m_nivel; + CTime m_time; + + // access routines.... + + }; + CMsgdocOlv* msg = new CMsgdocOlv(); + msg->m_nivel = 1; + msg->m_modulo = modulo; + msg->m_texto = fmt; + //msg->smsg(nivel, modulo,buf); + //SendMessage(mfrm,(WM_USER+1), 0, (LPARAM) msg );*/ +} +//************************************************************************************* +//************************************************************************************* +/** + * Función global para log + */ +void olvlog (int nivel, char * modulo, char *fmt, ...) +{ + char buf[1024]; + int k; + va_list arg_ptr; + + va_start(arg_ptr, fmt); + k = _vsnprintf(buf,1000, fmt, arg_ptr); + va_end(arg_ptr); + if (k<0) + strcpy(&buf[200],"HAY MAS"); + C_log::log(modulo,buf); +} +#endif \ No newline at end of file diff --git a/Olivia/olv.h b/Olivia/olv.h new file mode 100644 index 0000000..842cbd3 --- /dev/null +++ b/Olivia/olv.h @@ -0,0 +1,138 @@ +#pragma once + +/** +* @file olv.h +* Archivo de definiciones generales de la herramienta Olivia de OliviaTasks. +*/ + +/** +* Includes para archivo de definiciones OliviaDef.cs +*/ +#ifdef OLIVIA_COMPILA +#define class namespace +#define public +#define static +#define string CString +#include "OliviaDef.cs" +#undef class +#undef public +#undef static +#undef string +#include "olv_tasks_def.h" +#include "_log.h" +#include "_app.h" +#include "olv_limp_def.h" + +/** + * Tareas de ejecución para la ventana de progreso + */ +enum TareasProgr +{ + OLV_TAREA_CALC, ///0) + { + + nv--; + Sleep(1); + aux = new Djkt_elem_cola(); + } + if(!aux) + return FALSE; + nn++; + aux->id = i; + aux->id_inci=i_inci; + aux->sig = NULL; + while (true) + { + if (!aux1) + { + elem = aux; + break; + } + if (nodos[aux1->id].dis >= nodos[aux->id].dis) + { + aux->sig = aux1; + if(aux2) + aux2->sig=aux; + if (aux1 == elem) + elem = aux; + break; + } + if (!aux1->sig) + { + aux1->sig = aux; + break; + } + aux2=aux1; + aux1 = aux1->sig; + } + return TRUE; +}; +//************************************************************************************* +/** + * Función para la estructura del algoritmo Dijkstra, para obtener de la cola + */ +int Djkt_cola::dame() +{ + return dame(NULL); +}; +//************************************************************************************* +/** + * Función para la estructura del algoritmo Dijkstra, para obtener de la cola + */ +int Djkt_cola::dame(int *id_inci) +{ + if (!elem) + return -1; + if(nn<=0) + { + elem=NULL; + return -1; + } + nn--; + Djkt_elem_cola *aux = elem; + int res = aux->id; + elem = elem->sig; + if(id_inci) + *id_inci=aux->id_inci; + delete(aux); + return res; +}; +//************************************************************************************* +/** + * Función constructor para la estructura de nodos adyacentes para los ángulos + */ +Djkt_ang_ady::Djkt_ang_ady() +{ + nady=0; + i_conjs=0; + angs=0; + ids_padre=NULL; +} +//************************************************************************************* +/** + * Función destructor para la estructura de nodos adyacentes para los ángulos + */ +void Djkt_ang_ady::libera() +{ + if(i_conjs) + free(i_conjs); + i_conjs=NULL; + if(angs) + { + for(int i=0;i16) + { + nady=nady; + } + //malloc + i_conjs=(int*)malloc(nady*sizeof(int)); + if(!i_conjs) + return FALSE; + for(i=0;iii) && (i_conjs[jj]==-1)) || (i_conjs[jj]==j)) + break; + } + if(ii>=nady || jj>=nady) + return FALSE; + + *ii_=ii; + if(jj_) + *jj_=jj; + + return TRUE; +} +//************************************************************************************* +/** + * Para la estructura de nodos adyacentes para los ángulos, + * pone el ángulo de la conj, entre las adyacentes i y j + */ +BOOL Djkt_ang_ady::pon_ang_i_j(int i,int j, BYTE ang) +{ + int ii,jj; + + if(!dame_ii_jj(i,j,&ii,&jj)) + return FALSE; + + i_conjs[ii]=i; + i_conjs[jj]=j; + angs[ii][jj]=ang; + + return TRUE; +}; +//************************************************************************************* +/** + * Para la estructura de nodos adyacentes para los ángulos, + * devuelve el ángulo de la conj, entre las adyacentes i y j + */ +BOOL Djkt_ang_ady::dame_ang_i_j(int i,int j, BYTE *ang, BOOL inds_abs) +{ + int ii,jj; + + if(inds_abs) + { + if(!dame_ii_jj(i,j,&ii,&jj)) + return FALSE; + } + else + { + ii=i; + jj=j; + } + + *ang=angs[ii][jj]; + return TRUE; +} +//************************************************************************************* +/** + * Para la estructura de nodos adyacentes para los ángulos, + * pone que para llegar al nodo actual desde i_orig, el padre es j_padre + */ +BOOL Djkt_ang_ady::pon_padre(int i_orig,int j_padre, double dis, BOOL inds_abs) +{ + int ii,jj; + + if(inds_abs) + { + if(!dame_ii_jj(i_orig,j_padre,&ii,&jj)) + return FALSE; + } + else + { + ii=i_orig; + jj=j_padre; + } + + ids_padre[ii].id=jj; + ids_padre[ii].dis=(float)dis; + + return TRUE; +}; +//************************************************************************************* +/** + * Para la estructura de nodos adyacentes para los ángulos, + * devuelve que el padre es j_padre para ir al nodo actual desde i_orig + */ +BOOL Djkt_ang_ady::dame_padre(int i_orig,int *j_padre, double *dis, BOOL inds_abs) +{ + int ii,jj; + + if(inds_abs) + { + if(!dame_ii_jj(i_orig,-1,&ii,&jj)) + return FALSE; + } + else + { + ii=i_orig; + jj=-1; + } + + *j_padre = i_conjs[ids_padre[ii].id]; + *dis = ids_padre[ii].dis; + + return TRUE; +}; +//************************************************************************************* +/* + * Guarda a disco + */ +BOOL Djkt_ang_ady::guarda(HeadCostAng hd, int ic, char *path , char *ext) +{ + HANDLE hfile = INVALID_HANDLE_VALUE; + int nb, i; + char file[MAX_PATH]; + + sprintf_s(file,MAX_PATH,"%s%06d.%s",path,ic,ext); + + //crea archivo----------------------------------- + hfile = CreateFile(file, GENERIC_WRITE | GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); + if (hfile == INVALID_HANDLE_VALUE) + { + i=GetLastError(); + return FALSE; + } + + //graba cabecera------------ + nb = sizeof(hd); + //calcula el nb + hd.n=nady; //* BYTE + if (nb != _lwrite((int)hfile, (LPCCH)&hd, nb)) + { + goto va_mal; + } + + //guarda la matriz de conjs ady + nb=sizeof(int)*nady; + if (nb != _lwrite((int)hfile, (LPCCH) i_conjs, nb)) + { + goto va_mal; + } + //guarda la matriz de ángulos + nb=nady; + for(i=0;i0; + } + HANDLE hfile = INVALID_HANDLE_VALUE; + int nb; + char p[MAX_PATH]; + sprintf_s(p,MAX_PATH, "%s_%ld.%s",path, 0,EXT_ARCH_DIJ_DEFAULT); + hfile = CreateFile(p, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); + if (hfile == INVALID_HANDLE_VALUE) + return FALSE; + nb = sizeof(hd); + if (nb != _lread((int)hfile,&hd, nb)) + { + goto va_mal; + } + if(hfile != INVALID_HANDLE_VALUE) + CloseHandle(hfile); + sizn=sizeof(Djkt_nodo)+hd.max_conex*(sizeof(Djkt_ids_pdr)+sizeof(int)+sizeof(BYTE)*hd.max_conex); + return (hd.version== VERSION_DJ_ARCHI && hd.max_conex>0 && hd.nn>0 && sizn>0); + +va_mal: + if(hfile != INVALID_HANDLE_VALUE) + CloseHandle(hfile); + return FALSE; + + +} +//************************************************************************************* +BOOL Cdijkstra_arch::add_b( Djkt_nodo* blq, int iref, int inod, BOOL pon_inf ) +{ + HANDLE hfile = INVALID_HANDLE_VALUE; + int nb, i, nbt, j; + char p[MAX_PATH]; + sprintf_s(p,MAX_PATH,"%s_%ld.%s",path,iref,EXT_ARCH_DIJ_DEFAULT); + Head_dj_arch hdl; + //abre archivo----------------------------------- + hfile = CreateFile(p, GENERIC_WRITE | GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); + if (hfile == INVALID_HANDLE_VALUE) + { + hfile = CreateFile(p, GENERIC_WRITE | GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); + + + if (hfile == INVALID_HANDLE_VALUE) + { + olvlog(LOG_TODO,"Cdijkstra_arch::add_b","Error no se puede abrir archivo: %s", p); + + i=GetLastError(); + return FALSE; + } + //graba cabecera------------ + hdl=hd; + hdl.nb=0; + nb = sizeof(hdl); + if (nb != _lwrite((int)hfile, (LPCCH)&hdl, nb)) + { + olvlog(LOG_TODO,"Cdijkstra_arch::add_b","Error no se puede grabar cabecera de archivo: %s", p); + goto va_mal; + } + } + else + { + //lee cabecera------------- + nb = sizeof(hdl); + if (nb != _lread((int)hfile, &hdl, nb)) + { + olvlog(LOG_TODO,"Cdijkstra_arch::add_b","Error no se puede leer cabecera de archivo: %s", p); + + goto va_mal; + } + } + //va a lo ultimo--------------------------------- + if ( SetFilePointer(hfile, 0, NULL, FILE_END) == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) + { + olvlog(LOG_TODO,"Cdijkstra_arch::add_b","Error no se puede ir al final del archivo: %s", p); + + goto va_mal; + } + //guarda bloque--------------------------------- + for (i=0; i0) + { + if ( SetFilePointer(hfile, nb, NULL, FILE_CURRENT) == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) + { + olvlog(LOG_TODO,"Cdijkstra_arch::get_b","Error al ir al siguiente nodo, en nodo %ld archivo: %s", i, p); + + goto va_mal; + } + } + } + if(hfile != INVALID_HANDLE_VALUE) + CloseHandle(hfile); + return buf_res; +va_mal: + if(hfile != INVALID_HANDLE_VALUE) + CloseHandle(hfile); + if(buf_res && !buf) + { + for (i=0; i *ina, int namb, int tip_amb, int idinstal/*=-1*/, int idplan/*=-1*/ ) +{ + float *buf; + int i; + ia=ina; + nnod=namb; + nod_amb=tip_amb; + nnod=nnod*nod_amb; + nambi=namb; + nod_instal=idinstal; + nod_plan=idplan; + + if(idplan>=0) + { + nnod++; + id_plan=namb++; + + } + if(idinstal>=0) + { + nnod++; + id_instal=namb; + } + + //pide memoria + buf=(float*)realloc(dis,nnod*nnod*sizeof(float) ); + if(!buf) + { + ia=NULL; + return FALSE;//sin memoria + } + dis=buf; + for(i=nnod*nnod-1; i>=0; i--) + { + dis[i]=(float)MAYUSCULO; + } + return TRUE; + +} +//************************************************************************************* +void Cdijkstra_arch::pon_info_amb( Djkt_nodo* nodos, int iref,int ib ) +{ + int i, j, k; + if(!ia) + return; + //calcula fila--- + j=(iref*nod_amb+ib)*nnod; + + for (i=0; i=0) + { + dis[j+nambi*nod_amb+id_instal-nambi]=nodos[nod_instal].dis; + if(nodos[nod_instal].dis<0) + nodos[nod_instal].dis=nodos[nod_instal].dis; + } + if(nod_plan>=0) + { + dis[j+nambi*nod_amb+id_plan-nambi]=nodos[nod_plan].dis; + if(nodos[nod_plan].dis<0) + nodos[nod_plan].dis=nodos[nod_plan].dis; + } +} +//************************************************************************************* +float Cdijkstra_arch::dame_dis( int aorig,int norig, int ades, int n_des ) +{ + int i=aorig-nambi; + if(nod_amb<=norig) + norig=0; + if(nod_amb<=n_des) + n_des=0; + if(i<0) + i=0; + aorig-=i; + return dis[(ades*nod_amb+n_des)*nnod + aorig*nod_amb+norig+i]; +} + +BOOL Cdijkstra_arch::graba_dis(int id) +{ + Cgarray buf; + char p[MAX_PATH]; + sprintf(p,"%s_%ld.%s", path, id,TASKS_EXT_DIS); + Cb_file f; + if(!f.abre(p,2,TRUE)) + return FALSE; + buf.ptr=dis; + buf.n =nnod*nnod; + BOOL res =buf.graba(&f); + buf.ptr=NULL; + buf.n =0; + return res; + +} +//************************************************************************************* +BOOL Cdijkstra_arch::lee_dis() +{ + Cb_file f; + StrArray files; + char sext[MAX_PATH]; + strcpy(sext, path); + Cgarray buf; + //pilla archivos----------------------- + if(!Cdir_manager::listar(Cdir_manager::dir_anterior(sext), &files)) + return FALSE; + char *file; + for (int i = 0; i 1) + res = 1; + if (res < -1) + res = -1; + return acos(res); +} +//************************************************************************************* +/** + * Devuelve true si los puntos son iguales, false si no + */ +BOOL Colv_geom::pto_equals(double pt1[3], double pt2[3], BOOL d3 /*=false*/) +{ + BOOL c3; + if(d3) + c3=(fabs(pt1[2]-pt2[2])0 o a la izquierda si d<0 + */ +BOOL Colv_geom::haz_paralela(double (*ptos_orig)[3],int _np,double dis,double (**ptos_par)[3]) +{ + if(dis==0) + { + ptos_par=&ptos_orig; + return TRUE; + } + + double (*v_unitario)[][3]; + double (*ptos_salida)[][3]; + double (*ptos)[][3]; + int np,i; + double c,s,l,a1,a2,b1,b2,c1,c2,det,x,y; + + np=_np; + + ptos_salida=(double (*)[][3])malloc(sizeof(double)*3*np); + if(!ptos_salida) + return FALSE; + memset(ptos_salida,0,sizeof(double)*3*np); + + ptos=(double (*)[][3])malloc(sizeof(double)*3*np); + if(!ptos) + return FALSE; + memcpy(ptos,ptos_orig,sizeof(double)*3*np); + + v_unitario=(double (*)[][3])malloc(sizeof(double)*3*(np-1)); + if(!v_unitario) + return FALSE; + + //d distancia, positivo -> paralela a la izquierda , negativo a la derecha + //el array (*v_unitario) tiene los vectores unitarios de cada direccion + + for (i=0;i<=(np-2);i++) + { + c= (*ptos)[i+1][0]-(*ptos)[i][0] ; + s = (*ptos)[i+1][1]-(*ptos)[i][1]; + l = sqrt(c*c+s*s); + if(l==0) + l=1; + (*v_unitario)[i][0]= c/l; + (*v_unitario)[i][1]=s/l; + } + + // calculamos la normal para el primer punto + (*ptos_salida)[0][0]=(*ptos)[0][0]-dis*(*v_unitario)[0][1]; + (*ptos_salida)[0][1]=(*ptos)[0][1]+dis*(*v_unitario)[0][0]; + + // desde 1 hasta np-1 calculamos la interseccion de las lineas + for (i=1;i<=(np-2);i++) + { + l = dis/(1+(*v_unitario)[i][0]*(*v_unitario)[i-1][0] + +(*v_unitario)[i][1]*(*v_unitario)[i-1][1]) ; + (*ptos_salida)[i][0]=(*ptos)[i][0] + - l*((*v_unitario)[i][1]+(*v_unitario)[i-1][1]); + (*ptos_salida)[i][1]=(*ptos)[i][1] + + l*((*v_unitario)[i][0]+(*v_unitario)[i-1][0] ); + + } + + // usamos la normal para el ultimo punto + (*ptos_salida)[np-1][0]= (*ptos)[np-1][0]- dis*(*v_unitario)[np-2][1]; + (*ptos_salida)[np-1][1]= (*ptos)[np-1][1] + dis*(*v_unitario)[np-2][0]; + + //si el ultimo punto tiene las mismas coordenadas que el primero es un superficial + //en los superficiales se une el primero con el último + if ((*ptos)[np-1][0]==(*ptos)[0][0] &&(*ptos)[np-1][1]==(*ptos)[0][1]) + { + // el punto inicial y final se intersectan. Solucion ideal para superficiales + a1 = (*ptos_salida)[np-1][1]-(*ptos_salida)[np-2][1]; + b1 = (*ptos_salida)[np-2][0]-(*ptos_salida)[np-1][0]; + c1 = a1*(*ptos_salida)[np-2][0]+b1*(*ptos_salida)[np-2][1]; + a2 = (*ptos_salida)[0][1]-(*ptos_salida)[1][1]; + b2 = (*ptos_salida)[1][0]-(*ptos_salida)[0][0]; + c2 = a2*(*ptos_salida)[1][0]+b2*(*ptos_salida)[1][1]; + + det = a1*b2 - a2*b1; + x = (b2*c1 - b1*c2)/det; + y = (a1*c2 - a2*c1)/det; + (*ptos_salida)[np-1][0]=x; + (*ptos_salida)[np-1][1]=y; + (*ptos_salida)[0][0]=x; + (*ptos_salida)[0][1]=y; + } + + free(v_unitario); + free(ptos); + + ///Fin de los arcos intermedios + *ptos_par=(double(*)[3]) ptos_salida; + return TRUE; +} +//************************************************************************************* +/** + * Algoritmo Dijkstra de cálculo de camino de menor coste para ir de los 'n' nodos de una red al nodo 'fin'. + * 'nodos' es el array de tamaño n que contiene la información de costes, es de salida + * 'costes' es la matriz de nxn que contiene los costes de ir de todos a todos los nodos +*/ +BOOL Colv_geom::dijkstra_ang_inv_ok(CmapMatFloat &costes, Djkt_ang_ady *angs, int n, int fin, Djkt_nodo **nodos, BYTE **visto_ang_) +{ + int i, sig,sigr; + Djkt_cola q; + BOOL res=FALSE; + Djkt_nodo *distancias; + double d; + BOOL ang_ok; + //BYTE ang; + int id_inci; + BYTE *visto_ang=NULL; + int ii,jj; + + q.inicia(NULL); + distancias = *nodos; + if(!distancias) + distancias = (Djkt_nodo*)malloc(sizeof(Djkt_nodo)*n); + if (!distancias) + goto va_mal; + if(visto_ang_) + visto_ang=*visto_ang_; + if(!visto_ang) + visto_ang = (BYTE*)malloc(n*n*sizeof(BYTE)); + if(!visto_ang) + goto va_mal; + memset(visto_ang,0,n*n*sizeof(BYTE)); + + + if(angs) + { + ang_ok=TRUE; + for (i=0; i= MAYUSCULO) + continue; + if (visto_ang[sig*n+i])//si visto se pasa de el + continue; + if(angs) + { + if(!angs[sig].dame_ii_jj(i,-1,&ii,NULL)) + continue; + + if(distancias[sig].ids_ady.ids_padre[ii].id!=-1) + { + if(!angs[sig].dame_ii_jj(distancias[sig].ids_ady.ids_padre[ii].id,-1,&jj,NULL)) + continue; + + if(!angs[sig].angs[ii][jj]) + continue; + + } + d=distancias[sig].ids_ady.ids_padre[ii].dis + costes[i][sig]; + + if (distancias[i].dis > d)//se actualiza distancia si procede + { + if(d<0) + d=d; + distancias[i].dis = (float)d; + distancias[i].id_padre = sig; + visto_ang[sig*n+i]=0; + if (!q.pon(i,sig)) + goto va_mal; + } + + if(!angs[i].dame_ii_jj(sig,-1,&sigr,NULL)) + continue; + + for(jj=0;jj1)) + continue; + if(!angs[i].angs[jj][sigr]) + continue; + + if (distancias[i].ids_ady.ids_padre[jj].dis > d)//se actualiza distancia si procede + { + distancias[i].ids_ady.ids_padre[jj].dis = (float)d; + distancias[i].ids_ady.ids_padre[jj].id = sig; + visto_ang[sig*n+i]=0; + if (!q.pon(i,sig)) + goto va_mal; + } + } + } + else + { + //encontrado adyacente se hace la relajacion---------------- + d = distancias[sig].dis + costes[i][sig]; + if (distancias[i].dis > d)//se actualiza distancia si procede + { + distancias[i].dis = (float)d; + distancias[i].id_padre = sig; + if (!q.pon(i,sig)) + goto va_mal; + } + } + + + } + } + res = TRUE; + + if (nodos) + { + *nodos = distancias; + distancias = NULL; + } + +va_mal: + if (distancias) + free(distancias); + if(visto_ang_) + { + *visto_ang_=visto_ang; + visto_ang=NULL; + } + if (visto_ang) + free(visto_ang); + while (q.dame() >= 0); + + return res; +} +//************************************************************************************* +/* + * Da la ruta hasta el nodo final con el que se hizo dijkstra desde 'id_ini' + * Hay que haber llamado antes a dijkstra, y el array 'nodos' de salida es el que aquí + * es entrada, de tamaño 1xn. + * En 'secu' devuelve un array de la secuencia a seguir desde el nodo 'id_ini' hasta el nodo final + * Es de tamaño el número de nodos de la red, pero sólo están ocupados los 'n' primeros con la secuencia. + */ +double Colv_geom::ruta_dj_inv(int id_ini, int *secu, Djkt_nodo *nodos, int nmax, int *n) +{ + int padre= id_ini; + int nn = 0; + while (padre>=0 && nn=0 && nniold) + { + if(i1) + res*=i--; + + return res; +} +#endif +//************************************************************************************* \ No newline at end of file diff --git a/Olivia/olv_geom.h b/Olivia/olv_geom.h new file mode 100644 index 0000000..a9e518c --- /dev/null +++ b/Olivia/olv_geom.h @@ -0,0 +1,181 @@ +#pragma once +#ifdef OLIVIA_COMPILA +#include +#include +#include "mapmatrix.h" +#include + +#ifndef EXT_ARCH_DIJ_DEFAULT +#define EXT_ARCH_DIJ_DEFAULT "ndj" +#define NOMB_ARCH_DIJ_DEF "snodos_dj" +#endif + +/** +* @file olv_geom.h +* Archivo de declaraciones de clase de varias utilidades geométricas del programa Olivia. +*/ +#define OLV_PI 4.0*atan(1.0) +//************************************************************************************************************************** +/** + * Estructura de nodo para el cálculo de caminos óptimos por Dijkstra + */ +struct Djkt_nodo_0 +{ + int id_padre; //modo escritura 0x2-->modo lectura + //info de distancias ambitos + float *dis;//distancia de un nodo a otro (matriz de nnod*nnod) + int nod_amb;//nodos por ambito + int nambi;//numero de ambitos + int nnod;//numero de nodos por fila + int id_instal;//fila planta + int id_plan;//fila instal + int nod_instal;//nodo instalacion + int nod_plan;//nodo planta + int tip_ambitos; + + std::map *ia;//puntero a info asoc + + //funciones-------------------------------------------------------------------------- + Cdijkstra_arch(); + ~Cdijkstra_arch(); + + BOOL inicia(char* path_arch, BOOL nuevo=FALSE, int n_nod=0, int max_conex=MAX_CONEX_DJ_ARCHI);//si nuevo -> crea vacio + BOOL add_b(Djkt_nodo* blq, int iref, int inod, BOOL pon_inf=FALSE);//añade un bloque a el archivo + BOOL inicia_inf_amb(std::map* ina, int namb,int tip_amb, int id_instal=-1, int id_plan=-1); + void pon_info_amb(Djkt_nodo* nodos, int iref,int ib); + Djkt_nodo* get_b(int iref, int ibloq, Djkt_nodo* buf=NULL);//develve el bloque ibloq-esimo + float dame_dis(int aorig,int norig, int ades, int n_des); + + Djkt_nodo* dame_buf_nodos(BOOL angulos=FALSE ); + void libera_buf(Djkt_nodo* buf ); + BOOL lee_dis(); + BOOL graba_dis(int id); +}; +#endif + + + diff --git a/Olivia/olv_limp.cpp b/Olivia/olv_limp.cpp new file mode 100644 index 0000000..1dda447 --- /dev/null +++ b/Olivia/olv_limp.cpp @@ -0,0 +1,847 @@ +#include "stdafx.h" +#ifdef OLIVIA_COMPILA +#include "olv_limp.h" +#include "olv.h" +#include "olv_limp_thr.h" +#include "olv_geom.h" +#include "math.h" +#include "ini_file.h" +#include "olv_tasks.h" +#include "sock_sv.h" + +/** +* @file olv_limp.cpp +* Archivo de implementaciones de la utilidad de limpieza viaria del programa Olivia. +*/ +//******************************************************************************************************************************************* +Colv_limp::Colv_limp(COlivia *olv) +{ + nod_plant=-1; + this->olv = olv; + res_circ=OLV_RES_NO; + npts_ctrl = 3; + uds_tto = OliviaDef::GeneralDef::OlvTipTtoNoDef; + v_despl = 5; + t_tto = 5*60; + t_carg = 60*30; + t_conv = 3600*8; + t_desc = 60*40; + t_despl = 60*25/2; + t_sal=0; + nsec=4; + ancho_via = 2; //m + memset(coor_instal,0,3*sizeof(double)); + thr_limp = new Colv_limp_thr(this); + //cost_amb=NULL; + n_nw=n_amb=0; + pp=-1; + tipo_ambit=-1; + inww_amb=NULL; + memset(&conjs,0,sizeof(Info_conjs)); + cost_conj.clear(); + sec=NULL; + amb_sec=NULL; + rellena_campos(); + margen_sect=0.04; + plan=NULL; + calc_nsec=0; + ang_conj=NULL; + tip_conj.clear(); + ang_lim=OLV_LIMP_GIRO_VEHIC*OLV_PI/180; + ord_sec=NULL; + nod_instal=-1; + ord_sec_plan=NULL; + t_ini=7*3600; //7 de la mañana + igno_ais=FALSE; + lateral=0; + nsec_act=0; + olv_tasks = new Colv_tasks(olv); + soc=NULL; + tipo_shp_viaj=OLV_SHPRUTINST;//OLV_SHPRUT_SHPINST + nomb_tto[0]=0; + barr_mix=FALSE; +} +//******************************************************************************************************************************************* +Colv_limp::~Colv_limp(void) +{ + int i; + + cancela(); + delete(thr_limp); + + if(inww_amb) + { + for(i=0;iclose(); + delete soc; + soc=NULL; + } + + for (std::map::iterator it=iaso.begin(); it!=iaso.end(); ++it) + { + it->second.del(); + } + + libera_memo_secto(); +} +//************************************************************************************* +/** + * Libera la memoria de las matrices de sectorización + */ +void Colv_limp::libera_memo_secto() +{ + if(sec) + { + for(int i=0;iinicia_th(); + //empieza importando + thr_limp->encola(thr_limp->OLV_LIMP_EV_ABRE_DAT,NULL,FALSE); + + return TRUE; +} +//************************************************************************************* +/** + * Pone las opciones de configuración de lo que recibe por el socket + */ +int Colv_limp::pon_config(char *config_) +{ + int j; + char *token; + const int SZCONF = 8192; + char config[SZCONF]; + + if(!config) + return 0; + + memset(config,0,SZCONF); + strcpy_s(config,SZCONF,config_); + + //los parámetros son: + token = strtok(config, OliviaDef::GeneralDef::EjecGeoParamSep); + //avanza al siguiente token, el primero indica "\CONFIGURACION" + token = strtok(NULL, OliviaDef::GeneralDef::EjecGeoParamSep); + + //Lee parámetros + j=0; + while (token != NULL) + { + if(strstr(token,OliviaDef::GeneralDef::GL_tto)) + { + if(!olv->dame_param(token, &t_tto)) + break; + if(t_tto==0) + break; + } + else if(strstr(token,OliviaDef::GeneralDef::GL_res)) + { + if(!olv->dame_param(token, &res_circ)) + break; + } + else if(strstr(token,OliviaDef::GeneralDef::GL_uto)) + { + if(!olv->dame_param(token, &uds_tto)) + break; + if(uds_tto==OliviaDef::GeneralDef::OlvTipTtoMin) + { + tipo_ambit=OLV_AMB_PUN; + t_tto=t_tto*60;//porque viene en minutos + } + else if(uds_tto>OliviaDef::GeneralDef::OlvTipTtoMin) + tipo_ambit=OLV_AMB_LIN; + else + break; + } + else if(strstr(token,OliviaDef::GeneralDef::GL_vdp)) + { + if(!olv->dame_param(token, &v_despl)) + break; + if(v_despl<0) + break; + v_despl=v_despl*OLV_KMH2MS; + } + else if(strstr(token,OliviaDef::GeneralDef::GL_tdp)) + { + if(!olv->dame_param(token, &t_despl)) + break; + t_despl=t_despl*60/2;//porque viene en minutos + } + else if(strstr(token,OliviaDef::GeneralDef::GL_tca)) + { + if(!olv->dame_param(token, &t_carg)) + break; + t_carg=t_carg*60;//porque viene en minutos + } + else if(strstr(token,OliviaDef::GeneralDef::GL_anc)) + { + if(!olv->dame_param(token, &ancho_via)) + break; + if(ancho_via<0) + break; + } + else if(strstr(token,OliviaDef::GeneralDef::GG_tco)) + { + if(!olv->dame_param(token, &t_conv)) + break; + t_conv=t_conv*60;//porque viene en minutos + } + else if(strstr(token,OliviaDef::GeneralDef::GG_tdc)) + { + if(!olv->dame_param(token, &t_desc)) + break; + t_desc=t_desc*60;//porque viene en minutos + } + else if(strstr(token,OliviaDef::GeneralDef::GG_npt)) + { + if(!olv->dame_param(token, &npts_ctrl)) + break; + } + else if(strstr(token,OliviaDef::GeneralDef::GG_sec)) + { + if(!olv->dame_param(token, &nsec)) + break; + } + else if(strstr(token,OliviaDef::GeneralDef::GG_coox)) + { + if(!olv->dame_param(token, &coor_instal[0])) + break; + } + else if(strstr(token,OliviaDef::GeneralDef::GG_cooy)) + { + if(!olv->dame_param(token, &coor_instal[1])) + break; + } + else if(strstr(token,OliviaDef::GeneralDef::GG_hini)) + { + if(!olv->dame_param(token, &t_ini)) + break; + t_ini=t_ini*60;//porque viene en minutos + } + else if(strstr(token,OliviaDef::GeneralDef::GG_trafic)) + { + if(!olv->dame_param(token, &f_trafic)) + break; + f_trafic=f_trafic/100; + } + else if(strstr(token,OliviaDef::GeneralDef::GG_ais)) + { + if(!olv->dame_param(token, (int*)&igno_ais)) + break; + } + //el nombre del tto + else if(strstr(token,OliviaDef::GeneralDef::GG_strtto)) + { + if(!olv->dame_param(token, nomb_tto, sizeof(nomb_tto))) + break; + } + else if(strstr(token,OliviaDef::GeneralDef::GG_pd)) + { + if(!olv->dame_param(token, olv->paths.path_data, sizeof(olv->paths.path_data))) + break; + } + else if(strstr(token,OliviaDef::GeneralDef::GG_pn)) + { + if(!olv->dame_param(token, olv->paths.path_nw, sizeof(olv->paths.path_nw))) + break; + } + //los campos a leer de la dbf + else if(strstr(token,OliviaDef::GeneralDef::GAA_obser)) + { + if(!olv->dame_param(token, camps.campo_obs, sizeof(camps.campo_obs))) + break; + if(strlen(camps.campo_obs)>OLV_MAX_COL_SHP)//10 porque el shp solo pasa con 10 caracteres en los nombres de columna + camps.campo_obs[OLV_MAX_COL_SHP]=0; + } + else if(strstr(token,OliviaDef::GeneralDef::GAA_anch_tip)) + { + if(!olv->dame_param(token, camps.campo_anch, sizeof(camps.campo_anch))) + break; + if(strlen(camps.campo_anch)>OLV_MAX_COL_SHP)//10 porque el shp solo pasa con 10 caracteres en los nombres de columna + camps.campo_anch[OLV_MAX_COL_SHP]=0; + } + else if(strstr(token,OliviaDef::GeneralDef::GAA_tipolo)) + { + if(!olv->dame_param(token, camps.campo_tipo_ap, sizeof(camps.campo_tipo_ap))) + break; + if(strlen(camps.campo_tipo_ap)>OLV_MAX_COL_SHP)//10 porque el shp solo pasa con 10 caracteres en los nombres de columna + camps.campo_tipo_ap[OLV_MAX_COL_SHP]=0; + } + else if(strstr(token,OliviaDef::GeneralDef::GAA_entid)) + { + if(!olv->dame_param(token, camps.campo_tipo_ent, sizeof(camps.campo_tipo_ent))) + break; + if(strlen(camps.campo_tipo_ent)>OLV_MAX_COL_SHP)//10 porque el shp solo pasa con 10 caracteres en los nombres de columna + camps.campo_tipo_ent[OLV_MAX_COL_SHP]=0; + } + else if(strstr(token,OliviaDef::GeneralDef::GAL_aparc)) + { + if(!olv->dame_param(token, camps.atr_tip_ent[OLV_ATR_NOM_TIP_ENT_AP], sizeof(camps.atr_tip_ent[OLV_ATR_NOM_TIP_ENT_AP]))) + break; + } + else if(strstr(token,OliviaDef::GeneralDef::GAL_bord)) + { + if(!olv->dame_param(token, camps.atr_tip_ent[OLV_ATR_NOM_TIP_ENT_BORD], sizeof(camps.atr_tip_ent[OLV_ATR_NOM_TIP_ENT_BORD]))) + break; + } + else if(strstr(token,OliviaDef::GeneralDef::GAL_acera)) + { + if(!olv->dame_param(token, camps.atr_tip_ent[OLV_ATR_NOM_TIP_ENT_ACERA], sizeof(camps.atr_tip_ent[OLV_ATR_NOM_TIP_ENT_ACERA]))) + break; + } + else if(strstr(token,OliviaDef::GeneralDef::GAL_peat)) + { + if(!olv->dame_param(token, camps.atr_tip_ent[OLV_ATR_NOM_TIP_ENT_PEAT], sizeof(camps.atr_tip_ent[OLV_ATR_NOM_TIP_ENT_PEAT]))) + break; + } + else if(strstr(token,OliviaDef::GeneralDef::GAL_ap_lin)) + { + if(!olv->dame_param(token, camps.atr_tip_apa[OLV_ATR_TIP_AP_LIN], sizeof(camps.atr_tip_apa[OLV_ATR_TIP_AP_LIN]))) + break; + } + else if(strstr(token,OliviaDef::GeneralDef::GAL_ap_bat)) + { + if(!olv->dame_param(token, camps.atr_tip_apa[OLV_ATR_TIP_AP_BAT], sizeof(camps.atr_tip_apa[OLV_ATR_TIP_AP_BAT]))) + break; + } + //los campos a leer de la dbf de la red navegable + else if(strstr(token,OliviaDef::GeneralDef::GTC_onew)) + { + if(!olv->dame_param(token, camps.campo_circ, sizeof(camps.campo_circ))) + break; + } + else if(strstr(token,OliviaDef::GeneralDef::GTC_kph)) + { + if(!olv->dame_param(token, camps.campo_velo, sizeof(camps.campo_velo))) + break; + } + else if(strstr(token,OliviaDef::GeneralDef::GTC_fow)) + { + if(!olv->dame_param(token, camps.campo_fow, sizeof(camps.campo_fow))) + break; + } + else if(strstr(token,OliviaDef::GeneralDef::GTC_name)) + { + if(!olv->dame_param(token, camps.campo_name, sizeof(camps.campo_name))) + break; + } + else if(strstr(token,OliviaDef::GeneralDef::GTA_TF)) + { + if(!olv->dame_param(token, camps.atr_circ[OLV_ATR_CIRC_TF], sizeof(camps.atr_circ[OLV_ATR_CIRC_TF]))) + break; + } + else if(strstr(token,OliviaDef::GeneralDef::GTA_FT)) + { + if(!olv->dame_param(token, camps.atr_circ[OLV_ATR_CIRC_FT], sizeof(camps.atr_circ[OLV_ATR_CIRC_FT]))) + break; + } + else if(strstr(token,OliviaDef::GeneralDef::GTA_N)) + { + if(!olv->dame_param(token, camps.atr_circ[OLV_ATR_CIRC_NONE], sizeof(camps.atr_circ[OLV_ATR_CIRC_NONE]))) + break; + } + else if(strstr(token,OliviaDef::GeneralDef::GTA_pedes)) + { + if(!olv->dame_param(token, camps.atr_circ[OLV_ATR_CIRC_PEDES], sizeof(camps.atr_circ[OLV_ATR_CIRC_PEDES]))) + break; + } + else + { + token = strtok(NULL, OliviaDef::GeneralDef::EjecGeoParamSep); + continue; + } + token = strtok(NULL, OliviaDef::GeneralDef::EjecGeoParamSep); + j++; + } + + strcpy_s(olv->paths.path_res_rut,MAX_PATH,olv->paths.path_data); + strcpy_s(olv->paths.path_res_pt,MAX_PATH,olv->paths.path_data); + + return j; +} +//************************************************************************************* +/** + * Termina las tareas + */ +void Colv_limp::cancela() +{ + thr_limp->termina_th(); +} +//************************************************************************************* +/** + * Lee el ini y rellena los campos que lee, o bien por defecto + */ +BOOL Colv_limp::rellena_campos_ini(char *path) +{ + Cini_file ini; + int ig; + CString param; + + if(!ini.lee(path)) + return FALSE; + + param=OliviaDef::GeneralDef::GrupoCampoLimp; + ig=ini.get_grupo(param.GetBuffer(param.GetLength())); + if(ig>=0) + { + //leer campos del ini + param=OliviaDef::GeneralDef::GAA_obser; + strcpy_s(camps.campo_obs,OLV_LIMP_MAX_CAMP,ini.get(ig,param.GetBuffer(param.GetLength()),camps.campo_obs)); + camps.campo_obs[10]=0; + + param=OliviaDef::GeneralDef::GAA_anch_tip; + strcpy_s(camps.campo_anch,OLV_LIMP_MAX_CAMP,ini.get(ig,param.GetBuffer(param.GetLength()),camps.campo_anch)); + camps.campo_anch[10]=0; + + param=OliviaDef::GeneralDef::GAA_tipolo; + strcpy_s(camps.campo_tipo_ap,OLV_LIMP_MAX_CAMP,ini.get(ig,param.GetBuffer(param.GetLength()),camps.campo_tipo_ap)); + camps.campo_tipo_ap[10]=0; + + param=OliviaDef::GeneralDef::GAA_entid; + strcpy_s(camps.campo_tipo_ent,OLV_LIMP_MAX_CAMP,ini.get(ig,param.GetBuffer(param.GetLength()),camps.campo_tipo_ent)); + camps.campo_tipo_ent[10]=0; + } + param=OliviaDef::GeneralDef::GrupoAtribLimp; + ig=ini.get_grupo(param.GetBuffer(param.GetLength())); + if(ig>=0) + { + + param=OliviaDef::GeneralDef::GAL_aparc; + strcpy_s(camps.atr_tip_ent[OLV_ATR_NOM_TIP_ENT_AP],OLV_LIMP_MAX_CAMP,ini.get(ig,param.GetBuffer(param.GetLength()),camps.atr_tip_ent[OLV_ATR_NOM_TIP_ENT_AP])); + + param=OliviaDef::GeneralDef::GAL_bord; + strcpy_s(camps.atr_tip_ent[OLV_ATR_NOM_TIP_ENT_BORD],OLV_LIMP_MAX_CAMP,ini.get(ig,param.GetBuffer(param.GetLength()),camps.atr_tip_ent[OLV_ATR_NOM_TIP_ENT_BORD])); + + param=OliviaDef::GeneralDef::GAL_peat; + strcpy_s(camps.atr_tip_ent[OLV_ATR_NOM_TIP_ENT_PEAT],OLV_LIMP_MAX_CAMP,ini.get(ig,param.GetBuffer(param.GetLength()),camps.atr_tip_ent[OLV_ATR_NOM_TIP_ENT_PEAT])); + + param=OliviaDef::GeneralDef::GAL_acera; + strcpy_s(camps.atr_tip_ent[OLV_ATR_NOM_TIP_ENT_ACERA],OLV_LIMP_MAX_CAMP,ini.get(ig,param.GetBuffer(param.GetLength()),camps.atr_tip_ent[OLV_ATR_NOM_TIP_ENT_ACERA])); + + param=OliviaDef::GeneralDef::GAL_ap_lin; + strcpy_s(camps.atr_tip_apa[OLV_ATR_TIP_AP_LIN],OLV_LIMP_MAX_CAMP,ini.get(ig,param.GetBuffer(param.GetLength()),camps.atr_tip_apa[OLV_ATR_TIP_AP_LIN])); + + param=OliviaDef::GeneralDef::GAL_ap_bat; + strcpy_s(camps.atr_tip_apa[OLV_ATR_TIP_AP_BAT],OLV_LIMP_MAX_CAMP,ini.get(ig,param.GetBuffer(param.GetLength()),camps.atr_tip_apa[OLV_ATR_TIP_AP_BAT])); + } + ////////////////////////////////////////////////////// + param=OliviaDef::GeneralDef::GrupoCampoOtros; + ig=ini.get_grupo(param.GetBuffer(param.GetLength())); + if(ig>=0) + { + double ang; + param=OliviaDef::GeneralDef::GTO_girmax; + ang=ini.get(ig,param.GetBuffer(param.GetLength()),OLV_LIMP_GIRO_VEHIC); + ang_lim = ang*OLV_PI/180; + + param=OliviaDef::GeneralDef::GTO_anch_peat; + anchos_def[OLV_ANCH_DEF_PEAT]=ini.get(ig,param.GetBuffer(param.GetLength()),anchos_def[OLV_ANCH_DEF_PEAT]); + + param=OliviaDef::GeneralDef::GTO_anch_ace; + anchos_def[OLV_ANCH_DEF_ACE]=ini.get(ig,param.GetBuffer(param.GetLength()),anchos_def[OLV_ANCH_DEF_ACE]); + + param=OliviaDef::GeneralDef::GTO_anch_aplin; + anchos_def[OLV_ANCH_DEF_APLIN]=ini.get(ig,param.GetBuffer(param.GetLength()),anchos_def[OLV_ANCH_DEF_APLIN]); + + param=OliviaDef::GeneralDef::GTO_anch_apbat; + anchos_def[OLV_ANCH_DEF_APBAT]=ini.get(ig,param.GetBuffer(param.GetLength()),anchos_def[OLV_ANCH_DEF_APBAT]); + + param=OliviaDef::GeneralDef::GTO_anch_bordlib; + anchos_def[OLV_ANCH_DEF_BORD]=ini.get(ig,param.GetBuffer(param.GetLength()),anchos_def[OLV_ANCH_DEF_BORD]); + + param=OliviaDef::GeneralDef::GTO_desv_max; + DESV_MAX=ini.get(ig,param.GetBuffer(param.GetLength()),OLV_DESV_MAX); + + param=OliviaDef::GeneralDef::GTO_desv_max_abs; + DESV_MAX_ABS=ini.get(ig,param.GetBuffer(param.GetLength()),OLV_DESV_MAX_ABS); + } + return TRUE; +} +//************************************************************************************* +/** + * Actualiza el ini + */ +BOOL Colv_limp::guarda_campos_ini(char *path) +{ + Cini_file ini; + int ig; + + ig =ini.add_grupo(OLV_LIMP_GRUPO_DBF); + if(ig<0) + return FALSE; + + ini.add(ig,OLV_LIMP_PARAM_OBS,camps.campo_obs); + ini.add(ig,OLV_LIMP_PARAM_ANCHO,camps.campo_anch); + ini.add(ig,OLV_LIMP_PARAM_TIPO_AP,camps.campo_tipo_ap); + ini.add(ig,OLV_LIMP_PARAM_TIPO_ENT,camps.campo_tipo_ent); + + ini.add(ig,OLV_LIMP_PARAM_TIPO_ENT_APARCA,camps.atr_tip_ent[OLV_ATR_NOM_TIP_ENT_AP]); + ini.add(ig,OLV_LIMP_PARAM_TIPO_ENT_BORD,camps.atr_tip_ent[OLV_ATR_NOM_TIP_ENT_BORD]); + ini.add(ig,OLV_LIMP_PARAM_TIPO_ENT_PEATO,camps.atr_tip_ent[OLV_ATR_NOM_TIP_ENT_PEAT]); + ini.add(ig,OLV_LIMP_PARAM_TIPO_ENT_ACERA,camps.atr_tip_ent[OLV_ATR_NOM_TIP_ENT_ACERA]); + + ini.add(ig,OLV_LIMP_PARAM_TIPO_AP_LIN,camps.atr_tip_apa[OLV_ATR_TIP_AP_LIN]); + ini.add(ig,OLV_LIMP_PARAM_TIPO_AP_BAT,camps.atr_tip_apa[OLV_ATR_TIP_AP_BAT]); + + ig =ini.add_grupo(OLV_LIMP_GRUPO_OTROS); + if(ig<0) + return FALSE; + ini.add(ig,OLV_LIMP_PARAM_GIRO_VEHIC,OLV_LIMP_GIRO_VEHIC); + ini.add(ig,OLV_LIMP_PARAM_ANCH_DEF_PEAT,anchos_def[OLV_ANCH_DEF_PEAT]); + ini.add(ig,OLV_LIMP_PARAM_ANCH_DEF_ACE,anchos_def[OLV_ANCH_DEF_ACE]); + ini.add(ig,OLV_LIMP_PARAM_ANCH_DEF_APLIN,anchos_def[OLV_ANCH_DEF_APLIN]); + ini.add(ig,OLV_LIMP_PARAM_ANCH_DEF_APBAT,anchos_def[OLV_ANCH_DEF_APBAT]); + ini.add(ig,OLV_LIMP_PARAM_ANCH_DEF_BORD,anchos_def[OLV_ANCH_DEF_BORD]); + + ini.add(ig,OLV_LIMP_PARAM_DESV_MAX,DESV_MAX); + ini.add(ig,OLV_LIMP_PARAM_DESV_MAX_ABS,DESV_MAX_ABS); + + if(!ini.guarda(path)) + return FALSE; + return TRUE; + +} +//************************************************************************************* +/** + * Rellena los nombres de los campos de la dbf + */ +void Colv_limp::rellena_campos() +{ + //TOM TOM + sprintf_s(camps.campo_circ,OLV_LIMP_MAX_CAMP,"ONEWAY"); + sprintf_s(camps.campo_velo,OLV_LIMP_MAX_CAMP,"KPH"); + sprintf_s(camps.campo_fow,OLV_LIMP_MAX_CAMP,"FOW"); + sprintf_s(camps.campo_name,OLV_LIMP_MAX_CAMP,"NAME"); + + //VSM + sprintf_s(camps.campo_obs,OLV_LIMP_MAX_CAMP,"OBSERVACIO"); + sprintf_s(camps.campo_anch,OLV_LIMP_MAX_CAMP,"ANCHO_TIPO"); + sprintf_s(camps.campo_tipo_ap,OLV_LIMP_MAX_CAMP,"TIPOLOGIA"); + sprintf_s(camps.campo_tipo_ent,OLV_LIMP_MAX_CAMP,"NOM_TIPO_E"); + + //IGT + sprintf_s(camps.campo_secto,OLV_LIMP_MAX_CAMP,OliviaDef::GeneralDef::NombColSector); + + ///////rellena los atributos + //TOMTOM + sprintf_s(camps.atr_circ[OLV_ATR_CIRC_TF],OLV_LIMP_MAX_CAMP,"TF"); + sprintf_s(camps.atr_circ[OLV_ATR_CIRC_FT],OLV_LIMP_MAX_CAMP,"FT"); + sprintf_s(camps.atr_circ[OLV_ATR_CIRC_NONE],OLV_LIMP_MAX_CAMP,"N"); + sprintf_s(camps.atr_circ[OLV_ATR_CIRC_PEDES],OLV_LIMP_MAX_CAMP,"14"); + //VSM + sprintf_s(camps.atr_tip_ent[OLV_ATR_NOM_TIP_ENT_AP],OLV_LIMP_MAX_CAMP,"Banda_Aparcamiento"); + sprintf_s(camps.atr_tip_ent[OLV_ATR_NOM_TIP_ENT_BORD],"Bordillo_Libre"); + sprintf_s(camps.atr_tip_ent[OLV_ATR_NOM_TIP_ENT_PEAT],OLV_LIMP_MAX_CAMP,"Peatonales"); + sprintf_s(camps.atr_tip_ent[OLV_ATR_NOM_TIP_ENT_ACERA],OLV_LIMP_MAX_CAMP,"Acera"); + // + sprintf_s(camps.atr_tip_apa[OLV_ATR_TIP_AP_LIN],OLV_LIMP_MAX_CAMP,"Linea"); + sprintf_s(camps.atr_tip_apa[OLV_ATR_TIP_AP_BAT],OLV_LIMP_MAX_CAMP,"Bateria"); + + ///////rellena los valores de anchos por defecto + anchos_def[OLV_ANCH_DEF_PEAT]=6; + anchos_def[OLV_ANCH_DEF_ACE]=1.5; + anchos_def[OLV_ANCH_DEF_APLIN]=2; + anchos_def[OLV_ANCH_DEF_APBAT]=4; + anchos_def[OLV_ANCH_DEF_BORD]=1.5; + //rellena datos de desviación + DESV_MAX=OLV_DESV_MAX; + DESV_MAX_ABS=OLV_DESV_MAX_ABS; + + if(olv->paths.path_cfg_geo[0]) + { + rellena_campos_ini(olv->paths.path_cfg_geo); + } +} +//************************************************************************************* +/** + * Prueba debug + */ +void Colv_limp::prueba() +{ + Param_olv_limp_thr par; + pp++; + par.id_e=-1; + + int i =thr_limp->OLV_LIMP_EV_UNE_AMB_NW; + thr_limp->encola(i,&par,FALSE); + i ++; + thr_limp->encola(i,&par,FALSE); + i ++; + thr_limp->encola(i,&par,FALSE); +} +//************************************************************************************* +/** + * Devuelve el coste de recorrer un segmento en función de si es ámbito, segmento o carretera + */ +double Colv_limp::dame_ancho(char *observ, char *tipo) +{ + double aux, ancho,aux2; + char *token; + int i,ii,ff; + + ancho=0; + aux=aux2=0; + //El formato de observaciones tiene la forma "n metros", y el ancho es 'n'. + //Si no lo encontrara, tiene que ver el "ancho tipo" + if(strlen(observ)>0) + { + //busca los números + ii=-1; + for(i=0;i<(int)strlen(observ);i++) + { + if((observ[i]>='1') && (observ[i]<='9')) + { + if(ii<0) + ii=i; + ff=i; + } + } + if(ii>=0) + { + if(ff<((int)strlen(observ)-1))//delimita el número, donde acaba pone un null + observ[ff+1]=0; + aux = atof(&observ[ii]); + } + if(aux>0) + ancho=aux; + } + if(aux==0 && (strlen(tipo)>0))//bien porque no había campo observ o porque no se ha conseguido calcular + { + //se coge el campo de tipo, con el formato de "2-4" o "<2" o ">4" + if(token=strstr(tipo,"-"))//El ancho es tipo "2-4" + { + if((token-1)>0) + aux=atof(token-1); + if((token+1)>0) + aux2=atof(token+1); + aux=(aux+aux2)/2; + if(aux) + ancho=aux; + } + else if(token=strstr(tipo,"<"))//El ancho es tipo "<2" + { + if((token+1)>0) + aux=atof(token+1); + if(aux>1) + ancho=aux-1; + } + else if(token=strstr(tipo,">"))//El ancho es tipo ">4" + { + if((token+1)>0) + aux=atof(token+1); + if(aux) + ancho=aux+1; + } + } + + return ancho; +} +//************************************************************************************* +/** + * Devuelve el coste de recorrer un segmento en función de si es ámbito, segmento o carretera + */ +void Colv_limp::dame_cost(double ltot, int ia, float *cost, float *cost2) +{ + double velo; + double ancho; + + //////////////////////////////////////////////////////////////////////// + //Calcula el coste en función de si es carretera, segmento o ámbito + //Posibilidades: + //Se le da el coste al propio ámbito. + //Si es ámbito lineal, y t_tto es en km/h, cost=ltot/t_tto, pasando t_tto a m/s + //Si es ámbito lineal, y t_tto es km2/h, si ancho_via==0 entonces el ancho es el leído de la dbf + //y el coste de ida y de vuelta es cost=ltot*anch/t_tto, donde anch puede ser ancho_via o el de la info asociada + //Si es ámbito puntual, el coste es directamente t_tto, pasando t_tto de min a seg + //Si es segmento, ambos costes son 0 + //Si es carretera, la velocidad puede ser definida por la vía o v_despl si no es 0 + //y el cost=ltot/velo + //también hay que mirar si se puede en los dos sentidos o no + //////////////////////////////////////////////////////////////////////// + if(iaso[ia].flgs & OLV_LIMP_FLG_AMB) + { + //calculamos el coste del ámbito + if(tipo_ambit==OLV_AMB_LIN) + { + if((uds_tto==OliviaDef::GeneralDef::OlvTipTtoMh) || (uds_tto==OliviaDef::GeneralDef::OlvTipTtoMh_eje)) + ancho=1; + else if(uds_tto==OliviaDef::GeneralDef::OlvTipTtoM2h) + ancho=iaso[ia].inf_l.ancho; + else if(uds_tto==OliviaDef::GeneralDef::OlvTipTtoM2h_eje) + ancho=ancho_via; + + *cost2=*cost=(float)(ltot*ancho*3600/t_tto); //en segundos + } + else if(tipo_ambit==OLV_AMB_PUN) + { + *cost=*cost2=(float)t_tto; //en segundos + } + } + else if(iaso[ia].flgs & OLV_LIMP_FLG_SEG_AMB) + { + //coste fijo para los segmentos que unen ambitos, proporcional a su longitud + *cost2=*cost=0;//(float)(ltot/(3*OLV_KMH2MS));//OLV_LIMP_COST_SEGM + } + else if(iaso[ia].flgs & (OLV_LIMP_FLG_SEG_LIN | OLV_LIMP_FLG_SEG_PUN)) + { + //coste fijo para los segmentos + *cost2=*cost=(float)(ltot/(3*OLV_KMH2MS));//OLV_LIMP_COST_SEGM + } + else if(iaso[ia].flgs & OLV_LIMP_FLG_PEAT_REP) + { + //coste de desplazarse andando por las peatonales, no trabajando + if(v_despl==0) + velo=OLV_LIMP_VELO_DESP_PEAT*OLV_KMH2MS; + else + velo=v_despl; //velocidad que se haya configurado + *cost2=*cost=float(ltot/velo); + } + else if(iaso[ia].flgs & OLV_LIMP_FLG_NW)//es carretera + { + //calculamos el coste de la carretera + if(v_despl==0) + velo=iaso[ia].inf_n.velo; //velocidad definida por las vías, la que se ha leído del dbf + else + { + velo=v_despl*f_trafic; //velocidad que se haya configurado + } + ////////////////////////////////////////////////////////// + /*if(iaso[ia].flgs & OLV_LIMP_FLG_CIRC_NONE)//es pedestrian o prohibido, no se puede circular + *cost=*cost2=(float)MAYUSCULO; + else*/ + { + *cost=*cost2=(float)(ltot/velo); //en ambos sentidos + if(iaso[ia].flgs & OLV_LIMP_FLG_CIRC_FT) + *cost2=(float)MAYUSCULO; + else if(iaso[ia].flgs & OLV_LIMP_FLG_CIRC_TF) + *cost=(float)MAYUSCULO; + } + } +} +//************************************************************************************* +void Secu_amb::libera(int i, int n) +{ + for(int j=0;j cost_amb; /// iaso; /// *tramos; + + //************************************************************************************* + //Funciones + Colv_limp(COlivia *olv); + virtual ~Colv_limp(void); + //////////////// + void libera_memo_secto(); + void prueba(); + virtual BOOL inicia(); + virtual int pon_config(char *config); + virtual void cancela(); + virtual void rellena_campos(); + virtual void dame_cost(double ltot, int ia, float *cost, float *cost2); + double dame_ancho(char *observ, char *tipo); + BOOL rellena_campos_ini(char *path); + BOOL guarda_campos_ini(char *path); +}; +#endif \ No newline at end of file diff --git a/Olivia/olv_limp_def.h b/Olivia/olv_limp_def.h new file mode 100644 index 0000000..8036716 --- /dev/null +++ b/Olivia/olv_limp_def.h @@ -0,0 +1,521 @@ +#pragma once +#include +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////// +/** +* @file olv_limp_def.h +* Archivo de definiciones generales de Olivia. +*/ +//Defines +#define OLV_LIMP_AMB_NW_NODEF USHRT_MAX//-1 //dth[i].coste) + j=i; + } + return j; + }; +}th_param_planif; \ No newline at end of file diff --git a/Olivia/olv_limp_thr.cpp b/Olivia/olv_limp_thr.cpp new file mode 100644 index 0000000..cccc4a4 --- /dev/null +++ b/Olivia/olv_limp_thr.cpp @@ -0,0 +1,10550 @@ +#include "stdafx.h" + +#ifdef OLIVIA_COMPILA +//olivia +#include "olv_limp_thr.h" +#include "olv_thr.h" +#include "olv_limp.h" +#include "olv.h" +#include "olv_geom.h" +#include "olv_csv.h" +//igt_base +#include "lock.h" +#include +#include "olv_tasks.h" +#include "olv_tasks_def.h" +#include "olv_sock.h" +//utiles +#include "dir_manager.h" +#include "GeometryFunction.h" +#include "Fdbf.h" +#include "b_file.h" +#include "ManagerDbfGdataTable.h" +#include "sock_sv.h" +#include + +UINT th_planificacion(LPVOID pp); +/** +* @file olv_limp_thr.cpp +* Archivo de implementaciones del thread de control de la utilidad de limpieza viaria del programa Olivia. +*/ + +Colv_limp_thr::Colv_limp_thr(Colv_limp *olv_limp) : Colv_thr(olv_limp->olv) +{ + this->olv_limp = olv_limp; + thr_padre=NULL; + n_subthr_fin=0; + pirate=FALSE; + fin_permu=FALSE; + //los subthreads + n_subthr=Colv_geom::dame_n_nucleos(); //lanza un thread por procesador + subthrs = (Colv_limp_thr **)malloc(n_subthr*sizeof(Colv_limp_thr *)); + for(int i=0;itramos=NULL; +} + +Colv_limp_thr::~Colv_limp_thr(void) +{ + int i; + + //destruye los subthreads + if(subthrs) + { + for(i=0;itramos) + delete [] olv_limp->tramos; +} + +//************************************************************************************* +void Colv_limp_thr::inicia_th() +{ + inicia(OLV_MILIS_COLA,&cola_proc,-1,"limp_thr"); + olvlog(LOG_TODO,"olv_limp_t","Thread de limpieza limp_thr arrancado"); + borra_temp_files(); + pirate=FALSE; + fin_permu=FALSE; +} + +//************************************************************************************* +/** + * Cola de procesos en la que el thread está iterando y va ejecutando la tarea que le toque en cada momento + * También se usa en los subprocesos, cuando el proceso principal lanza los subprocesos, cada uno itera en una cola como esta + */ +void Colv_limp_thr::cola_proc(int evento, OlvAsync_cola *clase,Param_olv_limp_thr *e) +{ + BOOL bien=TRUE; + + Colv_limp_thr *this_i=static_cast(clase); + switch (evento) + { + case OLV_LIMP_EV_ABRE_DAT: + { + bien=this_i->abre_datos(); + if(bien && (this_i->olv->modo_ejecpirate)//sigue + this_i->encola(OLV_LIMP_EV_RELL_DAT,NULL,FALSE); + break; + } + case OLV_LIMP_EV_RELL_DAT: + { + bien=this_i->rellena_datos(); + if(bien && (this_i->olv->modo_ejecpirate)//sigue + { + if(!this_i->olv->olv_limp->barr_mix) + this_i->encola(OLV_LIMP_EV_UNE_AMB_NW,NULL,FALSE); + else + this_i->encola(OLV_LIMP_EV_BARRMIX,NULL,FALSE); + } + break; + } + case OLV_LIMP_EV_BARRMIX: + { + //esta tarea lanza varios subthreads para realizar las comprobaciones del barrido mixto + //y estos cuando acaban le encolan al padre (el que los ha lanzado) + //la tarea de comprueba_barr_mixto_fin + this_i->mejora_barr_mix(); + break; + } + case OLV_LIMP_EV_BARRMIX_SUB: + { + //aquí entran los subthreads para hacer las comprobaciones del barrido mixto + //encolan al padre la tarea de fin + int ithr; + if(e!=NULL) + ithr=e->id_e; + this_i->mejora_barr_mix_sub(ithr); + break; + } + case OLV_LIMP_EV_BARRMIX_FIN: + { + //aquí entra el padre cuando van acabando los subthreads + //si han terminado todos encola la siguiente tarea + this_i->n_subthr_fin++; + if(this_i->n_subthr_fin==this_i->n_subthr) + { + this_i->n_subthr_fin=0; + bien=this_i->mejora_barr_mix_fin(); + if(bien && (this_i->olv->modo_ejecpirate)//sigue + { + this_i->encola(OLV_LIMP_EV_UNE_AMB_NW,NULL,FALSE); + } + } + break; + } + case OLV_LIMP_EV_UNE_AMB_NW: + { + int soloi=-1; + bien=this_i->une_amb_nw(soloi); + if(bien && (this_i->olv->modo_ejecpirate)//sigue + { + if(this_i->olv_limp->tipo_ambit==OLV_AMB_LIN) + this_i->encola(OLV_LIMP_EV_COMPCORT,NULL,FALSE); + else //si son lineales, se mira si hay cortes para reapuntar antes de hacer topo + this_i->encola(OLV_LIMP_EV_TOPO_NW,NULL,FALSE); + } + break; + } + case OLV_LIMP_EV_COMPCORT: + { + this_i->compr_cortes_amb(); + break; + } + case OLV_LIMP_EV_COMPCORT_SUB: + { + //aquí entran los subthreads para hacer los cálculos de distancia, cuando acaban + //encolan al padre la tarea de fin + int ithr; + if(e!=NULL) + ithr=e->id_e; + this_i->compr_cortes_amb_sub(ithr); + break; + } + case OLV_LIMP_EV_COMPCORT_FIN: + { + //aquí entra el padre cuando van acabando los subthreads + //si han terminado todos encola la siguiente tarea + this_i->n_subthr_fin++; + if(this_i->n_subthr_fin==this_i->n_subthr) + { + this_i->n_subthr_fin=0; + bien=this_i->compr_cortes_amb_sub_fin(); + if(bien && (this_i->olv->modo_ejecpirate)//sigue + { + this_i->encola(OLV_LIMP_EV_TOPO_NW,NULL,FALSE); + } + } + break; + } + case OLV_LIMP_EV_TOPO_NW: + { + bien=this_i->topo_nw(); + if(bien && (this_i->olv->modo_ejecpirate)//sigue + this_i->encola(OLV_LIMP_EV_COST_CONJ,NULL,FALSE); + break; + } + case OLV_LIMP_EV_COST_CONJ: + { + //esta tarea lanza varios subthreads para realizar los cálculos + //de costes entre conjunciones (les encola la tarea dist_conj_sub), + //y estos cuando acaban le encolan al padre (el que los ha lanzado) + //la tarea de dist_conj_fin + bien=this_i->calcula_cost_conj(); + break; + } + case OLV_LIMP_EV_COST_CONJ_SUB: + { + //aquí entran los subthreads para hacer los cálculos de distancia, cuando acaban + //encolan al padre la tarea de fin + int ithr; + if(e!=NULL) + ithr=e->id_e; + this_i->calcula_cost_conj_sub(ithr); + break; + } + case OLV_LIMP_EV_COST_CONJ_FIN: + { + //aquí entra el padre cuando van acabando los subthreads + //si han terminado todos encola la siguiente tarea + + this_i->n_subthr_fin++; + if(this_i->n_subthr_fin==this_i->n_subthr) + { + this_i->n_subthr_fin=0; + bien=this_i->calcula_cost_conj_fin(); + if(bien && (this_i->olv->modo_ejecpirate)//sigue + { + this_i->encola(OLV_LIMP_EV_ANG_CONJ,NULL,FALSE); + } + } + break; + } + case OLV_LIMP_EV_ANG_CONJ: + { + //esta tarea lanza varios subthreads para realizar los cálculos + //de ángulos entre conjunciones (les encola la tarea ang_conj_sub), + //y estos cuando acaban le encolan al padre (el que los ha lanzado) + //la tarea de ang_conj_fin + bien=this_i->calcula_ang_conj(); + break; + } + case OLV_LIMP_EV_ANG_CONJ_SUB: + { + //aquí entran los subthreads para hacer los cálculos de ángulos, cuando acaban + //encolan al padre la tarea de fin + int ithr; + if(e!=NULL) + ithr=e->id_e; + this_i->calcula_ang_conj_sub(ithr); + break; + } + case OLV_LIMP_EV_ANG_CONJ_FIN: + { + //aquí entra el padre cuando van acabando los subthreads + //si han terminado todos encola la siguiente tarea + this_i->n_subthr_fin++; + if(this_i->n_subthr_fin==this_i->n_subthr) + { + this_i->n_subthr_fin=0; + bien=this_i->calcula_ang_conj_fin(); + if(bien && this_i->olv_limp->olv->modo_multitask && !this_i->pirate) + this_i->encola(OLV_LIMP_EV_GUARD_MATS,NULL,FALSE); + else if(bien && (this_i->olv->modo_ejecpirate)//sigue + this_i->encola(OLV_LIMP_EV_COST_AMB,NULL,FALSE); + } + break; + } + case OLV_LIMP_EV_GUARD_MATS: + { + bien=this_i->guarda_mats(); + break; + } + case OLV_LIMP_EV_GUARD_MATS_SUB: + { + int ithr; + if(e!=NULL) + ithr=e->id_e; + this_i->guarda_mats_sub(ithr); + break; + } + case OLV_LIMP_EV_GUARD_MATS_FIN: + { + //aquí entra el padre cuando van acabando los subthreads + //si han terminado todos encola la siguiente tarea + this_i->n_subthr_fin++; + int i; + if(this_i->n_subthr_fin==this_i->n_subthr) + { + this_i->n_subthr_fin=0; + for(i=0;in_subthr;i++) + if(this_i->subthrs[i]->prog_subthr<0) + break; + if(in_subthr) + { + bien=FALSE; + this_i->pon_mi_msg("Errores al guardar matrices de costes"); + break; + } + bien=this_i->guarda_mats_fin(); + if(bien && (this_i->olv->modo_ejecpirate)//sigue + this_i->encola(OLV_LIMP_EV_TASK_ESCUCHA,NULL,FALSE); + } + break; + } + case OLV_LIMP_EV_TASK_ESCUCHA: + { + bien=this_i->task_dj_escucha(); + break; + } + case OLV_LIMP_EV_TASK_FIN: + { + this_i->n_subthr_fin++; + if((e!=NULL) && e->id_e<0)//ha ido mal + { + if(e->id_e==-1) + this_i->subthrs[this_i->n_subthr_fin-1]->prog_subthr=-1; + else if(e->id_e==-2) + { + bien=FALSE; + this_i->pon_mi_msg("Errores en cálculo multitask, no ha habido conexión"); + break; + } + } + int i; + if(this_i->n_subthr_fin==this_i->n_subthr) + { + this_i->n_subthr_fin=0; + for(i=0;in_subthr;i++) + if(this_i->subthrs[i]->prog_subthr<0) + break; + if(in_subthr) + { + bien=FALSE; + this_i->pon_mi_msg("Errores en cálculo multitask"); + break; + } + this_i->task_dj_fin(); + if(bien && (this_i->olv->modo_ejecpirate)//sigue + this_i->encola(OLV_LIMP_EV_COST_AMB,NULL,FALSE); + } + break; + } + case OLV_LIMP_EV_COST_AMB: + { + //esta tarea lanza varios subthreads para realizar los cálculos + //de costes(les encola la tarea dist_amb_sub), + //y estos cuando acaban le encolan al padre (el que los ha lanzado) + //la tarea de dist_amb_fin + bien=this_i->calcula_cost_amb(); + break; + } + case OLV_LIMP_EV_COST_AMB_SUB: + { + //aquí entran los subthreads para hacer los cálculos de costes entre ámbitos, cuando acaban + //encolan al padre la tarea de fin + int ithr; + if(e!=NULL) + ithr=e->id_e; + this_i->calcula_cost_amb_sub(ithr); + break; + } + case OLV_LIMP_EV_COST_AMB_FIN: + { + //aquí entra el padre cuando van acabando los subthreads + //si han terminado todos encola la siguiente tarea + int i; + this_i->n_subthr_fin++; + if(this_i->n_subthr_fin==this_i->n_subthr) + { + this_i->n_subthr_fin=0; + for(i=0;in_subthr;i++) + if(this_i->subthrs[i]->prog_subthr<0) + break; + if(in_subthr) + { + bien=FALSE; + this_i->pon_mi_msg("Errores al calcular coste entre ámbitos"); + break; + } + bien=this_i->calcula_cost_amb_fin(); + if(bien && (this_i->olv->modo_ejecpirate)//sigue + { + if(this_i->olv->modo_ejec==OLV_EJEC_PLAN) //lee info de sectorización y va a planif + this_i->encola(OLV_LIMP_EV_LEE_SECTO,NULL,FALSE); + else //sectoriza + { + if(this_i->olv_limp->nsec==0)//hay que calcular el número de sectores + this_i->encola(OLV_LIMP_EV_CALC_NSEC,NULL,FALSE); + else + { + if(this_i->olv_limp->nsec<0) + { + this_i->olv_limp->calc_nsec=this_i->dame_cost_jornada();//indica que se tiene que ajustar a la jornada + this_i->olv_limp->nsec=this_i->olv_limp->nsec_act=this_i->olv_limp->nsec*(-1); + } + this_i->encola(OLV_LIMP_EV_SECTORIZA,NULL,FALSE); + } + } + } + + } + break; + } + case OLV_LIMP_EV_CALC_NSEC: + { + bien=this_i->calcula_n_sec(); + if(bien && (this_i->olv->modo_ejecpirate)//sigue + { + this_i->encola(OLV_LIMP_EV_SECTORIZA,NULL,FALSE); + } + break; + } + case OLV_LIMP_EV_SECTORIZA: + { + bien=this_i->sectoriza(); + if(bien && (this_i->olv->modo_ejecpirate)//sigue + { + this_i->pon_info_resul(); + if(this_i->olv->modo_ejec>=OLV_EJEC_DEBUG_SIGUE) + this_i->encola(OLV_LIMP_EV_PLANIFICA,NULL,FALSE); + else + { + this_i->borra_temp_files(); + this_i->pon_mi_progre(OLV_TAREA_FIN_SEC,0); + } + } + break; + } + case OLV_LIMP_EV_LEE_SECTO: + { + bien=this_i->lee_secto(); + if(bien && !this_i->pirate)//sigue + { + this_i->encola(OLV_LIMP_EV_PLANIFICA,NULL,FALSE); + } + break; + } + case OLV_LIMP_EV_PLANIFICA: + { + bien=this_i->planifica(); + break; + } + case OLV_LIMP_EV_PLANIFICA_SUB: + { + //aquí entran los subthreads para hacer los cálculos de planificación, cuando acaban + //encolan al padre la tarea de fin + int ithr; + if(e!=NULL) + ithr=e->id_e; + this_i->planifica_sub_1(ithr, this_i->olv_limp->cost_amb); + break; + } + case OLV_LIMP_EV_PLANIFICA_FIN: + { + //aquí entra el padre cuando van acabando los subthreads + //si han terminado todos encola la siguiente tarea + int i; + this_i->n_subthr_fin++; + if(this_i->n_subthr_fin==this_i->n_subthr) + { + this_i->n_subthr_fin=0; + for(i=0;in_subthr;i++) + { + if(this_i->subthrs[i]->prog_subthr<0) + { + break; + } + } + if(in_subthr) + { + bien=FALSE; + this_i->pon_mi_msg("Errores al planificar th %ld",i); + break; + } + bien = this_i->planifica_fin(); + //pone progreso como que ha terminado + if(bien) + { + this_i->pon_info_resul(); + this_i->borra_temp_files(); + this_i->pon_mi_progre(OLV_TAREA_FIN_PLANIF,0); + } + } + break; + } + case OLV_LIMP_EV_SUBTHR_PROG: + { + //aquí entra el padre porque le encolan los subthreads para avisarle del progreso + double pro=0; + for(int i=0;in_subthr;i++) + pro+=this_i->subthrs[i]->prog_subthr; + pro=OliviaDef::GeneralDef::ProgrMax*pro/this_i->n_subthr; + if(e!=NULL) + { + this_i->pon_mi_progre(e->id_e,(int)pro); + } + break; + } + } + if(!bien) + { + this_i->pon_mi_progre(OLV_TAREA_FIN_NOK,0); +#ifndef _DEBUG + this_i->borra_temp_files(); +#endif + } +} +//************************************************************************************* +void Colv_limp_thr::termina_th() +{ + if(tarea==OLV_TAREA_PERMU && !fin_permu) + { + fin_permu=TRUE; + return; + } + if(fin_permu) + fin_permu=FALSE; + pirate=TRUE; + para_subthrs(); + termina(); + olvlog(LOG_TODO,"olv_limp_t","Thread de limpieza limp_thr finalizado"); +} +//************************************************************************************* +/** + * Abre los datos de cartografía + */ +BOOL Colv_limp_thr::abre_datos() +{ + //////////////////////////////////////////////////////// + int i; + Info_aso2 info_aux; + CartoBaseInfoEntity ient; + + olvlog(LOG_TODO,"olv_limp_t","Abriendo datos"); + pon_mi_progre(OLV_TAREA_IMP, 0); + pon_mi_msg(""); + err_str[0]=0; + + //abre la cartografía con los datos + if(!olv_limp->carto.importShp(olv_limp->olv->paths.path_data)) + { + pon_mi_msg("Error en la importación del archivo\n%s",olv_limp->olv->paths.path_data); + return FALSE; + } + olv_limp->n_amb=olv_limp->carto.getNumberEntities(); + if(olv_limp->n_amb>=USHRT_MAX) + { + pon_mi_msg("Número de ámbitos (%ld) mayor que el permitido (%ld)\n",olv_limp->n_amb,USHRT_MAX); + return FALSE; + } + //Inicializa la información asociada + info_aux.reset(); + //si es tipo eje de calle lo pone en el flag + if((olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoMh_eje) || + (olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoM2h_eje)) + { + info_aux.flgs = OLV_LIMP_FLG_EJE; + } + info_aux.flgs |= OLV_LIMP_FLG_AMB; + for(i=0;in_amb;i++) + { + ient = olv_limp->carto.get(i); + info_aux.refe = ient.entity()->ref; + info_aux.iamb=i; + olv_limp->iaso[info_aux.refe]=info_aux; + } + + //abre la cartografía de la red navegable + if(!olv_limp->carto.importShp(olv_limp->olv->paths.path_nw)) + { + pon_mi_msg("Error en la importación del archivo\n%s",olv_limp->olv->paths.path_nw); + return FALSE; + } + olv_limp->n_nw=olv_limp->carto.getNumberEntities()-olv_limp->n_amb; + //Inicializa la información asociada + info_aux.reset(); + info_aux.flgs = OLV_LIMP_FLG_NW; + for(i=olv_limp->n_amb;in_nw+olv_limp->n_amb;i++) + { + ient=olv_limp->carto.get(i); + info_aux.refe = ient.entity()->ref; + olv_limp->iaso[info_aux.refe]=info_aux; + } + + ////////////////////////////////////////////////////////////////////////// + //rellena la información asociada de la red: + //sentidos de circulación, velocidad de la vía... + if(!rellena_info_nw()) + { + pon_mi_msg("Error al leer info asociada a red navegable: %s", err_str); + return FALSE; + } + + //////////////////// + + olvlog(LOG_TODO,"olv_limp_t","Finaliza Abrir datos con éxito"); + + return TRUE; +} +//************************************************************************************* +/** + * Rellena la información asociada de la red navegable y los datos de limpieza + */ +BOOL Colv_limp_thr::rellena_datos() +{ + if(!rellena_info_amb()) + { + pon_mi_msg("Error al leer info asociada a ámbitos: %s", err_str); + return FALSE; + } + + olvlog(LOG_TODO,"olv_limp_t","Finaliza Rellena datos con éxito"); + + return TRUE; +} +//************************************************************************************* +/** + * Comrpueba las entidades para adecuarlas al barrido mixto + */ +void Colv_limp_thr::mejora_barr_mix() +{ + int nthr=n_subthr; + olvlog(LOG_TODO,"olv_limp_t","Comienza las comprobaciones para el barrido mixto"); + lanza_subthrs(OLV_LIMP_EV_BARRMIX_SUB,nthr); +} +//************************************************************************************* +/** + * Comrpueba las entidades para adecuarlas al barrido mixto + */ +BOOL Colv_limp_thr::mejora_barr_mix_fin() +{ + //////////////// + //para los threads + para_subthrs(); + + return TRUE; +} +//************************************************************************************* +/** + * Comrpueba las entidades para adecuarlas al barrido mixto + */ +void Colv_limp_thr::mejora_barr_mix_sub(int ithr) +{ + //recorre los ámbitos + int i,j; + int refe_ace, refe_otro, refe_ant; + int na_desp,na_ini, na_fin, seg; + double lon_ace, lon_otro, pond, lon_ant,da; + BOOL mal=FALSE; + BOOL paralelas; + CartoBaseInfoEntity ient_ace, ient_otro; + + na_desp = (int)ceil(1.0*(olv_limp->n_amb)/n_subthr); + na_ini=ithr*na_desp; + na_fin = min((ithr+1)*na_desp,olv_limp->n_amb); + olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Comprueba Barr Mix Ambs %04d a %04d", ithr, na_ini, na_fin); + seg = GetTickCount(); + + //Bucle en los ámbitos + for(i=na_ini;icarto.get(i); + refe_ace = ient_ace.entity()->ref; + + if(!(olv_limp->iaso[refe_ace].flgs & OLV_LIMP_FLG_AMB_ACE)) + continue; + + //Se recorre las aceras + //Por cada acera, se recorre el resto de entidades, y las que sean + //bordillo o banda de aparcamiento, comprueba si es paralela + for(j=0;jn_amb && !pirate; j++) + { + ient_otro = olv_limp->carto.get(j); + refe_otro = ient_otro.entity()->ref; + if((j==i) || !(olv_limp->iaso[refe_otro].flgs & (OLV_LIMP_FLG_AMB_APA|OLV_LIMP_FLG_AMB_BORD))) + continue; + + //recorre ambas rectas a la par + //para ello, primero mira cuál es la más larga + lon_ace = ient_ace.getLong(); + lon_otro = ient_otro.getLong(); + + //parte de la más corta, y avanza en pasos del PORC_AVANCE% de su longitud + if(lon_aceiaso[refe_ace].refe2==-1) + { + //es la primera vez que ecuentra un bordillo paralelo + olv_limp->iaso[refe_ace].flgs=olv_limp->iaso[refe_ace].flgs | OLV_LIMP_FLG_AMB_NO; + while(olv_limp->iaso[refe_otro].refe2!=-1) + { + refe_otro=olv_limp->iaso[refe_otro].refe2; + } + olv_limp->iaso[refe_ace].refe2=refe_otro; + } + else + { + //esa acera ya tiene un bordillo paralelo, a este nuevo bordillo se le + //marca para que no se haga, y se acumula al anterior + refe_ant=olv_limp->iaso[refe_ace].refe2; + //marca el nuevo como no + olv_limp->iaso[refe_otro].flgs=olv_limp->iaso[refe_otro].flgs | OLV_LIMP_FLG_AMB_NO; + //coge el anterior + olv_limp->iaso[refe_otro].refe2=refe_ant; + //le añade un delta de ancho al anterior para que compense la longitud del nuevo + lon_ant=olv_limp->carto.getRef(refe_ant).getLong(); + da=lon_otro*olv_limp->iaso[refe_otro].inf_l.ancho/lon_ant; + olv_limp->iaso[refe_ant].inf_l.ancho+=da; + //renombra el otro como el anterior, para añadirle la acera + refe_otro=refe_ant; + } + //olv_limp->iaso[refe_ace].refe2=refe_otro; + + //suma los anchos de forma ponderada + pond=lon_ace/lon_otro; + if(pond>1) + pond=1; //cuando la acera es más grande, se suma el ancho de la acera, no se amplia + + //cuando la acera es más pequeña, puede que en ese bordillo o banda de aparcamiento + //haya otra acera en paralelo, así que se le sumará después su ancho también, + //de forma que la suma total sea la ponderación de los anchos + olv_limp->iaso[refe_otro].inf_l.ancho += olv_limp->iaso[refe_ace].inf_l.ancho*pond; + } + + //avisa de progreso + if(((i-na_ini)%100==0) || ((i-na_ini)==(na_desp-1))) + { + olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Comprobando Barrido Mixto ambs %ld de %ld", ithr, + (i-na_ini+1),na_desp); + } + } + + if(mal) + { + olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Error en mejoras Barrido mixto", ithr); + prog_subthr=-1;//para avisar al padre de que ha habido un error + } + else + { + olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Fin mejoras Barrido mixto, %.3f seg", ithr, 1.0*(GetTickCount()-seg)/1000); + } + thr_padre->encola(OLV_LIMP_EV_BARRMIX_FIN,NULL,FALSE); + +} +//************************************************************************************* +/** + * Avanza desde el primer punto de ient1 y el más próximo en ient2, + * midiendo la distancia entre las dos rectas + * devuelve si son paralelas o no en función de la dmedia y la desv + */ +BOOL Colv_limp_thr::barr_mix_paralelas(CartoBaseInfoEntity ient1, CartoBaseInfoEntity ient2) +{ + const double PORC_AVANCE = 0.2; //avanza en pasos del porc % de la longitud de la línea pequeña + //////////////////////////////////// + double l_avan, dmed, desv, l_parc, long1, dis; + int n; + double pt[3]; + + //comprueba si las puede descartar porque estén muy lejos + //mira si la distancia mínima del primer punto de ient1 a ient2 + //es muy grande para descartar + if((ient2.DisPtoLine(ient1.getPto(0))>OLV_BARRMIX_DMAX_DESC) && (ient2.DisPtoLine(ient1.getPto(ient1.getNumberPtos()-1))>OLV_BARRMIX_DMAX_DESC)) + return FALSE; + + l_parc=0; + long1=ient1.getLong(); + l_avan=PORC_AVANCE*long1; + n=(int)(1/PORC_AVANCE+0.5); + dmed=desv=0; + while(l_parcOLV_BARRMIX_DMED_MAX || desv>OLV_BARRMIX_DESV_MAX) + return FALSE; + + return TRUE; +} +//************************************************************************************* +/** + * Copia en las aceras que no se han usado para sectorizar porque se han asignado a bordillos o + * bandas de aparcamiento, el mismo sector que el bordillo que tienen asignado + * modo 0 secto, modo 1 planif + */ +void Colv_limp_thr::copia_info_barr_mix() +{ + for(int i=0;in_amb;i++) + { + if(!(olv_limp->iaso[i].flgs & OLV_LIMP_FLG_AMB_NO) || olv_limp->iaso[i].refe2<0) + continue; + + olv_limp->amb_sec[i].sec=olv_limp->amb_sec[olv_limp->iaso[olv_limp->iaso[i].refe2].iamb].sec; + olv_limp->amb_sec[i].iseq=olv_limp->amb_sec[olv_limp->iaso[olv_limp->iaso[i].refe2].iamb].iseq; + } +} +//************************************************************************************* +/** + * Rellena la información de sentidos de circulación y velocidad de las vías + * en la tabla de información asociada + */ +BOOL Colv_limp_thr::rellena_info_nw() +{ + Cb_file file; + Fdbf dbf; + int n,ntf, nft, nboth, nno,s,ia; + int icamps,icampv,icampn,icampf,f,idd, icampoid; + char nfile[MAX_PATH]; + char *sent; + BOOL ret=TRUE,ispedestrian; + + olvlog(LOG_TODO,"olv_limp_t","Rellenando matriz de info asociada a carreteras"); + pon_mi_progre(OLV_TAREA_IMP, (int) (OliviaDef::GeneralDef::ProgrMax*1/3)); //1/32 porque ya ha hecho 1/3, que es la importación + + ntf=nft=nboth=nno=0; + sent=NULL; + + //si no aplican los sentidos de circulación no se calculan, se ponen todos a todos sentidos + if(olv_limp->res_circ==OLV_RES_NO) + { + olvlog(LOG_TODO,"olv_limp_t","No aplican sentidos de circulación, puestos todos a 'ambos'"); + nboth=olv_limp->n_nw; + } + + //lee dbf del shp + strcpy_s(nfile,MAX_PATH,olv->paths.path_nw); + char bufAux[256]; + strcpy(nfile, Cdir_manager::cambia_extension_archivo(nfile,bufAux,".dbf")); + //cambiaext(nfile,".shp",".dbf"); + if(!file.abre(nfile,1) || !dbf.lee(&file)) + { + sprintf_s(err_str,OLV_MAX_ERR,"Error al abrir %s",nfile); + olvlog(LOG_TODO,"olv_limp_t","Error al abrir %s",nfile); + return FALSE; + } + + //busca el campo del sentido "ONEWAY" y el de "KPH" + icamps=icampv=icampn=icampf=-1; + icamps=dbf.findCol(olv_limp->camps.campo_circ); + icampv=dbf.findCol(olv_limp->camps.campo_velo); + icampn=dbf.findCol(olv_limp->camps.campo_name); + icampf=dbf.findCol(olv_limp->camps.campo_fow); + if(icamps==-1 || icampv==-1 || icampn==-1 || icampf==-1) + { + sprintf_s(err_str,OLV_MAX_ERR,"No encontrado campo %s y/o %s y/o %s en\n%s",olv_limp->camps.campo_circ, + olv_limp->camps.campo_velo,olv_limp->camps.campo_name,nfile); + olvlog(LOG_TODO,"No encontrado campo %s y/o %s y/o %s en\n%s",olv_limp->camps.campo_circ, + olv_limp->camps.campo_velo,olv_limp->camps.campo_name,nfile); + return FALSE; + } + icampoid=dbf.findCol(OLV_NOMB_OID); + + //////////////////////////////////////// + sent = (char*)malloc(dbf.getSize(icamps)+1); + if(!sent) + return FALSE; + sent[0]=0; + idd =dbf.leeNexRow(); + n=0; + ia=olv_limp->n_amb;//la info aso de la nw empieza donde acaba la de los ámbitos + while(idd == 1) + { + /////////////////////////////// + ispedestrian=FALSE; + if(olv_limp->res_circ!=OLV_RES_NO) + { + //("FOW" =3 OR "FOW">=7) AND ("ONEWAY" = 'N' OR "ONEWAY" = ' ' ) + //si se cumple lo anterior, son como doble sentido pero no se replican + ////////////////////////// + //sentido de circulación + strcpy(sent,dbf.getStr(icamps)); + s=0; + if(strcmp(sent,olv_limp->camps.atr_circ[OLV_ATR_CIRC_TF])==0) + { + s=OLV_LIMP_FLG_CIRC_TF; + ntf++; + } + else if(strcmp(sent,olv_limp->camps.atr_circ[OLV_ATR_CIRC_FT])==0) + { + s=OLV_LIMP_FLG_CIRC_FT; + nft++; + } + else if(strcmp(sent,olv_limp->camps.atr_circ[OLV_ATR_CIRC_NONE])==0) + { + //no aplica la restricción por ser servicio público, cómo se sabe si es de un único sentido? + s=OLV_LIMP_FLG_CIRC_NONE; + nno++; + } + else + { + nboth++; + } + + /////////////////////////////// + //fow + f=dbf.getI(icampf); + //solo mira si es pedestrian, f==14 + if(f==atoi(olv_limp->camps.atr_circ[OLV_ATR_CIRC_PEDES]) || f==-1) + { + s=OLV_LIMP_FLG_CIRC_NONE; + ispedestrian=TRUE; + } + /////////////////////////////// + + olv_limp->iaso[ia].flgs|=s; + } + + /////////////////////////////// + //velocidad + if((olv_limp->iaso[ia].flgs & OLV_LIMP_FLG_CIRC_NONE) || ispedestrian) + { + s= OLV_LIMP_VELO_CIRC_PEAT; //se le pone velo muy bajita para que intente no ir por ahí, porque son calles prohibidas + //a no ser que haya un contenedor + //o si es peatonal igual, que no haga las rutas por ahí, pero sí pase a hacer tratamientos + } + else + { + s=dbf.getI(icampv); + } + if(s<=0) + { + s=OLV_LIMP_VELO_DEF;//pone por def + } + + olv_limp->iaso[ia].inf_n.velo=1.0*s*OLV_KMH2MS; + + /////////////////////////////// + //nombre + olv_limp->iaso[ia].inf_n.nomb = (char*)malloc(dbf.getSize(icampn)+1); + if(!olv_limp->iaso[ia].inf_n.nomb) + break; + strcpy(olv_limp->iaso[ia].inf_n.nomb,dbf.getStr(icampn)); + + if(icampoid>=0) + olv_limp->iaso[ia].oid = dbf.getI(icampoid); + + /////////////////////////////// + //avisa de progreso + if((n%200==0) || (n==(olv_limp->n_nw+olv_limp->n_amb-1))) + { + pon_mi_progre(OLV_TAREA_IMP, (int) (OliviaDef::GeneralDef::ProgrMax* + (1.0*(n+1)/olv_limp->n_nw/3)+1/3));//por 2/3 porque esta tarea es la 2/3 + olvlog(LOG_TODO,"olv_limp_t","Rellenando info asociada a nw, %ld de %ld", + n+1,olv_limp->n_nw); + } + + ia++; + n++; + idd =dbf.leeNexRow(); + + } + if(nn_nw) + { + sprintf_s(err_str,OLV_MAX_ERR,"Error al leer record %ld en\n%s",ia,nfile); + ret=FALSE; + goto fin; + } + + olvlog(LOG_TODO,"olv_limp_t","Finaliza matriz de info asociada a carreteras: %ld doble sentido, %ld TF, %ld FT, %ld ninguno, %ld de %ld", + nboth,ntf,nft, nno, nboth+ntf+nft+nno, olv_limp->n_nw); + +fin: + if(sent) + free(sent); + + return ret; +} +//************************************************************************************* +/** + * Rellena la información de ancho de los ámbitos + * en la tabla de información asociada + */ +BOOL Colv_limp_thr::rellena_info_amb() +{ + Cb_file f; + Fdbf dbf; + int icampa,icampo,icampta,icampte,idd,ia, icampoid; + char *tipent, *tipap, *obs,*anc; + double ancho; + BOOL ret=TRUE,modo_ejes=FALSE; + int barr_mix=0; + char nfile[MAX_PATH]; + + //en principio, tipos puntuales no tienen info asociada + if(olv_limp->tipo_ambit==OLV_AMB_PUN) + return TRUE; + + //cuando se ha enviado eje de calle, no se lee info asociada porque la tabla es de tomotom, no tiene info + //tipo entidad ni nada.. + if((olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoMh_eje) || + (olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoM2h_eje)) + modo_ejes= TRUE; + + olvlog(LOG_TODO,"olv_limp_t","Rellenando matriz de info asociada a ámbitos"); + pon_mi_progre(OLV_TAREA_IMP, (int) (OliviaDef::GeneralDef::ProgrMax*2/3)); + + tipent=tipap=obs=anc=NULL; + + //lee dbf del shp + strcpy_s(nfile,MAX_PATH,olv->paths.path_data); + //cambiaext(nfile,".shp",".dbf"); + strcpy((Cdir_manager::extension_archivo(nfile)),"dbf"); + if(!f.abre(nfile,1) || !dbf.lee(&f)) + { + pon_mi_msg("Error al abrir %s",nfile); + ret=FALSE; + goto fin; + } + //busca el campo de observaciones, de ancho_tipo, de tipo_entidad y tipología_aparc + icampo=dbf.findCol(olv_limp->camps.campo_obs); + icampa=dbf.findCol(olv_limp->camps.campo_anch); + icampta=dbf.findCol(olv_limp->camps.campo_tipo_ap); + icampte=dbf.findCol(olv_limp->camps.campo_tipo_ent); + if(!modo_ejes && (icampa==-1 || icampo==-1 || icampta==-1 || icampte==-1)) + { + sprintf_s(err_str,OLV_MAX_ERR,"No encontrado campo %s y/o %s y/o %s\ny/o %s en\n%s",olv_limp->camps.campo_obs,olv_limp->camps.campo_anch, + olv_limp->camps.campo_tipo_ap,olv_limp->camps.campo_tipo_ent,nfile); + ret=FALSE; + goto fin; + } + icampoid=dbf.findCol(OLV_NOMB_OID); + + if(!modo_ejes) + { + tipent = (char*)malloc(dbf.getSize(icampte)+1); + tipap = (char*)malloc(dbf.getSize(icampta)+1); + obs = (char*)malloc(dbf.getSize(icampo)+1); + anc = (char*)malloc(dbf.getSize(icampa)+1); + if(!tipent || !tipap || !obs || !anc) + return FALSE; + } + + idd =dbf.leeNexRow(); + ia=0; + while(idd == 1) + { + if(!modo_ejes) + { + //si el campo tipo de entidad es banda_aparcamiento, el ancho es fijo, + //en función de la tipología del aparcamiento + //si no, hay que leer el ancho + ancho=OLV_LIMP_ANCH_DEF; + + /////////////////////////////// + strcpy(tipent,dbf.getStr(icampte)); + if(strlen(tipent)>0 && strcmp(tipent,olv_limp->camps.atr_tip_ent[OLV_ATR_NOM_TIP_ENT_AP])==0) + { + //es banda de aparcamiento + strcpy(tipap,dbf.getStr(icampta)); + if(strlen(tipap)>0 && strcmp(tipap,olv_limp->camps.atr_tip_apa[OLV_ATR_TIP_AP_LIN])==0) + { + //es aparcamiento lineal, ancho fijo 2 + ancho=olv_limp->anchos_def[OLV_ANCH_DEF_APLIN]; + } + else if(strlen(tipap)>0 && strcmp(tipap,olv_limp->camps.atr_tip_apa[OLV_ATR_TIP_AP_BAT])==0) + { + //es aparcamiento en batería, ancho fijo 4 + ancho=olv_limp->anchos_def[OLV_ANCH_DEF_APBAT]; + } + + //lo marca para saber si es barrido mixto + olv_limp->iaso[ia].flgs |= OLV_LIMP_FLG_AMB_APA; + if(!olv_limp->barr_mix && !(barr_mix & OLV_LIMP_FLG_AMB_APA)) + barr_mix |= OLV_LIMP_FLG_AMB_APA; + } + else if(strlen(tipent)>0 && strcmp(tipent,olv_limp->camps.atr_tip_ent[OLV_ATR_NOM_TIP_ENT_BORD])==0) + { + //es bordillo libre + ancho=olv_limp->anchos_def[OLV_ANCH_DEF_BORD]; + + //lo marca para saber si es barrido mixto + olv_limp->iaso[ia].flgs |= OLV_LIMP_FLG_AMB_BORD; + if(!olv_limp->barr_mix && !(barr_mix & OLV_LIMP_FLG_AMB_BORD)) + barr_mix |= OLV_LIMP_FLG_AMB_BORD; + } + else if(strlen(tipent)>0) + { + //es acera o peatonal + //hay que leer el ancho + strcpy(obs,dbf.getStr(icampo)); + strcpy(anc,dbf.getStr(icampa)); + + ancho = olv_limp->dame_ancho(obs,anc); + + if(strcmp(tipent,olv_limp->camps.atr_tip_ent[OLV_ATR_NOM_TIP_ENT_ACERA])==0) + { + if(ancho==0) + ancho=olv_limp->anchos_def[OLV_ANCH_DEF_ACE];//acera + + //lo marca para saber si es barrido mixto + olv_limp->iaso[ia].flgs |= OLV_LIMP_FLG_AMB_ACE; + if(!olv_limp->barr_mix && !(barr_mix & OLV_LIMP_FLG_AMB_ACE)) + barr_mix |= OLV_LIMP_FLG_AMB_ACE; + } + else if(strcmp(tipent,olv_limp->camps.atr_tip_ent[OLV_ATR_NOM_TIP_ENT_PEAT])==0) + { + if(ancho==0) + ancho=olv_limp->anchos_def[OLV_ANCH_DEF_PEAT];//peatonal + + olv_limp->iaso[ia].flgs |=OLV_LIMP_FLG_AMB_PEAT; + } + else + if(ancho==0) + ancho = OLV_LIMP_ANCH_DEF; + + } + olv_limp->iaso[ia].inf_l.ancho=ancho; + + /////////////////////////////// + //avisa de progreso + if((ia%100==0) || (ia==(olv_limp->n_amb-1))) + { + pon_mi_progre(OLV_TAREA_IMP, (int) (OliviaDef::GeneralDef::ProgrMax* + ((1.0*(ia+1)/olv_limp->n_amb)/3)+2/3)); + olvlog(LOG_TODO,"olv_limp_t","Rellenando info asociada a ámbitos, %ld de %ld", + ia+1,olv_limp->n_amb); + } + + if(!olv_limp->barr_mix) + olv_limp->barr_mix=(barr_mix & (OLV_LIMP_FLG_AMB_APA | OLV_LIMP_FLG_AMB_BORD)) && (barr_mix & OLV_LIMP_FLG_AMB_ACE); + } + if(icampoid>=0) + olv_limp->iaso[ia].oid = dbf.getI(icampoid); + + ia++; + idd =dbf.leeNexRow(); + } + + //olv_limp->barr_mix=FALSE; + + if(ian_amb) + { + sprintf_s(err_str,OLV_MAX_ERR,"Error al leer información asociada %ld en\n%s",ia,nfile); + ret=FALSE; + goto fin; + } + olvlog(LOG_TODO,"olv_limp_t","Finaliza Matriz de info asociada a ámbitos"); + +fin: + + if(tipent) + free(tipent); + if(tipap) + free(tipap); + if(obs) + free(obs); + if(anc) + free(anc); + + return ret; +} +//************************************************************************************* +/** + * Replica los ámbitos cuando son tipo peatonal, añadiendo otro lineal igual que tendrá solo coste + * de desplazamiento, no de tratamiento, más los segmentos que los unen, de coste 0 + */ +BOOL Colv_limp_thr::replica_peat() +{ + int i,j,k; + CartoBaseInfoEntity ient, ientcp; + CartoLine peatcp; + Info_aso2 info_aux; + double ptos[2][3]; + CartoLine ptos_aux; + ptos_aux.pts.n = 2; + ptos_aux.pts.ptr = ptos; + + olvlog(LOG_TODO,"olv_limp_t","Replicando calles peatonales"); + + peatcp.idPropsP =0; + for(i=0;in_amb; i++) + { + ient=olv_limp->carto.get(i); + if(!(olv_limp->iaso[ient.entity()->ref].flgs & OLV_LIMP_FLG_AMB_PEAT)) + continue; + + //Replica la peatonal + if(!ient.getCopy(&peatcp) || !olv_limp->carto.add(peatcp)) + break; + ientcp=olv_limp->carto.get(olv_limp->carto.getNumberEntities()-1); + + //Añade la info aso + info_aux.reset(); + info_aux.flgs=OLV_LIMP_FLG_PEAT_REP; + info_aux.refe=ientcp.entity()->ref; + info_aux.refe2=ient.entity()->ref; + olv_limp->iaso[info_aux.refe]=info_aux; + + //añade los dos extremos + for(j=0;j<2;j++) + { + for(k=0;k<2;k++) + { + memcpy(ptos[k],ient.getPto(j),3*sizeof(double)); + } + //lo añade al carto + olv_limp->carto.add(ptos_aux); + ientcp=olv_limp->carto.get(olv_limp->carto.getNumberEntities()-1); + //Añade la info aso + info_aux.reset(); + info_aux.flgs=OLV_LIMP_FLG_PEAT_SEG | (j*OLV_LIMP_FLG_FIN); + info_aux.refe=ientcp.entity()->ref; + info_aux.refe2=ient.entity()->ref; + olv_limp->iaso[info_aux.refe]=info_aux; + } + } + ptos_aux.pts.ptr = NULL; + if(in_amb) + return FALSE; + + return TRUE; +} +//************************************************************************************* +/** + * Replica las calles cuando son de doble sentido y se tienen en cuenta las restricciones + * de circulación, para que se asignen los ámbitos sólo a la calle del sentido en el que estén + */ +BOOL Colv_limp_thr::replica_doble_sent(Info_inw_dmin *inww_ord) +{ + int i,KK,iaux; + unsigned short refnw; + CartoBaseInfoEntity ientamb, ientcp, ientnw; + CartoLine nwcp; + Info_aso2 info_aux; + + if(olv_limp->res_circtipo_ambit; + nwcp.idPropsP=0; + + //recorre los ámbitos viendo a qué calle están asignados, y si es a una + //de doble sentido, se replica la calle y se pone cada una de un sentido, y se asigna + //el ámbito a la calle de la que esté a la derecha + //recorre el array de info nw + for(i=0;in_amb*KK;i++) + { + refnw=inww_ord[i].refnw; + if(!(olv_limp->iaso[refnw].flgs & OLV_LIMP_FLG_NW) || + (olv_limp->iaso[refnw].flgs & OLV_LIMP_FLG_CIRC_NO_DOB)) + continue; + + ientamb = olv_limp->carto.getRef(inww_ord[i].refamb); + ientnw = olv_limp->carto.getRef(refnw); + + //Replica la calle + if(!ientnw.getCopy(&nwcp) || !olv_limp->carto.add(nwcp)) + break; + ientcp=olv_limp->carto.get(olv_limp->carto.getNumberEntities()-1); + + //le pone a la calle original que es solo FT + olv_limp->iaso[refnw].flgs |= OLV_LIMP_FLG_CIRC_FT; + //Añade la info aso de la copia + info_aux.reset(); + info_aux.flgs=OLV_LIMP_FLG_NW | OLV_LIMP_FLG_NW_REP | OLV_LIMP_FLG_CIRC_TF; + info_aux.refe=ientcp.entity()->ref; + //copia la velo y el nombre + info_aux.inf_n.velo=olv_limp->iaso[refnw].inf_n.velo; + info_aux.inf_n.nomb = (char*)malloc(strlen(olv_limp->iaso[refnw].inf_n.nomb)+1); + if(!info_aux.inf_n.nomb) + break; + strcpy(info_aux.inf_n.nomb,olv_limp->iaso[refnw].inf_n.nomb); + info_aux.refe2=refnw; + //añade la info + olv_limp->iaso[info_aux.refe]=info_aux; + + ////////////////////////////////////////////// + //busca los ámbitos apuntados a ese nw, los que están a la izquiera les reapunta + iaux=i; + while((iauxn_amb*KK) && (inww_ord[iaux].refnw==refnw)) + { + if(!(olv_limp->iaso[inww_ord[iaux].refamb].flgs & OLV_LIMP_FLG_DER)) + { + inww_ord[iaux].refnw=info_aux.refe;//el lineal que acaba de añadir + //reapunta también el original + olv_limp->inww_amb[(int)inww_ord[iaux].alpha].refnw=info_aux.refe; + ///////////////////////////// + olv_limp->iaso[inww_ord[iaux].refamb].flgs |= OLV_LIMP_FLG_DER; + } + iaux++; + + } + i=iaux-1; + + } + if(in_amb*KK) + return FALSE; + + return TRUE; +} +//************************************************************************************* +/** + * Une la red navegable y los ámbitos + * 'soloi' es para debug, indica si se quiere realizar la unión de un único ámbito pasado en soloi + */ +BOOL Colv_limp_thr::une_amb_nw(int soloi) +{ + int KK,i,refamb,k; + CartoBaseInfoEntity iamb; + BOOL comp_lejos,modo_ejes=FALSE; + + comp_lejos=(olv_limp->res_circuds_tto!=OliviaDef::GeneralDef::OlvTipTtoMh_eje) && + (olv_limp->uds_tto!=OliviaDef::GeneralDef::OlvTipTtoM2h_eje)); + + + //si es tipo ejes, lo hace de otra forma + if((olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoMh_eje) || + (olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoM2h_eje)) + { + modo_ejes=TRUE; + } + ////////////////// + //coge el factor del tipo de ámbito, 1 si es puntual, 2 si es lineal + KK=olv_limp->tipo_ambit; + + ////////////////// + //replica las peatonales que sea necesario + if(KK==OLV_AMB_LIN) + { + if(!replica_peat()) + { + pon_mi_msg("Error al replicar peatonales"); + return FALSE; + } + } + + ////////////////// + //inicia cuando ya sabe si es tipo lineal o puntual + if(!olv_limp->inww_amb) + { + olv_limp->inww_amb = (Info_inw_dmin *)malloc(olv_limp->n_amb*KK*sizeof(Info_inw_dmin)); + } + if(!olv_limp->inww_amb) + { + pon_mi_msg("Error, sin memoria para matriz de índices\nde ámbitos a carreteras"); + return FALSE; + } + //rellena todos a no def + for(i=0;in_amb*KK;i++) + { + olv_limp->inww_amb[i].reset(i%olv_limp->n_amb); + } + /////////////////// + olvlog(LOG_TODO,"olv_limp_t","Uniendo ámbitos a NW"); + pon_mi_progre(OLV_TAREA_UNE_NW_AMB, 0); + pon_mi_msg(""); + err_str[0]=0; + + //Bucle por ámbito + for(i=0;in_amb && !pirate; i++) + { + if((soloi>-1) && (soloin_amb) && (i!=soloi)) + continue;//para debug, si soloi apunta al ámbito que queremos calcular solo + + iamb = olv_limp->carto.getEntity(i); + refamb=iamb.entity()->ref; + if(olv_limp->iaso[refamb].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + + //rellena en inww_amb el inw y su info de la carretera del nw élegida como + //más cercana al ámbito + if(modo_ejes) + busca_inw_dmin_ejes(i); + else + busca_inw_dmin(i); + + //////////////////////////////////////////// + //comprueba en todos los ámbitos si va andando, si están asignados a una carretera muy lejos + //y tienen un ámbito más cerca, les asigna ese (excepto en el caso ejes) + if(comp_lejos) + comprueba_amb_lejos(i); + + if((i%100==0) ||(i==(olv_limp->n_amb-1))) + { + olvlog(LOG_TODO,"olv_limp_t","Uniendo ámbitos a NW, %ld de %ld",i+1,olv_limp->n_amb); + //avisa de progreso + pon_mi_progre(OLV_TAREA_UNE_NW_AMB, (int) ((OliviaDef::GeneralDef::ProgrMax* + (i+1)/olv_limp->n_amb)*((olv_limp->tipo_ambit==OLV_AMB_LIN ? 0.5 : 1)))); + } + } + //cuida si ha salido antes por falta de memo + if(in_amb) + { + pon_mi_msg("Error en la unión de ámbitos a red navegable"); + return FALSE; + } + //Bucle por ámbito + for(i=0;in_amb && !pirate; i++) + { + if((soloi>-1) && (soloin_amb) && (i!=soloi)) + continue;//para debug, si soloi apunta al ámbito que queremos calcular solo + + iamb = olv_limp->carto.getEntity(i); + refamb=iamb.entity()->ref; + if(olv_limp->iaso[refamb].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + + //Añade los segmentos a clase NW_union + add_uniones_obj(i); + } + + //cuida si ha salido antes por falta de memo + if(in_amb) + { + pon_mi_msg("Error en la unión de ámbitos a red navegable"); + return FALSE; + } + + if(comp_lejos) //ojo + comprueba_aislados(olv_limp->inww_amb); + + ///////////////////////////////////////////////////// + //si hay algún ámbito asignado a una carretera de prohibido circular + //se le quita el flag a la carretera + if(olv_limp->res_circ!=OLV_RES_NO) + { + for(i=0;in_amb && !pirate; i++) + { + refamb=olv_limp->carto.getEntity(i).entity()->ref; + if(olv_limp->iaso[refamb].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + for(k=0; kiaso[olv_limp->inww_amb[i + k*olv_limp->n_amb].refnw].flgs & + OLV_LIMP_FLG_CIRC_NONE) + { + //le quita el flag + olv_limp->iaso[olv_limp->inww_amb[i + k*olv_limp->n_amb].refnw].flgs = + olv_limp->iaso[olv_limp->inww_amb[i + k*olv_limp->n_amb].refnw].flgs & ~OLV_LIMP_FLG_CIRC_NONE; + } + } + } + } + + return TRUE; +} +//************************************************************************************* +/** + * Como se ha podido unir unos ámbitos a otros, revisa que no se hayan unido sólo entre sí + * y no a ninguna carretera, en ese caso estarían aislados. Lo revisa para, en esos casos, + * forzar a que apunte alguno a una carretera + */ +void Colv_limp_thr::comprueba_aislados(Info_inw_dmin *inww) +{ + int i,KK,iamb,k,j, refamb; + BYTE *ambs_flgs; + int *ambs_cola; + int ncola; + BOOL aislado; + double dmin; + int iambmin; + +#define FLG_VISTO 1 +#define FLG_TEMP 2 + + KK=olv_limp->tipo_ambit; + //inicia el array de flags + ambs_flgs = (BYTE*)malloc(olv_limp->n_amb); + if(!ambs_flgs) + return; + memset(ambs_flgs,0,olv_limp->n_amb); + //inicia la cola + ambs_cola = (int*)malloc(olv_limp->n_amb*sizeof(int)); + if(!ambs_cola) + return; + memset(ambs_cola,0,olv_limp->n_amb*sizeof(int)); + ncola=0; + + //bucle para cada ámbito + for(i=0;in_amb && !pirate; i++) + { + if(ambs_flgs[i] & FLG_VISTO) + continue; + + refamb=olv_limp->carto.getEntity(i).entity()->ref; + if(olv_limp->iaso[refamb].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + aislado=TRUE; + //lo mete a la cola + ambs_cola[ncola]=i; + ncola=1; + + while (ncola) + { + //saca ámbito de la cola + ncola--; + iamb=ambs_cola[ncola]; + + //le pone el flag temporal + ambs_flgs[iamb] |= FLG_TEMP; + + //bucle en los dos extremos + for(k=0;kiaso[inww[iamb+k*olv_limp->n_amb].refnw].flgs & OLV_LIMP_FLG_NW)) + { + //lo mete en la cola si su extremo es un ámbito + //no visto ni temporal + if(ambs_flgs[inww[iamb+k*olv_limp->n_amb].refnw] & (FLG_TEMP | FLG_VISTO)) + continue; + ambs_cola[ncola]=inww[iamb+k*olv_limp->n_amb].refnw; + ncola++; + } + else + aislado=FALSE; + } + } + + if(aislado) + { + //es una aislada o grupo de aisladas, + //deja apuntada a una nw la de distancia menor + dmin=MAYUSCULO; + iambmin=-1; + for(j=0;jn_amb; j++) + { + if(!(ambs_flgs[j] & FLG_TEMP)) + continue; + + for(k=0;kn_amb].inw_old) + continue;//no debería + if(inww[j+k*olv_limp->n_amb].inw_old->dminn_amb; + dmin=inww[j+k*olv_limp->n_amb].inw_old->dmin; + } + } + } + if(dmin=0) + { + //reapunta a la inw old + memcpy(&inww[iambmin],inww[iambmin].inw_old,sizeof(Info_inw_dmin)); + free(inww[iambmin].inw_old); + inww[iambmin].inw_old=NULL; + + //añade el segmento de unión + add_uniones_obj(iambmin%olv_limp->n_amb); + } + } + + //todos los estudiados, que son los del flag temporal, los pone como vistos + for(j=0;jn_amb; j++) + { + if(ambs_flgs[j] & FLG_TEMP) + { + ambs_flgs[j] = ambs_flgs[j] & ~FLG_TEMP; + ambs_flgs[j] = ambs_flgs[j] | FLG_VISTO; //le quita el flag temporal y le pone el de visto + } + } + } + + free(ambs_flgs); + free(ambs_cola); +} +//************************************************************************************* +/** + * Comprueba en 'inww' si 'daux' es menor que las almacenadas. + * Devuelve la posición del array inww donde tiene que ir o -1 si no es menor + * y vacía dicha posición, moviendo las demás, para que el siguiente guarde ahí lo que toca + */ +int Colv_limp_thr::is_dmin(double daux, Info_inw_dmin *inww) +{ + int i=-1,k; + + if(!inww) + return i; + + for(i=0; i=i; k--) + { + memcpy(&inww[k+1], &inww[k],sizeof(Info_inw_dmin)); + } + break; + } + } + if(i>=OLV_LIMP_N_DMIN_NW) + i=-1; + + return i; +} +//************************************************************************************* +/** + * Devuelve la ent de la nw que esté más cerca del ámbito iamb, a la que se le asigna + */ +BOOL Colv_limp_thr::busca_inw_dmin_ejes(int i_amb) +{ + CartoBaseInfoEntity ientnw, ientamb; + int refamb, refenw,inw,z,npts,k; + //se recorre las nw buscando el mismo oid + ientamb=olv_limp->carto.getEntity(i_amb); + refamb=ientamb.entity()->ref; + npts=ientamb.getNumberPtos(); + //////////////////////////////////////////////////////////////////////// + //Bucle por cada carretera de la nw + //empiezan donde acaban los ámbitos, y terminan en namb+nnw + for(inw=olv_limp->n_amb; inwn_amb+olv_limp->n_nw && !pirate; inw++) + { + ientnw=olv_limp->carto.getEntity(inw); + refenw=ientnw.entity()->ref; + if(!(olv_limp->iaso[refenw].flgs & OLV_LIMP_FLG_NW)) + continue; //no debería, pero por si acaso + + if(olv_limp->iaso[refenw].oid==olv_limp->iaso[refamb].oid) + break; + } + if(inw>=olv_limp->n_amb+olv_limp->n_nw || pirate) + return FALSE; + + //ha encontrado la nw, la pone en inww + //para el punto inicial y final, o solo una vez si es puntual + for(k=0; k<2; k++) + { + z=i_amb+k*olv_limp->n_amb; + olv_limp->inww_amb[z].reset(); + olv_limp->inww_amb[z].refnw=refenw; + olv_limp->inww_amb[z].dmin=0; + olv_limp->inww_amb[z].ip=k*(npts-2); + olv_limp->inww_amb[z].lamb=(float)k; + memcpy(olv_limp->inww_amb[z].pt,ientamb.getPto(k*(npts-1)),3*sizeof(double)); + //copia info de qué amb y qué punto ini o fin es, para poder recuperar cuando está ordenador por inw + olv_limp->inww_amb[z].refamb=refamb; + olv_limp->inww_amb[z].alpha=(float)(z); + } + return TRUE; +} +//************************************************************************************* +/** + * Devuelve la distancia de un ámbito 'i_amb' a la carretera más cercana, + * y rellena la info de dicha carretera en inww_amb. + * KK indica el tipo de ámbito, si es 1 es puntual, sólo se calcula una distancia a la carretera, + * si es 2, es lineal, se calculan la distancia al extremo inicial y al final + */ +BOOL Colv_limp_thr::busca_inw_dmin(int i_amb) +{ + Info_inw_dmin inwaux, inww[OLV_LIMP_N_DMIN_NW*2]; //Almacena las N mejores carreteras del punto inicial y las N del punto final + CartoLine prime_ptos_i, prime_ptos_f, prime_ptos, ptos_aux; + double lon, disptos, daux, alphamin[2], desv,lamb; + int i, inw, refenw,k,i_inww,j,jmin[2],i_nw,KK,refamb,ip; + CartoBaseInfoEntity ientnw, ientamb; + double pt_ang[2][3], *p0, *p1, prod, mod1, mod2; //almacena dos puntos para calcular el vector con el que forma el ángulo el ámbito + + //////////////////////////// + //esto se hace porque se sabe que son siempre 2 puntos, y así no se pide memoria + //dinámica en el garray + ptos_aux.pts.n = 2; + ptos_aux.pts.ptr =pt_ang; + //////////////////////////// + ientamb=olv_limp->carto.getEntity(i_amb); + refamb=ientamb.entity()->ref; + KK=olv_limp->tipo_ambit; + + + + //inicializa array local para almacenamiento de las tres carreteras más cercanas + memset(inww,0,sizeof(Info_inw_dmin)*OLV_LIMP_N_DMIN_NW*2); + for(i=0; in_amb; inwn_amb+olv_limp->n_nw && !pirate; inw++) + { + ientnw=olv_limp->carto.getEntity(inw); + refenw=ientnw.entity()->ref; + if(!(olv_limp->iaso[refenw].flgs & OLV_LIMP_FLG_NW)) + continue; //no debería, pero por si acaso + + //lo hace para punto inicial y final si es lineal, o solo una vez si es puntual + for(k=0; kpts,&ip, &lamb); + } + + inwaux.ip=(short)ip; + inwaux.lamb=(float)lamb; + + i_inww=is_dmin(daux,&inww[k*OLV_LIMP_N_DMIN_NW]); + if(i_inww>=0) + { + //Dist ptos-recta. Si dist mayor que la mínima guardada, descarta. + // Si todas dist similares y menores que una dada, se guarda + //inw->linea de la nw + inww[i_inww+k*OLV_LIMP_N_DMIN_NW].dmin=(float)daux; + inww[i_inww+k*OLV_LIMP_N_DMIN_NW].refnw=inwaux.refnw; + inww[i_inww+k*OLV_LIMP_N_DMIN_NW].ip = inwaux.ip; + inww[i_inww+k*OLV_LIMP_N_DMIN_NW].lamb=inwaux.lamb; + inww[i_inww+k*OLV_LIMP_N_DMIN_NW].pt[0]=inww[i_inww+k*OLV_LIMP_N_DMIN_NW].pt[1]= + inww[i_inww+k*OLV_LIMP_N_DMIN_NW].pt[2]=0; + } + } + } + //////////////////////////////////////////////////////////////////////// + //coger de los tres de inww el que del punto ip de nw al extremo de amb forme el ángulo + //cuya diferencia con pi/2 sea menor (en el caso lineal) + //y ponerlo en inww_amb[i-olv_limp->n_ini_amb] + jmin[0]=jmin[1]=0; + alphamin[0]=alphamin[1]=MAYUSCULO; + for(j=0;j=OLV_LIMP_AMB_NW_NODEF)) //por si acaso + continue; + + ientnw=olv_limp->carto.getRef(i_nw); + + //calcula el punto del inw donde se da el mínimo + p0=ientnw.getPto(inww[j+k*OLV_LIMP_N_DMIN_NW].ip); + p1=ientnw.getPto(inww[j+k*OLV_LIMP_N_DMIN_NW].ip+1); + inww[j+k*OLV_LIMP_N_DMIN_NW].pt[2]=0; + inww[j+k*OLV_LIMP_N_DMIN_NW].pt[0]=p0[0]+(p1[0]-p0[0])*inww[j+k*OLV_LIMP_N_DMIN_NW].lamb; + inww[j+k*OLV_LIMP_N_DMIN_NW].pt[1]=p0[1]+(p1[1]-p0[1])*inww[j+k*OLV_LIMP_N_DMIN_NW].lamb; + + //solo para tipo lineal, elige el de distancia menor y que el ángulo que forma el ámbito con + //el punto más cercano de la nw sea el más ortogonal + if(KK==OLV_AMB_LIN) + { + if(k==0) + prime_ptos = prime_ptos_i; + else + prime_ptos = prime_ptos_f; + //el ángulo se calcula entre el extremo del ámbito con el vector que forman dicho extremo del + //ámbito con el punto del inw donde se da el mínimo + pt_ang[0][0] = prime_ptos.getPto(0)[0]; + pt_ang[0][1] = prime_ptos.getPto(0)[1]; + pt_ang[0][2] = prime_ptos.getPto(0)[2]; + pt_ang[1][0] = inww[j+k*OLV_LIMP_N_DMIN_NW].pt[0]; + pt_ang[1][1] = inww[j+k*OLV_LIMP_N_DMIN_NW].pt[1]; + pt_ang[1][2] = inww[j+k*OLV_LIMP_N_DMIN_NW].pt[2]; + + prod=GeometryFunction::ProdEscalar(&prime_ptos,&ptos_aux); + mod1=GeometryFunction::Dist2d(prime_ptos.getPto(0), prime_ptos.getPto(1)); + mod2=GeometryFunction::Dist2d(pt_ang[0],pt_ang[1]); + inww[j+k*OLV_LIMP_N_DMIN_NW].alpha=(float)fabs(prod/(mod1*mod2)); + } + } + } + if(pirate) + goto fin; + + if(KK==OLV_AMB_LIN) + { + //únicamente si el segundo más cercano (el de la pos '1') tiene alpha menor, y una distancia no mucho mayor + //lo coge, + //si no, se queda el más cercano + for(k=0; kres_circ!=OLV_RES_NO) + { + //si hay restricciones de circulación, y se va a coger como dmin una carretera peatonal, coge la siguiente de dmin + for(k=0; kiaso[inww[k*OLV_LIMP_N_DMIN_NW].refnw].flgs & OLV_LIMP_FLG_CIRC_NONE) && + !(olv_limp->iaso[inww[1+k*OLV_LIMP_N_DMIN_NW].refnw].flgs & OLV_LIMP_FLG_CIRC_NONE)) + jmin[k]=1; + } + } + + //copia el mínimo que ha encontrado + //para el punto inicial y final, o solo una vez si es puntual + for(k=0; kinww_amb[i_amb+k*olv_limp->n_amb],&inww[jmin[k]+k*OLV_LIMP_N_DMIN_NW],sizeof(Info_inw_dmin)); + //copia info de qué amb y qué punto ini o fin es, para poder recuperar cuando está ordenador por inw + olv_limp->inww_amb[i_amb+k*olv_limp->n_amb].refamb=refamb; + olv_limp->inww_amb[i_amb+k*olv_limp->n_amb].alpha=(float)(i_amb+k*olv_limp->n_amb); + } +fin: + prime_ptos.pts.ptr = NULL; + ptos_aux.pts.ptr = NULL; + return TRUE; +} +//************************************************************************************* +/** + * Dado un ámbito 'i_amb' (ya relativo al n_ini_amb) de un total de n_amb, + * de 'npt_amb' puntos almacenados en 'pt_amb', + * añade al 'ob' las uniones del mismo con la carretera 'pt_nw' + * de los dos extremos si es lineal o uno si es puntual, indicado por 'KK' + */ +void Colv_limp_thr::add_uniones_obj(int i_amb) +{ + double ptos[2][3]; + int refamb,nptos,KK, refnw,npt_amb; + CartoBaseInfoEntity ientamb,ientnw,ientseg; + CartoLine ptos_aux; + INT64 ff; + Info_aso2 info_aux; + BOOL ya=TRUE; + Info_inw_dmin *inww; + + //////////////////////////// + //esto se hace porque se sabe que son siempre 2 puntos, y así no se pide memoria + //dinámica en el garray + ptos_aux.pts.n = 2; + ptos_aux.pts.ptr = ptos; + //////////////////////////// + ientamb=olv_limp->carto.getEntity(i_amb); + refamb=ientamb.entity()->ref; + KK=olv_limp->tipo_ambit; + nptos=2; //siempre añade segmentos + + //poner el flag de segmento, si es eje, refe2... si es lin o pun, si es fin... + if(KK==OLV_AMB_LIN) + ff=OLV_LIMP_FLG_SEG_LIN; + else + ff=OLV_LIMP_FLG_SEG_PUN; + if(olv_limp->iaso[refamb].flgs & OLV_LIMP_FLG_EJE) + ff|=OLV_LIMP_FLG_EJE_SEG; + + ////////////////////////// + for(int k=0; kinww_amb[i_amb+k*olv_limp->n_amb]; + ya=TRUE; + do + { + //apunta al nw más cercano del ámbito actual que se acaba de encontrar + refnw=inww->refnw; + if(refnw<0 || refnw>=(olv_limp->n_nw+olv_limp->n_amb) || (refnw==i_amb)) //por si acaso + continue; + ientnw = olv_limp->carto.getRef(refnw); + + //apunta el array de puntos al ámbito + if(KK==OLV_AMB_LIN)//para tipo lineal, obtiene los primeros puntos de los dos extremos + { + npt_amb = ientamb.getNumberPtos(); + } + else if(KK==OLV_AMB_PUN) //para tipo puntual, es un único punto + { + npt_amb = 1; + } + + if(olv_limp->iaso[refnw].flgs & OLV_LIMP_FLG_AMB) + ff |= OLV_LIMP_FLG_DER | OLV_LIMP_FLG_SEG_AMB; + else if(olv_limp->iaso[refnw].flgs & OLV_LIMP_FLG_NW) + { + if((GeometryFunction::IsDer(&ientnw, ientamb.getPto((npt_amb-1)*k),inww->ip, inww->ip+1))) + { + if(!(olv_limp->iaso[refnw].flgs & OLV_LIMP_FLG_CIRC_TF)) + { + ff |= OLV_LIMP_FLG_DER; //FT o both + olv_limp->iaso[refamb].flgs |= OLV_LIMP_FLG_DER; + } + } + else if(olv_limp->iaso[refnw].flgs & OLV_LIMP_FLG_CIRC_TF) + { + ff |= OLV_LIMP_FLG_DER; //TF + olv_limp->iaso[refamb].flgs |= OLV_LIMP_FLG_DER; + } + } + if(k==OLV_AMB_LIN-1) + ff|=OLV_LIMP_FLG_FIN; + + //rellena el segmento + //el primer punto es el de la carretera más cercano al ámbito + memcpy(ptos[0],inww->pt,3*sizeof(double)); + //el segundo punto es el propio del ámbito (inicio y final si es lineal) + memcpy(ptos[1],ientamb.getPto((npt_amb-1)*k),3*sizeof(double)); + //lo añade al carto + olv_limp->carto.add(ptos_aux); + + ientseg=olv_limp->carto.getEntity(olv_limp->carto.getNumberEntities()-1); + //Añade la info aso + info_aux.reset(); + info_aux.flgs=ff; + info_aux.refe=ientseg.entity()->ref; + info_aux.refe2=ientamb.entity()->ref; + olv_limp->iaso[info_aux.refe]=info_aux; + + if(inww->inw_old)//ojo + { + if(inww->inw_old->dmininw_old;//añade las uniones a la nw y a los cercanos siempre! + ya=FALSE; + } + else + ya=TRUE; + } + else + ya=TRUE; + } while (!ya); + } + ptos_aux.pts.ptr = NULL; +} +//************************************************************************************* +/** + * Comprueba si el segmento corta a otro ámbito (en tratamientos lineales) + * si lo corta, apunta el primer punto del segmento al punto extremo más cercano + * de dicho ámbito al ámbito ppal + */ +void Colv_limp_thr::compr_cortes_amb() +{ + olvlog(LOG_TODO,"olv_limp_t","Comprobando cortes entre uniones y ámbitos"); + pon_mi_progre(OLV_TAREA_COST_AMB, 0); + pon_mi_msg("Comprobando cortes entre uniones y ámbitos"); + err_str[0]=0; + //lanza los threads + lanza_subthrs(OLV_LIMP_EV_COMPCORT_SUB,1); +} +//************************************************************************************* +/** + * Función de los subthreads + */ +void Colv_limp_thr::compr_cortes_amb_sub(int ithr) +{ + int na_ini,na_fin,na_desp,na; + int KK, seg; + Param_olv_limp_thr pp; + + CartoBaseInfoEntity ient_na, ient_i, ient_ia; + int ref_na, ref_i, ref_ia, isg,nent; + int iamb2,npt_amb2,ip,h; + double dist,lamb,*pt_amb2,lambs,distseg; + + //////////////// + pp.id_e=OLV_TAREA_COST_AMB;//manda de parámetro la tarea de la que es el progreso + KK=olv_limp->tipo_ambit; + na_desp = (int)ceil(1.0*(olv_limp->n_amb)/n_subthr); + na_ini=ithr*na_desp; + na_fin = min((ithr+1)*na_desp,olv_limp->n_amb); + //////////////// + + olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Ambs %04d a %04d", ithr,na_ini, na_fin); + + seg = GetTickCount(); + ///////////////////////////////////// + //Bucle por cada ámbito de los que le tocan a este thread + ///////////////////////////////////// + na=na_ini; + nent=olv_limp->carto.getNumberEntities(); + + ///////////////////////////////////// + for(na=na_ini;nacarto.get(na); + ref_na=ient_na.entity()->ref; + //revisa si la unión de este ámbito con la carretera interseca con otro ámbito + for(isg=olv_limp->n_amb+olv_limp->n_nw;isgcarto.get(isg); + if(ient_i.entity()->type!=CartoBaseTypes::Line) + continue; + + ref_i=ient_i.entity()->ref; + + if(!(olv_limp->iaso[ref_i].flgs & OLV_LIMP_FLG_SEG_LIN) || olv_limp->iaso[ref_i].refe2!=ref_na || + (olv_limp->iaso[ref_i].flgs & OLV_LIMP_FLG_SEG_AMB)) + continue; + + //ha encontrado el segmento inicial del ámbito, comprueba si corta con algún otro ámbito + //recorre de nuevo los ámbitos, esta vez todos + for(iamb2=0;iamb2n_amb;iamb2++) + { + if(iamb2==na) + continue; + + ient_ia=olv_limp->carto.get(iamb2); + ref_ia=ient_ia.entity()->ref; + if(olv_limp->iaso[ref_ia].refe2==ref_na || olv_limp->iaso[ref_na].refe2==ref_ia) + continue; + dist=ient_ia.DplineSeg(ient_i.getPto(0), ient_i.getPto(1),&ip, &lamb,&lambs); + if(dist>=OLV_DIF_MAX_MISMA_COOR || (lambs<=0.1) || (lambs>=0.9)) + continue;//no intersecan + + //intersecan + //apunta el primer ámbito al extremo más cercano del otro ámbito + //mira cuál es el extremo más cercano + npt_amb2 = ient_ia.getNumberPtos(); + //pt_amb2=ient_ia.PtInLine(ip, lamb,pt_aux); + //renombra pt_amb2 al extremo al que esta mas cerca + if((ip+lamb)>=((npt_amb2-1)/2)) + { + //extremo final + h=1; + } + else + { + //extremo inicial + h=0; + } + pt_amb2=ient_ia.getPto((npt_amb2-1)*h); + //calcula distancia del ámbito a ientamb2 + dist=GeometryFunction::Dist2d(ient_i.getPto(1),pt_amb2);//el segundo punto de la unión es el punto del ámbito + distseg=ient_i.getLong();//la longitud del segmento que lo unía con la carretera + if(dist<1.5*distseg && distencola(OLV_LIMP_EV_SUBTHR_PROG,&pp,FALSE); + } + } + olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Fin comprobación cortes entre uniones y ambs, %.3f seg", ithr, 1.0*(GetTickCount()-seg)/1000); + thr_padre->encola(OLV_LIMP_EV_COMPCORT_FIN,NULL,FALSE); +} +//************************************************************************************* +/** + * Función final + */ +BOOL Colv_limp_thr::compr_cortes_amb_sub_fin() +{ + //para los threads + para_subthrs(); + + return TRUE; +} +//************************************************************************************* +/** + * Comprueba, si es ámbito, si la carretera está muy lejos. + * Si es que sí, o bien busca otro ámbito más cercano, o lo deja vacío + */ +void Colv_limp_thr::comprueba_amb_lejos(int i_amb ) +{ + int i,k,h, iaux,is_fin,npt_amb_min, lejos; + double dist_aux,dist_aux2,dmin,dmax,longmax; + double *pt_amb_min; + BOOL ya_ini; + BOOL modo_solouno; + BOOL modo_unolibre; + Info_inw_dmin *inwaux=NULL; + int KK,refamb,refamb2,npt_amb,npt_amb2; + CartoBaseInfoEntity ientamb,ientamb2; + double *pt_amb, *pt_amb2; + BOOL guarda_nw_old; + + /*double lamb, pt_aux[3]; + int ip;*/ + + //////////////////////// + KK=olv_limp->tipo_ambit; + dmax=OLV_DIST_MAX_AMB_NW;// m de separación max entre peatonal y calle + /////////////////////// + ientamb=olv_limp->carto.getEntity(i_amb); + refamb=ientamb.entity()->ref; + npt_amb=ientamb.getNumberPtos(); + /////////////////////// + + ya_ini=FALSE; + modo_unolibre=(olv_limp->iaso[refamb].flgs & OLV_LIMP_FLG_AMB_PEAT); //Solo para las peatonales permite dejar un lado sin apuntar + modo_solouno=FALSE; + lejos=0; + longmax=dmax; + if(modo_unolibre) + longmax=ientamb.getLong(); + //Calcula la distancia del principio y del final a la nw + for(k=0;kinww_amb[i_amb+k*olv_limp->n_amb].pt); + guarda_nw_old=TRUE; + + + //if(dist_aux2n_amb; i++) + { + if(i==i_amb) + continue; + + ientamb2=olv_limp->carto.getEntity(i); + refamb2=ientamb2.entity()->ref; + + if(olv_limp->iaso[refamb2].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + + if(KK==OLV_AMB_LIN)//para tipo lineal, obtiene los primeros puntos de los dos extremos + { + npt_amb2 = ientamb2.getNumberPtos(); + + } + else if(KK==OLV_AMB_PUN) //para tipo puntual, es un único punto + { + npt_amb2 = 1; + } + for(h=0;h=((npt_amb2-1)/2)) + { + //extremo final + h=1; + } + else + { + //extremo inicial + h=0; + } + pt_amb2=ientamb2.getPto((npt_amb2-1)*h); + + } + else if(KK==OLV_AMB_PUN) //para tipo puntual, es un unico punto + { + npt_amb2 = 1; + pt_amb2 = ientamb2.getPto(0); + dist_aux=GeometryFunction::Dist2d(pt_amb, pt_amb2); + h=0; + } + + if(dist_auxinww_amb[iaux+is_fin*olv_limp->n_amb].refnw==i_amb) && + olv_limp->inww_amb[iaux+is_fin*olv_limp->n_amb].inw_old) + { + //si sí, comprueba cuál de los dos tiene la nw a menos distancia + //ese lo apunta a la nw y el otro al ámbito cercano + if(olv_limp->inww_amb[iaux+is_fin*olv_limp->n_amb].inw_old->dmin< + olv_limp->inww_amb[i_amb+k*olv_limp->n_amb].dmin) + { + + if(olv_limp->inww_amb[iaux+is_fin*olv_limp->n_amb].inw_old->dmininww_amb[iaux+is_fin*olv_limp->n_amb].inw_old; + memcpy(&olv_limp->inww_amb[iaux+is_fin*olv_limp->n_amb],inwaux,sizeof(Info_inw_dmin)); + //libera el old + free(olv_limp->inww_amb[iaux+is_fin*olv_limp->n_amb].inw_old); + olv_limp->inww_amb[iaux+is_fin*olv_limp->n_amb].inw_old=NULL; + } + //si es mayor que dmax, el anterior se queda como está, y este pone de ppal al ámbito y no guarda old + //indica que no guarde de este el old porque solo va a coger de ppal al ámbito + guarda_nw_old=FALSE; + } + else + { + //es éste el que está más cerca + //al otro le borra el old + free(olv_limp->inww_amb[iaux+is_fin*olv_limp->n_amb].inw_old); + olv_limp->inww_amb[iaux+is_fin*olv_limp->n_amb].inw_old=NULL; + if(olv_limp->inww_amb[i_amb+k*olv_limp->n_amb].dmininww_amb[i_amb+k*olv_limp->n_amb],sizeof(Info_inw_dmin)); + olv_limp->inww_amb[i_amb+k*olv_limp->n_amb].inw_old = inwaux; + } + + //copia en la principal la nueva info + inwaux=&olv_limp->inww_amb[i_amb+k*olv_limp->n_amb]; + //////////////////////////////////////////// + inwaux->dmin = (float)dmin; + inwaux->refnw = iaux; + inwaux->ip = (npt_amb_min-1)*is_fin; + inwaux->lamb = 0; + memcpy(inwaux->pt,pt_amb_min,3*sizeof(double)); + ya_ini=TRUE; + } + else if((dmin>longmax) && !modo_solouno) + { + //si está todavía más lejos, lo apunta a su principio + lejos|=1<inww_amb[i_amb].refnw = refamb; + olv_limp->inww_amb[i_amb].ip =0; + memcpy(olv_limp->inww_amb[i_amb].pt,ientamb.getPto(olv_limp->inww_amb[i_amb].ip),3*sizeof(double)); + } + else if(lejos & (1<<0)) + { + //si ha dejado sólo el segundo + olv_limp->inww_amb[i_amb+olv_limp->n_amb].refnw = refamb; + olv_limp->inww_amb[i_amb+olv_limp->n_amb].ip = npt_amb-1; + memcpy(olv_limp->inww_amb[i_amb+olv_limp->n_amb].pt,ientamb.getPto(olv_limp->inww_amb[i_amb+olv_limp->n_amb].ip),3*sizeof(double)); + } +} +//************************************************************************************* +/** + * Comprueba si hay ámbitos a un lado que se supone deberían estar al otro + */ +BOOL Colv_limp_thr::comprueba_latelaridad() +{ + int sent,id; + BOOL sigue_msg=TRUE; + + if(olv_limp->res_circlateral<=0) + return TRUE; + + char msg_[OLV_MAX_MSG_PROCE]; + char nfile[MAX_PATH]; + + strcpy_s(nfile,MAX_PATH,olv->paths.path_data); + //cambiaext(nfile,".shp",".dbf"); + strcpy((Cdir_manager::extension_archivo(nfile)),"dbf"); + + msg_[0]=0; + + ///////////////////LATERALIDAD + //recorres inww_amb_aux, que está ordenado por inw + //solo en puntuales + //si res_cirobjt)[inww_amb_aux[i].inw].ia].flgs & OLV_LIMP_FLG_CIRC_FT //fronto mismo sentido que lineal + //si lateral==derecha y amb a la izquierda, descarta + //amb -> ias[inww_amb_aux[ì].iamb].flgs & OLV_LIMP_FLG_DER + //o si lateral==izda y amb a la derecga, descarta + + for(int ia=0; ian_amb; ia++) + { + sent=0; + if(olv_limp->iaso[olv_limp->inww_amb[ia].refnw].flgs & OLV_LIMP_FLG_CIRC_FT ) + sent++; + if(olv_limp->iaso[olv_limp->inww_amb[ia].refnw].flgs & OLV_LIMP_FLG_CIRC_TF ) + sent++; + if(sent!=1) + continue; + //comprueba lateralidad + if(olv_limp->iaso[olv_limp->inww_amb[ia].refamb].flgs & OLV_LIMP_FLG_DER)//ambito a la derecha + { + if(olv_limp->lateral==1) //lateralidad derecha + continue; + } + else//ambito a la izquierda + { + if(olv_limp->lateral==2) //lateralidad izquierda + continue; + } + + //lee el objectid del ámbito + id=olv_limp->iaso[olv_limp->inww_amb[ia].refamb].oid; + olvlog(LOG_TODO,"olv_limp_t","Ámbito %ld lateralidad errónea",olv_limp->iaso[olv_limp->inww_amb[ia].refamb].oid); + + //imprime + if(msg_[0]==0) + sprintf_s(msg_,OLV_MAX_MSG_PROCE,"Encontrados contenedores con lateralidad errónea: "); + if(sigue_msg) + sprintf_s(msg_,OLV_MAX_MSG_PROCE,"%s %ld,",msg_,id); + if(sigue_msg && strlen(msg_)+10>=OLV_MAX_MSG_PROCE) + sigue_msg=FALSE;//para que no se pase del largo + + } + if(!sigue_msg && ((strlen(msg_)+5)tipo_ambit; + mal=FALSE; + nwcp.idPropsP=0; + ///////////////// + + ///////////////// + olvlog(LOG_TODO,"olv_limp_t","Generando topología con los segmentos de unión"); + pon_mi_progre(OLV_TAREA_TOPO_NW, 0); + pon_mi_msg(""); + err_str[0]=0; + + int ent1=olv_limp->carto.getNumberEntities(); + + //inicializa la matriz auxiliar para ordenación + inww_amb_aux = (Info_inw_dmin *)malloc(olv_limp->n_amb*KK*sizeof(Info_inw_dmin)); + if(!inww_amb_aux) + { + pon_mi_msg("Error, sin memoria para matriz de índices\nde ámbitos a carreteras"); + return FALSE; + } + memcpy(inww_amb_aux,olv_limp->inww_amb,olv_limp->n_amb*KK*sizeof(Info_inw_dmin)); + ////////////////////////////////////////////////// + //ordena la matriz de info de inw, va de punto más cercano + //al inicio del inw inicial al más lejano, y aumentando en inw + //dentro del mismo inw, ordena por ip y a igual ip, por lamb + qsort(inww_amb_aux,olv_limp->n_amb*KK,sizeof(Info_inw_dmin),Colv_limp_thr::compara_inww_amb); + + olvlog(LOG_TODO,"olv_limp_t","Generando topología: Matriz de info de inw dmin ordenada"); + + ////////////////////// + //mira a ver si tiene que replicar calles de doble sentido + if(!replica_doble_sent(inww_amb_aux)) + { + pon_mi_msg("Errores al replicar doble sentido"); + return FALSE; + } + //hay que volver a ordenar por si se ha modificado algo al replicar + qsort(inww_amb_aux,olv_limp->n_amb*KK,sizeof(Info_inw_dmin),Colv_limp_thr::compara_inww_amb); + + //////////////////// + if(KK<2)//en recogida, se mira si hay que comprobar la lateralidad + comprueba_latelaridad(); + + /////////////////////////////////////////////////////////////////////// + //Bucle por cada item del array inww_amb, para ir troceando las carreteras que cortan + ia=0; + while(ian_amb*KK && !pirate) + { + + /////////////////////////////// + ia_aux=ia; + refnw=inww_amb_aux[ia_aux].refnw; + + if(olv_limp->iaso[inww_amb_aux[ia_aux].refamb].flgs & OLV_LIMP_FLG_AMB_NO) + { + ia++; + continue; + } + if(!(olv_limp->iaso[refnw].flgs & OLV_LIMP_FLG_NW)) //es que se ha reapuntado a otro ámbito por ser peatonal lejana + { + ia++; + continue; + } + ientnw=olv_limp->carto.getRef(refnw); + npt_nw=ientnw.getNumberPtos(); + memcpy(&info_aux,&olv_limp->iaso[refnw],sizeof(Info_aso2)); + + iat=ia; + nt=1; + //primero cuenta los tramos de esa inwi, nt + while((ian_amb*KK) && (inww_amb_aux[ia].refnw==refnw)) + { + ia++; + nt++; + } + + if(nt<2) //tiene que haber siempre mínimo 2 tramos, ya que en todos los inw de este array hay algún ámbito asignado + { + olvlog(LOG_TODO,"olv_limp_t","Gen. Topo. Inw %03d mal, se obtienen %ld tramos, no suficientes",refnw,nt); + mal=TRUE; + ia++; + continue; + } + + //ya se saben los tramos, se va troceando la carretera + ia=iat; + iat=0; + inww_amb_aux[ia].flgs=0; + while(iat0 && inww_amb_aux[ia-1].flgs>1) + olv_limp->inww_amb[(int)inww_amb_aux[ia-1].alpha].refnw=info_aux.refe; + + //recorre la carretera inwi y la parte en trozos acorde a los ámbitos + if(iat==0)//hace el primer tramo, del extremo inicial al primer ámbito + { + npt_nw_aux=inww_amb_aux[ia].ip+2; + if(Colv_geom::pto_equals(ientnw.getPto(0), inww_amb_aux[ia].pt)) + { + //no se hace tramo porque está unido por el extremo + iat++; + ia++; + if(nt==2) + { + iat++;//si solo eran dos tramos, pasa + ia++; + } + continue; + } + //los primeros puntos son los de la carretera hasta el ámbito + for(pp=0;ppcarto.add(ptos_aux); + info_aux.refe=olv_limp->carto.get(olv_limp->carto.getNumberEntities()-1).entity()->ref; + if(olv_limp->iaso[refnw].inf_n.nomb) + { + info_aux.inf_n.nomb = (char*)malloc(strlen(olv_limp->iaso[refnw].inf_n.nomb)+1); + strcpy(info_aux.inf_n.nomb,olv_limp->iaso[refnw].inf_n.nomb); + } + olv_limp->iaso[info_aux.refe]=info_aux; + + iat++; + ia++; + } + + + + if((ia%100==0) || (ia==(olv_limp->n_amb*KK))) + { + olvlog(LOG_TODO,"olv_limp_t","Generando topología, %ld de %ld",ia,olv_limp->n_amb*KK); + //avisa de progreso + pon_mi_progre(OLV_TAREA_TOPO_NW, (int) ((OliviaDef::GeneralDef::ProgrMax* + 1.0*(ia)/(olv_limp->n_amb*KK)))); + } + ia--; //decrementa para cuando se ha pasado + } + info_aux.inf_n.nomb = NULL; + if(mal) + { + pon_mi_msg("Errores en el análisis topológico"); + } + if(mal || pirate) + { + if(inww_amb_aux) + free(inww_amb_aux); + return FALSE; + } + + int ia_old; + ia=ia_old=0; + while(ian_amb*KK) + { + refnw=inww_amb_aux[ia].refnw; + if(olv_limp->iaso[inww_amb_aux[ia].refamb].flgs & OLV_LIMP_FLG_AMB_NO) + { + ia++; + continue; + } + if((refnw<0) || (refnwn_amb) || (inww_amb_aux[ia].flgs<2)) //si al final no ha hecho tramos + { + ia++; + continue; + } + + //marca para borrar calle + olv_limp->carto.removeRef(refnw); + + //avanza hasta el siguiente inwi + while((ian_amb*KK) && (inww_amb_aux[ia].refnw==refnw)) + { + ia++; + } + + } + + //hace limpieza de la carto + olv_limp->carto.FastClear(); + + if(inww_amb_aux) + free(inww_amb_aux); + + if(!pon_nodos_planta(olv_limp->coor_instal)) + { + pon_mi_msg("Error, No se ha podido incluir planta en red"); + return FALSE; + } + + //hace limpieza de la carto, ya que ha terminado de hacer topología o añadir cosas + olv_limp->carto.FastClear(); + + //olv_limp->carto.linesExportShp("C:\\Proyectos\\Olivia\\Instal\\topo.shp"); + + return TRUE; +} +//************************************************************************************* +/** + * Compara las estructuras inww_amb. Las ordena por inw, a mismo inw por ip, y a mismo ip por lamb + */ +int Colv_limp_thr::compara_inww_amb (const void * a, const void * b) +{ + //si arefnw - ((Info_inw_dmin*) b)->refnw; + if(r==0) + { + //a mismo inw, es menor el de menor ip + r=((Info_inw_dmin*) a)->ip - ((Info_inw_dmin*) b)->ip; + if(r==0) + { + //a mismo ip, es menor el de menor lamb + dd=((Info_inw_dmin*) a)->lamb - ((Info_inw_dmin*) b)->lamb; + if(dd<0) + r=-1; + else if(dd>0) + r=1; + else + r=0; + } + } + + return r; +} +//************************************************************************************* +/** + * Añade a la red de conjunciones en qué conjunción está la planta y la instalación + */ +BOOL Colv_limp_thr::pon_nodos_planta(double pt[3]) +{ + int i, nent, refent,ip; + double dmin,d,lamb,pt_proy_nw[3],*pt_ip,*pt_ip1; + CartoBaseInfoEntity ientnw; + CartoLine lines[2]; + Info_inw_dmin inww; + Info_aso2 info_aux; + + if((pt[0]==0) && (pt[1]==0)) + return TRUE;//no hay instalación, no se pone + + //////////////////////////////////////////////////////////////////////// + //Bucle por cada carretera de la nw + dmin=DBL_MAX; + nent=olv_limp->carto.getNumberEntities(); + inww.reset(); + for(i=0; icarto.get(i).entity()->type!=CartoBaseTypes::Line) + continue; + + refent=olv_limp->carto.get(i).entity()->ref; + if(!(olv_limp->iaso[refent].flgs & OLV_LIMP_FLG_NW)) + continue; + + ientnw=olv_limp->carto.get(i); + + //calcula la distancia al punto de la instalación + d = ientnw.DisPtoLine(pt,&ip,&lamb); + if(d=DBL_MAX) + return FALSE; + + ///////////////////////////////////////////////// + //ya tiene el inw de la distancia mínima + + //apunta al que ha encontrado mínimo + ientnw = olv_limp->carto.getRef(inww.refnw); + + //calcula el punto del inw donde se da el mínimo + pt_ip=ientnw.getPto(inww.ip); + pt_ip1=ientnw.getPto(inww.ip+1); + + pt_proy_nw[2]=0; + for(i=0;i<2;i++) + pt_proy_nw[i]=pt_ip[i]+(pt_ip1[i]-pt_ip[i])*inww.lamb; + + ///////////////////////////////////////////////// + //sustituye las coords por el punto proyectado en la nw + memcpy(pt,pt_proy_nw,3*sizeof(double)); + ///////////////////////////////////////////////// + + //hace dos tramos + if(!ientnw.DivLine(&lines[0],&lines[1],inww.ip,inww.lamb)) + return FALSE; + + //añade los tramos, les pone la misma info asociada que la carretera original + info_aux.reset(); + memcpy(&info_aux,&olv_limp->iaso[inww.refnw],sizeof(Info_aso2)); + + for(i=0;i<2;i++) + { + if(lines[i].getNumberPtos()<2) + continue; + olv_limp->carto.add(lines[i]); + info_aux.refe=olv_limp->carto.get(olv_limp->carto.getNumberEntities()-1).entity()->ref; + + if(olv_limp->iaso[inww.refnw].inf_n.nomb) + { + info_aux.inf_n.nomb = (char*)malloc(strlen(olv_limp->iaso[inww.refnw].inf_n.nomb)+1); + strcpy(info_aux.inf_n.nomb,olv_limp->iaso[inww.refnw].inf_n.nomb); + } + + olv_limp->iaso[info_aux.refe]=info_aux; + } + + olv_limp->carto.removeRef(inww.refnw); + //olv_limp->carto.clear(); //se hace después + + return TRUE; +} +//************************************************************************************* +/** + * Apunta en qué nodos está la planta y la instalación + */ +BOOL Colv_limp_thr::busca_conjs_planta(double pt[3], int *nod) +{ + int ic; + BOOL mal=FALSE; + + if((pt[0]==0) && (pt[1]==0)) + return TRUE;//no hay instalación, no se pone + + //busca ese punto en la lista de conjunciones + //busca la conjunción en la lista + //lo hace para los dos extremos de la línea + for(ic=0; icconjs.n;ic++) + { + if((Colv_geom::pto_equals(pt,olv_limp->conjs.coor[ic]))) + break; + } + if(ic==olv_limp->conjs.n) + { + return FALSE; + } + *nod=ic; + + return TRUE; +} +//************************************************************************************* +/** + * Lanza sub-threads + */ +void Colv_limp_thr::lanza_subthrs(int tar, int nthr_def/*=-1*/) +{ + char nomb[32]; + Param_olv_limp_thr pp; + int nn; + if((nthr_def>0) && (nthr_defthr_padre=this; + subthrs[i]->n_subthr = nn; + subthrs[i]->prog_subthr = 0; + subthrs[i]->pirate=FALSE; + subthrs[i]->inicia(OLV_MILIS_COLA,&cola_proc,-1,nomb); + subthrs[i]->encola(tar,&pp,FALSE); + } + + //fuerza fin para que avance olivia + for(int i=nn;iprog_subthr = 0; + } + for(int i=0;ipirate=pirate; + subthrs[i]->termina(); + } + } +} +//************************************************************************************* +/** + * Rellena la matriz de costes entre todas las conjunciones + */ +BOOL Colv_limp_thr::calcula_cost_conj() +{ + int i; + //////////////// + + olvlog(LOG_TODO,"olv_limp_t","Rellenando matriz de costes entre conjunciones"); + pon_mi_progre(OLV_TAREA_COST_AMB, 0); + pon_mi_msg("Rellenando matriz de costes entre nodos"); + err_str[0]=0; + + //calcula el número de nodos de la red + //que es el número de intersecciones de la red navegable, incluyendo el número de ámbitos x2 porque + //aparecen el punto del ámbito y el proyectado en la carretera más próxima (y x2 si son lineales) + olvlog(LOG_TODO,"olv_limp_t","Comienza a buscar conjunciones"); + if(!busca_conjs()) + { + pon_mi_msg("Error, sin memoria para matriz de conjunciones en busca_conjs"); + return FALSE; + } + + //***************************************************************** + //log_debug + /*CartoBaseInfoEntity ient; + int refent; + for(int i=0;in_amb;i++) + { + refent=i; + ient=olv_limp->carto.getRef(refent); + + olvlog(LOG_TODO,"olv_limp_t","refent %04d flgs 0x%x -----------------------", refent, olv_limp->iaso[refent].flgs); + olvlog(LOG_TODO,"olv_limp_t","inod 0 %03d 1 %03d",olv_limp->iaso[refent].inod[0],olv_limp->iaso[refent].inod[1]); + olvlog(LOG_TODO,"olv_limp_t","refe2 %04d",olv_limp->iaso[refent].refe2); + olvlog(LOG_TODO,"olv_limp_t","refe_nw 0 %04d 1 %04d",olv_limp->iaso[olv_limp->inww_amb[refent].refnw].oid, + olv_limp->iaso[olv_limp->inww_amb[refent+olv_limp->n_amb].refnw].oid); + olvlog(LOG_TODO,"olv_limp_t","refe_nw inod 0 %03d 1 %03d",olv_limp->iaso[olv_limp->inww_amb[refent].refnw].inod[0], + olv_limp->iaso[olv_limp->inww_amb[refent+olv_limp->n_amb].refnw].inod[1]); + }*/ + //***************************************************************** + + pon_mi_msg("Rellenando matriz de costes entre nodos. %ld nodos por calcular", olv_limp->conjs.n); + //pide memoria para el array de distancias entre conjunciones + ///mira a ver con cuántos nvect puede calcular la matriz + CoptiMemo oo; + int nvect = oo.calc_nvect_master(olv_limp->conjs.n); + if(nvect<0) + { + pon_mi_msg("Error, sin memoria para matriz de conjunciones en cálculo de nvect"); + return FALSE; + } + olvlog(LOG_TODO,"olv_limp_t","Se va a ejecutar con nvect=%ld de %ld",nvect,olv_limp->conjs.n); + olv_limp->cost_conj.clear(); + olv_limp->tip_conj.clear(); + olv_limp->cost_conj.inicializa(olv_limp->conjs.n,n_subthr,nvect); + olv_limp->tip_conj.inicializa(olv_limp->conjs.n,n_subthr,nvect); + + //si solo le llega una calle a una conjunción, y es de sentido único, le pone doble sentido + for(i=0;iconjs.n;i++) + { + if(olv_limp->conjs.inc[i].n==1) + { + if(olv_limp->iaso[olv_limp->conjs.inc[i].refnw0].flgs & (OLV_LIMP_FLG_CIRC_FT | OLV_LIMP_FLG_CIRC_TF)) + olv_limp->iaso[olv_limp->conjs.inc[i].refnw0].flgs &= ~OLV_LIMP_FLG_CIRC_FT & ~OLV_LIMP_FLG_CIRC_TF; + } + } + + //lanza los threads + lanza_subthrs(OLV_LIMP_EV_COST_CONJ_SUB); + + return TRUE; +} +//************************************************************************************* +/** + * Comprueba la memoria para las conjunciones + */ +BOOL Colv_limp_thr::add_conj(Info_conjs *conjs, double coor[3]) +{ + if(!cuida_memo_conj(conjs)) + return FALSE; + + memcpy(conjs->coor[conjs->n],coor,3*sizeof(double)); + conjs->n++; + + return TRUE; +} +//************************************************************************************* +/** + * Comprueba la memoria para las conjunciones + */ +BOOL Colv_limp_thr::cuida_memo_conj(Info_conjs *conjs) +{ + double (*coor2)[3]; + Info_conjs_inw *inc2; + + if((conjs->n+1)>conjs->m) + { + conjs->m+=OLV_LIMP_M_CONJ; + + //primero las coordenadas + coor2 = (double (*)[3])realloc(conjs->coor,conjs->m*3*sizeof(double)); + if(!coor2) + { + free(conjs->coor); + return FALSE; + } + conjs->coor=coor2; + memset(&conjs->coor[conjs->m-OLV_LIMP_M_CONJ],0,OLV_LIMP_M_CONJ*3*sizeof(double)); + + //primero las incidencias + inc2 = (Info_conjs_inw *)realloc(conjs->inc,conjs->m*sizeof(Info_conjs_inw)); + if(!inc2) + { + free(conjs->inc); + return FALSE; + } + conjs->inc=inc2; + //inicializa + for(int i=conjs->m-OLV_LIMP_M_CONJ;im;i++) + { + conjs->inc[i].n=conjs->inc[i].refnw0=-1; + } + } + + return TRUE; +} +//************************************************************************************* +/** + * Rellena la matriz de conjunciones entre toda la red, navegable y ámbitos + * y la info de las conjunciones se rellena en 'conjs' + */ +BOOL Colv_limp_thr::busca_conjs() +{ + int io, refent, nent,i,k,npts,ic, ics[2], refe2,sum; + CartoBaseInfoEntity ient; + double *pto; + BOOL modo_ejes, mal; + + mal=modo_ejes=FALSE; + + if((olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoMh_eje) || + (olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoM2h_eje)) + modo_ejes=TRUE; + + //bucle por cada entidad de la carto + //si es modos de ámbitos normales, lineales o puntuales, se va de inicio a final del carto, en orden + //y se van buscando las conjs de los ámbitos, los nw, y los segmentos + //si es un modo en el que los ámbitos son ejes, se va al revés, añadiendo primero las conjunciones de + //los segmentos y la nw, y por último las de los ejes. Se hace para que en el siguiente paso, al buscar, + //aparezca primero la conjunción de la carretera, porque es de la que no se tiene constancia ic_ini/ic_fin + + io=0; + nent=olv_limp->carto.getNumberEntities(); + if(modo_ejes) + { + i=nent; + sum=-1; + } + else + { + i=-1; + sum=1; + } + for(io=0;iocarto.get(i).entity()->type!=CartoBaseTypes::Line) + continue; + + ient=olv_limp->carto.get(i); + refent=ient.entity()->ref; + npts=ient.getNumberPtos(); + + if((olv_limp->iaso[refent].flgs & OLV_LIMP_FLG_PEAT_SEG) || + (olv_limp->iaso[refent].flgs & OLV_LIMP_FLG_EJE_SEG)) + continue; + + for(k=0; k<2; k++) + { + pto = ient.getPto(k*(npts-1)); + if((olv_limp->iaso[refent].flgs & OLV_LIMP_FLG_PEAT_REP) || + (olv_limp->iaso[refent].flgs & OLV_LIMP_FLG_EJE)) + { + //en estos casos replica las conjunciones + //llega la segunda vez + ic=olv_limp->conjs.n; + if(!add_conj(&olv_limp->conjs, pto)) + { + mal=TRUE; + break; + } + } + else + { + //busca la conjunción en la lista + //lo hace para los dos extremos de la línea + for(ic=0; icconjs.n;ic++) + { + if((Colv_geom::pto_equals(pto,olv_limp->conjs.coor[ic]))) + break; + } + if(ic==olv_limp->conjs.n) + { + //no lo ha encontrado, lo añade + if(!add_conj(&olv_limp->conjs,pto)) + { + mal=TRUE; + break; + } + } + } + ics[k]=ic; + + //si es carretera, le pone a la conjunción que llega una al menos + //if(olv_limp->iaso[refent].flgs & OLV_LIMP_FLG_NW) + { + if(olv_limp->conjs.inc[ic].n<0) + { + olv_limp->conjs.inc[ic].n=1; + olv_limp->conjs.inc[ic].refnw0=refent; + } + else + olv_limp->conjs.inc[ic].n++; + } + } + + //guarda las conjunciones en la iaso + for(k=0; k<2; k++) + { + olv_limp->iaso[refent].inod[k]=ics[k]; + } + + //si es segmento de ámbito puntual, le pone al ámbito la conjunción + if(olv_limp->iaso[refent].flgs & OLV_LIMP_FLG_SEG_PUN) + { + refe2=olv_limp->iaso[refent].refe2; + olv_limp->iaso[refe2].inod[0]=olv_limp->iaso[refe2].inod[1]=ics[1]; + } + + } + + if(iocarto.getNumberEntities(); + int ref1, ref2; + for(i=0;icarto.get(i).entity()->type!=CartoBaseTypes::Line) + continue; + + ient=olv_limp->carto.get(i); + refent=ient.entity()->ref; + npts=ient.getNumberPtos(); + + if(olv_limp->iaso[refent].flgs & OLV_LIMP_FLG_PEAT_SEG) + { + //ref1 es la réplica de la peatonal + ref1=olv_limp->iaso[refent].refe; + //ref2 es la peatonal original + ref2=olv_limp->iaso[refent].refe2; + } + else if(olv_limp->iaso[refent].flgs & OLV_LIMP_FLG_EJE_SEG) + { + //ref1 es el eje original, como ámbito + ref1=olv_limp->iaso[refent].refe2; + //ref2 es la calle a la que está asignado + ref2=olv_limp->inww_amb[ref1].refnw; + } + else + continue; + if(olv_limp->iaso[refent].flgs & OLV_LIMP_FLG_FIN) + k=1; + else + k=0; + //el primer nodo el del ámbito + olv_limp->iaso[refent].inod[0]=olv_limp->iaso[ref1].inod[k]; + //el primer nodo el de la réplica + olv_limp->iaso[refent].inod[1]=olv_limp->iaso[ref2].inod[k]; + } + + olvlog(LOG_TODO,"olv_limp_t","Encontradas %ld conjunciones en la red navegable",olv_limp->conjs.n); + + olvlog(LOG_TODO,"olv_limp_t","Comienza a buscar las conjunciones de la planta"); + + if(!busca_conjs_planta(olv_limp->coor_instal, &olv_limp->nod_instal)) + { + olvlog(LOG_TODO,"olv_limp_t","No se ha podido encontrar los nodos de la planta"); + return FALSE; + } + olvlog(LOG_TODO,"olv_limp_t","Encontradas las conjunciones de la planta"); + + return TRUE; +} +//************************************************************************************* +/** + * Rellena la matriz de distancias entre todas las conjunciones. + * El thread entra aquí cuando los subthreads que realizan la tarea realmente han finalizado + */ +BOOL Colv_limp_thr::calcula_cost_conj_fin() +{ + //////////////// + //para los threads + para_subthrs(); + //olv_limp->cost_conj.memAjust(); + olvlog(LOG_TODO,"olv_limp_t","FIN Matriz de dist entre conjs %ldx%ld", + olv_limp->conjs.n,olv_limp->conjs.n); + + /////////////////////////////// + /*if(olv_limp->res_circ==OLV_RES_NO) + { + //va directo a cost_amb, calcula ahora si va a ser multitask o no + //calcula si puede ser multitask o no + CoptiMemo oo; + olv->modo_multitask=oo.is_multi(olv_limp->conjs.n,n_subthr,sizeof(Djkt_elem_cola)); + }*/ + //////////////////////////////// + + return TRUE; +} +//************************************************************************************* +/** + * Rellena la matriz de distancias entre todas las conjunciones, es la parte de cálculos que + * realizan los subthreads. 'ithr' indica qué thread es, para calcular qué conjunciones le tocan. + */ +void Colv_limp_thr::calcula_cost_conj_sub(int ithr) +{ + int nd,i,k,ics[2]; + int n_ini, n_desp, n_fin, seg; + float cost,cost2; + BOOL mal=FALSE; + Param_olv_limp_thr pp; + + int nent, refent; + CartoBaseInfoEntity ient; + + //////////////// + nent=olv_limp->carto.getNumberEntities(); + mal=FALSE; + pp.id_e=OLV_TAREA_COST_AMB;//manda de parámetro la tarea de la que es el progreso + n_desp = (int)ceil(1.0*(nent)/n_subthr); + n_ini=ithr*n_desp; + n_fin = min((ithr+1)*n_desp,nent); + cost=cost2=0; + nd=0; + //////////////// + + olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Entidades %04d a %04d", ithr,n_ini, n_fin); + + seg = GetTickCount(); + ///////////////////////////////////// + //bucle por cada entidad de la carto + for(i=n_ini; icarto.get(i); + refent = ient.entity()->ref; + for(k=0;k<2;k++) + ics[k]=olv_limp->iaso[refent].inod[k]; + + if(ics[0]<0 || ics[1]<0) + continue; + + /////////////////// + //pone en el array de tipos qué es + olv_limp->tip_conj.set(ics[0],ics[1],refent); + olv_limp->tip_conj.set(ics[1],ics[0],refent); + /////////////////////////////////// + nd+=2; + + //ya tiene una línea y sus dos extremos localizados, calcula el coste + calcula_cost(refent,&cost,&cost2); + + //añade los costes a la matriz + if(cost>olv_limp->cost_conj[ics[0]][ics[1]]) + cost=olv_limp->cost_conj[ics[0]][ics[1]]; + olv_limp->cost_conj.set(ics[0],ics[1], min(cost,olv_limp->cost_conj[ics[0]][ics[1]])); + + if(cost2>olv_limp->cost_conj[ics[1]][ics[0]]) + cost2=olv_limp->cost_conj[ics[1]][ics[0]]; + olv_limp->cost_conj.set(ics[1],ics[0],min(cost2,olv_limp->cost_conj[ics[1]][ics[0]])); + + ///////////////////////////////////// + + //avisa de progreso + if(((i-n_ini)%800==0) || ((i-n_ini)==(n_desp-1))) + { + olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Rellenando matriz de dist entre conjs %ld de %ld", ithr, + (i-n_ini+1),n_desp); + //avisa de progreso + prog_subthr=((1.0*(i-n_ini+1)/n_desp)+0)/3;///3 porque es la tercera parte del progreso los costes de conjunciones y la otra mitad los costes de ámbitos + thr_padre->encola(OLV_LIMP_EV_SUBTHR_PROG,&pp,FALSE); + } + } + + olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Fin Matriz de dist entre conjs, %ld distancias, %.3f seg", ithr, nd,1.0*(GetTickCount()-seg)/1000); + + thr_padre->encola(OLV_LIMP_EV_COST_CONJ_FIN,NULL,FALSE); +} +//************************************************************************************* +/** + * Calcula el coste de la línea io, cost en sentido ida y cost2 en sentido vuelta + */ +void Colv_limp_thr::calcula_cost(int refent, float *cost, float *cost2) +{ + double ltot; + + *cost=*cost2=0; + //////////////////// + ltot=0; + if(olv_limp->carto.getRef(refent).entity()->type == CartoBaseTypes::Line) + { + ltot=olv_limp->carto.getRef(refent).getLong(); + if(ltot==0) + { + //es un segmento de unión de peat con rep o de eje de calle con nw + cost=cost2=0; + return; + } + } + /////////////////// + olv_limp->dame_cost(ltot,refent,cost,cost2); +} +//************************************************************************************* +/** + * Rellena la matriz de ángulos entre las conjunciones adyacentes a una dada + */ +BOOL Colv_limp_thr::calcula_ang_conj() +{ + //////////////// + + olvlog(LOG_TODO,"olv_limp_t","Rellenando matriz de ángulos entre conjunciones"); + pon_mi_progre(OLV_TAREA_COST_AMB, (int) (OliviaDef::GeneralDef::ProgrMax*1/3)); + pon_mi_msg("Rellenando matriz de ángulos entre nodos"); + err_str[0]=0; + + //pide memoria para el array de distancias entre conjunciones + olv_limp->ang_conj = new Djkt_ang_ady[olv_limp->conjs.n]; + + //lanza los threads + lanza_subthrs(OLV_LIMP_EV_ANG_CONJ_SUB); + + return TRUE; +} + +//************************************************************************************* +/** + * Rellena la matriz de ángulos entre todas las conjunciones. + * El thread entra aquí cuando los subthreads que realizan la tarea realmente han finalizado + */ +BOOL Colv_limp_thr::calcula_ang_conj_fin() +{ + //////////////// + //para los threads + para_subthrs(); + + revisa_calles_cortadas(); + + ////////////////////////////////// + //calcula si va a ser multitask o no + CoptiMemo oo; //se deja a false siempre de momento + olv->modo_multitask=FALSE;//oo.is_multi(olv_limp->conjs.n,n_subthr,sizeof(Djkt_elem_cola)); + ////////////////////////////////// + + olvlog(LOG_TODO,"olv_limp_t","FIN Matriz de ang entre conjs %ldx%ld", + olv_limp->conjs.n,olv_limp->conjs.n); + return TRUE; +} +//************************************************************************************* +/** + * Rellena la matriz de ángulos entre todas las conjunciones adyacentes a una dada, es la parte de cálculos que + * realizan los subthreads. 'ithr' indica qué thread es, para calcular qué conjunciones le tocan. + */ +void Colv_limp_thr::calcula_ang_conj_sub(int ithr) +{ + Param_olv_limp_thr pp; + + int i,j,nconj,KK,na,ic,nady; + int n_ini, n_desp, n_fin, seg; + BOOL mal=FALSE; + BYTE aa; + BYTE *conjs; + double ang; + + //////////////// + pp.id_e=OLV_TAREA_COST_AMB;//manda de parámetro la tarea de la que es el progreso + KK=olv_limp->tipo_ambit; + nconj=olv_limp->conjs.n; + n_desp = (int)ceil(1.0*nconj/n_subthr); + n_ini=ithr*n_desp; + n_fin = min((ithr+1)*n_desp,nconj); + na=0; + conjs=NULL; + conjs=(BYTE*)malloc(olv_limp->conjs.n*sizeof(BYTE)); + if(!conjs) + mal=TRUE; + else + memset(conjs,0,olv_limp->conjs.n*sizeof(BYTE)); + //////////////// + + olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Ángulos de conjunciones %04d a %04d", ithr,n_ini, n_fin); + + seg = GetTickCount(); + ///////////////////////////////////// + //bucle por cada conjunción de la carto + for(ic=n_ini; icconjs.n*sizeof(BYTE)); + //Busca conjunciones adyacentes + for(i=0;icost_conj[i][ic]>=MAYUSCULO) && (olv_limp->cost_conj[ic][i]>=MAYUSCULO)) + continue; + + //marca las conjunciones que son adyacentes + conjs[i]=1; + + for(j=i+1;jcost_conj[ic][j]>=MAYUSCULO) + { + continue; + } + + //marca las conjunciones que son adyacentes + conjs[j]=1; + } + + } + for(i=0;i16) + { + nady=nady; + } + //ya tiene las adyacentes de la conjunción ic, inicializa array de angulos + if(!olv_limp->ang_conj[ic].inicia(nady)) + { + mal=TRUE; + break; + } + //Busca conjunciones adyacentes + for(i=0;icost_conj[i][ic]>=MAYUSCULO) || (olv_limp->cost_conj[ic][j]>=MAYUSCULO)) + { + aa=0; + } + else + { + //si no hay restricciones de circulación, se pone que se el ángulo es ok siempre + //si no, se calcula, y el ángulo es ok si es menor que el ángulo límite + //if(olv_limp->res_circ!=OLV_RES_NO) + { + ang=dame_ang_conj(ic,i,j); + aa=(ang<=olv_limp->ang_lim); + } + } + olv_limp->ang_conj[ic].pon_ang_i_j(i,j,aa); + + na++; + + } + } + + //avisa de progreso + if(((ic-n_ini)%500==0) || ((ic-n_ini)==(n_desp-1))) + { + olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Rellenando matriz de ang entre conjs %ld de %ld", ithr, + (ic-n_ini+1),n_desp); + //avisa de progreso + prog_subthr=((1.0*(ic-n_ini+1)/n_desp)+1)/3;///3 porque es la tercera parte del progreso los costes de conjunciones + thr_padre->encola(OLV_LIMP_EV_SUBTHR_PROG,&pp,FALSE); + } + } + + if(conjs) + free(conjs); + + olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Fin Matriz de ang entre conjs, %ld ángulos, %.3f seg", ithr, na,1.0*(GetTickCount()-seg)/1000); + + thr_padre->encola(OLV_LIMP_EV_ANG_CONJ_FIN,NULL,FALSE); +} +//************************************************************************************* +/** + * Devuelve el ángulo entre dos conjunciones + */ +double Colv_limp_thr::dame_ang_conj(int ic, int i, int j) +{ + double ang, *p, v[2][2]; + int npts,k,t; + CartoBaseInfoEntity ient; + int refconj_i = olv_limp->tip_conj[i][ic]; + int refconj_j = olv_limp->tip_conj[j][ic]; + + ang=0; + + //cambio de sentido en carretera o ámbito + if(i==j) + { + if((olv_limp->iaso[refconj_i].flgs & OLV_LIMP_FLG_NW) || (olv_limp->iaso[refconj_j].flgs & OLV_LIMP_FLG_NW)) + { + if(olv_limp->res_circ==OLV_RES_NO) + return 0; + else + return OLV_PI;//ángulo de 180º en carretera y sigue sentidos, no se puede (excepto si es calle cortada, que se revisa luego) + } + else + return 0; + } + + if(!(olv_limp->iaso[refconj_i].flgs & OLV_LIMP_FLG_NW) || !(olv_limp->iaso[refconj_j].flgs & OLV_LIMP_FLG_NW)) + { + return 0;//uno de los dos no son carretera, se puede siempre + } + + if(((olv_limp->iaso[refconj_i].flgs & OLV_LIMP_FLG_NW_REP) && (olv_limp->iaso[refconj_i].refe2 == refconj_j)) || + ((olv_limp->iaso[refconj_j].flgs & OLV_LIMP_FLG_NW_REP) && (olv_limp->iaso[refconj_j].refe2 == refconj_i))) + { + //si intenta ir de nw a réplica, pero de la misma calle + return OLV_PI; + } + //return 0; + //las dos son carretera, mira si por coste no se puede ir + //calcula los puntos próximos a la conjunción + for(t=0;t<2;t++) + { + if(t==0) + ient = olv_limp->carto.getRef(refconj_i); + else + ient = olv_limp->carto.getRef(refconj_j); + + p=ient.getPto(0); + npts=ient.getNumberPtos(); + if(Colv_geom::pto_equals(olv_limp->conjs.coor[ic], p)) + { + p=ient.getPto(1); + //la conjunción es el primer punto + for(k=0;k<2;k++) + { + v[t][k]=p[k]-olv_limp->conjs.coor[ic][k]; + } + } + else + { + p=ient.getPto(npts-2); + //la conjunción es el último punto + for(k=0;k<2;k++) + { + v[t][k]=p[k]-olv_limp->conjs.coor[ic][k]; + } + } + } + + ang=Colv_geom::ang_vect(v[0],v[1]); + ang=OLV_PI-ang; + + return ang; +} +//************************************************************************************* +/** + * Resvisa los ángulos, de forma que si hay algún giro "prohibido" de 180º, en caso + * de que sean calles cortadas o sin salida, los pone a ok + */ +void Colv_limp_thr::revisa_calles_cortadas() +{ + int ic,i,j,k,nady; + //if(olv_limp->res_circ==OLV_RES_NO) + // return; + for(ic=0;icconjs.n;ic++) + { + nady=olv_limp->ang_conj[ic].nady; + for(i=0;iang_conj[ic].angs[i][j]) + { + //si el ángulo es prohibido, mira a ver si hay más conjunciones + for(k=0;kang_conj[ic].i_conjs[k]<0 || olv_limp->ang_conj[ic].i_conjs[k]>=olv_limp->conjs.n) + { + olvlog(LOG_TODO,"olv_limp_t","Ojo ang_conj fuera de límites ic %ld, k %ld",ic,k); + continue; + } + /*if(((k!=i) || (k!=j)) && (olv_limp->conjs.inc[olv_limp->ang_conj[ic].i_conjs[k]].n>1)) + break;*/ + if((olv_limp->ang_conj[ic].i_conjs[k]!=olv_limp->ang_conj[ic].i_conjs[i]) && + (olv_limp->ang_conj[ic].i_conjs[k]!=olv_limp->ang_conj[ic].i_conjs[j]) && + (olv_limp->cost_conj[ic][olv_limp->ang_conj[ic].i_conjs[k]]conjs.inc[olv_limp->ang_conj[ic].i_conjs[k]].n>1)) + break; + } + if(k>=nady)//estos nodos son los únicos que tiene para entrar y salir + { + olv_limp->ang_conj[ic].angs[i][j]=1; + } + } + } + } + } +} +//************************************************************************************* +/** + * Rellena la matriz de costes entre todos los ámbitos + */ +BOOL Colv_limp_thr::calcula_cost_amb() +{ + //////////////// + + olvlog(LOG_TODO,"olv_limp_t","Rellenando matriz de costes entre ámbitos"); + pon_mi_progre(OLV_TAREA_COST_AMB, (int) (OliviaDef::GeneralDef::ProgrMax*2/3)); + pon_mi_msg("Rellenando matriz de costes entre ámbitos. %ld ámbitos por calcular",olv_limp->n_amb); + err_str[0]=0; + char st[MAX_PATH]; + char st1[MAX_PATH]; + + strcpy_s(st1,MAX_PATH,olv_limp->olv->paths.path_temp); + if(st1[strlen(st1)-1]=='\\') + { + st1[strlen(st1)-1]=0; + } + sprintf(st,"%s\\%s",st1,NOMB_ARCH_DIJ_DEF); + //inicia archivo para los djistra-------------- + if(!olv_limp->arch_dj.inicia(st,!olv->modo_multitask,olv_limp->conjs.n)) + { + olvlog(LOG_TODO,"olv_limp_t","Error al iniciar archivo dj en directorio %s",st); + return FALSE; + } + if(!olv_limp->arch_dj.inicia_inf_amb(&olv_limp->iaso,olv_limp->n_amb,olv_limp->tipo_ambit,olv_limp->nod_instal, olv_limp->nod_plant)) + { + olvlog(LOG_TODO,"olv_limp_t","Error al iniciar info de ambitos en archivo de dj"); + return FALSE; + } + + //////////////////////////////////////////////// + if(!inicia_cost_amb()) + { + return FALSE; + } + + if(!olv_limp->olv->modo_multitask) + { + //lanza los threads, tiene memo suficiente para todos los threads + lanza_subthrs(OLV_LIMP_EV_COST_AMB_SUB); + } + else + { + //en modo multitask entra aquí cuando ya han terminado las tasks + //se lee la matriz de ámbitos que han guardado las tasks + if(!olv_limp->arch_dj.lee_dis()) + return FALSE; + if(!olv_limp->olv_tasks->lee_cost_amb(olv_limp->cost_amb)) + return FALSE; + + //borra los archivos temporales + borra_temp_files(FALSE); + + //después de leerla, encola el cost_amb_fin + for(int i=0;iprog_subthr=0;//para que no dé error + encola(OLV_LIMP_EV_COST_AMB_FIN,NULL,FALSE); + } + } + + return TRUE; +} +//************************************************************************************* +BOOL Colv_limp_thr::inicia_cost_amb() +{ + int i,j; + + //pide memoria para el array de distancias entre ámbitos + if(!olv_limp->cost_amb.inicia(olv_limp->n_amb,olv_limp->n_amb)) + { + pon_mi_msg("Error, sin memoria para matriz de dist entre ámbitos"); + return FALSE; + } + + //inicializa todo a 0 + for(i=0;in_amb;i++) + { + for(j=0;jn_amb;j++) + olv_limp->cost_amb[i][j]=(float)MAYUSCULO;//porque se va a almacenar la minima + } + + //Inicia el array de orden /secuencia + olv_limp->ord_sec=(Secu_amb*)malloc(sizeof(Secu_amb)*olv_limp->n_amb); + if(!olv_limp->ord_sec) + { + pon_mi_msg("Error, sin memoria para matriz de orden y secuencia"); + return FALSE; + } + memset(olv_limp->ord_sec,0,sizeof(Secu_amb)*olv_limp->n_amb); + + return TRUE; +} +//************************************************************************************* +/** + * Rellena la matriz de distancias entre todos los ámbitos. + * El thread entra aquí cuando los subthreads que realizan la tarea realmente han finalizado + */ +BOOL Colv_limp_thr::calcula_cost_amb_fin() +{ + //////////////// + int ai=1; + + if(!olv_limp->olv->modo_multitask) + { + //para los threads + para_subthrs(); + } + + if(pirate) + return FALSE; + + //////////////// + //mira si hay aislados + if(!avisa_aislados()) + return FALSE; + + //avisa aislados ha ido bien, no hay aislados + + if(pirate) + return FALSE; + + //calcula el coste a las plantas + if(!calcula_cost_plant()) + { + pon_mi_msg("Error, planta o instalación aisladas"); + return FALSE; + } + + olv_limp->nsec_act=olv_limp->nsec; + + olvlog(LOG_TODO,"olv_limp_t","FIN Matriz de dist entre ámbitos %ldx%ld", + olv_limp->n_amb,olv_limp->n_amb); + + return TRUE; +} +//************************************************************************************* +/** + * Dado el array relleno con los aislados, saca cartel avisando + */ +BOOL Colv_limp_thr::avisa_aislados() +{ + int i,j,k,ii, ref_i, ref_j; + BYTE *ambs_ais; + char ais_msg[OLV_MAX_MSG_PROCE]; + char nfile[MAX_PATH]; + + strcpy_s(nfile,MAX_PATH,olv->paths.path_data); + //cambiaext(nfile,".shp",".dbf"); + strcpy((Cdir_manager::extension_archivo(nfile)),"dbf"); + ambs_ais = (BYTE*)malloc(olv_limp->n_amb); + if(!ambs_ais) + { + pon_mi_msg("Error, sin memoria en fin de calcula coste ámbitos"); + return FALSE; + } + memset(ambs_ais,0,olv_limp->n_amb); + + //revisa costes de ámbitos + int nais; + for(i=0;in_amb; i++) + { + if(ambs_ais[i]) + continue; + ref_i=olv_limp->carto.get(i).entity()->ref; + + if(olv_limp->iaso[ref_i].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + for(j=0;jn_amb; j++) + { + if(i==j) + continue; + ref_j=olv_limp->carto.get(j).entity()->ref; + + if(olv_limp->iaso[ref_j].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + if(ambs_ais[j]) + continue; + if(olv_limp->cost_amb[i][j]>=MAYUSCULO) + { + //puede estar aislado i o j + nais=0; + for(k=0;kn_amb;k++) + { + if(k==i) + continue; + if(olv_limp->cost_amb[k][j]>=MAYUSCULO)//comprueba si j está aislado para los demás ámbitos también + { + nais=j; + break; + } + if(k==j) + continue; + if(olv_limp->cost_amb[i][k]>=MAYUSCULO)//comprueba si i está aislado para los demás ámbitos también + { + nais=i; + break; + } + } + if(kn_amb) + ambs_ais[nais]=1; + } + } + } + + nais=0; + int inw,inw2; + INT64 flgs2; + for(i=0;in_amb;i++) + { + if(ambs_ais[i]) + { + nais++; + inw=olv_limp->inww_amb[i].refnw; + if(olv_limp->tipo_ambit==OLV_AMB_LIN) + { + inw2=olv_limp->inww_amb[i+olv_limp->n_amb].refnw; + flgs2=olv_limp->iaso[inw2].flgs; + } + else + { + inw2=0; + flgs2=0; + } + olvlog(LOG_TODO,"olv_limp_t","Ámbito %05d aislado, inw1 %05d inw2 %05d, flags amb %02X inw1 %02X inw2 %02X ",i,inw,inw2, + olv_limp->iaso[i].flgs,olv_limp->iaso[inw].flgs,flgs2); + } + } + + if(!nais) + { + free(ambs_ais); + return TRUE; + } + + if(nais==1) + sprintf_s(ais_msg,"Encontrado %ld ámbito aislado %s: ", nais,olv_limp->igno_ais?"(Se ignora)":""); + else + sprintf_s(ais_msg,"Encontrados %ld ámbitos aislados %s: ",nais,olv_limp->igno_ais?"(Se ignoran)":""); + int inais=0; + for(i=0;in_amb;i++) + { + if(ambs_ais[i]) + { + ref_i=olv_limp->carto.get(i).entity()->ref; + if(olv_limp->igno_ais)//si toca ignorar aislados, lo marca para ignorarlo en la sectorización + { + olv_limp->iaso[ref_i].flgs|=OLV_LIMP_FLG_AMB_NO; + } + + ii=olv_limp->iaso[ref_i].oid; + if(nais==1) + { + sprintf_s(ais_msg,"%s %ld",ais_msg,ii); + break; + } + else if(inais==nais-1) + sprintf_s(ais_msg,"%s y %ld",ais_msg,ii); + else if(inais>0 && inais%4==0) + sprintf_s(ais_msg,"%s %ld,\n",ais_msg,ii); + else + sprintf_s(ais_msg,"%s %ld,",ais_msg,ii); + if(strlen(ais_msg)+10>=OLV_MAX_MSG_PROCE) + break; + inais++; + + } + } + if(in_amb && nais>1 && ((strlen(ais_msg)+5)igno_ais) + Sleep (OLV_T_SLEEP_MSG); + //////////////////////////// + + free(ambs_ais); + if(olv_limp->igno_ais) + return TRUE; + else + return FALSE; +} +//************************************************************************************* +/** + * Apunta en qué nodos está la planta y la instalación + */ +BOOL Colv_limp_thr::calcula_cost_plant() +{ + int ic,ia,ka,nais,k, ref_ia; + Djkt_nodo *costes_nodos; + BOOL mal=FALSE; + + if(olv_limp->nod_instal<0) + return TRUE; + + //Inicia el array de orden /secuencia + olv_limp->ord_sec_plan=(Secu_amb*)malloc(sizeof(Secu_amb)); + if(!olv_limp->ord_sec_plan) + { + pon_mi_msg("Error, sin memoria para matriz de orden y secuencia"); + return FALSE; + } + memset(olv_limp->ord_sec_plan,0,sizeof(Secu_amb)); + olvlog(LOG_TODO,"olv_limp_t","Calculando coste a planta e instalación"); + + costes_nodos=NULL; + k=0; + + ic=olv_limp->nod_instal; + + if(!Colv_geom::dijkstra_ang_inv_ok(olv_limp->cost_conj, olv_limp->ang_conj, olv_limp->conjs.n, + ic, &costes_nodos, &visto_ang)) + { + pon_mi_msg("Error al calcular costes de ámbitos a instalación"); + return FALSE; + } + + olv_limp->ord_sec_plan[k].ctnod[0]=costes_nodos; + olv_limp->ord_sec_plan[k].ctnod[1]=NULL; + + costes_nodos=NULL; + + //revisa si está aislado de algún ámbito + nais=0; + for(ia=0;ian_amb;ia++) + { + ref_ia=olv_limp->carto.get(ia).entity()->ref; + if(olv_limp->iaso[ref_ia].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + for(ka=0;katipo_ambit;ka++) + { + if(olv_limp->ord_sec_plan[k].ctnod[0][olv_limp->iaso[ref_ia].inod[ka]].dis>=MAYUSCULO) + { + nais++; + break; + } + } + if(nais) + break; + } + if(ian_amb) + { + pon_mi_msg("Error al calcular costes de ámbitos a instalación"); + return FALSE; + } + + return TRUE; +} +//************************************************************************************* +/** + * Rellena la matriz de distancias entre todos los ámbitos, es la parte de cálculos que + * realizan los subthreads. 'ithr' indica qué thread es, para calcular qué ámbitos le tocan. + */ +void Colv_limp_thr::calcula_cost_amb_sub(int ithr) +{ + int na_ini,na_fin,na_desp,na,i,k; + int KK, seg; + BOOL log_debug=FALSE; + Djkt_nodo *costes_nodos; + double caux; + Param_olv_limp_thr pp; + BOOL mal=FALSE; + CartoBaseInfoEntity ient_na, ient_i; + int ref_na, ref_i, amb_i, amb_na; + + //////////////// + pp.id_e=OLV_TAREA_COST_AMB;//manda de parámetro la tarea de la que es el progreso + KK=olv_limp->tipo_ambit; + na_desp = (int)ceil(1.0*(olv_limp->n_amb)/n_subthr); + na_ini=ithr*na_desp; + na_fin = min((ithr+1)*na_desp,olv_limp->n_amb); + costes_nodos=NULL; + //////////////// + + olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Ambs %04d a %04d", ithr,na_ini, na_fin); + + seg = GetTickCount(); + ///////////////////////////////////// + //Bucle por cada ámbito de los que le tocan a este thread + ///////////////////////////////////// + //el coste de un ámbito a sí mismo es el de trabajar ese ámbito, + //que es el coste de ir de su conj inicial a la final + na=na_ini; + + ///////////////////////////////////// + for(na=na_ini;naias[i].ic_ini está almacenado el índice de la conjunción del nodo inicial del ámbito + //y en olv_limp->ias[i].ic_fin el del final. + ///////////////////////////////////////////// + //calcula el coste máximo del ámbito na a todos los demás + //los añade a la fila na de la matriz de costes + //es coste máximo porque hace el máximo de: + //inicio(na)->inicio(ni), inicio(na)->final(ni), final(na)->inicio(ni), final(na)->final(ni) + ///////////////////////////////////////////// + //k==0, calcula las distancias del nodo inicial de ese ámbito a todas las demás conjunciones + //k==1, calucla las distancias del nodo final + ient_na = olv_limp->carto.get(na); + ref_na = ient_na.entity()->ref; + amb_na=olv_limp->iaso[ref_na].iamb; + + for(k=0;kcost_conj, olv_limp->ang_conj, olv_limp->conjs.n, + (1-k)*olv_limp->iaso[ref_na].inod[0]+k*olv_limp->iaso[ref_na].inod[1], + &costes_nodos, &visto_ang)) + { + mal=TRUE; + break; + } + + //recorre todos los demás ámbitos buscando el coste a ellos en el array de costes devuelto, y los almacena + //almacena el coste a su nodo inicial y a su nodo final + if(olv_limp->iaso[ref_na].flgs & OLV_LIMP_FLG_AMB_NO) + { + for (i=0; iconjs.n; i++) + { + costes_nodos[i].dis=(float)MAYUSCULO; + costes_nodos[i].id_padre=-1; + costes_nodos[i].ids_ady.nady=0; + } + } + else + { + for(i=0;in_amb;i++) + { + ient_i = olv_limp->carto.get(i); + ref_i = ient_i.entity()->ref; + amb_i=olv_limp->iaso[ref_i].iamb; + + if(olv_limp->iaso[ref_i].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + if(na==i) + { + //el coste de un ámbito a sí mismo es el de trabajar ese ámbito + olv_limp->cost_amb[amb_na][amb_na]=olv_limp->cost_conj[olv_limp->iaso[ref_na].inod[0]][olv_limp->iaso[ref_na].inod[1]]; + continue; + } + + if(olv_limp->cost_amb[amb_i][amb_na]>costes_nodos[olv_limp->iaso[ref_i].inod[0]].dis) + olv_limp->cost_amb[amb_i][amb_na]=costes_nodos[olv_limp->iaso[ref_i].inod[1]].dis; + if(KK==OLV_AMB_LIN) + { + if(olv_limp->cost_amb[amb_i][amb_na]>costes_nodos[olv_limp->iaso[ref_i].inod[0]].dis) + olv_limp->cost_amb[amb_i][amb_na]=costes_nodos[olv_limp->iaso[ref_i].inod[1]].dis; + } + } + } + + if(!olv_limp->arch_dj.add_b(costes_nodos, na, k, TRUE)) + { + olvlog(LOG_TODO,"olv_limp_t","Subthr %ld,Error %ld no se ha podido guardar dj iref: %ld k: %ld", ithr, + GetLastError(),na,k); + } + + for(i=0;iconjs.n;i++) + { + costes_nodos[i].libera(); + } + free(costes_nodos); + + olv_limp->ord_sec[na].ctnod[k]=NULL; + if(KK==1) + olv_limp->ord_sec[na].ctnod[1]=NULL; + + } + if(mal) + break; + + //si es ámbito lineal calcula la distancia media de los cuatro nodos + if(na==1) + if(log_debug) + { + for(i=0;in_amb;i++) + { + if(olv_limp->cost_amb[amb_na][i]>=MAYUSCULO) + caux=-1; + else + caux=olv_limp->cost_amb[amb_na][amb_i]; + olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Coste ámb %ld a ámb %ld es %lf", ithr, + na,i,caux); + } + } + + //avisa de progreso + if(((na-na_ini)%100==0) || ((na-na_ini)==(na_desp-1))) + { + olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Rellenando matriz de dist entre ambs %ld de %ld", ithr, + (na-na_ini+1),na_desp); + //avisa de progreso + prog_subthr=((1.0*(na-na_ini+1)/na_desp)+2)/3;///3 porque es la tercera parte del progreso los costes de conjunciones + thr_padre->encola(OLV_LIMP_EV_SUBTHR_PROG,&pp,FALSE); + } + } + + if(visto_ang) + { + free(visto_ang); + visto_ang=NULL; + } + + if(mal) + { + olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Error en cálculo de matriz de distancias entre ámbitos", ithr); + prog_subthr=-1;//para avisar al padre de que ha habido un error + } + else + { + olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Fin Matriz de dist entre ambs, %.3f seg", ithr, 1.0*(GetTickCount()-seg)/1000); + } + thr_padre->encola(OLV_LIMP_EV_COST_AMB_FIN,NULL,FALSE); + + ///////////////////////////////////// +} +//************************************************************************************* +/** + * Genera los sectores + */ +BOOL Colv_limp_thr::sectoriza() +{ + int i; + BOOL res=TRUE; + + if(olv_limp->n_amb<2) + { + pon_mi_msg("Error, número de ámbitos es %ld",olv_limp->n_amb); + return FALSE; + } + + pon_mi_progre(OLV_TAREA_SECTORIZ, 0); + pon_mi_msg(""); + err_str[0]=0; + + if(!pide_memo_secto()) + { + pon_mi_msg("Error, Sin memoria para sectorización"); + return FALSE; + } + + ////////////////////////////////////////////////////////////// + olvlog(LOG_TODO,"olv_limp_t","Comienza sectorización %ld ámbitos en %ld sectores", + olv_limp->n_amb, olv_limp->nsec_act); + + /////////////////////////////////////// + //Algoritmo 1 + if(!sectoriza_1()) + { + pon_mi_msg("Errores producidos en sectorización: %s",err_str); + res=FALSE; + goto pinta; + } + + /////////////////////////////////////// + //Si es barrido mixto hay que copiar la info en las que no se ha sectorizado + if(olv_limp->barr_mix) + copia_info_barr_mix(); + + ////////////////////////////////////////////////////////////////////////////// + //Guarda el shape añadiendo la columna de sector + if(!guarda_dbf_sector(0)) + { + pon_mi_msg("Errores producidos en sectorización: %s",err_str); + return FALSE; + } + //Guarda el shape añadiendo la columna de secuencia vacía + if(!guarda_dbf_sector(1)) + { + pon_mi_msg("Errores producidos en sectorización: %s",err_str); + return FALSE; + } + ////////////////////////////////////////////////////////////////////////////// + for(i=0;insec;i++) + { + olvlog(LOG_TODO,"olv_limp_t","Sector %ld, %03d ámbitos, coste total %lf",i,olv_limp->sec[i].namb, olv_limp->sec[i].cost_ac); + } + olvlog(LOG_TODO,"olv_limp_t","Finalizada generacion de sectores--------------------------"); + +pinta: + + return res; +} +//************************************************************************************* +/** + * Pide memoria e inicializa los arrays para la sectorización + */ +BOOL Colv_limp_thr::pide_memo_secto() +{ + int i,j; + ////////////////////////////////////////////////////////////// + //pide memoria para el array de distancias del sector + olv_limp->sec = (Info_sec *)malloc(olv_limp->nsec*sizeof(Info_sec)); + if(!olv_limp->sec) + { + pon_mi_msg("Error, sin memoria para matriz de sectores"); + return FALSE; + } + memset(olv_limp->sec,0,olv_limp->nsec*sizeof(Info_sec)); + for(i=0;insec;i++) + { + olv_limp->sec[i].iamb = (short *)malloc(olv_limp->n_amb*sizeof(short)); + if(!olv_limp->sec[i].iamb) + { + pon_mi_msg("Error, sin memoria para matriz de sectores"); + return FALSE; + } + } + //inicializa todo a mayúsculo + for(i=0;insec;i++) + { + olv_limp->sec[i].namb=0; + olv_limp->sec[i].iamb_ini_def=-1; + olv_limp->sec[i].t_despl[0]=olv_limp->sec[i].t_despl[1]=(float)olv_limp->t_despl; + for(j=0;jn_amb;j++) + { + olv_limp->sec[i].iamb[j]=-1; + } + } + ////////////////////////////////////////////////////////////// + //pide memoria para el array de ámbitos asignados al sector + olv_limp->amb_sec = (Info_amb_sec *)malloc(olv_limp->n_amb*sizeof(Info_amb_sec)); + if(!olv_limp->amb_sec) + { + pon_mi_msg("Error, sin memoria para matriz de ámbitos en los sectores"); + return FALSE; + } + memset(olv_limp->amb_sec,0,olv_limp->n_amb*sizeof(Info_amb_sec)); + //inicializa todo + for(j=0;jn_amb;j++) + { + olv_limp->amb_sec[j].sec=-1; + olv_limp->amb_sec[j].iseq=-1; + olv_limp->amb_sec[j].t=0; + } + + olv_limp->nsec_orig=olv_limp->nsec; + + return TRUE; +} +//************************************************************************************* +/** + * Añade el ámbito 'i_amb' al sector 'i_sec', actualizando la info en todos los lugares necesarios + */ +BOOL Colv_limp_thr::add_amb_sec(int i_amb, int namb, int i_sec, Info_sec *ss, Info_amb_sec *aa, Matrix2d &cost_amb, double cost_tot, int i_amb_p) +{ + if(olv_limp->iaso[olv_limp->carto.get(i_amb).entity()->ref].flgs & OLV_LIMP_FLG_AMB_NO) + return FALSE; + ss[i_sec].iamb[ss[i_sec].namb]=i_amb; + ss[i_sec].namb++; + //apunta el ámbito al sector + aa[i_amb].sec=i_sec; + + return TRUE; +} +//************************************************************************************* +/** + * Le quita el ámbito 'i_amb' al sector 'i_sec', actualizando la info en todos los lugares necesarios + * Actualiza el coste que es el que lleva, mas el desplazamiento del que ya tiene al nuevo, más el coste del nuevo + * Al salir, hay que actualizar las distancias! + */ +void Colv_limp_thr::quita_amb_sec(int i_amb, int namb, int i_sec, Info_sec *ss, Info_amb_sec *aa, Matrix2d &cost_amb, int i_amb_p) +{ + int i,j; + for(i=0;i=ss[i_sec].namb) + return ; //no lo tenía este sector + + //le quita de su array de índices si tiene al menos uno posterior + for(j=i;j &cost_amb, Info_sec *ss, Info_amb_sec *aa) +{ + int s, i,ii, j, k; + double d, dmax; + BOOL sec_cerc; + + //busca elementos------------------------------- + add_amb_sec(iamb_extr,n_amb,0,ss,aa,cost_amb,MAYUSCULO,-1); + //busca ambitos extremos-------------------- + for(s=1; s=0) + continue; + if(olv_limp->iaso[olv_limp->carto.get(j).entity()->ref].flgs & OLV_LIMP_FLG_AMB_NO)//se ha marcado para no usarse, por aislado o por carga insuficiente + { + aa[j].sec=-1; + continue; + } + + for (ii=0; ii=0) + break; + } + if(!sec_cerc && ii=0) + continue; + if(olv_limp->iaso[olv_limp->carto.get(j).entity()->ref].flgs & OLV_LIMP_FLG_AMB_NO)//se ha marcado para no usarse, por aislado o por carga insuficiente + continue; + + add_amb_sec(j,n_amb,n_sec-1,ss,aa,cost_amb,MAYUSCULO,-1); + k=j; + } + + return TRUE; +} +//************************************************************************************* +/** + * Añade el ámbito 'i_amb' al sector 'i_sec', actualizando la info en todos los lugares necesarios + * Actualiza el coste que es el que lleva, mas el desplazamiento del que ya tiene al nuevo, más el coste del nuevo + */ +BOOL Colv_limp_thr::add_amb_sec_cost(int i_amb, int namb, int i_sec, Info_sec *ss, Info_amb_sec *aa, Matrix2d &cost_amb) +{ + if(olv_limp->iaso[olv_limp->carto.get(i_amb).entity()->ref].flgs & OLV_LIMP_FLG_AMB_NO) + return FALSE; + ss[i_sec].iamb[ss[i_sec].namb]=i_amb; + ss[i_sec].namb++; + //apunta el ámbito al sector + aa[i_amb].sec=i_sec; + + //actualiza el coste del sector + //si no es el primer ámbito, suma el coste de ir del anterior a este + double dmed; + int k; + dmed=0; + if(ss[i_sec].namb>1) + { + //calcula la distancia media entre los extremos + for(k=0; k<3*olv_limp->tipo_ambit-2; k++) + { + dmed+=olv_limp->arch_dj.dame_dis(ss[i_sec].iamb[ss[i_sec].namb-1], k/2, i_amb,k%2); + } + dmed=dmed/(3*olv_limp->tipo_ambit-2); + ss[i_sec].cost_ac+=(float)dmed; + } + //suma el coste de hacer el ámbito + ss[i_sec].cost_ac+=cost_amb[i_amb][i_amb]; + + return TRUE; +} +//************************************************************************************* +/** + * Prueba sectorizacion algoritmo 1, expansion desde los mas dispares + */ +BOOL Colv_limp_thr::genera_sectores(int iamb_extr, int n_amb, int n_sec, Matrix2d &cost_amb, Info_sec *ss, Info_amb_sec *aa) +{ + int s, i,ii, j, jj, k, kk;//,jmin; + double d, dmax,dmed; + double cos_acum_sec; + int *isec=NULL; + int nord, isec_min; + BOOL hay_cambio=TRUE; + isec=(int*)malloc(n_sec*sizeof(int)); + memset(isec,0,n_sec*sizeof(int)); + if(!isec) + return FALSE; + //busca elementos------------------------------- + add_amb_sec_cost(iamb_extr,n_amb,0,ss,aa,cost_amb); + //busca ambitos extremos-------------------- + for(s=1; s=0) + continue; + if(olv_limp->iaso[olv_limp->carto.get(j).entity()->ref].flgs & OLV_LIMP_FLG_AMB_NO)//se ha marcado para no usarse, por aislado o por carga insuficiente + { + aa[j].sec=-1; + continue; + } + d=DBL_MAX; + for(i=0; i=i; k--) + isec[k+1]=isec[k]; + isec[i]=j; + nord++; + } + isec_min=nord-1; + hay_cambio=FALSE; + + } + else + { + isec_min--; + if(isec_min<0) + { + k=0; + kk=0; + for(j=0; j=0; ii--) + { + if(aa[aa[ss[j].iamb[i]].iamb_cerca[ii]].sec<0) + kk++; + } + } + } + if(kk>0 || k!=n_amb) + olvlog(LOG_TODO,"olv_limp_t","Error en la generacion de sectores, asignados %ld ambitos de %ld, existen %ld ambitos cercanos sin asignar",k, n_amb, kk); + break;//todos asignados + } + } + //intenta poner a sector de menor coste mas ambitos + cos_acum_sec=-1; + while(TRUE) + { + if(cos_acum_sec>=0) + { + if(cos_acum_sec==ss[isec[isec_min]].cost_ac) + break; + if(dmax=0; ii--) + { + j=aa[jj].iamb_cerca[ii]; + if(aa[j].sec>=0) + continue; + + //calcula la distancia media de ese ámbito cercano al sector al que lo intenta añadir + dmed=dame_dmed_amb_sec(j,isec[isec_min]); + if(dmed=d) + break; + if(aa[j].namb_cerca>2) + { + nord=0; + //busca si resto de ramas estan pilladas + l=-1; + for (s=0; s1) + break; + if( l<0) + l=aa[j].iamb_cerca[s]; + } + } + if(nord>1 ||l<0) + break; + + } + else if(aa[j].namb_cerca>1) + { + if(aa[j].iamb_cerca[0]==jj) + l=aa[j].iamb_cerca[1]; + else + l=aa[j].iamb_cerca[0]; + } + else + break; + jj=j; + j=l; + + + } + if(dacum2) + { + nord=0; + //busca si resto de ramas estan pilladas + l=-1; + for (s=0; s1) + break; + if(aa[j].iamb_cerca[s]!=jj && l<0) + l=aa[j].iamb_cerca[s]; + } + } + if(nord>1 || l<0) + break; + + } + else if(aa[j].namb_cerca>1) + { + if(aa[j].iamb_cerca[0]==jj) + l=aa[j].iamb_cerca[1]; + else + l=aa[j].iamb_cerca[0]; + } + else + break; + jj=j; + j=l; + }*/ + + } + } while (TRUE); + free(isec); + + return TRUE; +} +//************************************************************************************* +/** + * Devuelve la distancia media del sector isec al ámbito iamb + */ +double Colv_limp_thr::dame_dmed_amb_sec(int iamb, int isec) +{ + int i;//,j; + double dmed, dmedtot; + dmed=dmedtot=0; + //se recorre todos los ámbitos del sector + for (i=0; isec[isec].namb; i++) + { + dmed=dame_dmed_amb(i, iamb); + dmedtot+=dmed/olv_limp->sec[isec].namb; + } + return dmedtot; +} +//************************************************************************************* +/** + * Devuelve la distancia media entre ámbitos (sobre todo para cuando son lineales) + */ +double Colv_limp_thr::dame_dmed_amb(int iamb1, int iamb2) +{ + int k; + double dmed; + + dmed=0; + //calcula la distancia media entre los extremos de i e iamb + for(k=0; k<3*olv_limp->tipo_ambit-2; k++) + { + dmed+=olv_limp->arch_dj.dame_dis(iamb1, k/2, iamb2,k%2); + } + dmed=dmed/(3*olv_limp->tipo_ambit-2); + + return dmed; +} +//************************************************************************************* +/** + * Prueba sectorizacion algoritmo pro, sectoriza basado en ámbitos, no en sectores + */ +BOOL Colv_limp_thr::genera_sectores_pro(int n_sec, Matrix2d &cost_amb, Info_sec *ss, Info_amb_sec *aa) +{ + std::map> sec; + int i,j,jj,k,kk,s,s2,n,t; + double dmin,d,d1; + int nsec; + int namb; + BOOL mal=FALSE; + int nmax, bloq; + int oo[2]; + + //asigna cada ámbito a un sector + namb=olv_limp->n_amb; + bloq=1; + n=0; + for(i=0;iiaso[olv_limp->carto.get(i).entity()->ref].flgs & OLV_LIMP_FLG_AMB_NO)//se ha marcado para no usarse, por aislado o por carga insuficiente + { + aa[i].sec=-1; + n++; + continue; + } + aa[i].sec=i-n; + sec[i-n].push_back(i); + } + nsec=namb-n; + nmax=(int)(nsec/n_sec*1.3); + + //lo hace hasta que ya quedan solo el número de sectores que tienen que quedar + while(nsec>n_sec) + { + dmin=DBL_MAX; + k=kk=-1; + //recorre los ámbitos, y coge el que tenga un ámbito que pertenezca a + //otro sector que esté a la distancia mínima + for(i=0;iiaso[olv_limp->carto.get(i).entity()->ref].flgs & OLV_LIMP_FLG_AMB_NO)//se ha marcado para no usarse, por aislado o por carga insuficiente + continue; + //comprueba que el sector no esté creciendo demasiado + if(sec[aa[i].sec].size()>nmax) + continue; + for(j=0;jnmax) + continue; + //////////////////////////////// + //calcula la dist media entre el jj y todos los ámbitos del sector de i + d=0; + n=(int)sec[aa[i].sec].size(); + for (t=0; tn_amb, olv_limp->amb_sec, olv_limp->ord_sec)) + { + sprintf_s(err_str,OLV_MAX_ERR,"Error al rellenar ambitos cercanos por carretera"); + return FALSE; + } + + //comprueba islas + if(!quita_islas(olv_limp->n_amb, olv_limp->amb_sec, olv_limp->ord_sec)) + { + olvlog(LOG_TODO,"quita_islas","No consigue eliminar islas"); + + } + ////////////////////// + //Como primer ámbito coge el más extremo + //el de menor 'y+x' + maxx=MAYUSCULO; + int ref_amb; + for(i=0;in_amb;i++) + { + ref_amb = olv_limp->carto.get(i).entity()->ref; + if(olv_limp->iaso[ref_amb].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + if((olv_limp->conjs.coor[olv_limp->iaso[ref_amb].inod[0]][1]+olv_limp->conjs.coor[olv_limp->iaso[ref_amb].inod[0]][0])conjs.coor[olv_limp->iaso[ref_amb].inod[0]][1]+olv_limp->conjs.coor[olv_limp->iaso[ref_amb].inod[0]][0]; + iamb=i; + } + } + + if((iamb<0) || (iamb>=olv_limp->n_amb)) + { + sprintf_s(err_str,OLV_MAX_ERR,"Error no se ha encontrado ambito extremo"); + return FALSE; + } + + if(pirate) + { + sprintf_s(err_str,OLV_MAX_ERR,"Sale por peticion de usuario"); + return FALSE; + } + + //si se ha calculado el número de sectores ya se ha sectorizado inicialmente, no hay que llamar a genera_sectores + int nsec; + if(olv_limp->calc_nsec==0) + { + nsec=olv_limp->nsec; + } + else + { + nsec=olv_limp->nsec_act; + //entra aquí si ha calculado el número de sectores, y ya va a sectorizar + //en este modo, primero usa solo los dos primeros sectores, al primero le da un ámbito y al segundo el resto de ámbitos + + } + if(!genera_sectores_pro(nsec,olv_limp->cost_amb,olv_limp->sec, olv_limp->amb_sec)) + { + sprintf_s(err_str,OLV_MAX_ERR,"Error al generar sectores"); + return FALSE; + } + + guarda_dbf_sector(0); + + pon_mi_progre(OLV_TAREA_PERMU,0); + if(olv_limp->nsec>1) + { + if(olv_limp->calc_nsec==0) + { + dd=iguala_sectores4(olv_limp->n_amb, olv_limp->nsec, olv_limp->cost_amb, olv_limp->sec, olv_limp->amb_sec); + } + else + { + //entra aquí si ha calculado el número de sectores, y ya va a sectorizar + dd=iguala_sectores5(iamb,olv_limp->n_amb, olv_limp->nsec, olv_limp->cost_amb, olv_limp->sec, olv_limp->amb_sec); + } + olvlog(LOG_TODO,"olv_limp_t","Conseguida una desviación de: %lf",dd); + } + else + { + olv_limp->sec[0].cost_ac=(float)calcula_cost_1sec_total(olv_limp->n_amb,olv_limp->sec,olv_limp->ang_conj); + if(olv_limp->sec[0].cost_ac>=MAYUSCULO) + dd=-1; + } + + if(dd<0)//si es -2, aislados, ya lo ha puesto el iguala_sectores4 + { + if(dd==-2) + sprintf_s(err_str,OLV_MAX_ERR,"Existen ámbitos aislados que\nno ha sido posible unir a la red"); + return FALSE; + } + + return TRUE; +} +//************************************************************************************* +/** +* parte del ambito central del sector y crea el arbol de camino minimo de dicho sector + marca en cada ambito quien es su padre y cuantos hijos tiene + devuelve el numero de ambitos frontera +**/ +int Colv_limp_thr::asigna_padres(int amb_central, int namb, Matrix2d &cost_amb, Info_sec *ss, Info_amb_sec *aa, int *buf, int nhijos_fron) +{ + int i,j; + int psel,sel; + double d, dsel=MAYUSCULO; + int nn=1; + int oo[2]; + + for (i=0; inamb; i++) + { + if(aa[ss->iamb[i]].iseq!=-1) + { + olvlog(LOG_TODO,"olv_limp_t","Error en iasigna_padres, Ambito %d ya tiene padre asignados, sec %d",ss->iamb[i], aa[ss->iamb[i]].sec); + + + } + } + buf[0]=amb_central; + aa[amb_central].iseq=-2; + aa[amb_central].t=0; + while(nnnamb) + { + dsel=MAYUSCULO; + sel=-1; + for (i=0; inamb; j++)//recorre ambitos del sector + { + if(aa[ss->iamb[j]].iseq!=-1) + continue; + d=dis_min_amb(oo,buf[i],NULL, false,ss->iamb[j]);//cost_amb[buf[i]][ss->iamb[j]]; + if(diamb[j]; + psel=buf[i]; + } + } + } + if(sel<0) + { + olvlog(LOG_TODO,"olv_limp_t","Error en iasigna_padres, no encontrado ambitos libres sin padres"); + break;//terminado (esto no deberia pasar) + } + if(aa[psel].iseq<0) + aa[psel].iseq=sel; + buf[nn]=sel; + aa[sel].iseq=psel; + aa[sel].t+=1; + aa[psel].t+=1; + nn++; + } + //recorre ambitos para pillar los ambitos frontera---------------- + d=0; + j=recorre_hijos(amb_central, namb, aa, NULL, 0, cost_amb, &d); + if((j+1)!=nn) + olvlog(LOG_TODO,"olv_limp_t","Error en iasigna_padres,Existen hijos aislados"); + + nn=0; + for(j=0; jnamb; j++)//recorre ambitos del sector + { + if(aa[ss->iamb[j]].t<=nhijos_fron) + buf[nn++]=ss->iamb[j]; + } + + + return nn; +} +//************************************************************************************* +double Colv_limp_thr::dis_min_amb(int ids[2], int id_nod_ini, Secu_amb * ord_sec, BOOL res_nod, int iamb) +{ + double dd=MAYUSCULO; + double dis; + double dd2=MAYUSCULO; + ids[0]=ids[1]=0; + CartoLine line1, line2; + + double p1[3], p2[3]; + p1[2]=p2[2]=0; + int i; + + //si puntuales, entra una vez, si lineales, entra cuatro + for(int k=0; k<3*olv_limp->tipo_ambit-2; k++) + { + dis=olv_limp->arch_dj.dame_dis(id_nod_ini, k/2, iamb,k%2); + if(disiaso[olv_limp->carto.get(id_nod_ini).entity()->ref].inod[ids[1]]; + } + + //////////////////////////////////////////////////////////// + if(OLV_PORC_LINRECT==0) + dd2=0; + else + { + if(olv_limp->tipo_ambit==OLV_AMB_LIN) + { + line1.pts.n=0; + line2.pts.n=0; + for(i=0;i<2;i++) + { + line1.addPto(olv_limp->conjs.coor[olv_limp->iaso[id_nod_ini].inod[i]]); + line2.addPto(olv_limp->conjs.coor[olv_limp->iaso[iamb].inod[i]]); + } + dd2=line1.disMedLines(&line2); + } + else + { + dd2=GeometryFunction::Dist2d(olv_limp->conjs.coor[olv_limp->iaso[id_nod_ini].inod[0]],olv_limp->conjs.coor[olv_limp->iaso[iamb].inod[0]]); + } + + //pasa de dist a segundos + double velo; + if(olv_limp->v_despl==0) + velo=OLV_LIMP_VELO_CIRC_NW*OLV_KMH2MS; + else + velo=olv_limp->v_despl; + dd2=dd2/velo; + } + + //////////////////////////////////////////////////////////// + //return dd; + return dd*(1-OLV_PORC_LINRECT)+dd2*OLV_PORC_LINRECT; +} +//************************************************************************************* +typedef struct Dists +{ + double dist; + int iamb; +}Dists; +//************************************************************************************* +BOOL Colv_limp_thr::quita_islas(int namb, Info_amb_sec *aa, Secu_amb * ord_sec) +{ + int nis =-1, i; + if(namb<2) + return true; + short* islas = (short*) malloc(namb * sizeof(short)); + + if(!islas) + return false; + //marca todos los ambitos sin islas + for (i=0;i amb_pend; + for (i=0;iiaso[olv_limp->carto.get(i).entity()->ref].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + if(islas[i]>-1) + continue; + nis++; + amb_pend.push(i); + while(!amb_pend.empty()) + { + int amb_act=amb_pend.top(); + amb_pend.pop(); + islas[amb_act]=nis; + //añade cercanos a la pila + for (int k =0 ; k-1) + continue; + amb_pend.push(aa[amb_act].iamb_cerca[k]); + } + + } + } + olvlog(LOG_TODO,"quita_islas","Numero de islas %ld",nis); + + if(nis<1) + goto va_bien; + + //quita islas + int iamb=-1; + int iamb_cerca=-1; + int oo[2]; + double dis, dd; + for (int kis = nis; kis>0; kis--) + { + iamb=-1; + iamb_cerca=-1; + dis=MAYUSCULO; + for (i=0; iiaso[olv_limp->carto.get(i).entity()->ref].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + if(islas[i]!= kis) + continue; + for (int ii = 0; iiiaso[olv_limp->carto.get(ii).entity()->ref].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + if(islas[ii]== kis) + continue; + dd = dis_min_amb(oo,i,NULL, false,ii); + if(ddconjs.n); + if(!secu1) + { + olvlog(LOG_TODO,"rellena_amb_cercanos_por_carretera","Sin memoria para ambitos"); + return FALSE; + } + + Dists dis_[MAX_LEN_BUF_CERCANAS]; + + rmax=RMAX_INI; + + //matriz de conexion con ambitos (te dice si una conjuncion esta conectada con un ambito y en ese caso con cual. -1 en caso contrario) + conex = (int*) malloc(olv_limp->conjs.n * sizeof(int)); + if (!conex) + { + olvlog(LOG_TODO,"rellena_amb_cercanos_por_carretera","Sin memoria para conjunciones"); + return FALSE; + } + for (n=0;nconjs.n;n++) + conex[n]=-1; + // matriz de distancias (olv_limp->cost_conj[][]) + //olv_limp->tipo_ambit//indica que tipo de ambitos estamos tratando1 si es puntual 2 si es lineal + //olv_limp->ias[0].ic[0]id de la conjunion 1 del ambito 0 + //olv_limp->ias[0].ic[1]id de la conjunion 2 del ambito 0 + //bucle por todos los ambitos + //bucle por todos los nodos del ambito + //bucle por todos los nodos + //marcas en el array si el nodo es el del ambito o si tiene conexion directa con dicho ámbito + for (n=0;nconjs.n;n++) + { + for (i=0;icarto.get(i).entity()->ref; + if(olv_limp->iaso[ref_i].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + for (j=0;jtipo_ambit;j++) + { + if (olv_limp->iaso[ref_i].inod[j]==n ) + { + //Ha encontrado que esta conjunción conecta con el ámbito iésimo + conex[n]=i; + //Sale de los dos bucles + i=namb; + break; + } + else if(olv_limp->cost_conj[n][olv_limp->iaso[ref_i].inod[j]]!=(float)MAYUSCULO && conex[n]==-1) + { + conex[n]=i; + } + } + } + } + + if(logdebug) + { + for(j=0;jconjs.n;j++) + { + olvlog(LOG_TODO,"rellena_amb_cercanos_por_carretera","n %ld conex[n] %ld",j, conex[j]); + } + } + + secu2=&secu1[olv_limp->conjs.n]; + for(j=0; jarch_dj.dame_buf_nodos(FALSE); + buf_aux[1]=olv_limp->arch_dj.dame_buf_nodos(FALSE); + + if(!buf_aux[0] || !buf_aux[1]) + { + olvlog(LOG_TODO,"rellena_amb_cercanos_por_carretera","Sin memoria para buffer de nodos"); + goto va_mal; + } + + for (j=0; jcarto.get(j).entity()->ref; + if(olv_limp->iaso[ref_j].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + cargado[0]=FALSE; + cargado[1]=FALSE; + for (i=0; icarto.get(i).entity()->ref; + if(j==i) + continue; + if(olv_limp->iaso[ref_i].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + //selecciona distancia minima de un ambito a otro + dd=dis_min_amb(oo,i,&ord_sec[j], TRUE, j); + if(dd>=MAYUSCULO)//sin conexion entre ambitos + continue; + + //cargar ambito antes de archivo------------------- + if(!cargado[oo[0]]) + { + olv_limp->arch_dj.get_b(j,oo[0],buf_aux[oo[0]]); + cargado[oo[0]]=TRUE; + } + //se verifica que en los cercanos no se pase por los mismos nodos + Colv_geom::ruta_dj_inv_ok(oo[1], secu1, buf_aux[oo[0]],olv_limp->conjs.n, &r1); + + + //Recorre los nodos de la ruta entre esos ámbitos para ver si alguno de los nodos no conecta directamente + //con algún ámbito, en cuyo caso lo descarta + //o lo descarta también si lleva varios nodos de carretera seguidos + rr=0; + for (n=0;n0 && conex[secu1[n]]==-1 && conex[secu1[n-1]]==-1) + rr++; + else if( n<(r1-2)) + rr=0; + } + if (n=MAX_LEN_BUF_CERCANAS) + continue; + + aa[i].iamb_cerca[aa[i].namb_cerca]=j | (rr<<24); + aa[i].namb_cerca++; + } + } + + //ordena------------- + for (i=0;icarto.get(i).entity()->ref; + if(olv_limp->iaso[ref_i].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + + memset(dis_,0,sizeof(Dists)*MAX_LEN_BUF_CERCANAS); + if(aa[i].namb_cerca<=0) + { + aa[i].namb_cerca=aa[i].namb_cerca; + olvlog(LOG_TODO,"rellena_amb_cercanos_por_carretera","iamb %ld 0 cercanos",i); + continue; + } + + for(j=0;j>24; + dis_[j].dist=dis_min_amb(oo,i,&ord_sec[aa[i].iamb_cerca[j] & 0x00ffffff], TRUE, aa[i].iamb_cerca[j] & 0x00ffffff); + dis_[j].iamb=aa[i].iamb_cerca[j]; + } + + qsort(dis_,aa[i].namb_cerca,sizeof(Dists),Colv_limp_thr::compara_dist_cerc); + + if(logdebug) + { + for(j=0;j>24, dis_[j].dist); + } + } + + for(j=0;j0 ;j--) + { + r1=(aa[i].iamb_cerca[j-1] & 0xff000000)>>24; + r2=(aa[i].iamb_cerca[j] & 0xff000000)>>24; + if(r1>0 || r2>0) + r1=r1; + if((r2-r1)>RMAX_INI) + aa[i].namb_cerca=j; + + } + + for(j=0;j>24); + } + aa[i].iamb_cerca[j]= aa[i].iamb_cerca[j] & 0x00ffffff; + } + } + olv_limp->arch_dj.libera_buf(buf_aux[0]); + olv_limp->arch_dj.libera_buf(buf_aux[1]); + if(secu1) + free(secu1); + if(conex) + free(conex); + + return TRUE; +va_mal: + olv_limp->arch_dj.libera_buf(buf_aux[0]); + olv_limp->arch_dj.libera_buf(buf_aux[1]); + + if(conex) + free(conex); + if(secu1) + free(secu1); + return FALSE; + +} +//************************************************************************************* +/** + * Compara las estructuras Dist. Las ordena por distancia + */ +int Colv_limp_thr::compara_dist_cerc (const void * a, const void * b) +{ + //si adist - ((Dists*) b)->dist); +} +//************************************************************************************* +/** + * Busca el sector más cercano a un ámbito + * busca el ambito frontera de iamb mas cercano al sector id_sec + * si modo==1 busca se busca a cualquier sector menos id_sec + */ +int Colv_limp_thr::busca_sec_cerca_amb(Info_amb_sec *aa,int iamb, int id_sec, int modo) +{ + int i,s,ia; + if(id_sec<0) + return -1; + for(i=0; i=i; k--) + isec[k+1]=isec[k]; + isec[i]=j; + nord++; + } + return isec; +} +//************************************************************************************* +/** + * Algoritmo 5 de igualación de sectores, pasando ámbitos de un sector a otro que tenga cerca + */ +double Colv_limp_thr::iguala_sectores5(int iamb, int n_amb, int n_sec, Matrix2d &cost_amb, Info_sec *ss, Info_amb_sec *aa) +{ + double desv; + int res; + enum Res{ + RES_SALE_BIEN, + RES_SALE_MAL, + RES_NO_SALE, + RES_GENERA, + }; + int i,j; + + desv=0; + + //llama al iguala_sect4 con, al principio sólo 2 sectores activos + //luego comprueba si el último de los nsec su coste es mayor que la jornada + //y si es así, nsec_act++, cuidando que no pase de nsec + //se le añade un ámbito, el más lejano de nsec_act + //si su coste es cero, nsec_act-- + //si es el coste es >0 y <= que el coste jornada, todo ok + do + { + olvlog(LOG_TODO,"olv_limp_t","Iguala sectores 5 con %ld sectores", olv_limp->nsec_act); + desv=iguala_sectores4( n_amb, olv_limp->nsec_act, cost_amb, ss, aa); + if(desv<0) + { + //sale mal + res=RES_SALE_MAL; + continue; + } + if(ss[olv_limp->nsec_act-1].cost_ac==0) + { + if((olv_limp->nsec_act-1)<=0) + { + //sale bien, pero forzado, no debería salir por aquí.. + res=RES_SALE_BIEN; + continue; + } + olv_limp->nsec_act--; + res=RES_GENERA; + } + else if(ss[olv_limp->nsec_act-1].cost_ac>olv_limp->calc_nsec) + { + //añade un sec activo, siempre que haya disponibles + if((olv_limp->nsec_act+1)>olv_limp->nsec) + { + //sale bien, pero forzado, no debería salir por aquí.. + res=RES_SALE_BIEN; + continue; + } + olv_limp->nsec_act++; + //llama de nuevo al genera_sectores + res=RES_GENERA; + } + else + { + //sale bien + res=RES_SALE_BIEN; + } + if(res==RES_GENERA) + { + ////////////////////////////////////////////////////////////// + //reinicializa + for(i=0;insec;i++) + { + olv_limp->sec[i].namb=0; + olv_limp->sec[i].iamb_ini_def=-1; + olv_limp->sec[i].t_despl[0]=olv_limp->sec[i].t_despl[1]=(float)olv_limp->t_despl; + for(j=0;jn_amb;j++) + { + olv_limp->sec[i].iamb[j]=-1; + } + } + //reinicializa + for(j=0;jn_amb;j++) + { + olv_limp->amb_sec[j].sec=-1; + olv_limp->amb_sec[j].iseq=-1; + olv_limp->amb_sec[j].t=0; + } + ////////////////////////////////////////////////////////////// + if(!genera_sectores3(iamb,olv_limp->n_amb,olv_limp->nsec_act,olv_limp->cost_amb,olv_limp->sec, olv_limp->amb_sec)) + { + //sale mal + res=RES_SALE_MAL; + } + } + + } while (res>=RES_NO_SALE); + + if(res==RES_SALE_MAL) + return -1; + + //si sale bien, libera el espacio libre + if(olv_limp->nsec_actnsec) + { + for(int i=olv_limp->nsec_act;insec;i++) + { + if(olv_limp->sec[i].cost_amb_sec) + { + free(olv_limp->sec[i].cost_amb_sec); + olv_limp->sec[i].cost_amb_sec = NULL; + } + if(olv_limp->sec[i].cost_amb_sec_aux) + { + free(olv_limp->sec[i].cost_amb_sec_aux); + olv_limp->sec[i].cost_amb_sec_aux = NULL; + } + if(olv_limp->sec[i].iamb) + { + free(olv_limp->sec[i].iamb); + olv_limp->sec[i].iamb = NULL; + } + } + Info_sec* sec_aux; + sec_aux=(Info_sec*)realloc(olv_limp->sec,olv_limp->nsec_act*sizeof(Info_sec)); + if(!sec_aux) + return -1; + olv_limp->sec=sec_aux; + olv_limp->nsec=olv_limp->nsec_act; + } + + return desv; +} +//************************************************************************************* +/** + * Algoritmo 4 de igualación de sectores, pasando ámbitos de un sector a otro que tenga cerca + */ +double Colv_limp_thr::iguala_sectores4(int n_amb, int n_sec, Matrix2d &cost_amb, Info_sec *ss, Info_amb_sec *aa) +{ + double desv; + double desv_last,cos_min, cos_min_last, cos_max, cos_max_last; + double desv_abs_old, desv_abs; + double d, d1; + BYTE* st=NULL; + int *isec=NULL, *iamb_r=NULL, j, i, ii, jj,k; + int sec_m=0; + int sselc=-1; + int iamb,ip, sec; + int nth=Colv_geom::dame_n_nucleos(); + Secu_amb * ord_sec=olv_limp->ord_sec; + th_param_planif thp; + memset(&thp, 0, sizeof(thp)); + thp.milis_sleep=1; + thp.namb_t=n_amb; + thp.abs=TRUE; + desv_last=dame_desv_sec(n_sec,ss, TRUE,&desv_abs_old); + BOOL log_debug=FALSE; + BOOL todo_ok=FALSE; + BOOL aisladas=FALSE; + char nfile[MAX_PATH]; + BOOL nocalc=FALSE; + ii=jj=0; + iamb=-1; + + strcpy_s(nfile,MAX_PATH,olv->paths.path_data); + //cambiaext(nfile,".shp",".dbf"); + strcpy((Cdir_manager::extension_archivo(nfile)),"dbf"); + + //////////////////////////////////////////// + //avisa de progreso + olvlog(LOG_TODO,"olv_limp_t","Calculando permutaciones para mejorar al igualar sectores"); + pon_mi_progre(OLV_TAREA_PERMU,0); + //////// + + thp.dth=(th_data_planif*)malloc(sizeof(th_data_planif)*nth); + memset(thp.dth, 0, sizeof(th_data_planif)*nth); + + for (i=0; i=0) + Sleep(1); + + } + ///////////////////////////////////// + sec=-1; + desv=iguala_sectores3(n_amb, n_sec, cost_amb, ss, aa, ord_sec, &thp); + if(desv>=MAYUSCULO) + { + sprintf_s(err_str,OLV_MAX_ERR,"Error en iguala_sect3"); + goto salir; + } + desv_last=dame_desv_sec(n_sec,ss, TRUE, &desv_abs_old); + + olvlog(LOG_TODO,"olv_limp_t","Iguala sectores 4. Desv: %lf",desv_last); + + if(olv_limp->calc_nsec<=0) + cos_max_last=dame_mima(n_sec, ss,&cos_min_last); + else + cos_max_last=cos_min_last=0; + iamb_r=(int*)malloc(sizeof(int)*n_amb*2); + if(!iamb_r) + { + sprintf_s(err_str,OLV_MAX_ERR,"Error al pedir memoria"); + goto salir; + } + + st=guarda_estado(n_amb,n_sec,aa,ss,st); + + if(!st) + { + sprintf_s(err_str,OLV_MAX_ERR,"Error al guardar estado"); + goto salir; + } + do + { + + if(((desv_lastDESV_MAX) && (desv_abs_old<=olv_limp->DESV_MAX_ABS)) || (desv_abs_old<=olv_limp->DESV_MAX_ABS) || fin_permu) + { + todo_ok=TRUE; + break; + } + //ordena sectores por coste-------------------------- + isec=ordena_sec(n_sec,ss,isec); + //selecciona sector a bloquear + do + { + //elije un sector con mas de un ambito (para poder quitarle uno) + sselc=isec[sec_m]; + if(ss[sselc].namb>1) + break; + sec_m++; + } + while(sec_m>=n_sec-1); + + if(sec_m>=n_sec-1) + { + todo_ok=TRUE; + break; + } + //busca ambito mas pequeño posible que tenga otro de otro sector más cerca + d=MAYUSCULO; + iamb=-1; + for (i=0; iiaso[olv_limp->carto.get(ss[sselc].iamb[i]).entity()->ref].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + for (j=0; j=0) + { + d=d1; + iamb=ss[sselc].iamb[i]; + ip=k; + sec=aa[k].sec; + } + } + } + if(d>=MAYUSCULO || sec<0) + { + sprintf_s(err_str,OLV_MAX_ERR,"Error, no encuentra más ámbitos cercanos"); + if(desv=desv_last) + { + if(olv_limp->calc_nsec<=0 && desv==desv_last) + cos_max=dame_mima(n_sec, ss, &cos_min); + else + cos_max=cos_min=0; + + if( desv>desv_last || (((cos_max-cos_min)>= (cos_max_last-cos_min_last)))) + + { + //se vuelve a estado anterior + pon_estado(n_amb,n_sec,aa,ss,cost_amb,st); + + desv=dame_desv_sec(n_sec,ss, TRUE); + if(desv!=desv_last) + olvlog(LOG_TODO,"olv_limp_t","Iguala sectores 4. Error no coincide desv anterior Desv: %lf Desv_old",desv, desv_last); + sec_m++; + if(sec_m>=n_sec-1) + { + todo_ok=TRUE; + break; + } + continue; + + } + sec_m=0; + } + sec_m=0; + olvlog(LOG_TODO,"olv_limp_t","Iguala sectores 4. Cambio mejora desv old: %lf, new %lf",desv_last, desv); + desv_last=desv; + desv_abs_old=desv_abs; + cos_max_last=cos_max; + cos_min_last=cos_min; + + st=guarda_estado(n_amb,n_sec,aa,ss,st); + if(!st) + { + sprintf_s(err_str,OLV_MAX_ERR,"Error al guardar estado anterior"); + goto salir; + } + } while (!pirate); + if(!todo_ok) + goto salir; + + st=guarda_estado(n_amb,n_sec,aa,ss,st); + if(!st) + goto salir; + + /* + if(olv_limp->calc_nsec>0) + todo_ok=FALSE;//se reinicia para ver si la siguiente parte todo_ok + while(olv_limp->calc_nsec>0 && !pirate) + { + if((desv_lastMAYUSCULO) + continue; + quita_amb_sec(iamb,n_amb,sselc,ss,aa,cost_amb,aa[iamb].iseq); + add_amb_sec(iamb,n_amb,sec,ss,aa,cost_amb,MAYUSCULO,ip); + + for (ii=0; ii=desv_last) + { + //se vuelve a estado anterior + pon_estado(n_amb,n_sec,aa,ss,cost_amb,st); + + desv=dame_desv_sec(n_sec,ss, TRUE); + if(desv!=desv_last) + desv_last=desv; + continue; + } + olvlog(LOG_TODO,"olv_limp_t","Iguala sectores4. Cambio mejora desv old: %lf, new %lf",desv_last, desv); + desv_last=desv; + st=guarda_estado(n_amb,n_sec,aa,ss,st); + if(!st) + { + sprintf_s(err_str,OLV_MAX_ERR,"Error al guardar estado"); + goto salir; + } + break; + + } + } + if(i>=ss[sselc].namb) + { + todo_ok=TRUE; + break; + } + } + */ + +salir: + if(log_debug) + { + olvlog(LOG_TODO,"olv_limp_t","------------------------------------------------"); + for(i=0;i0) + Sleep(1); + if(iamb_r) + free(iamb_r); + if(st) + free(st); + free(isec); + + if(thp.dth) + { + if(thp.dth[0].sec) + free(thp.dth[0].sec); + free(thp.dth); + + } + + if(!todo_ok) + { + olvlog(LOG_TODO,"olv_limp_t","Errores varios en iguala_sectores4"); + if(aisladas) + return -2; + return -1; + } + return desv_last; +} +//************************************************************************************* +/** + * Recorre los 'nesc' sectores igualando su coste + * La idea es poner ambitos a los sectores de menor coste manteniendo la condicion de no aisladas + */ +#define MAX_AMBI_IGUALA_SEC 500 +double Colv_limp_thr::iguala_sectores3(int n_amb, int n_sec, Matrix2d &cost_amb, Info_sec *ss, Info_amb_sec *aa, Secu_amb * ord_sec, th_param_planif *thp) +{ + double desv,desv_last, desv_fut,desv_abs;//máxima desviación permitida respecto a la media + BOOL hay_cambio,log_debug, prime; + int *amb_fron;//indice a ambitos frontera de sectores + int *isec=NULL;//indice a sectores (ordenados de mayor a menor) + int *icerca;//indice a ambitos cercanos a los frontera de un sector + int *icamb;//indices a ambitos cambiados de sector en un pasp + int cambio[2][2];//[0]ambito y sector que se pasa al[1] ambito (padre) y sector + int siz_sec=(n_amb+1); + int j, i, k,kk, kkk; + int isec_min; + int ncerca; + int nhijos_frontera=10; + int namb_camb; + int ind_camb; + int nais=0; + //------------------------------- + + log_debug=TRUE; + if(log_debug) + olvlog(LOG_TODO,"olv_limp_t","Empieza igualacion de sectores 3"); + isec=(int*)malloc(sizeof(int)*(1+n_sec*(n_amb+1)+n_sec+n_amb*5)); + memset(isec,0,sizeof(int)*(1+n_sec*(n_amb+1)+n_sec+n_amb*5)); + + desv_last=desv_abs=MAYUSCULO; + prime=TRUE; + + if(!isec) + { + olvlog(LOG_TODO,"olv_limp_t","Error en igualacion de sectores 3, sin memoria para bufferes"); + return desv_last;//no debería pasar + } + icerca=&isec[n_sec+1]; + icamb=&icerca[n_amb*2]; + amb_fron=&icamb[n_amb*3]; + + //calcula media y desviacion de costes en sectores + //bucle + hay_cambio=TRUE; + ind_camb=-1; + for(j=0; jDESV_MAX) && (desv_abs<=olv_limp->DESV_MAX_ABS)) || (desv_abs<=olv_limp->DESV_MAX_ABS) || fin_permu)//if(desv_lastcalc_nsec) + { + isec[0]=n_sec-1; + ordena_sec(n_sec-1, ss, &isec[1]); + isec_min=n_sec-1; + } + else + { + ordena_sec(n_sec, ss, isec); + isec_min=n_sec-1; + } + hay_cambio=FALSE; + if(log_debug && ind_camb>=0) + olvlog(LOG_TODO,"olv_limp_t","Iguala sectores 3, mejorada desviacion tipica a %lf", desv_last); + } + else + { + isec_min--; + if(isec_min<=0) + break;//no se puede mejorar mas + } + //busca fronteras de otros sectores cercanas al sector isec_min + if(ss[isec[isec_min]].flags_tem& OLV_LIMP_FLG_SEC_INFO_BLOCK) + continue; + ncerca=0; + for(j=0; j=0; i--) + { + //verifica que tenga ambitos cercanos de otros sectores + //si es asi añade al array + k=busca_sec_cerca_amb(aa,amb_fron[kk+i], isec[isec_min],1); + if(k>=0) + { + icerca[ncerca*2]=k; + icerca[ncerca*2+1]=amb_fron[kk+i]; + ncerca++; + } + } + continue; + } + //recore ambitos frontera de sector j + kk=isec[j]*siz_sec+1; + for(i=amb_fron[isec[j]*siz_sec]-1; i>=0; i--) + { + k=busca_sec_cerca_amb(aa,amb_fron[kk+i], isec[isec_min]); + if(k>=0) + { + icerca[ncerca*2]=amb_fron[kk+i]; + icerca[ncerca*2+1]=k; + ncerca++; + } + } + } + if(ncerca<=0) + continue;//no se puede mejorar + if(ncerca>n_amb) + ncerca=ncerca; + desv_fut=MAYUSCULO; + ind_camb=-1; + for(i=0; imilis_sleep=0; + calcula_coste_1sec(ord_sec, &ss[cambio[0][1]], thp,FALSE); + calcula_coste_1sec(ord_sec, &ss[cambio[1][1]], thp,FALSE); + thp->milis_sleep=1; + } + //comprueba mejora o no----------------------- + desv=dame_desv_sec(n_sec,ss,TRUE,&desv_abs); + + if(desvdesv) + { + desv_fut=desv; + ind_camb=i; + } + } + //se deshace el cambio-------------------------- + for (j=0; jn_amb>=MAX_AMBI_IGUALA_SEC && ind_camb>=0) + break; + } + if(ind_camb>=0) + { + cambio[0][0]=icerca[ind_camb*2];//se pone este + cambio[0][1]=aa[cambio[0][0]].sec; + cambio[1][0]=icerca[ind_camb*2+1];//con padre este + cambio[1][1]=aa[cambio[1][0]].sec; + namb_camb=1; + icamb[0]=cambio[0][0]; + icamb[1]=cambio[1][0]; + icamb[2]=cambio[0][0]; + for (j=0; jmilis_sleep=0; + calcula_coste_1sec(ord_sec, &ss[cambio[0][1]], thp,FALSE); + calcula_coste_1sec(ord_sec, &ss[cambio[1][1]], thp,FALSE); + thp->milis_sleep=1; + } + //comprueba mejora o no----------------------- + double desv_lastold=desv_last; + desv_last=dame_desv_sec(n_sec,ss,TRUE,&desv_abs); + + if(desv_lastoldOJO -->El cambio selec empeora des_act:%lf desv_obt: %lf",desv_lastold, desv_last); + //se deshace el cambio-------------------------- + for (j=0; jOJO -->Se quita cambio y queda desv: %lf",desv_last); + hay_cambio=FALSE; + } + else + hay_cambio=TRUE; + } + else + { + hay_cambio=FALSE; + } + } while (TRUE); + //fin ---------------------------------------------------------- + + if(isec) + free(isec); + if(FALSE) + { + olvlog(LOG_TODO,"olv_limp_t","------------------------------------------------"); + + for(i=0;icalc_nsec>0) + { + cost_med=olv_limp->calc_nsec; //impone el coste medio de los sectores, que es justo la jornada laboral + nsec--; //se quita un sector, el último, para el cálculo de la media + } + else + { + for(j=0;jcalc_nsec>0) && (dd>0)) + { + dd+=cost_med*nsec*2; + } + aux=abs(dd); + if(aux>cost_max) + cost_max=aux; + cost_med2+=dd*dd/nsec; + } + if(olv_limp->calc_nsec>0) + { + if(((ss[nsec].cost_ac-cost_med)>0))//si está en modo fijar jornada, tampoco queremos que se desmadre el último + { + aux=cost_med; + if(aux>cost_max) + cost_max=aux; + cost_med2+=cost_med*cost_med/nsec; + } + } + if(cost_med2>MINUSCULO) + cost_med2=sqrt(cost_med2); + else + cost_med2=0; + if(absol) + *absol=cost_max; + if(porc) + return cost_med2/cost_med; + else + return cost_med2; +} +//************************************************************************************* +/** + * Calcula diferencia minima y maxima de costes entre sectores + */ +double Colv_limp_thr::dame_mima(int nsec, Info_sec *ss, double *mini) +{ + int i; + int j; + double costmax=-MAYUSCULO; + double costmin=MAYUSCULO; + double dd; + + + //calcula la desviación típica + for(j=0;jcostmax) + costmax=dd; + if (ddiseq=aa[a].iseq; + inf->sec=aa[a].sec; + inf->t=aa[a].t; + + } + for (a=0; a &cost_amb, BYTE* st ) +{ + int i, k=0, s; + Info_est_amb *inf; + //prepara todo a 0--------------------- + for (i=0; iiseq; + aa[i].t=inf->t; + aa[i].sec=inf->sec; + s=inf->sec; + if(s>=0) + ss[s].iamb[ss[s].namb++]=i; + } + for (i=0; i &cost_amb, double *cost, BOOL inicia) +{ + int i, h; + int oo[2]; + if(inicia) + { + for (i=0; iiaso[olv_limp->carto.get(i).entity()->ref].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + if(aa[i].iseq!=iamb) + continue; + if(aa[i].res) + continue; + if(i==iamb) + continue; + aa[i].res=1; + *cost+=dis_min_amb(oo,iamb,NULL, false,i)+cost_amb[i][i];//cost_amb[iamb][i]+cost_amb[i][i]; + if(iamb_r) + { + iamb_r[namb_r*2]=i; + iamb_r[namb_r*2+1]=iamb; + } + namb_r++; + if(namb_r>namb) + namb_r=namb_r; + if(aa[i].t>1) + namb_r=recorre_hijos(i,namb, aa, iamb_r, namb_r, cost_amb, cost, FALSE); + h--; + if(h<=-2) + break; + } + return namb_r; +} +//************************************************************************************* +/** + * Actualiza la matriz de costes de los ámbitos a otros ámbitos + */ +BOOL Colv_limp_thr::actualiza_costes( int namb,int n_sec, Info_amb_sec *aa, Info_sec *ss, Matrix2d &cost_amb ) +{ + + int s, a, i, na, k, kk, p; + double d; + BOOL res=TRUE; + for (a=0; a=namb) + continue; + na=ss[s].namb; + ss[s].namb=1; + ss[s].iamb[0]=a; + ss[s].cost_ac=cost_amb[a][a]; + aa[a].res=1; + while(TRUE) + { + k=-1; + d=MAYUSCULO; + for(i=0; icost_amb[kk][a]) + { + d=cost_amb[kk][a]; + p=kk; + k=a; + } + } + } + if (k<0) + { + break; + } + ss[s].cost_ac+=cost_amb[p][k]+cost_amb[k][k]; + aa[k].res=1; + ss[s].iamb[ss[s].namb++]=k; + } + if(na!=ss[s].namb) + res=FALSE; + + + } + + return res; +} +//************************************************************************************* +/** + * Calcula el coste de desplazamiento de ir de ir por todos los ambitos sec desde ini hasta fin + */ +double Colv_limp_thr::dame_coste( Secu_amb * sec, int ini, int fin, Info_sec *s, BOOL ind_abs) +{ + double d=0; + int ind_cost,fin_old; + + fin_old=fin; + + while(iniiamb[sec[fin].iamb]; + else + ind_cost=sec[fin].iamb; + + d+=olv_limp->cost_amb[s->iamb[sec[fin].iamb]][s->iamb[sec[fin].iamb]]; + d+=olv_limp->arch_dj.dame_dis(s->iamb[sec[fin-1].iamb],(sec[fin-1].entrada+1)%2,s->iamb[sec[fin].iamb],sec[fin].entrada); + fin--; + } + d+=olv_limp->cost_amb[s->iamb[sec[ini].iamb]][s->iamb[sec[ini].iamb]]; + + if(ini==0)//si ini es 0 falta sumar el coste de la planta al primer ambito + { + if (ind_abs) + ind_cost=s->iamb[sec[ini].iamb]; + else + ind_cost=sec[ini].iamb; + if(olv_limp->nod_instal>=0) + { + int ee=0; + if(sec[ini].entrada>=0) + ee=sec[ini].entrada; + d+=olv_limp->arch_dj.dame_dis(olv_limp->arch_dj.id_instal,0,s->iamb[sec[ini].iamb],ee); + //d+=sec[ind_cost].ctnod[ee][olv_limp->nod_instal].dis; + } + else + d+=olv_limp->t_despl; + } + + //suma el coste de ir del ultimo ambito a la instalación + if(olv_limp->nod_instal>=0) + d+=olv_limp->ord_sec_plan[0].ctnod[0][olv_limp->iaso[olv_limp->carto.get(s->iamb[sec[fin_old].iamb]).entity()->ref].inod[(sec[fin_old].entrada+1)%2]].dis; + else + d+=olv_limp->t_despl; + + return d; +} +//************************************************************************************* +/** + * Calcula el coste de desplazamiento de ir por todos los ambitos sec desde ini hasta fin + * cambiando el ámbito de pos_old como si estuviera en pos_new + */ +double Colv_limp_thr::dame_coste_ex( Secu_amb * sec, int ini, int fin, Info_sec *s, int pos_old, int pos_new, int entrada ) +{ + double d=0; + int sig, act; + int a_ent, s_ent; + + while(iniarch_dj.dame_dis(sec[act].iamb,a_ent,s->iamb[sec[sig].iamb],(s_ent+1)%2); + d+=olv_limp->cost_amb[s->iamb[sec[act].iamb]][s->iamb[sec[act].iamb]]; + + ini++; + } + + act=Colv_geom::dame_ind_per(ini,pos_old,pos_new); + d+=olv_limp->cost_amb[s->iamb[sec[ini].iamb]][s->iamb[sec[ini].iamb]]; + return d; +} +//************************************************************************************* +/** + * Lee la sectorización que viene como info asociada en el shp de entrada + */ +BOOL Colv_limp_thr::lee_secto() +{ + BOOL ret; + int i,s,idd, ics, icsq; + char nfile[MAX_PATH]; + int *info; + Cb_file f; + Fdbf dbf; + + std::map> l_sec; + + olvlog(LOG_TODO,"olv_limp_t","Comienza lectura de sectorización"); + pon_mi_progre(OLV_TAREA_LEE_SECTO, 0); + pon_mi_msg(""); + err_str[0]=0; + + ///////////////////////////////////// + info = (int *)malloc(olv_limp->n_amb*sizeof(int)); + if(!info) + { + sprintf_s(err_str,OLV_MAX_ERR,"Error, sin memoria para info asociada"); + return FALSE; + } + memset(info,0,olv_limp->n_amb*sizeof(int)); + + //lee dbf del shp la columna SECTOR + strcpy_s(nfile,MAX_PATH,olv->paths.path_data); + //cambiaext(nfile,".shp",".dbf"); + strcpy((Cdir_manager::extension_archivo(nfile)),"dbf"); + if(!f.abre(nfile,1) || !dbf.lee(&f)) + { + ret=FALSE; + goto fin; + } + ics=dbf.findCol(olv_limp->camps.campo_secto); + icsq=dbf.findCol("SECUENCIA"); + if(ics<0 || icsq<0) + { + ret=FALSE; + goto fin; + } + idd =dbf.leeNexRow(); + //rellena para cada sector info[i] qué ámbitos tiene + for(i=0;in_amb && idd==1; i++) + { + if(olv_limp->iaso[olv_limp->carto.get(i).entity()->ref].flgs & OLV_LIMP_FLG_AMB_NO) + { + idd=dbf.leeNexRow(); + continue; + } + + s=dbf.getI(ics); + + //la primera vez lo añade vacío + if(l_sec[dbf.getI(ics)].size()==0) + l_sec[s].push_back(-1); + + if(dbf.getI(icsq)==1)//se ha marcado ese elemento como primero, lo pone en el primer elemento + l_sec[s][0]=i; + + l_sec[s].push_back(i); + idd=dbf.leeNexRow(); + } + if(in_amb) + { + ret=FALSE; + goto fin; + } + + olv_limp->nsec=(int)l_sec.size(); + + //////////////////////////////////////// + //inicia los arrays para la sectorización + if(!pide_memo_secto()) + { + sprintf_s(err_str,OLV_MAX_ERR,"Error, Sin memoria para lectura de sectorización"); + ret=FALSE; + goto fin; + } + + i=-1; + int ia=0; + //mira cuántos sectores diferentes hay + for (std::map>::iterator it=l_sec.begin(); it!=l_sec.end(); ++it) + { + i++; + olv_limp->sec[i].namb = (int)it->second.size()-1; + olv_limp->sec[i].iamb_ini_def = it->second[0]; + for(int ia=1;iasec[i].namb+1;ia++) + { + olv_limp->sec[i].iamb[ia-1]=it->second[ia]; + olv_limp->amb_sec[it->second[ia]].sec = i; + } + } + +fin: + + free(info); + + if(!ret) + { + pon_mi_msg("Error en lectura de info de sectorización: %s",err_str); + } + + return ret; +} +//************************************************************************************* +/** + * Calcula el número de sectores óptimo para los ámbitos dados + */ +BOOL Colv_limp_thr::calcula_n_sec() +{ + BOOL ret; + int nsec; + double cost_tot,cost_sec; + + //////////////// + ret=TRUE; + nsec=-1; + //////////////// + + olvlog(LOG_TODO,"olv_limp_t","Comienza cálculo del número de sectores"); + pon_mi_progre(OLV_TAREA_CALC_SEC, 0); + pon_mi_msg(""); + err_str[0]=0; + + //////////////// + olv_limp->nsec =olv_limp->nsec_act = 1; //se fija a un sector para planificar todo junto + + if(!pide_memo_secto()) + { + sprintf_s(err_str,OLV_MAX_ERR,"Error, Sin memoria"); + ret=FALSE; + goto fin; + } + + //hace la sectorización con un sector para que lo asigne por árbol + if(!sectoriza_1())//rellena Info_sec + { + sprintf_s(err_str,OLV_MAX_ERR,"Error en la primera sectorización"); + ret=FALSE; + goto fin; + } + //////////////////////////////// + + //calcula el coste de un sector con todos los ámbitos + cost_tot=olv_limp->sec[0].cost_ac;//calcula_cost_1sec_total(olv_limp->n_amb,olv_limp->sec,olv_limp->ias,olv_limp->conjs.n,olv_limp->cost_conj,olv_limp->ang_conj); + if(cost_tot>=MAYUSCULO) + { + sprintf_s(err_str,OLV_MAX_ERR,"Error en el cálculo del coste total de los ámbitos"); + ret=FALSE; + goto fin; + } + + //calcula el número de sectores, diviendo por el coste máximo de un sector + cost_sec = dame_cost_jornada(); + if(cost_sec<=0) + { + sprintf_s(err_str,OLV_MAX_ERR,"Tiempos de jornada, descanso y desplazamiento erróneos"); + ret=FALSE; + goto fin; + } + nsec = (int)(cost_tot/cost_sec) + 1; + //////////////// + olv_limp->calc_nsec=cost_sec; //se indica que el número de sectores es calculado, no impuesto + //////////////////////////////// + + //libera memoria + olv_limp->libera_memo_secto(); + //pone el número de sectores calculado + if(nsec==1) + { + olv_limp->nsec =olv_limp->nsec_act = nsec; + } + else + { + olv_limp->nsec = nsec + 2;//elena abr 2018 coge un margen de 2, excepto si le ha salido que es 1 + olv_limp->nsec_act = max(nsec,2); + } + ///////////////////////////////// + +fin: + if(!ret) + { + pon_mi_msg("Error en el cálculo del número de sectores: %s",err_str); + } + + return ret; +} +//************************************************************************************* +/** + * Calcula el tiempo efectivo de una jornada + */ +double Colv_limp_thr::dame_cost_jornada() +{ + return olv_limp->t_conv-olv_limp->t_desc; +} +//************************************************************************************* +/** + * Lanza la planificación de todos los ámbitos en un sector para calcular el coste total, y lo devuelve + * Devuelve también la secuencia de ámbitos planificada + */ +double Colv_limp_thr::calcula_cost_1sec_total(int n_amb, Info_sec *ss, Djkt_ang_ady *ang_conj) +{ + double coste; + int nth,n_sec,i; + Secu_amb *ord_sec; + th_param_planif thp; + BOOL log_debug; + BOOL nocalc; + + //////////////// + log_debug=TRUE; + n_sec=1; + nth=Colv_geom::dame_n_nucleos(); + //inicia th + memset(&thp, 0, sizeof(thp)); + thp.milis_sleep=1; + thp.namb_t=n_amb; + nocalc=FALSE; + coste=0; + //////////////// + + ord_sec=olv_limp->ord_sec; + + //avisa de progreso + olvlog(LOG_TODO,"olv_limp_t","Calculando permutaciones para mejorar al calcular coste de un sector total"); + pon_mi_progre(OLV_TAREA_PERMU,0); + //////// + + thp.dth=(th_data_planif*)malloc(sizeof(th_data_planif)*nth); + memset(thp.dth, 0, sizeof(th_data_planif)*nth); + thp.abs=TRUE; + + //lanza threads + for (i=0; i=0) + Sleep(1); + } + + if(!calcula_coste_sectores(ord_sec, ss, n_sec, &thp, FALSE)) + { + coste=MAYUSCULO; + goto salir; + } + coste=ss[0].cost_ac; + +salir: + + //se bloquea y + thp.pirate=TRUE; + while(thp.nth>0) + Sleep(1); + + if(thp.dth) + { + if(thp.dth[0].sec) + free(thp.dth[0].sec); + free(thp.dth); + + } + return coste; +} +//************************************************************************************* +/** + * Devuelve la planificación de todos los sectores, en los que calcula la ruta óptima o cercana a la óptima + * que recorre los ámbitos de dicho sector + */ +BOOL Colv_limp_thr::planifica() +{ + olvlog(LOG_TODO,"olv_limp_t","Comienza planificación"); + pon_mi_progre(OLV_TAREA_PLANIF, 0); + pon_mi_msg(""); + err_str[0]=0; + + //revisa si algún sector no tiene ámbitos + int ns=0; + for(int i=0;insec;i++) + { + if(olv_limp->sec[i].namb>0) + ns++; + } + olv_limp->nsec=ns; + + //inicializa el array de planificaciones + olv_limp->plan=(Info_planif*)malloc(olv_limp->nsec*sizeof(Info_planif)); + if(!olv_limp->plan) + { + pon_mi_msg("Error, sin memoria en array de planificación"); + return FALSE; + } + memset(olv_limp->plan,0,olv_limp->nsec*sizeof(Info_planif)); + + //lanza los threads + lanza_subthrs(OLV_LIMP_EV_PLANIFICA_SUB); + + return TRUE; +} +//************************************************************************************* +/** + * Devuelve la planificación del sector iésimo, que realiza el thread 'ithr' + */ +void Colv_limp_thr::planifica_sub_1(int ithr, Matrix2d &cost_amb) +{ + Info_sec *s; + Info_amb_sec *aa; + int i,iaux,is_ini,is_fin,is_desp,is,jmin; + BOOL log_debug=FALSE; + BOOL sal,sig; + Djkt_nodo *costes_nodos; + int nsecu,KK,ic_aux,ss,nsecu2; + Secu_amb *secu_ambi=NULL; + Param_olv_limp_thr pp; + Djkt_nodo* buf_nod=NULL; + costes_nodos=NULL; + int msecu1, msecu2; + msecu1 = msecu2 = olv_limp->conjs.n*2; + int *secu,*secu2; + secu=(int *)malloc(olv_limp->conjs.n*2*sizeof(int)); + + if(!secu) + { + sal=TRUE; + goto fin; + } + + buf_nod=olv_limp->arch_dj.dame_buf_nodos(); + if(!buf_nod) + { + sal=TRUE; + goto fin; + } + + memset(secu,0,olv_limp->conjs.n*2*sizeof(int)); + secu2=(int *)malloc(olv_limp->conjs.n*2*sizeof(int)); + if(!secu2) + { + sal=TRUE; + goto fin; + } + memset(secu2,0,olv_limp->conjs.n*2*sizeof(int)); + nsecu2=0; + ////////////////////////// + pp.id_e=OLV_TAREA_PLANIF;//manda de parámetro la tarea de la que es el progreso + ic_aux=0; + KK=olv_limp->tipo_ambit; + sal=sig=FALSE; + jmin=0; + prog_subthr=0; + aa=olv_limp->amb_sec; + iaux=-1; + + //////////////////////////////////////////////////// + //mira a ver cuántos sectores le tocan a este thread + if(olv_limp->nsecnsec) + { + //solo hace un sector, el ithr-esimo + is_ini=ithr; + is_fin=ithr+1; + } + else + { + //no hace ningún sector, no hace falta + is_ini=0; + is_fin=0; + } + } + else + { + //hay más sectores que threads, le tocan más de uno + is_desp=(int)ceil(1.0*(olv_limp->nsec)/n_subthr); + is_ini=ithr*is_desp; + is_fin=min((ithr+1)*is_desp,olv_limp->nsec); + } + ////////////////////////// + if(is_fin==is_ini) + olvlog(LOG_TODO,"olv_limp_t","Subthr %02d, No Planifica ningún sector", ithr); + else if(is_fin-is_ini-1==0) + olvlog(LOG_TODO,"olv_limp_t","Subthr %02d, Planifica sector %02d", ithr,is_ini); + else + olvlog(LOG_TODO,"olv_limp_t","Subthr %02d, Planifica sectores %02d a %02d", ithr,is_ini, is_fin-1); + + ////////////////////////// + //bucle en todos los sectores que le tocan al thread + for(is=is_ini;issec[is]; + if(s->namb<=0) + continue; + s->cost_despl_aux=0; + sig=FALSE; + + //busca el ámbito inicial de la planificiación + secu_ambi=planifica_sect(s,olv_limp->ang_conj, OLV_LIMP_FACT_PERM); + if(!secu_ambi) + { + olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Imposible planificar sector %02d",ithr,is); + sal=TRUE; + continue; + } + if(esta_repe(secu_ambi, s->namb)) + { + olvlog(LOG_TODO,"olv_limp_t","Esta repe despues de planifica sec"); + sal=TRUE; + continue; + } + + /////////////////////////////////////////// + //Añade la ruta de la instalación al primer punto + if(olv_limp->nod_instal>=0 && olv_limp->ord_sec_plan) + { + olv_limp->arch_dj.get_b(s->iamb[secu_ambi[0].iamb],secu_ambi[0].entrada,buf_nod); + Colv_geom::ruta_dj_inv_ok( + olv_limp->nod_instal,//id conjuncion inicial + &secu2[0], //puntero a secuencia + buf_nod, //nodos djktra conj final + olv_limp->conjs.n, + &nsecu2); + + if(!genera_planif_instala(is, 0, 0, nsecu2, secu2, OLV_IDA_INST)) + sal=TRUE; + } + /////////////////////////////////////////// + + ss=1; + s->cost_despl_aux=olv_limp->cost_amb[s->iamb[secu_ambi[0].iamb]][s->iamb[secu_ambi[0].iamb]]; + s->cost_despl_aux+=s->t_despl[0];//el desplazamiento de la instalación al primer ámbito + secu[0]=olv_limp->iaso[olv_limp->carto.get(s->iamb[secu_ambi[0].iamb]).entity()->ref].inod[secu_ambi[0].entrada]; + + //almacena el coste acumulado + aa[s->iamb[secu_ambi[0].iamb]].iseq=0; + double cc, cc1=0; + for (i=1; inamb; i++) + { + olv_limp->arch_dj.get_b(s->iamb[secu_ambi[i].iamb],secu_ambi[i].entrada, buf_nod); + cc=Colv_geom::ruta_dj_inv_ok( + olv_limp->iaso[olv_limp->carto.get(s->iamb[secu_ambi[i-1].iamb]).entity()->ref].inod[(secu_ambi[i-1].entrada+1)%2],//id conjuncion final + &secu[ss], //puntero a secuencia + buf_nod, //nodos djktra conj inicial + olv_limp->conjs.n, + &nsecu); + ss+=nsecu; + s->cost_despl_aux+=(float)cc; + s->cost_despl_aux+=olv_limp->cost_amb[s->iamb[secu_ambi[i].iamb]][s->iamb[secu_ambi[i].iamb]]; + + //almacena el coste acumulado + aa[s->iamb[secu_ambi[i].iamb]].iseq=i; + cc1+=olv_limp->arch_dj.dame_dis(s->iamb[secu_ambi[i-1].iamb],(secu_ambi[i-1].entrada+1)%2,s->iamb[secu_ambi[i].iamb], secu_ambi[i].entrada); + + ////////////////// + if((i%50)==0 || (i==s->namb-1)) + { + //avisa de progreso + olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Planificando sector %02d, amb %ld de %ld", ithr,is, + (i+1),(s->namb)); + prog_subthr=(1.0*(i+1)/(s->namb))*((is+1)/(is_fin-is_ini)); //porque son varios sectores + thr_padre->encola(OLV_LIMP_EV_SUBTHR_PROG,&pp,FALSE); + } + ///////////////// + + } + if(olv_limp->tipo_ambit==OLV_AMB_LIN)//añade el coste del último ámbito si es lineal + { + secu[ss++]=olv_limp->iaso[olv_limp->carto.get(s->iamb[secu_ambi[s->namb-1].iamb]).entity()->ref].inod[(secu_ambi[s->namb-1].entrada+1)%2]; + } + s->cost_despl_aux+=s->t_despl[1];//el desplazamiento del último ámbito a la instalación + + if(esta_repe(secu_ambi, s->namb, FALSE)) + olvlog(LOG_TODO,"olv_limp_t","Esta repe despues de planificar"); + + olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Planificando sector %02d, coste total %lf",ithr,is,s->cost_despl_aux); + + /////////////////////////////////////////// + //Ruta del último punto a la instalación + if(olv_limp->nod_instal>=0 && olv_limp->ord_sec_plan) + { + + Colv_geom::ruta_dj_inv_ok( + olv_limp->iaso[olv_limp->carto.get(s->iamb[secu_ambi[s->namb-1].iamb]).entity()->ref].inod[(secu_ambi[s->namb-1].entrada+1)%2], + &secu2[0], //puntero a secuencia + olv_limp->ord_sec_plan[0].ctnod[0], //nodos djktra conj final + olv_limp->conjs.n, + &nsecu2); + if(!genera_planif_instala(is, 0, 0, nsecu2, secu2, OLV_VUELTA_INST)) + { + sal=TRUE; + break; + } + } + /////////////////////////////////////////// + + if(!pirate && !sal) + { + ////////////////////////////////// + //genera la ruta y los puntos de control + if(!genera_planif(is,s->cost_despl_aux, ss, secu,OLV_PLAN_NORMAL)) + sal=TRUE; + olv_limp->sec[is].cost_ac=(float)(olv_limp->plan[is].elem[olv_limp->plan[is].nelem-1].coste+olv_limp->sec[is].t_despl[0]+olv_limp->sec[is].t_despl[1]); + } + ////////////////////////////////// + if( secu_ambi) + { + free(secu_ambi); + secu_ambi=NULL; + } + } + free(secu); + free(secu2); +fin: + //Ha terminado, encola al padre + olv_limp->arch_dj.libera_buf(buf_nod); + if(sal) + { + prog_subthr=-1;//para avisar al padre de que ha habido un error + } + thr_padre->encola(OLV_LIMP_EV_PLANIFICA_FIN,NULL,FALSE); +} +//************************************************************************************* +/** + * Finaliza y centraliza tareas de planificar, cuando han acabado todos los threads + */ +BOOL Colv_limp_thr::planifica_fin() +{ + //para los threads + para_subthrs(); + err_str[0]=0; + + /////////////////////////////////////// + //Si es barrido mixto hay que copiar la info en las que no se ha sectorizado + if(olv_limp->barr_mix) + copia_info_barr_mix(); + + /////////////////////////////////// + //prepara los datos para guardarlos + if(!genera_rut_ctrl(olv_limp->nsec, olv_limp->plan, FALSE)) + { + pon_mi_msg("Errores en la generación de cartografía con ruta"); + return FALSE; + } + //genera el listado del itinerario + if(!genera_list_rut_ctrl()) + { + pon_mi_msg("Errores en la generación del listado de la ruta: %s",err_str); + return FALSE; + } + //graba a archivo el obg + if(!guarda_shp_rut_ctrl()) + { + pon_mi_msg("Errores en el guardado a shp de la ruta: %s",err_str); + return FALSE; + } + + if(!guarda_dbf_sector(2)) + { + pon_mi_msg("Errores en la generación de información asociada de sector: %s",err_str); + return FALSE; + } + /////////////////////////////////// + + ///////////////////////////////////////////// + //A continuación genera y graba los archivos de los subtramos de cada ruta + if(!gen_guard_subtramos()) + return FALSE; + /////////////////////////////////// + + olvlog(LOG_TODO,"olv_limp_t","Planificación finalizada"); + + return TRUE; +} +//************************************************************************************* +/** + * Dada la secuencia de las conjunciones que sigue la ruta, genera la ruta diciendo por qué + * elementos de la red pasa y coloca los puntos de control + */ +BOOL Colv_limp_thr::genera_planif(int is, double cost_sec, int nsecu, int *secu, int tip_plan) +{ + int npt_ctrl,ipc; + double cost_ctrl; + Info_planif *pp; + + olvlog(LOG_TODO,"olv_limp_t","Almacenando planificación sector %02d",is); + + ///////////////// + ipc=0; + npt_ctrl=(olv_limp->npts_ctrl-2); + pp=&olv_limp->plan[is]; + + if(!genera_planif_aux(is,&olv_limp->sec[is], pp, nsecu, secu,tip_plan)) + return FALSE; + + cost_ctrl=pp->elem[pp->nelem-1].coste/(olv_limp->npts_ctrl-2+1); + pon_ptos_ctrl(pp, npt_ctrl, cost_ctrl); + + ////////////////////////////////////////////////////////// + + /*if (!_CrtCheckMemory()) + int i=0;*/ + + return TRUE; +} +//************************************************************************************* +/** + */ +void Colv_limp_thr::pon_ptos_ctrl(Info_planif *pp, int npt_ctrl, double cost_ctrl) +{ + double cost_acum; + int i, ipc; + /////////////////////////////////////////////////////////////// + //Inicializa el array de puntos de control + pp->pts_ctrl=(Info_planif_ctrl*)malloc((olv_limp->npts_ctrl-2+1)*sizeof(Info_planif_ctrl)); + if(!pp->pts_ctrl) + return; + memset(pp->pts_ctrl,0,(olv_limp->npts_ctrl-2+1)*sizeof(Info_planif_ctrl)); + ipc=0; + + cost_acum=0; + for(i=0;inelem;i++) + { + ///////////////////////////// + cost_acum=pp->elem[i].coste; + //mira si toca punto de control + if((cost_acum-(ipc)*(cost_ctrl/*+olv_limp->t_desc*/))>(cost_ctrl-1)) + { + if(ipcpts_ctrl[ipc].ipt=i-1; + ipc++; + } + else + ipc=ipc; + } + } + + for(i=0;ipts_ctrl[i].ipt<0) + pp->pts_ctrl[i].ipt=pp->nelem-1; + } +} +//************************************************************************************* +/** + * Dada la secuencia de las conjunciones que sigue la ruta, genera la ruta diciendo por qué + * elementos de la red pasa y coloca los puntos de control - Función auxiliar + */ +BOOL Colv_limp_thr::genera_planif_aux(int is, Info_sec *ss, Info_planif *pp, int nsecu, int *secu, int tip_plan) +{ + int nent, ref_j, i, j, dt,npt, amb_j,nelesec,tp,ref_nw,itr,last_pt,k; + double cost,cost_perd,ltot,cost_parc_aux; + CartoBaseInfoEntity ient; + BYTE *ambs_sec; + BOOL is_uno,sal,is_descarg,sdire; + + ////////////////////////////////////////////////////////////////// + nent=olv_limp->carto.getNumberEntities(); + nelesec=itr=0; + cost_parc_aux=0; + sal=is_descarg=sdire=FALSE; + last_pt=-1; + is_uno=FALSE; + ref_nw=0; + ////////////////////////////////////////////////////////////////// + + if(nsecu==1) + { + is_uno=TRUE; + nsecu=2; + } + //Inicializa los arrays de elementos + pp->nelem = nsecu-1; + //ielem + pp->elem=(Info_elem_planif*)malloc(pp->nelem*sizeof(Info_elem_planif)); + if(!pp->elem) + return FALSE; + memset(pp->elem,0,pp->nelem*sizeof(Info_elem_planif)); + ////////////////////////////////////////////////////////////////// + + //si es un único elemento + if(is_uno) + { + //recorre los ámbitos buscándolo + for(j=0;jcarto.getEntity(j); + + if(ient.entity()->type!=CartoBaseTypes::Line) + continue; + + ref_j=ient.entity()->ref; + amb_j=olv_limp->iaso[ref_j].iamb; + + if(secu[0]==olv_limp->iaso[ref_j].inod[0] || + secu[0]==olv_limp->iaso[ref_j].inod[1]) + break; + } + if(j>=nent) + { + return FALSE; + } + cost=0; + if(amb_j>0) + { + cost=olv_limp->cost_amb[amb_j][amb_j]; + } + else + { + amb_j=olv_limp->iaso[olv_limp->iaso[ref_j].refe2].iamb; + if(amb_j>0) + cost=olv_limp->cost_amb[amb_j][amb_j]; + + } + dt=OLV_TTO; + + //añade la info del elemento + pp->elem[0].refe=ref_j; + pp->elem[0].k=0; + pp->elem[0].tp = OLV_PLAN_TIP_AMB; + pp->elem[0].ref_nw = -1; + pp->elem[0].coste = cost; + pp->elem[0].ltot = 0; + pp->t[dt]=cost; + pp->m[dt]=0; + return TRUE; + } + ////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////// + ambs_sec=(BYTE*)malloc(ss->namb); + if(!ambs_sec) + return FALSE; + memset(ambs_sec,0,ss->namb); + + //bucle para cada conjunción de la secuencia + for(i=0;icarto.getEntity(j); + if(ient.entity()->type!=CartoBaseTypes::Line) + continue; + + ref_j=ient.entity()->ref; + amb_j=olv_limp->iaso[ref_j].iamb; + + //busca por las conjunciones almacenadas + sdire=((secu[i]==olv_limp->iaso[ref_j].inod[0])&& + (secu[i+1]==olv_limp->iaso[ref_j].inod[1])); + if(sdire || + (((secu[i+1]==olv_limp->iaso[ref_j].inod[0])&& + (secu[i]==olv_limp->iaso[ref_j].inod[1])))) + { + break; + } + } + if(j>=nent) + { + sal=TRUE; + continue; + } + if(amb_j<0 && olv_limp->iaso[ref_j].refe2>=0) + { + //no es un ámbito + amb_j=olv_limp->iaso[olv_limp->iaso[ref_j].refe2].iamb; + } + if(amb_j<0 && !(olv_limp->iaso[ref_j].flgs & OLV_LIMP_FLG_NW)) + { + sal=TRUE; + continue; + } + + //calcula la longitud + npt=ient.getNumberPtos(); + ltot = ient.getLong(); + cost=olv_limp->cost_conj[secu[i]][secu[i+1]]; + dt=OLV_DT_N; + ///////////////////////////// + //mira a ver si es carretera o amb para poner inw + if(olv_limp->iaso[ref_j].flgs & OLV_LIMP_FLG_AMB) //es ámbito + { + ref_nw=olv_limp->inww_amb[amb_j+!sdire*olv_limp->n_amb].refnw; + + /////////////////////////////////// + //si no pertenece a los ámbitos de este sector o ya ha pasado por él, + //es que está desplazándose por él, le pone tipo nw + for(k=0;knamb;k++) + { + if(ss->iamb[k]==amb_j) + break; + } + if(k>=ss->namb || ambs_sec[k] || (tip_plan==OLV_PLAN_INST)) + { + tp=OLV_PLAN_TIP_NW; //es la segunda vez que pasa por ahí + dt=OLV_DESP; + cost=ltot/olv_limp->v_despl; + } + else + { + /////////////////////////////////// + if(olv_limp->iaso[ref_j].flgs & OLV_LIMP_FLG_AMB_PEAT) + tp=OLV_PLAN_TIP_AMB_PEAT; + else + tp=OLV_PLAN_TIP_AMB; + + dt=OLV_TTO; + ambs_sec[k]=1; + } + + } + else if(olv_limp->iaso[ref_j].flgs & OLV_LIMP_FLG_SEG_LIN) //es segmento de ámbito + { + if(olv_limp->iaso[ref_j].flgs & OLV_LIMP_FLG_FIN) + ref_nw=olv_limp->inww_amb[amb_j+olv_limp->n_amb].refnw; + else + ref_nw = olv_limp->inww_amb[amb_j].refnw; + tp=OLV_PLAN_TIP_SEG_LIN; + ltot=0; + } + else if(olv_limp->iaso[ref_j].flgs & OLV_LIMP_FLG_SEG_PUN) + { + ref_nw = olv_limp->inww_amb[amb_j].refnw; + tp=OLV_PLAN_TIP_AMB; + ltot=0; + if((last_pt==ref_j) || (tip_plan==OLV_PLAN_INST)) + { + cost=0; + tp=OLV_PLAN_TIP_NW; + } + else + { + cost=olv_limp->cost_amb[amb_j][amb_j]; + last_pt=ref_j; + dt=OLV_TTO; + } + } + else if(olv_limp->iaso[ref_j].flgs & OLV_LIMP_FLG_PEAT_REP) + { + tp=OLV_PLAN_TIP_AMB_PEAT_DESP; + //en info0 se ha guardado la peatonal original + ref_nw=olv_limp->inww_amb[amb_j+!sdire*olv_limp->n_amb].refnw; + dt=OLV_DESP; + cost=ltot/olv_limp->v_despl; + } + else//es carretera + { + ref_nw=ref_j; + tp=OLV_PLAN_TIP_NW; + dt=OLV_DESP; + } + + //////////////////// + if(is_descarg && (tp!=OLV_PLAN_TIP_AMB)) + { + cost_perd+=cost; + cost=ltot=0; + } + //////////////////// + if((ltot==0) && (dt!=OLV_TTO)) + cost=0; + ////// + //calcula coste acumulado + if(nelesec>0) + cost_parc_aux=pp->elem[nelesec-1].coste; + else + cost_parc_aux=0; + //añade la info del elemento + pp->elem[nelesec].refe=ref_j; + pp->elem[nelesec].k=!sdire; + pp->elem[nelesec].tp = tp; + pp->elem[nelesec].ref_nw = ref_nw; + pp->elem[nelesec].coste = cost_parc_aux + cost; + pp->elem[nelesec].ltot = ltot; + pp->elem[nelesec].aux=0; + + ////////////// + if(dtuds_tto==OliviaDef::GeneralDef::OlvTipTtoM2h) && (dt==OLV_TTO)) + pp->m[dt]+=(ltot*olv_limp->iaso[ref_j].inf_l.ancho); + else + pp->m[dt]+=ltot; + pp->t[dt]+=cost; + } + + ////////////// + if((tip_plan==OLV_PLAN_RECO) && (tp==OLV_PLAN_TIP_AMB)) + { + pp->elem[nelesec].aux=itr;//marca los tramos + if(comprueba_descarg(amb_j)) + itr++; + if((!is_descarg && comprueba_descarg(amb_j)) + || (is_descarg && !comprueba_descarg(amb_j))) + { + cost_perd=0; + is_descarg=!is_descarg; + } + + } + ////////////// + nelesec++; + } + if(sal) + { + free(ambs_sec); + return FALSE; + } + + pp->nelem = nelesec; + + free(ambs_sec); + return TRUE; +} +//************************************************************************************* +/** + * Comprueba si en este elemento se va a descargar y en ese caso no se cuenta el desplazamiento hasta el siguiente + */ +BOOL Colv_limp_thr::comprueba_descarg(int iamb) +{ + return FALSE; +} +//************************************************************************************* +/** + * Dada la secuencia de las conjunciones que sigue la ruta para ir y volver de la instalación, genera la planificación + */ +BOOL Colv_limp_thr::genera_planif_instala(int is, int nvaciados, int ini, int fin, int *secu, int tip_viaje) +{ + int i; + Info_planif *pp,*pp_insta; + Info_sec *ss; + + ss=&olv_limp->sec[is]; + pp=&olv_limp->plan[is]; + pp_insta = pp->planif_insta; + if(!pp_insta) + { + //inicializa, sólo la primera vez + //cuenta el número de veces que va a vaciar + pp->ninsta=2;//inicialmente tiene la ida y la vuelta a la instalación + if(nvaciados) + pp->ninsta+=nvaciados*2-1; //todos los vaciados son ida y vuelta + pp_insta = (Info_planif *)malloc(pp->ninsta*sizeof(Info_planif)); + if(!pp_insta) + return FALSE; + memset(pp_insta,0,pp->ninsta*sizeof(Info_planif)); + + pp_insta[0].ninsta=OLV_IDA_INST; + pp_insta[pp->ninsta-1].ninsta=OLV_VUELTA_INST; + pp->planif_insta = pp_insta; + } + + //busca cuál le toca rellenar + for(i=0;ininsta;i++) + { + if(pp_insta[i].nelem==0) + break; + } + if(i>=pp->ninsta) + return FALSE; + pp_insta[i].ninsta=tip_viaje; + + if(!genera_planif_aux(is,ss, &pp_insta[i],fin-ini,&secu[ini],OLV_PLAN_INST)) + return FALSE; + + if(tip_viaje==OLV_IDA_INST) + olv_limp->sec[is].t_despl[0]=(float)pp_insta[0].elem[pp_insta[0].nelem-1].coste; + else if(tip_viaje==OLV_VUELTA_INST) //son impares, implica que la última ida adescargar es a la instalación también + olv_limp->sec[is].t_despl[1]=(float)pp_insta[pp->ninsta-1].elem[pp_insta[pp->ninsta-1].nelem-1].coste; + + return TRUE; +} +//************************************************************************************* +/** + * Dadas las rutas de los sectores, genera la ruta en una única línea en el obg + * y en otro coloca los puntos de control + */ +BOOL Colv_limp_thr::genera_rut_ctrl(int ns, Info_planif *planif, BOOL tramos) +{ + int is, it, nt, ie_ini, ie_fin, i, k, ins, npt,nmax_pts; + double long_fl, long_max_fl; + BOOL mal; + CartoLine lin, lin_fl; + CartoPto pt; + CartoBaseInfoEntity ient, ient2; + Info_planif *pp; + + //////////////// + long_max_fl=15; + long_fl=1; + nmax_pts=0; + mal=FALSE; + memset(pt.pt,0,3*sizeof(double)); + ///////////////// + + olvlog(LOG_TODO,"olv_limp_t","Generando lineales de las rutas en obg"); + + /////////////////////////////////////////////// + //Genera el obg de la ruta, un lineal por sector (o varios por sector si hay idas a recogida) + for(is=0;istramos[is].size(); + for(it=0;ittramos[is][it].ie[0]; + ie_fin=olv_limp->tramos[is][it].ie[1]; + + if(!genera_rut_aux(pp, is, FALSE,ie_ini,ie_fin)) + { + mal=TRUE; + break; + + } + } + } + else + { + if(!genera_rut_aux(pp, is, FALSE,0,pp->nelem-1)) + { + mal=TRUE; + break; + + } + + for(ins=0;insninsta;ins++) + { + //solo entra aquí si hay ruta a las instalaciones + if(!genera_rut_aux(&pp->planif_insta[ins], is, TRUE,0,pp->planif_insta[ins].nelem-1)) + { + mal=TRUE; + break; + } + } + } + } + /////////////////////////////////////////////// + //Genera el obg de los puntos + if(!tramos && !mal) + { + int ie; + int isfin; + for(is=0;isnpts_ctrl;i++) + { + pt.ia=is+1; + memset(pt.pt,0,3*sizeof(double)); + if(pp->nelem>0) + { + isfin=0; + if(i==0) + ie=0; //el punto de control primero está en el primer elemento + else if(i==olv_limp->npts_ctrl-1) + { + ie=pp->nelem-1;//el punto de control último está en el último elemento + isfin=1; + } + else + ie=pp->pts_ctrl[i-1].ipt;//los puntos de control intermedios, los que se han calculado + + ient=olv_limp->carto.getRef(pp->elem[ie].refe); + npt=ient.getNumberPtos(); + k=(pp->elem[ie].k+isfin)%2; //porque si es el punto de control final, lo tiene que poner al final + //del tramo, no al principio + + memcpy(pt.pt,ient.getPto(k*(npt-1)),3*sizeof(double)); + } + mal=(!carto_ctrl.add(pt)); + } + } + } + + if(mal) + return FALSE; + + return TRUE; +} +//************************************************************************************* +/** + * Dadas las rutas de los sectores, genera la ruta en una única línea en el obg + * y en otro coloca los puntos de control - Función auxiliar + */ +BOOL Colv_limp_thr::genera_rut_aux(Info_planif *pp, int is, BOOL is_insta, int ie_ini, int ie_fin) +{ + int npt,npt_tot,i,k; + double (*pts_lin)[3],(*ptos_par)[3],(*ptos)[3],(*pts_lin_fl)[3]; + BOOL mal; + CartoLine lin, lin_parc, lin_fl; + CartoBaseInfoEntity ient; + double d; + double ltot, long_max_fl; + int nfl; + CartoBase *flech, *rut; + + //para debug + CartoBase carto_aux; + + if(is_insta) + { + flech = NULL; + rut = &carto_inst; + } + else + { + flech=&carto_flech; + rut =&carto_rut; + } + + //////////////// + long_max_fl=5; + mal=FALSE; + ///////////////// + + if(pp->nelem==0 && is_insta) + return TRUE; + if(pp->nelem==0 && !is_insta) + npt_tot=2; + else + { + npt_tot=0; + //Contar puntos + for(i=ie_ini;i<=ie_fin;i++) + { + ///////////////////////////// + npt_tot += olv_limp->carto.getRef(pp->elem[i].refe).getNumberPtos()-1; + } + npt_tot++; + } + if(!(lin.pts+=npt_tot))//pide memoria + { + return FALSE; + } + pts_lin = lin.pts.ptr; + + //Añadir puntos + for(i=ie_ini;i<=ie_fin;i++) + { + ient=olv_limp->carto.getRef(pp->elem[i].refe); + npt=ient.getNumberPtos(); + lin_parc.pts.n=0; + ptos=(double (*)[3])ient.getPto(0); + ptos_par=NULL; + + //si es carretera y es de doble sentido, + //hace la paralela a una distancia dada para que no se superpongan la ida y la vuelta + if((pp->elem[i].tp==OLV_PLAN_TIP_NW) && (olv_limp->iaso[pp->elem[i].refe].flgs & OLV_LIMP_FLG_NW) && + !((olv_limp->iaso[pp->elem[i].refe].flgs & OLV_LIMP_FLG_CIRC_NO_DOB))) + { + d=OLV_DIST_PARALELAS; + if(pp->elem[i].k==0) + d=d*(-1);//distancia negativa si es sentido contrario + + Colv_geom::haz_paralela(ptos,npt,d,&ptos_par); + ptos=(double (*)[3])ptos_par; + } + lin_parc.pts.add(ptos,npt); + ///////////////////////// + //por si hay que darle la vuelta a los puntos + if(pp->elem[i].k==1) + { + lin_parc.invert(); + } + + carto_aux.add(lin_parc); + + if(!(lin.pts+lin_parc.pts)) + { + return FALSE; + } + if(inelem==0 && !is_insta) + { + lin.addPto(olv_limp->carto.getPto(0)); + lin.addPto(olv_limp->carto.getPto(0)); + } + lin.ia=is+1; + if(!rut->add(lin)) + { + return FALSE; + } + + if(is_insta) + return TRUE; + + ///////////////////// + //carto_aux.exportShp("C:\\Proyectos\\Olivia\\Instal\\rut.shp"); + ///////////////////// + + //ahora las flechas + lin_fl.pts+=2; + lin_fl.pts.n=2; + pts_lin_fl = lin_fl.pts.ptr; + lin_fl.ia=is+1; + if(pp->nelem==0 && !is_insta) + { + lin_fl.addPto(olv_limp->carto.getPto(0)); + lin_fl.addPto(olv_limp->carto.getPto(0)); + if(!flech->add(lin_fl)) + { + return FALSE; + } + return TRUE; + } + + ///////////////////////////////// + //Pone las flechas a lo largo de la línea + nfl=0; + ltot= lin.getLong(); + nfl=(int)(ltot/long_max_fl); + for(i=0;iadd(lin_fl)) + { + break; + } + } + if(iolv->paths.path_res_rut); + //cambiaext(path_shp,".shp",""); + *(Cdir_manager::extension_archivo(path_shp)-1)=0; + + strcat_s(path_shp,"_R.shp"); + carto_rut.setNameIa(olv_limp->camps.campo_secto); + if(!carto_rut.linesExportShp(path_shp)) + return FALSE; + if(!guarda_cols_ruta(path_shp)) + return FALSE; + + /////////////////////////////////////////////////////// + //luego graba los archivos de los puntos de control + //graba todos los sectores en un único path + strcpy_s(path_shp,MAX_PATH,olv_limp->olv->paths.path_res_pt); + //cambiaext(path_shp,".shp",""); + *(Cdir_manager::extension_archivo(path_shp)-1)=0; + strcat_s(path_shp,"_C.shp"); + carto_ctrl.setNameIa(olv_limp->camps.campo_secto); + if(!carto_ctrl.ptosExportShp(path_shp)) + return FALSE; + if(!guarda_cols_ctrl(path_shp)) + return FALSE; + + ///////////////////////////////////////////// + //A continuación graba los archivos de las flechas + strcpy_s(path_shp,MAX_PATH,olv_limp->olv->paths.path_res_rut); + //cambiaext(path_shp,".shp",""); + *(Cdir_manager::extension_archivo(path_shp)-1)=0; + + strcat_s(path_shp,"_Raux.shp"); + carto_flech.setNameIa(olv_limp->camps.campo_secto); + if(!carto_flech.linesExportShp(path_shp)) + return FALSE; + + ///////////////////////////////////////////// + //A continuación graba los archivos de los viajes a las instalaciones + if(olv_limp->nod_instal>=0) + { + strcpy_s(path_shp,MAX_PATH,olv_limp->olv->paths.path_res_rut); + //cambiaext(path_shp,".shp",""); + *(Cdir_manager::extension_archivo(path_shp)-1)=0; + + strcat_s(path_shp,"_I.shp"); + carto_inst.setNameIa(olv_limp->camps.campo_secto); + if(!carto_inst.linesExportShp(path_shp)) + return FALSE; + if(!guarda_cols_insta(path_shp)) + return FALSE; + } + + return TRUE; +} +//************************************************************************************* +/** + * Genera y guarda el shp con las rutas en subtramos, para recogida porque se va a descargar + */ +BOOL Colv_limp_thr::gen_guard_subtramos() +{ + int ntramos=0; + char path_shp[MAX_PATH]; + + //reutiliza los mismos cartos + carto_rut.del(); + carto_flech.del(); + + //cuenta tramos + cuenta_tramos(); + + if(!genera_rut_ctrl(olv_limp->nsec, olv_limp->plan, TRUE)) + { + pon_mi_msg("Errores en la generación de cartografía con ruta de los subtramos"); + return FALSE; + } + + rellena_tramos(); + + if(olv_limp->tipo_shp_viaj==OLV_SHPRUTINST) + { + int ii=rellena_insta_tramos(); + //combina los lineales de cada subtramo con la ida a descargar y la vuelta de descargar anterior + if(ii>0 && !combina_rut_insta()) + { + pon_mi_msg("Errores en la combinación de viajes con viajes a instalación"); + return FALSE; + } + } + + //graba los archivos de la ruta de los sectores + //graba todos los sectores en un único path + strcpy_s(path_shp,MAX_PATH,olv_limp->olv->paths.path_res_rut); + //cambiaext(path_shp,".shp",""); + *(Cdir_manager::extension_archivo(path_shp)-1)=0; + + strcat_s(path_shp,"_R2.shp"); + carto_rut.setNameIa(olv_limp->camps.campo_secto); + if(!carto_rut.linesExportShp(path_shp)) + { + pon_mi_msg("Errores en el guardado del shp de la capa de viajes"); + return FALSE; + } + + if(!guarda_cols_ruta_tram(path_shp)) + { + pon_mi_msg("Errores al guardar las columnas de la capa de viajes"); + return FALSE; + } + + /*///////////////////////////////////////////// + //A continuación sobreescribe los archivos de las flechas + strcpy_s(path_shp,MAX_PATH,olv_limp->olv->paths.path_res_rut); + //cambiaext(path_shp,".shp",""); + *(Cdir_manager::extension_archivo(path_shp)-1)=0; + + strcat_s(path_shp,"_Raux.shp"); + carto_flech.setNameIa(olv_limp->camps.campo_secto); + if(!carto_flech.exportShp(path_shp)) + { + pon_mi_msg("Errores en el guardado del shp de la capa de viajes aux"); + return FALSE; + }*/ + + //guarda en los ámbitos una columna de "tramo al que pertenecen" + if(!guarda_dbf_sector(3)) + { + pon_mi_msg("Errores al guardar la columna de viaje de cada cont"); + return FALSE; + } + + delete [] olv_limp->tramos; + olv_limp->tramos=NULL; + + return TRUE; +}//************************************************************************************* +/** + * Como los viajes a instalaciones están ordenados, y los tramos también + * le corresponde a cada tramo it el viaje it y el it+1, excepto al último, que le pueden + * corresponder 3 viajes si la instalación y la descarga no son en el mismo sitio + * Además, actualiza el tiempo de los tramos + */ +int Colv_limp_thr::rellena_insta_tramos() +{ + int it, nt, nins,ii; + Info_planif *pinsta; + Info_tramos *tramo; + + ii=0; //para saber si hace algún tramo o no + for(int is=0;isnsec;is++) + { + nt=(int)olv_limp->tramos[is].size(); + nins = olv_limp->plan[is].ninsta; + if(!nins) + continue; + if(olv_limp->plan[is].planif_insta[nins-1].nelem==0) + nins--; //es porque la descarga y planta son la misma + pinsta = olv_limp->plan[is].planif_insta; + for(it=0;ittramos[is][it]; + tramo->iins[0]=2*it; + tramo->iins[1]=2*it+1; + + /////////////////////////////////////// + //Actualiza los tiempos del tramo sumando los tiempos del viaje a inst + tramo->t_ini -= (float)pinsta[tramo->iins[0]].elem[pinsta[tramo->iins[0]].nelem-1].coste; + tramo->t_fin += (float)pinsta[tramo->iins[1]].elem[pinsta[tramo->iins[1]].nelem-1].coste; + tramo->t_total_tr=(float) (tramo->t_fin-tramo->t_ini); + } + //para el último tramo + tramo = &olv_limp->tramos[is][it]; + tramo->iins[0]=2*it; + tramo->iins[1]=nins-1; + tramo->t_ini -= (float)pinsta[tramo->iins[0]].elem[pinsta[tramo->iins[0]].nelem-1].coste; + tramo->t_fin += (float)pinsta[tramo->iins[1]].elem[pinsta[tramo->iins[1]].nelem-1].coste; + tramo->t_total_tr=(float) (tramo->t_fin-tramo->t_ini); + ii++; + } + return ii; +} +//************************************************************************************* +/** + * Añade las columnas de información a la ruta, tiempos, longitudes, y demás + */ +BOOL Colv_limp_thr::guarda_cols_ruta_tram(char *path_shp) +{ + char *info; + char path_dbf[MAX_PATH]; + double tt; + int h,m,s; + int i, it,ntram,nt,nt_parc; + ManagerDbfGdataTable dbfmgr; + + //cuenta el número de sectores no vacíos + ntram=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + continue; + ntram+=(int)olv_limp->tramos[i].size(); + } + + //añade una columna a la ruta de tiempo de ruta + strcpy_s(path_dbf,MAX_PATH,path_shp); + //cambiaext(path_dbf,".shp",".dbf"); + strcpy((Cdir_manager::extension_archivo(path_dbf)),"dbf"); + info = (char *)malloc(ntram*OLV_SHP_SZ_CAMP_CHAR); + if(!info) + { + return FALSE; + } + memset(info,0,ntram*OLV_SHP_SZ_CAMP_CHAR); + AddColsDbf dataDbf(info); + + //SECTOR ya viene + + //TRATAMIENTO + nt_parc=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + continue; + nt=(int)olv_limp->tramos[i].size(); + for(it=0;itnomb_tto); + } + nt_parc+=nt; + } + if(!dbfmgr.AddCol(path_dbf,"TTO",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) + { + free(info); + return FALSE; + } + memset(info,0,ntram*OLV_SHP_SZ_CAMP_CHAR); + + //VIAJE + nt_parc=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + continue; + nt=(int)olv_limp->tramos[i].size(); + for(it=0;itnsec;i++) + { + if(olv_limp->sec[i].namb==0) + continue; + nt=(int)olv_limp->tramos[i].size(); + for(it=0;ittramos[i][it].t_ini; + dame_h_m_s(tt, &h, &m, &s); + sprintf_s(&info[(nt_parc+it)*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%02d:%02d:%02d h",h,m,s); + } + nt_parc+=nt; + } + if(!dbfmgr.AddCol(path_dbf,"H_INI",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) + { + free(info); + return FALSE; + } + memset(info,0,ntram*OLV_SHP_SZ_CAMP_CHAR); + + //H_FIN + nt_parc=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + continue; + nt=(int)olv_limp->tramos[i].size(); + for(it=0;ittramos[i][it].t_fin; + dame_h_m_s(tt, &h, &m, &s); + sprintf_s(&info[(nt_parc+it)*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%02d:%02d:%02d h",h,m,s); + } + nt_parc+=nt; + } + if(!dbfmgr.AddCol(path_dbf,"H_FIN",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) + { + free(info); + return FALSE; + } + memset(info,0,ntram*OLV_SHP_SZ_CAMP_CHAR); + + //T_TOTAL + nt_parc=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + continue; + nt=(int)olv_limp->tramos[i].size(); + for(it=0;ittramos[i][it].t_total_tr;//tramos[i][it].t_fin-tramos[i][it].t_ini; + dame_h_m_s(tt, &h, &m, &s); + sprintf_s(&info[(nt_parc+it)*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%02d:%02d:%02d h",h,m,s); + } + nt_parc+=nt; + } + if(!dbfmgr.AddCol(path_dbf,"T_TOTAL",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) + { + free(info); + return FALSE; + } + memset(info,0,ntram*OLV_SHP_SZ_CAMP_CHAR); + + //T_TTO + nt_parc=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + continue; + nt=(int)olv_limp->tramos[i].size(); + for(it=0;ittramos[i][it].t_tto_tr; + dame_h_m_s(tt, &h, &m, &s); + sprintf_s(&info[(nt_parc+it)*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%02d:%02d:%02d h",h,m,s); + } + nt_parc+=nt; + } + if(!dbfmgr.AddCol(path_dbf,"T_TTO",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) + { + free(info); + return FALSE; + } + memset(info,0,ntram*OLV_SHP_SZ_CAMP_CHAR); + + return TRUE; +} +//************************************************************************************* +/** + * Cuenta los tramos que hay en la ruta del sector is, si va varias veces a descargar + */ +void Colv_limp_thr::cuenta_tramos() +{ + olv_limp->tramos = new std::vector[olv_limp->nsec]; + Info_planif *pp; + Info_tramos tramo; + int ie,ii,ilast,iamb; + + memset(&tramo,0,sizeof(Info_tramos)); + tramo.iins[0]=tramo.iins[1]=-1; + + for(int is=0;isnsec;is++) + { + pp=&olv_limp->plan[is]; + ii=0; + tramo.ie[0]=0; + for(ie=0;ienelem;ie++) + { + if(pp->elem[ie].tp!=OLV_PLAN_TIP_AMB) + continue; + if(pp->elem[ie].aux!=ii) + { + tramo.ie[1]=ilast; + olv_limp->tramos[is].push_back(tramo); + ii++; + tramo.ie[0]=ie; + } + if(olv_limp->iaso[pp->elem[ie].refe].flgs & OLV_LIMP_FLG_SEG_PUN) + iamb=olv_limp->iaso[pp->elem[ie].refe].refe2; + else + iamb=olv_limp->iaso[pp->elem[ie].refe].iamb; + olv_limp->amb_sec[iamb].res=ii; //marca el tramo en el array de ambitos + ilast=ie; + } + tramo.ie[1]=pp->nelem-1; + olv_limp->tramos[is].push_back(tramo); + } +} +//************************************************************************************* +/** + * Rellena la info de los tramos + */ +void Colv_limp_thr::rellena_tramos() +{ + Info_planif *pp; + Info_tramos *tramo; + int ie,it,nt; + + for(int is=0;isnsec;is++) + { + pp=&olv_limp->plan[is]; + nt=(int)olv_limp->tramos[is].size(); + for(it=0;ittramos[is][it]; + tramo->namb=0; + tramo->ncont=0; + for(ie=tramo->ie[0]; ie<=tramo->ie[1];ie++) + { + tramo->long_tr+=(float) pp->elem[ie].ltot; + if(pp->elem[ie].tp!=OLV_PLAN_TIP_AMB) + continue; + + tramo->namb++; + } + + tramo->t_tto_tr = (float)(pp->t[OLV_TTO]); + if(pp->planif_insta) + { + if(it==0) + tramo->t_ini = (float)(olv_limp->t_ini+olv_limp->t_sal+pp->planif_insta[0].elem[pp->planif_insta[0].nelem-1].coste); + else + tramo->t_ini = (float)(pp->planif_insta[2*it].t[OLV_TTO]+pp->planif_insta[2*it].elem[pp->planif_insta[2*it].nelem-1].coste); + tramo->t_fin = (float)pp->planif_insta[2*it+1].t[OLV_TTO]; + } + else + { + tramo->t_ini = (float)(olv_limp->t_ini+olv_limp->t_sal); + tramo->t_fin = (float)(tramo->t_ini + olv_limp->sec[is].cost_ac+olv_limp->t_desc); + } + + tramo->t_total_tr = (float) (tramo->t_fin-tramo->t_ini); + } + } +} +//************************************************************************************* +/** + * Dadas las rutas de los sectores, genera la ruta en una única línea en el obg + * y en otro coloca los puntos de control + */ +BOOL Colv_limp_thr::combina_rut_insta() +{ + //en ob_rut ahora están todos los subtramos en orden: + //1 viaje del sector 1, 2 viaje del sector 1, 1 viaje del sector 2, etc + //hay que añadir al primer viaje de cada sector la ida desde instalación y la ida a descargar (y la ida a instalación + //si es un único viaje) + //al resto de viajes intermedios hay que añadirles la vuelta de descargar anterior y la ida a descargar + //al último viaje hay que añadirle la ida a descargar y la ida a instalación + int is=0, it=0, nt=0, i=0, npt_tot, npt, ntparc,ii; + int niparc, res, nmax_pts; + BOOL mal = false; + Info_planif *planif, *pp; + double (*ptos_aux)[3],(*ptos)[3]; + CartoLine lin; + + planif= olv_limp->plan; + + ntparc=0; + niparc=0; + nmax_pts=0; + for(is=0;isnsec && !mal;is++) + { + pp=&planif[is]; + nt=(int)olv_limp->tramos[is].size(); + lin.ia=is+1; + lin.pts.n=0; + for(it=0;ittramos[is][it].iins[0]; ii<=olv_limp->tramos[is][it].iins[1];ii++) + { + npt=carto_inst.getEntity(ii+niparc).getNumberPtos(); + npt_tot+=npt; + res++; + } + //dado que junta tramos, resta para no replicar los puntos de unión + npt_tot=npt_tot-res; + + //////////////////////////////////////////////////////////////////// + //marca para borrar ese tramo + carto_rut.remove(it+ntparc); + //ya que tiene el total de puntos, actualiza el lineal de ese tramo + lin.pts+=npt_tot; + ptos_aux=lin.pts.ptr; + if(!ptos_aux) + { + mal=TRUE; + continue; + } + + ////////////////////////////////////////////////////////////////////// + //ahora copia en ptos_aux los lineales de los tramos que le corresponden + for(ii=olv_limp->tramos[is][it].iins[0]; ii<=olv_limp->tramos[is][it].iins[1];ii++) + { + npt=carto_inst.getEntity(ii+niparc).getNumberPtos(); + ptos = (double (*)[3])carto_inst.getEntity(ii+niparc).getPto(0); + + //copia el viaje al lineal total + lin.pts.add(ptos,npt); + lin.pts.n--; + //memcpy(ptos_aux[npt_parc],ptos,npt*3*sizeof(double)); + //npt_parc+=npt-1; + if(ii==olv_limp->tramos[is][it].iins[1]) + lin.pts.n++; + + if(ii==olv_limp->tramos[is][it].iins[0]) + { + //después del primer viaje se copia el tramo de recogida + npt=carto_rut.getEntity(it+ntparc).getNumberPtos(); + ptos = (double (*)[3])carto_rut.getEntity(it+ntparc).getPto(0); + + //copia el viaje al lineal total + lin.pts.add(ptos,npt); + lin.pts.n--; + //memcpy(ptos_aux[npt_parc],ptos,npt*3*sizeof(double)); + //npt_parc+=npt-1; + } + } + ////////////////////////////////////////////////////////////////////// + if(!carto_rut.add(lin)) + { + mal=TRUE; //entra por aquí?? + continue; + } + } + niparc+=ii; //ii apunta a la última instalación del primer sector + ntparc+=nt; + } + if(mal) + { + return FALSE; + } + carto_rut.FastClear(); + return TRUE; +} +//************************************************************************************* +/** + * Añade las columnas de información a la ruta, tiempos, longitudes, y demás + */ +BOOL Colv_limp_thr::guarda_cols_ruta(char *path_shp) +{ + char *info; + char path_dbf[MAX_PATH]; + double tt; + int h,m,s; + char nombia[16]; + int nsec, i, isec_novac; + ManagerDbfGdataTable dbfmgr; + + //cuenta el número de sectores no vacíos + nsec=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb!=0) + nsec++; + } + + //////////////////////////////////// + //El coste_ac es lo mismo que el cost del último elemento de la planif + //más el de desplazamientos inicial y final y de descargas + //Para el total, hay que añadir los descansos + ///////////////////////////////////// + + //añade una columna a la ruta de tiempo de ruta + strcpy_s(path_dbf,MAX_PATH,path_shp); + //cambiaext(path_dbf,".shp",".dbf"); + strcpy((Cdir_manager::extension_archivo(path_dbf)),"dbf"); + info = (char *)malloc(nsec*OLV_SHP_SZ_CAMP_CHAR); + if(!info) + { + return FALSE; + } + memset(info,0,nsec*OLV_SHP_SZ_CAMP_CHAR); + AddColsDbf dataDbf(info); + + //SECTOR ya viene + //TRATAMIENTO + isec_novac=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + { + continue; + } + sprintf_s(&info[isec_novac*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%s",olv_limp->nomb_tto); + isec_novac++; + } + if(!dbfmgr.AddCol(path_dbf,"TTO",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) + { + free(info); + return FALSE; + } + memset(info,0,nsec*OLV_SHP_SZ_CAMP_CHAR); + + //rellena la info de hora inicial + isec_novac=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + { + continue; + } + tt=olv_limp->t_ini; + dame_h_m_s(tt, &h, &m, &s); + sprintf_s(&info[isec_novac*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%02d:%02d:%02d h",h,m,s); + isec_novac++; + } + if(!dbfmgr.AddCol(path_dbf,"H_INI",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) + { + free(info); + return FALSE; + } + memset(info,0,nsec*OLV_SHP_SZ_CAMP_CHAR); + + //rellena la info de hora final + isec_novac=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + { + continue; + } + tt=olv_limp->t_ini+ olv_limp->sec[i].cost_ac + olv_limp->t_desc; + + dame_h_m_s(tt, &h, &m, &s); + sprintf_s(&info[isec_novac*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%02d:%02d:%02d h",h,m,s); + isec_novac++; + } + if(!dbfmgr.AddCol(path_dbf,"H_FIN",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) + { + free(info); + return FALSE; + } + memset(info,0,nsec*OLV_SHP_SZ_CAMP_CHAR); + + //rellena la info de duración total + isec_novac=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + continue; + tt=olv_limp->sec[i].cost_ac+olv_limp->t_desc; + dame_h_m_s(tt, &h, &m, &s); + sprintf_s(&info[isec_novac*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%02d:%02d:%02d h",h,m,s); + isec_novac++; + } + if(!dbfmgr.AddCol(path_dbf,"T_TOTAL",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) + { + free(info); + return FALSE; + } + memset(info,0,nsec*OLV_SHP_SZ_CAMP_CHAR); + + //rellena la info de duración de los desplazamientos + isec_novac=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + continue; + tt=olv_limp->sec[i].t_despl[0]+olv_limp->sec[i].t_despl[1]; + dame_h_m_s(tt, &h, &m, &s); + sprintf_s(&info[isec_novac*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%02d:%02d:%02d h",h,m,s); + isec_novac++; + } + if(!dbfmgr.AddCol(path_dbf,"T_INSTA",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) + { + free(info); + return FALSE; + } + memset(info,0,nsec*OLV_SHP_SZ_CAMP_CHAR); + + //rellena la info de duración de los descansos + isec_novac=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + continue; + tt=olv_limp->t_desc; + dame_h_m_s(tt, &h, &m, &s); + sprintf_s(&info[isec_novac*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%02d:%02d:%02d h",h,m,s); + isec_novac++; + } + if(!dbfmgr.AddCol(path_dbf,"T_DESCAN",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) + { + free(info); + return FALSE; + } + memset(info,0,nsec*OLV_SHP_SZ_CAMP_CHAR); + + //rellena la info de duración de la ruta + isec_novac=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + continue; + tt=olv_limp->plan[i].elem[olv_limp->plan[i].nelem-1].coste; + dame_h_m_s(tt, &h, &m, &s); + sprintf_s(&info[isec_novac*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%02d:%02d:%02d h",h,m,s); + isec_novac++; + } + if(!dbfmgr.AddCol(path_dbf,"T_RUTA",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) + { + free(info); + return FALSE; + } + memset(info,0,nsec*OLV_SHP_SZ_CAMP_CHAR); + + //rellena la info de longitud de la ruta + isec_novac=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + continue; + tt=olv_limp->plan[i].m[0]+olv_limp->plan[i].m[1]; + sprintf_s(&info[isec_novac*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%.2f",tt); + isec_novac++; + } + if(!dbfmgr.AddCol(path_dbf,"M_RUTA",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) + { + free(info); + return FALSE; + } + memset(info,0,nsec*OLV_SHP_SZ_CAMP_CHAR); + + //rellena primero T DESP, M DESP, VELO DESP, T TRAT, M TRAT, VELO/T TRAT + int p; + for(int k=0;knsec;i++) + { + if(olv_limp->sec[i].namb==0) + continue; + tt=olv_limp->plan[i].t[k]; + dame_h_m_s(tt, &h, &m, &s); + sprintf_s(&info[isec_novac*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%02d:%02d:%02d h",h,m,s); + isec_novac++; + } + } + else if(p==1) + { + if(k==OLV_TTO) + { + if(olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoM2h || olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoM2h_eje) + strcpy_s(nombia,"M2_"); + else if(olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoMh || olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoMh_eje) + strcpy_s(nombia,"M_"); + else if(olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoMin) + strcpy_s(nombia,"UDS_"); + } + else + { + strcpy_s(nombia,"M_"); + } + if((k==OLV_TTO) && (olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoMin)) + { + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + continue; + tt=olv_limp->sec[i].namb; + sprintf_s(&info[isec_novac*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%ld",(int)tt); + isec_novac++; + } + } + else + { + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + continue; + tt=olv_limp->plan[i].m[k]; + sprintf_s(&info[isec_novac*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%.2f",tt); + isec_novac++; + + } + } + } + else if(p==2) + { + if(k==OLV_TTO) + { + tt=olv_limp->t_tto; + if(olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoM2h || olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoM2h_eje) + strcpy_s(nombia,"M2_H_"); + else if(olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoMh || olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoMh_eje) + strcpy_s(nombia,"M_H_"); + else if(olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoMin) + { + strcpy_s(nombia,"MIN_"); + tt=tt/60;//para pasarlo a minutos + } + + } + else + { + strcpy_s(nombia,"M_H_"); + tt=olv_limp->v_despl/OLV_KMH2MS; + } + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + continue; + if(tt) + sprintf_s(&info[isec_novac*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%.1f",tt); + else + sprintf_s(&info[isec_novac*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"Def. Vias"); + isec_novac++; + } + } + if(k==OLV_TTO) + { + strcat_s(nombia,"TRAT"); + } + else if(k==OLV_DESP) + { + strcat_s(nombia,"DESP"); + } + if(!dbfmgr.AddCol(path_dbf,nombia,GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) + { + free(info); + return FALSE; + } + memset(info,0,nsec*OLV_SHP_SZ_CAMP_CHAR); + } + } + + free(info); + return TRUE; +} +//************************************************************************************* +/** + * Añade las columnas de información a los puntos de control + */ +BOOL Colv_limp_thr::guarda_cols_ctrl(char *path_shp) +{ + char path_dbf[MAX_PATH]; + int h,m,s,k; + double tt; + char *info; + int nsec, i, isec_novac; + ManagerDbfGdataTable dbfmgr; + + //cuenta el número de sectores no vacíos + nsec=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb!=0) + nsec++; + } + + //añade una columna a los puntos de control de secuencia + strcpy_s(path_dbf,MAX_PATH,path_shp); + //cambiaext(path_dbf,".shp",".dbf"); + strcpy((Cdir_manager::extension_archivo(path_dbf)),"dbf"); + + info = (char *)malloc(nsec*olv_limp->npts_ctrl*OLV_SHP_SZ_CAMP_CHAR); + if(!info) + { + return FALSE; + } + memset(info,0,nsec*olv_limp->npts_ctrl*OLV_SHP_SZ_CAMP_CHAR); + AddColsDbf dataDbf(info); + + //rellena el nombre del tto + k=0; + isec_novac=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + continue; + + sprintf_s(&info[k*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,olv_limp->nomb_tto); + k++; + for(k;k<(isec_novac+1)*olv_limp->npts_ctrl-1;k++) + sprintf_s(&info[k*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,olv_limp->nomb_tto); + sprintf_s(&info[k*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,olv_limp->nomb_tto); + isec_novac++; + k++; + } + if(!dbfmgr.AddCol(path_dbf,"TTO",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) + { + free(info); + return FALSE; + } + memset(info,0,nsec*olv_limp->npts_ctrl*OLV_SHP_SZ_CAMP_CHAR); + + //rellena la info + k=0; + isec_novac=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + continue; + sprintf_s(&info[k*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"Inicio"); + k++; + for(k;k<(isec_novac+1)*olv_limp->npts_ctrl-1;k++) + sprintf_s(&info[k*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"Medio"); + sprintf_s(&info[k*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"Fin"); + isec_novac++; + k++; + } + if(!dbfmgr.AddCol(path_dbf,"SECUENCIA",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) + { + free(info); + return FALSE; + } + memset(info,0,nsec*olv_limp->npts_ctrl*OLV_SHP_SZ_CAMP_CHAR); + + //rellena la info de tiempo + k=0; + isec_novac=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + continue; + tt= olv_limp->t_ini+olv_limp->sec[i].t_despl[0]; + dame_h_m_s(tt, &h, &m, &s); + sprintf_s(&info[k*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%02d:%02d:%02d h",h,m,s); + k++; + for(k;k<(isec_novac+1)*olv_limp->npts_ctrl-1;k++) + { + tt= olv_limp->plan[i].pts_ctrl[k-(isec_novac*olv_limp->npts_ctrl+1)].cost; + dame_h_m_s(tt, &h, &m, &s); + sprintf_s(&info[k*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%02d:%02d:%02d h",h,m,s); + } + tt= olv_limp->plan[i].pts_ctrl[olv_limp->npts_ctrl-2].cost; + dame_h_m_s(tt, &h, &m, &s); + sprintf_s(&info[k*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%02d:%02d:%02d h",h,m,s); + k++; + isec_novac++; + } + if(!dbfmgr.AddCol(path_dbf,"HORA",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) + { + free(info); + return FALSE; + } + + free(info); + return TRUE; +} +//************************************************************************************* +/** + * Añade las columnas de información a las rutas de viajes a la instalación + */ +BOOL Colv_limp_thr::guarda_cols_insta(char *path_shp) +{ + char path_dbf[MAX_PATH]; + char *info; + double tt,ttt; + int h,m,s,insta,i,ninsta,ninsta_parc,ninsta_novac; + char tray[OLV_SHP_SZ_CAMP_CHAR]; + ManagerDbfGdataTable dbfmgr; + + //añade una columna + strcpy_s(path_dbf,MAX_PATH,path_shp); + //cambiaext(path_dbf,".shp",".dbf"); + char bufAux[256]; + strcpy(path_dbf, Cdir_manager::cambia_extension_archivo(path_dbf,bufAux,".dbf")); + //cuenta el número de instalaciones + ninsta=0; + for(i=0;insec;i++) + { + for(insta=0;instaplan[i].ninsta;insta++) + { + if(olv_limp->plan[i].planif_insta[insta].nelem!=0) + ninsta++; + } + } + + info = (char *)malloc(ninsta*OLV_SHP_SZ_CAMP_CHAR); + if(!info) + { + return FALSE; + } + memset(info,0,ninsta*OLV_SHP_SZ_CAMP_CHAR); + AddColsDbf dataDbf(info); + + //rellena el nombre del tto + ninsta_parc=0; + for(i=0;insec;i++) + { + ttt=0; + ninsta_novac=0; + for(insta=0;instaplan[i].ninsta;insta++) + { + if(olv_limp->plan[i].planif_insta[insta].nelem==0) + continue; + + sprintf_s(&info[(insta+ninsta_parc)*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%s",olv_limp->nomb_tto); + ninsta_novac++; + } + ninsta_parc+=ninsta_novac; + } + if(!dbfmgr.AddCol(path_dbf,"TTO",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) + { + free(info); + return FALSE; + } + memset(info,0,ninsta*OLV_SHP_SZ_CAMP_CHAR); + + //rellena la info de tipo de trayecto + ninsta_parc=0; + for(i=0;insec;i++) + { + ninsta_novac=0; + for(insta=0;instaplan[i].ninsta;insta++) + { + if(olv_limp->plan[i].planif_insta[insta].nelem==0) + continue; + + switch(olv_limp->plan[i].planif_insta[insta].ninsta) + { + case OLV_IDA_INST: + strcpy_s(tray,"Ida desde instalacion"); //quitado acento para evitar que salga mal + break; + case OLV_VUELTA_INST: + strcpy_s(tray,"Vuelta a instalacion"); + break; + case OLV_IDA_PLANT_ULT: + strcpy_s(tray,"Ultima ida a descargar"); + break; + case OLV_IDA_PLANT: + strcpy_s(tray,"Ida a descargar"); + break; + case OLV_VUELTA_PLANT: + strcpy_s(tray,"Vuelta de descargar"); + break; + } + sprintf_s(&info[(insta+ninsta_parc)*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%s",tray); + ninsta_novac++; + } + ninsta_parc+=ninsta_novac; + } + if(!dbfmgr.AddCol(path_dbf,"TRAYECTO",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) + { + free(info); + return FALSE; + } + memset(info,0,ninsta*OLV_SHP_SZ_CAMP_CHAR); + + //rellena la info de tipo de hora + ninsta_parc=0; + for(i=0;insec;i++) + { + ninsta_novac=0; + for(insta=0;instaplan[i].ninsta;insta++) + { + if(olv_limp->plan[i].planif_insta[insta].nelem==0) + continue; + + switch(olv_limp->plan[i].planif_insta[insta].ninsta) + { + case OLV_IDA_INST: + tt=olv_limp->t_ini; + break; + case OLV_VUELTA_INST: + tt=olv_limp->t_ini+olv_limp->sec[i].cost_ac-olv_limp->sec[i].t_despl[1]+olv_limp->t_desc; + olv_limp->plan[i].planif_insta[insta].t[OLV_TTO]=tt; + break; + case OLV_IDA_PLANT: + case OLV_IDA_PLANT_ULT: + tt=olv_limp->plan[i].planif_insta[insta].t[OLV_TTO]; + break; + case OLV_VUELTA_PLANT: + tt=olv_limp->plan[i].planif_insta[insta].t[OLV_TTO]; + break; + } + dame_h_m_s(tt, &h, &m, &s); + sprintf_s(&info[(insta+ninsta_parc)*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%02d:%02d:%02d h",h,m,s); + ninsta_novac++; + } + ninsta_parc+=ninsta_novac; + } + if(!dbfmgr.AddCol(path_dbf,"H_TRAY",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) + { + free(info); + return FALSE; + } + memset(info,0,ninsta*OLV_SHP_SZ_CAMP_CHAR); + + //rellena la info de duración + ninsta_parc=0; + for(i=0;insec;i++) + { + ttt=0; + ninsta_novac=0; + for(insta=0;instaplan[i].ninsta;insta++) + { + if(olv_limp->plan[i].planif_insta[insta].nelem==0) + continue; + + tt=olv_limp->plan[i].planif_insta[insta].elem[olv_limp->plan[i].planif_insta[insta].nelem-1].coste; + ttt+=tt; + dame_h_m_s(tt, &h, &m, &s); + sprintf_s(&info[(insta+ninsta_parc)*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%02d:%02d:%02d h",h,m,s); + ninsta_novac++; + } + ninsta_parc+=ninsta_novac; + } + if(!dbfmgr.AddCol(path_dbf,"T_TRAY",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) + { + free(info); + return FALSE; + } + memset(info,0,ninsta*OLV_SHP_SZ_CAMP_CHAR); + + //rellena la info de longitud + ninsta_parc=0; + for(i=0;insec;i++) + { + ninsta_novac=0; + for(insta=0;instaplan[i].ninsta;insta++) + { + if(olv_limp->plan[i].planif_insta[insta].nelem==0) + continue; + + tt=olv_limp->plan[i].planif_insta[insta].m[OLV_DESP]; + sprintf_s(&info[(insta+ninsta_parc)*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%.2f",tt); + ninsta_novac++; + } + ninsta_parc+=ninsta_novac; + } + if(!dbfmgr.AddCol(path_dbf,"M_TRAY",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) + { + free(info); + return FALSE; + } + memset(info,0,ninsta*OLV_SHP_SZ_CAMP_CHAR); + + free(info); + return TRUE; +} +//************************************************************************************* +/** + * Recorre la ruta y genera un listado en csv donde guarda las calles por las que va pasando la ruta + * El archivo se llama como el shape, concatenando el número de sector y L, en formato csv + */ +BOOL Colv_limp_thr::genera_list_rut_ctrl() +{ + Info_planif *pp; + Colv_csv cc; + char tto_desp[32],observ[32],calle[1024],path_csv[MAX_PATH],fila[256],fila0[256]; + int i,j,h,m,seg,ii,dt; + double ltot,ltot0,tt,t0; + BOOL mal; + + double lttt; + + mal=FALSE; + strcpy_s(path_csv,MAX_PATH,olv_limp->olv->paths.path_data); + //cambiaext(path_csv,".shp","_L.csv"); + strcpy((Cdir_manager::extension_archivo(path_csv)-1),"_L.csv"); + //////////// + if(!cc.inicia(path_csv)) + { + sprintf_s(err_str, "Error al iniciar archivo %s",path_csv); + return FALSE; + } + //Inicia el archivo csv donde va a guardar las calles del itinerario + if(!cc.escribe("Ruta;Secuencia;Calle;Observaciones;Tratamiento/Desplazamiento;Longitud (m);Tiempo acumulado (h);\r\n")) + mal=TRUE; + + olvlog(LOG_TODO,"olv_limp_t","Escribiendo listados de las rutas en csv"); + + //graba los listados de la ruta de los sectores + for(int s=0; snsec && !mal;s++) + { + lttt=0; + ltot0=0; + pp=&olv_limp->plan[s]; + if(pp->nelem==0) + continue; + ii=1; + i=0; + t0=olv_limp->t_ini + olv_limp->sec[s].t_despl[0]; + + ////////////////////////////////////////////// + //primer punto de control e instalación + if(i==0) + { + dame_h_m_s(olv_limp->t_ini, &h, &m, &seg); + sprintf_s(fila0,256,"%02d;%04d;%s;%s;%s;%s;%02d:%02d:%02d;\r\n",s+1,ii,"","","Instalación","",h,m,seg); + if(!cc.escribe(fila0)) + { + mal=TRUE; + continue;; + } + dame_h_m_s(t0, &h, &m, &seg); + sprintf_s(fila0,256,"%02d;%04d;%s;%s;%s;%s;%02d:%02d:%02d;\r\n",s+1,ii,"","","Control","",h,m,seg); + if(!cc.escribe(fila0)) + { + mal=TRUE; + continue;; + } + } + ////////////////////////////////////////////// + + for(i=0;inelem;i++) + { + if(pp->elem[i].tp==OLV_PLAN_TIP_SEG_LIN) + goto ctrl; + + if((pp->elem[i].ltot ==0) && (i>1) && (pp->elem[i].coste==pp->elem[i-1].coste)) + continue; + + if(i<(pp->nelem-1)) + { + if(((pp->elem[i].ref_nw == pp->elem[i+1].ref_nw) || + (((olv_limp->iaso[pp->elem[i].ref_nw].flgs & OLV_LIMP_FLG_NW) && (olv_limp->iaso[pp->elem[i+1].ref_nw].flgs & OLV_LIMP_FLG_NW))&& + (strcmp(olv_limp->iaso[pp->elem[i].ref_nw].inf_n.nomb,olv_limp->iaso[pp->elem[i+1].ref_nw].inf_n.nomb)==0))) + && (pp->elem[i].tp == pp->elem[i+1].tp) ) + { + ltot0+=pp->elem[i].ltot; + lttt+=pp->elem[i].ltot; + goto ctrl; + } + } + + strcpy_s(observ,32,""); + strcpy_s(tto_desp,32,""); + switch(pp->elem[i].tp) + { + case OLV_PLAN_TIP_NW: + strcpy_s(tto_desp,32,"Desplazamiento"); + dt=OLV_DESP; + break; + case OLV_PLAN_TIP_AMB_PEAT_DESP: + strcpy_s(tto_desp,32,"Despl. por peatonal"); + dt=OLV_DESP; + break; + case OLV_PLAN_TIP_AMB_PEAT: + strcpy_s(observ,32,"Peatonal");//pasa al siguiente para poner tto también + case OLV_PLAN_TIP_AMB: + case OLV_PLAN_TIP_SEG_PUN: + strcpy_s(tto_desp,32,"Tratamiento"); + dt=OLV_TTO; + break; + case OLV_PLAN_TIP_SEG_LIN: + goto ctrl; + } + + if(pp->elem[i].ref_nw>0 && (olv_limp->iaso[pp->elem[i].ref_nw].flgs & OLV_LIMP_FLG_NW) && + olv_limp->iaso[pp->elem[i].ref_nw].inf_n.nomb) + strcpy_s(calle,1024,olv_limp->iaso[pp->elem[i].ref_nw].inf_n.nomb); + else if((pp->elem[i].ref_nw>0) && (!(olv_limp->iaso[pp->elem[i].ref_nw].flgs & OLV_LIMP_FLG_NW)) && + (pp->elem[i].tp == OLV_PLAN_TIP_AMB_PEAT)) + strcpy_s(calle,1024,"Parque---"); + else + calle[0]=0; + + tt=pp->elem[i].coste+t0; //a todos los costes de la ruta se añade el tiempo de desplazamiento + ltot=ltot0+pp->elem[i].ltot; + ltot0=0; + lttt+=pp->elem[i].ltot; + + ////////////////////////////////////////////// + //mira si tiene que poner observaciones por si fuera contendor + if(((olv_limp->iaso[pp->elem[i].refe].flgs & OLV_LIMP_FLG_SEG_PUN)) && (pp->elem[i].tp==OLV_PLAN_TIP_AMB)) + dame_observ_cont(pp->elem[i].refe, observ); + ////////////////////////////////////////////// + + dame_h_m_s(tt, &h, &m, &seg); + if((olv_limp->tipo_ambit==OLV_AMB_PUN) && (pp->elem[i].tp==OLV_PLAN_TIP_AMB)) + sprintf_s(fila,256,"%02d;%04d;%s;%s;%s;%s;%02d:%02d:%02d;\r\n",s+1,ii,calle,observ,tto_desp,"",h,m,seg); + else + sprintf_s(fila,256,"%02d;%04d;%s;%s;%s;%.1f;%02d:%02d:%02d;\r\n",s+1,ii,calle,observ,tto_desp,ltot,h,m,seg); + + ////////////////////////////////////////////// + //escribe fila de paso + if(!cc.escribe(fila)) + { + mal=TRUE; + continue; + } + +ctrl: + ////////////////////////////////////////////// + //puntos de control intermedios + for(j=0;jnpts_ctrl-2 && !mal;j++) + { + if(pp->pts_ctrl[j].ipt==i) + { + t0+=olv_limp->t_desc/(olv_limp->npts_ctrl-2); + tt+=olv_limp->t_desc/(olv_limp->npts_ctrl-2); + pp->pts_ctrl[j].cost = tt; + dame_h_m_s(tt, &h, &m, &seg); + sprintf_s(fila0,256,"%02d;%04d;%s;%s;%s;%s;%02d:%02d:%02d;\r\n",s+1,ii,"","","Control","",h,m,seg); + if(!cc.escribe(fila0)) + { + mal=TRUE; + continue; + } + } + } + ////////////////////////////////////////////// + //viajes a vaciar intermedios + if((olv_limp->iaso[pp->elem[i].refe].flgs & OLV_LIMP_FLG_SEG_PUN)&& (pp->elem[i].tp==OLV_PLAN_TIP_AMB)) + { + if(!genera_list_fila_vaci(&cc, fila0,pp->elem[i].refe, s,ii,tt, &t0,FALSE)) + { + mal=TRUE; + break; + } + } + ////////////////////////////////////////////// + + ii++; + } + ////////////////////////////////////////////// + //último punto de control e instalación + if((i==(pp->nelem))&& !mal) + { + tt=olv_limp->t_ini+ olv_limp->sec[s].cost_ac + olv_limp->t_desc-olv_limp->sec[s].t_despl[1]; + quita_t_ult_desc(s,&tt); + dame_h_m_s(tt, &h, &m, &seg); + sprintf_s(fila0,256,"%02d;%04d;%s;%s;%s;%s;%02d:%02d:%02d;\r\n",s+1,ii,calle,"","Control","",h,m,seg); + if(!cc.escribe(fila0)) + { + mal=TRUE; + continue; + } + pp->pts_ctrl[olv_limp->npts_ctrl-2].cost = tt; + + ////////////////////////////////////////////// + //último viaje a vaciar + if(olv_limp->iaso[pp->elem[i-1].refe].flgs & OLV_LIMP_FLG_SEG_PUN) + { + if(!genera_list_fila_vaci(&cc, fila0,pp->elem[i-1].refe, s,ii,tt, &t0,TRUE)) + { + mal=TRUE; + break; + } + } + ////////////////////////////////////////////// + tt=olv_limp->t_ini+ olv_limp->sec[s].cost_ac + olv_limp->t_desc; + dame_h_m_s(tt, &h, &m, &seg); + sprintf_s(fila0,256,"%02d;%04d;%s;%s;%s;%s;%02d:%02d:%02d;\r\n",s+1,ii,"","","Instalación","",h,m,seg); + if(!cc.escribe(fila0)) + { + mal=TRUE; + continue;; + } + } + + } + + cc.cierra(); + + if(mal) + { + sprintf_s(err_str, "Error al escribir fila en archivo %s",path_csv); + return FALSE; + } + + return TRUE; +} +//************************************************************************************* +/** + * Quita al tiempo total el del último desplazamiento y la última descarga, solo para reco + */ +void Colv_limp_thr::quita_t_ult_desc(int s, double *t) +{ + +} +//************************************************************************************* +/** + * Añade una línea al listado csv con el viaje a vaciar y vuelta + */ +void Colv_limp_thr::dame_h_m_s(double tt, int *h_, int *m_, int *s_) +{ + int h,m,s; + + h=(int)(tt/3600); + m=(int)((tt-h*3600)/60); + s=(int)(tt-m*60-h*3600); + h=h%24; + + *h_=h; + *m_=m; + *s_=s; +} +//************************************************************************************* +/** + * Añade una línea al listado csv con el viaje a vaciar y vuelta + */ +BOOL Colv_limp_thr::genera_list_fila_vaci(Colv_csv *cc, char *fila0,int ielem, int s, int ii, double tt, double *t0,BOOL is_fin) +{ + return TRUE; +} +//************************************************************************************* +/** + * Añade una columna de observación al listado si es contenedores + */ +void Colv_limp_thr::dame_observ_cont(int iamb,char *observ) +{ +} +//************************************************************************************* +/** + * Modifica el dbf del shp original para poner la sectorización, + * que es el mismo que de entrada con una columna más, + * SECTOR (modo 0) o SECUENCIA VACÍA (modo 1) o SECUENCIA BUENA (modo 2) o TRAMO al que pertenece (modo 3) + */ +BOOL Colv_limp_thr::guarda_dbf_sector(int modo) +{ + char path_dbf[MAX_PATH]; + char nom_ia[16]; + + class AddColS : public IAddColDbf + { + public: + Colv_limp *olv_limp; + int mod; + int dt; + AddColS(Colv_limp *ll, int mod) + { + this->olv_limp=ll; + this->mod=mod; + } + virtual void setData(int i, void *data) + { + if(data) + { + switch(mod) + { + case 0://sector + dt=olv_limp->amb_sec[i].sec+1; + break; + case 1://secuencia vacía + dt=0; + break; + case 2://secuencia buena + dt=olv_limp->amb_sec[i].iseq+1; + break; + case 3: + dt=olv_limp->amb_sec[i].res+1; + break; + } + memcpy(data,(void*)&dt,sizeof(int)); + } + + }; + }; + AddColS dataDbf(olv_limp,modo); + ManagerDbfGdataTable dbfmgr; + + //primero graba los archivos de la ruta de los sectores + //graba todos los sectores en un único path + strcpy_s(path_dbf,MAX_PATH,olv_limp->olv->paths.path_data); + //cambiaext(path_dbf,".shp",".dbf"); + strcpy((Cdir_manager::extension_archivo(path_dbf)),"dbf"); + //pone el nombre de la columna + if(modo==0)//sector + strcpy_s(nom_ia,16,"SECTOR"); + else if((modo==1)|| (modo==2))//secuencia + strcpy_s(nom_ia,16,"SECUENCIA"); + else if(modo==3) + strcpy_s(nom_ia,16,"VIAJE"); + + if(!dbfmgr.AddCol(path_dbf,nom_ia,GdataTable::Tint,&dataDbf)) + { + return FALSE; + } + + return TRUE; +} +//************************************************************************************* +/** + * Planifica o calcula el orden en el que hay que recorrer los ambitos del sector s + * la idea es partir de una solucion factible (la cual se consigue por distancias minimas) + * una vez que se tenga se realizan pequeños cambios en dicho orden para ver si mejora, si es asi se deja dicho cambio como permanente + * si no se quita y se intenta otro cambio + */ +Secu_amb * Colv_limp_thr::planifica_sect(Info_sec *s, Djkt_ang_ady *ang_conj, int npermu) +{ + int i,k, j, nsec; + BOOL res=FALSE; + BOOL camb; + th_param_planif thp; + int nth=Colv_geom::dame_n_nucleos(); + int obset=0; + double ca, cold; + Secu_amb *sec; + BOOL nocalc=FALSE; + + sec=(Secu_amb*)malloc(s->namb*sizeof(Secu_amb)); + if(!sec) + goto sal; + memset(sec,0,s->namb*sizeof(Secu_amb)); + + //prepara arrays---------------------- + memset(&thp,0,sizeof(thp)); + + //copia la info del sector + + for (i=0; inamb && !pirate; i++) + { + for(k=0;k<2;k++) + { + sec[i].ctnod[k]=NULL; + } + } + if(pirate) + goto sal; + + //consigue solucion factible------------------------------ + nsec=0; + sec[nsec].iamb=dame_planif_iamb_ini(s,olv_limp->cost_amb,&sec[nsec].entrada ); + //sec[nsec].entrada=-1; + sec[sec[nsec].iamb].flags=1; + if(sec[nsec].iamb<0) + goto sal; + nsec++; + while(nsecnamb) + { + if(!busca_cercano(s,sec, nsec-1, TRUE))//se pilla el minimo local + break; + nsec++; + } + + if(nsecnamb) + goto sal; + //mejora solucion--------------------- + //prepara thread------------ + thp.dth=(th_data_planif*)malloc(sizeof(th_data_planif)*nth); + thp.sec=sec; + thp.tl=this; + + thp.namb=s->namb; + thp.namb_t=s->namb; + thp.s=s; + thp.abs=TRUE;//cambio ger + if(!thp.dth) + goto sigue; + thp.dth[0].sec=(Secu_amb *)malloc(s->namb*nth*sizeof(Secu_amb)); + if(!thp.dth[0].sec) + goto sigue; + for (i=1; inamb*i]; + //lanza-------------------- + for (i=0; i=0) + Sleep(1); + + } + ca=dame_coste(sec,0,s->namb-1,s,TRUE); + do + { + thp.modo=2; + cold=ca; + camb=FALSE; + + //bucle hasta recorrer todos los elementos de sec + //movimientos de elementos puntuales (cambio de posicion) + for (i=1; inamb; i++) + { + thp.param[0]=i; + thp.a_currar(); + //espera thread + while(!thp.terminado()) + Sleep(thp.milis_sleep); + //elije la mejor permuta + j=thp.dame_min(); + + if(j<0 || ca <=thp.dth[j].coste) + continue; + cambia_elem(sec, i, thp.dth[j].pos[0], thp.dth[j].pos[1]); + ca=thp.dth[j].coste; + + cold=ca; + camb=TRUE; + } + //permutaciones de npermu elementos + /*thp.modo=1; + cold=ca; + //camb=FALSE; + for (i=npermu+obset; inamb; i++) + { + thp.param[0]=max(i-npermu, obset); + thp.param[1]=i; + thp.a_currar(); + while(!thp.terminado()) + Sleep(1); + j=thp.dame_min(); + if(j<0 || ca <=thp.dth[j].coste || thp.dth[j].pos[0]<0) + continue; + ca =thp.dth[j].coste; + memcpy(sec, thp.dth[j].sec, s->namb*sizeof(Secu_amb)); + olvlog(LOG_TODO,"olv_limp_t","Permu Mejora coste de %lf a %lf actu: %lf", + cold, ca, dame_coste(sec,0,s->namb-1,ias, s)); + cold=ca; + camb=TRUE; + }*/ + } while (camb); + thp.milis_sleep=1; + + //fuera thread + thp.pirate=TRUE; + while(thp.nth>0) + Sleep(1); + + //---------------------------------------------------------- +sigue: + if (thp.dth) + { + if(thp.dth[0].sec) + free(thp.dth[0].sec); + free(thp.dth); + } + + + pon_t_desp(s, sec); + + + res=TRUE; +sal: + if(!res) + { + if(sec) + free(sec); + sec=NULL; + } + + return sec; +} +//************************************************************************************* +/** + * Rellena los tiempos de desplazamiento + */ +void Colv_limp_thr::pon_t_desp(Info_sec *s, Secu_amb *sec) +{ + if((olv_limp->nod_instal>=0) && (s->namb>1)) + { + s->t_despl[0]=olv_limp->arch_dj.dame_dis(olv_limp->arch_dj.id_instal,0,s->iamb[sec[0].iamb],sec[0].entrada); + s->t_despl[1]=olv_limp->ord_sec_plan[0].ctnod[0][olv_limp->iaso[olv_limp->carto.get(s->iamb[sec[s->namb-1].iamb]).entity()->ref].inod[(sec[s->namb-1].entrada+1)%2]].dis; + } +} +//************************************************************************************* +/** + * Rellena el siguiente nodo en la secuencia + */ +BOOL Colv_limp_thr::busca_cercano(Info_sec *s, Secu_amb *sec, int isec, BOOL ind_abs) +{ + double d=MAYUSCULO; + int nam, nsal, nent; + int k, kk, i, j; + int ic, ind_cost; + ic=sec[isec].entrada; + if(isec==0) + isec=isec; + if(ic<0) + kk=olv_limp->tipo_ambit; + else + kk=1; + + for (k=0; knamb; i++) + { + if(sec[i].flags &1) + continue;///ya esta en la secuencia + if (ind_abs) + ind_cost=s->iamb[i]; + else + ind_cost=i; + for (j=0; jtipo_ambit; j++) + { + if(d>olv_limp->arch_dj.dame_dis(s->iamb[sec[isec].iamb],ic,s->iamb[i],j)) + { + d=olv_limp->arch_dj.dame_dis(s->iamb[sec[isec].iamb],ic,s->iamb[i],j); + nent=j; + nsal=ic; + nam=i; + } + + } + } + } + if(d>=MAYUSCULO) + return FALSE; + + sec[isec++].entrada=(nsal+1)%2; + sec[isec].entrada=nent; + sec[isec].iamb=nam; + sec[nam].flags=1; + return TRUE; +} +//************************************************************************************* +/** + * Da el ámbito inicial por el que empezar la planificación, en función del modo + */ +short Colv_limp_thr::dame_planif_iamb_ini(Info_sec *s, Matrix2d &cost_amb, short *ent/*=NULL*/) +{ + int i,j,iaux,ient,nn, ref_i, ref_j,k; + float aux, dist, dist1; + int modo; + double a, b,c,d,e; + int KK=olv_limp->tipo_ambit; + + //cost_amb=olv_limp->cost_amb; + iaux=-1; + modo=3; + //////////////////////////////////////////////////// + //Coge el ámbito por defecto que se le hubiera dado en la columna secuencia + //Si no, busca el ámbito más cercano a la instalación, si la hubiera configurada, + //Si no, coge el de mayor coste (modo 1) + //O el de 'y+x' menor (modo 2) + //O el más alejado del centro (modo 3) + if(s->iamb_ini_def!=-1) + { + ient=0; + for(i=0;inamb;i++) + { + if(s->iamb[i]==s->iamb_ini_def) + break; + } + iaux=i; + //busca el nodo más cercano a la instalación, si tiene 2 nodos y hay instalación + if(olv_limp->tipo_ambit==OLV_AMB_LIN && olv_limp->nod_instal>=0) + { + //comprueba los dos nodos + dist=olv_limp->arch_dj.dame_dis(olv_limp->arch_dj.id_instal,0,s->iamb[iaux],ient); + dist1=olv_limp->arch_dj.dame_dis(olv_limp->arch_dj.id_instal,0,s->iamb[iaux],1); + if(dist1nod_instal>=0) + { + aux=(float)MAYUSCULO; + //se coge de punto inicial el más cercano a la instalación + for(i=0;inamb;i++) + { + ref_i=olv_limp->carto.get(s->iamb[i]).entity()->ref; + if(olv_limp->iaso[ref_i].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + //calcula la distancia de la instalación al inicio del ámbito + ient=0; + dist=olv_limp->arch_dj.dame_dis(olv_limp->arch_dj.id_instal,0,s->iamb[i],ient); + if(olv_limp->tipo_ambit==OLV_AMB_LIN) + { + //comprueba los dos nodos + + dist1=olv_limp->arch_dj.dame_dis(olv_limp->arch_dj.id_instal,0,s->iamb[i],1); + + if(dist1namb;i++) + { + ref_i=olv_limp->carto.get(s->iamb[i]).entity()->ref; + if(olv_limp->iaso[ref_i].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + //calcula la distancia de mayor entre dos ámbitos + for(j=0;jnamb;j++) + { + if(i==j) + continue; + + ref_j=olv_limp->carto.get(s->iamb[j]).entity()->ref; + if(olv_limp->iaso[ref_j].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + + dist=cost_amb[s->iamb[i]][s->iamb[j]]; + //busca el mayor + if(dist>aux) + { + aux=dist; + iaux=i; + } + } + } + } + else if(modo==2) + { + ///////////////////////////////////// + ////////////////////// + //Como primer ámbito coge el más extremo + //el de menor 'y+x' + aux=(float)MAYUSCULO; + for(i=0;inamb;i++) + { + ref_i=olv_limp->carto.get(s->iamb[i]).entity()->ref; + if(olv_limp->iaso[ref_i].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + if((olv_limp->conjs.coor[olv_limp->iaso[ref_i].inod[0]][1]+olv_limp->conjs.coor[olv_limp->iaso[ref_i].inod[0]][0])conjs.coor[olv_limp->iaso[ref_i].inod[0]][1]+ + olv_limp->conjs.coor[olv_limp->iaso[ref_i].inod[0]][0]); + iaux=i; + } + } + } + else if(modo==3) + { + ////////////////////// + a=0; + b=0; + c=0; + d=0; + e=-1; + nn=0; + //Como primer ámbito coge el más alejado del centro + //coge la x y la y media, el centro + for(i=0;inamb;i++) + { + ref_i=olv_limp->carto.get(s->iamb[i]).entity()->ref; + if(olv_limp->iaso[ref_i].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + for(k=0;kconjs.coor[olv_limp->iaso[ref_i].inod[k]][1]/1000;//divide para que no haga overflow + b+=olv_limp->conjs.coor[olv_limp->iaso[ref_i].inod[k]][0]/1000; + nn++; + } + } + a=a/nn; + b=b/nn; + //busca el más alejado de la x e y media + for(i=0;inamb;i++) + { + ref_i=olv_limp->carto.get(s->iamb[i]).entity()->ref; + if(olv_limp->iaso[ref_i].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + for(k=0;kconjs.coor[olv_limp->iaso[ref_i].inod[k]][1]/1000-a; + c=fabs(c); + d=olv_limp->conjs.coor[olv_limp->iaso[ref_i].inod[k]][0]/1000-b; + d=fabs(d); + if((c+d)>e) + { + e=(c+d); + iaux=i; + if(ent) + *ent=k; + } + } + } + } + return (short)iaux; +} +//************************************************************************************* +/** + * Permuta los elementos de sec en sec_out, desde el indice ini hasta fin aplicando la permutacion p-esima + */ +BOOL Colv_limp_thr::permuta(Secu_amb * sec, int ini, int fin, int p, Secu_amb * sec_out) +{ + int n=fin-ini-1;//numero de elementos a permutar + int nn, i, j, k; + + nn=Colv_geom::fact(n); + for (i=ini; i=0) + return FALSE;//Error al permutar + sec_out[j].flags=1; + sec_out[i].entrada=sec[j].entrada; + sec_out[i].iamb=sec[j].iamb; + } + return TRUE; + +} +//************************************************************************************* +/** + * Cambia de lugar el elemento de la pos_old a la pos_new en la secuencia de elementos sec + */ +void Colv_limp_thr::cambia_elem( Secu_amb * sec,int pos_old, int pos_new, int entr ) +{ + int i; + Secu_amb s; + s.entrada=entr; + s.iamb=sec[pos_old].iamb; + if(pos_old>pos_new) + { + for (i=pos_old; i>pos_new; i--) + { + sec[i].entrada=sec[i-1].entrada; + sec[i].iamb=sec[i-1].iamb; + } + } + else + { + for (i=pos_old; isec=ord_sec; + thp->tl=this; + thp->abs=TRUE; + + if(!thp->dth[0].sec) + thp->dth[0].sec=(Secu_amb *)malloc(thp->namb_t*thp->nth*sizeof(Secu_amb)); + if(!thp->dth[0].sec) + goto npermu; + + for (i=1; inth; i++) + { + thp->dth[i].sec=&thp->dth[0].sec[thp->namb_t*i]; + } + + permu=TRUE; +npermu: + + for (nsecuencia=0; nsecuencianamb; nsecuencia++) + ord_sec[nsecuencia].flags =0; + nsecuencia=0; + + if(ss->namb<=0) + { + ss->cost_ac=0; + return TRUE; + } + //calcula ambito inicial------------ + ord_sec[nsecuencia].iamb=dame_planif_iamb_ini(ss,olv_limp->cost_amb, &ord_sec[nsecuencia].entrada); + if(ord_sec[nsecuencia].iamb<0) + return FALSE; + ord_sec[ord_sec[nsecuencia].iamb].flags=1; + nsecuencia++; + while(nsecuencianamb) + { + if(!busca_cercano(ss,ord_sec, nsecuencia-1,TRUE))//se pilla el minimo local + break; + nsecuencia++; + } + if (nsecuencia>=ss->namb) + { + ss->cost_ac=(float)dame_coste(ord_sec, 0, ss->namb-1, ss, TRUE); + } + else + return FALSE; + + //mira a ver si tiene que pertmutar o no. Si un sector tiene casi todos los ámbitos, no se permuta + int namb_m, nsec; + if(olv_limp->n_amb>=OLV_DESV_MAX_NAMB_MIN) + { + if(olv_limp->calc_nsec) + { + if(olv_limp->nsec_act>1) + namb_m = olv_limp->n_amb/(olv_limp->nsec_act-1); + else + namb_m= olv_limp->n_amb; + } + else + namb_m= olv_limp->n_amb/olv_limp->nsec; + namb_m+=(int)(namb_m*OLV_DESV_MAX_NAMB); + nsec=olv_limp->nsec; + if(olv_limp->calc_nsec>0) + nsec--; + for(int p=0;psec[p].namb>namb_m) + { + permu=FALSE; + break; + } + } + } + + if(!permu) + return TRUE; + + //mejora solucion--------------------- + //prepara thread------------ + thp->namb=ss->namb; + thp->s=ss; + ca=dame_coste(ord_sec, 0, ss->namb-1, ss, TRUE); + if(loguear) + olvlog(LOG_TODO,"olv_limp_t","coste de partida %lf",ca); + do + { + thp->modo=2; + cold=ca; + camb=FALSE; + + //bucle hasta recorrer todos los elementos de sec + //movimientos de elementos puntuales (cambio de posicion) + for (i=1; inamb; i++) + { + thp->param[0]=i; + thp->a_currar(); + //espera thread + while(!thp->terminado()) + Sleep(thp->milis_sleep); + //elije la mejor permuta + k=thp->dame_min(); + if(loguear && k>=0) + olvlog(LOG_TODO,"olv_limp_t","Candidato cal_costes cambia %ld, a %ld, costes: %lf ", + i, thp->dth[k].pos[0], thp->dth[k].coste); + if(k<0 || ca <=thp->dth[k].coste) + continue; + + cambia_elem(ord_sec, i, thp->dth[k].pos[0], thp->dth[k].pos[1]); + ca=thp->dth[k].coste; + if(loguear) + olvlog(LOG_TODO,"olv_limp_t","Mejora coste cambia %ld, a %ld, costes: %lf a %lf", + i, thp->dth[k].pos[0], cold, ca); + cold=ca; + camb=TRUE; + } + //permutaciones de npermu elementos + /*thp.modo=1; + cold=ca; + //camb=FALSE; + for (i=npermu+obset; inamb; i++) + { + thp.param[0]=max(i-npermu, obset); + thp.param[1]=i; + thp.a_currar(); + while(!thp.terminado()) + Sleep(1); + j=thp.dame_min(); + if(j<0 || ca <=thp.dth[j].coste || thp.dth[j].pos[0]<0) + continue; + ca =thp.dth[j].coste; + memcpy(sec, thp.dth[j].sec, s->namb*sizeof(Secu_amb)); + olvlog(LOG_TODO,"olv_limp_t","Permu Mejora coste de %lf a %lf actu: %lf", + cold, ca, dame_coste(sec,0,s->namb-1,ias, s)); + cold=ca; + camb=TRUE; + }*/ + } while (camb && !pirate); + + pon_t_desp(ss, ord_sec); + + ss->cost_ac=(float)ca; + if(loguear) + { + olvlog(LOG_TODO,"olv_limp_t","Coste %lf",ss->cost_ac); + if(esta_repe(thp->sec, thp->namb, FALSE)) + olvlog(LOG_TODO,"olv_limp_t","Esta repe en calcula costes"); + } + + return TRUE; + + //fuera thread + /*if(permu) + { + thp->pirate=TRUE; + while(thp->nth>0) + Sleep(1); + }*/ +} +//************************************************************************************* +/** + * Calcula el coste de los sectores mediante planificación de sus ámbitos + */ +BOOL Colv_limp_thr::calcula_coste_sectores( Secu_amb * ord_sec,Info_sec *ss,int n_sec, th_param_planif *thp, BOOL loguear ) +{ + int obset=0; + int i; + BOOL res=FALSE; + int j; + + if(!thp) + goto npermu; + + thp->sec=ord_sec; + thp->tl=this; + thp->abs=TRUE; + thp->milis_sleep=0; + + if(!thp->dth[0].sec) + thp->dth[0].sec=(Secu_amb *)malloc(thp->namb_t*thp->nth*sizeof(Secu_amb)); + if(!thp->dth[0].sec) + goto npermu; + + for (i=1; inth; i++) + { + thp->dth[i].sec=&thp->dth[0].sec[thp->namb_t*i]; + } + +npermu: + + for (j=0; j=n_sec) + res=TRUE; + + + thp->milis_sleep=1; + + return res; +} +//************************************************************************************* +/** + * Comprueba si hay elementos repetidos en las permutaciones + */ +BOOL Colv_limp_thr::esta_repe( Secu_amb *sec, int nsec, BOOL log ) +{ + BOOL res=FALSE; + int i; + for (i=0; i=0) + { + olvlog(LOG_TODO,"olv_limp_t","Esta repe la secuencia %ld, en posiciones %ld, %ld ",sec[i].iamb, i, sec[sec[i].iamb].flags); + res=TRUE; + } + sec[sec[i].iamb].flags=i; + } + return res; +} +//************************************************************************************* +/** + * Escribe la info resultado de la planificación + */ +void Colv_limp_thr::pon_info_resul() +{ + char msg_[OLV_MAX_MSG_PROCE]; + char msg_aux[64]; + int i,h,m,s; + double tt; + int nsec=0; + + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb!=0) + nsec++; + } + + if(olv_limp->olv->modo_ejec==OLV_EJEC_SECT) + { + //si se ha ejecutado en modo cálculo de sectorización + if(olv_limp->calc_nsec>0) + { + //se ha pedido proponer número de sectores óptimo + sprintf_s(msg_,OLV_MAX_MSG_PROCE, + "Se ha calculado la sectorización para el número de sectores óptimo\ndada la conf. elegida, que es de %ld, de tiempos:\n", + nsec); + } + else + { + //se ha impuesto el número de sectores + sprintf_s(msg_,OLV_MAX_MSG_PROCE,"Se ha calculado la sectorización para %ld sectores, de tiempos:\n", + nsec); + } + } + else if(olv_limp->olv->modo_ejec==OLV_EJEC_PLAN) + { + sprintf_s(msg_,OLV_MAX_MSG_PROCE,"Se ha calculado la planificación para %ld sectores, de tiempos:\n", + nsec); + } + else if(olv_limp->olv->modo_ejec==OLV_EJEC_TODO) + { + sprintf_s(msg_,OLV_MAX_MSG_PROCE,"Resultados de todo el proceso para %ld sectores, de tiempos:\n", + nsec); + } + else + msg_[0]=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + continue; + tt=olv_limp->sec[i].cost_ac+olv_limp->t_desc; + dame_h_m_s(tt, &h, &m, &s); + sprintf_s(msg_aux,64,"Sector %ld: %02d:%02d:%02d h, %03d elementos\n",i+1,h,m,s,olv_limp->sec[i].namb); + strcat_s(msg_,OLV_MAX_MSG_PROCE,msg_aux); + } + pon_mi_msg(msg_); + pon_mi_progre(tarea,100); +} +//************************************************************************************* +/* + * Lanza los multi procesos para el cálculo de cost_amb + */ +BOOL Colv_limp_thr::lanza_tasks(int nthr_def/*=-1*/) +{ + int nn; + char comline[256]; + char app_path[MAX_PATH]; + char app_path_aux[MAX_PATH]; + BOOL ret=TRUE; + + if(nthr_def>0) + nn=nthr_def; + else + nn=n_subthr; + + comline[0]=0; + app_path[0]=0; + app_path_aux[0]=0; + + olv_limp->olv_tasks->get_dll_dir(app_path_aux); + if(!app_path_aux[0]) + return FALSE; + + char *pch=strrchr(app_path_aux,'\\'); + if(!pch) + return FALSE; + + *pch=0; + + sprintf(app_path,"%s\\%s\\%s",app_path_aux,TASKS_FOLDER_NAME,TASKS_APP_NAME); + + //Arranca los tasks + for(int i=0;iolv->olv_sock->ip, + TASKS_PORT, + i); + + if(!olv_limp->olv_tasks->lanza_app(app_path, comline)) + ret=FALSE; + } + + for(int i=nthr_def;iprog_subthr = 0; + + for(int i=0;iolv_tasks->inidirs(olv_limp->olv->paths.path_temp); + + olvlog(LOG_TODO,"olv_limp_t","Guardando matrices"); + + //lanza los threads + lanza_subthrs(OLV_LIMP_EV_GUARD_MATS_SUB); + + return TRUE; +} +//************************************************************************************* +/* + * Cada thread de los que guardan a disco la matriz de dist entre conjunciones y de ángulos + */ +void Colv_limp_thr::guarda_mats_sub(int ithr) +{ + int nconj,ic; + int n_ini, n_desp, n_fin, seg; + BOOL mal=FALSE; + Param_olv_limp_thr pp; + HeadCostConj hd; + HeadCostAng hda; + + //////////////// + pp.id_e=OLV_TAREA_GUARD_MAT;//manda de parámetro la tarea de la que es el progreso + nconj=olv_limp->conjs.n; + //las conjunciones que va a hacer + n_desp = (int)ceil(1.0*nconj/n_subthr); + n_ini=ithr*n_desp; + n_fin = min((ithr+1)*n_desp,nconj); + + memset(&hd,0,sizeof(HeadCostConj)); + memset(&hda,0,sizeof(HeadCostAng)); + //////////////// + + olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Guardando filas de matrices %04d a %04d", ithr,n_ini, n_fin); + + seg = GetTickCount(); + ///////////////////////////////////// + //bucle por cada conjunción de la carto + Cgarray bufer; + for(ic=n_ini; iccost_conj[ic].guarda(hd,ic,olv_limp->olv_tasks->path_cconj,TASKS_EXT_MAT,&bufer)) + { + mal=TRUE; + continue; + } + + if(olv_limp->ang_conj) + { + if(!olv_limp->ang_conj[ic].guarda(hda,ic,olv_limp->olv_tasks->path_ang, TASKS_EXT_MAT)) + { + mal=TRUE; + continue; + } + } + + //avisa de progreso + if(((ic-n_ini)%500==0) || ((ic-n_ini)==(n_desp-1))) + { + olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Guardando matrices, %ld de %ld", ithr, + (ic-n_ini+1),n_desp); + //avisa de progreso + prog_subthr=(1.0*(ic-n_ini+1)/n_desp);/// + thr_padre->encola(OLV_LIMP_EV_SUBTHR_PROG,&pp,FALSE); + } + } + if(mal) + goto va_mal; + +va_mal: + if(mal) + { + olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Error en guardado de matrices", ithr); + prog_subthr=-1;//para avisar al padre de que ha habido un error + } + else + { + olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Fin guardado matriz, %.3f seg", ithr, 1.0*(GetTickCount()-seg)/1000); + } + + thr_padre->encola(OLV_LIMP_EV_GUARD_MATS_FIN,NULL,FALSE); + +} +//************************************************************************************* +/* + * Cada thread de los que guardan a disco la matriz de dist entre conjunciones y de ángulos + */ +BOOL Colv_limp_thr::guarda_mats_fin() +{ + //////////////// + //para los threads + para_subthrs(); + + //guarda matriz de info aso + guarda_iaso(); + olvlog(LOG_TODO,"olv_limp_t","Guardada matriz de info aso"); + + //libera esta memoria que ya no le hace falta + olv_limp->tip_conj.clear(); + + olvlog(LOG_TODO,"olv_limp_t","FIN Guardado Matrices"); + return TRUE; +} +//************************************************************************************* +/* + * Guarda los ic de la info aso del ámbito ia + */ +BOOL Colv_limp_thr::guarda_iaso() +{ + HANDLE hfile = INVALID_HANDLE_VALUE; + int nb, i, ref_i; + HeadInfoAso hd; + + //crea archivo----------------------------------- + hfile = CreateFile(olv_limp->olv_tasks->file_iaso, GENERIC_WRITE | GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); + if (hfile == INVALID_HANDLE_VALUE) + { + i=GetLastError(); + return FALSE; + } + memset(&hd,0,sizeof(HeadInfoAso)); + hd.nint=olv_limp->n_amb*3; + //graba cabecera------------ + nb = sizeof(hd); + //calcula el nb + if (nb != _lwrite((int)hfile, (LPCCH)&hd, nb)) + { + goto va_mal; + } + + nb=sizeof(int); + //se embucla en los ámbitos guardando sus flags ic[0] e ic[1] + for(i=0;in_amb;i++) + { + ref_i=olv_limp->carto.get(i).entity()->ref; + if (nb != _lwrite((int)hfile, (LPCCH)&olv_limp->iaso[ref_i].inod[0], nb)) + break; + if (nb != _lwrite((int)hfile, (LPCCH)&olv_limp->iaso[ref_i].inod[1], nb)) + break; + if (nb != _lwrite((int)hfile, (LPCCH)&olv_limp->iaso[ref_i].flgs, nb)) + break; + } + if(in_amb) + goto va_mal; + + CloseHandle(hfile); + return TRUE; + +va_mal: + CloseHandle(hfile); + return FALSE; +} +//************************************************************************************* +void Colv_limp_thr::ini_infotask(int ntasks) +{ + InfoIniTask ii; + memset(&ii,0,sizeof(InfoIniTask)); + ii.KK = olv_limp->tipo_ambit; + ii.n = olv_limp->conjs.n; + ii.namb = olv_limp->n_amb; + ii.nthr=n_subthr; + ii.ntsks=ntasks; + ii.usa_angs = (olv_limp->ang_conj!=NULL); + ii.id_instal = olv_limp->nod_instal; + ii.id_planta = olv_limp->nod_plant; + strcpy_s(ii.path_temp,MAX_PATH,olv_limp->olv_tasks->path_temp); + strcpy_s(ii.path_cconj,MAX_PATH,olv_limp->olv_tasks->path_cconj); + strcpy_s(ii.path_costamb,MAX_PATH,olv_limp->olv_tasks->path_costamb); + strcpy_s(ii.path_ang,MAX_PATH,olv_limp->olv_tasks->path_ang); + strcpy_s(ii.file_iaso,MAX_PATH,olv_limp->olv_tasks->file_iaso); + strcpy_s(ii.ext,8,TASKS_EXT_MAT); + memcpy(&olv_limp->olv->infotask,&ii,sizeof(InfoIniTask)); +} +//************************************************************************************* +BOOL Colv_limp_thr::task_dj_escucha() +{ + //////////////////////////////////////////////// + //lanza las tasks + //ejecuta n veces OliviaTasks, cada una va a calcular una parte de la matriz de costes entre ambitos + //con sus correspondientes dijkstras y lo va a escribir en disco + //antes de eso, se han guardado en disco la matriz (o maps) de costes entre conjunciones y de ángulos entre conjunciones + //////////////////////////////////////////////// + + int ntasks=1; + pon_mi_progre(OLV_TAREA_MULTITASK, 0); + olvlog(LOG_TODO,"olv_limp_t","Comienza ejecución Multitask"); + ini_infotask(ntasks); + + //lanza la escucha + olv_limp->soc = new Csock_svThread(); + olv_limp->soc->escucha=olv_limp->olv_tasks; + + if(!olv_limp->soc->liseningThread(TASKS_PORT,olv_limp->olv->olv_sock->ip)) + { + goto mal; + } + + ////////////////////////////////////// + if(!lanza_tasks(ntasks)) + { + pon_mi_msg("Error al lanzar multitask para el cálculo de costes entre ámbitos"); + return FALSE; + } + + + return TRUE; + +mal: + olv_limp->soc->close(); + delete olv_limp->soc; + olv_limp->soc=NULL; + return FALSE; +} +//************************************************************************************* +BOOL Colv_limp_thr::task_dj_fin() +{ + //debe iniciar la matriz cost_amb y leerla lo que han rellenado los tasks, y combinarla + + return TRUE; +} +//************************************************************************************* +void Colv_limp_thr::borra_temp_files(BOOL todo/*=TRUE*/) +{ + Cdir_manager dm; + if(todo) + { + //borra los archivos de dijkstra + dm.borra_archivos(olv_limp->olv->paths.path_temp,EXT_ARCH_DIJ_DEFAULT); + } + //borra los archivos asociados al multitask + dm.borra_archivos(olv_limp->olv->paths.path_temp,TASKS_EXT_MAT,TRUE); + dm.borra_archivos(olv_limp->olv->paths.path_temp,TASKS_EXT_DIS,TRUE); +} +//************************************************************************************* +//************************************************************************************* +//************************************************************************************* +//************************************************************************************* +/** + * Thread para cálculo multiproceso de la planificación + */ +UINT th_planificacion(LPVOID pp) +{ + th_param_planif *p=(th_param_planif*)pp; + int id_th=p->id_th; + int id_curro=p->id_curro; + int ini, fin, i, j, entr, entr_m; + int mm[2]; + double d, dm; + p->id_th=-1; + while(!p->pirate) + { + if(id_curro==p->id_curro) + { + //no curro + Sleep(p->milis_sleep); + continue; + } + id_curro=p->id_curro; + //ha currar + switch(p->modo) + { + case (0)://cambio de un elemento en la ruta + i=p->namb/p->nth; + ini=max(i*id_th, 1); + if(id_th+1==p->nth) + fin=p->namb; + else + fin=ini+i; + i=-1; + dm=MAYUSCULO; + entr=0; + while(iniparam[0]) + { + + d=p->tl->dame_coste(p->sec, 0,p->namb-1, p->s, p->abs); + + } + else + d=p->tl->dame_coste_ex(p->sec,0,p->namb-1,p->s,p->param[0],ini, entr); + if(d=1 || (ini==p->param[0])) + { + ini++; + entr=0; + } + else + entr=1; + + } + p->dth[id_th].coste=dm; + p->dth[id_th].pos[0]=i; + p->dth[id_th].pos[1]=entr_m; + + break; + case (1)://permutaciones de elementos + i=Colv_geom::fact(p->param[1]-p->param[0]); + j=i/p->nth; + ini=max(i*id_th, 1); + if(id_th+1==p->nth) + fin=i; + else + fin=ini+j; + i=-1; + dm=MAYUSCULO; + while(initl->permuta(p->sec, p->param[0], p->param[1], ini, p->dth[id_th].sec)) + { + ini++; + continue; + } + d=p->tl->dame_coste(p->dth[id_th].sec, 0,p->namb-1, p->s, p->abs); + if(dtl->permuta(p->sec, p->param[0], p->param[1], i, p->dth[id_th].sec)) + { + p->dth[id_th].coste=MAYUSCULO; + } + else + p->dth[id_th].coste=dm; + p->dth[id_th].pos[0]=i; + break; + case (2)://cambio de un elemento en la ruta (cambiandolo de verdad) + //pilla un entorno de como mucho +-100 ambitos para las permu + //----------------------------------------------- + /*i=p->namb/p->nth; + ini=max(i*id_th, 1); + if(id_th+1==p->nth) + fin=p->namb; + else + fin=ini+i;*/ + mm[0]=max(p->param[0]-50,0); + mm[1]=min(mm[0]+101,p->namb); + i=(mm[1]-mm[0])/p->nth; + ini=mm[0]+max(i*id_th, 1); + if(id_th+1==p->nth) + fin=mm[1]; + else + fin=ini+i; + //----------------------------------------------- + + i=-1; + dm=MAYUSCULO; + entr=entr_m=0; + while(iniparam[0]) + { + d=p->tl->dame_coste(p->sec, 0,p->namb-1, p->s, p->abs); + + } + else + { + memcpy(p->dth[id_th].sec,p->sec, p->namb_t*sizeof(Secu_amb)); + p->tl->cambia_elem(p->dth[id_th].sec, p->param[0],ini, entr); + d=p->tl->dame_coste(p->dth[id_th].sec, 0,p->namb-1, p->s, p->abs); + } + if(d=1 || (ini==p->param[0])) + { + ini++; + entr=0; + } + else + entr=1; + + } + p->dth[id_th].coste=dm; + p->dth[id_th].pos[0]=i; + p->dth[id_th].pos[1]=entr_m; + + break; + default: + break; + } + p->dth[id_th].currando=FALSE; + } + //salida de thread------------------------- + p->dth[id_th].activo=FALSE; + lck_sum_atm(&p->nth,-1); + + return 0; +} +//************************************************************************************* +//************************************************************************************* +//************************************************************************************* +//************************************************************************************* +//************************************************************************************* +#endif \ No newline at end of file diff --git a/Olivia/olv_limp_thr.h b/Olivia/olv_limp_thr.h new file mode 100644 index 0000000..20743d3 --- /dev/null +++ b/Olivia/olv_limp_thr.h @@ -0,0 +1,303 @@ +#pragma once +#ifdef OLIVIA_COMPILA +#include "olv_thr.h" +#include "olv_limp_def.h" +//utiles +#include "OlvAsync_cola.h" +#include "CartoBaseElements.h" +#include "CartoBase.h" +#include "Fdbf.h" +#include "b_file.h" +#include "ManagerDbfGdataTable.h" + +/** +* @file olv_limp_thr.h +* Archivo de definiciones del thread de control de la utilidad de limpieza viaria del programa Olivia. +*/ + +class Colv_limp; +class Colv_csv; +class Colv_limp_thr; +class Colv_tasks; +struct Info_inw_dmin; +struct Info_conjs; +struct Info_sec; +struct Info_amb_sec; +struct Info_amb_arbol; +struct Info_rut; +struct Info_est_amb; +struct Djkt_nodo; +struct Secu_amb; +struct Info_planif; +struct th_param_planif; +struct Djkt_ang_ady; +struct HeadCostConj; +struct HeadCostAng; +/** + * Estructura de parámetros de comunicación con el thread de cálculo de limpieza + */ +typedef struct Param_olv_limp_thr +{ + int id_e; +}Param_olv_limp_thr; +//******************************************* +/** + * Clase extendida para rellenar los datos del dbf + */ +class AddColsDbf : public IAddColDbf +{ +public: + char *info; + + AddColsDbf(char *info) + { + this->info=info; + } + virtual void setData(int i, void *data) + { + if(data) + { + memcpy(data,(void*)&info[i*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR); + } + + }; +}; +//******************************************* +/** +* Clase del thread de control de la utilidad de limpieza viaria del programa Olivia.\n +* Contiene el grueso de cálculos, tanto de la parte de limpieza como de recogida de residuos, todos los algoritmos de\n +* sectorización y planificación, cálculo de costes, etc. +*/ +//****************************************************************************************************** +class Colv_limp_thr : public Colv_thr, public OlvAsync_cola +{ +public: + //************************************************************************************* + //Variables + enum Ev_olv_limp_thr /// *clase,Param_olv_limp_thr *e); + + //Apertura de los datos de partida + BOOL abre_datos(); + + //Rellena la info de los datos de partida + virtual BOOL rellena_datos(); + BOOL rellena_info_nw(); + BOOL rellena_info_amb(); + BOOL replica_peat(); + void mejora_barr_mix(); + void mejora_barr_mix_sub(int ithr); + BOOL mejora_barr_mix_fin(); + BOOL barr_mix_paralelas(CartoBaseInfoEntity ient1, CartoBaseInfoEntity ient2); + void copia_info_barr_mix(); + //Unión de ámbitos a la red navegable + BOOL une_amb_nw(int soloi=-1); + int is_dmin(double daux, Info_inw_dmin *inww); + BOOL busca_inw_dmin(int i_amb); + BOOL busca_inw_dmin_ejes(int i_amb); + void add_uniones_obj(int i_amb); + void comprueba_amb_lejos(int i_amb ); + void comprueba_aislados(Info_inw_dmin *inww); + BOOL comprueba_latelaridad(); + void compr_cortes_amb(); + void compr_cortes_amb_sub(int ithr); + BOOL compr_cortes_amb_sub_fin(); + //Generación de topología + BOOL replica_doble_sent(Info_inw_dmin *inww_ord); + BOOL topo_nw(); + static int compara_inww_amb (const void * a, const void * b); + void borra_rep(); + + //Métodos para multithread + virtual void lanza_subthrs(int tar, int nthr_def=-1); + void para_subthrs(); + + //Cálculo del coste entre conjunciones + BOOL calcula_cost_conj(); + BOOL add_conj(Info_conjs *conjs, double coor[3]); + BOOL cuida_memo_conj(Info_conjs *conjs); + BOOL busca_conjs(); + void calcula_cost_conj_sub(int ithr); + BOOL calcula_cost_conj_fin(); + void calcula_cost(int refent, float *cost, float *cost2); + //Cálculo de ángulos entre conjunciones + BOOL calcula_ang_conj(); + void calcula_ang_conj_sub(int ithr); + double dame_ang_conj(int ic, int i, int j); + BOOL calcula_ang_conj_fin(); + void revisa_calles_cortadas(); + + //Cálculo del coste entre ámbitos + void invierte_nodos(int nn, int KK,Secu_amb * ord_sec, BOOL *pirate); + BOOL calcula_cost_amb(); + BOOL inicia_cost_amb(); + BOOL calcula_cost_amb_fin(); + void calcula_cost_amb_sub(int ithr); + BOOL avisa_aislados(); + void prueba_costs(); + + //Sectorización + BOOL sectoriza(); + BOOL pide_memo_secto(); + + //Métodos auxiliares para sectorización + BOOL add_amb_sec(int i_amb, int namb, int i_sec, Info_sec *ss, Info_amb_sec *aa, Matrix2d &cost_amb, double cost_tot, int i_amb_p=-1); + void quita_amb_sec(int i_amb, int namb, int i_sec, Info_sec *ss, Info_amb_sec *aa, Matrix2d &cost_amb, int i_amb_p=-1); + BOOL sectoriza_1(); + double dame_desv_sec(int nsec, Info_sec *ss, BOOL porc =FALSE, double *absol=NULL); + BOOL sectoriza_2(double *cost_ac_); + double iguala_sectores3(int n_amb, int n_sec, Matrix2d &cost_amb, Info_sec *ss, Info_amb_sec *aa, Secu_amb * ord_sec=NULL, th_param_planif *thp=NULL); + double iguala_sectores4(int n_amb, int n_sec, Matrix2d &cost_amb, Info_sec *ss, Info_amb_sec *aa); + double iguala_sectores5(int iamb, int n_amb, int n_sec, Matrix2d &cost_amb, Info_sec *ss, Info_amb_sec *aa); + BOOL calcula_coste_sectores(Secu_amb * ord_sec,Info_sec *ss,int n_sec, th_param_planif *thp=NULL, BOOL loguear=FALSE ); + BOOL calcula_coste_1sec( Secu_amb * ord_sec, Info_sec *ss, th_param_planif *thp, BOOL loguear ); + int asigna_padres(int amb_central, int namb, Matrix2d &cost_amb, Info_sec *ss, Info_amb_sec *aa, int *buf, int nhijos_fron); + int busca_sec_cerca_amb(Info_amb_sec *aa,int iamb, int id_sec, int modo=0); + BOOL genera_sectores3(int iamb_extr, int n_amb, int n_sec, Matrix2d &cost_amb, Info_sec *ss, Info_amb_sec *aa); + BOOL genera_sectores(int iamb_extr, int n_amb, int n_sec, Matrix2d &cost_amb, Info_sec *ss, Info_amb_sec *aa); + double dame_dmed_amb_sec(int iamb, int isec); + double dame_dmed_amb(int iamb1, int iamb2); + BOOL genera_sectores_pro(int n_sec, Matrix2d &cost_amb, Info_sec *ss, Info_amb_sec *aa); + BOOL add_amb_sec_cost(int i_amb, int namb, int i_sec, Info_sec *ss, Info_amb_sec *aa, Matrix2d &cost_amb); + BYTE* guarda_estado(int namb,int n_sec, Info_amb_sec *aa, Info_sec *ss,BYTE *buf ); + BOOL pon_estado(int namb,int n_sec, Info_amb_sec *aa, Info_sec *ss, Matrix2d &cost_amb, BYTE *st ); + int* ordena_sec(int n_sec, Info_sec *ss, int *buf);//ordena sectores de mayor a menor coste + int recorre_hijos(int iamb, int namb, Info_amb_sec *aa, int *iamb_r, int namb_r, Matrix2d &cost_amb, double *cost, BOOL inicia=TRUE); + BOOL actualiza_costes(int namb,int n_sec, Info_amb_sec *aa, Info_sec *ss, Matrix2d &cost_amb); + static int compara_dist_cerc (const void * a, const void * b); + + //Lee secto + BOOL lee_secto(); + + //Calcula el número de sectores + BOOL calcula_n_sec(); + virtual double dame_cost_jornada(); + double calcula_cost_1sec_total(int n_amb, Info_sec *ss, Djkt_ang_ady *ang_conj); + + //Planificación + BOOL planifica(); + virtual void planifica_sub_1(int ithr, Matrix2d &cost_amb); + BOOL planifica_fin(); + + //Métodos para guardado post-planificación + BOOL genera_planif(int is, double cost_sec, int nsecu, int *secu, int tip_plan); + BOOL genera_planif_aux(int is, Info_sec *ss, Info_planif *pp, int nsecu, int *secu, int tip_plan); + BOOL genera_planif_instala(int is, int nvaciados, int ini, int fin, int *secu, int tip_viaje); + BOOL guarda_shp_rut_ctrl(); + BOOL genera_list_rut_ctrl(); + virtual void quita_t_ult_desc(int s, double *t); + virtual BOOL genera_list_fila_vaci(Colv_csv *cc, char *fila0,int ielem, int s, int ii, double tt, double *t0,BOOL is_fin); + BOOL guarda_dbf_sector(int modo); + virtual BOOL gen_guard_subtramos(); + BOOL genera_rut_aux(Info_planif *pp, int is, BOOL is_insta, int ie_ini, int ie_fin); + BOOL genera_rut_ctrl(int ns, Info_planif *planif, BOOL tramos); + + //Métodos auxiliares para Planificación + short dame_planif_iamb_ini(Info_sec *s,Matrix2d &cost_amb, short *ent=NULL); + Secu_amb * planifica_sect(Info_sec *s, Djkt_ang_ady *ang_conj, int npermu); + BOOL busca_cercano(Info_sec *s, Secu_amb *sec, int isec, BOOL ind_abs=FALSE); + virtual double dame_coste(Secu_amb * sec, int ini, int fin, Info_sec *s, BOOL ind_abs=FALSE); + BOOL permuta(Secu_amb * sec, int ini, int fin, int p, Secu_amb * sec_out); + double dame_coste_ex( Secu_amb * sec , int ini, int fin, Info_sec *s, int pos_old, int pos_new, int entr ); + void cambia_elem(Secu_amb * sec,int pos_old, int pos_new, int entr); + BOOL esta_repe( Secu_amb *sec, int nsec, BOOL log=FALSE ); + void pon_info_resul(); + double dame_mima(int nsec, Info_sec *ss, double *mini=NULL); + double dame_dif_mima(int nsec, Info_sec *ss); + BOOL rellena_amb_cercanos_por_carretera(int namb, Info_amb_sec *aa, Secu_amb * ord_sec); + double dis_min_amb(int ids[2], int id_nod_ini, Secu_amb * ord_sec, BOOL res_nod, int iamb); + virtual void pon_ptos_ctrl(Info_planif *pp, int npt_ctrl, double cost_ctrl); + + ///////////////////////////// + virtual BOOL pon_nodos_planta(double pt[3]); + virtual BOOL busca_conjs_planta(double pt[3], int *nod); + virtual BOOL calcula_cost_plant(); + void dame_h_m_s(double tt, int *h, int *m, int *s); + virtual BOOL guarda_cols_ruta(char *path_shp); + BOOL guarda_cols_ctrl(char *path_shp); + virtual BOOL guarda_cols_insta(char *path_shp); + virtual void pon_t_desp(Info_sec *s, Secu_amb *sec); + virtual BOOL comprueba_descarg(int iamb); + virtual void dame_observ_cont(int iamb,char *observ); + BOOL quita_islas(int namb, Info_amb_sec *aa, Secu_amb * ord_sec); + + //Guardado de matrices + BOOL guarda_mats(); + void guarda_mats_sub(int ithr); + BOOL guarda_mats_fin(); + BOOL guarda_iaso(); + + //Cálculo en tasks de costes entre ámbitos + BOOL lanza_tasks(int nthr_def=-1); + BOOL task_dj_escucha(); + BOOL task_dj_fin(); + void borra_temp_files(BOOL todo=TRUE); + + //Para los viajes + void cuenta_tramos(); + virtual void rellena_tramos(); + BOOL combina_rut_insta(); + virtual int rellena_insta_tramos(); + virtual BOOL guarda_cols_ruta_tram(char *path_shp); + void ini_infotask(int ntasks); +}; +#endif \ No newline at end of file diff --git a/Olivia/olv_limp_thr_old.cpp b/Olivia/olv_limp_thr_old.cpp new file mode 100644 index 0000000..57b2d84 --- /dev/null +++ b/Olivia/olv_limp_thr_old.cpp @@ -0,0 +1,10369 @@ +#include "stdafx.h" + +#ifdef OLIVIA_COMPILA +//olivia +#include "olv_limp_thr.h" +#include "olv_thr.h" +#include "olv_limp.h" +#include "olv_shp.h" +#include "olv_geofoto.h" +#include "olv.h" +#include "olv_geom.h" +#include "olv_csv.h" +//geofoto +#include "varios.h" +#include "wvarios.h" +#include "gdiplus.h" +#include "obgeo.h" +#include "dbf.h" +#include "vector.h" +#include "nivelint.h" +#include "Geomet.h" +//igt_base +#include "igt_lock.h" +#include "vector.h" +#include "value.h" +#include +#include "olv_tasks.h" +#include "olv_tasks_def.h" +#include "olv_sock.h" +#include "dir_manager.h" + +UINT th_planificacion(LPVOID pp); +/** +* @file olv_limp_thr.cpp +* Archivo de implementaciones del thread de control de la utilidad de limpieza viaria del programa Olivia. +*/ + +Colv_limp_thr::Colv_limp_thr(Colv_limp *olv_limp) : Colv_thr(olv_limp->olv) +{ + this->olv_limp = olv_limp; + thr_padre=NULL; + n_subthr_fin=0; + pirate=FALSE; + fin_permu=FALSE; + //los subthreads + n_subthr=Colv_geom::dame_n_nucleos(); //lanza un thread por procesador + subthrs = (Colv_limp_thr **)malloc(n_subthr*sizeof(Colv_limp_thr *)); + for(int i=0;i *clase,Param_olv_limp_thr *e) + +{ + BOOL bien=TRUE; + + Colv_limp_thr *this_i=static_cast(clase); + switch (evento) + { + case OLV_LIMP_EV_ABRE_DAT: + { + bien=this_i->abre_datos(); + if(bien && (this_i->olv->modo_ejecpirate)//sigue + this_i->encola(OLV_LIMP_EV_RELL_DAT,NULL,FALSE); + break; + } + case OLV_LIMP_EV_RELL_DAT: + { + bien=this_i->rellena_datos(); + if(bien && (this_i->olv->modo_ejecpirate)//sigue + { + if(!this_i->olv->olv_limp->barr_mix) + this_i->encola(OLV_LIMP_EV_UNE_AMB_NW,NULL,FALSE); + else + this_i->encola(OLV_LIMP_EV_BARRMIX,NULL,FALSE); + } + break; + } + case OLV_LIMP_EV_BARRMIX: + { + //esta tarea lanza varios subthreads para realizar las comprobaciones del barrido mixto + //y estos cuando acaban le encolan al padre (el que los ha lanzado) + //la tarea de comprueba_barr_mixto_fin + this_i->mejora_barr_mix(); + break; + } + case OLV_LIMP_EV_BARRMIX_SUB: + { + //aquí entran los subthreads para hacer las comprobaciones del barrido mixto + //encolan al padre la tarea de fin + int ithr; + if(e!=NULL) + ithr=e->id_e; + this_i->mejora_barr_mix_sub(ithr); + break; + } + case OLV_LIMP_EV_BARRMIX_FIN: + { + //aquí entra el padre cuando van acabando los subthreads + //si han terminado todos encola la siguiente tarea + + this_i->n_subthr_fin++; + if(this_i->n_subthr_fin==this_i->n_subthr) + { + this_i->n_subthr_fin=0; + bien=this_i->mejora_barr_mix_fin(); + if(bien && (this_i->olv->modo_ejecpirate)//sigue + { + this_i->encola(OLV_LIMP_EV_UNE_AMB_NW,NULL,FALSE); + } + } + break; + } + case OLV_LIMP_EV_UNE_AMB_NW: + { + int soloi=-1; + bien=this_i->une_amb_nw(soloi); + if(bien && (this_i->olv->modo_ejecpirate)//sigue + this_i->encola(OLV_LIMP_EV_TOPO_NW,NULL,FALSE); + break; + } + case OLV_LIMP_EV_TOPO_NW: + { + bien=this_i->topo_nw(); + if(bien && (this_i->olv->modo_ejecpirate)//sigue + this_i->encola(OLV_LIMP_EV_COST_CONJ,NULL,FALSE); + break; + } + case OLV_LIMP_EV_COST_CONJ: + { + //esta tarea lanza varios subthreads para realizar los cálculos + //de costes entre conjunciones (les encola la tarea dist_conj_sub), + //y estos cuando acaban le encolan al padre (el que los ha lanzado) + //la tarea de dist_conj_fin + bien=this_i->calcula_cost_conj(); + break; + } + case OLV_LIMP_EV_COST_CONJ_SUB: + { + //aquí entran los subthreads para hacer los cálculos de distancia, cuando acaban + //encolan al padre la tarea de fin + int ithr; + if(e!=NULL) + ithr=e->id_e; + this_i->calcula_cost_conj_sub(ithr); + break; + } + case OLV_LIMP_EV_COST_CONJ_FIN: + { + //aquí entra el padre cuando van acabando los subthreads + //si han terminado todos encola la siguiente tarea + + this_i->n_subthr_fin++; + if(this_i->n_subthr_fin==this_i->n_subthr) + { + this_i->n_subthr_fin=0; + bien=this_i->calcula_cost_conj_fin(); + if(bien && (this_i->olv->modo_ejecpirate)//sigue + { + if(this_i->olv_limp->res_circ!=OLV_RES_NO) + this_i->encola(OLV_LIMP_EV_ANG_CONJ,NULL,FALSE); + else if(this_i->olv_limp->olv->modo_multitask) + this_i->encola(OLV_LIMP_EV_GUARD_MATS,NULL,FALSE); + else + this_i->encola(OLV_LIMP_EV_COST_AMB,NULL,FALSE); + } + } + break; + } + case OLV_LIMP_EV_ANG_CONJ: + { + //esta tarea lanza varios subthreads para realizar los cálculos + //de ángulos entre conjunciones (les encola la tarea ang_conj_sub), + //y estos cuando acaban le encolan al padre (el que los ha lanzado) + //la tarea de ang_conj_fin + bien=this_i->calcula_ang_conj(); + break; + } + case OLV_LIMP_EV_ANG_CONJ_SUB: + { + //aquí entran los subthreads para hacer los cálculos de ángulos, cuando acaban + //encolan al padre la tarea de fin + int ithr; + if(e!=NULL) + ithr=e->id_e; + this_i->calcula_ang_conj_sub(ithr); + break; + } + case OLV_LIMP_EV_ANG_CONJ_FIN: + { + //aquí entra el padre cuando van acabando los subthreads + //si han terminado todos encola la siguiente tarea + this_i->n_subthr_fin++; + if(this_i->n_subthr_fin==this_i->n_subthr) + { + this_i->n_subthr_fin=0; + bien=this_i->calcula_ang_conj_fin(); + if(bien && this_i->olv_limp->olv->modo_multitask && !this_i->pirate) + this_i->encola(OLV_LIMP_EV_GUARD_MATS,NULL,FALSE); + else if(bien && (this_i->olv->modo_ejecpirate)//sigue + this_i->encola(OLV_LIMP_EV_COST_AMB,NULL,FALSE); + } + break; + } + case OLV_LIMP_EV_GUARD_MATS: + { + bien=this_i->guarda_mats(); + break; + } + case OLV_LIMP_EV_GUARD_MATS_SUB: + { + int ithr; + if(e!=NULL) + ithr=e->id_e; + this_i->guarda_mats_sub(ithr); + break; + } + case OLV_LIMP_EV_GUARD_MATS_FIN: + { + //aquí entra el padre cuando van acabando los subthreads + //si han terminado todos encola la siguiente tarea + this_i->n_subthr_fin++; + int i; + if(this_i->n_subthr_fin==this_i->n_subthr) + { + this_i->n_subthr_fin=0; + for(i=0;in_subthr;i++) + if(this_i->subthrs[i]->prog_subthr<0) + break; + if(in_subthr) + { + bien=FALSE; + this_i->pon_mi_msg("Errores al guardar matrices de costes"); + break; + } + bien=this_i->guarda_mats_fin(); + if(bien && (this_i->olv->modo_ejecpirate)//sigue + this_i->encola(OLV_LIMP_EV_TASK_ESCUCHA,NULL,FALSE); + } + break; + } + case OLV_LIMP_EV_TASK_ESCUCHA: + { + bien=this_i->task_dj_escucha(); + break; + } + case OLV_LIMP_EV_TASK_FIN: + { + this_i->n_subthr_fin++; + if((e!=NULL) && e->id_e<0)//ha ido mal + { + if(e->id_e==-1) + this_i->subthrs[this_i->n_subthr_fin-1]->prog_subthr=-1; + else if(e->id_e==-2) + { + bien=FALSE; + this_i->pon_mi_msg("Errores en cálculo multitask, no ha habido conexión"); + break; + } + } + int i; + if(this_i->n_subthr_fin==this_i->n_subthr) + { + this_i->n_subthr_fin=0; + for(i=0;in_subthr;i++) + if(this_i->subthrs[i]->prog_subthr<0) + break; + if(in_subthr) + { + bien=FALSE; + this_i->pon_mi_msg("Errores en cálculo multitask"); + break; + } + this_i->task_dj_fin(); + if(bien && (this_i->olv->modo_ejecpirate)//sigue + this_i->encola(OLV_LIMP_EV_COST_AMB,NULL,FALSE); + } + break; + } + case OLV_LIMP_EV_COST_AMB: + { + //esta tarea lanza varios subthreads para realizar los cálculos + //de costes(les encola la tarea dist_amb_sub), + //y estos cuando acaban le encolan al padre (el que los ha lanzado) + //la tarea de dist_amb_fin + bien=this_i->calcula_cost_amb(); + break; + } + case OLV_LIMP_EV_COST_AMB_SUB: + { + //aquí entran los subthreads para hacer los cálculos de costes entre ámbitos, cuando acaban + //encolan al padre la tarea de fin + int ithr; + if(e!=NULL) + ithr=e->id_e; + this_i->calcula_cost_amb_sub(ithr); + break; + } + case OLV_LIMP_EV_COST_AMB_FIN: + { + //aquí entra el padre cuando van acabando los subthreads + //si han terminado todos encola la siguiente tarea + int i; + this_i->n_subthr_fin++; + if(this_i->n_subthr_fin==this_i->n_subthr) + { + this_i->n_subthr_fin=0; + for(i=0;in_subthr;i++) + if(this_i->subthrs[i]->prog_subthr<0) + break; + if(in_subthr) + { + bien=FALSE; + this_i->pon_mi_msg("Errores al calcular coste entre ámbitos"); + break; + } + bien=this_i->calcula_cost_amb_fin(); + if(bien && (this_i->olv->modo_ejecpirate)//sigue + { + if(this_i->olv->modo_ejec==OLV_EJEC_PLAN) //lee info de sectorización y va a planif + this_i->encola(OLV_LIMP_EV_LEE_SECTO,NULL,FALSE); + else //sectoriza + { + if(this_i->olv_limp->nsec==0)//hay que calcular el número de sectores + this_i->encola(OLV_LIMP_EV_CALC_NSEC,NULL,FALSE); + else + { + if(this_i->olv_limp->nsec<0) + { + this_i->olv_limp->calc_nsec=this_i->dame_cost_jornada();//indica que se tiene que ajustar a la jornada + this_i->olv_limp->nsec=this_i->olv_limp->nsec_act=this_i->olv_limp->nsec*(-1); + } + this_i->encola(OLV_LIMP_EV_SECTORIZA,NULL,FALSE); + } + } + } + + } + break; + } + case OLV_LIMP_EV_CALC_NSEC: + { + bien=this_i->calcula_n_sec(); + if(bien && (this_i->olv->modo_ejecpirate)//sigue + { + this_i->encola(OLV_LIMP_EV_SECTORIZA,NULL,FALSE); + } + break; + } + case OLV_LIMP_EV_SECTORIZA: + { + bien=this_i->sectoriza(); + if(bien && (this_i->olv->modo_ejecpirate)//sigue + { + this_i->pon_info_resul(); + if(this_i->olv->modo_ejec>=OLV_EJEC_DEBUG_SIGUE) + this_i->encola(OLV_LIMP_EV_PLANIFICA,NULL,FALSE); + else + { + this_i->borra_temp_files(); + this_i->pon_mi_progre(OLV_TAREA_FIN_SEC,0); + } + } + break; + } + case OLV_LIMP_EV_LEE_SECTO: + { + bien=this_i->lee_secto(); + if(bien && !this_i->pirate)//sigue + { + this_i->encola(OLV_LIMP_EV_PLANIFICA,NULL,FALSE); + } + break; + } + case OLV_LIMP_EV_PLANIFICA: + { + bien=this_i->planifica(); + break; + } + case OLV_LIMP_EV_PLANIFICA_SUB: + { + //aquí entran los subthreads para hacer los cálculos de planificación, cuando acaban + //encolan al padre la tarea de fin + int ithr; + if(e!=NULL) + ithr=e->id_e; + this_i->planifica_sub_1(ithr, this_i->olv_limp->cost_amb); + break; + } + case OLV_LIMP_EV_PLANIFICA_FIN: + { + //aquí entra el padre cuando van acabando los subthreads + //si han terminado todos encola la siguiente tarea + int i; + this_i->n_subthr_fin++; + if(this_i->n_subthr_fin==this_i->n_subthr) + { + this_i->n_subthr_fin=0; + for(i=0;in_subthr;i++) + { + if(this_i->subthrs[i]->prog_subthr<0) + { + break; + } + } + if(in_subthr) + { + bien=FALSE; + this_i->pon_mi_msg("Errores al planificar th %ld",i); + break; + } + bien = this_i->planifica_fin(); + //pone progreso como que ha terminado + if(bien) + { + this_i->pon_info_resul(); + this_i->borra_temp_files(); + this_i->pon_mi_progre(OLV_TAREA_FIN_PLANIF,0); + } + } + break; + } + case OLV_LIMP_EV_SUBTHR_PROG: + { + //aquí entra el padre porque le encolan los subthreads para avisarle del progreso + double pro=0; + for(int i=0;in_subthr;i++) + pro+=this_i->subthrs[i]->prog_subthr; + pro=OliviaDef::GeneralDef::ProgrMax*pro/this_i->n_subthr; + if(e!=NULL) + { + this_i->pon_mi_progre(e->id_e,(int)pro); + } + break; + } + } + if(!bien) + { + this_i->pon_mi_progre(OLV_TAREA_FIN_NOK,0); +#ifndef _DEBUG + this_i->borra_temp_files(); +#endif + } +} +//************************************************************************************* +void Colv_limp_thr::termina_th() +{ + if(tarea==OLV_TAREA_PERMU && !fin_permu) + { + fin_permu=TRUE; + return; + } + if(fin_permu) + fin_permu=FALSE; + pirate=TRUE; + para_subthrs(); + termina(); + wgeolog(LOG_TODO,"olv_limp_t","Thread de limpieza limp_thr finalizado"); +} +//************************************************************************************* +/** + * Abre los datos de cartografía + */ +BOOL Colv_limp_thr::abre_datos() +{ + int icla,ii,KK,flx,flx_s; + + wgeolog(LOG_TODO,"olv_limp_t","Abriendo datos"); + pon_mi_progre(OLV_TAREA_IMP, 0); + pon_mi_msg(""); + err_str[0]=0; + + //OJO siempre primero van los ámbitos y luego la red navegable a continuación, + //si se cambia, tener en cuenta en los cálculos del thread + + //abre la cartografía con los datos + KK=olv_limp->tipo_ambit; + if(KK==OLV_AMB_LIN) + icla=OLV_ICLA_LIN_AMB; + else if(KK==OLV_AMB_PUN) + icla=OLV_ICLA_PUN_AMB; + if(!olv_limp->olv->olv_sh->abre_shp(olv_limp->olv->paths.path_data,icla,MODO_SHP_MEMO)) + { + pon_mi_msg("Error en la importación del archivo\n%s",olv_limp->olv->paths.path_data); + return FALSE; + } + olv_limp->n_amb=olv_limp->olv->olv_ob->vect.nobj; + olv_limp->n_ini_nw=olv_limp->n_amb; + + if(olv_limp->n_amb>=USHRT_MAX) + { + pon_mi_msg("Número de ámbitos (%ld) mayor que el permitido (%ld)\n",olv_limp->n_amb,USHRT_MAX); + return FALSE; + } + + //abre la red navegable a continuación + if(!olv_limp->olv->olv_sh->abre_shp(olv_limp->olv->paths.path_nw, OLV_ICLA_LIN_NW,MODO_SHP_MEMO)) + { + pon_mi_msg("Error en la importación del archivo\n%s",olv_limp->olv->paths.path_nw); + return FALSE; + } + olv_limp->n_nw=olv_limp->olv->olv_ob->vect.nobj-olv_limp->n_amb; + + ////////////////////////////////////////////////////////////////////////// + //inicializa el array de información asociada + //si es tipo puntual, se almacenan 2 infos asociadas, la del propio puntual + //y para cuando se añada el segmento + //si es tipo lineal, se almacenan 3 infos asociadas, porque se necesita conservar la del + //lineal como tal, y aparte se dan dos, una para cada segmento de unión. + olv_limp->ias = (Info_aso *)malloc((olv_limp->n_nw+olv_limp->n_amb*(KK+1))*sizeof(Info_aso)); + if(!olv_limp->ias) + { + pon_mi_msg("Error, sin memoria para la información asociada"); + return FALSE; + } + memset(olv_limp->ias,0,(olv_limp->n_nw+olv_limp->n_amb*(KK+1))*sizeof(Info_aso)); + olv_limp->n_ini_amb_iai=olv_limp->n_ini_nw+olv_limp->n_nw;//los segmentos del inicio empiezan donde acaba el nw + if(KK==OLV_AMB_LIN) + olv_limp->n_ini_amb_iaf=olv_limp->n_ini_amb_iai+olv_limp->n_amb;//los segmentos del final empiezan donde acaba el anterior + //si es tipo eje de calle lo pone en el flag + if((olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoMh_eje) || + (olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoM2h_eje)) + { + flx=OLV_LIMP_FLG_EJE; + flx_s=OLV_LIMP_FLG_EJE_SEG; + } + else + { + flx=0; + flx_s=0; + } + //inicializa los índices a los shapes originales en la información asociada + //OJO toma por seguro que en el ob se ha abierto primero los ámbitos y luego la red nw + for(ii=0; iin_amb;ii++) + { + olv_limp->ias[ii].flgs = OLV_LIMP_FLG_AMB|flx; + olv_limp->ias[ii].ishp=ii; + (*olv_limp->olv->olv_ob->objt)[ii].ia=ii; + if(KK==OLV_AMB_LIN) + { + //ahora la ia de sus segmentos, pero no lo apunta porque no están en el ob todavía + olv_limp->ias[ii+olv_limp->n_ini_amb_iai].flgs = OLV_LIMP_FLG_SEG_LIN | flx_s; + olv_limp->ias[ii+olv_limp->n_ini_amb_iai].ishp=ii; + olv_limp->ias[ii+olv_limp->n_ini_amb_iaf].flgs = OLV_LIMP_FLG_SEG_LIN | OLV_LIMP_FLG_FIN | flx_s; + olv_limp->ias[ii+olv_limp->n_ini_amb_iaf].ishp=ii; + } + else if(KK==OLV_AMB_PUN) + { + olv_limp->ias[ii+olv_limp->n_ini_amb_iai].flgs = OLV_LIMP_FLG_SEG_PUN; + olv_limp->ias[ii+olv_limp->n_ini_amb_iai].ishp=ii; + } + } + for(ii=olv_limp->n_ini_nw; iin_ini_nw+olv_limp->n_nw;ii++) + { + olv_limp->ias[ii].ishp=ii-KK*olv_limp->n_ini_nw; + (*olv_limp->olv->olv_ob->objt)[ii].ia=ii; + } + + ////////////////////////////////////////////////////////////////////////// + //rellena la información asociada: sentidos de circulación, velocidad de la vía, ancho de acera... + if(!rellena_info_nw()) + { + pon_mi_msg("Error al leer info asociada a red navegable: %s", err_str); + return FALSE; + } + + //////////////////// + + wgeolog(LOG_TODO,"olv_limp_t","Finaliza Abrir datos con éxito"); + + return TRUE; +} +//************************************************************************************* +/** + * Rellena la información asociada de la red navegable y los datos de limpieza + */ +BOOL Colv_limp_thr::rellena_datos() +{ + if(!rellena_info_amb()) + { + pon_mi_msg("Error al leer info asociada a ámbitos: %s", err_str); + return FALSE; + } + + wgeolog(LOG_TODO,"olv_limp_t","Finaliza Rellena datos con éxito"); + + return TRUE; +} +//************************************************************************************* +/** + * Comrpueba las entidades para adecuarlas al barrido mixto + */ +void Colv_limp_thr::mejora_barr_mix() +{ + int nthr=n_subthr; + wgeolog(LOG_TODO,"olv_limp_t","Comienza las comprobaciones para el barrido mixto"); + lanza_subthrs(OLV_LIMP_EV_BARRMIX_SUB,nthr); + + //fuerza fin para que avance olivia + for(int i=nthr;iprog_subthr = 0; + } + for(int i=0;in_amb)/n_subthr); + na_ini=ithr*na_desp; + na_fin = min((ithr+1)*na_desp,olv_limp->n_amb); + ob=thr_padre->olv_limp->olv->olv_ob; + wgeolog(LOG_TODO,"olv_limp_t","Subthr %ld, Comprueba Barr Mix Ambs %04d a %04d", ithr, na_ini, na_fin); + seg = GetTickCount(); + + //Bucle en los ámbitos + for(i=na_ini;iolv->olv_ob->objt)[i].tipo != OBJ_LINEAL) + continue;//comprueba clases + + if(olv_limp->ias[i].info3!=OLV_AMBLIN_ACE) + continue; + + //apunta el array de puntos de la acera + il_ace=(*olv_limp->olv->olv_ob->objt)[i].indx; + npt_ace = (*olv_limp->olv->olv_ob->lial)[il_ace].n; + i_ace=(*olv_limp->olv->olv_ob->lial)[il_ace].indx; + pt_ace = &(*olv_limp->olv->olv_ob->ptos)[i_ace]; + + //Se recorre las aceras + //Por cada acera, se recorre el resto de entidades, y las que sean + //bordillo o banda de aparcamiento, comprueba si es paralela + for(j=0;jn_amb && !pirate; j++) + { + if(((*olv_limp->olv->olv_ob->objt)[j].tipo != OBJ_LINEAL) || (j==i) || (olv_limp->ias[j].info3>=OLV_AMBLIN_ACE)) + continue;//comprueba clases + + //apunta al array de puntos de esta otra entidad, que puede ser bordillo libre o aparcamiento + il_otro=(*olv_limp->olv->olv_ob->objt)[j].indx; + npt_otro = (*olv_limp->olv->olv_ob->lial)[il_otro].n; + i_otro=(*olv_limp->olv->olv_ob->lial)[il_otro].indx; + pt_otro = &(*olv_limp->olv->olv_ob->ptos)[i_otro]; + + //recorre ambas rectas a la par + //para ello, primero mira cuál es la más larga + lon_ace=long_linea((double (*)[][3]) pt_ace,npt_ace,NULL,NULL,NULL,NULL); + lon_otro=long_linea((double (*)[][3]) pt_otro,npt_otro,NULL,NULL,NULL,NULL); + + //wgeolog(LOG_TODO,"olv_limp_t","Subthr %ld, Comprueba %04d a %04d-----------------", ithr, i,j); + + //parte de la más corta, y avanza en pasos del PORC_AVANCE% de su longitud + if(lon_aceias[i].flgs & OLV_LIMP_FLG_AMB_NO)) + { + olv_limp->ias[i].flgs=olv_limp->ias[i].flgs | OLV_LIMP_FLG_AMB_NO; + } + olv_limp->ias[i].info0=j; + + //suma los anchos de forma ponderada + pond=lon_ace/lon_otro; + if(pond>1) + pond=1; //cuando la acera es más grande, se suma el ancho de la acera, no se amplia + + //cuando la acera es más pequeña, puede que en ese bordillo o banda de aparcamiento + //haya otra acera en paralelo, así que se le sumará después su ancho también, + //de forma que la suma total sea la ponderación de los anchos + olv_limp->ias[j].info1 += olv_limp->ias[i].info1*pond; + } + + //avisa de progreso + if(((i-na_ini)%100==0) || ((i-na_ini)==(na_desp-1))) + { + wgeolog(LOG_TODO,"olv_limp_t","Subthr %ld, Comprobando Barrido Mixto ambs %ld de %ld", ithr, + (i-na_ini+1),na_desp); + } + + } + + if(mal) + { + wgeolog(LOG_TODO,"olv_limp_t","Subthr %ld, Error en mejoras Barrido mixto", ithr); + prog_subthr=-1;//para avisar al padre de que ha habido un error + } + else + { + wgeolog(LOG_TODO,"olv_limp_t","Subthr %ld, Fin mejoras Barrido mixto, %.3f seg", ithr, 1.0*(GetTickCount()-seg)/1000); + } + thr_padre->encola(OLV_LIMP_EV_BARRMIX_FIN,NULL,FALSE); + +} +//************************************************************************************* +/** + * Devuelve true si hay que descartar que sean paralelas porque están muy lejos + * Para ello, hace la recta que une el punto inicial de cada una de las dos rectas y + * calcula el ángulo que forma esa recta con la primera. + * La distancia entre las dos rectas será la longitud de ese segmento por el seno del ángulo + * Si esa distancia es mayor que dminmax se descarta + */ +BOOL Colv_limp_thr::barr_mix_desc(int npt1, double (*pt1)[3], int npt2, double (*pt2)[3]) +{ + short ip; + float lamb; + double dist; + + dist=Colv_geom::dist_pto_poli((double (*)[3])pt1,(double (*)[][3])pt2,npt2,&ip, &lamb); + if(dist<=OLV_BARRMIX_DMAX_DESC)//está cerca, no se descarta + return FALSE; + + return TRUE; + + double pt_aux[2][3], laux,ang; + + //hace la recta que une el punto inicial de cada una de las dos rectas + memcpy(pt_aux[0],pt1,3*sizeof(double)); + memcpy(pt_aux[1],pt2,3*sizeof(double)); + laux=long_linea((double (*)[][3]) pt_aux,2,NULL,NULL,NULL,NULL); + + //calcula el ángulo que forma esa recta con la primera + ang=Colv_geom::ang_vect_ptos((double (*)[][3])pt1, (double (*)[][3])pt_aux); + laux=laux*sin(ang); + + //wgeolog(LOG_TODO,"olv_limp_t","laux=%.2f, ang=%.2f", laux,ang*180/OLV_PI); + + if(laux<=OLV_BARRMIX_DMAX_DESC)//está cerca, no se descarta + return FALSE; + + return TRUE; +} +//************************************************************************************* +/** + * Avanza desde el primer punto de pt1 y el más próximo en pt2, + * en pasos de l_avan, midiendo la distancia entre las dos rectas + * devuelve si son paralelas o no en función de la dmedia y la desv + */ +BOOL Colv_limp_thr::barr_mix_paralelas(int npt1, double (*pt1)[3], double long1, int npt2, double (*pt2)[3]) +{ + const double PORC_AVANCE = 0.2; //avanza en pasos del porc % de la longitud de la línea pequeña + //////////////////////////////////// + double l_avan, pt[3], l_parc, dmed, desv; + int i; + short ip; + float lamb; + std::vector dmin; + + //comprueba si las puede descartar porque estén muy lejos + if(barr_mix_desc(npt1, pt1, npt2, pt2)) + return FALSE; + + l_avan=PORC_AVANCE*long1; + + i=0; + l_parc=0; + while(l_parcOLV_BARRMIX_DMED_MAX || desv>OLV_BARRMIX_DESV_MAX) + return FALSE; + + //wgeolog(LOG_TODO,"olv_limp_t","PARALELAS"); + + return TRUE; +} +//************************************************************************************* +/** + * Copia en las aceras que no se han usado para sectorizar porque se han asignado a bordillos o + * bandas de aparcamiento, el mismo sector que el bordillo que tienen asignado + * modo 0 secto, modo 1 planif + */ +void Colv_limp_thr::copia_info_barr_mix() +{ + for(int i=0;in_amb;i++) + { + if(!(olv_limp->ias[i].flgs & OLV_LIMP_FLG_AMB_NO) || olv_limp->ias[i].info0<0) + continue; + + olv_limp->amb_sec[i].sec=olv_limp->amb_sec[olv_limp->ias[i].info0].sec; + olv_limp->amb_sec[i].iseq=olv_limp->amb_sec[olv_limp->ias[i].info0].iseq; + } +} +//************************************************************************************* +/** + * Rellena la información de sentidos de circulación y velocidad de las vías + * en la tabla de información asociada + */ +BOOL Colv_limp_thr::rellena_info_nw() +{ + int n, ntf, nft, nboth, nno,s,ia,icamps,icampv,icampn,icampf,f; + char nfile[MAX_PATH]; + Cdbf dbf; + char *sent, *velo, *name,*fow; + BOOL ret=TRUE,ispedestrian; + + if(!olv_limp->ias) + return FALSE; + + sent=velo=name=fow=NULL; + + wgeolog(LOG_TODO,"olv_limp_t","Rellenando matriz de info asociada a carreteras"); + pon_mi_progre(OLV_TAREA_IMP, (int) (OliviaDef::GeneralDef::ProgrMax*1/3)); //1/32 porque ya ha hecho 1/3, que es la importación + + n=0; + ntf=nft=nboth=nno=0; + + //si no aplican los sentidos de circulación no se calculan, se ponen todos a todos sentidos + if(olv_limp->res_circ==OLV_RES_NO) + { + wgeolog(LOG_TODO,"olv_limp_t","No aplican sentidos de circulación, puestos todos a 'ambos'"); + nboth=olv_limp->n_nw; + } + + //lee dbf del shp + strcpy_s(nfile,MAX_PATH,olv->paths.path_nw); + cambiaext(nfile,".shp",".dbf"); + dbf.noespa = TRUE; + if (!dbf.abre(nfile,0)) + { + sprintf_s(err_str,OLV_MAX_ERR,"Error al abrir %s",nfile); + wgeolog(LOG_TODO,"olv_limp_t","Error al abrir %s",nfile); + return FALSE; + } + + //busca el campo del sentido "ONEWAY" y el de "KPH" + icamps=icampv=icampn=icampf=-1; + for(n=0; ncamps.campo_circ)) + icamps=n; + if(!strcmp((*dbf.camp)[n].nombre,olv_limp->camps.campo_velo)) + icampv=n; + if(!strcmp((*dbf.camp)[n].nombre,olv_limp->camps.campo_name)) + icampn=n; + if(!strcmp((*dbf.camp)[n].nombre,olv_limp->camps.campo_fow)) + icampf=n; + } + if(icamps==-1 || icampv==-1 || icampn==-1 || icampf==-1) + { + sprintf_s(err_str,OLV_MAX_ERR,"No encontrado campo %s y/o %s y/o %s en\n%s",olv_limp->camps.campo_circ, + olv_limp->camps.campo_velo,olv_limp->camps.campo_name,nfile); + wgeolog(LOG_TODO,"No encontrado campo %s y/o %s y/o %s en\n%s",olv_limp->camps.campo_circ, + olv_limp->camps.campo_velo,olv_limp->camps.campo_name,nfile); + return FALSE; + } + + //////////////////////////////////////// + //prepara para leer la info de sentidos de circulación y la guarda en los flags + sent=(char*)malloc((*dbf.camp)[icamps].nb*2);//*2 para dejar un margen + if(!sent) + { + sprintf_s(err_str,OLV_MAX_ERR,"Error al pedir memoria para campo %s en\n%s",olv_limp->camps.campo_circ,nfile); + ret=FALSE; + goto fin; + } + sent[0]=0; + + //////////////////////////////////////// + //prepara para leer la info de sentidos de circulación y la guarda en los flags + velo=(char*)malloc((*dbf.camp)[icampv].nb*2);//*2 para dejar un margen + if(!velo) + { + sprintf_s(err_str,OLV_MAX_ERR,"Error al pedir memoria para campo %s en\n%s",olv_limp->camps.campo_velo,nfile); + ret=FALSE; + goto fin; + } + velo[0]=0; + + //////////////////////////////////////// + //prepara para leer la info de sentidos de nombre la guarda en los flags + name=(char*)malloc((*dbf.camp)[icampn].nb*2);//*2 para dejar un margen + if(!name) + { + sprintf_s(err_str,OLV_MAX_ERR,"Error al pedir memoria para campo %s en\n%s",olv_limp->camps.campo_name,nfile); + ret=FALSE; + goto fin; + } + name[0]=0; + + //////////////////////////////////////// + //prepara para leer la info de sentidos de FOW + fow=(char*)malloc((*dbf.camp)[icampf].nb*2);//*2 para dejar un margen + if(!fow) + { + sprintf_s(err_str,OLV_MAX_ERR,"Error al pedir memoria para campo %s en\n%s",olv_limp->camps.campo_fow,nfile); + ret=FALSE; + goto fin; + } + fow[0]=0; + + for(n=0;nn_nw; n++) + { + ia=(*olv_limp->olv->olv_ob->objt)[n+olv_limp->n_ini_nw].ia; + if (!dbf.lee_rec(n,0)) + { + break; + } + /////////////////////////////// + ispedestrian=FALSE; + if(olv_limp->res_circ!=OLV_RES_NO) + { + //("FOW" =3 OR "FOW">=7) AND ("ONEWAY" = 'N' OR "ONEWAY" = ' ' ) + //si se cumple lo anterior, son como doble sentido pero no se replican + ////////////////////////// + //sentido de circulación + dbf.dame_campo_c(icamps,sent); + s=0; + if(strlen(sent)==0) + { + nboth++; + } + else if(strcmp(sent,olv_limp->camps.atr_circ[OLV_ATR_CIRC_TF])==0) + { + s=OLV_LIMP_FLG_CIRC_TF; + ntf++; + } + else if(strcmp(sent,olv_limp->camps.atr_circ[OLV_ATR_CIRC_FT])==0) + { + s=OLV_LIMP_FLG_CIRC_FT; + nft++; + } + else if(strcmp(sent,olv_limp->camps.atr_circ[OLV_ATR_CIRC_NONE])==0) + { + //no aplica la restricción por ser servicio público, cómo se sabe si es de un único sentido? + //s=OLV_LIMP_FLG_CIRC_NONE; + nno++; + } + + /////////////////////////////// + //fow + f=0; + dbf.dame_campo_c(icampf,fow); + //solo mira si es pedestrian, f==14 + if(atoi(fow)==atoi(olv_limp->camps.atr_circ[OLV_ATR_CIRC_PEDES])) + { + s=OLV_LIMP_FLG_CIRC_NONE; + ispedestrian=TRUE; + } + /////////////////////////////// + + olv_limp->ias[ia].flgs=s; + } + + /////////////////////////////// + //velocidad + if((olv_limp->ias[ia].flgs & OLV_LIMP_FLG_CIRC_NONE) || ispedestrian) + { + s= OLV_LIMP_VELO_PEAT; //se le pone velo muy bajita para que intente no ir por ahí, porque son calles prohibidas + //a no ser que haya un contenedor + //o si es peatonal igual, que no haga las rutas por ahí, pero sí pase a hacer tratamientos + } + else + { + dbf.dame_campo_c(icampv,velo); + s=atoi(velo); + } + if(s<=0) + { + s=OLV_LIMP_VELO_DEF;//pone por def + //wgeolog(LOG_TODO,"olv_limp_t","Cuidado, info asociada a nw, %ld, puesta velo por defecto 10 km/h",n+1); + } + + olv_limp->ias[ia].info1=1.0*s; + + /////////////////////////////// + //nombre + dbf.dame_campo_c(icampn,name); + + olv_limp->ias[ia].info2 = (char*)malloc((*dbf.camp)[icampn].nb); + if(!olv_limp->ias[ia].info2) + break; + strcpy_s(olv_limp->ias[ia].info2,(*dbf.camp)[icampn].nb,name); + + olv_limp->ias[ia].info0=olv_limp->ias[ia].info3=-1; + + /////////////////////////////// + //avisa de progreso + if((n%200==0) || (n==(olv_limp->n_nw-1))) + { + pon_mi_progre(OLV_TAREA_IMP, (int) (OliviaDef::GeneralDef::ProgrMax* + (1.0*(n+1)/olv_limp->n_nw/3)+1/3));//por 2/3 porque esta tarea es la 2/3 + wgeolog(LOG_TODO,"olv_limp_t","Rellenando info asociada a nw, %ld de %ld", + n+1,olv_limp->n_nw); + } + + + } + if(nn_nw) + { + sprintf_s(err_str,OLV_MAX_ERR,"Error al leer record %ld en\n%s",n,nfile); + ret=FALSE; + goto fin; + } + + wgeolog(LOG_TODO,"olv_limp_t","Finaliza matriz de info asociada a carreteras: %ld doble sentido, %ld TF, %ld FT, %ld ninguno, %ld de %ld", + nboth,ntf,nft, nno, nboth+ntf+nft+nno, olv_limp->n_nw); + +fin: + if(sent) + free(sent); + if(velo) + free(velo); + if(name) + free(name); + if(fow) + free(fow); + return ret; +} +//************************************************************************************* +/** + * Rellena la información de ancho de los ámbitos + * en la tabla de información asociada + */ +BOOL Colv_limp_thr::rellena_info_amb() +{ + int n, icampa,icampo,icampta,icampte,ia; + char nfile[MAX_PATH]; + Cdbf dbf; + char *tipent, *tipap, *obs,*anc; + double ancho; + BOOL log_debug=FALSE; + BOOL ret=TRUE; + int barr_mix=0; //si entra en banda ap añade 1, en bordillo libre añade 2 y en acera añade 4, de forma que si es mayor que 4 es barrido mixto + + if(!olv_limp->ias) + return FALSE; + + //en principio, tipos puntuales no tienen info asociada + if(olv_limp->tipo_ambit==OLV_AMB_PUN) + return TRUE; + + //cuando se ha enviado eje de calle, no se lee info asociada porque la tabla es de tomotom, no tiene info + //tipo entidad ni nada.. + if((olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoMh_eje) || + (olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoM2h_eje)) + return TRUE; + + wgeolog(LOG_TODO,"olv_limp_t","Rellenando matriz de info asociada a ámbitos"); + pon_mi_progre(OLV_TAREA_IMP, (int) (OliviaDef::GeneralDef::ProgrMax*2/3)); + + obs=anc=tipent=tipap=NULL; + + //lee dbf del shp + strcpy_s(nfile,MAX_PATH,olv->paths.path_data); + cambiaext(nfile,".shp",".dbf"); + dbf.noespa = TRUE; + if (!dbf.abre(nfile,0)) + { + pon_mi_msg("Error al abrir %s",nfile); + ret=FALSE; + goto fin; + } + + //busca el campo de observaciones, de ancho_tipo, de tipo_entidad y tipología_aparc + icampa=icampo=icampta=icampte=-1; + for(n=0; ncamps.campo_obs)) + icampo=n; + if(!strcmp((*dbf.camp)[n].nombre,olv_limp->camps.campo_anch)) + icampa=n; + if(!strcmp((*dbf.camp)[n].nombre,olv_limp->camps.campo_tipo_ap)) + icampta=n; + if(!strcmp((*dbf.camp)[n].nombre,olv_limp->camps.campo_tipo_ent)) + icampte=n; + } + if(icampa==-1 || icampo==-1 || icampta==-1 || icampte==-1) + { + sprintf_s(err_str,OLV_MAX_ERR,"No encontrado campo %s y/o %s y/o %s\ny/o %s en\n%s",olv_limp->camps.campo_obs,olv_limp->camps.campo_anch, + olv_limp->camps.campo_tipo_ap,olv_limp->camps.campo_tipo_ent,nfile); + ret=FALSE; + goto fin; + } + + //////////////////////////////////////// + //prepara para leer la info de tipo de entidad + tipent=(char*)malloc((*dbf.camp)[icampte].nb*2); //*2 para dejar un margen + if(!tipent) + { + sprintf_s(err_str,OLV_MAX_ERR,"Error al pedir memoria para campo %s en\n%s",olv_limp->camps.campo_tipo_ent,nfile); + ret=FALSE; + goto fin; + } + tipent[0]=0; + + //////////////////////////////////////// + //prepara para leer la info de tipo de aparcamiento + tipap=(char*)malloc((*dbf.camp)[icampta].nb*2); //*2 para dejar un margen + if(!tipap) + { + sprintf_s(err_str,OLV_MAX_ERR,"Error al pedir memoria para campo %s en\n%s",olv_limp->camps.campo_tipo_ap,nfile); + ret=FALSE; + goto fin; + } + tipap[0]=0; + + //////////////////////////////////////// + //prepara para leer la info observaciones + obs=(char*)malloc((*dbf.camp)[icampo].nb*2); //*2 para dejar un margen + if(!obs) + { + sprintf_s(err_str,OLV_MAX_ERR,"Error al pedir memoria para campo %s en\n%s",olv_limp->camps.campo_obs,nfile); + ret=FALSE; + goto fin; + } + obs[0]=0; + + //////////////////////////////////////// + //prepara para leer la info de anchos de acera + anc=(char*)malloc((*dbf.camp)[icampa].nb*2); //*2 para dejar un margen + if(!anc) + { + sprintf_s(err_str,OLV_MAX_ERR,"Error al pedir memoria para campo %s en\n%s",olv_limp->camps.campo_anch,nfile); + ret=FALSE; + goto fin; + } + anc[0]=0; + + for(n=0;nn_amb; n++) + { + ia=(*olv_limp->olv->olv_ob->objt)[n].ia;//ojo, se toma por seguro que la primera capa abierta es la de ámbitos + if (!dbf.lee_rec(n,0)) + { + break; + } + + //si el campo tipo de entidad es banda_aparcamiento, el ancho es fijo, + //en función de la tipología del aparcamiento + //si no, hay que leer el ancho + ancho=OLV_LIMP_ANCH_DEF; + olv_limp->ias[ia].info3=0; + /////////////////////////////// + dbf.dame_campo_c(icampte,tipent); + if(strlen(tipent)>0 && strcmp(tipent,olv_limp->camps.atr_tip_ent[OLV_ATR_NOM_TIP_ENT_AP])==0) + { + //es banda de aparcamiento + dbf.dame_campo_c(icampta,tipap); + if(strlen(tipap)>0 && strcmp(tipap,olv_limp->camps.atr_tip_apa[OLV_ATR_TIP_AP_LIN])==0) + { + //es aparcamiento lineal, ancho fijo 2 + ancho=olv_limp->anchos_def[OLV_ANCH_DEF_APLIN]; + } + else if(strlen(tipap)>0 && strcmp(tipap,olv_limp->camps.atr_tip_apa[OLV_ATR_TIP_AP_BAT])==0) + { + //es aparcamiento en batería, ancho fijo 4 + ancho=olv_limp->anchos_def[OLV_ANCH_DEF_APBAT]; + } + + if(log_debug) + wgeolog(LOG_TODO,"olv_limp_t","info aso a ámb %ld: tipent %s, tipap %s",n+1,tipent,tipap); + + //lo marca para saber si es barrido mixto + olv_limp->ias[ia].info3=OLV_AMBLIN_APA; + if(!olv_limp->barr_mix && !(barr_mix & (1<<(OLV_AMBLIN_APA-1)))) + barr_mix |= (1<<(OLV_AMBLIN_APA-1)); + } + else if(strlen(tipent)>0 && strcmp(tipent,olv_limp->camps.atr_tip_ent[OLV_ATR_NOM_TIP_ENT_BORD])==0) + { + //es bordillo libre + ancho=olv_limp->anchos_def[OLV_ANCH_DEF_BORD]; + + //lo marca para saber si es barrido mixto + olv_limp->ias[ia].info3=OLV_AMBLIN_BORD; + if(!olv_limp->barr_mix && !(barr_mix & (1<<(OLV_AMBLIN_BORD-1)))) + barr_mix |= (1<<(OLV_AMBLIN_BORD-1)); + } + else if(strlen(tipent)>0) + { + //es acera o peatonal + //hay que leer el ancho + dbf.dame_campo_c(icampo,obs); + dbf.dame_campo_c(icampa,anc); + + if(log_debug) + wgeolog(LOG_TODO,"olv_limp_t","info aso a ámb %ld: obs %s, anch %s",n+1,obs,anc); + + if(strcmp(tipent,olv_limp->camps.atr_tip_ent[OLV_ATR_NOM_TIP_ENT_ACERA])==0) + { + ancho=olv_limp->anchos_def[OLV_ANCH_DEF_ACE];//acera + + //lo marca para saber si es barrido mixto + olv_limp->ias[ia].info3=OLV_AMBLIN_ACE; + if(!olv_limp->barr_mix && !(barr_mix & (1<<(OLV_AMBLIN_ACE-1)))) + barr_mix |= (1<<(OLV_AMBLIN_ACE-1)); + } + else if(strcmp(tipent,olv_limp->camps.atr_tip_ent[OLV_ATR_NOM_TIP_ENT_PEAT])==0) + { + ancho=olv_limp->anchos_def[OLV_ANCH_DEF_PEAT];//peatonal + + olv_limp->ias[ia].info3=OLV_AMBLIN_PEAT; + } + else + ancho = OLV_LIMP_ANCH_DEF; + + //si es tipo peatonal lo pone en los flags + if(strcmp(tipent,olv_limp->camps.atr_tip_ent[OLV_ATR_NOM_TIP_ENT_PEAT])==0) + { + olv_limp->ias[ia].flgs |= OLV_LIMP_FLG_PEAT; + } + } + olv_limp->ias[ia].info1=ancho; + if(log_debug) + wgeolog(LOG_TODO,"olv_limp_t","info aso a ámb %ld: ancho %lf",n+1, ancho); + + olv_limp->ias[ia].info0=-1; + + /////////////////////////////// + //avisa de progreso + if((n%100==0) || (n==(olv_limp->n_amb-1))) + { + pon_mi_progre(OLV_TAREA_IMP, (int) (OliviaDef::GeneralDef::ProgrMax* + ((1.0*(n+1)/olv_limp->n_amb)/3)+2/3)); + wgeolog(LOG_TODO,"olv_limp_t","Rellenando info asociada a ámbitos, %ld de %ld", + n+1,olv_limp->n_amb); + } + + if(!olv_limp->barr_mix) + olv_limp->barr_mix=(barr_mix>(1<<(OLV_AMBLIN_ACE-1)) && barr_mix<(1<<(OLV_AMBLIN_PEAT-1))); + } + + if(nn_amb) + { + sprintf_s(err_str,OLV_MAX_ERR,"Error al leer información asociada %ld en\n%s",n,nfile); + ret=FALSE; + goto fin; + } + + + wgeolog(LOG_TODO,"olv_limp_t","Finaliza Matriz de info asociada a ámbitos"); + +fin: + if(obs) + free(obs); + if(anc) + free(anc); + if(tipent) + free(tipent); + if(tipap) + free(tipap); + + return ret; +} +//************************************************************************************* +/** + * Replica los ámbitos cuando son tipo peatonal, añadiendo otro lineal igual que tendrá solo coste + * de desplazamiento, no de tratamiento, más los segmentos que los unen, de coste 0 + */ +BOOL Colv_limp_thr::replica_peat(int n_amb, int nias, Info_aso **ias_, Cobgeo *ob) +{ + int i,n_peat,il,indx,npts,ip,max_npts,p,k; + double (*ptos)[3],(*ptos_aux)[][3]; + Info_aso *ias_aux; + Objgeo lineal; + BOOL mal; + Info_aso *ias; + + ptos_aux=NULL; + ias=*ias_; + + //cuenta el número de peatonales + n_peat=0; + for(i=0;in_peat=n_peat; + + //si hay peatonales, agranda el array de info asociada + //npeat*3 porque van la réplica del peatonal y sus dos segmentos + ias_aux = (Info_aso *)realloc(ias,(nias+n_peat*3)*sizeof(Info_aso)); + if(!ias_aux) + { + return FALSE; + } + ias=ias_aux; + memset(&ias[nias],0,n_peat*3*sizeof(Info_aso)); + + //indica dónde empieza la info aso de las peatonales + olv_limp->n_ini_amb_iapr=nias; + + //Inicializa el lineal con los parámteros comunes + //crea el lineal + lineal.tipo = OBJ_LINEAL; + lineal.flags[0] = 0; + lineal.flags[1] = 0; + lineal.ev.id = 0; + lineal.pt.lin = (Linealgeo*) malloc (sizeof(Linealgeo)); + if(!lineal.pt.lin) + { + return FALSE; + } + lineal.clase = OLV_ICLA_LIN_PEAT; + lineal.pt.lin->ptos=NULL; + ///////////////// + mal=FALSE; + ip=0; + max_npts=0; + //replica las peatonales + for(i=0;iobjt)[i].indx; + npts = (*ob->lial)[il].n; + indx=(*ob->lial)[il].indx; + ptos = &(*ob->ptos)[indx]; + + //pone los valores + lineal.ia = nias + ip; + lineal.pt.lin->n= npts; + + //pide memoria para los puntos si hace falta + if(npts>max_npts) + { + ptos_aux = (double (*)[][3]) realloc(lineal.pt.lin->ptos,npts * 3 * sizeof(double)); + max_npts=npts; + } + if(!ptos_aux) + { + mal=TRUE; + continue; + } + lineal.pt.lin->ptos=ptos_aux; + + //copia los puntos del ámbito + memcpy(lineal.pt.lin->ptos,ptos,npts*3*sizeof(double)); + lineal.pt.lin->flags = 0; + if(ob->pon_obj(&lineal)<0) + { + mal=TRUE; + } + + //reapunta el array de puntos + ptos = &(*ob->ptos)[indx]; + + //añade los dos extremos, por si se ha movido memoria en el pon + for(k=0;k<2;k++) + { + lineal.ia = nias + ip + (k+1)*n_peat; + lineal.pt.lin->n= 2; + for(p=0;p<2;p++) + memcpy(&(*lineal.pt.lin->ptos)[p],ptos[k*(npts-1)],3*sizeof(double)); + lineal.pt.lin->flags = 0; + if(ob->pon_obj(&lineal)<0) + { + mal=TRUE; + } + ptos = &(*ob->ptos)[indx]; + } + + //actualiza la info asociada + ias[nias+ip].flgs=OLV_LIMP_FLG_PEAT_REP; + ias[nias+ip].info0=i; + ias[nias+ip+n_peat].flgs=OLV_LIMP_FLG_PEAT_SEG; + ias[nias+ip+2*n_peat].flgs=OLV_LIMP_FLG_PEAT_SEG; + + ip++; + } + ob->libera_objgeo(&lineal); + if(mal) + return FALSE; + + *ias_ = ias; + + return TRUE; +} +//************************************************************************************* +/** + * Replica las calles cuando son de doble sentido y se tienen en cuenta las restricciones + * de circulación, para que se asignen los ámbitos sólo a la calle del sentido en el que estén + */ +BOOL Colv_limp_thr::replica_doble_sent(Info_inw_dmin *inww, Info_aso **ias_, Cobgeo *ob) +{ + int i,iaux,indx,npts,max_npts,n_doble,id,nias,KK,inw,ia,inwl; + double (*ptos)[3],(*ptos_aux)[3]; + Info_aso *ias_aux; + Objgeo lineal; + BOOL mal; + Info_aso *ias; + + ptos_aux=NULL; + ias=*ias_; + KK=olv_limp->tipo_ambit; + nias=olv_limp->n_nw+olv_limp->n_amb*(KK+1)+olv_limp->n_peat*3; + max_npts=0; + mal=FALSE; + + olv_limp->n_ini_nw_2 = nias; + + if(olv_limp->res_circn_ini_nw;in_ini_nw+olv_limp->n_nw; i++) + { + if(ias[(*ob->objt)[i].ia].flgs & OLV_LIMP_FLG_CIRC_NO_DOB) + continue; + n_doble++; + } + if(n_doble==0) + return TRUE;//no hay calles de doble sentido + + + //si hay calles de doble sentido, agranda el array de info asociada + //n_doble porque va la réplica + ias_aux = (Info_aso *)realloc(ias,(nias+n_doble)*sizeof(Info_aso)); + if(!ias_aux) + { + return FALSE; + } + ias=ias_aux; + memset(&ias[nias],0,n_doble*sizeof(Info_aso)); + + //Inicializa el lineal con los parámteros comunes + //crea el lineal + lineal.tipo = OBJ_LINEAL; + lineal.flags[0] = 0; + lineal.flags[1] = 0; + lineal.ev.id = 0; + lineal.pt.lin = (Linealgeo*) malloc (sizeof(Linealgeo)); + if(!lineal.pt.lin) + { + return FALSE; + } + lineal.clase = OLV_ICLA_LIN_NW_REP; + lineal.pt.lin->ptos=NULL; + /////////////////////////// + + id=0; + //cuenta el número de calles de doble sentido que hay que replicar + for(i=0;in_amb*KK; i++) + { + //apunta al nw más cercano del ámbito actual + inw=inww[i].inw; + if((inw<0) || (inwn_ini_nw)) + continue; + ia=(*ob->objt)[inw].ia; + if((ias[ia].flgs & OLV_LIMP_FLG_NO_NW) || + (ias[ia].flgs & OLV_LIMP_FLG_CIRC_NO_DOB)) + continue; + + //llega aquí si es nw de doble sentido + inwl=(*ob->objt)[inw].indx; + npts = (*ob->lial)[inwl].n; + indx=(*ob->lial)[inwl].indx; + ptos = &(*ob->ptos)[indx]; + + ////////////////////////////////////////////// + //se hace réplica + //pone los valores + lineal.ia = nias + id; + lineal.pt.lin->n= npts; + + ptos_aux=(double (*)[3])lineal.pt.lin->ptos; + //pide memoria para los puntos si hace falta + if(npts>max_npts) + { + ptos_aux = (double (*)[3]) realloc(lineal.pt.lin->ptos,npts * 3 * sizeof(double)); + max_npts=npts; + } + if(!ptos_aux) + { + mal=TRUE; + continue; + } + + //copia los puntos de la calle + memcpy(ptos_aux,ptos,npts*3*sizeof(double)); + + //copia los puntos de la calle + lineal.pt.lin->ptos=(double (*)[][3])ptos_aux; + lineal.pt.lin->flags = 0; + if(ob->pon_obj(&lineal)<0) + { + mal=TRUE; + continue; + } + + //actualiza la info asociada, les cambia el flag, tenían los dos sentidos (flg 0), + //y se le pone uno de los dos + //el original + ias[ia].flgs|=OLV_LIMP_FLG_CIRC_FT; + //el nuevo + ias[nias + id].flgs|=OLV_LIMP_FLG_CIRC_TF|OLV_LIMP_FLG_NW_REP; + //copia ishp + ias[nias + id].ishp = ias[ia].ishp; + //copia velocidad + ias[nias + id].info1 = ias[ia].info1; + //copia nombre + ias[nias + id].info2 = (char*)malloc(OLV_LIMP_MAX_CAMP); + if(!ias[nias + id].info2) + { + return FALSE; + } + ias[ia].info2[OLV_LIMP_MAX_CAMP-1]=0; + strcpy_s(ias[nias + id].info2,OLV_LIMP_MAX_CAMP,ias[ia].info2); + //copia ishp + ias[nias + id].ishp = ias[ia].ishp; + + ////////////////////////////////////////////// + //a los que están a la izquiera les reapunta + iaux=i; + while((iauxn_amb*KK) && (inww[iaux].inw==inw)) + { + if(!(ias[inww[iaux].iamb+olv_limp->n_ini_amb_iai].flgs & OLV_LIMP_FLG_DER)) + { + inww[iaux].inw=(ob->vect.nobj-1);//el lineal que acaba de añadir + //reapunta también el original + olv_limp->inww_amb[inww[iaux].iamb].inw=(ob->vect.nobj-1); + ///////////////////////////// + + ias[inww[iaux].iamb+olv_limp->n_ini_amb_iai].flgs |= OLV_LIMP_FLG_DER; + (*ob->objt)[inww[iaux].iamb].clase=-6; + //wgeolog(LOG_TODO,"olv_limp_t","Ámbito %ld reapuntado a la derecha",inww[iaux].iamb); + + } + iaux++; + + } + i=iaux-1; + + id++; + } + + + olv_limp->n_nw_dobl = id; + + ob->libera_objgeo(&lineal); + if(mal) + return FALSE; + + *ias_ = ias; + + return TRUE; +} +//************************************************************************************* +/** + * Une la red navegable y los ámbitos + * 'soloi' es para debug, indica si se quiere realizar la unión de un único ámbito pasado en soloi + */ +BOOL Colv_limp_thr::une_amb_nw(int soloi) +{ + int i,k,KK; + //variables para apuntar al ámbito y nw en cuestión + int npt_amb, il_amb,iamb; + double (*pt_amb)[3]; + BOOL log_debug=FALSE; + + ////////////////// + //coge el factor del tipo de ámbito, 1 si es puntual, 2 si es lineal + KK=olv_limp->tipo_ambit; + + ////////////////// + //replica las peatonales que sea necesario + if(KK==OLV_AMB_LIN) + { + int n_ias=(olv_limp->n_nw+olv_limp->n_amb*(KK+1)); + if(!replica_peat(olv_limp->n_amb,n_ias,&olv_limp->ias,olv_limp->olv->olv_ob)) + { + pon_mi_msg("Error al replicar peatonales: %s", err_str); + return FALSE; + } + } + ////////////////// + + //inicia cuando ya sabe si es tipo lineal o puntual + if(!olv_limp->inww_amb) + { + olv_limp->inww_amb = (Info_inw_dmin *)malloc(olv_limp->n_amb*KK*sizeof(Info_inw_dmin)); + } + if(!olv_limp->inww_amb) + { + pon_mi_msg("Error, sin memoria para matriz de índices\nde ámbitos a carreteras"); + return FALSE; + } + + //rellena todos a no def + for(i=0;in_amb*KK;i++) + { + olv_limp->inww_amb[i].inw=OLV_LIMP_AMB_NW_NODEF; + olv_limp->inww_amb[i].iamb=i%olv_limp->n_amb; + olv_limp->inww_amb[i].dmin=(float)MAYUSCULO; + olv_limp->inww_amb[i].inw_old=NULL; + olv_limp->inww_amb[i].ip=olv_limp->inww_amb[i].flgs=0; + olv_limp->inww_amb[i].lamb=olv_limp->inww_amb[i].alpha=0; + olv_limp->inww_amb[i].pt[0]=olv_limp->inww_amb[i].pt[1]=olv_limp->inww_amb[i].pt[2]=0; + } + /////////////////// + + wgeolog(LOG_TODO,"olv_limp_t","Uniendo ámbitos a NW"); + pon_mi_progre(OLV_TAREA_UNE_NW_AMB, 0); + pon_mi_msg(""); + err_str[0]=0; + + //Bucle por ámbito + for(i=0;in_amb && !pirate; i++) + { + if((soloi>-1) && (soloin_amb) && (i!=soloi)) + continue;//para debug, si soloi apunta al ámbito que queremos calcular solo + + if(olv_limp->ias[i].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + + //apunta el array de puntos al ámbito + il_amb=(*olv_limp->olv->olv_ob->objt)[i].indx; + if(KK==OLV_AMB_LIN)//para tipo lineal, obtiene los primeros puntos de los dos extremos + { + if((*olv_limp->olv->olv_ob->objt)[i].tipo != OBJ_LINEAL) + continue;//comprueba clases + npt_amb = (*olv_limp->olv->olv_ob->lial)[il_amb].n; + iamb=(*olv_limp->olv->olv_ob->lial)[il_amb].indx; + pt_amb = &(*olv_limp->olv->olv_ob->ptos)[iamb]; + } + else if(KK==OLV_AMB_PUN) //para tipo puntual, es un único punto + { + if((*olv_limp->olv->olv_ob->objt)[i].tipo != OBJ_PUNTUAL) + continue;//comprueba clases + npt_amb = 1; + iamb=il_amb; + pt_amb = &(*olv_limp->olv->olv_ob->ptos)[iamb]; + } + + //rellena en inww_amb el inw y su info de la carretera del nw élegida como + //más cercana al ámbito + busca_inw_dmin(i,olv_limp->n_amb, npt_amb,pt_amb, + olv_limp->n_ini_nw, olv_limp->n_nw, + KK,olv_limp->inww_amb , olv_limp->olv->olv_ob); + + //////////////////////////////////////////// + //comprueba en todos los ámbitos si va andando, si están asignados a una carretera muy lejos + //y tienen un ámbito más cerca, les asigna ese (excepto en el caso ejes) + if((olv_limp->res_circuds_tto!=OliviaDef::GeneralDef::OlvTipTtoMh_eje) && + (olv_limp->uds_tto!=OliviaDef::GeneralDef::OlvTipTtoM2h_eje))) + comprueba_amb_lejos(i,olv_limp->n_amb, npt_amb,pt_amb,olv_limp->inww_amb,olv_limp->ias, olv_limp->olv->olv_ob); + + //Añade los segmentos a clase NW_union + add_uniones_obj(i,olv_limp->n_amb,olv_limp->n_ini_nw,olv_limp->n_ini_amb_iai,olv_limp->n_ini_amb_iaf,npt_amb,KK, + olv_limp->inww_amb,olv_limp->ias, olv_limp->olv->olv_ob); + + if(log_debug) + { + //loguea + for(k=0; kinww_amb[i + k*olv_limp->n_amb].dmin, + olv_limp->inww_amb[i + k*olv_limp->n_amb].inw, + olv_limp->inww_amb[i + k*olv_limp->n_amb].ip, + olv_limp->inww_amb[i + k*olv_limp->n_amb].lamb, + olv_limp->inww_amb[i + k*olv_limp->n_amb].alpha); + } + + if((i%100==0) ||(i==(olv_limp->n_amb-1))) + { + wgeolog(LOG_TODO,"olv_limp_t","Uniendo ámbitos a NW, %ld de %ld",i+1,olv_limp->n_amb); + //avisa de progreso + pon_mi_progre(OLV_TAREA_UNE_NW_AMB, (int) ((OliviaDef::GeneralDef::ProgrMax* + 1.0*(i+1)/olv_limp->n_amb))); + } + + } + //cuida si ha salido antes por falta de memo + if(in_amb) + { + pon_mi_msg("Error en la unión de ámbitos a red navegable"); + return FALSE; + } + + if(olv_limp->res_circinww_amb); + + ///////////////////////////////////////////////////// + //si hay algún ámbito asignado a una carretera de prohibido circular + //se le quita el flag a la carretera + if(olv_limp->res_circ!=OLV_RES_NO) + { + for(i=0;in_amb && !pirate; i++) + { + if(olv_limp->ias[i].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + for(k=0; kias[(*olv->olv_ob->objt)[olv_limp->inww_amb[i + k*olv_limp->n_amb].inw].ia].flgs & + OLV_LIMP_FLG_CIRC_NONE) + { + //le quita el flag + olv_limp->ias[(*olv->olv_ob->objt)[olv_limp->inww_amb[i + k*olv_limp->n_amb].inw].ia].flgs = + olv_limp->ias[(*olv->olv_ob->objt)[olv_limp->inww_amb[i + k*olv_limp->n_amb].inw].ia].flgs & ~OLV_LIMP_FLG_CIRC_NONE; + } + } + } + } + + return TRUE; +} +//************************************************************************************* +/** + * Como se ha podido unir unos ámbitos a otros, revisa que no se hayan unido sólo entre sí + * y no a ninguna carretera, en ese caso estarían aislados. Lo revisa para, en esos casos, + * forzar a que apunte alguno a una carretera + */ +void Colv_limp_thr::comprueba_aislados(Info_inw_dmin *inww) +{ + int i,KK,iamb,k,j; + BYTE *ambs_flgs; + int *ambs_cola; + int ncola; + BOOL aislado; + double dmin; + int iambmin; + int npt_amb; + +#define FLG_VISTO 1 +#define FLG_TEMP 2 + + KK=olv_limp->tipo_ambit; + //inicia el array de flags + ambs_flgs = (BYTE*)malloc(olv_limp->n_amb); + if(!ambs_flgs) + return; + memset(ambs_flgs,0,olv_limp->n_amb); + //inicia la cola + ambs_cola = (int*)malloc(olv_limp->n_amb*sizeof(int)); + if(!ambs_cola) + return; + memset(ambs_cola,0,olv_limp->n_amb*sizeof(int)); + ncola=0; + + //bucle para cada ámbito + for(i=0;in_amb && !pirate; i++) + { + if(ambs_flgs[i] & FLG_VISTO) + continue; + + if(olv_limp->ias[i].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + aislado=TRUE; + //lo mete a la cola + ambs_cola[ncola]=i; + ncola=1; + + while (ncola) + { + //saca ámbito de la cola + ncola--; + iamb=ambs_cola[ncola]; + + //le pone el flag temporal + ambs_flgs[iamb] |= FLG_TEMP; + + //bucle en los dos extremos + for(k=0;kn_amb].inwn_amb) + { + //lo mete en la cola si su extremo es un ámbito + //no visto ni temporal + if(ambs_flgs[inww[iamb+k*olv_limp->n_amb].inw] & (FLG_TEMP | FLG_VISTO)) + continue; + ambs_cola[ncola]=inww[iamb+k*olv_limp->n_amb].inw; + ncola++; + } + else + aislado=FALSE; + } + } + + if(aislado) + { + //es una aislada o grupo de aisladas, + //deja apuntada a una nw la de distancia menor + dmin=MAYUSCULO; + iambmin=-1; + for(j=0;jn_amb; j++) + { + if(!(ambs_flgs[j] & FLG_TEMP)) + continue; + + for(k=0;kn_amb].inw_old) + continue;//no debería + if(inww[j+k*olv_limp->n_amb].inw_old->dminn_amb; + dmin=inww[j+k*olv_limp->n_amb].inw_old->dmin; + } + } + } + if(dmin=0) + { + //reapunta a la inw old + memcpy(&inww[iambmin],inww[iambmin].inw_old,sizeof(Info_inw_dmin)); + free(inww[iambmin].inw_old); + inww[iambmin].inw_old=NULL; + + //añade el segmento de unión + if(KK==OLV_AMB_LIN)//para tipo lineal, obtiene los primeros puntos de los dos extremos + npt_amb = (*olv_limp->olv->olv_ob->lial)[(*olv_limp->olv->olv_ob->objt)[iambmin].indx].n; + else if(KK==OLV_AMB_PUN) //para tipo puntual, es un único punto + npt_amb = 1; + + add_uniones_obj(iambmin%olv_limp->n_amb,olv_limp->n_amb,olv_limp->n_ini_nw,olv_limp->n_ini_amb_iai,olv_limp->n_ini_amb_iaf,npt_amb,KK, + olv_limp->inww_amb,olv_limp->ias, olv_limp->olv->olv_ob); + } + } + + //todos los estudiados, que son los del flag temporal, los pone como vistos + for(j=0;jn_amb; j++) + { + if(ambs_flgs[j] & FLG_TEMP) + { + ambs_flgs[j] = ambs_flgs[j] & ~FLG_TEMP; + ambs_flgs[j] = ambs_flgs[j] | FLG_VISTO; //le quita el flag temporal y le pone el de visto + } + } + } + + free(ambs_flgs); + free(ambs_cola); +} +//************************************************************************************* +/** + * Comprueba en 'inww' si 'daux' es menor que las almacenadas. + * Devuelve la posición del array inww donde tiene que ir o -1 si no es menor + * y vacía dicha posición, moviendo las demás, para que el siguiente guarde ahí lo que toca + */ +int Colv_limp_thr::is_dmin(double daux, Info_inw_dmin *inww) +{ + int i=-1,k; + + if(!inww) + return i; + + for(i=0; i=i; k--) + { + memcpy(&inww[k+1], &inww[k],sizeof(Info_inw_dmin)); + } + break; + } + } + if(i>=OLV_LIMP_N_DMIN_NW) + i=-1; + + return i; +} +//************************************************************************************* +/** + * Devuelve la distancia de un ámbito 'i_amb'(ya relativo al n_ini_amb) de 'npt_amb' puntos almacenados + * en 'pt_amb' a la carretera más cercana, y rellena la info de dicha carretera en inww_amb. + * KK indica el tipo de ámbito, si es 1 es puntual, sólo se calcula una distancia a la carretera, + * si es 2, es lineal, se calculan la distancia al extremo inicial y al final + * 'n_amb' es el número total de ámbitos, ini_nw el inicial de carreteras y 'n_nw' el número de ellas. + * 'pb' es donde están las polilíneas tanto de carreteras como de ámbitos. + */ +BOOL Colv_limp_thr::busca_inw_dmin(int i_amb, int n_amb, int npt_amb, double (*pt_amb)[3], int ini_nw, int n_nw, + int KK, Info_inw_dmin *inww_amb, Cobgeo *ob) +{ + //variables para apuntar al ámbito y nw en cuestión + int npt_nw, il_nw, i_nw, indx_nw; + double (*pt_nw)[3]; + //variables locales + BOOL pinta_amb,pinta_nw,log_detalle; + double alphamin[2], daux, dtot, dist; + int i_inww, j, k, jmin[2]; + double (*pt_amb_prime_i)[3], (*pt_amb_prime_f)[3], (*pt_prime)[3]; + double pt_ang[2][3]; //almacena dos puntos para calcular el vector con el que forma el ángulo el ámbito + Info_inw_dmin inwaux; + Info_inw_dmin inww[OLV_LIMP_N_DMIN_NW*2]; //Almacena las N mejores carreteras del punto inicial y las N del punto final + + ///////////////////// + pinta_amb=FALSE; + pinta_nw=FALSE; + log_detalle=FALSE; + + //inicializa + pt_amb_prime_i=pt_amb_prime_f=pt_prime=NULL; + + //inicializa array local para almacenamiento de las tres carreteras más cercanas + memset(inww,0,sizeof(Info_inw_dmin)*OLV_LIMP_N_DMIN_NW*2); + for(int j=0; jolv_ob); + Colv_geom::pon_pto((double(*)[3])pt_amb_prime_f[j],OLV_ICLA_PUN_AMB,0,olv->olv_ob); + } + } + } + + //////////////////////////////////////////////////////////////////////// + //Bucle por cada carretera de la nw + for(int inw=ini_nw; inwobjt)[inw].clase != OLV_ICLA_LIN_NW) + continue; //no debería, pero por si acaso + + il_nw=(*ob->objt)[inw].indx; + npt_nw = (*ob->lial)[il_nw].n; + indx_nw=(*ob->lial)[il_nw].indx; + pt_nw = &(*ob->ptos)[indx_nw]; + inwaux.inw=inw; + + //lo hace para punto inicial y final si es lineal, o solo una vez si es puntual + for(k=0; k=0) + { + //Dist ptos-recta. Si dist mayor que la mínima guardada, descarta. + // Si todas dist similares y menores que una dada, se guarda + //inw->linea de la nw + inww[i_inww+k*OLV_LIMP_N_DMIN_NW].dmin=(float)daux; + inww[i_inww+k*OLV_LIMP_N_DMIN_NW].inw=inwaux.inw; + inww[i_inww+k*OLV_LIMP_N_DMIN_NW].ip = inwaux.ip; + inww[i_inww+k*OLV_LIMP_N_DMIN_NW].lamb=inwaux.lamb; + inww[i_inww+k*OLV_LIMP_N_DMIN_NW].pt[0]=inww[i_inww+k*OLV_LIMP_N_DMIN_NW].pt[1]= + inww[i_inww+k*OLV_LIMP_N_DMIN_NW].pt[2]=0; + } + } + } + if(pirate) + goto fin; + //////////////////////////////////////////////////////////////////////// + //coger de los tres de inww el que del punto ip de nw al extremo de amb forme el ángulo + //cuya diferencia con pi/2 sea menor (en el caso lineal) + //y ponerlo en inww_amb[i-olv_limp->n_ini_amb] + jmin[0]=jmin[1]=0; + alphamin[0]=alphamin[1]=MAYUSCULO; + for(j=0;j=n_nw+ini_nw)) //por si acaso + continue; + il_nw = (*ob->objt)[i_nw].indx; + npt_nw = (*ob->lial)[il_nw].n; + indx_nw=(*ob->lial)[il_nw].indx; + pt_nw = &(*ob->ptos)[indx_nw]; + + //calcula el punto del inw donde se da el mínimo + inww[j+k*OLV_LIMP_N_DMIN_NW].pt[2]=0; + inww[j+k*OLV_LIMP_N_DMIN_NW].pt[0]=pt_nw[inww[j+k*OLV_LIMP_N_DMIN_NW].ip][0]+ + (pt_nw[inww[j+k*OLV_LIMP_N_DMIN_NW].ip+1][0]-pt_nw[inww[j+k*OLV_LIMP_N_DMIN_NW].ip][0])* + inww[j+k*OLV_LIMP_N_DMIN_NW].lamb; + inww[j+k*OLV_LIMP_N_DMIN_NW].pt[1]=pt_nw[inww[j+k*OLV_LIMP_N_DMIN_NW].ip][1]+ + (pt_nw[inww[j+k*OLV_LIMP_N_DMIN_NW].ip+1][1]-pt_nw[inww[j+k*OLV_LIMP_N_DMIN_NW].ip][1])* + inww[j+k*OLV_LIMP_N_DMIN_NW].lamb; + + if(inww[j+k*OLV_LIMP_N_DMIN_NW].pt[0]==0 || inww[j+k*OLV_LIMP_N_DMIN_NW].pt[1]==0) + int a=0; + + //solo para tipo lineal, elige el de distancia menor y que el ángulo que forma el ámbito con + //el punto más cercano de la nw sea el más ortogonal + if(KK==OLV_AMB_LIN) + { + if(k==0) + pt_prime = pt_amb_prime_i; + else + pt_prime = pt_amb_prime_f; + //el ángulo se calcula entre el extremo del ámbito con el vector que forman dicho extremo del + //ámbito con el punto del inw donde se da el mínimo + pt_ang[0][0] = pt_prime[0][0]; + pt_ang[0][1] = pt_prime[0][1]; + pt_ang[0][2] = pt_prime[0][2]; + pt_ang[1][0] = inww[j+k*OLV_LIMP_N_DMIN_NW].pt[0]; + pt_ang[1][1] = inww[j+k*OLV_LIMP_N_DMIN_NW].pt[1]; + pt_ang[1][2] = inww[j+k*OLV_LIMP_N_DMIN_NW].pt[2]; + + inww[j+k*OLV_LIMP_N_DMIN_NW].alpha=(float)fabs(Colv_geom::prod_esc((double(*)[][3])pt_prime, + (double(*)[][3])pt_ang)); + } + } + } + if(KK==OLV_AMB_LIN) + { + //únicamente si el segundo más cercano (el de la pos '1') tiene alpha menor, y una distancia no mucho mayor (*) + //lo coge, + //si no, se queda el más cercano + for(k=0; kres_circ!=OLV_RES_NO) + { + //si hay restricciones de circulación, y se va a coger como dmin una carretera peatonal, coge la siguiente de dmin + for(k=0; kias[(*ob->objt)[inww[k*OLV_LIMP_N_DMIN_NW].inw].ia].info1 ==0) && + (olv_limp->ias[(*ob->objt)[inww[1+k*OLV_LIMP_N_DMIN_NW].inw].ia].info1 !=0)) + jmin[k]=1; + } + } + + //copia el mínimo que ha encontrado + //para el punto inicial y final, o solo una vez si es puntual + for(k=0; kobjt)[i_amb].ia; + ////////////////////////// + for(int k=0; kinww_amb[i_amb+k*n_amb].inw; + if(inw<0 || inw>=(olv_limp->n_nw+ini_nw)) //por si acaso + continue; + il_nw = (*olv_limp->olv->olv_ob->objt)[inw].indx; + indx_nw=(*olv_limp->olv->olv_ob->lial)[il_nw].indx; + pt_nw = &(*olv_limp->olv->olv_ob->ptos)[indx_nw]; + npt_nw = (*olv_limp->olv->olv_ob->lial)[il_nw].n; + + //apunta el array de puntos al ámbito + il_amb=(*olv_limp->olv->olv_ob->objt)[i_amb].indx; + if(KK==OLV_AMB_LIN)//para tipo lineal, obtiene los primeros puntos de los dos extremos + { + npt_amb = (*olv_limp->olv->olv_ob->lial)[il_amb].n; + indx_amb=(*olv_limp->olv->olv_ob->lial)[il_amb].indx; + pt_amb = &(*olv_limp->olv->olv_ob->ptos)[indx_amb]; + } + else if(KK==OLV_AMB_PUN) //para tipo puntual, es un único punto + { + npt_amb = 1; + indx_amb=il_amb; + pt_amb = &(*olv_limp->olv->olv_ob->ptos)[indx_amb]; + } + + //calcula donde está ya la info de los segmentos + iass=ia+(1-k)*n_ini_ia_i+k*n_ini_ia_f;//sus flags indican que es segmento y si es final o no + + //mira a ver si está a la derecha el punto del ámbito + //k=0; solo un punto, k=1, el punto final, por si es lineal + if(Colv_geom::is_der((double (*)[][3])&pt_nw[inww_amb[i_amb+k*n_amb].ip], pt_amb[(npt_amb-1)*k])) + { + if((inw=ini_nw)&& !(olv_limp->ias[(*ob->objt)[inw].ia].flgs & OLV_LIMP_FLG_CIRC_TF))) + { + icla=OLV_ICLA_LIN_NW_UD; + ias[iass].flgs |= OLV_LIMP_FLG_DER; //FT o both + } + else + icla=OLV_ICLA_LIN_NW_UI; + + } + else + { + if((inw=ini_nw)&& (olv_limp->ias[(*ob->objt)[inw].ia].flgs & OLV_LIMP_FLG_CIRC_TF))) + { + icla=OLV_ICLA_LIN_NW_UD; + ias[iass].flgs |= OLV_LIMP_FLG_DER; //tf + } + else + icla=OLV_ICLA_LIN_NW_UI; + } + + if(inwias[i_amb].flgs & OLV_LIMP_FLG_PEAT); //Solo para las peatonales permite dejar un lado sin apuntar + modo_solouno=FALSE; + lejos=0; + //Calcula la distancia del principio y del final a la nw + for(k=0;ktipo_ambit;k++) + { + dist_aux2 = Colv_geom::dist_pto_pto((double (*)[3])pt_amb[(npt_amb-1)*k], (double (*)[3])inww_amb[i_amb+k*n_amb].pt); + + if(dist_aux2n_amb; i++) + { + if(i==i_amb) + continue; + + if(olv_limp->ias[i].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + + if(olv_limp->tipo_ambit==OLV_AMB_LIN)//para tipo lineal, obtiene los primeros puntos de los dos extremos + { + npt_amb_aux = (*ob->lial)[(*ob->objt)[i].indx].n; + pt_amb_aux = &(*ob->ptos)[(*ob->lial)[(*ob->objt)[i].indx].indx]; + } + else if(olv_limp->tipo_ambit==OLV_AMB_PUN) //para tipo puntual, es un único punto + { + npt_amb_aux = 1; + pt_amb_aux = &(*ob->ptos)[(*ob->objt)[i].indx]; + } + + for(h=0;htipo_ambit;h++) + { + dist_aux=Colv_geom::dist_pto_pto((double (*)[3])pt_amb[(npt_amb-1)*k], (double (*)[3])pt_amb_aux[(npt_amb_aux-1)*h]); + if(dist_auxres_circlateral<=0) + return TRUE; + + char msg_[OLV_MAX_MSG_PROCE]; + char nfile[MAX_PATH]; + + strcpy_s(nfile,MAX_PATH,olv->paths.path_data); + cambiaext(nfile,".shp",".dbf"); + + + msg_[0]=0; + + ///////////////////LATELARIDAD + //recorres inww_amb_aux, que está ordenado por inw + //solo en puntuales + //si res_cirobjt)[inww_amb_aux[i].inw].ia].flgs & OLV_LIMP_FLG_CIRC_FT //fronto mismo sentido que lineal + //si lateral==derecha y amb a la izquierda, descarta + //amb -> ias[inww_amb_aux[ì].iamb].flgs & OLV_LIMP_FLG_DER + //o si lateral==izda y amb a la derecga, descarta + + for(int ia=0; ian_amb; ia++) + { + sent=0; + if(olv_limp->ias[(*olv_limp->olv->olv_ob->objt)[inww_amb_aux[ia].inw].ia].flgs & OLV_LIMP_FLG_CIRC_FT ) + sent++; + if(olv_limp->ias[(*olv_limp->olv->olv_ob->objt)[inww_amb_aux[ia].inw].ia].flgs & OLV_LIMP_FLG_CIRC_TF ) + sent++; + if(sent!=1) + continue; + //comprueba lateralidad + if(olv_limp->ias[inww_amb_aux[ia].iamb+olv_limp->n_ini_amb_iai].flgs & OLV_LIMP_FLG_DER)//ambito a la derecha + { + if(olv_limp->lateral==1) //lateralidad derecha + continue; + } + else//ambito a la izquierda + { + if(olv_limp->lateral==2) //lateralidad izquierda + continue; + } + + //lee el objectid del ámbito + olv_limp->olv->olv_sh->dame_col_int_dbf(nfile,inww_amb_aux[ia].iamb,inww_amb_aux[ia].iamb+1,&id,"OBJECTID",err_str,OLV_MAX_ERR); + wgeolog(LOG_TODO,"olv_limp_t","Ámbito %ld lateralidad errónea",id); + + //imprime + if(msg_[0]==0) + sprintf_s(msg_,OLV_MAX_MSG_PROCE,"Encontrados contenedores con lateralidad errónea: "); + if(sigue_msg) + sprintf_s(msg_,OLV_MAX_MSG_PROCE,"%s %ld,",msg_,id); + if(sigue_msg && strlen(msg_)+10>=OLV_MAX_MSG_PROCE) + sigue_msg=FALSE;//para que no se pase del largo + + } + if(!sigue_msg && ((strlen(msg_)+5)olv->olv_ob; + KK=olv_limp->tipo_ambit; + npt_nw_aux=0; + log_debug=FALSE; + mal=FALSE; + inww_amb_aux=NULL; + ///////////////// + wgeolog(LOG_TODO,"olv_limp_t","Generando topología con los segmentos de unión"); + pon_mi_progre(OLV_TAREA_TOPO_NW, 0); + pon_mi_msg(""); + err_str[0]=0; + + //inicializa la matriz auxiliar para ordenación + inww_amb_aux = (Info_inw_dmin *)malloc(olv_limp->n_amb*KK*sizeof(Info_inw_dmin)); + if(!inww_amb_aux) + { + pon_mi_msg("Error, sin memoria para matriz de índices\nde ámbitos a carreteras"); + return FALSE; + } + memcpy(inww_amb_aux,olv_limp->inww_amb,olv_limp->n_amb*KK*sizeof(Info_inw_dmin)); + + ////////////////////////////////////////////////// + //ordena la matriz de info de inw, va de punto más cercano + //al inicio del inw inicial al más lejano, y aumentando en inw + //dentro del mismo inw, ordena por ip y a igual ip, por lamb + qsort(inww_amb_aux,olv_limp->n_amb*KK,sizeof(Info_inw_dmin),Colv_limp_thr::compara_inww_amb); + + wgeolog(LOG_TODO,"olv_limp_t","Generando topología: Matriz de info de inw dmin ordenada:"); + if(log_debug) + { + for(ia=0;ian_amb*KK;ia++) + wgeolog(LOG_TODO,"olv_limp_t","ia %02d, inw %03d, ip %ld, lamb %lf",ia, + inww_amb_aux[ia].inw-olv_limp->n_ini_nw,inww_amb_aux[ia].ip,inww_amb_aux[ia].lamb); + } + + ////////////////////// + //mira a ver si tiene que replicar calles de doble sentido + if(!replica_doble_sent(inww_amb_aux, &olv_limp->ias, ob)) + { + pon_mi_msg("Errores al replicar doble sentido"); + return FALSE; + } + + //////////////////// + if(KK<2)//en recogida, se mira si hay que comprobar la lateralidad + comprueba_latelaridad(inww_amb_aux); + + //hay que volver a ordenar + qsort(inww_amb_aux,olv_limp->n_amb*KK,sizeof(Info_inw_dmin),Colv_limp_thr::compara_inww_amb); + /////////////// + + //////////////////////////////////////////////////////////////////////// + //Bucle por cada item del array inww_amb, para ir troceando las carreteras que cortan + ia=0; + while(ian_amb*KK && !pirate) + { + + /////////////////////////////// + ia_aux=ia; + inwi=inww_amb_aux[ia_aux].inw; + + if(olv_limp->ias[inww_amb_aux[ia_aux].iamb].flgs & OLV_LIMP_FLG_AMB_NO) + { + ia++; + continue; + } + if(inwin_ini_nw) //si es menor es que se ha reapuntado a otro ámbito por ser peatonal lejana + { + ia++; + continue; + } + inwil=(*ob->objt)[inwi].indx; + npt_nw = (*ob->lial)[inwil].n; + indx_nw=(*ob->lial)[inwil].indx; + pt_nw = &(*ob->ptos)[indx_nw]; + iaso=(*ob->objt)[inwi].ia; + /////////////////////////////// + if(npt_nw>MAXPTONW) + { + pt_nw_aux = (double (*)[3])realloc(pt_nw_aux,3*npt_nw*sizeof(double)); + if(!pt_nw_aux) + { + wgeolog(LOG_TODO,"olv_limp_t","Sin memoria en topo_nw"); + mal=TRUE; + break; + } + MAXPTONW=npt_nw; + } + memset(pt_nw_aux,0,3*MAXPTONW*sizeof(double)); + /////////////////////////////// + + iat=ia; + nt=1; + //primero cuenta los tramos de esa inwi, nt + while((ian_amb*KK) && (inww_amb_aux[ia].inw==inwi)) + { + ia++; + nt++; + } + + if(nt<2) //tiene que haber siempre mínimo 2 tramos, ya que en todos los inw de este array hay algún ámbito asignado + { + wgeolog(LOG_TODO,"olv_limp_t","Gen. Topo. Inw %03d mal, se obtienen %ld tramos, no suficientes",inwi-olv_limp->n_ini_nw,nt); + mal=TRUE; + ia++; + continue; + } + + if(log_debug) + wgeolog(LOG_TODO,"olv_limp_t","Gen. Topo. Inw %03d de %ld puntos se parte en %ld tramos",inwi-olv_limp->n_ini_nw,npt_nw,nt); + + //ya se saben los tramos, se va troceando la carretera + ia=iat; + iat=0; + inww_amb_aux[ia].flgs=nt; + while(iatMAXPTONW) + { + wgeolog(LOG_TODO,"olv_limp_t","Gen. Topo. Inw %03d mal, se excede máximo de puntos",inwi-olv_limp->n_ini_nw); + mal=TRUE; + ia++; + iat++; + continue; + } + if(memcmp(&pt_nw[0],&inww_amb_aux[ia].pt,3*1*sizeof(double))==0) + { + //no se hace tramo porque está unido por el extremo + inww_amb_aux[ia].flgs--; + iat++; + ia++; + if(nt==2) + { + iat++;//si solo eran dos tramos, pasa + ia++; + } + continue; + } + //los primeros puntos son los de la carretera hasta el ámbito + memcpy(&pt_nw_aux[0],&pt_nw[0],3*(npt_nw_aux-1)*sizeof(double)); + //el punto final es el del ámbito + memcpy(&pt_nw_aux[npt_nw_aux-1],&inww_amb_aux[ia].pt,3*1*sizeof(double)); + + if(log_debug) + wgeolog(LOG_TODO,"olv_limp_t","Gen. Topo. Inw %03d, tramo inicial %ld, %ld puntos, ip %ld, ia %ld",inwi-olv_limp->n_ini_nw,iat, + npt_nw_aux,inww_amb_aux[ia].ip,ia); + } + else if(iat==(nt-1))//hace el último tramo, del último ámbito al extremo final + { + npt_nw_aux=npt_nw-inww_amb_aux[ia-1].ip; + if(npt_nw_aux>MAXPTONW) + { + wgeolog(LOG_TODO,"olv_limp_t","Gen. Topo. Inw %03d mal, se excede máximo de puntos",inwi-olv_limp->n_ini_nw); + mal=TRUE; + ia++; + iat++; + continue; + } + if(memcmp(&pt_nw[npt_nw-1],&inww_amb_aux[ia-1].pt,3*1*sizeof(double))==0) + { + //no se hace tramo porque está unido por el extremo + inww_amb_aux[ia-1].flgs--; + iat++; + ia++; + continue; + } + //el primer punto es el del ámbito anterior + memcpy(&pt_nw_aux[0],&inww_amb_aux[ia-1].pt,3*1*sizeof(double)); + //los siguientes puntos son los de la carretera hasta el final + memcpy(&pt_nw_aux[1],&pt_nw[inww_amb_aux[ia-1].ip+1],3*(npt_nw_aux-1)*sizeof(double)); + + if(log_debug) + wgeolog(LOG_TODO,"olv_limp_t","Gen. Topo. Inw %03d, tramo final %ld, %ld puntos, ip %ld, ia %ld",inwi-olv_limp->n_ini_nw,iat, + npt_nw_aux,inww_amb_aux[ia-1].ip+1,ia-1); + } + else //hace los tramos de enmedio + { + npt_nw_aux=inww_amb_aux[ia].ip-inww_amb_aux[ia-1].ip+2; + if(npt_nw_aux>MAXPTONW) + { + wgeolog(LOG_TODO,"olv_limp_t","Gen. Topo. Inw %03d mal, se excede máximo de puntos",inwi-olv_limp->n_ini_nw); + mal=TRUE; + ia++; + iat++; + continue; + } + //el primer punto es el del primer ámbito + memcpy(&pt_nw_aux[0],&inww_amb_aux[ia-1].pt,3*1*sizeof(double)); + //los siguientes puntos son los de la carretera + memcpy(&pt_nw_aux[1],&pt_nw[inww_amb_aux[ia-1].ip+1],3*(npt_nw_aux-2)*sizeof(double)); + //el último punto es el del ámbito siguiente + memcpy(&pt_nw_aux[npt_nw_aux-1],&inww_amb_aux[ia].pt,3*1*sizeof(double)); + + if(log_debug) + wgeolog(LOG_TODO,"olv_limp_t","Gen. Topo. Inw %03d, tramo medio %ld, %ld puntos, ip %ld, ia %ld",inwi-olv_limp->n_ini_nw,iat, + npt_nw_aux,inww_amb_aux[ia].ip,ia); + } + + iat++; + ia++; + //añade el tramo al ob, le pone el índice a la misma info asociada que la carretera original + if(olv_limp->ias[iaso].flgs & OLV_LIMP_FLG_AMB) + icla=OLV_ICLA_LIN_AMB;//por si está troceando ámbito peatonal + else if(olv_limp->ias[iaso].flgs & OLV_LIMP_FLG_NW_REP) + icla=OLV_ICLA_LIN_NW_REP; + else + icla=OLV_ICLA_LIN_NW; + Colv_geom::pon_lin(npt_nw_aux, (double (*)[][3])pt_nw_aux, icla, iaso, ob); + + //reapunta al inw por si ha habido reallocs en pon_obj + inwi=inww_amb_aux[ia_aux].inw; + inwil=(*ob->objt)[inwi].indx; + npt_nw = (*ob->lial)[inwil].n; + indx_nw=(*ob->lial)[inwil].indx; + pt_nw = &(*ob->ptos)[indx_nw]; + iaso=(*ob->objt)[inwi].ia; + } + ia--; //decrementa para cuando se ha pasado + + if((ia%100==0) || (ia==(olv_limp->n_amb*KK))) + { + wgeolog(LOG_TODO,"olv_limp_t","Generando topología, %ld de %ld",ia,olv_limp->n_amb*KK); + //avisa de progreso + pon_mi_progre(OLV_TAREA_TOPO_NW, (int) ((OliviaDef::GeneralDef::ProgrMax* + 1.0*(ia)/(olv_limp->n_amb*KK)))); + } + } + if(mal) + { + pon_mi_msg("Errores en el análisis topológico"); + } + if(mal || pirate) + { + if(inww_amb_aux) + free(inww_amb_aux); + return FALSE; + } + + //borra los nw que ha dividido en tramos + //que son los que estaban asignados a los ámbitos + //recorriendo el array de infos para borrar solo dichos inwi + ia=0; + int nnul=0; + while(ian_amb*KK) + { + /////////////////////////////// + inwi=inww_amb_aux[ia].inw; + if(olv_limp->ias[inww_amb_aux[ia].iamb].flgs & OLV_LIMP_FLG_AMB_NO) + { + ia++; + continue; + } + iaso=(*ob->objt)[inwi].ia; + if((inwi<0) || (inwin_ini_nw) || (inww_amb_aux[ia].flgs<2)) + { + ia++; + continue; + } + + (*ob->objt)[inwi].flags[1] = (*ob->objt)[inwi].flags[1] | B1_OBJ_NULO; + nnul++; + //avanza hasta el siguiente inwi + while((ian_amb*KK) && (inww_amb_aux[ia].inw==inwi)) + { + ia++; + } + } + + ob->limpia(); + ia=0; + //cuenta cuántas entidades lineales se han quedado en la red + for(inwi=0;inwiolv->olv_ob->vect.nobj;inwi++) + { + if((*ob->objt)[inwi].tipo==OBJ_LINEAL) + ia++; + + } + + wgeolog(LOG_TODO,"olv_limp_t","Generada topología, %ld entidades lineales en la red",ia); + + if(inww_amb_aux) + free(inww_amb_aux); + + if(!pon_nodos_planta(olv_limp->coor_instal)) + { + pon_mi_msg("Error, No se ha podido incluir planta en red"); + return FALSE; + } + + return TRUE; +} +//************************************************************************************* +/** + * Compara las estructuras inww_amb. Las ordena por inw, a mismo inw por ip, y a mismo ip por lamb + */ +int Colv_limp_thr::compara_inww_amb (const void * a, const void * b) +{ + //si ainw - ((Info_inw_dmin*) b)->inw; + if(r==0) + { + //a mismo inw, es menor el de menor ip + r=((Info_inw_dmin*) a)->ip - ((Info_inw_dmin*) b)->ip; + if(r==0) + { + //a mismo ip, es menor el de menor lamb + dd=((Info_inw_dmin*) a)->lamb - ((Info_inw_dmin*) b)->lamb; + if(dd<0) + r=-1; + else if(dd>0) + r=1; + else + r=0; + } + } + + return r; +} +//************************************************************************************* +/** + * Añade a la red de conjunciones en qué conjunción está la planta y la instalación + */ +BOOL Colv_limp_thr::pon_nodos_planta(double pt[3]) +{ + int il,npts,indx,i,npts_aux,no; + short ip; + double (*ptos)[3],pt_proy_nw[3]; + Cobgeo *ob; + double d, dmin; + float lamb; + BOOL mal =FALSE; + int MAXPTONW; + double (*ptos_aux)[3]=NULL; + Info_inw_dmin inww; + + ob=olv_limp->olv->olv_ob; + no=ob->vect.nobj; + + if((pt[0]==0) && (pt[1]==0)) + return TRUE;//no hay instalación, no se pone + + //////////////////////////////////////////////////////////////////////// + //Bucle por cada carretera de la nw + + dmin=MAYUSCULO; + for(i=0; iobjt)[i].tipo != OBJ_LINEAL) + continue; + if(olv_limp->ias[(*ob->objt)[i].ia].flgs & OLV_LIMP_FLG_NO_NW) + continue; + + il=(*ob->objt)[i].indx; + npts = (*ob->lial)[il].n; + indx=(*ob->lial)[il].indx; + ptos = &(*ob->ptos)[indx]; + + //calcula la distancia al punto de la instalación + d = Colv_geom::dist_pto_poli((double (*)[3])pt,(double (*)[][3])ptos,npts,&ip, &lamb); + if(d=MAYUSCULO) + return FALSE; + + ///////////////////////////////////////////////// + //ya tiene el inw de la distancia mínima + + //apunta al que ha encontrado mínimo + il=(*ob->objt)[inww.inw].indx; + npts = (*ob->lial)[il].n; + indx=(*ob->lial)[il].indx; + ptos = &(*ob->ptos)[indx]; + + //calcula el punto del inw donde se da el mínimo + pt_proy_nw[2]=0; + pt_proy_nw[0]=ptos[inww.ip][0]+(ptos[inww.ip+1][0]-ptos[inww.ip][0])*inww.lamb; + pt_proy_nw[1]=ptos[inww.ip][1]+(ptos[inww.ip+1][1]-ptos[inww.ip][1])*inww.lamb; + + //sustituye las coords por el punto proyectado en la nw + memcpy(pt,pt_proy_nw,3*sizeof(double)); + + if(!Colv_geom::pon_pto((double (*)[3])pt_proy_nw, 10001, -1, ob)) + return FALSE; + + //hace dos tramos + //apunta al que ha encontrado mínimo + il=(*ob->objt)[inww.inw].indx; + indx=(*ob->lial)[il].indx; + ptos = &(*ob->ptos)[indx]; + //primer tramo + npts_aux=inww.ip+2; + MAXPTONW = max(npts_aux,npts-inww.ip); + ptos_aux = (double (*)[3])malloc(3*MAXPTONW*sizeof(double)); + if(!ptos_aux) + return FALSE; + memset(ptos_aux,0,3*MAXPTONW*sizeof(double)); + //los primeros puntos son los de la carretera hasta el ámbito + memcpy(ptos_aux[0],ptos[0],3*(npts_aux-1)*sizeof(double)); + //el punto final es el del ámbito + memcpy(ptos_aux[npts_aux-1],pt_proy_nw,3*1*sizeof(double)); + + if(!Colv_geom::pon_lin(npts_aux, (double (*)[][3])ptos_aux, OLV_ICLA_LIN_NW_REP, (*ob->objt)[inww.inw].ia, ob)) + { + free(ptos_aux); + return FALSE; + } + + //////////////////////////////// + //segundo tramo + //apunta al que ha encontrado mínimo + il=(*ob->objt)[inww.inw].indx; + indx=(*ob->lial)[il].indx; + ptos = &(*ob->ptos)[indx]; + /// + memset(ptos_aux,0,3*MAXPTONW*sizeof(double)); + npts_aux=npts-inww.ip; + //el primer punto es el del ámbito anterior + memcpy(ptos_aux[0],pt_proy_nw,3*1*sizeof(double)); + //los siguientes puntos son los de la carretera hasta el final + memcpy(ptos_aux[1],ptos[inww.ip+1],3*(npts_aux-1)*sizeof(double)); + + if(!Colv_geom::pon_lin(npts_aux, (double (*)[][3])ptos_aux, OLV_ICLA_LIN_NW_REP, (*ob->objt)[inww.inw].ia, ob)) + { + free(ptos_aux); + return FALSE; + } + + (*ob->objt)[inww.inw].flags[1] = (*ob->objt)[inww.inw].flags[1] | B1_OBJ_NULO; + if(!ob->limpia()) + { + free(ptos_aux); + return FALSE; + } + + free(ptos_aux); + return TRUE; +} +//************************************************************************************* +/** + * Apunta en qué nodos está la planta y la instalación + */ +BOOL Colv_limp_thr::busca_conjs_planta(Info_conjs *conjs, double pt[3], int *nod) +{ + int ic; + Cobgeo *ob; + BOOL mal=FALSE; + + ob=olv_limp->olv->olv_ob; + + if((pt[0]==0) && (pt[1]==0)) + return TRUE;//no hay instalación, no se pone + + //busca ese punto en la lista de conjunciones + //busca la conjunción en la lista + //lo hace para los dos extremos de la línea + for(ic=0; icn;ic++) + { + if((Colv_geom::pto_equals(pt,conjs->coor[ic]))) + break; + } + if(ic==conjs->n) + { + return FALSE; + } + *nod=ic; + + return TRUE; +} +//************************************************************************************* +/** + * Lanza sub-threads + */ +void Colv_limp_thr::lanza_subthrs(int tar, int nthr_def/*=-1*/) +{ + char nomb[32]; + Param_olv_limp_thr pp; + int nn; + if((nthr_def>0) && (nthr_defthr_padre=this; + subthrs[i]->n_subthr = nn; + subthrs[i]->prog_subthr = 0; + subthrs[i]->pirate=FALSE; + subthrs[i]->inicia(OLV_MILIS_COLA,&cola_proc,-1,nomb); + subthrs[i]->encola(tar,&pp,FALSE); + } +} +//************************************************************************************* +/** + * Para sub-threads + */ +void Colv_limp_thr::para_subthrs() +{ + //Para los subthreads + for(int i=0;ipirate=pirate; + subthrs[i]->termina(); + } + } +} +//************************************************************************************* +/** + * Rellena la matriz de costes entre todas las conjunciones + */ +BOOL Colv_limp_thr::calcula_cost_conj() +{ + int i, j; + //////////////// + + wgeolog(LOG_TODO,"olv_limp_t","Rellenando matriz de costes entre conjunciones"); + pon_mi_progre(OLV_TAREA_COST_AMB, 0); + pon_mi_msg(""); + err_str[0]=0; + + //calcula el número de nodos de la red + //que es el número de intersecciones de la red navegable, incluyendo el número de ámbitos x2 porque + //aparecen el punto del ámbito y el proyectado en la carretera más próxima (y x2 si son lineales) + wgeolog(LOG_TODO,"olv_limp_t","Comienza a buscar conjunciones"); + if(!busca_conjs(olv_limp->tipo_ambit, olv_limp->ias, olv_limp->olv->olv_ob,&olv_limp->conjs)) + { + pon_mi_msg("Error, sin memoria para matriz de conjunciones en busca_conjs"); + return FALSE; + } + + //pide memoria para el array de distancias entre conjunciones + ///mira a ver con cuántos nvect puede calcular la matriz + CoptiMemo oo; + int nvect = oo.calc_nvect_master(olv_limp->conjs.n); + if(nvect<0) + { + pon_mi_msg("Error, sin memoria para matriz de conjunciones en cálculo de nvect"); + return FALSE; + } + wgeolog(LOG_TODO,"olv_limp_t","Se va a ejecutar con nvect=%ld de %ld",nvect,olv_limp->conjs.n); + olv_limp->cost_conj.clear(); + olv_limp->tip_conj.clear(); + olv_limp->cost_conj.inicializa(olv_limp->conjs.n,n_subthr,nvect); + olv_limp->tip_conj.inicializa(olv_limp->conjs.n,n_subthr,nvect); + + //revisa las calles cortadas, y les pone que son tipo doble sentido a sus replicas + for(i=0;iconjs.n;i++) + { + if(olv_limp->conjs.inc[i].n==1) + { + //busca las que tienen esa calle y les cambia el flag + for(j=0;jolv->olv_ob->vect.nobj;j++) + { + if(((*olv_limp->olv->olv_ob->objt)[j].tipo == OBJ_LINEAL) && + (!(olv_limp->ias[(*olv_limp->olv->olv_ob->objt)[j].ia].flgs & OLV_LIMP_FLG_NO_NW)) && + (olv_limp->ias[(*olv_limp->olv->olv_ob->objt)[j].ia].ishp==olv_limp->conjs.inc[i].inw0) && + (olv_limp->ias[(*olv_limp->olv->olv_ob->objt)[j].ia].flgs & (OLV_LIMP_FLG_CIRC_FT | OLV_LIMP_FLG_CIRC_TF))) + olv_limp->ias[(*olv_limp->olv->olv_ob->objt)[j].ia].flgs &= ~OLV_LIMP_FLG_CIRC_FT & ~OLV_LIMP_FLG_CIRC_TF; + } + } + } + + //lanza los threads + lanza_subthrs(OLV_LIMP_EV_COST_CONJ_SUB); + + return TRUE; +} +//************************************************************************************* +/** + * Comprueba la memoria para las conjunciones + */ +BOOL Colv_limp_thr::add_conj(Info_conjs *conjs, double coor[3]) +{ + if(!cuida_memo_conj(conjs)) + return FALSE; + + memcpy(conjs->coor[conjs->n],coor,3*sizeof(double)); + conjs->n++; + + return TRUE; +} +//************************************************************************************* +/** + * Comprueba la memoria para las conjunciones + */ +BOOL Colv_limp_thr::cuida_memo_conj(Info_conjs *conjs) +{ + double (*coor2)[3]; + Info_conjs_inw *inc2; + + if((conjs->n+1)>conjs->m) + { + conjs->m+=OLV_LIMP_M_CONJ; + + //primero las coordenadas + coor2 = (double (*)[3])realloc(conjs->coor,conjs->m*3*sizeof(double)); + if(!coor2) + { + free(conjs->coor); + return FALSE; + } + conjs->coor=coor2; + memset(&conjs->coor[conjs->m-OLV_LIMP_M_CONJ],0,OLV_LIMP_M_CONJ*3*sizeof(double)); + + //primero las incidencias + inc2 = (Info_conjs_inw *)realloc(conjs->inc,conjs->m*sizeof(Info_conjs_inw)); + if(!inc2) + { + free(conjs->inc); + return FALSE; + } + conjs->inc=inc2; + //inicializa + for(int i=conjs->m-OLV_LIMP_M_CONJ;im;i++) + { + conjs->inc[i].n=conjs->inc[i].inw0=-1; + } + } + + return TRUE; +} +//************************************************************************************* +/** + * Rellena la matriz de conjunciones entre la red navegable. + * Que está almacenada en 'ob', y la info de las conjunciones se rellena en 'conjs' + */ +BOOL Colv_limp_thr::busca_conjs(int KK, Info_aso *ias, Cobgeo *ob, Info_conjs *conjs) +{ + int i,il,npt,ic,k,ics[2],io,nn; + double (*ptos)[3]; + BOOL mal=FALSE; + BOOL log_debug=FALSE; + BOOL modo_ejes=FALSE; + + if(!ob || !conjs) + return FALSE; + + if((olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoMh_eje) || + (olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoM2h_eje)) + modo_ejes=TRUE; + + //bucle por cada entidad de la carto + //si es modos de ámbitos normales, lineales o puntuales, se va de inicio a final del obg, en orden + //y se van buscando las conjs de los ámbitos, los nw, y los segmentos + //si es un modo en el que los ámbitos son ejes, se va al revés, añadiendo primero las conjunciones de + //los segmentos y la nw, y por último las de los ejes. Se hace para que en el siguiente paso, al buscar, + //aparezca primero la conjunción de la carretera, porque es de la que no se tiene constancia ic_ini/ic_fin + io=0; + if(modo_ejes) + i=ob->vect.nobj-1; + else + i=0; + while((iovect.nobj) && !mal && !pirate) + { + if(((*ob->objt)[i].tipo == OBJ_LINEAL) && !(((ias[(*ob->objt)[i].ia].flgs & OLV_LIMP_FLG_PEAT_SEG) || + (ias[(*ob->objt)[i].ia].flgs & OLV_LIMP_FLG_EJE_SEG)))) + { + //almacena las coordenadas ordenadas en el array de conjs si no están ya + il=(*ob->objt)[i].indx; + npt = (*ob->lial)[il].n; + ptos = &(*ob->ptos)[(*ob->lial)[il].indx]; + + for(k=0; k<2; k++) + { + if((ias[(*ob->objt)[i].ia].flgs & OLV_LIMP_FLG_PEAT_REP) || + (ias[(*ob->objt)[i].ia].flgs & OLV_LIMP_FLG_EJE) ) + { + //en estos casos replica las conjunciones + //llega la segunda vez + ic=conjs->n; + if(!add_conj(conjs,ptos[k*(npt-1)])) + { + mal=TRUE; + break; + } + } + else + { + //busca la conjunción en la lista + //lo hace para los dos extremos de la línea + for(ic=0; icn;ic++) + { + if((Colv_geom::pto_equals(ptos[k*(npt-1)],conjs->coor[ic]))) + break; + } + if(ic==conjs->n) + { + //no lo ha encontrado, lo añade + if(!add_conj(conjs,ptos[k*(npt-1)])) + { + mal=TRUE; + break; + } + } + if(log_debug) + wgeolog(LOG_TODO,"olv_limp_t","Conjunción %04ld, io %04d, x %lf y %lf",ic, + i,ptos[k*(npt-1)][0],ptos[k*(npt-1)][1]); + } + ics[k]=ic; + + //si es carretera, le pone a la conjunción que llega una al menos + if(!(ias[(*ob->objt)[i].ia].flgs & OLV_LIMP_FLG_NO_NW)) + { + if(conjs->inc[ic].n<0) + { + conjs->inc[ic].n=1; + conjs->inc[ic].inw0=ias[(*ob->objt)[i].ia].ishp; + } + else + conjs->inc[ic].n++; + } + } + + /////////////////////////////////////////////////////////////////////// + //////aprovecha para apuntar el índice de la conjunción de sus extremos + //////en todos los casos excepto en carreteras + //tampoco lo hace para los segmentos de unión entre ámbitos + if((ias[(*ob->objt)[i].ia].flgs & + (OLV_LIMP_FLG_AMB | OLV_LIMP_FLG_SEG_PUN | OLV_LIMP_FLG_SEG_LIN | OLV_LIMP_FLG_PEAT_REP)) /*&& + !(ias[(*ob->objt)[i].ia].flgs & OLV_LIMP_FLG_SEG_AMB)*/) + { + ias[(*ob->objt)[i].ia].ic_ini=ics[0]; + ias[(*ob->objt)[i].ia].ic_fin=ics[1]; + if(ias[(*ob->objt)[i].ia].flgs & OLV_LIMP_FLG_SEG_PUN ) + { + //si es segmento de ámbito puntual, el extremo final del segmento corresponde al ámbito puntual + ias[ias[(*ob->objt)[i].ia].ishp].ic_fin=ias[ias[(*ob->objt)[i].ia].ishp].ic_ini=ics[1]; + } + if(ias[(*ob->objt)[i].ia].flgs & OLV_LIMP_FLG_PEAT_REP) + { + nn=olv_limp->n_peat; + //si es segmento de ámbito replicado, se ponen sus extremos a mano desde el ámbito replicado + ias[(*ob->objt)[i].ia+nn].ic_ini=ias[ias[(*ob->objt)[i].ia].info0].ic_ini; + ias[(*ob->objt)[i].ia+nn].ic_fin=ics[0]; + ias[(*ob->objt)[i].ia+2*nn].ic_ini=ias[ias[(*ob->objt)[i].ia].info0].ic_fin; + ias[(*ob->objt)[i].ia+2*nn].ic_fin=ics[1]; + } + } + if(log_debug) + wgeolog(LOG_TODO,"olv_limp_t","Ámb %03ld, conj %ld %ld",i,ics[0],ics[1]); + } + + if(modo_ejes) + i--; + else + i++; + io++; + + /////////////////////////////////////////////////////////////////////// + + } + if(iovect.nobj || mal) + { + wgeolog(LOG_TODO,"olv_limp_t","Error, sin memoria para matriz de conjunciones en busca_conjs"); + return FALSE; + } + + if(pirate) + return FALSE; + + if(modo_ejes) + { + for(io=0;iovect.nobj;io++) + { + if(((*ob->objt)[io].tipo != OBJ_LINEAL) || ((*ob->objt)[io].ia<0)) + continue; + if(!(ias[(*ob->objt)[io].ia].flgs & OLV_LIMP_FLG_EJE_SEG)) + continue; + + i=ias[(*ob->objt)[io].ia].ishp; + il=(*ob->objt)[i].indx; + npt = (*ob->lial)[il].n; + ptos = &(*ob->ptos)[(*ob->lial)[il].indx]; + //k=0 son inicios, k=1 son finales + k=0; + for(ic=0; icn && k<2;ic++) + { + if(Colv_geom::pto_equals(ptos[k*(npt-1)],conjs->coor[ic])) + { + ics[k]=ic; + k++; + ic=-1;//reinicia + } + } + if(ic==conjs->n) + { + break; + } + + ias[olv_limp->n_ini_amb_iai+i].ic_ini=ics[0]; + ias[olv_limp->n_ini_amb_iai+i].ic_fin=ias[i].ic_ini; + ias[olv_limp->n_ini_amb_iaf+i].ic_ini=ics[1]; + ias[olv_limp->n_ini_amb_iaf+i].ic_fin=ias[i].ic_fin; + + /*wgeolog(LOG_TODO,"olv_limp_t","ishp %ld ini_ini %ld ini_fin %ld fin_in %ld fin-fin %ld", + i,ics[0],ias[i].ic[0],ics[1],ias[i].ic[1]);*/ + + + } + if(iovect.nobj) + { + wgeolog(LOG_TODO,"olv_limp_t","Error, no se pudo asignar segmentos"); + return FALSE; + } + } + + if(pirate) + return FALSE; + + wgeolog(LOG_TODO,"olv_limp_t","Encontradas %ld conjunciones en la red navegable",conjs->n); + + wgeolog(LOG_TODO,"olv_limp_t","Comienza a buscar las conjunciones de la planta"); + + if(!busca_conjs_planta(conjs,olv_limp->coor_instal, &olv_limp->nod_instal)) + { + wgeolog(LOG_TODO,"olv_limp_t","No se ha podido encontrar los nodos de la planta"); + return FALSE; + } + wgeolog(LOG_TODO,"olv_limp_t","Encontradas las conjunciones de la planta"); + + return TRUE; +} +//************************************************************************************* +/** + * Rellena la matriz de distancias entre todas las conjunciones. + * El thread entra aquí cuando los subthreads que realizan la tarea realmente han finalizado + */ +BOOL Colv_limp_thr::calcula_cost_conj_fin() +{ + //////////////// + //para los threads + para_subthrs(); + //olv_limp->cost_conj.memAjust(); + wgeolog(LOG_TODO,"olv_limp_t","FIN Matriz de dist entre conjs %ldx%ld", + olv_limp->conjs.n,olv_limp->conjs.n); + + /*//mira a ver si tiene que ser multitask o no + INT64 sdj = olv_limp->conjs.n*olv_limp->conjs.n*sizeof(float); + if(sdj>=(INT64)OLV_TASKS_MAXMEMNOMULTI) + olv->modo_multitask=TRUE;*/ + /////////////////////////////// + if(olv_limp->res_circ==OLV_RES_NO) + { + //va directo a cost_amb, calcula ahora si va a ser multitask o no + //calcula si puede ser multitask o no + CoptiMemo oo; + olv->modo_multitask=oo.is_multi(olv_limp->conjs.n,n_subthr,sizeof(Djkt_elem_cola)); + } + //////////////////////////////// + + return TRUE; +} +//************************************************************************************* +/** + * Rellena la matriz de distancias entre todas las conjunciones, es la parte de cálculos que + * realizan los subthreads. 'ithr' indica qué thread es, para calcular qué conjunciones le tocan. + */ +void Colv_limp_thr::calcula_cost_conj_sub(int ithr) +{ + int ic,il,npt,KK,nc,nd,i,k,ics[2]; + int n_ini, n_desp, n_fin, seg; + float cost,cost2; + Cobgeo *ob; + double (*ptos)[3]; + BOOL mal=FALSE; + Param_olv_limp_thr pp; + Info_aso *ias; + float costaux,cost2aux; + + //////////////// + mal=FALSE; + pp.id_e=OLV_TAREA_COST_AMB;//manda de parámetro la tarea de la que es el progreso + KK=olv_limp->tipo_ambit; + ob=olv_limp->olv->olv_ob; + n_desp = (int)ceil(1.0*(ob->vect.nobj)/n_subthr); + n_ini=ithr*n_desp; + n_fin = min((ithr+1)*n_desp,ob->vect.nobj); + cost=cost2=0; + nc=nd=0; + ias=olv_limp->ias; + //////////////// + + wgeolog(LOG_TODO,"olv_limp_t","Subthr %ld, Entidades %04d a %04d", ithr,n_ini, n_fin); + + seg = GetTickCount(); + ///////////////////////////////////// + //bucle por cada entidad de la carto + for(i=n_ini; iobjt)[i].ia<0) + continue; + if((ias[(*ob->objt)[i].ia].flgs & + (OLV_LIMP_FLG_AMB | OLV_LIMP_FLG_SEG_PUN | OLV_LIMP_FLG_SEG_LIN | OLV_LIMP_FLG_PEAT_REP | + OLV_LIMP_FLG_PEAT_SEG | OLV_LIMP_FLG_EJE_SEG)) && !(ias[(*ob->objt)[i].ia].flgs & OLV_LIMP_FLG_SEG_AMB)) + { + //si es tipo ámbito o segmento ya se tiene sus conjunciones apuntadas + ics[0]=ias[(*ob->objt)[i].ia].ic_ini; + ics[1]=ias[(*ob->objt)[i].ia].ic_fin; + } + else + { + //es una carretera, hay que buscar sus conjunciones + il=(*ob->objt)[i].indx; + npt = (*ob->lial)[il].n; + ptos = &(*ob->ptos)[(*ob->lial)[il].indx]; + + for(k=0; k<2; k++) + { + //lo hace para los dos extremos de la línea + for(ic=0; icconjs.n;ic++) + { + if(Colv_geom::pto_equals(ptos[k*(npt-1)],olv_limp->conjs.coor[ic])) + break; + } + if(ic>=olv_limp->conjs.n) + { + mal=TRUE; + break; + } + ics[k]=ic; + } + } + /////////////////// + //pone en el array de tipos qué es + //olv_limp->tip_conj[ics[0]][ics[1]]=olv_limp->tip_conj[ics[1]][ics[0]]=i; + olv_limp->tip_conj.set(ics[0],ics[1],i); + olv_limp->tip_conj.set(ics[1],ics[0],i); + /////////////////////////////////// + nd+=2; + //ya tiene una línea y sus dos extremos ic e ic2 localizados, calcula el coste + calcula_cost(i,ob,olv_limp->ias,&cost,&cost2); + + //añade los costes a la matriz + if(cost>olv_limp->cost_conj[ics[0]][ics[1]]) + cost=olv_limp->cost_conj[ics[0]][ics[1]]; + //olv_limp->cost_conj[ics[0]][ics[1]]=min(cost,olv_limp->cost_conj[ics[0]][ics[1]]); + olv_limp->cost_conj.set(ics[0],ics[1], min(cost,olv_limp->cost_conj[ics[0]][ics[1]])); + + if(cost2>olv_limp->cost_conj[ics[1]][ics[0]]) + cost2=olv_limp->cost_conj[ics[1]][ics[0]]; + olv_limp->cost_conj.set(ics[1],ics[0],min(cost2,olv_limp->cost_conj[ics[1]][ics[0]])); + + /////////////////////////////////// + if(FALSE) + { + if(cost>=MAYUSCULO) + costaux=-1; + else + costaux=cost; + if(cost2>=MAYUSCULO) + cost2aux=-1; + else + cost2aux=cost2; + wgeolog(LOG_TODO,"olv_limp_t","Subthr %ld, io %04d, cost %03.3f cost2 %03.3f",ithr,i,costaux,cost2aux); + } + ///////////////////////////////////// + + //avisa de progreso + if(((i-n_ini)%800==0) || ((i-n_ini)==(n_desp-1))) + { + wgeolog(LOG_TODO,"olv_limp_t","Subthr %ld, Rellenando matriz de dist entre conjs %ld de %ld", ithr, + (i-n_ini+1),n_desp); + //avisa de progreso + prog_subthr=((1.0*(i-n_ini+1)/n_desp)+0)/3;///3 porque es la tercera parte del progreso los costes de conjunciones y la otra mitad los costes de ámbitos + thr_padre->encola(OLV_LIMP_EV_SUBTHR_PROG,&pp,FALSE); + } + } + + wgeolog(LOG_TODO,"olv_limp_t","Subthr %ld, Fin Matriz de dist entre conjs, %ld distancias, %.3f seg", ithr, nd,1.0*(GetTickCount()-seg)/1000); + + thr_padre->encola(OLV_LIMP_EV_COST_CONJ_FIN,NULL,FALSE); +} +//************************************************************************************* +/** + * Calcula el coste de la línea io, cost en sentido ida y cost2 en sentido vuelta + */ +void Colv_limp_thr::calcula_cost(int io, Cobgeo *ob, Info_aso *ias, float *cost, float *cost2) +{ + int il,ia, npt; + double (*ptos)[3]; + double ltot; + + *cost=*cost2=0; + //////////////////// + ia=(*ob->objt)[io].ia; + ltot=0; + if((*ob->objt)[io].tipo == OBJ_LINEAL) + { + il=(*ob->objt)[io].indx; + npt = (*ob->lial)[il].n; + ptos = &(*ob->ptos)[(*ob->lial)[il].indx]; + ltot=long_linea((double (*)[][3]) ptos,npt,NULL,NULL,NULL,NULL); + } + /////////////////// + olv_limp->dame_cost(ltot,ia,cost,cost2); +} +//************************************************************************************* +/** + * Rellena la matriz de ángulos entre las conjunciones adyacentes a una dada + */ +BOOL Colv_limp_thr::calcula_ang_conj() +{ + //////////////// + + wgeolog(LOG_TODO,"olv_limp_t","Rellenando matriz de ángulos entre conjunciones"); + pon_mi_progre(OLV_TAREA_COST_AMB, (int) (OliviaDef::GeneralDef::ProgrMax*1/3)); + pon_mi_msg(""); + err_str[0]=0; + + //pide memoria para el array de distancias entre conjunciones + olv_limp->ang_conj = new Djkt_ang_ady[olv_limp->conjs.n]; + + //lanza los threads + lanza_subthrs(OLV_LIMP_EV_ANG_CONJ_SUB); + + return TRUE; +} + +//************************************************************************************* +/** + * Rellena la matriz de ángulos entre todas las conjunciones. + * El thread entra aquí cuando los subthreads que realizan la tarea realmente han finalizado + */ +BOOL Colv_limp_thr::calcula_ang_conj_fin() +{ + //////////////// + //para los threads + para_subthrs(); + + revisa_calles_cortadas(); + + ////////////////////////////////// + //calcula si va a ser multitask o no + CoptiMemo oo; + olv->modo_multitask=oo.is_multi(olv_limp->conjs.n,n_subthr,sizeof(Djkt_elem_cola)); + ////////////////////////////////// + + wgeolog(LOG_TODO,"olv_limp_t","FIN Matriz de ang entre conjs %ldx%ld", + olv_limp->conjs.n,olv_limp->conjs.n); + return TRUE; +} +//************************************************************************************* +/** + * Rellena la matriz de ángulos entre todas las conjunciones adyacentes a una dada, es la parte de cálculos que + * realizan los subthreads. 'ithr' indica qué thread es, para calcular qué conjunciones le tocan. + */ +void Colv_limp_thr::calcula_ang_conj_sub(int ithr) +{ + Cobgeo *ob; + Param_olv_limp_thr pp; + + int i,j,nconj,KK,na,ic,nady; + int n_ini, n_desp, n_fin, seg; + BOOL mal=FALSE; + BYTE aa; + BYTE *conjs; + double ang; + + //////////////// + pp.id_e=OLV_TAREA_COST_AMB;//manda de parámetro la tarea de la que es el progreso + KK=olv_limp->tipo_ambit; + ob=olv_limp->olv->olv_ob; + nconj=olv_limp->conjs.n; + n_desp = (int)ceil(1.0*nconj/n_subthr); + n_ini=ithr*n_desp; + n_fin = min((ithr+1)*n_desp,nconj); + na=0; + conjs=NULL; + conjs=(BYTE*)malloc(olv_limp->conjs.n*sizeof(BYTE)); + if(!conjs) + mal=TRUE; + else + memset(conjs,0,olv_limp->conjs.n*sizeof(BYTE)); + //////////////// + + wgeolog(LOG_TODO,"olv_limp_t","Subthr %ld, Ángulos de conjunciones %04d a %04d", ithr,n_ini, n_fin); + + seg = GetTickCount(); + ///////////////////////////////////// + //bucle por cada conjunción de la carto + for(ic=n_ini; icconjs.n*sizeof(BYTE)); + //Busca conjunciones adyacentes + for(i=0;icost_conj[i][ic]>=MAYUSCULO) && (olv_limp->cost_conj[ic][i]>=MAYUSCULO)) + continue; + + //marca las conjunciones que son adyacentes + conjs[i]=1; + + for(j=i+1;jcost_conj[ic][j]>=MAYUSCULO) + { + continue; + } + + //marca las conjunciones que son adyacentes + conjs[j]=1; + } + + } + for(i=0;i16) + { + nady=nady; + } + //ya tiene las adyacentes de la conjunción ic, inicializa array de angulos + if(!olv_limp->ang_conj[ic].inicia(nady)) + { + mal=TRUE; + break; + } + //Busca conjunciones adyacentes + for(i=0;icost_conj[i][ic]>=MAYUSCULO) || (olv_limp->cost_conj[ic][j]>=MAYUSCULO)) + { + aa=0; + } + else + { + //si no hay restricciones de circulación, se pone que se el ángulo es ok siempre + //si no, se calcula, y el ángulo es ok si es menor que el ángulo límite + if(olv_limp->res_circ!=OLV_RES_NO) + { + ang=dame_ang_conj(ic,i,j); + aa=(ang<=olv_limp->ang_lim); + } + } + olv_limp->ang_conj[ic].pon_ang_i_j(i,j,aa); + + na++; + + } + } + + //avisa de progreso + if(((ic-n_ini)%500==0) || ((ic-n_ini)==(n_desp-1))) + { + wgeolog(LOG_TODO,"olv_limp_t","Subthr %ld, Rellenando matriz de ang entre conjs %ld de %ld", ithr, + (ic-n_ini+1),n_desp); + //avisa de progreso + prog_subthr=((1.0*(ic-n_ini+1)/n_desp)+1)/3;///3 porque es la tercera parte del progreso los costes de conjunciones + thr_padre->encola(OLV_LIMP_EV_SUBTHR_PROG,&pp,FALSE); + } + } + + if(conjs) + free(conjs); + + wgeolog(LOG_TODO,"olv_limp_t","Subthr %ld, Fin Matriz de ang entre conjs, %ld ángulos, %.3f seg", ithr, na,1.0*(GetTickCount()-seg)/1000); + + thr_padre->encola(OLV_LIMP_EV_ANG_CONJ_FIN,NULL,FALSE); +} +//************************************************************************************* +/** + * Devuelve el ángulo entre dos conjunciones + */ +double Colv_limp_thr::dame_ang_conj(int ic, int i, int j) +{ + int k,il,npts,indx; + double v1[2],v2[2],(*ptos)[3],ang; + Cobgeo *ob=olv_limp->olv->olv_ob; + int tip_conj = olv_limp->tip_conj[i][ic]; + ang=0; + if(i==j) + { + if(olv_limp->ias[(*ob->objt)[tip_conj].ia].flgs & + OLV_LIMP_FLG_NO_NW) + { + ang=0;//es un segmento o ámbito, sí se puede + } + else if(olv_limp->res_circ==OLV_RES_NO) + { + ang=0; + } + else + { + ang=OLV_PI;//ángulo de 180º en carretera y sigue sentidos, no se puede (excepto si es calle cortada, que se revisa luego) + } + } + else if((olv_limp->ias[(*ob->objt)[tip_conj].ia].flgs & + (OLV_LIMP_FLG_SEG_LIN|OLV_LIMP_FLG_SEG_PUN|OLV_LIMP_FLG_PEAT_SEG|OLV_LIMP_FLG_EJE_SEG)) || + (olv_limp->ias[(*ob->objt)[olv_limp->tip_conj[j][ic]].ia].flgs & + (OLV_LIMP_FLG_SEG_LIN|OLV_LIMP_FLG_SEG_PUN|OLV_LIMP_FLG_PEAT_SEG|OLV_LIMP_FLG_EJE_SEG))) + { + ang=0; + + } + else if((!(olv_limp->ias[(*ob->objt)[tip_conj].ia].flgs & + OLV_LIMP_FLG_NO_NW)) && (!(olv_limp->ias[(*ob->objt)[olv_limp->tip_conj[j][ic]].ia].flgs & + OLV_LIMP_FLG_NO_NW))) + { + //las dos son carretera, si por coste no se puede ir, + if(olv_limp->res_circias[(*ob->objt)[tip_conj].ia].ishp==olv_limp->ias[(*ob->objt)[olv_limp->tip_conj[ic][j]].ia].ishp) && + ((olv_limp->ias[(*ob->objt)[tip_conj].ia].flgs & OLV_LIMP_FLG_NW_REP) || (olv_limp->ias[(*ob->objt)[olv_limp->tip_conj[ic][j]].ia].flgs & OLV_LIMP_FLG_NW_REP))) + { + //si intenta ir de nw a réplica, pero de la misma calle + ang=OLV_PI; + } + else + { + + //calcula los puntos próximos a la conjunción + //llega aquí si es nw de doble sentido + il=(*ob->objt)[tip_conj].indx; + npts = (*ob->lial)[il].n; + indx=(*ob->lial)[il].indx; + ptos = &(*ob->ptos)[indx]; + if(Colv_geom::pto_equals(olv_limp->conjs.coor[ic], ptos[0])) + { + //la conjunción es el primer punto + for(k=0;k<2;k++) + { + v1[k]=ptos[1][k]-olv_limp->conjs.coor[ic][k]; + } + } + else + { + //la conjunción es el último punto + for(k=0;k<2;k++) + { + v1[k]=ptos[npts-2][k]-olv_limp->conjs.coor[ic][k]; + } + } + + //es carretera, calcula los puntos próximos a la conjunción + //llega aquí si es nw de doble sentido + il=(*ob->objt)[olv_limp->tip_conj[j][ic]].indx; + npts = (*ob->lial)[il].n; + indx=(*ob->lial)[il].indx; + ptos = &(*ob->ptos)[indx]; + if(Colv_geom::pto_equals(olv_limp->conjs.coor[ic], ptos[0])) + { + //la conjunción es el primer punto + for(k=0;k<2;k++) + { + v2[k]=ptos[1][k]-olv_limp->conjs.coor[ic][k]; + } + } + else + { + //la conjunción es el último punto + for(k=0;k<2;k++) + { + v2[k]=ptos[npts-2][k]-olv_limp->conjs.coor[ic][k]; + } + } + + ang=Colv_geom::ang_vect(v1,v2); + ang=OLV_PI-ang; + } + } + else + { + ang=0; + } + + return ang; +} +//************************************************************************************* +/** + * Resvisa los ángulos, de forma que si hay algún giro "prohibido" de 180º, en caso + * de que sean calles cortadas o sin salida, los pone a ok + */ +void Colv_limp_thr::revisa_calles_cortadas() +{ + int ic,i,j,k,nady; + if(olv_limp->res_circ==OLV_RES_NO) + return; + for(ic=0;icconjs.n;ic++) + { + nady=olv_limp->ang_conj[ic].nady; + for(i=0;iang_conj[ic].angs[i][j]) + { + //si el ángulo es prohibido, mira a ver si hay más conjunciones + for(k=0;kang_conj[ic].i_conjs[k]<0 || olv_limp->ang_conj[ic].i_conjs[k]>=olv_limp->conjs.n) + { + wgeolog(LOG_TODO,"olv_limp_t","Ojo ang_conj fuera de límites ic %ld, k %ld",ic,k); + continue; + } + if((olv_limp->ang_conj[ic].i_conjs[k]!=olv_limp->ang_conj[ic].i_conjs[i]) && + (olv_limp->ang_conj[ic].i_conjs[k]!=olv_limp->ang_conj[ic].i_conjs[j]) && + (olv_limp->cost_conj[ic][olv_limp->ang_conj[ic].i_conjs[k]]conjs.inc[olv_limp->ang_conj[ic].i_conjs[k]].n>1)) + break; + } + if(k>=nady)//estos nodos son los únicos que tiene para entrar y salir + { + olv_limp->ang_conj[ic].angs[i][j]=1; + } + } + } + } + } +} +//************************************************************************************* +/** + * Rellena la matriz de costes entre todos los ámbitos + */ +BOOL Colv_limp_thr::calcula_cost_amb() +{ + int i; + BOOL log_debug=FALSE; + //////////////// + + wgeolog(LOG_TODO,"olv_limp_t","Rellenando matriz de costes entre ámbitos"); + pon_mi_progre(OLV_TAREA_COST_AMB, (int) (OliviaDef::GeneralDef::ProgrMax*2/3)); + pon_mi_msg(""); + err_str[0]=0; + char st[MAX_PATH]; + char st1[MAX_PATH]; + + strcpy_s(st1,MAX_PATH,olv_limp->olv->paths.path_temp); + if(st1[strlen(st1)-1]=='\\') + { + st1[strlen(st1)-1]=0; + } + sprintf(st,"%s\\%s",st1,NOMB_ARCH_DIJ_DEF); + //inicia archivo para los djistra-------------- + if(!olv_limp->arch_dj.inicia(st,!olv->modo_multitask,olv_limp->conjs.n)) + { + wgeolog(LOG_TODO,"olv_limp_t","Error al iniciar archivo dj en directorio %s",st); + return FALSE; + } + if(!olv_limp->arch_dj.inicia_inf_amb(olv_limp->ias,olv_limp->n_amb,olv_limp->tipo_ambit,olv_limp->nod_instal, olv_limp->nod_plant)) + { + wgeolog(LOG_TODO,"olv_limp_t","Error al iniciar info de ambitos en archivo de dj"); + return FALSE; + } + ////////////////////////////////// + //primero loguea la info asociada de los ámbitos a su índice a su conjunción incial y su conjunción final + if(log_debug) + { + wgeolog(LOG_TODO,"olv_limp_t","Info asociada a ámbitos, conjs:"); + for(i=0;in_amb;i++) + { + wgeolog(LOG_TODO,"olv_limp_t","Info asociada a ámbitos, amb %03d: conj ini %04d conj fin %04d",i, + olv_limp->ias[i].ic_ini,olv_limp->ias[i].ic_fin); + } + } + + //////////////////////////////////////////////// + if(!inicia_cost_amb()) + { + return FALSE; + } + + if(!olv_limp->olv->modo_multitask) + { + //lanza los threads, tiene memo suficiente para todos los threads + lanza_subthrs(OLV_LIMP_EV_COST_AMB_SUB,n_subthr); + } + else + { + //wgeolog(LOG_TODO,"olv_limp_t","sizeof %ld %ld %ld %ld", sizeof(Head_dj_arch),sizeof(Djkt_nodo), sizeof(Djkt_ids_pdr),olv_limp->arch_dj.sizn); + + //en modo multitask entra aquí cuando ya han terminado las tasks + //se lee la matriz de ámbitos que han guardado las tasks + if(!olv_limp->arch_dj.lee_dis()) + return FALSE; + if(!olv_limp->olv_tasks->lee_cost_amb(olv_limp->cost_amb)) + return FALSE; + + //borra los archivos temporales + borra_temp_files(FALSE); + + //después de leerla, encola el cost_amb_fin + for(int i=0;iprog_subthr=0;//para que no dé error + encola(OLV_LIMP_EV_COST_AMB_FIN,NULL,FALSE); + } + } + + return TRUE; +} +//************************************************************************************* +BOOL Colv_limp_thr::inicia_cost_amb() +{ + int i,j; + + //pide memoria para el array de distancias entre ámbitos + if(!olv_limp->cost_amb.inicia(olv_limp->n_amb,olv_limp->n_amb)) + { + pon_mi_msg("Error, sin memoria para matriz de dist entre ámbitos"); + return FALSE; + } + + //inicializa todo a 0 + for(i=0;in_amb;i++) + { + for(j=0;jn_amb;j++) + olv_limp->cost_amb[i][j]=(float)MAYUSCULO;//porque se va a almacenar la minima + } + + //Inicia el array de orden /secuencia + olv_limp->ord_sec=(Secu_amb*)malloc(sizeof(Secu_amb)*olv_limp->n_amb); + if(!olv_limp->ord_sec) + { + pon_mi_msg("Error, sin memoria para matriz de orden y secuencia"); + return FALSE; + } + memset(olv_limp->ord_sec,0,sizeof(Secu_amb)*olv_limp->n_amb); + + return TRUE; +} +//************************************************************************************* +/** + * Rellena la matriz de distancias entre todos los ámbitos. + * El thread entra aquí cuando los subthreads que realizan la tarea realmente han finalizado + */ +BOOL Colv_limp_thr::calcula_cost_amb_fin() +{ + //////////////// + int ai=1; + + if(!olv_limp->olv->modo_multitask) + { + //para los threads + para_subthrs(); + } + + if(pirate) + return FALSE; + + //////////////// + //mira si hay aislados + if(!avisa_aislados()) + return FALSE; + + //avisa aislados ha ido bien, no hay aislados + + if(pirate) + return FALSE; + + //calcula el coste a las plantas + if(!calcula_cost_plant()) + { + pon_mi_msg("Error, planta o instalación aisladas"); + return FALSE; + } + + olv_limp->nsec_act=olv_limp->nsec; + + wgeolog(LOG_TODO,"olv_limp_t","FIN Matriz de dist entre ámbitos %ldx%ld", + olv_limp->n_amb,olv_limp->n_amb); + + return TRUE; +} +//************************************************************************************* +/** + * Dado el array relleno con los aislados, saca cartel avisando + */ +BOOL Colv_limp_thr::avisa_aislados() +{ + int i,j,k,ii; + BYTE *ambs_ais; + char ais_msg[OLV_MAX_MSG_PROCE]; + char nfile[MAX_PATH]; + + strcpy_s(nfile,MAX_PATH,olv->paths.path_data); + cambiaext(nfile,".shp",".dbf"); + + ambs_ais = (BYTE*)malloc(olv_limp->n_amb); + if(!ambs_ais) + { + pon_mi_msg("Error, sin memoria en fin de calcula coste ámbitos"); + return FALSE; + } + memset(ambs_ais,0,olv_limp->n_amb); + + //revisa costes de ámbitos + int nais; + for(i=0;in_amb; i++) + { + if(ambs_ais[i]) + continue; + if(olv_limp->ias[i].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + for(j=0;jn_amb; j++) + { + if(i==j) + continue; + if(olv_limp->ias[j].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + if(ambs_ais[j]) + continue; + if(olv_limp->cost_amb[i][j]>=MAYUSCULO) + { + //puede estar aislado i o j + nais=0; + for(k=0;kn_amb;k++) + { + if(k==i) + continue; + if(olv_limp->cost_amb[k][j]>=MAYUSCULO)//comprueba si j está aislado para los demás ámbitos también + { + nais=j; + break; + } + if(k==j) + continue; + if(olv_limp->cost_amb[i][k]>=MAYUSCULO)//comprueba si i está aislado para los demás ámbitos también + { + nais=i; + break; + } + } + if(kn_amb) + ambs_ais[nais]=1; + } + } + } + + nais=0; + int inw; + for(i=0;in_amb;i++) + { + if(ambs_ais[i]) + { + nais++; + Colv_geom::pon_pto((double (*)[3])olv_limp->conjs.coor[olv_limp->ias[i].ic[0]], OLV_ICLA_PUN_AIS, -1, olv_limp->olv->olv_ob); + olv_limp->olv->olv_sh->dame_col_int_dbf(nfile,i,i+1,&ii,"OBJECTID",err_str,OLV_MAX_ERR); + + inw=olv_limp->inww_amb[i].inw; + wgeolog(LOG_TODO,"olv_limp_t","Ámbito %ld aislado, calle %ld ia %03d flags %02X",i,inw,inw, + olv_limp->ias[inw].flgs); + } + } + + if(!nais) + { + free(ambs_ais); + return TRUE; + } + + if(nais==1) + sprintf_s(ais_msg,"Encontrado %ld ámbito aislado %s: ", nais,olv_limp->igno_ais?"(Se ignora)":""); + else + sprintf_s(ais_msg,"Encontrados %ld ámbitos aislados %s: ",nais,olv_limp->igno_ais?"(Se ignoran)":""); + int inais=0; + for(i=0;in_amb;i++) + { + if(ambs_ais[i]) + { + if(olv_limp->igno_ais)//si toca ignorar aislados, lo marca para ignorarlo en la sectorización + { + olv_limp->ias[i].flgs|=OLV_LIMP_FLG_AMB_NO; + } + + olv_limp->olv->olv_sh->dame_col_int_dbf(nfile,i,i+1,&ii,"OBJECTID",err_str,OLV_MAX_ERR); + if(nais==1) + { + sprintf_s(ais_msg,"%s %ld",ais_msg,ii); + break; + } + else if(inais==nais-1) + sprintf_s(ais_msg,"%s y %ld",ais_msg,ii); + else if(inais>0 && inais%4==0) + sprintf_s(ais_msg,"%s %ld,\n",ais_msg,ii); + else + sprintf_s(ais_msg,"%s %ld,",ais_msg,ii); + if(strlen(ais_msg)+10>=OLV_MAX_MSG_PROCE) + break; + inais++; + + } + } + if(in_amb && nais>1 && ((strlen(ais_msg)+5)igno_ais) + Sleep (OLV_T_SLEEP_MSG); + //////////////////////////// + + free(ambs_ais); + if(olv_limp->igno_ais) + return TRUE; + else + return FALSE; +} +//************************************************************************************* +/** + * Apunta en qué nodos está la planta y la instalación + */ +BOOL Colv_limp_thr::calcula_cost_plant() +{ + int ic,ia,ka,nais,k; + Djkt_nodo *costes_nodos; + BOOL mal=FALSE; + + if(olv_limp->nod_instal<0) + return TRUE; + + //Inicia el array de orden /secuencia + olv_limp->ord_sec_plan=(Secu_amb*)malloc(sizeof(Secu_amb)); + if(!olv_limp->ord_sec_plan) + { + pon_mi_msg("Error, sin memoria para matriz de orden y secuencia"); + return FALSE; + } + memset(olv_limp->ord_sec_plan,0,sizeof(Secu_amb)); + wgeolog(LOG_TODO,"olv_limp_t","Calculando coste a planta e instalación"); + + costes_nodos=NULL; + k=0; + + ic=olv_limp->nod_instal; + + if(!Colv_geom::dijkstra_ang_inv_ok(olv_limp->cost_conj, olv_limp->ang_conj, olv_limp->conjs.n, + ic, &costes_nodos, &visto_ang)) + { + pon_mi_msg("Error al calcular costes de ámbitos a instalación"); + return FALSE; + } + + olv_limp->ord_sec_plan[k].ctnod[0]=costes_nodos; + olv_limp->ord_sec_plan[k].ctnod[1]=NULL; + + costes_nodos=NULL; + + //revisa si está aislado de algún ámbito + nais=0; + for(ia=0;ian_amb;ia++) + { + if(olv_limp->ias[ia].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + for(ka=0;katipo_ambit;ka++) + { + if(olv_limp->ord_sec_plan[k].ctnod[0][olv_limp->ias[ia].ic[ka]].dis>=MAYUSCULO) + { + nais++; + break; + } + } + if(nais) + break; + } + if(ian_amb) + { + pon_mi_msg("Error al calcular costes de ámbitos a instalación"); + return FALSE; + } + + return TRUE; +} +//************************************************************************************* +/** + * Rellena la matriz de distancias entre todos los ámbitos, es la parte de cálculos que + * realizan los subthreads. 'ithr' indica qué thread es, para calcular qué ámbitos le tocan. + */ +void Colv_limp_thr::calcula_cost_amb_sub(int ithr) +{ + int na_ini,na_fin,na_desp,na,i,k; + int KK, seg; + Cobgeo *ob; + BOOL log_debug=FALSE; + Djkt_nodo *costes_nodos; + double caux; + Param_olv_limp_thr pp; + BOOL mal=FALSE; + + //////////////// + pp.id_e=OLV_TAREA_COST_AMB;//manda de parámetro la tarea de la que es el progreso + KK=olv_limp->tipo_ambit; + na_desp = (int)ceil(1.0*(olv_limp->n_amb)/n_subthr); + na_ini=ithr*na_desp; + na_fin = min((ithr+1)*na_desp,olv_limp->n_amb); + ob=olv_limp->olv->olv_ob; + costes_nodos=NULL; + //////////////// + + wgeolog(LOG_TODO,"olv_limp_t","Subthr %ld, Ambs %04d a %04d", ithr,na_ini, na_fin); + + seg = GetTickCount(); + ///////////////////////////////////// + //Bucle por cada ámbito de los que le tocan a este thread + ///////////////////////////////////// + //el coste de un ámbito a sí mismo es el de trabajar ese ámbito, + //que es el coste de ir de su conj inicial a la final + na=na_ini; + + ///////////////////////////////////// + for(na=na_ini;naias[i].ic_ini está almacenado el índice de la conjunción del nodo inicial del ámbito + //y en olv_limp->ias[i].ic_fin el del final. Se puede acceder con i directamente al array ias porque + //la info asociada está añadida por orden, primero los ámbitos + ///////////////////////////////////////////// + //calcula el coste máximo del ámbito na a todos los demás + //los añade a la fila na de la matriz de costes + //es coste máximo porque hace el máximo de: + //inicio(na)->inicio(ni), inicio(na)->final(ni), final(na)->inicio(ni), final(na)->final(ni) + ///////////////////////////////////////////// + //k==0, calcula las distancias del nodo inicial de ese ámbito a todas las demás conjunciones + //k==1, calucla las distancias del nodo final + for(k=0;kcost_conj, olv_limp->ang_conj, olv_limp->conjs.n, + (1-k)*olv_limp->ias[na].ic_ini+k*olv_limp->ias[na].ic_fin, + &costes_nodos, &visto_ang)) + { + mal=TRUE; + break; + } + + //recorre todos los demás ámbitos buscando el coste a ellos en el array de costes devuelto, y los almacena + //almacena el coste a su nodo inicial y a su nodo final + if(olv_limp->ias[na].flgs & OLV_LIMP_FLG_AMB_NO) + { + for (i=0; iconjs.n; i++) + { + costes_nodos[i].dis=(float)MAYUSCULO; + costes_nodos[i].id_padre=-1; + costes_nodos[i].ids_ady.nady=0; + } + } + else + { + for(i=0;in_amb;i++) + { + if(olv_limp->ias[i].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + if(na==i) + { + //el coste de un ámbito a sí mismo es el de trabajar ese ámbito + olv_limp->cost_amb[na][na]=olv_limp->cost_conj[olv_limp->ias[na].ic_ini][olv_limp->ias[na].ic_fin]; + continue; + } + + if(olv_limp->cost_amb[i][na]>costes_nodos[olv_limp->ias[i].ic_ini].dis) + olv_limp->cost_amb[i][na]=costes_nodos[olv_limp->ias[i].ic_ini].dis; + if(KK==OLV_AMB_LIN) + { + if(olv_limp->cost_amb[i][na]>costes_nodos[olv_limp->ias[i].ic_fin].dis) + olv_limp->cost_amb[i][na]=costes_nodos[olv_limp->ias[i].ic_fin].dis; + } + } + } + + if(!olv_limp->arch_dj.add_b(costes_nodos, na, k, TRUE)) + { + wgeolog(LOG_TODO,"olv_limp_t","Subthr %ld,Error %ld no se ha podido guardar dj iref: %ld k: %ld", ithr, + GetLastError(),na,k); + } + + for(i=0;iconjs.n;i++) + { + costes_nodos[i].libera(); + } + free(costes_nodos); + + olv_limp->ord_sec[na].ctnod[k]=NULL; + if(KK==1) + olv_limp->ord_sec[na].ctnod[1]=NULL; + + } + if(mal) + break; + + //si es ámbito lineal calcula la distancia media de los cuatro nodos + if(na==1) + if(log_debug) + { + for(i=0;in_amb;i++) + { + if(olv_limp->cost_amb[na][i]>=MAYUSCULO) + caux=-1; + else + caux=olv_limp->cost_amb[na][i]; + wgeolog(LOG_TODO,"olv_limp_t","Subthr %ld, Coste ámb %ld a ámb %ld es %lf", ithr, + na,i,caux); + } + } + + //avisa de progreso + if(((na-na_ini)%100==0) || ((na-na_ini)==(na_desp-1))) + { + wgeolog(LOG_TODO,"olv_limp_t","Subthr %ld, Rellenando matriz de dist entre ambs %ld de %ld", ithr, + (na-na_ini+1),na_desp); + //avisa de progreso + prog_subthr=((1.0*(na-na_ini+1)/na_desp)+2)/3;///3 porque es la tercera parte del progreso los costes de conjunciones + thr_padre->encola(OLV_LIMP_EV_SUBTHR_PROG,&pp,FALSE); + } + } + + if(visto_ang) + { + free(visto_ang); + visto_ang=NULL; + } + + if(mal) + { + wgeolog(LOG_TODO,"olv_limp_t","Subthr %ld, Error en cálculo de matriz de distancias entre ámbitos", ithr); + prog_subthr=-1;//para avisar al padre de que ha habido un error + } + else + { + wgeolog(LOG_TODO,"olv_limp_t","Subthr %ld, Fin Matriz de dist entre ambs, %.3f seg", ithr, 1.0*(GetTickCount()-seg)/1000); + } + thr_padre->encola(OLV_LIMP_EV_COST_AMB_FIN,NULL,FALSE); + + ///////////////////////////////////// +} +//************************************************************************************* +/** + * Genera los sectores + */ +BOOL Colv_limp_thr::sectoriza() +{ + int i,j; + BOOL res=TRUE; + + if(olv_limp->n_amb<2) + { + pon_mi_msg("Error, número de ámbitos es %ld",olv_limp->n_amb); + return FALSE; + } + + pon_mi_progre(OLV_TAREA_SECTORIZ, 0); + pon_mi_msg(""); + err_str[0]=0; + + if(!pide_memo_secto()) + { + pon_mi_msg("Error, Sin memoria para sectorización"); + return FALSE; + } + + ////////////////////////////////////////////////////////////// + wgeotext(LOG_TODO,"olv_limp_t","Comienza sectorización %ld ámbitos en %ld sectores", + olv_limp->n_amb, olv_limp->nsec_act); + + /////////////////////////////////////// + //Algoritmo 1 + if(!sectoriza_1()) + { + pon_mi_msg("Errores producidos en sectorización: %s",err_str); + res=FALSE; + goto pinta; + } + + /////////////////////////////////////// + //Si es barrido mixto hay que copiar la info en las que no se ha sectorizado + if(olv_limp->barr_mix) + copia_info_barr_mix(); + + ////////////////////////////////////////////////////////////////////////////// + //Guarda el shape añadiendo la columna de sector + if(!guarda_dbf_sector(0)) + { + pon_mi_msg("Errores producidos en sectorización: %s",err_str); + return FALSE; + } + //Guarda el shape añadiendo la columna de secuencia vacía + if(!guarda_dbf_sector(1)) + { + pon_mi_msg("Errores producidos en sectorización: %s",err_str); + return FALSE; + } + ////////////////////////////////////////////////////////////////////////////// + for(i=0;insec;i++) + { + wgeotext(LOG_TODO,"olv_limp_t","Sector %ld, %03d ámbitos, coste total %lf",i,olv_limp->sec[i].namb, olv_limp->sec[i].cost_ac); + } + wgeotext(LOG_TODO,"olv_limp_t","Finalizada generacion de sectores--------------------------"); + +pinta: + ////////////////////////////////////////////////////////////// + //pinta los sectores, solo en modo debug + for(j=0;jn_amb;j++) + { + if(olv_limp->amb_sec[j].sec>=0) + (*olv_limp->olv->olv_ob->objt)[j].clase = 666 + olv_limp->amb_sec[j].sec; + } + + return res; +} +//************************************************************************************* +/** + * Pide memoria e inicializa los arrays para la sectorización + */ +BOOL Colv_limp_thr::pide_memo_secto() +{ + int i,j; + ////////////////////////////////////////////////////////////// + //pide memoria para el array de distancias del sector + olv_limp->sec = (Info_sec *)malloc(olv_limp->nsec*sizeof(Info_sec)); + if(!olv_limp->sec) + { + pon_mi_msg("Error, sin memoria para matriz de sectores"); + return FALSE; + } + memset(olv_limp->sec,0,olv_limp->nsec*sizeof(Info_sec)); + for(i=0;insec;i++) + { + olv_limp->sec[i].iamb = (short *)malloc(olv_limp->n_amb*sizeof(short)); + if(!olv_limp->sec[i].iamb) + { + pon_mi_msg("Error, sin memoria para matriz de sectores"); + return FALSE; + } + } + //inicializa todo a mayúsculo + for(i=0;insec;i++) + { + olv_limp->sec[i].namb=0; + olv_limp->sec[i].iamb_ini_def=-1; + olv_limp->sec[i].t_despl[0]=olv_limp->sec[i].t_despl[1]=(float)olv_limp->t_despl; + for(j=0;jn_amb;j++) + { + olv_limp->sec[i].iamb[j]=-1; + } + } + ////////////////////////////////////////////////////////////// + //pide memoria para el array de ámbitos asignados al sector + olv_limp->amb_sec = (Info_amb_sec *)malloc(olv_limp->n_amb*sizeof(Info_amb_sec)); + if(!olv_limp->amb_sec) + { + pon_mi_msg("Error, sin memoria para matriz de ámbitos en los sectores"); + return FALSE; + } + memset(olv_limp->amb_sec,0,olv_limp->n_amb*sizeof(Info_amb_sec)); + //inicializa todo + for(j=0;jn_amb;j++) + { + olv_limp->amb_sec[j].sec=-1; + olv_limp->amb_sec[j].iseq=-1; + olv_limp->amb_sec[j].t=0; + } + + olv_limp->nsec_orig=olv_limp->nsec; + + return TRUE; +} +//************************************************************************************* +/** + * Añade el ámbito 'i_amb' al sector 'i_sec', actualizando la info en todos los lugares necesarios + * Actualiza el coste que es el que lleva, mas el desplazamiento del que ya tiene al nuevo, más el coste del nuevo + */ +BOOL Colv_limp_thr::add_amb_sec(int i_amb, int namb, int i_sec, Info_sec *ss, Info_amb_sec *aa, Matrix2d &cost_amb, double cost_tot, int i_amb_p) +{ + if(olv_limp->ias[i_amb].flgs & OLV_LIMP_FLG_AMB_NO) + return FALSE; + ss[i_sec].iamb[ss[i_sec].namb]=i_amb; + ss[i_sec].namb++; + //apunta el ámbito al sector + aa[i_amb].sec=i_sec; + + return TRUE; +} +//************************************************************************************* +/** + * Le quita el ámbito 'i_amb' al sector 'i_sec', actualizando la info en todos los lugares necesarios + * Actualiza el coste que es el que lleva, mas el desplazamiento del que ya tiene al nuevo, más el coste del nuevo + * Al salir, hay que actualizar las distancias! + */ +void Colv_limp_thr::quita_amb_sec(int i_amb, int namb, int i_sec, Info_sec *ss, Info_amb_sec *aa, Matrix2d &cost_amb, int i_amb_p) +{ + int i,j; + for(i=0;i=ss[i_sec].namb) + return ; //no lo tenía este sector + + //le quita de su array de índices si tiene al menos uno posterior + for(j=i;j &cost_amb, Info_sec *ss, Info_amb_sec *aa) +{ + int s, i,ii, j, k; + double d, dmax; + BOOL sec_cerc; + + //busca elementos------------------------------- + add_amb_sec(iamb_extr,n_amb,0,ss,aa,cost_amb,MAYUSCULO,-1); + //busca ambitos extremos-------------------- + for(s=1; s=0) + continue; + if(olv_limp->ias[j].flgs & OLV_LIMP_FLG_AMB_NO)//se ha marcado para no usarse, por aislado o por carga insuficiente + { + aa[j].sec=-1; + continue; + } + + for (ii=0; ii=0) + break; + } + if(!sec_cerc && ii=0) + continue; + if(olv_limp->ias[j].flgs & OLV_LIMP_FLG_AMB_NO)//se ha marcado para no usarse, por aislado o por carga insuficiente + continue; + + add_amb_sec(j,n_amb,n_sec-1,ss,aa,cost_amb,MAYUSCULO,-1); + k=j; + } + + return TRUE; +} +//************************************************************************************* +/** + * Prueba sectorización algoritmo 1, expansión según cercanía de árbol de coste mínimo + */ +BOOL Colv_limp_thr::sectoriza_1() +{ + double maxx,dd; + int iamb,i; + + dd=0; + + ///////////////////////////////////// + //calcula el árbol de coste mínimo para rellenar cercanos + //rellena_amb_cercanos_por_arbol(olv_limp->n_amb, olv_limp->cost_amb, olv_limp->amb_sec); + if(!rellena_amb_cercanos_por_carretera(olv_limp->n_amb, olv_limp->amb_sec, olv_limp->ord_sec)) + { + sprintf_s(err_str,OLV_MAX_ERR,"Error al rellenar ambitos cercanos por carretera"); + return FALSE; + } + + //comprueba islas + if(!quita_islas(olv_limp->n_amb, olv_limp->amb_sec, olv_limp->ord_sec)) + { + wgeolog(LOG_TODO,"quita_islas","No consigue eliminar islas"); + + } + ////////////////////// + //Como primer ámbito coge el más extremo + //el de menor 'y+x' + maxx=MAYUSCULO; + for(i=0;in_amb;i++) + { + if(olv_limp->ias[i].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + if((olv_limp->conjs.coor[olv_limp->ias[i].ic_ini][1]+olv_limp->conjs.coor[olv_limp->ias[i].ic_ini][0])conjs.coor[olv_limp->ias[i].ic_ini][1]+olv_limp->conjs.coor[olv_limp->ias[i].ic_ini][0]; + iamb=i; + } + } + + if((iamb<0) || (iamb>=olv_limp->n_amb)) + { + sprintf_s(err_str,OLV_MAX_ERR,"Error no se ha encontrado ambito extremo"); + return FALSE; + } + + if(pirate) + { + sprintf_s(err_str,OLV_MAX_ERR,"Sale por peticion de usuario"); + return FALSE; + } + + //si se ha calculado el número de sectores ya se ha sectorizado inicialmente, no hay que llamar a genera_sectores + if(olv_limp->calc_nsec==0) + { + if(!genera_sectores3(iamb,olv_limp->n_amb,olv_limp->nsec,olv_limp->cost_amb,olv_limp->sec, olv_limp->amb_sec)) + { + sprintf_s(err_str,OLV_MAX_ERR,"Error al generar sectores"); + return FALSE; + } + } + else + { + //entra aquí si ha calculado el número de sectores, y ya va a sectorizar + //en este modo, primero usa solo los dos primeros sectores, al primero le da un ámbito y al segundo el resto de ámbitos + if(!genera_sectores3(iamb,olv_limp->n_amb,olv_limp->nsec_act,olv_limp->cost_amb,olv_limp->sec, olv_limp->amb_sec)) + { + sprintf_s(err_str,OLV_MAX_ERR,"Error al generar sectores"); + return FALSE; + } + } + + pon_mi_progre(OLV_TAREA_PERMU,0); + if(olv_limp->nsec>1) + { + if(olv_limp->calc_nsec==0) + { + dd=iguala_sectores4(olv_limp->n_amb, olv_limp->nsec, olv_limp->cost_amb, olv_limp->sec, olv_limp->amb_sec); + } + else + { + //entra aquí si ha calculado el número de sectores, y ya va a sectorizar + dd=iguala_sectores5(iamb,olv_limp->n_amb, olv_limp->nsec, olv_limp->cost_amb, olv_limp->sec, olv_limp->amb_sec); + } + wgeotext(LOG_TODO,"olv_limp_t","Conseguida una desviación de: %lf",dd); + } + else + { + olv_limp->sec[0].cost_ac=(float)calcula_cost_1sec_total(olv_limp->n_amb,olv_limp->sec,olv_limp->ias,olv_limp->ang_conj); + if(olv_limp->sec[0].cost_ac>=MAYUSCULO) + dd=-1; + } + + if(dd<0)//si es -2, aislados, ya lo ha puesto el iguala_sectores4 + { + if(dd==-2) + sprintf_s(err_str,OLV_MAX_ERR,"Existen ámbitos aislados que\nno ha sido posible unir a la red"); + return FALSE; + } + + return TRUE; +} +//************************************************************************************* +/** +* parte del ambito central del sector y crea el arbol de camino minimo de dicho sector + marca en cada ambito quien es su padre y cuantos hijos tiene + devuelve el numero de ambitos frontera +**/ +int Colv_limp_thr::asigna_padres(int amb_central, int namb, Matrix2d &cost_amb, Info_sec *ss, Info_amb_sec *aa, int *buf, int nhijos_fron) +{ + int i,j; + int psel,sel; + double d, dsel=MAYUSCULO; + int nn=1; + + for (i=0; inamb; i++) + { + if(aa[ss->iamb[i]].iseq!=-1) + { + wgeotext(LOG_TODO,"olv_limp_t","Error en iasigna_padres, Ambito %d ya tiene padre asignados, sec %d",ss->iamb[i], aa[ss->iamb[i]].sec); + + + } + } + buf[0]=amb_central; + aa[amb_central].iseq=-2; + aa[amb_central].t=0; + while(nnnamb) + { + dsel=MAYUSCULO; + sel=-1; + for (i=0; inamb; j++)//recorre ambitos del sector + { + if(aa[ss->iamb[j]].iseq!=-1) + continue; + d=cost_amb[buf[i]][ss->iamb[j]]; + if(diamb[j]; + psel=buf[i]; + } + } + } + if(sel<0) + { + wgeotext(LOG_TODO,"olv_limp_t","Error en iasigna_padres, no encontrado ambitos libres sin padres"); + break;//terminado (esto no deberia pasar) + } + if(aa[psel].iseq<0) + aa[psel].iseq=sel; + buf[nn]=sel; + aa[sel].iseq=psel; + aa[sel].t+=1; + aa[psel].t+=1; + nn++; + } + //recorre ambitos para pillar los ambitos frontera---------------- + d=0; + j=recorre_hijos(amb_central, namb, aa, NULL, 0, cost_amb, &d); + if((j+1)!=nn) + wgeotext(LOG_TODO,"olv_limp_t","Error en iasigna_padres,Existen hijos aislados"); + + nn=0; + for(j=0; jnamb; j++)//recorre ambitos del sector + { + if(aa[ss->iamb[j]].t<=nhijos_fron) + buf[nn++]=ss->iamb[j]; + } + + + return nn; +} +//************************************************************************************* +double Colv_limp_thr::dis_min_amb(int ids[2], int id_nod_ini, Secu_amb * ord_sec, BOOL res_nod, int iamb) +{ + double dd=MAYUSCULO; + ids[0]=ids[1]=0; + + //si puntuales, entra una vez, si lineales, entra cuatro + for(int k=0; k<3*olv_limp->tipo_ambit-2; k++) + { + if(dd>olv_limp->arch_dj.dame_dis(id_nod_ini, k/2, iamb,k%2)) + { + ids[0]=k%2; + ids[1]=k/2; + dd=olv_limp->arch_dj.dame_dis(id_nod_ini, k/2, iamb,k%2); + } + } + if(res_nod) + { + ids[1]=olv_limp->ias[id_nod_ini].ic[ids[1]]; + } + + return dd; +} +//************************************************************************************* +typedef struct Dists +{ + double dist; + int iamb; +}Dists; +//************************************************************************************* +BOOL Colv_limp_thr::quita_islas(int namb, Info_amb_sec *aa, Secu_amb * ord_sec) +{ + int nis =-1, i; + if(namb<2) + return true; + short* islas = (short*) malloc(namb * sizeof(short)); + + if(!islas) + return false; + //marca todos los ambitos sin islas + for (i=0;i amb_pend; + for (i=0;iias[i].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + if(islas[i]>-1) + continue; + nis++; + amb_pend.push(i); + while(!amb_pend.empty()) + { + int amb_act=amb_pend.top(); + amb_pend.pop(); + islas[amb_act]=nis; + //añade cercanos a la pila + for (int k =0 ; k-1) + continue; + amb_pend.push(aa[amb_act].iamb_cerca[k]); + } + + } + } + wgeolog(LOG_TODO,"quita_islas","Numero de islas %ld",nis); + + if(nis<1) + goto va_bien; + + //quita islas + int iamb=-1; + int iamb_cerca=-1; + int oo[2]; + double dis, dd; + for (int kis = nis; kis>0; kis--) + { + iamb=-1; + iamb_cerca=-1; + dis=MAYUSCULO; + for (i=0; iias[i].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + if(islas[i]!= kis) + continue; + for (int ii = 0; iiias[i].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + if(islas[ii]== kis) + continue; + dd = dis_min_amb(oo,i,NULL, false,ii); + if(ddconjs.n); + if(!secu1) + { + wgeolog(LOG_TODO,"rellena_amb_cercanos_por_carretera","Sin memoria para ambitos"); + return FALSE; + } + + Dists dis_[MAX_LEN_BUF_CERCANAS]; + + rmax=RMAX_INI; + + //matriz de conexion con ambitos (te dice si una conjuncion esta conectada con un ambito y en ese caso con cual. -1 en caso contrario) + conex = (int*) malloc(olv_limp->conjs.n * sizeof(int)); + if (!conex) + { + wgeolog(LOG_TODO,"rellena_amb_cercanos_por_carretera","Sin memoria para conjunciones"); + return FALSE; + } + for (n=0;nconjs.n;n++) + conex[n]=-1; + // matriz de distancias (olv_limp->cost_conj[][]) + //olv_limp->tipo_ambit//indica que tipo de ambitos estamos tratando1 si es puntual 2 si es lineal + //olv_limp->ias[0].ic[0]id de la conjunion 1 del ambito 0 + //olv_limp->ias[0].ic[1]id de la conjunion 2 del ambito 0 + //bucle por todos los ambitos + //bucle por todos los nodos del ambito + //bucle por todos los nodos + //marcas en el array si el nodo es el del ambito o si tiene conexion directa con dicho ámbito + for (n=0;nconjs.n;n++) + { + for (i=0;itipo_ambit;j++) + { + if(olv_limp->ias[i].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + if (olv_limp->ias[i].ic[j]==n ) + { + //Ha encontrado que esta conjunción conecta con el ámbito iésimo + conex[n]=i; + //Sale de los dos bucles + i=namb; + break; + } + else if(olv_limp->cost_conj[n][olv_limp->ias[i].ic[j]]!=(float)MAYUSCULO && conex[n]==-1) + { + conex[n]=i; + } + } + } + } + + if(logdebug) + { + for(j=0;jconjs.n;j++) + { + wgeolog(LOG_TODO,"rellena_amb_cercanos_por_carretera","n %ld conex[n] %ld",j, conex[j]); + } + } + + secu2=&secu1[olv_limp->conjs.n]; + for(j=0; jarch_dj.dame_buf_nodos(FALSE); + buf_aux[1]=olv_limp->arch_dj.dame_buf_nodos(FALSE); + + if(!buf_aux[0] || !buf_aux[1]) + { + wgeolog(LOG_TODO,"rellena_amb_cercanos_por_carretera","Sin memoria para buffer de nodos"); + goto va_mal; + } + + for (j=0; jias[j].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + cargado[0]=FALSE; + cargado[1]=FALSE; + for (i=0; iias[i].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + //selecciona distancia minima de un ambito a otro + dd=dis_min_amb(oo,i,&ord_sec[j], TRUE, j); + if(dd>=MAYUSCULO)//sin conexion entre ambitos + continue; + + //cargar ambito antes de archivo------------------- + if(!cargado[oo[0]]) + { + olv_limp->arch_dj.get_b(j,oo[0],buf_aux[oo[0]]); + cargado[oo[0]]=TRUE; + } + //se verifica que en los cercanos no se pase por los mismos nodos + Colv_geom::ruta_dj_inv_ok(oo[1], secu1, buf_aux[oo[0]],olv_limp->conjs.n, &r1); + + + //Recorre los nodos de la ruta entre esos ámbitos para ver si alguno de los nodos no conecta directamente + //con algún ámbito, en cuyo caso lo descarta + //o lo descarta también si lleva varios nodos de carretera seguidos + rr=0; + for (n=0;n0 && conex[secu1[n]]==-1 && conex[secu1[n-1]]==-1) + rr++; + else if( n<(r1-2)) + rr=0; + } + if (n=MAX_LEN_BUF_CERCANAS) + continue; + + aa[i].iamb_cerca[aa[i].namb_cerca]=j | (rr<<24); + aa[i].namb_cerca++; + } + } + + //ordena------------- + for (i=0;iias[i].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + + memset(dis_,0,sizeof(Dists)*MAX_LEN_BUF_CERCANAS); + if(aa[i].namb_cerca<=0) + { + aa[i].namb_cerca=aa[i].namb_cerca; + wgeolog(LOG_TODO,"rellena_amb_cercanos_por_carretera","iamb %ld 0 cercanos",i); + continue; + } + + for(j=0;j>24; + dis_[j].dist=dis_min_amb(oo,i,&ord_sec[aa[i].iamb_cerca[j] & 0x00ffffff], TRUE, aa[i].iamb_cerca[j] & 0x00ffffff); + dis_[j].iamb=aa[i].iamb_cerca[j]; + } + + qsort(dis_,aa[i].namb_cerca,sizeof(Dists),Colv_limp_thr::compara_dist_cerc); + + if(logdebug) + { + for(j=0;j>24, dis_[j].dist); + } + } + + for(j=0;j0 ;j--) + { + r1=(aa[i].iamb_cerca[j-1] & 0xff000000)>>24; + r2=(aa[i].iamb_cerca[j] & 0xff000000)>>24; + if(r1>0 || r2>0) + r1=r1; + if((r2-r1)>RMAX_INI) + aa[i].namb_cerca=j; + + } + + for(j=0;j>24); + } + aa[i].iamb_cerca[j]= aa[i].iamb_cerca[j] & 0x00ffffff; + } + } + olv_limp->arch_dj.libera_buf(buf_aux[0]); + olv_limp->arch_dj.libera_buf(buf_aux[1]); + if(secu1) + free(secu1); + if(conex) + free(conex); + + return TRUE; +va_mal: + olv_limp->arch_dj.libera_buf(buf_aux[0]); + olv_limp->arch_dj.libera_buf(buf_aux[1]); + + if(conex) + free(conex); + if(secu1) + free(secu1); + return FALSE; + +} +//************************************************************************************* +/** + * Compara las estructuras Dist. Las ordena por distancia + */ +int Colv_limp_thr::compara_dist_cerc (const void * a, const void * b) +{ + //si adist - ((Dists*) b)->dist); +} +//************************************************************************************* +/** + * Busca el sector más cercano a un ámbito + * busca el ambito frontera de iamb mas cercano al sector id_sec + * si modo==1 busca se busca a cualquier sector menos id_sec + */ +int Colv_limp_thr::busca_sec_cerca_amb(Info_amb_sec *aa,int iamb, int id_sec, int modo) +{ + int i,s,ia; + if(id_sec<0) + return -1; + for(i=0; i=i; k--) + isec[k+1]=isec[k]; + isec[i]=j; + nord++; + } + return isec; +} +//************************************************************************************* +/** + * Algoritmo 5 de igualación de sectores, pasando ámbitos de un sector a otro que tenga cerca + */ +double Colv_limp_thr::iguala_sectores5(int iamb, int n_amb, int n_sec, Matrix2d &cost_amb, Info_sec *ss, Info_amb_sec *aa) +{ + double desv; + int res; + enum Res{ + RES_SALE_BIEN, + RES_SALE_MAL, + RES_NO_SALE, + RES_GENERA, + }; + int i,j; + + desv=0; + + //llama al iguala_sect4 con, al principio sólo 2 sectores activos + //luego comprueba si el último de los nsec su coste es mayor que la jornada + //y si es así, nsec_act++, cuidando que no pase de nsec + //se le añade un ámbito, el más lejano de nsec_act + //si su coste es cero, nsec_act-- + //si es el coste es >0 y <= que el coste jornada, todo ok + do + { + wgeolog(LOG_TODO,"olv_limp_t","Iguala sectores 5 con %ld sectores", olv_limp->nsec_act); + desv=iguala_sectores4( n_amb, olv_limp->nsec_act, cost_amb, ss, aa); + if(desv<0) + { + //sale mal + res=RES_SALE_MAL; + continue; + } + if(ss[olv_limp->nsec_act-1].cost_ac==0) + { + if((olv_limp->nsec_act-1)<=0) + { + //sale bien, pero forzado, no debería salir por aquí.. + res=RES_SALE_BIEN; + continue; + } + olv_limp->nsec_act--; + res=RES_GENERA; + } + else if(ss[olv_limp->nsec_act-1].cost_ac>olv_limp->calc_nsec) + { + //añade un sec activo, siempre que haya disponibles + if((olv_limp->nsec_act+1)>olv_limp->nsec) + { + //sale bien, pero forzado, no debería salir por aquí.. + res=RES_SALE_BIEN; + continue; + } + olv_limp->nsec_act++; + //llama de nuevo al genera_sectores + res=RES_GENERA; + } + else + { + //sale bien + res=RES_SALE_BIEN; + } + if(res==RES_GENERA) + { + ////////////////////////////////////////////////////////////// + //reinicializa + for(i=0;insec;i++) + { + olv_limp->sec[i].namb=0; + olv_limp->sec[i].iamb_ini_def=-1; + olv_limp->sec[i].t_despl[0]=olv_limp->sec[i].t_despl[1]=(float)olv_limp->t_despl; + for(j=0;jn_amb;j++) + { + olv_limp->sec[i].iamb[j]=-1; + } + } + //reinicializa + for(j=0;jn_amb;j++) + { + olv_limp->amb_sec[j].sec=-1; + olv_limp->amb_sec[j].iseq=-1; + olv_limp->amb_sec[j].t=0; + } + ////////////////////////////////////////////////////////////// + if(!genera_sectores3(iamb,olv_limp->n_amb,olv_limp->nsec_act,olv_limp->cost_amb,olv_limp->sec, olv_limp->amb_sec)) + { + //sale mal + res=RES_SALE_MAL; + } + } + + } while (res>=RES_NO_SALE); + + if(res==RES_SALE_MAL) + return -1; + + //si sale bien, libera el espacio libre + if(olv_limp->nsec_actnsec) + { + for(int i=olv_limp->nsec_act;insec;i++) + { + if(olv_limp->sec[i].cost_amb_sec) + free(olv_limp->sec[i].cost_amb_sec); + if(olv_limp->sec[i].cost_amb_sec_aux) + free(olv_limp->sec[i].cost_amb_sec_aux); + if(olv_limp->sec[i].iamb) + free(olv_limp->sec[i].iamb); + } + Info_sec* sec_aux; + sec_aux=(Info_sec*)realloc(olv_limp->sec,olv_limp->nsec_act*sizeof(Info_sec)); + if(!sec_aux) + return -1; + olv_limp->sec=sec_aux; + olv_limp->nsec=olv_limp->nsec_act; + } + + return desv; +} +//************************************************************************************* +/** + * Algoritmo 4 de igualación de sectores, pasando ámbitos de un sector a otro que tenga cerca + */ +double Colv_limp_thr::iguala_sectores4(int n_amb, int n_sec, Matrix2d &cost_amb, Info_sec *ss, Info_amb_sec *aa) +{ + double desv; + double desv_last,cos_min, cos_min_last, cos_max, cos_max_last; + double desv_abs_old, desv_abs; + double d, d1; + BYTE* st=NULL; + int *isec=NULL, *iamb_r=NULL, j, i, ii, jj,k; + int sec_m=0; + int sselc=-1; + int iamb,ip, sec; + int nth=Colv_geom::dame_n_nucleos(); + Secu_amb * ord_sec=olv_limp->ord_sec; + th_param_planif thp; + memset(&thp, 0, sizeof(thp)); + thp.milis_sleep=1; + thp.namb_t=n_amb; + thp.abs=TRUE; + desv_last=dame_desv_sec(n_sec,ss, TRUE,&desv_abs_old); + BOOL log_debug=FALSE; + BOOL todo_ok=FALSE; + BOOL aisladas=FALSE; + char nfile[MAX_PATH]; + BOOL nocalc=FALSE; + ii=jj=0; + + strcpy_s(nfile,MAX_PATH,olv->paths.path_data); + cambiaext(nfile,".shp",".dbf"); + + + //////////////////////////////////////////// + //avisa de progreso + wgeolog(LOG_TODO,"olv_limp_t","Calculando permutaciones para mejorar al igualar sectores"); + pon_mi_progre(OLV_TAREA_PERMU,0); + //////// + + thp.dth=(th_data_planif*)malloc(sizeof(th_data_planif)*nth); + memset(thp.dth, 0, sizeof(th_data_planif)*nth); + + for (i=0; i=0) + Sleep(1); + + } + ///////////////////////////////////// + + desv=iguala_sectores3(n_amb, n_sec, cost_amb, ss, aa, ord_sec, &thp); + if(desv>=MAYUSCULO) + { + sprintf_s(err_str,OLV_MAX_ERR,"Error en iguala_sect3"); + goto salir; + } + desv_last=dame_desv_sec(n_sec,ss, TRUE, &desv_abs_old); + + wgeolog(LOG_TODO,"olv_limp_t","Iguala sectores 4. Desv: %lf",desv_last); + + if(olv_limp->calc_nsec<=0) + cos_max_last=dame_mima(n_sec, ss,&cos_min_last); + else + cos_max_last=cos_min_last=0; + iamb_r=(int*)malloc(sizeof(int)*n_amb*2); + if(!iamb_r) + { + sprintf_s(err_str,OLV_MAX_ERR,"Error al pedir memoria"); + goto salir; + } + + st=guarda_estado(n_amb,n_sec,aa,ss,st); + + if(!st) + { + sprintf_s(err_str,OLV_MAX_ERR,"Error al guardar estado"); + goto salir; + } + do + { + + if((desv_lastias[ss[sselc].iamb[i]].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + for (j=0; j=0) + { + d=d1; + iamb=ss[sselc].iamb[i]; + ip=k; + sec=aa[k].sec; + } + } + } + if(d>=MAYUSCULO || sec<0) + { + sprintf_s(err_str,OLV_MAX_ERR,"Error, no encuentra más ámbitos cercanos"); + if(desvias, &thp,FALSE); + calcula_coste_1sec(ord_sec, &ss[sec], olv_limp->ias, &thp,FALSE); + //se pasa ambito mas peque del mayor sector al sector mas cercano + //se fija sector mas alto como bloqueado + ss[sselc].flags_tem|=OLV_LIMP_FLG_SEC_INFO_BLOCK; + + iguala_sectores3(n_amb, n_sec, cost_amb, ss, aa, ord_sec, &thp); + + //se desbloquea + ss[sselc].flags_tem&=~OLV_LIMP_FLG_SEC_INFO_BLOCK; + iguala_sectores3(n_amb, n_sec, cost_amb, ss, aa, ord_sec, &thp); + + desv=dame_desv_sec(n_sec,ss, TRUE, &desv_abs); + + if(desv>=desv_last) + { + if(olv_limp->calc_nsec<=0 && desv==desv_last) + cos_max=dame_mima(n_sec, ss, &cos_min); + else + cos_max=cos_min=0; + + if( desv>desv_last || (((cos_max-cos_min)>= (cos_max_last-cos_min_last)))) + + { + //se vuelve a estado anterior + pon_estado(n_amb,n_sec,aa,ss,cost_amb,st); + + desv=dame_desv_sec(n_sec,ss, TRUE); + if(desv!=desv_last) + wgeolog(LOG_TODO,"olv_limp_t","Iguala sectores 4. Error no coincide desv anterior Desv: %lf Desv_old",desv, desv_last); + sec_m++; + if(sec_m>=n_sec-1) + { + todo_ok=TRUE; + break; + } + continue; + + } + sec_m=0; + } + sec_m=0; + wgeolog(LOG_TODO,"olv_limp_t","Iguala sectores 4. Cambio mejora desv old: %lf, new %lf",desv_last, desv); + desv_last=desv; + desv_abs_old=desv_abs; + cos_max_last=cos_max; + cos_min_last=cos_min; + + st=guarda_estado(n_amb,n_sec,aa,ss,st); + if(!st) + { + sprintf_s(err_str,OLV_MAX_ERR,"Error al guardar estado anterior"); + goto salir; + } + } while (!pirate); + if(!todo_ok) + goto salir; + + st=guarda_estado(n_amb,n_sec,aa,ss,st); + if(!st) + goto salir; + + /* + if(olv_limp->calc_nsec>0) + todo_ok=FALSE;//se reinicia para ver si la siguiente parte todo_ok + while(olv_limp->calc_nsec>0 && !pirate) + { + if((desv_lastMAYUSCULO) + continue; + quita_amb_sec(iamb,n_amb,sselc,ss,aa,cost_amb,aa[iamb].iseq); + add_amb_sec(iamb,n_amb,sec,ss,aa,cost_amb,MAYUSCULO,ip); + + for (ii=0; ii=desv_last) + { + //se vuelve a estado anterior + pon_estado(n_amb,n_sec,aa,ss,cost_amb,st); + + desv=dame_desv_sec(n_sec,ss, TRUE); + if(desv!=desv_last) + desv_last=desv; + continue; + } + wgeolog(LOG_TODO,"olv_limp_t","Iguala sectores4. Cambio mejora desv old: %lf, new %lf",desv_last, desv); + desv_last=desv; + st=guarda_estado(n_amb,n_sec,aa,ss,st); + if(!st) + { + sprintf_s(err_str,OLV_MAX_ERR,"Error al guardar estado"); + goto salir; + } + break; + + } + } + if(i>=ss[sselc].namb) + { + todo_ok=TRUE; + break; + } + } + */ + +salir: + if(log_debug) + { + wgeotext(LOG_TODO,"olv_limp_t","------------------------------------------------"); + for(i=0;i0) + Sleep(1); + if(iamb_r) + free(iamb_r); + if(st) + free(st); + free(isec); + + if(thp.dth) + { + if(thp.dth[0].sec) + free(thp.dth[0].sec); + free(thp.dth); + + } + + if(!todo_ok) + { + wgeotext(LOG_TODO,"olv_limp_t","Errores varios en iguala_sectores4"); + if(aisladas) + return -2; + return -1; + } + return desv_last; +} +//************************************************************************************* +/** + * Recorre los 'nesc' sectores igualando su coste + * La idea es poner ambitos a los sectores de menor coste manteniendo la condicion de no aisladas + */ +#define MAX_AMBI_IGUALA_SEC 500 +double Colv_limp_thr::iguala_sectores3(int n_amb, int n_sec, Matrix2d &cost_amb, Info_sec *ss, Info_amb_sec *aa, Secu_amb * ord_sec, th_param_planif *thp) +{ + double desv,desv_last, desv_fut;//máxima desviación permitida respecto a la media + BOOL hay_cambio,log_debug; + int *amb_fron;//indice a ambitos frontera de sectores + int *isec=NULL;//indice a sectores (ordenados de mayor a menor) + int *icerca;//indice a ambitos cercanos a los frontera de un sector + int *icamb;//indices a ambitos cambiados de sector en un pasp + int cambio[2][2];//[0]ambito y sector que se pasa al[1] ambito (padre) y sector + int siz_sec=(n_amb+1); + int j, i, k,kk, kkk; + int isec_min; + int ncerca; + int nhijos_frontera=10; + int namb_camb; + int ind_camb; + int nais=0; + //------------------------------- + + log_debug=TRUE; + if(log_debug) + wgeotext(LOG_TODO,"olv_limp_t","Empieza igualacion de sectores 3"); + isec=(int*)malloc(sizeof(int)*(1+n_sec*(n_amb+1)+n_sec+n_amb*5)); + + desv_last=MAYUSCULO; + + if(!isec) + { + wgeotext(LOG_TODO,"olv_limp_t","Error en igualacion de sectores 3, sin memoria para bufferes"); + return desv_last;//no debería pasar + } + icerca=&isec[n_sec+1]; + icamb=&icerca[n_amb*2]; + amb_fron=&icamb[n_amb*3]; + + //calcula media y desviacion de costes en sectores + //bucle + hay_cambio=TRUE; + ind_camb=-1; + for(j=0; jias, thp); + if(desv_lastcalc_nsec) + { + isec[0]=n_sec-1; + ordena_sec(n_sec-1, ss, &isec[1]); + isec_min=n_sec-1; + } + else + { + ordena_sec(n_sec, ss, isec); + isec_min=n_sec-1; + } + hay_cambio=FALSE; + if(log_debug && ind_camb>=0) + wgeotext(LOG_TODO,"olv_limp_t","Iguala sectores 3, mejorada desviacion tipica a %lf", desv_last); + } + else + { + isec_min--; + if(isec_min<=0) + break;//no se puede mejorar mas + } + //busca fronteras de otros sectores cercanas al sector isec_min + if(ss[isec[isec_min]].flags_tem& OLV_LIMP_FLG_SEC_INFO_BLOCK) + continue; + ncerca=0; + for(j=0; j=0; i--) + { + //verifica que tenga ambitos cercanos de otros sectores + //si es asi añade al array + k=busca_sec_cerca_amb(aa,amb_fron[kk+i], isec[isec_min],1); + if(k>=0) + { + icerca[ncerca*2]=k; + icerca[ncerca*2+1]=amb_fron[kk+i]; + ncerca++; + } + } + continue; + } + //recore ambitos frontera de sector j + kk=isec[j]*siz_sec+1; + for(i=amb_fron[isec[j]*siz_sec]-1; i>=0; i--) + { + k=busca_sec_cerca_amb(aa,amb_fron[kk+i], isec[isec_min]); + if(k>=0) + { + icerca[ncerca*2]=amb_fron[kk+i]; + icerca[ncerca*2+1]=k; + ncerca++; + } + } + } + if(ncerca<=0) + continue;//no se puede mejorar + if(ncerca>n_amb) + ncerca=ncerca; + desv_fut=MAYUSCULO; + ind_camb=-1; + for(i=0; imilis_sleep=0; + calcula_coste_1sec(ord_sec, &ss[cambio[0][1]], olv_limp->ias, thp,FALSE); + calcula_coste_1sec(ord_sec, &ss[cambio[1][1]], olv_limp->ias, thp,FALSE); + thp->milis_sleep=1; + } + //comprueba mejora o no----------------------- + desv=dame_desv_sec(n_sec,ss,TRUE); + + if(desvdesv) + { + desv_fut=desv; + ind_camb=i; + } + } + //se deshace el cambio-------------------------- + for (j=0; jn_amb>=MAX_AMBI_IGUALA_SEC && ind_camb>=0) + break; + } + if(ind_camb>=0) + { + cambio[0][0]=icerca[ind_camb*2];//se pone este + cambio[0][1]=aa[cambio[0][0]].sec; + cambio[1][0]=icerca[ind_camb*2+1];//con padre este + cambio[1][1]=aa[cambio[1][0]].sec; + namb_camb=1; + icamb[0]=cambio[0][0]; + icamb[1]=cambio[1][0]; + icamb[2]=cambio[0][0]; + for (j=0; jmilis_sleep=0; + calcula_coste_1sec(ord_sec, &ss[cambio[0][1]], olv_limp->ias, thp,FALSE); + calcula_coste_1sec(ord_sec, &ss[cambio[1][1]], olv_limp->ias, thp,FALSE); + thp->milis_sleep=1; + } + //comprueba mejora o no----------------------- + double desv_lastold=desv_last; + desv_last=dame_desv_sec(n_sec,ss,TRUE); + + if(desv_lastoldOJO -->El cambio selec empeora des_act:%lf desv_obt: %lf",desv_lastold, desv_last); + //se deshace el cambio-------------------------- + for (j=0; jOJO -->Se quita cambio y queda desv: %lf",desv_last); + hay_cambio=FALSE; + } + else + hay_cambio=TRUE; + } + else + { + hay_cambio=FALSE; + } + } while (TRUE); + //fin ---------------------------------------------------------- + + if(isec) + free(isec); + if(FALSE) + { + wgeotext(LOG_TODO,"olv_limp_t","------------------------------------------------"); + + for(i=0;icalc_nsec>0) + { + cost_med=olv_limp->calc_nsec; //impone el coste medio de los sectores, que es justo la jornada laboral + nsec--; //se quita un sector, el último, para el cálculo de la media + } + else + { + for(j=0;jcalc_nsec>0) && (dd>0)) + { + dd+=cost_med*nsec*2; + } + aux=abs(dd); + if(aux>cost_max) + cost_max=aux; + cost_med2+=dd*dd/nsec; + } + if(olv_limp->calc_nsec>0) + { + if(((ss[nsec].cost_ac-cost_med)>0))//si está en modo fijar jornada, tampoco queremos que se desmadre el último + { + aux=cost_med; + if(aux>cost_max) + cost_max=aux; + cost_med2+=cost_med*cost_med/nsec; + } + } + if(cost_med2>MINUSCULO) + cost_med2=sqrt(cost_med2); + else + cost_med2=0; + if(absol) + *absol=cost_max; + if(porc) + return cost_med2/cost_med; + else + return cost_med2; +} +//************************************************************************************* +/** + * Calcula diferencia minima y maxima de costes entre sectores + */ +double Colv_limp_thr::dame_mima(int nsec, Info_sec *ss, double *mini) +{ + int i; + int j; + double costmax=-MAYUSCULO; + double costmin=MAYUSCULO; + double dd; + + + //calcula la desviación típica + for(j=0;jcostmax) + costmax=dd; + if (ddiseq=aa[a].iseq; + inf->sec=aa[a].sec; + inf->t=aa[a].t; + + } + for (a=0; a &cost_amb, BYTE* st ) +{ + int i, k=0, s; + Info_est_amb *inf; + //prepara todo a 0--------------------- + for (i=0; iiseq; + aa[i].t=inf->t; + aa[i].sec=inf->sec; + s=inf->sec; + if(s>=0) + ss[s].iamb[ss[s].namb++]=i; + } + for (i=0; i &cost_amb, double *cost, BOOL inicia) +{ + int i, h; + if(inicia) + { + for (i=0; iias[i].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + if(aa[i].iseq!=iamb) + continue; + if(aa[i].res) + continue; + if(i==iamb) + continue; + aa[i].res=1; + *cost+=cost_amb[iamb][i]+cost_amb[i][i]; + if(iamb_r) + { + iamb_r[namb_r*2]=i; + iamb_r[namb_r*2+1]=iamb; + } + namb_r++; + if(namb_r>namb) + namb_r=namb_r; + if(aa[i].t>1) + namb_r=recorre_hijos(i,namb, aa, iamb_r, namb_r, cost_amb, cost, FALSE); + h--; + if(h<=-2) + break; + } + return namb_r; +} +//************************************************************************************* +/** + * Actualiza la matriz de costes de los ámbitos a otros ámbitos + */ +BOOL Colv_limp_thr::actualiza_costes( int namb,int n_sec, Info_amb_sec *aa, Info_sec *ss, Matrix2d &cost_amb ) +{ + + int s, a, i, na, k, kk, p; + double d; + BOOL res=TRUE; + for (a=0; a=namb) + continue; + na=ss[s].namb; + ss[s].namb=1; + ss[s].iamb[0]=a; + ss[s].cost_ac=cost_amb[a][a]; + aa[a].res=1; + while(TRUE) + { + k=-1; + d=MAYUSCULO; + for(i=0; icost_amb[kk][a]) + { + d=cost_amb[kk][a]; + p=kk; + k=a; + } + } + } + if (k<0) + { + break; + } + ss[s].cost_ac+=cost_amb[p][k]+cost_amb[k][k]; + aa[k].res=1; + ss[s].iamb[ss[s].namb++]=k; + } + if(na!=ss[s].namb) + res=FALSE; + + + } + + return res; +} +//************************************************************************************* +/** + * Calcula el coste de desplazamiento de ir de ir por todos los ambitos sec desde ini hasta fin + */ +double Colv_limp_thr::dame_coste( Secu_amb * sec, int ini, int fin, Info_aso *ias , Info_sec *s, BOOL ind_abs) +{ + double d=0; + int ind_cost,fin_old; + + fin_old=fin; + + while(iniiamb[sec[fin].iamb]; + else + ind_cost=sec[fin].iamb; + + d+=olv_limp->cost_amb[s->iamb[sec[fin].iamb]][s->iamb[sec[fin].iamb]]; + d+=olv_limp->arch_dj.dame_dis(s->iamb[sec[fin-1].iamb],(sec[fin-1].entrada+1)%2,s->iamb[sec[fin].iamb],sec[fin].entrada); + fin--; + } + d+=olv_limp->cost_amb[s->iamb[sec[ini].iamb]][s->iamb[sec[ini].iamb]]; + + if(ini==0)//si ini es 0 falta sumar el coste de la planta al primer ambito + { + if (ind_abs) + ind_cost=s->iamb[sec[ini].iamb]; + else + ind_cost=sec[ini].iamb; + if(olv_limp->nod_instal>=0) + { + int ee=0; + if(sec[ini].entrada>=0) + ee=sec[ini].entrada; + d+=olv_limp->arch_dj.dame_dis(olv_limp->arch_dj.id_instal,0,s->iamb[sec[ini].iamb],ee); + //d+=sec[ind_cost].ctnod[ee][olv_limp->nod_instal].dis; + } + else + d+=olv_limp->t_despl; + } + + //suma el coste de ir del ultimo ambito a la instalación + if(olv_limp->nod_instal>=0) + d+=olv_limp->ord_sec_plan[0].ctnod[0][ias[s->iamb[sec[fin_old].iamb]].ic[(sec[fin_old].entrada+1)%2]].dis; + else + d+=olv_limp->t_despl; + + return d; +} +//************************************************************************************* +/** + * Calcula el coste de desplazamiento de ir por todos los ambitos sec desde ini hasta fin + * cambiando el ámbito de pos_old como si estuviera en pos_new + */ +double Colv_limp_thr::dame_coste_ex( Secu_amb * sec, int ini, int fin, Info_aso *ias, Info_sec *s, int pos_old, int pos_new, int entrada ) +{ + double d=0; + int sig, act; + int a_ent, s_ent; + + while(iniarch_dj.dame_dis(sec[act].iamb,a_ent,s->iamb[sec[sig].iamb],(s_ent+1)%2); + d+=olv_limp->cost_amb[s->iamb[sec[act].iamb]][s->iamb[sec[act].iamb]]; + + ini++; + } + + act=Colv_geom::dame_ind_per(ini,pos_old,pos_new); + d+=olv_limp->cost_amb[s->iamb[sec[ini].iamb]][s->iamb[sec[ini].iamb]]; + return d; +} +//************************************************************************************* +/** + * Lee la sectorización que viene como info asociada en el shp de entrada + */ +BOOL Colv_limp_thr::lee_secto() +{ + BOOL ret; + int i,s; + char nfile[MAX_PATH]; + int *info; + + std::map> l_sec; + + wgeolog(LOG_TODO,"olv_limp_t","Comienza lectura de sectorización"); + pon_mi_progre(OLV_TAREA_LEE_SECTO, 0); + pon_mi_msg(""); + err_str[0]=0; + + ///////////////////////////////////// + info = (int *)malloc(olv_limp->n_amb*sizeof(int)); + if(!info) + { + sprintf_s(err_str,OLV_MAX_ERR,"Error, sin memoria para info asociada"); + return FALSE; + } + memset(info,0,olv_limp->n_amb*sizeof(int)); + + //lee dbf del shp la columna SECTOR + strcpy_s(nfile,MAX_PATH,olv->paths.path_data); + cambiaext(nfile,".shp",".dbf"); + if(!olv_limp->olv->olv_sh->dame_col_int_dbf(nfile,0,olv_limp->n_amb,info,olv_limp->camps.campo_secto,err_str,OLV_MAX_ERR)) + { + ret=FALSE; + goto fin; + } + + //rellena para cada sector info[i] qué ámbitos tiene + for(i=0;in_amb; i++) + { + if(olv_limp->ias[i].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + + l_sec[info[i]].push_back(i); + } + + + olv_limp->nsec=l_sec.size(); + + //////////////////////////////////////// + //inicia los arrays para la sectorización + if(!pide_memo_secto()) + { + sprintf_s(err_str,OLV_MAX_ERR,"Error, Sin memoria para lectura de sectorización"); + ret=FALSE; + goto fin; + } + + i=-1; + int ia=0; + //mira cuántos sectores diferentes hay + for (std::map>::iterator it=l_sec.begin(); it!=l_sec.end(); ++it) + { + i++; + olv_limp->sec[i].namb = it->second.size(); + for(int ia=0;iasec[i].namb;ia++) + { + olv_limp->sec[i].iamb[ia]=it->second[ia]; + olv_limp->amb_sec[it->second[ia]].sec = i; + } + } + + ////////////////////////////////////// + //lee del dbf la columna SECUENCIA por si se ha puesto uno por defecto + if(!olv_limp->olv->olv_sh->dame_col_int_dbf(nfile,0,olv_limp->n_amb,info,"SECUENCIA",err_str,OLV_MAX_ERR)) + { + ret=FALSE; + goto fin; + } + //si hay algún ámbito con secuencia "1" y no hay ya uno ámbito puesto como inicial en el sector, se pone + for(s=0;snsec;s++) + { + for(i=0;isec[s].namb;i++) + { + if(info[olv_limp->sec[s].iamb[i]]==1) + { + olv_limp->sec[s].iamb_ini_def=i; + break; + } + } + } + +fin: + + free(info); + + if(!ret) + { + pon_mi_msg("Error en lectura de info de sectorización: %s",err_str); + } + else + { + ////////////////////////////////////////////////////////////// + //pinta los sectores, solo en modo debug + for(int j=0;jn_amb;j++) + { + if(olv_limp->amb_sec[j].sec>=0) + (*olv_limp->olv->olv_ob->objt)[j].clase = 666 + olv_limp->amb_sec[j].sec; + } + } + + return ret; +} +//************************************************************************************* +/** + * Calcula el número de sectores óptimo para los ámbitos dados + */ +BOOL Colv_limp_thr::calcula_n_sec() +{ + BOOL ret; + int nsec; + double cost_tot,cost_sec; + + //////////////// + ret=TRUE; + nsec=-1; + //////////////// + + wgeolog(LOG_TODO,"olv_limp_t","Comienza cálculo del número de sectores"); + pon_mi_progre(OLV_TAREA_CALC_SEC, 0); + pon_mi_msg(""); + err_str[0]=0; + + //////////////// + olv_limp->nsec =olv_limp->nsec_act = 1; //se fija a un sector para planificar todo junto + + if(!pide_memo_secto()) + { + sprintf_s(err_str,OLV_MAX_ERR,"Error, Sin memoria"); + ret=FALSE; + goto fin; + } + + //hace la sectorización con un sector para que lo asigne por árbol + if(!sectoriza_1())//rellena Info_sec + { + sprintf_s(err_str,OLV_MAX_ERR,"Error en la primera sectorización"); + ret=FALSE; + goto fin; + } + //////////////////////////////// + + //calcula el coste de un sector con todos los ámbitos + cost_tot=olv_limp->sec[0].cost_ac;//calcula_cost_1sec_total(olv_limp->n_amb,olv_limp->sec,olv_limp->ias,olv_limp->conjs.n,olv_limp->cost_conj,olv_limp->ang_conj); + if(cost_tot>=MAYUSCULO) + { + sprintf_s(err_str,OLV_MAX_ERR,"Error en el cálculo del coste total de los ámbitos"); + ret=FALSE; + goto fin; + } + + //calcula el número de sectores, diviendo por el coste máximo de un sector + cost_sec = dame_cost_jornada(); + if(cost_sec<=0) + { + sprintf_s(err_str,OLV_MAX_ERR,"Tiempos de jornada, descanso y desplazamiento erróneos"); + ret=FALSE; + goto fin; + } + nsec = (int)(cost_tot/cost_sec) + 1; + //////////////// + olv_limp->calc_nsec=cost_sec; //se indica que el número de sectores es calculado, no impuesto + //////////////////////////////// + + //libera memoria + olv_limp->libera_memo_secto(); + //pone el número de sectores calculado + if(nsec==1) + { + olv_limp->nsec =olv_limp->nsec_act = nsec; + } + else + { + olv_limp->nsec = nsec + 2;//elena abr 2018 coge un margen de 2, excepto si le ha salido que es 1 + olv_limp->nsec_act = max(nsec,2); + } + ///////////////////////////////// + +fin: + if(!ret) + { + pon_mi_msg("Error en el cálculo del número de sectores: %s",err_str); + } + + return ret; +} +//************************************************************************************* +/** + * Calcula el tiempo efectivo de una jornada + */ +double Colv_limp_thr::dame_cost_jornada() +{ + return olv_limp->t_conv-olv_limp->t_desc; +} +//************************************************************************************* +/** + * Lanza la planificación de todos los ámbitos en un sector para calcular el coste total, y lo devuelve + * Devuelve también la secuencia de ámbitos planificada + */ +double Colv_limp_thr::calcula_cost_1sec_total(int n_amb, Info_sec *ss, Info_aso *ias, Djkt_ang_ady *ang_conj) +{ + double coste; + int nth,n_sec,i; + Secu_amb *ord_sec; + th_param_planif thp; + BOOL log_debug; + BOOL nocalc; + + //////////////// + log_debug=TRUE; + n_sec=1; + nth=Colv_geom::dame_n_nucleos(); + //inicia th + memset(&thp, 0, sizeof(thp)); + thp.milis_sleep=1; + thp.namb_t=n_amb; + nocalc=FALSE; + coste=0; + //////////////// + + ord_sec=olv_limp->ord_sec; + + //avisa de progreso + wgeolog(LOG_TODO,"olv_limp_t","Calculando permutaciones para mejorar al calcular coste de un sector total"); + pon_mi_progre(OLV_TAREA_PERMU,0); + //////// + + thp.dth=(th_data_planif*)malloc(sizeof(th_data_planif)*nth); + memset(thp.dth, 0, sizeof(th_data_planif)*nth); + thp.abs=TRUE; + + //lanza threads + for (i=0; i=0) + Sleep(1); + } + + if(!calcula_coste_sectores(ord_sec, ss, n_sec, ias, &thp, TRUE)) + { + coste=MAYUSCULO; + goto salir; + } + coste=ss[0].cost_ac; + +salir: + + //se bloquea y + thp.pirate=TRUE; + while(thp.nth>0) + Sleep(1); + + if(thp.dth) + { + if(thp.dth[0].sec) + free(thp.dth[0].sec); + free(thp.dth); + + } + return coste; +} +//************************************************************************************* +/** + * Devuelve la planificación de todos los sectores, en los que calcula la ruta óptima o cercana a la óptima + * que recorre los ámbitos de dicho sector + */ +BOOL Colv_limp_thr::planifica() +{ + wgeolog(LOG_TODO,"olv_limp_t","Comienza planificación"); + pon_mi_progre(OLV_TAREA_PLANIF, 0); + pon_mi_msg(""); + err_str[0]=0; + + //revisa si algún sector no tiene ámbitos + int ns=0; + for(int i=0;insec;i++) + { + if(olv_limp->sec[i].namb>0) + ns++; + } + olv_limp->nsec=ns; + + //inicializa el array de planificaciones + olv_limp->plan=(Info_planif*)malloc(olv_limp->nsec*sizeof(Info_planif)); + if(!olv_limp->plan) + { + pon_mi_msg("Error, sin memoria en array de planificación"); + return FALSE; + } + memset(olv_limp->plan,0,olv_limp->nsec*sizeof(Info_planif)); + + //lanza los threads + lanza_subthrs(OLV_LIMP_EV_PLANIFICA_SUB); + + return TRUE; +} +//************************************************************************************* +/** + * Devuelve la planificación del sector iésimo, que realiza el thread 'ithr' + */ +void Colv_limp_thr::planifica_sub_1(int ithr, Matrix2d &cost_amb) +{ + Info_sec *s; + Info_amb_sec *aa; + int i,iaux,is_ini,is_fin,is_desp,is,jmin; + BOOL log_debug=FALSE; + BOOL sal,sig; + Djkt_nodo *costes_nodos; + int nsecu,KK,ic_aux,ss,nsecu2; + Secu_amb *secu_ambi=NULL; + Param_olv_limp_thr pp; + Djkt_nodo* buf_nod=NULL; + costes_nodos=NULL; + int msecu1, msecu2; + msecu1 = msecu2 = olv_limp->conjs.n*2; + int *secu,*secu2; + secu=(int *)malloc(olv_limp->conjs.n*2*sizeof(int)); + + if(!secu) + { + sal=TRUE; + goto fin; + } + + buf_nod=olv_limp->arch_dj.dame_buf_nodos(); + if(!buf_nod) + { + sal=TRUE; + goto fin; + } + + memset(secu,0,olv_limp->conjs.n*2*sizeof(int)); + secu2=(int *)malloc(olv_limp->conjs.n*2*sizeof(int)); + if(!secu2) + { + sal=TRUE; + goto fin; + } + memset(secu2,0,olv_limp->conjs.n*2*sizeof(int)); + nsecu2=0; + ////////////////////////// + pp.id_e=OLV_TAREA_PLANIF;//manda de parámetro la tarea de la que es el progreso + ic_aux=0; + KK=olv_limp->tipo_ambit; + sal=sig=FALSE; + jmin=0; + prog_subthr=0; + aa=olv_limp->amb_sec; + iaux=-1; + + //////////////////////////////////////////////////// + //mira a ver cuántos sectores le tocan a este thread + if(olv_limp->nsecn_subthr) + { + //hay menos sectores que threads, o le toca uno o ninguno + if(ithrnsec) + { + //solo hace un sector, el ithr-esimo + is_ini=ithr; + is_fin=ithr+1; + } + else + { + //no hace ningún sector, no hace falta + is_ini=0; + is_fin=0; + } + } + else + { + //hay más sectores que threads, le tocan más de uno + is_desp=(int)ceil(1.0*(olv_limp->nsec)/n_subthr); + is_ini=ithr*is_desp; + is_fin=min((ithr+1)*is_desp,olv_limp->nsec); + } + ////////////////////////// + if(is_fin==is_ini) + wgeolog(LOG_TODO,"olv_limp_t","Subthr %02d, No Planifica ningún sector", ithr); + else if(is_fin-is_ini-1==0) + wgeolog(LOG_TODO,"olv_limp_t","Subthr %02d, Planifica sector %02d", ithr,is_ini); + else + wgeolog(LOG_TODO,"olv_limp_t","Subthr %02d, Planifica sectores %02d a %02d", ithr,is_ini, is_fin-1); + + + ////////////////////////// + //bucle en todos los sectores que le tocan al thread + for(is=is_ini;issec[is]; + if(s->namb<=0) + continue; + s->cost_despl_aux=0; + sig=FALSE; + + //busca el ámbito inicial de la planificiación + secu_ambi=planifica_sect(s,olv_limp->ang_conj, olv_limp->ias, OLV_LIMP_FACT_PERM); + if(!secu_ambi) + { + wgeolog(LOG_TODO,"olv_limp_t","Subthr %ld, Imposible planificar sector %02d",ithr,is); + sal=TRUE; + continue; + } + if(esta_repe(secu_ambi, s->namb)) + { + wgeolog(LOG_TODO,"olv_limp_t","Esta repe despues de planifica sec"); + sal=TRUE; + continue; + } + + /////////////////////////////////////////// + //Añade la ruta de la instalación al primer punto + if(olv_limp->nod_instal>=0 && olv_limp->ord_sec_plan) + { + olv_limp->arch_dj.get_b(s->iamb[secu_ambi[0].iamb],secu_ambi[0].entrada,buf_nod); + Colv_geom::ruta_dj_inv_ok( + olv_limp->nod_instal,//id conjuncion inicial + &secu2[0], //puntero a secuencia + buf_nod, //nodos djktra conj final + olv_limp->conjs.n, + &nsecu2); + + if(!genera_planif_instala(is, 0, 0, nsecu2, secu2, OLV_IDA_INST)) + sal=TRUE; + } + /////////////////////////////////////////// + + ss=1; + s->cost_despl_aux=olv_limp->cost_amb[s->iamb[secu_ambi[0].iamb]][s->iamb[secu_ambi[0].iamb]]; + s->cost_despl_aux+=s->t_despl[0];//el desplazamiento de la instalación al primer ámbito + secu[0]=olv_limp->ias[s->iamb[secu_ambi[0].iamb]].ic[secu_ambi[0].entrada]; + + //almacena el coste acumulado + aa[s->iamb[secu_ambi[0].iamb]].iseq=0; + double cc, cc1=0; + for (i=1; inamb; i++) + { + olv_limp->arch_dj.get_b(s->iamb[secu_ambi[i].iamb],secu_ambi[i].entrada, buf_nod); + cc=Colv_geom::ruta_dj_inv_ok( + olv_limp->ias[s->iamb[secu_ambi[i-1].iamb]].ic[(secu_ambi[i-1].entrada+1)%2],//id conjuncion final + &secu[ss], //puntero a secuencia + buf_nod, //nodos djktra conj inicial + olv_limp->conjs.n, + &nsecu); + ss+=nsecu; + s->cost_despl_aux+=(float)cc; + s->cost_despl_aux+=olv_limp->cost_amb[s->iamb[secu_ambi[i].iamb]][s->iamb[secu_ambi[i].iamb]]; + + //almacena el coste acumulado + aa[s->iamb[secu_ambi[i].iamb]].iseq=i; + cc1+=olv_limp->arch_dj.dame_dis(s->iamb[secu_ambi[i-1].iamb],(secu_ambi[i-1].entrada+1)%2,s->iamb[secu_ambi[i].iamb], secu_ambi[i].entrada); + + ////////////////// + if((i%50)==0 || (i==s->namb-1)) + { + //avisa de progreso + wgeolog(LOG_TODO,"olv_limp_t","Subthr %ld, Planificando sector %02d, amb %ld de %ld", ithr,is, + (i+1),(s->namb)); + prog_subthr=(1.0*(i+1)/(s->namb))*((is+1)/(is_fin-is_ini)); //porque son varios sectores + thr_padre->encola(OLV_LIMP_EV_SUBTHR_PROG,&pp,FALSE); + } + ///////////////// + + } + if(olv_limp->tipo_ambit==OLV_AMB_LIN)//añade el coste del último ámbito si es lineal + { + secu[ss++]=olv_limp->ias[s->iamb[secu_ambi[s->namb-1].iamb]].ic[(secu_ambi[s->namb-1].entrada+1)%2]; + } + s->cost_despl_aux+=s->t_despl[1];//el desplazamiento del último ámbito a la instalación + + if(esta_repe(secu_ambi, s->namb, FALSE)) + wgeolog(LOG_TODO,"olv_limp_t","Esta repe despues de planificar"); + + wgeolog(LOG_TODO,"olv_limp_t","Subthr %ld, Planificando sector %02d, coste total %lf",ithr,is,s->cost_despl_aux); + + /////////////////////////////////////////// + //Ruta del último punto a la instalación + if(olv_limp->nod_instal>=0 && olv_limp->ord_sec_plan) + { + + Colv_geom::ruta_dj_inv_ok( + olv_limp->ias[s->iamb[secu_ambi[s->namb-1].iamb]].ic[(secu_ambi[s->namb-1].entrada+1)%2], + &secu2[0], //puntero a secuencia + olv_limp->ord_sec_plan[0].ctnod[0], //nodos djktra conj final + olv_limp->conjs.n, + &nsecu2); + if(!genera_planif_instala(is, 0, 0, nsecu2, secu2, OLV_VUELTA_INST)) + { + sal=TRUE; + break; + } + } + /////////////////////////////////////////// + + if(!pirate && !sal) + { + ////////////////////////////////// + //genera la ruta y los puntos de control + if(!genera_planif(is,s->cost_despl_aux, ss, secu,OLV_PLAN_NORMAL)) + sal=TRUE; + + } + ////////////////////////////////// + if( secu_ambi) + { + free(secu_ambi); + secu_ambi=NULL; + } + } + free(secu); + free(secu2); +fin: + //Ha terminado, encola al padre + olv_limp->arch_dj.libera_buf(buf_nod); + if(sal) + { + prog_subthr=-1;//para avisar al padre de que ha habido un error + } + thr_padre->encola(OLV_LIMP_EV_PLANIFICA_FIN,NULL,FALSE); +} +//************************************************************************************* +/** + * Finaliza y centraliza tareas de planificar, cuando han acabado todos los threads + */ +BOOL Colv_limp_thr::planifica_fin() +{ + + //para los threads + para_subthrs(); + err_str[0]=0; + + /////////////////////////////////////// + //Si es barrido mixto hay que copiar la info en las que no se ha sectorizado + if(olv_limp->barr_mix) + copia_info_barr_mix(); + + //Inicia los obg + ob_rut = new Cobgeo(); + ob_ctrl = new Cobgeo(); + ob_flech = new Cobgeo(); + ob_inst = new Cobgeo(); + ob_inst_fl= new Cobgeo(); + memcpy(&ob_inst_fl->nvl,&olv_limp->olv->olv_ob->nvl,sizeof(Niveles)); + memcpy(&ob_inst->nvl,&olv_limp->olv->olv_ob->nvl,sizeof(Niveles)); + memcpy(&ob_rut->nvl,&olv_limp->olv->olv_ob->nvl,sizeof(Niveles)); + memcpy(&ob_flech->nvl,&olv_limp->olv->olv_ob->nvl,sizeof(Niveles)); + memcpy(&ob_ctrl->nvl,&olv_limp->olv->olv_ob->nvl,sizeof(Niveles)); + + /////////////////////////////////// + //prepara los datos para guardarlos + if(!genera_obg_rut_ctrl(olv_limp->nsec, olv_limp->plan, ob_rut, ob_ctrl)) + { + pon_mi_msg("Errores en la generación de cartografía con ruta"); + return FALSE; + } + //genera el listado del itinerario + if(!genera_list_rut_ctrl(ob_rut)) + { + pon_mi_msg("Errores en la generación del listado de la ruta: %s",err_str); + return FALSE; + } + //graba a archivo el obg + if(!guarda_shp_rut_ctrl(ob_rut, ob_ctrl)) + { + pon_mi_msg("Errores en el guardado a shp de la ruta: %s",err_str); + return FALSE; + } + + if(!guarda_dbf_sector(2)) + { + pon_mi_msg("Errores en la generación de información asociada de sector: %s",err_str); + return FALSE; + } + /////////////////////////////////// + + ///////////////////////////////////////////// + //A continuación genera y graba los archivos de los subtramos de cada ruta + if(!gen_guard_subtramos()) + return FALSE; + /////////////////////////////////// + + wgeolog(LOG_TODO,"olv_limp_t","Planificación finalizada"); + + return TRUE; +} +//************************************************************************************* +/** + * Dada la secuencia de las conjunciones que sigue la ruta, genera la ruta diciendo por qué + * elementos de la red pasa y coloca los puntos de control + */ +BOOL Colv_limp_thr::genera_planif(int is, double cost_sec, int nsecu, int *secu, int tip_plan) +{ + int npt_ctrl,ipc; + double cost_ctrl; + Info_planif *pp; + + wgeolog(LOG_TODO,"olv_limp_t","Almacenando planificación sector %02d",is); + + ///////////////// + cost_ctrl=(cost_sec-olv_limp->sec[is].t_despl[0]-olv_limp->sec[is].t_despl[1])/(olv_limp->npts_ctrl-2+1); + ipc=0; + npt_ctrl=(olv_limp->npts_ctrl-2); + pp=&olv_limp->plan[is]; + + if(!genera_planif_aux(is,&olv_limp->sec[is], pp, nsecu, secu,tip_plan)) + return FALSE; + + pon_ptos_ctrl(pp, npt_ctrl, cost_ctrl); + + ////////////////////////////////////////////////////////// + + olv_limp->sec[is].cost_ac=(float)cost_sec; + + return TRUE; +} +//************************************************************************************* +/** + */ +void Colv_limp_thr::pon_ptos_ctrl(Info_planif *pp, int npt_ctrl, double cost_ctrl) +{ + double cost_acum; + int i, ipc; + /////////////////////////////////////////////////////////////// + //Inicializa el array de puntos de control + pp->pts_ctrl=(Info_planif_ctrl*)malloc((olv_limp->npts_ctrl-2+1)*sizeof(Info_planif_ctrl)); + if(!pp->pts_ctrl) + return; + memset(pp->pts_ctrl,0,(olv_limp->npts_ctrl-2+1)*sizeof(Info_planif_ctrl)); + ipc=0; + + cost_acum=0; + for(i=0;inelem;i++) + { + ///////////////////////////// + cost_acum=pp->elem[i].coste; + //mira si toca punto de control + if((cost_acum-ipc*(cost_ctrl/*+olv_limp->t_desc*/))>(cost_ctrl+1)) + { + if(ipcpts_ctrl[ipc].ipt=i-1; + ipc++; + } + else + ipc=ipc; + } + } + + for(i=0;ipts_ctrl[i].ipt<0) + pp->pts_ctrl[i].ipt=pp->nelem-1; + } +} +//************************************************************************************* +/** + * Dada la secuencia de las conjunciones que sigue la ruta, genera la ruta diciendo por qué + * elementos de la red pasa y coloca los puntos de control - Función auxiliar + */ +BOOL Colv_limp_thr::genera_planif_aux(int is, Info_sec *ss, Info_planif *pp, int nsecu, int *secu, int tip_plan) +{ + int i,j,npt,il,indx,npt_ctrl,nelesec,ia_nw,tp,namb,last_pt,dt,k,itr; + double (*ptos)[3], cost_parc_aux,ltot,cost, cost_perd; + Cobgeo *ob; + BOOL sal,sdire,log_debug,is_descarg,is_uno; + BYTE *ambs_sec; + + ///////////////// + ob=olv_limp->olv->olv_ob; + sal=FALSE; + npt_ctrl=(olv_limp->npts_ctrl-2); + cost_parc_aux=0; + nelesec=0; + namb=0; + log_debug=FALSE; + last_pt=-1; + is_descarg=FALSE; + is_uno=FALSE; + + if(nsecu==1) + { + is_uno=TRUE; + nsecu=2; + } + + //Inicializa los arrays de elementos + pp->nelem = nsecu-1; + //ielem + pp->elem=(Info_elem_planif*)malloc(pp->nelem*sizeof(Info_elem_planif)); + if(!pp->elem) + return FALSE; + memset(pp->elem,0,pp->nelem*sizeof(Info_elem_planif)); + ////////////////////////////////////////////////////////////////// + itr=0; + + ////////////////////////////////////////////////////////////////// + //si es un único elemento + if(is_uno) + { + //recorre los ámbitos buscándolo + for(j=0;jvect.nobj;j++) + { + if((*ob->objt)[j].tipo != OBJ_LINEAL) + continue; + if(secu[0]==olv_limp->ias[(*ob->objt)[j].ia].ic_ini || + secu[0]==olv_limp->ias[(*ob->objt)[j].ia].ic_fin) + break; + } + if(j>=ob->vect.nobj) + { + return FALSE; + } + i=olv_limp->ias[(*ob->objt)[j].ia].ishp; + cost=olv_limp->cost_amb[i][i]; + dt=OLV_TTO; + + //añade la info del elemento + pp->elem[0].i=j; + pp->elem[0].k=0; + pp->elem[0].tp = OLV_PLAN_TIP_AMB; + pp->elem[0].ia_nw = 0; + pp->elem[0].coste = cost; + pp->elem[0].ltot = 0; + pp->t[dt]=cost; + pp->m[dt]=0; + return TRUE; + } + ////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////// + ambs_sec=(BYTE*)malloc(ss->namb); + if(!ambs_sec) + return FALSE; + memset(ambs_sec,0,ss->namb); + + //bucle para cada conjunción de la secuencia + for(i=0;ivect.nobj;j++) + { + if((*ob->objt)[j].tipo != OBJ_LINEAL) + continue; + + if((olv_limp->ias[(*ob->objt)[j].ia].flgs & + (OLV_LIMP_FLG_AMB | OLV_LIMP_FLG_SEG_PUN | OLV_LIMP_FLG_SEG_LIN | OLV_LIMP_FLG_PEAT_REP | OLV_LIMP_FLG_PEAT_SEG))&& + !(olv_limp->ias[(*ob->objt)[j].ia].flgs & OLV_LIMP_FLG_SEG_AMB)) + { + //busca por las conjunciones almacenadas + sdire=((secu[i]==olv_limp->ias[(*ob->objt)[j].ia].ic_ini)&& + (secu[i+1]==olv_limp->ias[(*ob->objt)[j].ia].ic_fin)); + if(sdire || + (((secu[i+1]==olv_limp->ias[(*ob->objt)[j].ia].ic_ini)&& + (secu[i]==olv_limp->ias[(*ob->objt)[j].ia].ic_fin)))) + { + break; + } + } + else + { + //es un segmento de carretera, hay que buscar la conjunción + il=(*ob->objt)[j].indx; + npt = (*ob->lial)[il].n; + indx=(*ob->lial)[il].indx; + ptos = &(*ob->ptos)[indx]; + + //busca el lineal que esté entre esta conjunción y la siguiente + sdire=( + ((olv_limp->conjs.coor[secu[i]][0]==ptos[0][0]) && + (olv_limp->conjs.coor[secu[i]][1]==ptos[0][1])) && + ((olv_limp->conjs.coor[secu[i+1]][0]==ptos[(npt-1)][0]) && + (olv_limp->conjs.coor[secu[i+1]][1]==ptos[(npt-1)][1])) + ); + if(sdire || + ( + ((olv_limp->conjs.coor[secu[i]][0]==ptos[(npt-1)][0]) && + (olv_limp->conjs.coor[secu[i]][1]==ptos[(npt-1)][1])) && + ((olv_limp->conjs.coor[secu[i+1]][0]==ptos[0][0]) && + (olv_limp->conjs.coor[secu[i+1]][1]==ptos[0][1])) + )) + { + break; + } + } + } + if(j>=ob->vect.nobj) + { + sal=TRUE; + continue; + } + + //calcula la longitud + il=(*ob->objt)[j].indx; + npt = (*ob->lial)[il].n; + indx=(*ob->lial)[il].indx; + ptos = &(*ob->ptos)[indx]; + ltot = long_linea((double (*)[][3]) ptos,npt,NULL,NULL,NULL,NULL); + cost=olv_limp->cost_conj[secu[i]][secu[i+1]]; + dt=OLV_DT_N; + ///////////////////////////// + //mira a ver si es carretera o amb para poner inw + if(olv_limp->ias[(*ob->objt)[j].ia].flgs & OLV_LIMP_FLG_AMB) //es ámbito + { + ia_nw=olv_limp->inww_amb[j+!sdire*olv_limp->n_amb].inw; + + /////////////////////////////////// + //si no pertenece a los ámbitos de este sector o ya ha pasado por él, + //es que está desplazándose por él, le pone tipo nw + for(k=0;knamb;k++) + { + if(ss->iamb[k]==(*ob->objt)[j].ia) + break; + } + if(k>=ss->namb || ambs_sec[k]) + { + tp=OLV_PLAN_TIP_NW; + dt=OLV_DESP; + } + else + { + /////////////////////////////////// + if(olv_limp->ias[(*ob->objt)[j].ia].flgs & OLV_LIMP_FLG_PEAT) + tp=OLV_PLAN_TIP_AMB_PEAT; + else + tp=OLV_PLAN_TIP_AMB; + + dt=OLV_TTO; + namb++; + ambs_sec[k]=1; + } + + } + else if(olv_limp->ias[(*ob->objt)[j].ia].flgs & OLV_LIMP_FLG_SEG_LIN) //es segmento de ámbito + { + if(olv_limp->ias[(*ob->objt)[j].ia].flgs & OLV_LIMP_FLG_FIN) + ia_nw=olv_limp->inww_amb[olv_limp->ias[(*ob->objt)[j].ia].ishp+olv_limp->n_amb].inw; + else + ia_nw = olv_limp->inww_amb[olv_limp->ias[(*ob->objt)[j].ia].ishp].inw; + tp=OLV_PLAN_TIP_SEG_LIN; + ltot=0; + } + else if(olv_limp->ias[(*ob->objt)[j].ia].flgs & OLV_LIMP_FLG_SEG_PUN) + { + ia_nw = olv_limp->inww_amb[olv_limp->ias[(*ob->objt)[j].ia].ishp].inw; + tp=OLV_PLAN_TIP_AMB; + ltot=0; + if((last_pt==olv_limp->ias[(*ob->objt)[j].ia].ishp) || (tip_plan==OLV_PLAN_INST)) + { + cost=0; + tp=OLV_PLAN_TIP_NW; + } + else + { + cost=olv_limp->cost_amb[olv_limp->ias[(*ob->objt)[j].ia].ishp][olv_limp->ias[(*ob->objt)[j].ia].ishp]; + last_pt=olv_limp->ias[(*ob->objt)[j].ia].ishp; + dt=OLV_TTO; + } + } + else if(olv_limp->ias[(*ob->objt)[j].ia].flgs & OLV_LIMP_FLG_PEAT_REP) + { + tp=OLV_PLAN_TIP_AMB_PEAT_DESP; + //en info0 se ha guardado la peatonal original + ia_nw=olv_limp->inww_amb[olv_limp->ias[(*ob->objt)[j].ia].info0+!sdire*olv_limp->n_amb].inw; + dt=OLV_DESP; + } + else if(olv_limp->ias[(*ob->objt)[j].ia].flgs & OLV_LIMP_FLG_PEAT_SEG) + { + continue; + } + else//es carretera + { + ia_nw=(*ob->objt)[j].ia; + tp=OLV_PLAN_TIP_NW; + dt=OLV_DESP; + } + + //////////////////// + if(is_descarg && (tp!=OLV_PLAN_TIP_AMB)) + { + cost_perd+=cost; + cost=ltot=0; + } + //////////////////// + if((ltot==0) && (dt!=OLV_TTO)) + cost=0; + ////// + //calcula coste acumulado + if(nelesec>0) + cost_parc_aux=pp->elem[nelesec-1].coste; + else + cost_parc_aux=0; + //añade la info del elemento + pp->elem[nelesec].i=j; + pp->elem[nelesec].k=!sdire; + pp->elem[nelesec].tp = tp; + pp->elem[nelesec].ia_nw = ia_nw; + pp->elem[nelesec].coste = cost_parc_aux + cost; + pp->elem[nelesec].ltot = ltot; + pp->elem[nelesec].aux=0; + + if(log_debug) + wgeolog(LOG_TODO,"olv_limp_t","Plan sec, nelesec %03d j %04d k %ld t %ld ia_nw %04d cost %lf ", + nelesec,j,!sdire,tp,ia_nw,pp->elem[nelesec].coste); + + + ////////////// + if(dtuds_tto==OliviaDef::GeneralDef::OlvTipTtoM2h) && (dt==OLV_TTO)) + pp->m[dt]+=(ltot*olv_limp->ias[pp->elem[i].i].info1); + else + pp->m[dt]+=ltot; + pp->t[dt]+=cost; + } + + ////////////// + if((tip_plan==OLV_PLAN_RECO) && (tp==OLV_PLAN_TIP_AMB)) + { + pp->elem[nelesec].aux=itr;//marca los tramos + if(comprueba_descarg(olv_limp->ias[(*ob->objt)[j].ia].ishp)) + itr++; + if((!is_descarg && comprueba_descarg(olv_limp->ias[(*ob->objt)[j].ia].ishp)) + || (is_descarg && !comprueba_descarg(olv_limp->ias[(*ob->objt)[j].ia].ishp))) + { + cost_perd=0; + is_descarg=!is_descarg; + } + + } + ////////////// + nelesec++; + } + if(sal) + { + free(ambs_sec); + return FALSE; + } + + pp->nelem = nelesec; + + free(ambs_sec); + return TRUE; +} +//************************************************************************************* +/** + * Comprueba si en este elemento se va a descargar y en ese caso no se cuenta el desplazamiento hasta el siguiente + */ +BOOL Colv_limp_thr::comprueba_descarg(int iamb) +{ + return FALSE; +} +//************************************************************************************* +/** + * Dada la secuencia de las conjunciones que sigue la ruta para ir y volver de la instalación, genera la planificación + */ +BOOL Colv_limp_thr::genera_planif_instala(int is, int nvaciados, int ini, int fin, int *secu, int tip_viaje) +{ + int i; + Info_planif *pp,*pp_insta; + Info_sec *ss; + + ss=&olv_limp->sec[is]; + pp=&olv_limp->plan[is]; + pp_insta = pp->planif_insta; + if(!pp_insta) + { + //inicializa, sólo la primera vez + //cuenta el número de veces que va a vaciar + pp->ninsta=2;//inicialmente tiene la ida y la vuelta a la instalación + if(nvaciados) + pp->ninsta+=nvaciados*2-1; //todos los vaciados son ida y vuelta + pp_insta = (Info_planif *)malloc(pp->ninsta*sizeof(Info_planif)); + if(!pp_insta) + return FALSE; + memset(pp_insta,0,pp->ninsta*sizeof(Info_planif)); + + pp_insta[0].ninsta=OLV_IDA_INST; + pp_insta[pp->ninsta-1].ninsta=OLV_VUELTA_INST; + + } + + //busca cuál le toca rellenar + for(i=0;ininsta;i++) + { + if(pp_insta[i].nelem==0) + break; + } + if(i>=pp->ninsta) + return FALSE; + + if(!genera_planif_aux(is,ss, &pp_insta[i],fin-ini,&secu[ini],OLV_PLAN_INST)) + return FALSE; + + pp_insta[i].ninsta=tip_viaje; + olv_limp->plan[is].planif_insta = pp_insta; + return TRUE; +} +//************************************************************************************* +/** + * Dadas las rutas de los sectores, genera la ruta en una única línea en el obg + * y en otro coloca los puntos de control + */ +BOOL Colv_limp_thr::genera_obg_rut_ctrl(int ns, Info_planif *planif, Cobgeo *ob_rut, Cobgeo *ob_ctrl) +{ + int is,il,npt,indx,i,k,ic,nmax_pts,ins; + Cobgeo *ob; + BOOL mal; + double (*ptos)[3], pt[3]; + Objgeo *lineal; + Info_planif *pp; + Objgeo *lineal_fl; + double long_fl, long_max_fl; + + //////////////// + long_max_fl=15; + long_fl=1; + //////////////// + + wgeolog(LOG_TODO,"olv_limp_t","Generando lineales de las rutas en obg"); + + ///////////////// + ob=olv_limp->olv->olv_ob; + mal=FALSE; + lineal=NULL; + nmax_pts=0; + ///////////////// + + //Inicializar + lineal= new Objgeo; + if(!lineal) + { + return FALSE; + } + lineal->tipo = OBJ_LINEAL; + lineal->flags[0] = 0; + lineal->flags[1] = 0; + lineal->ev.id = 0; + lineal->pt.lin = (Linealgeo*) malloc (sizeof(Linealgeo)); + if(!lineal->pt.lin) + { + return FALSE; + } + lineal->pt.lin->n= 0; + lineal->pt.lin->flags=0; + lineal->pt.lin->ptos = NULL; + /////////////////////// + //Inicializar flechas + lineal_fl= new Objgeo; + if(!lineal_fl) + { + return FALSE; + } + lineal_fl->tipo = OBJ_LINEAL; + lineal_fl->flags[0] = 0; + lineal_fl->flags[1] = 0; + lineal_fl->ev.id = 0; + lineal_fl->pt.lin = (Linealgeo*) malloc (sizeof(Linealgeo)); + if(!lineal_fl->pt.lin) + { + return FALSE; + } + lineal_fl->pt.lin->n= 2; + lineal_fl->pt.lin->flags=0; + lineal_fl->pt.lin->ptos = (double (*)[][3]) malloc(2 * 3 * sizeof(double)); + if(!lineal_fl->pt.lin->ptos) + { + return FALSE; + } + + /////////////////////////////////////////////// + //Genera el obg de la ruta, un lineal por sector (o varios por sector si hay idas a recogida) + for(is=0;isia = is+1;//le suma uno para que sea empezando en 1 y no en 0 + lineal->clase = OLV_ICLA_LIN_RUT+is; + + lineal_fl->ia = is+1;//le suma uno para que sea empezando en 1 y no en 0 + lineal_fl->clase=OLV_ICLA_LIN_RUT+is; + + if(!genera_obg_rut_aux(pp, ob_rut, ob_flech,lineal,&nmax_pts, lineal_fl, FALSE,0,pp->nelem)) + { + mal=TRUE; + break; + + } + + for(ins=0;insninsta;ins++) + { + //solo entra aquí si hay ruta a las instalaciones + if(!genera_obg_rut_aux(&pp->planif_insta[ins], ob_inst, ob_inst_fl,lineal,&nmax_pts, lineal_fl, TRUE,0,pp->planif_insta[ins].nelem)) + { + mal=TRUE; + break; + } + } + + } + + ob_rut->libera_objgeo(lineal); + delete lineal; + lineal=NULL; + ob_rut->libera_objgeo(lineal_fl); + delete lineal_fl; + lineal_fl=NULL; + + /////////////////////////////////////////////// + //Genera el obg de los puntos + if(ob_ctrl) + { + int ie; + int isfin; + for(is=0;isnpts_ctrl;i++) + { + if(pp->nelem==0) + { + memcpy(pt,ob_ctrl->nvl.ogtb,2*sizeof(double));//para rutas vacías, lo rellena con 0 + } + else + { + isfin=0; + if(i==0) + ie=0; //el punto de control primero está en el primer elemento + else if(i==olv_limp->npts_ctrl-1) + { + ie=pp->nelem-1;//el punto de control último está en el último elemento + isfin=1; + } + else + ie=pp->pts_ctrl[i-1].ipt;//los puntos de control intermedios, los que se han calculado + ic=pp->elem[ie].i; + + il=(*ob->objt)[ic].indx; + indx=(*ob->lial)[il].indx; + npt = (*ob->lial)[il].n; + ptos = &(*ob->ptos)[indx]; + k=(pp->elem[ie].k+isfin)%2; //porque si es el punto de control final, lo tiene que poner al final + //del tramo, no al principio, y + + memcpy(pt,ptos[k*(npt-1)],3*sizeof(double)); + } + mal=!Colv_geom::pon_pto((double(*)[3])pt, OLV_ICLA_PUN_CON+is,is+1, ob_ctrl); + } + } + + if(lineal) + { + ob_rut->libera_objgeo(lineal); + delete lineal; + } + } + + if(mal) + return FALSE; + + return TRUE; +} +//************************************************************************************* +/** + * Dadas las rutas de los sectores, genera la ruta en una única línea en el obg + * y en otro coloca los puntos de control - Función auxiliar + */ +BOOL Colv_limp_thr::genera_obg_rut_aux(Info_planif *pp, Cobgeo *ob_rut, Cobgeo *ob_flech,Objgeo *lineal,int *nmax_pts, Objgeo *lineal_fl, BOOL is_insta, int ie_ini, int ie_fin) +{ + int il,npt,indx,npt_tot,i,npt_parc,k; + Cobgeo *ob; + BOOL mal; + double (*ptos)[3], pt[3],(*ptos_aux)[3]; + double (*pts_lin)[3]; + double (*pts_lin_fl)[3]; + double ltot, long_max_fl; + int nfl; + + //////////////// + long_max_fl=5; + //////////////// + ob=olv_limp->olv->olv_ob; + mal=FALSE; + ///////////////// + + if(pp->nelem==0 && is_insta) + return TRUE; + if(pp->nelem==0 && !is_insta) + npt_tot=2; + else + { + npt_tot=0; + //Contar puntos + for(i=ie_ini;iobjt)[pp->elem[i].i].indx; + npt = (*ob->lial)[il].n; + npt_tot += npt-1; + } + npt_tot++; + } + + lineal->pt.lin->n= npt_tot; + + ptos_aux=(double (*)[3])lineal->pt.lin->ptos; + //pide memoria para los puntos si hace falta + if(npt_tot>*nmax_pts) + { + ptos_aux = (double (*)[3]) realloc(lineal->pt.lin->ptos,npt_tot * 3 * sizeof(double)); + *nmax_pts=npt_tot; + } + if(!ptos_aux) + { + return FALSE; + } + pts_lin = ptos_aux; + + npt_parc=0;//num de puntos parcial + double (*ptos_par)[3]; + double d; + //Añadir puntos + for(i=ie_ini;iobjt)[pp->elem[i].i].indx; + indx=(*ob->lial)[il].indx; + npt = (*ob->lial)[il].n; + ptos = &(*ob->ptos)[indx]; + ptos_par=NULL; + + //si es carretera y es de doble sentido, + //hace la paralela a una distancia dada para que no se superpongan la ida y la vuelta + if((pp->elem[i].tp==OLV_PLAN_TIP_NW) && !((olv_limp->ias[pp->elem[i].ia_nw].flgs & OLV_LIMP_FLG_CIRC_NO_DOB))) + { + d=OLV_DIST_PARALELAS; + if(pp->elem[i].k==0) + d=d*(-1);//distancia negativa si es sentido contrario + Colv_geom::haz_paralela(ptos,npt,d,&ptos_par); + ptos=(double (*)[3])ptos_par; + } + + memcpy(pts_lin[npt_parc],ptos,npt*3*sizeof(double)); + + ///////////////////////// + //por si hay que darle la vuelta a los puntos + if(pp->elem[i].k==1) + { + for(k=0;knelem==0 && !is_insta) + { + memcpy(pts_lin,ob_rut->nvl.ogtb,2*sizeof(double)); + } + lineal->pt.lin->ptos = (double (*)[][3])pts_lin; + lineal->pt.lin->flags = 0; + if(ob_rut->pon_obj(lineal)<0) + { + return FALSE; + } + + if(pp->nelem==0 && !is_insta) + { + pts_lin_fl= (double (*)[3])lineal_fl->pt.lin->ptos; + memcpy(pts_lin_fl[0],ob_rut->nvl.ogtb,2*sizeof(double)); + memcpy(pts_lin_fl[1],ob_rut->nvl.ogtb,2*sizeof(double)); + if(ob_flech->pon_obj(lineal_fl)<0) + { + return FALSE; + } + return TRUE; + } + + ///////////////////////////////// + //Pone las flechas a lo largo de la línea + nfl=0; + pts_lin_fl= (double (*)[3])lineal_fl->pt.lin->ptos; + ltot=long_linea((double (*)[][3]) pts_lin,npt_tot,NULL,NULL,NULL,NULL); + nfl=(int)(ltot/long_max_fl); + for(i=0;ipt.lin->flags = 0; + if(ob_flech->pon_obj(lineal_fl)<0) + { + break; + } + } + if(iolv->paths.path_res_rut); + cambiaext(path_shp,".shp",""); + strcat_s(path_shp,"_R.shp"); + if(!olv_limp->olv->olv_sh->guarda_shp(path_shp,ob_rut,TIPO_ENT_LINEA,olv_limp->camps.campo_secto,TIPO_IA_INT)) + return FALSE; + if(!guarda_cols_ruta(path_shp)) + return FALSE; + + /////////////////////////////////////////////////////// + //luego graba los archivos de los puntos de control + //graba todos los sectores en un único path + strcpy_s(path_shp,MAX_PATH,olv_limp->olv->paths.path_res_pt); + cambiaext(path_shp,".shp",""); + strcat_s(path_shp,"_C.shp"); + if(!olv_limp->olv->olv_sh->guarda_shp(path_shp,ob_ctrl,TIPO_ENT_PUNTO,olv_limp->camps.campo_secto,TIPO_IA_INT)) + return FALSE; + if(!guarda_cols_ctrl(path_shp)) + return FALSE; + + ///////////////////////////////////////////// + //A continuación graba los archivos de las flechas + strcpy_s(path_shp,MAX_PATH,olv_limp->olv->paths.path_res_rut); + cambiaext(path_shp,".shp",""); + strcat_s(path_shp,"_Raux.shp"); + if(!olv_limp->olv->olv_sh->guarda_shp(path_shp,ob_flech,TIPO_ENT_LINEA,olv_limp->camps.campo_secto,TIPO_IA_INT)) + return FALSE; + + ///////////////////////////////////////////// + //A continuación graba los archivos de los viajes a las instalaciones + if(olv_limp->nod_instal>=0) + { + strcpy_s(path_shp,MAX_PATH,olv_limp->olv->paths.path_res_rut); + cambiaext(path_shp,".shp",""); + strcat_s(path_shp,"_I.shp"); + if(!olv_limp->olv->olv_sh->guarda_shp(path_shp,ob_inst,TIPO_ENT_LINEA,olv_limp->camps.campo_secto,TIPO_IA_INT)) + return FALSE; + if(!guarda_cols_insta(path_shp)) + return FALSE; + } + + return TRUE; +} +//************************************************************************************* +/** + * Genera y guarda el shp con las rutas en subtramos, para recogida porque se va a descargar + */ +BOOL Colv_limp_thr::gen_guard_subtramos() +{ + int ntramos=0; + char path_shp[MAX_PATH]; + + ob_rut = new Cobgeo(); + memcpy(&ob_rut->nvl,&olv_limp->olv->olv_ob->nvl,sizeof(Niveles)); + ob_flech = new Cobgeo(); + memcpy(&ob_flech->nvl,&olv_limp->olv->olv_ob->nvl,sizeof(Niveles)); + + //cuenta tramos + tramos=cuenta_tramos(); + + if(!genera_obg_rut_ctrl(olv_limp->nsec, olv_limp->plan, ob_rut, NULL)) + { + pon_mi_msg("Errores en la generación de cartografía con ruta de los subtramos"); + return FALSE; + } + + rellena_tramos(); + + if(olv_limp->tipo_shp_viaj==OLV_SHPRUTINST) + { + int ii=rellena_insta_tramos(); + //combina los lineales de cada subtramo con la ida a descargar y la vuelta de descargar anterior + if(ii>0 && !combina_rut_insta(ob_rut, ob_inst)) + { + pon_mi_msg("Errores en la combinación de viajes con viajes a instalación"); + return FALSE; + } + } + + //graba los archivos de la ruta de los sectores + //graba todos los sectores en un único path + strcpy_s(path_shp,MAX_PATH,olv_limp->olv->paths.path_res_rut); + cambiaext(path_shp,".shp",""); + strcat_s(path_shp,"_R2.shp"); + if(!olv_limp->olv->olv_sh->guarda_shp(path_shp,ob_rut,TIPO_ENT_LINEA,olv_limp->camps.campo_secto,TIPO_IA_INT)) + { + pon_mi_msg("Errores en el guardado del shp de la capa de viajes"); + return FALSE; + } + + if(!guarda_cols_ruta_tram(path_shp)) + { + pon_mi_msg("Errores al guardar las columnas de la capa de viajes"); + return FALSE; + } + + ///////////////////////////////////////////// + //A continuación sobreescribe los archivos de las flechas + strcpy_s(path_shp,MAX_PATH,olv_limp->olv->paths.path_res_rut); + cambiaext(path_shp,".shp",""); + strcat_s(path_shp,"_Raux.shp"); + if(!olv_limp->olv->olv_sh->guarda_shp(path_shp,ob_flech,TIPO_ENT_LINEA,olv_limp->camps.campo_secto,TIPO_IA_INT)) + { + pon_mi_msg("Errores en el guardado del shp de la capa de viajes aux"); + return FALSE; + } + + //guarda en los ámbitos una columna de "tramo al que pertenecen" + if(!guarda_dbf_sector(3)) + { + pon_mi_msg("Errores al guardar la columna de viaje de cada cont"); + return FALSE; + } + + delete [] tramos; + tramos=NULL; + + return TRUE; +}//************************************************************************************* +/** + * Como los viajes a instalaciones están ordenados, y los tramos también + * le corresponde a cada tramo it el viaje it y el it+1, excepto al último, que le pueden + * corresponder 3 viajes si la instalación y la descarga no son en el mismo sitio + * Además, actualiza el tiempo de los tramos + */ +int Colv_limp_thr::rellena_insta_tramos() +{ + int it, nt, nins,ii; + Info_planif *pinsta; + Info_tramos *tramo; + + ii=0; //para saber si hace algún tramo o no + for(int is=0;isnsec;is++) + { + nt=tramos[is].size(); + nins = olv_limp->plan[is].ninsta; + if(!nins) + continue; + if(olv_limp->plan[is].planif_insta[nins-1].nelem==0) + nins--; //es porque la descarga y planta son la misma + pinsta = olv_limp->plan[is].planif_insta; + for(it=0;itiins[0]=2*it; + tramo->iins[1]=2*it+1; + + /////////////////////////////////////// + //Actualiza los tiempos del tramo sumando los tiempos del viaje a inst + tramo->t_ini -= (float)pinsta[tramo->iins[0]].elem[pinsta[tramo->iins[0]].nelem-1].coste; + tramo->t_fin += (float)pinsta[tramo->iins[1]].elem[pinsta[tramo->iins[1]].nelem-1].coste; + tramo->t_total_tr=(float) (tramo->t_fin-tramo->t_ini); + } + //para el último tramo + tramo = &tramos[is][it]; + tramo->iins[0]=2*it; + tramo->iins[1]=nins-1; + tramo->t_ini -= (float)pinsta[tramo->iins[0]].elem[pinsta[tramo->iins[0]].nelem-1].coste; + tramo->t_fin += (float)pinsta[tramo->iins[1]].elem[pinsta[tramo->iins[1]].nelem-1].coste; + tramo->t_total_tr=(float) (tramo->t_fin-tramo->t_ini); + ii++; + } + return ii; +} +//************************************************************************************* +/** + * Añade las columnas de información a la ruta, tiempos, longitudes, y demás + */ +BOOL Colv_limp_thr::guarda_cols_ruta_tram(char *path_shp) +{ + char *info; + char path_dbf[MAX_PATH]; + double tt; + int h,m,s; + int i, it,ntram,nt,nt_parc; + + //cuenta el número de sectores no vacíos + ntram=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + continue; + ntram+=tramos[i].size(); + } + + //añade una columna a la ruta de tiempo de ruta + strcpy_s(path_dbf,MAX_PATH,path_shp); + cambiaext(path_dbf,".shp",".dbf"); + info = (char *)malloc(ntram*OLV_SHP_SZ_CAMP_CHAR); + if(!info) + { + return FALSE; + } + memset(info,0,ntram*OLV_SHP_SZ_CAMP_CHAR); + + //SECTOR ya viene + + //TRATAMIENTO + nt_parc=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + continue; + nt=(int)tramos[i].size(); + for(it=0;itnomb_tto); + } + nt_parc+=nt; + } + if(!olv_limp->olv->olv_sh->add_col_dbf(path_dbf,ntram,TIPO_IA_CHAR,info,"TTO",err_str,OLV_MAX_ERR)) + { + free(info); + return FALSE; + } + memset(info,0,ntram*OLV_SHP_SZ_CAMP_CHAR); + + //VIAJE + nt_parc=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + continue; + nt=(int)tramos[i].size(); + for(it=0;itolv->olv_sh->add_col_dbf(path_dbf,ntram,TIPO_IA_CHAR,info,"VIAJE",err_str,OLV_MAX_ERR)) + { + free(info); + return FALSE; + } + memset(info,0,ntram*OLV_SHP_SZ_CAMP_CHAR); + + //H_INI + nt_parc=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + continue; + nt=(int)tramos[i].size(); + for(it=0;itolv->olv_sh->add_col_dbf(path_dbf,ntram,TIPO_IA_CHAR,info,"H_INI",err_str,OLV_MAX_ERR)) + { + free(info); + return FALSE; + } + memset(info,0,ntram*OLV_SHP_SZ_CAMP_CHAR); + + //H_FIN + nt_parc=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + continue; + nt=(int)tramos[i].size(); + for(it=0;itolv->olv_sh->add_col_dbf(path_dbf,ntram,TIPO_IA_CHAR,info,"H_FIN",err_str,OLV_MAX_ERR)) + { + free(info); + return FALSE; + } + memset(info,0,ntram*OLV_SHP_SZ_CAMP_CHAR); + + //T_TOTAL + nt_parc=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + continue; + nt=(int)tramos[i].size(); + for(it=0;itolv->olv_sh->add_col_dbf(path_dbf,ntram,TIPO_IA_CHAR,info,"T_TOTAL",err_str,OLV_MAX_ERR)) + { + free(info); + return FALSE; + } + memset(info,0,ntram*OLV_SHP_SZ_CAMP_CHAR); + + //T_TTO + nt_parc=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + continue; + nt=(int)tramos[i].size(); + for(it=0;itolv->olv_sh->add_col_dbf(path_dbf,ntram,TIPO_IA_CHAR,info,"T_TTO",err_str,OLV_MAX_ERR)) + { + free(info); + return FALSE; + } + memset(info,0,ntram*OLV_SHP_SZ_CAMP_CHAR); + + return TRUE; +} +//************************************************************************************* +/** + * Cuenta los tramos que hay en la ruta del sector is, si va varias veces a descargar + */ +std::vector* Colv_limp_thr::cuenta_tramos() +{ + std::vector *tramos = new std::vector[olv_limp->nsec]; + Info_planif *pp; + Info_tramos tramo; + int ie,ii,ilast; + + memset(&tramo,0,sizeof(Info_tramos)); + tramo.iins[0]=tramo.iins[1]=-1; + + for(int is=0;isnsec;is++) + { + pp=&olv_limp->plan[is]; + ii=0; + tramo.ie[0]=0; + for(ie=0;ienelem;ie++) + { + if(pp->elem[ie].tp!=OLV_PLAN_TIP_AMB) + continue; + if(pp->elem[ie].aux!=ii) + { + tramo.ie[1]=ilast; + tramos[is].push_back(tramo); + ii++; + tramo.ie[0]=ie; + } + olv_limp->amb_sec[olv_limp->ias[(*olv->olv_ob->objt)[pp->elem[ie].i].ia].ishp].res=ii; //marca el tramo en el array de ambitos + ilast=ie; + } + tramo.ie[1]=pp->nelem-1; + tramos[is].push_back(tramo); + } + + return tramos; +} +//************************************************************************************* +/** + * Rellena la info de los tramos + */ +void Colv_limp_thr::rellena_tramos() +{ + Info_planif *pp; + Info_tramos *tramo; + int ie,it,nt; + + for(int is=0;isnsec;is++) + { + pp=&olv_limp->plan[is]; + nt=tramos[is].size(); + for(it=0;itnamb=0; + tramo->ncont=0; + for(ie=tramo->ie[0]; ie<=tramo->ie[1];ie++) + { + tramo->long_tr+=(float) pp->elem[ie].ltot; + if(pp->elem[ie].tp!=OLV_PLAN_TIP_AMB) + continue; + + tramo->namb++; + } + + tramo->t_tto_tr = (float)(pp->t[OLV_TTO]); + if(pp->planif_insta) + { + if(it==0) + tramo->t_ini = (float)(olv_limp->t_ini+olv_limp->t_sal+pp->planif_insta[0].elem[pp->planif_insta[0].nelem-1].coste); + else + tramo->t_ini = (float)(pp->planif_insta[2*it].t[OLV_TTO]+pp->planif_insta[2*it].elem[pp->planif_insta[2*it].nelem-1].coste); + tramo->t_fin = (float)pp->planif_insta[2*it+1].t[OLV_TTO]; + } + else + { + tramo->t_ini = (float)(olv_limp->t_ini+olv_limp->t_sal); + tramo->t_fin = (float)(tramo->t_ini + pp->elem[pp->nelem-1].coste); + } + + tramo->t_total_tr = (float) (tramo->t_fin-tramo->t_ini); + } + } +} +//************************************************************************************* +/** + * Dadas las rutas de los sectores, genera la ruta en una única línea en el obg + * y en otro coloca los puntos de control + */ +BOOL Colv_limp_thr::combina_rut_insta(Cobgeo *ob_rut, Cobgeo *ob_inst) +{ + //en ob_rut ahora están todos los subtramos en orden: + //1 viaje del sector 1, 2 viaje del sector 1, 1 viaje del sector 2, etc + //hay que añadir al primer viaje de cada sector la ida desde instalación y la ida a descargar (y la ida a instalación + //si es un único viaje) + //al resto de viajes intermedios hay que añadirles la vuelta de descargar anterior y la ida a descargar + //al último viaje hay que añadirle la ida a descargar y la ida a instalación + int is=0, it=0, nt=0, i=0, il, il2, npt_tot, npt, ntparc,ii; + int niparc, res, nmax_pts,npt_parc; + BOOL mal = false; + Info_planif *planif, *pp; + double (*ptos_aux)[3],(*ptos)[3]; + Objgeo *lineal; + + ///////////////// + //Inicializar lineal + lineal= new Objgeo; + if(!lineal) + { + return FALSE; + } + lineal->tipo = OBJ_LINEAL; + lineal->flags[0] = 0; + lineal->flags[1] = 0; + lineal->ev.id = 0; + lineal->pt.lin = (Linealgeo*) malloc (sizeof(Linealgeo)); + if(!lineal->pt.lin) + { + return FALSE; + } + lineal->pt.lin->n= 0; + lineal->pt.lin->flags=0; + lineal->pt.lin->ptos = NULL; + /////////////////////// + + planif= olv_limp->plan; + + ntparc=0; + niparc=0; + nmax_pts=0; + for(is=0;isnsec && !mal;is++) + { + pp=&planif[is]; + nt=tramos[is].size(); + lineal->ia = is+1;//le suma uno para que sea empezando en 1 y no en 0 + lineal->clase = OLV_ICLA_LIN_RUT+is; + for(it=0;itobjt)[it+ntparc].indx; + npt=(*ob_rut->lial)[il].n; + npt_tot+=npt; + for(ii=tramos[is][it].iins[0]; ii<=tramos[is][it].iins[1];ii++) + { + il=(*ob_inst->objt)[ii+niparc].indx; + npt=(*ob_inst->lial)[il].n; + npt_tot+=npt; + res++; + } + //dado que junta tramos, resta para no replicar los puntos de unión + npt_tot=npt_tot-res; + + //////////////////////////////////////////////////////////////////// + //marca para borrar ese tramo + (*ob_rut->objt)[it+ntparc].flags[1] = (*ob_rut->objt)[it+ntparc].flags[1] | B1_OBJ_NULO; + //ya que tiene el total de puntos, actualiza el lineal de ese tramo + lineal->pt.lin->n= npt_tot; + ptos_aux=(double (*)[3])lineal->pt.lin->ptos; + if(npt_tot>nmax_pts) + { + ptos_aux = (double (*)[3]) realloc(lineal->pt.lin->ptos,npt_tot * 3 * sizeof(double)); + nmax_pts=npt_tot; + } + if(!ptos_aux) + { + mal=TRUE; + continue; + } + + ////////////////////////////////////////////////////////////////////// + //ahora copia en ptos_aux los lineales de los tramos que le corresponden + npt_parc=0; + for(ii=tramos[is][it].iins[0]; ii<=tramos[is][it].iins[1];ii++) + { + il=(*ob_inst->objt)[ii+niparc].indx; + npt=(*ob_inst->lial)[il].n; + il2=(*ob_inst->lial)[il].indx; + ptos = &(*ob_inst->ptos)[il2]; + + //copia el viaje al lineal total + memcpy(ptos_aux[npt_parc],ptos,npt*3*sizeof(double)); + npt_parc+=npt-1; + if(ii==tramos[is][it].iins[1]) + npt_parc++; + + if(ii==tramos[is][it].iins[0]) + { + //después del primer viaje se copia el tramo de recogida + il=(*ob_rut->objt)[it+ntparc].indx; + npt=(*ob_rut->lial)[il].n; + il2=(*ob_rut->lial)[il].indx; + ptos = &(*ob_rut->ptos)[il2]; + + //copia el viaje al lineal total + memcpy(ptos_aux[npt_parc],ptos,npt*3*sizeof(double)); + npt_parc+=npt-1; + } + } + ////////////////////////////////////////////////////////////////////// + + lineal->pt.lin->ptos = (double (*)[][3])ptos_aux; + lineal->pt.lin->flags = 0; + if(ob_rut->pon_obj(lineal)<0) + { + mal=TRUE; //entra por aquí?? + continue; + } + } + niparc+=ii; //ii apunta a la última instalación del primer sector + ntparc+=nt; + } + if(mal) + { + return FALSE; + } + ob_rut->limpia(); + return TRUE; +} +//************************************************************************************* +/** + * Añade las columnas de información a la ruta, tiempos, longitudes, y demás + */ +BOOL Colv_limp_thr::guarda_cols_ruta(char *path_shp) +{ + char *info; + char path_dbf[MAX_PATH]; + double tt; + int h,m,s; + char nombia[16]; + int nsec, i, isec_novac; + + //cuenta el número de sectores no vacíos + nsec=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb!=0) + nsec++; + } + + //////////////////////////////////// + //El coste_ac es lo mismo que el cost del último elemento de la planif + //más el de desplazamientos inicial y final y de descargas + //Para el total, hay que añadir los descansos + ///////////////////////////////////// + + //añade una columna a la ruta de tiempo de ruta + strcpy_s(path_dbf,MAX_PATH,path_shp); + cambiaext(path_dbf,".shp",".dbf"); + info = (char *)malloc(nsec*OLV_SHP_SZ_CAMP_CHAR); + if(!info) + { + return FALSE; + } + memset(info,0,nsec*OLV_SHP_SZ_CAMP_CHAR); + + //SECTOR ya viene + //TRATAMIENTO + isec_novac=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + { + continue; + } + sprintf_s(&info[isec_novac*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%s",olv_limp->nomb_tto); + isec_novac++; + } + if(!olv_limp->olv->olv_sh->add_col_dbf(path_dbf,nsec,TIPO_IA_CHAR,info,"TTO",err_str,OLV_MAX_ERR)) + { + free(info); + return FALSE; + } + memset(info,0,nsec*OLV_SHP_SZ_CAMP_CHAR); + + //rellena la info de hora inicial + isec_novac=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + { + continue; + } + tt=olv_limp->t_ini; + dame_h_m_s(tt, &h, &m, &s); + sprintf_s(&info[isec_novac*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%02d:%02d:%02d h",h,m,s); + isec_novac++; + } + if(!olv_limp->olv->olv_sh->add_col_dbf(path_dbf,nsec,TIPO_IA_CHAR,info,"H_INI",err_str,OLV_MAX_ERR)) + { + free(info); + return FALSE; + } + memset(info,0,nsec*OLV_SHP_SZ_CAMP_CHAR); + + //rellena la info de hora final + isec_novac=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + { + continue; + } + tt=olv_limp->t_ini+ olv_limp->sec[i].cost_ac + olv_limp->t_desc; + + dame_h_m_s(tt, &h, &m, &s); + sprintf_s(&info[isec_novac*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%02d:%02d:%02d h",h,m,s); + isec_novac++; + } + if(!olv_limp->olv->olv_sh->add_col_dbf(path_dbf,nsec,TIPO_IA_CHAR,info,"H_FIN",err_str,OLV_MAX_ERR)) + { + free(info); + return FALSE; + } + memset(info,0,nsec*OLV_SHP_SZ_CAMP_CHAR); + + //rellena la info de duración total + isec_novac=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + continue; + tt=olv_limp->sec[i].cost_ac+olv_limp->t_desc; + dame_h_m_s(tt, &h, &m, &s); + sprintf_s(&info[isec_novac*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%02d:%02d:%02d h",h,m,s); + isec_novac++; + } + if(!olv_limp->olv->olv_sh->add_col_dbf(path_dbf,nsec,TIPO_IA_CHAR,info,"T_TOTAL",err_str,OLV_MAX_ERR)) + { + free(info); + return FALSE; + } + memset(info,0,nsec*OLV_SHP_SZ_CAMP_CHAR); + + //rellena la info de duración de los desplazamientos + isec_novac=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + continue; + tt=olv_limp->sec[i].t_despl[0]+olv_limp->sec[i].t_despl[1]; + dame_h_m_s(tt, &h, &m, &s); + sprintf_s(&info[isec_novac*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%02d:%02d:%02d h",h,m,s); + isec_novac++; + } + if(!olv_limp->olv->olv_sh->add_col_dbf(path_dbf,nsec,TIPO_IA_CHAR,info,"T_INSTA",err_str,OLV_MAX_ERR)) + { + free(info); + return FALSE; + } + memset(info,0,nsec*OLV_SHP_SZ_CAMP_CHAR); + + //rellena la info de duración de los descansos + isec_novac=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + continue; + tt=olv_limp->t_desc; + dame_h_m_s(tt, &h, &m, &s); + sprintf_s(&info[isec_novac*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%02d:%02d:%02d h",h,m,s); + isec_novac++; + } + if(!olv_limp->olv->olv_sh->add_col_dbf(path_dbf,nsec,TIPO_IA_CHAR,info,"T_DESCAN",err_str,OLV_MAX_ERR)) + { + free(info); + return FALSE; + } + memset(info,0,nsec*OLV_SHP_SZ_CAMP_CHAR); + + //rellena la info de duración de la ruta + isec_novac=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + continue; + tt=olv_limp->plan[i].elem[olv_limp->plan[i].nelem-1].coste; + dame_h_m_s(tt, &h, &m, &s); + sprintf_s(&info[isec_novac*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%02d:%02d:%02d h",h,m,s); + isec_novac++; + } + if(!olv_limp->olv->olv_sh->add_col_dbf(path_dbf,nsec,TIPO_IA_CHAR,info,"T_RUTA",err_str,OLV_MAX_ERR)) + { + free(info); + return FALSE; + } + memset(info,0,nsec*OLV_SHP_SZ_CAMP_CHAR); + + //rellena la info de longitud de la ruta + isec_novac=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + continue; + tt=olv_limp->plan[i].m[0]+olv_limp->plan[i].m[1]; + sprintf_s(&info[isec_novac*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%.2f",tt); + isec_novac++; + } + if(!olv_limp->olv->olv_sh->add_col_dbf(path_dbf,nsec,TIPO_IA_CHAR,info,"M_RUTA",err_str,OLV_MAX_ERR)) + { + free(info); + return FALSE; + } + memset(info,0,nsec*OLV_SHP_SZ_CAMP_CHAR); + + //rellena primero T DESP, M DESP, VELO DESP, T TRAT, M TRAT, VELO/T TRAT + int p; + for(int k=0;knsec;i++) + { + if(olv_limp->sec[i].namb==0) + continue; + tt=olv_limp->plan[i].t[k]; + dame_h_m_s(tt, &h, &m, &s); + sprintf_s(&info[isec_novac*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%02d:%02d:%02d h",h,m,s); + isec_novac++; + } + } + else if(p==1) + { + if(k==OLV_TTO) + { + if(olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoM2h || olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoM2h_eje) + strcpy_s(nombia,"M2_"); + else if(olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoMh || olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoMh_eje) + strcpy_s(nombia,"M_"); + else if(olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoMin) + strcpy_s(nombia,"UDS_"); + } + else + { + strcpy_s(nombia,"M_"); + } + if((k==OLV_TTO) && (olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoMin)) + { + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + continue; + tt=olv_limp->sec[i].namb; + sprintf_s(&info[isec_novac*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%ld",(int)tt); + isec_novac++; + } + } + else + { + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + continue; + tt=olv_limp->plan[i].m[k]; + sprintf_s(&info[isec_novac*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%.2f",tt); + isec_novac++; + + } + } + } + else if(p==2) + { + if(k==OLV_TTO) + { + tt=olv_limp->t_tto; + if(olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoM2h || olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoM2h_eje) + strcpy_s(nombia,"M2_H_"); + else if(olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoMh || olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoMh_eje) + strcpy_s(nombia,"M_H_"); + else if(olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoMin) + { + strcpy_s(nombia,"MIN_"); + tt=tt/60;//para pasarlo a minutos + } + + } + else + { + strcpy_s(nombia,"M_H_"); + tt=olv_limp->v_despl; + } + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + continue; + if(tt) + sprintf_s(&info[isec_novac*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%.1f",tt); + else + sprintf_s(&info[isec_novac*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"Def. Vias"); + isec_novac++; + } + } + if(k==OLV_TTO) + { + strcat_s(nombia,"TRAT"); + } + else if(k==OLV_DESP) + { + strcat_s(nombia,"DESP"); + } + if(!olv_limp->olv->olv_sh->add_col_dbf(path_dbf,nsec,TIPO_IA_CHAR,info,nombia,err_str,OLV_MAX_ERR)) + { + free(info); + return FALSE; + } + memset(info,0,nsec*OLV_SHP_SZ_CAMP_CHAR); + } + } + + free(info); + return TRUE; +} +//************************************************************************************* +/** + * Añade las columnas de información a los puntos de control + */ +BOOL Colv_limp_thr::guarda_cols_ctrl(char *path_shp) +{ + char path_dbf[MAX_PATH]; + int h,m,s,k; + double tt; + char *info; + int nsec, i, isec_novac; + + //cuenta el número de sectores no vacíos + nsec=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb!=0) + nsec++; + } + + //añade una columna a los puntos de control de secuencia + strcpy_s(path_dbf,MAX_PATH,path_shp); + cambiaext(path_dbf,".shp",".dbf"); + + info = (char *)malloc(nsec*olv_limp->npts_ctrl*OLV_SHP_SZ_CAMP_CHAR); + if(!info) + { + return FALSE; + } + memset(info,0,nsec*olv_limp->npts_ctrl*OLV_SHP_SZ_CAMP_CHAR); + + //rellena el nombre del tto + k=0; + isec_novac=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + continue; + + sprintf_s(&info[k*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,olv_limp->nomb_tto); + k++; + for(k;k<(isec_novac+1)*olv_limp->npts_ctrl-1;k++) + sprintf_s(&info[k*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,olv_limp->nomb_tto); + sprintf_s(&info[k*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,olv_limp->nomb_tto); + isec_novac++; + k++; + } + if(!olv_limp->olv->olv_sh->add_col_dbf(path_dbf,nsec*olv_limp->npts_ctrl,TIPO_IA_CHAR,info,"TTO",err_str,OLV_MAX_ERR)) + { + free(info); + return FALSE; + } + memset(info,0,nsec*olv_limp->npts_ctrl*OLV_SHP_SZ_CAMP_CHAR); + + //rellena la info + k=0; + isec_novac=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + continue; + sprintf_s(&info[k*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"Inicio"); + k++; + for(k;k<(isec_novac+1)*olv_limp->npts_ctrl-1;k++) + sprintf_s(&info[k*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"Medio"); + sprintf_s(&info[k*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"Fin"); + isec_novac++; + k++; + } + if(!olv_limp->olv->olv_sh->add_col_dbf(path_dbf,nsec*olv_limp->npts_ctrl,TIPO_IA_CHAR,info,"SECUENCIA",err_str,OLV_MAX_ERR)) + { + free(info); + return FALSE; + } + memset(info,0,nsec*olv_limp->npts_ctrl*OLV_SHP_SZ_CAMP_CHAR); + + //rellena la info de tiempo + k=0; + isec_novac=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + continue; + tt= olv_limp->t_ini+olv_limp->sec[i].t_despl[0]; + dame_h_m_s(tt, &h, &m, &s); + sprintf_s(&info[k*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%02d:%02d:%02d h",h,m,s); + k++; + for(k;k<(isec_novac+1)*olv_limp->npts_ctrl-1;k++) + { + tt= olv_limp->plan[i].pts_ctrl[k-(isec_novac*olv_limp->npts_ctrl+1)].cost; + dame_h_m_s(tt, &h, &m, &s); + sprintf_s(&info[k*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%02d:%02d:%02d h",h,m,s); + } + tt= olv_limp->plan[i].pts_ctrl[olv_limp->npts_ctrl-2].cost; + dame_h_m_s(tt, &h, &m, &s); + sprintf_s(&info[k*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%02d:%02d:%02d h",h,m,s); + k++; + isec_novac++; + } + if(!olv_limp->olv->olv_sh->add_col_dbf(path_dbf,nsec*olv_limp->npts_ctrl,TIPO_IA_CHAR,info,"HORA",err_str,OLV_MAX_ERR)) + { + free(info); + return FALSE; + } + + + free(info); + return TRUE; +} +//************************************************************************************* +/** + * Añade las columnas de información a las rutas de viajes a la instalación + */ +BOOL Colv_limp_thr::guarda_cols_insta(char *path_shp) +{ + char path_dbf[MAX_PATH]; + char *info; + double tt,ttt; + int h,m,s,insta,i,ninsta,ninsta_parc,ninsta_novac; + char tray[OLV_SHP_SZ_CAMP_CHAR]; + + //añade una columna + strcpy_s(path_dbf,MAX_PATH,path_shp); + cambiaext(path_dbf,".shp",".dbf"); + + //cuenta el número de instalaciones + ninsta=0; + for(i=0;insec;i++) + { + for(insta=0;instaplan[i].ninsta;insta++) + { + if(olv_limp->plan[i].planif_insta[insta].nelem!=0) + ninsta++; + } + } + + info = (char *)malloc(ninsta*OLV_SHP_SZ_CAMP_CHAR); + if(!info) + { + return FALSE; + } + memset(info,0,ninsta*OLV_SHP_SZ_CAMP_CHAR); + + //rellena el nombre del tto + ninsta_parc=0; + for(i=0;insec;i++) + { + ttt=0; + ninsta_novac=0; + for(insta=0;instaplan[i].ninsta;insta++) + { + if(olv_limp->plan[i].planif_insta[insta].nelem==0) + continue; + + sprintf_s(&info[(insta+ninsta_parc)*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%s",olv_limp->nomb_tto); + ninsta_novac++; + } + ninsta_parc+=ninsta_novac; + } + if(!olv_limp->olv->olv_sh->add_col_dbf(path_dbf,ninsta,TIPO_IA_CHAR,info,"TTO",err_str,OLV_MAX_ERR)) + { + free(info); + return FALSE; + } + memset(info,0,ninsta*OLV_SHP_SZ_CAMP_CHAR); + + //rellena la info de tipo de trayecto + ninsta_parc=0; + for(i=0;insec;i++) + { + ninsta_novac=0; + for(insta=0;instaplan[i].ninsta;insta++) + { + if(olv_limp->plan[i].planif_insta[insta].nelem==0) + continue; + + switch(olv_limp->plan[i].planif_insta[insta].ninsta) + { + case OLV_IDA_INST: + strcpy_s(tray,"Ida desde instalacion"); //quitado acento para evitar que salga mal + break; + case OLV_VUELTA_INST: + strcpy_s(tray,"Vuelta a instalacion"); + break; + case OLV_IDA_PLANT_ULT: + strcpy_s(tray,"Ultima ida a descargar"); + break; + case OLV_IDA_PLANT: + strcpy_s(tray,"Ida a descargar"); + break; + case OLV_VUELTA_PLANT: + strcpy_s(tray,"Vuelta de descargar"); + break; + } + sprintf_s(&info[(insta+ninsta_parc)*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%s",tray); + ninsta_novac++; + } + ninsta_parc+=ninsta_novac; + } + if(!olv_limp->olv->olv_sh->add_col_dbf(path_dbf,ninsta,TIPO_IA_CHAR,info,"TRAYECTO",err_str,OLV_MAX_ERR)) + { + free(info); + return FALSE; + } + memset(info,0,ninsta*OLV_SHP_SZ_CAMP_CHAR); + + //rellena la info de tipo de hora + ninsta_parc=0; + for(i=0;insec;i++) + { + ninsta_novac=0; + for(insta=0;instaplan[i].ninsta;insta++) + { + if(olv_limp->plan[i].planif_insta[insta].nelem==0) + continue; + + switch(olv_limp->plan[i].planif_insta[insta].ninsta) + { + case OLV_IDA_INST: + tt=olv_limp->t_ini; + break; + case OLV_VUELTA_INST: + tt=olv_limp->t_ini+olv_limp->sec[i].cost_ac-olv_limp->sec[i].t_despl[1]+olv_limp->t_desc; + olv_limp->plan[i].planif_insta[insta].t[OLV_TTO]=tt; + break; + case OLV_IDA_PLANT: + case OLV_IDA_PLANT_ULT: + tt=olv_limp->plan[i].planif_insta[insta].t[OLV_TTO]; + break; + case OLV_VUELTA_PLANT: + tt=olv_limp->plan[i].planif_insta[insta].t[OLV_TTO]; + break; + } + dame_h_m_s(tt, &h, &m, &s); + sprintf_s(&info[(insta+ninsta_parc)*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%02d:%02d:%02d h",h,m,s); + ninsta_novac++; + } + ninsta_parc+=ninsta_novac; + } + if(!olv_limp->olv->olv_sh->add_col_dbf(path_dbf,ninsta,TIPO_IA_CHAR,info,"H_TRAY",err_str,OLV_MAX_ERR)) + { + free(info); + return FALSE; + } + memset(info,0,ninsta*OLV_SHP_SZ_CAMP_CHAR); + + //rellena la info de duración + ninsta_parc=0; + for(i=0;insec;i++) + { + ttt=0; + ninsta_novac=0; + for(insta=0;instaplan[i].ninsta;insta++) + { + if(olv_limp->plan[i].planif_insta[insta].nelem==0) + continue; + + tt=olv_limp->plan[i].planif_insta[insta].elem[olv_limp->plan[i].planif_insta[insta].nelem-1].coste; + ttt+=tt; + dame_h_m_s(tt, &h, &m, &s); + sprintf_s(&info[(insta+ninsta_parc)*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%02d:%02d:%02d h",h,m,s); + ninsta_novac++; + } + ninsta_parc+=ninsta_novac; + } + if(!olv_limp->olv->olv_sh->add_col_dbf(path_dbf,ninsta,TIPO_IA_CHAR,info,"T_TRAY",err_str,OLV_MAX_ERR)) + { + free(info); + return FALSE; + } + memset(info,0,ninsta*OLV_SHP_SZ_CAMP_CHAR); + + //rellena la info de longitud + ninsta_parc=0; + for(i=0;insec;i++) + { + ninsta_novac=0; + for(insta=0;instaplan[i].ninsta;insta++) + { + if(olv_limp->plan[i].planif_insta[insta].nelem==0) + continue; + + tt=olv_limp->plan[i].planif_insta[insta].m[OLV_DESP]; + sprintf_s(&info[(insta+ninsta_parc)*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%.2f",tt); + ninsta_novac++; + } + ninsta_parc+=ninsta_novac; + } + if(!olv_limp->olv->olv_sh->add_col_dbf(path_dbf,ninsta,TIPO_IA_CHAR,info,"M_TRAY",err_str,OLV_MAX_ERR)) + { + free(info); + return FALSE; + } + memset(info,0,ninsta*OLV_SHP_SZ_CAMP_CHAR); + + free(info); + return TRUE; +} +//************************************************************************************* +/** + * Recorre la ruta y genera un listado en csv donde guarda las calles por las que va pasando la ruta + * El archivo se llama como el shape, concatenando el número de sector y L, en formato csv + */ +BOOL Colv_limp_thr::genera_list_rut_ctrl(Cobgeo *ob_rut) +{ + Info_planif *pp; + Colv_csv cc; + char tto_desp[32],observ[32],calle[1024],path_csv[MAX_PATH],fila[256],fila0[256]; + int i,j,h,m,seg,ii,dt; + double ltot,ltot0,tt,t0; + BOOL mal; + + double lttt; + + mal=FALSE; + strcpy_s(path_csv,MAX_PATH,olv_limp->olv->paths.path_data); + cambiaext(path_csv,".shp","_L.csv"); + //////////// + if(!cc.inicia(path_csv)) + { + sprintf_s(err_str, "Error al iniciar archivo %s",path_csv); + return FALSE; + } + //Inicia el archivo csv donde va a guardar las calles del itinerario + if(!cc.escribe("Ruta;Secuencia;Calle;Observaciones;Tratamiento/Desplazamiento;Longitud (m);Tiempo acumulado (h);\r\n")) + mal=TRUE; + + wgeolog(LOG_TODO,"olv_limp_t","Escribiendo listados de las rutas en csv"); + + //graba los listados de la ruta de los sectores + for(int s=0; snsec && !mal;s++) + { + lttt=0; + ltot0=0; + pp=&olv_limp->plan[s]; + if(pp->nelem==0) + continue; + ii=1; + i=0; + t0=olv_limp->t_ini + olv_limp->sec[s].t_despl[0]; + + ////////////////////////////////////////////// + //primer punto de control e instalación + if(i==0) + { + dame_h_m_s(olv_limp->t_ini, &h, &m, &seg); + sprintf_s(fila0,256,"%02d;%04d;%s;%s;%s;%s;%02d:%02d:%02d;\r\n",s+1,ii,"","","Instalación","",h,m,seg); + if(!cc.escribe(fila0)) + { + mal=TRUE; + continue;; + } + dame_h_m_s(t0, &h, &m, &seg); + sprintf_s(fila0,256,"%02d;%04d;%s;%s;%s;%s;%02d:%02d:%02d;\r\n",s+1,ii,"","","Control","",h,m,seg); + if(!cc.escribe(fila0)) + { + mal=TRUE; + continue;; + } + } + ////////////////////////////////////////////// + + for(i=0;inelem;i++) + { + if(pp->elem[i].tp==OLV_PLAN_TIP_SEG_LIN) + goto ctrl; + + if((pp->elem[i].ltot ==0) && (i>1) && (pp->elem[i].coste==pp->elem[i-1].coste)) + continue; + + if(i<(pp->nelem-1)) + { + if(((pp->elem[i].ia_nw == pp->elem[i+1].ia_nw) || + (((olv_limp->ias[pp->elem[i].ia_nw].info2 && olv_limp->ias[pp->elem[i+1].ia_nw].info2) + && (strcmp(olv_limp->ias[pp->elem[i].ia_nw].info2,olv_limp->ias[pp->elem[i+1].ia_nw].info2)==0)))) + && (pp->elem[i].tp == pp->elem[i+1].tp) ) + { + ltot0+=pp->elem[i].ltot; + lttt+=pp->elem[i].ltot; + goto ctrl; + } + } + + strcpy_s(observ,32,""); + strcpy_s(tto_desp,32,""); + switch(pp->elem[i].tp) + { + case OLV_PLAN_TIP_NW: + strcpy_s(tto_desp,32,"Desplazamiento"); + dt=OLV_DESP; + break; + case OLV_PLAN_TIP_AMB_PEAT_DESP: + strcpy_s(tto_desp,32,"Despl. por peatonal"); + dt=OLV_DESP; + break; + case OLV_PLAN_TIP_AMB_PEAT: + strcpy_s(observ,32,"Peatonal");//pasa al siguiente para poner tto también + case OLV_PLAN_TIP_AMB: + case OLV_PLAN_TIP_SEG_PUN: + strcpy_s(tto_desp,32,"Tratamiento"); + dt=OLV_TTO; + break; + case OLV_PLAN_TIP_SEG_LIN: + goto ctrl; + } + + if(pp->elem[i].ia_nw>0 && olv_limp->ias[pp->elem[i].ia_nw].info2) + strcpy_s(calle,1024,olv_limp->ias[pp->elem[i].ia_nw].info2); + else if((pp->elem[i].ia_nw>0) && (pp->elem[i].ia_nwn_ini_nw) && (pp->elem[i].tp == OLV_PLAN_TIP_AMB_PEAT)) + strcpy_s(calle,1024,"Parque---"); + else + calle[0]=0; + + tt=pp->elem[i].coste+t0; //a todos los costes de la ruta se añade el tiempo de desplazamiento + ltot=ltot0+pp->elem[i].ltot; + ltot0=0; + lttt+=pp->elem[i].ltot; + + ////////////////////////////////////////////// + //mira si tiene que poner observaciones por si fuera contendor + if(((olv_limp->ias[(*olv_limp->olv->olv_ob->objt)[pp->elem[i].i].ia].flgs & OLV_LIMP_FLG_SEG_PUN)) && (pp->elem[i].tp==OLV_PLAN_TIP_AMB)) + dame_observ_cont(olv_limp->ias[(*olv_limp->olv->olv_ob->objt)[pp->elem[i].i].ia].ishp, observ); + ////////////////////////////////////////////// + + + dame_h_m_s(tt, &h, &m, &seg); + if((olv_limp->tipo_ambit==OLV_AMB_PUN) && (pp->elem[i].tp==OLV_PLAN_TIP_AMB)) + sprintf_s(fila,256,"%02d;%04d;%s;%s;%s;%s;%02d:%02d:%02d;\r\n",s+1,ii,calle,observ,tto_desp,"",h,m,seg); + else + sprintf_s(fila,256,"%02d;%04d;%s;%s;%s;%.1f;%02d:%02d:%02d;\r\n",s+1,ii,calle,observ,tto_desp,ltot,h,m,seg); + + ////////////////////////////////////////////// + //escribe fila de paso + if(!cc.escribe(fila)) + { + mal=TRUE; + continue; + } + +ctrl: + ////////////////////////////////////////////// + //puntos de control intermedios + for(j=0;jnpts_ctrl-2 && !mal;j++) + { + if(pp->pts_ctrl[j].ipt==i) + { + t0+=olv_limp->t_desc/(olv_limp->npts_ctrl-2); + tt+=olv_limp->t_desc/(olv_limp->npts_ctrl-2); + pp->pts_ctrl[j].cost = tt; + dame_h_m_s(tt, &h, &m, &seg); + sprintf_s(fila0,256,"%02d;%04d;%s;%s;%s;%s;%02d:%02d:%02d;\r\n",s+1,ii,"","","Control","",h,m,seg); + if(!cc.escribe(fila0)) + { + mal=TRUE; + continue; + } + } + } + ////////////////////////////////////////////// + //viajes a vaciar intermedios + if((olv_limp->ias[(*olv_limp->olv->olv_ob->objt)[pp->elem[i].i].ia].flgs & OLV_LIMP_FLG_SEG_PUN)&& (pp->elem[i].tp==OLV_PLAN_TIP_AMB)) + { + if(!genera_list_fila_vaci(&cc, fila0, + olv_limp->ias[(*olv_limp->olv->olv_ob->objt)[pp->elem[i].i].ia].ishp, + pp->elem[i].i, s,ii,tt, &t0,FALSE)) + { + mal=TRUE; + break; + } + } + ////////////////////////////////////////////// + + ii++; + } + ////////////////////////////////////////////// + //último punto de control e instalación + if((i==(pp->nelem))&& !mal) + { + dame_h_m_s(tt, &h, &m, &seg); + sprintf_s(fila0,256,"%02d;%04d;%s;%s;%s;%s;%02d:%02d:%02d;\r\n",s+1,ii,calle,"","Control","",h,m,seg); + if(!cc.escribe(fila0)) + { + mal=TRUE; + continue; + } + pp->pts_ctrl[olv_limp->npts_ctrl-2].cost = tt; + + ////////////////////////////////////////////// + //último viaje a vaciar + if(olv_limp->ias[(*olv_limp->olv->olv_ob->objt)[pp->elem[i-1].i].ia].flgs & OLV_LIMP_FLG_SEG_PUN) + { + if(!genera_list_fila_vaci(&cc, fila0, + olv_limp->ias[(*olv_limp->olv->olv_ob->objt)[pp->elem[i-1].i].ia].ishp, + pp->elem[i-1].i, s,ii,tt, &t0,TRUE)) + { + mal=TRUE; + break; + } + } + ////////////////////////////////////////////// + + t0+=olv_limp->sec[s].t_despl[1]; //último punto de instalación, le añade el t_desplazamiento/2 + tt=pp->elem[pp->nelem-1].coste+t0; + dame_h_m_s(tt, &h, &m, &seg); + sprintf_s(fila0,256,"%02d;%04d;%s;%s;%s;%s;%02d:%02d:%02d;\r\n",s+1,ii,"","","Instalación","",h,m,seg); + if(!cc.escribe(fila0)) + { + mal=TRUE; + continue;; + } + } + + } + + cc.cierra(); + + if(mal) + { + sprintf_s(err_str, "Error al escribir fila en archivo %s",path_csv); + return FALSE; + } + + return TRUE; +} +//************************************************************************************* +/** + * Añade una línea al listado csv con el viaje a vaciar y vuelta + */ +void Colv_limp_thr::dame_h_m_s(double tt, int *h_, int *m_, int *s_) +{ + int h,m,s; + + h=(int)(tt/3600); + m=(int)((tt-h*3600)/60); + s=(int)(tt-m*60-h*3600); + h=h%24; + + *h_=h; + *m_=m; + *s_=s; +} +//************************************************************************************* +/** + * Añade una línea al listado csv con el viaje a vaciar y vuelta + */ +BOOL Colv_limp_thr::genera_list_fila_vaci(Colv_csv *cc, char *fila0,int iamb, int ielem, int s, int ii, double tt, double *t0,BOOL is_fin) +{ + return TRUE; +} +//************************************************************************************* +/** + * Añade una columna de observación al listado si es contenedores + */ +void Colv_limp_thr::dame_observ_cont(int iamb,char *observ) +{ +} +//************************************************************************************* +/** + * Modifica el dbf del shp original para poner la sectorización, + * que es el mismo que de entrada con una columna más, + * SECTOR (modo 0) o SECUENCIA VACÍA (modo 1) o SECUENCIA BUENA (modo 2) o TRAMO al que pertenece (modo 3) + */ +BOOL Colv_limp_thr::guarda_dbf_sector(int modo) +{ + int *info; + char path_dbf[MAX_PATH]; + char nom_ia[16]; + + //primero graba los archivos de la ruta de los sectores + //graba todos los sectores en un único path + strcpy_s(path_dbf,MAX_PATH,olv_limp->olv->paths.path_data); + cambiaext(path_dbf,".shp",".dbf"); + + info = (int *)malloc(olv_limp->n_amb*sizeof(int)); + if(!info) + { + sprintf_s(err_str,OLV_MAX_ERR,"Error, sin memoria para info asociada"); + return FALSE; + } + + //rellena la info + for(int i=0;in_amb;i++) + { + if(modo==0)//sector + info[i]=olv_limp->amb_sec[i].sec+1; + else if(modo==1)//secuencia vacía + info[i]=0; + else if(modo==2)//secuencia buena + { + info[i]=olv_limp->amb_sec[i].iseq+1; + //wgeolog(LOG_TODO,"olv_limp_t","seq i %ld %ld",i,info[i]); + } + else if(modo==3)//tramo al que pertenece (cuando en recogida hay varios tramos) + { + info[i]=olv_limp->amb_sec[i].res+1; + } + } + + //pone el nombre de la columna + if(modo==0)//sector + strcpy_s(nom_ia,16,"SECTOR"); + else if((modo==1)|| (modo==2))//secuencia + strcpy_s(nom_ia,16,"SECUENCIA"); + else if(modo==3) + strcpy_s(nom_ia,16,"VIAJE"); + + if(!olv_limp->olv->olv_sh->add_col_dbf(path_dbf,olv_limp->n_amb,TIPO_IA_INT,(char*)info,nom_ia,err_str,OLV_MAX_ERR)) + { + free(info); + return FALSE; + } + + free(info); + return TRUE; +} +//************************************************************************************* +/** + * Planifica o calcula el orden en el que hay que recorrer los ambitos del sector s + * la idea es partir de una solucion factible (la cual se consigue por distancias minimas) + * una vez que se tenga se realizan pequeños cambios en dicho orden para ver si mejora, si es asi se deja dicho cambio como permanente + * si no se quita y se intenta otro cambio + */ +Secu_amb * Colv_limp_thr::planifica_sect(Info_sec *s, Djkt_ang_ady *ang_conj, Info_aso *ias, int npermu) +{ + int i,k, j, nsec; + BOOL res=FALSE; + BOOL camb; + th_param_planif thp; + int nth=Colv_geom::dame_n_nucleos(); + int obset=0; + double ca, cold; + Secu_amb *sec; + BOOL nocalc=FALSE; + + sec=(Secu_amb*)malloc(s->namb*sizeof(Secu_amb)); + if(!sec) + goto sal; + memset(sec,0,s->namb*sizeof(Secu_amb)); + + //prepara arrays---------------------- + memset(&thp,0,sizeof(thp)); + + //copia la info del sector + + for (i=0; inamb && !pirate; i++) + { + for(k=0;k<2;k++) + { + sec[i].ctnod[k]=NULL; + } + } + if(pirate) + goto sal; + + //consigue solucion factible------------------------------ + nsec=0; + sec[nsec].iamb=dame_planif_iamb_ini(s,olv_limp->cost_amb,&sec[nsec].entrada ); + //sec[nsec].entrada=-1; + sec[sec[nsec].iamb].flags=1; + if(sec[nsec].iamb<0) + goto sal; + nsec++; + while(nsecnamb) + { + if(!busca_cercano(s,ias, sec, nsec-1, TRUE))//se pilla el minimo local + break; + nsec++; + } + + if(nsecnamb) + goto sal; + //mejora solucion--------------------- + //prepara thread------------ + thp.dth=(th_data_planif*)malloc(sizeof(th_data_planif)*nth); + thp.ias=ias; + thp.sec=sec; + thp.tl=this; + + thp.namb=s->namb; + thp.namb_t=s->namb; + thp.s=s; + thp.abs=TRUE;//cambio ger + if(!thp.dth) + goto sigue; + thp.dth[0].sec=(Secu_amb *)malloc(s->namb*nth*sizeof(Secu_amb)); + if(!thp.dth[0].sec) + goto sigue; + for (i=1; inamb*i]; + //lanza-------------------- + for (i=0; i=0) + Sleep(1); + + } + ca=dame_coste(sec,0,s->namb-1,ias, s,TRUE); + do + { + thp.modo=2; + cold=ca; + camb=FALSE; + + //bucle hasta recorrer todos los elementos de sec + //movimientos de elementos puntuales (cambio de posicion) + for (i=1; inamb; i++) + { + thp.param[0]=i; + thp.a_currar(); + //espera thread + while(!thp.terminado()) + Sleep(thp.milis_sleep); + //elije la mejor permuta + j=thp.dame_min(); + + if(j<0 || ca <=thp.dth[j].coste) + continue; + cambia_elem(sec, i, thp.dth[j].pos[0], thp.dth[j].pos[1]); + ca=thp.dth[j].coste; + + cold=ca; + camb=TRUE; + } + //permutaciones de npermu elementos + /*thp.modo=1; + cold=ca; + //camb=FALSE; + for (i=npermu+obset; inamb; i++) + { + thp.param[0]=max(i-npermu, obset); + thp.param[1]=i; + thp.a_currar(); + while(!thp.terminado()) + Sleep(1); + j=thp.dame_min(); + if(j<0 || ca <=thp.dth[j].coste || thp.dth[j].pos[0]<0) + continue; + ca =thp.dth[j].coste; + memcpy(sec, thp.dth[j].sec, s->namb*sizeof(Secu_amb)); + wgeolog(LOG_TODO,"olv_limp_t","Permu Mejora coste de %lf a %lf actu: %lf", + cold, ca, dame_coste(sec,0,s->namb-1,ias, s)); + cold=ca; + camb=TRUE; + }*/ + } while (camb); + thp.milis_sleep=1; + + //fuera thread + thp.pirate=TRUE; + while(thp.nth>0) + Sleep(1); + + //---------------------------------------------------------- +sigue: + if (thp.dth) + { + if(thp.dth[0].sec) + free(thp.dth[0].sec); + free(thp.dth); + } + + + pon_t_desp(s, ias, sec); + + + res=TRUE; +sal: + if(!res) + { + if(sec) + free(sec); + sec=NULL; + } + + return sec; +} +//************************************************************************************* +/** + * Rellena los tiempos de desplazamiento + */ +void Colv_limp_thr::pon_t_desp(Info_sec *s, Info_aso *ias, Secu_amb *sec) +{ + if((olv_limp->nod_instal>=0) && (s->namb>1)) + { + s->t_despl[0]=olv_limp->arch_dj.dame_dis(olv_limp->arch_dj.id_instal,0,s->iamb[sec[0].iamb],sec[0].entrada); + s->t_despl[1]=olv_limp->ord_sec_plan[0].ctnod[0][ias[s->iamb[sec[s->namb-1].iamb]].ic[(sec[s->namb-1].entrada+1)%2]].dis; + } +} +//************************************************************************************* +/** + * Rellena el siguiente nodo en la secuencia + */ +BOOL Colv_limp_thr::busca_cercano(Info_sec *s, Info_aso *ias, Secu_amb *sec, int isec, BOOL ind_abs) +{ + double d=MAYUSCULO; + int nam, nsal, nent; + int k, kk, i, j; + int ic, ind_cost; + ic=sec[isec].entrada; + if(isec==0) + isec=isec; + if(ic<0) + kk=olv_limp->tipo_ambit; + else + kk=1; + + for (k=0; knamb; i++) + { + if(sec[i].flags &1) + continue;///ya esta en la secuencia + if (ind_abs) + ind_cost=s->iamb[i]; + else + ind_cost=i; + for (j=0; jtipo_ambit; j++) + { + if(d>olv_limp->arch_dj.dame_dis(s->iamb[sec[isec].iamb],ic,s->iamb[i],j)) + { + d=olv_limp->arch_dj.dame_dis(s->iamb[sec[isec].iamb],ic,s->iamb[i],j); + nent=j; + nsal=ic; + nam=i; + } + + } + } + } + if(d>=MAYUSCULO) + return FALSE; + + sec[isec++].entrada=(nsal+1)%2; + sec[isec].entrada=nent; + sec[isec].iamb=nam; + sec[nam].flags=1; + return TRUE; +} +//************************************************************************************* +/** + * Da el ámbito inicial por el que empezar la planificación, en función del modo + */ +short Colv_limp_thr::dame_planif_iamb_ini(Info_sec *s, Matrix2d &cost_amb, short *ent/*=NULL*/) +{ + int i,j,iaux,ient,nn; + float aux, dist, dist1; + int modo; + double a, b,c,d,e; + + //cost_amb=olv_limp->cost_amb; + iaux=-1; + modo=3; + //////////////////////////////////////////////////// + //Coge el ámbito por defecto que se le hubiera dado en la columna secuencia + //Si no, busca el ámbito más cercano a la instalación, si la hubiera configurada, + //Si no, coge el de mayor coste (modo 1) + //O el de 'y+x' menor (modo 2) + //O el más alejado del centro (modo 3) + if(s->iamb_ini_def!=-1) + { + iaux=s->iamb_ini_def; + ient=0; + //busca el nodo más cercano a la instalación, si tiene 2 nodos y hay instalación + if(olv_limp->tipo_ambit==OLV_AMB_LIN && olv_limp->nod_instal>=0) + { + //comprueba los dos nodos + dist=olv_limp->arch_dj.dame_dis(olv_limp->arch_dj.id_instal,0,s->iamb[iaux],ient); + dist1=olv_limp->arch_dj.dame_dis(olv_limp->arch_dj.id_instal,0,s->iamb[iaux],1); + if(dist1nod_instal>=0) + { + aux=(float)MAYUSCULO; + //se coge de punto inicial el más cercano a la instalación + for(i=0;inamb;i++) + { + if(olv_limp->ias[s->iamb[i]].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + //calcula la distancia de la instalación al inicio del ámbito + ient=0; + dist=olv_limp->arch_dj.dame_dis(olv_limp->arch_dj.id_instal,0,s->iamb[i],ient); + if(olv_limp->tipo_ambit==OLV_AMB_LIN) + { + //comprueba los dos nodos + + dist1=olv_limp->arch_dj.dame_dis(olv_limp->arch_dj.id_instal,0,s->iamb[i],1); + + + if(dist1namb;i++) + { + if(olv_limp->ias[s->iamb[i]].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + //calcula la distancia de mayor entre dos ámbitos + for(j=0;jnamb;j++) + { + if(i==j) + continue; + + if(olv_limp->ias[s->iamb[j]].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + + dist=cost_amb[s->iamb[i]][s->iamb[j]]; + //busca el mayor + if(dist>aux) + { + aux=dist; + iaux=i; + } + } + } + } + else if(modo==2) + { + ///////////////////////////////////// + ////////////////////// + //Como primer ámbito coge el más extremo + //el de menor 'y+x' + aux=(float)MAYUSCULO; + for(i=0;inamb;i++) + { + if(olv_limp->ias[s->iamb[i]].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + if((olv_limp->conjs.coor[olv_limp->ias[s->iamb[i]].ic_ini][1]+olv_limp->conjs.coor[olv_limp->ias[s->iamb[i]].ic_ini][0])conjs.coor[olv_limp->ias[s->iamb[i]].ic_ini][1]+ + olv_limp->conjs.coor[olv_limp->ias[s->iamb[i]].ic_ini][0]); + iaux=i; + } + } + } + else if(modo==3) + { + ////////////////////// + a=0; + b=0; + c=0; + d=0; + e=-1; + nn=0; + //Como primer ámbito coge el más alejado del centro + //coge la x y la y media, el centro + for(i=0;inamb;i++) + { + if(olv_limp->ias[s->iamb[i]].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + a+=olv_limp->conjs.coor[olv_limp->ias[s->iamb[i]].ic_ini][1]; + b+=olv_limp->conjs.coor[olv_limp->ias[s->iamb[i]].ic_ini][0]; + nn++; + } + a=a/nn; + b=b/nn; + //busca el más alejado de la x e y media + for(i=0;inamb;i++) + { + if(olv_limp->ias[s->iamb[i]].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + c=olv_limp->conjs.coor[olv_limp->ias[s->iamb[i]].ic_ini][1]-a; + c=c*c; + d=olv_limp->conjs.coor[olv_limp->ias[s->iamb[i]].ic_ini][0]-b; + d=d*d; + if((c+d)>e) + { + e=(c+d); + iaux=i; + if(ent) + *ent=0; + } + } + } + return (short)iaux; +} +//************************************************************************************* +/** + * Permuta los elementos de sec en sec_out, desde el indice ini hasta fin aplicando la permutacion p-esima + */ +BOOL Colv_limp_thr::permuta(Secu_amb * sec, int ini, int fin, int p, Secu_amb * sec_out) +{ + int n=fin-ini-1;//numero de elementos a permutar + int nn, i, j, k; + + nn=Colv_geom::fact(n); + for (i=ini; i=0) + return FALSE;//Error al permutar + sec_out[j].flags=1; + sec_out[i].entrada=sec[j].entrada; + sec_out[i].iamb=sec[j].iamb; + } + return TRUE; + +} +//************************************************************************************* +/** + * Cambia de lugar el elemento de la pos_old a la pos_new en la secuencia de elementos sec + */ +void Colv_limp_thr::cambia_elem( Secu_amb * sec,int pos_old, int pos_new, int entr ) +{ + int i; + Secu_amb s; + s.entrada=entr; + s.iamb=sec[pos_old].iamb; + if(pos_old>pos_new) + { + for (i=pos_old; i>pos_new; i--) + { + sec[i].entrada=sec[i-1].entrada; + sec[i].iamb=sec[i-1].iamb; + } + } + else + { + for (i=pos_old; iias=ias; + thp->sec=ord_sec; + thp->tl=this; + thp->abs=TRUE; + + if(!thp->dth[0].sec) + thp->dth[0].sec=(Secu_amb *)malloc(thp->namb_t*thp->nth*sizeof(Secu_amb)); + if(!thp->dth[0].sec) + goto npermu; + + for (i=1; inth; i++) + { + thp->dth[i].sec=&thp->dth[0].sec[thp->namb_t*i]; + } + + permu=TRUE; +npermu: + + for (nsecuencia=0; nsecuencianamb; nsecuencia++) + ord_sec[nsecuencia].flags =0; + nsecuencia=0; + + if(ss->namb<=0) + { + ss->cost_ac=0; + return TRUE; + } + //calcula ambito inicial------------ + ord_sec[nsecuencia].iamb=dame_planif_iamb_ini(ss,olv_limp->cost_amb, &ord_sec[nsecuencia].entrada); + if(ord_sec[nsecuencia].iamb<0) + return FALSE; + ord_sec[ord_sec[nsecuencia].iamb].flags=1; + nsecuencia++; + while(nsecuencianamb) + { + if(!busca_cercano(ss,ias, ord_sec, nsecuencia-1,TRUE))//se pilla el minimo local + break; + nsecuencia++; + } + if (nsecuencia>=ss->namb) + { + ss->cost_ac=(float)dame_coste(ord_sec, 0, ss->namb-1, ias , ss, TRUE); + } + else + return FALSE; + + //mira a ver si tiene que pertmutar o no. Si un sector tiene casi todos los ámbitos, no se permuta + int namb_m, nsec; + if(olv_limp->n_amb>=OLV_DESV_MAX_NAMB_MIN) + { + if(olv_limp->calc_nsec) + { + if(olv_limp->nsec_act>1) + namb_m = olv_limp->n_amb/(olv_limp->nsec_act-1); + else + namb_m= olv_limp->n_amb; + } + else + namb_m= olv_limp->n_amb/olv_limp->nsec; + namb_m+=(int)(namb_m*OLV_DESV_MAX_NAMB); + nsec=olv_limp->nsec; + if(olv_limp->calc_nsec>0) + nsec--; + for(int p=0;psec[p].namb>namb_m) + { + permu=FALSE; + break; + } + } + } + + if(!permu) + return TRUE; + + //mejora solucion--------------------- + //prepara thread------------ + thp->namb=ss->namb; + thp->s=ss; + ca=dame_coste(ord_sec, 0, ss->namb-1, ias , ss, TRUE); + if(loguear) + wgeolog(LOG_TODO,"olv_limp_t","coste de partida %lf",ca); + do + { + thp->modo=2; + cold=ca; + camb=FALSE; + + //bucle hasta recorrer todos los elementos de sec + //movimientos de elementos puntuales (cambio de posicion) + for (i=1; inamb; i++) + { + thp->param[0]=i; + thp->a_currar(); + //espera thread + while(!thp->terminado()) + Sleep(thp->milis_sleep); + //elije la mejor permuta + k=thp->dame_min(); + if(loguear && k>=0) + wgeolog(LOG_TODO,"olv_limp_t","Candidato cal_costes cambia %ld, a %ld, costes: %lf ", + i, thp->dth[k].pos[0], thp->dth[k].coste); + if(k<0 || ca <=thp->dth[k].coste) + continue; + + cambia_elem(ord_sec, i, thp->dth[k].pos[0], thp->dth[k].pos[1]); + ca=thp->dth[k].coste; + if(loguear) + wgeolog(LOG_TODO,"olv_limp_t","Mejora coste cambia %ld, a %ld, costes: %lf a %lf", + i, thp->dth[k].pos[0], cold, ca); + cold=ca; + camb=TRUE; + } + //permutaciones de npermu elementos + /*thp.modo=1; + cold=ca; + //camb=FALSE; + for (i=npermu+obset; inamb; i++) + { + thp.param[0]=max(i-npermu, obset); + thp.param[1]=i; + thp.a_currar(); + while(!thp.terminado()) + Sleep(1); + j=thp.dame_min(); + if(j<0 || ca <=thp.dth[j].coste || thp.dth[j].pos[0]<0) + continue; + ca =thp.dth[j].coste; + memcpy(sec, thp.dth[j].sec, s->namb*sizeof(Secu_amb)); + wgeolog(LOG_TODO,"olv_limp_t","Permu Mejora coste de %lf a %lf actu: %lf", + cold, ca, dame_coste(sec,0,s->namb-1,ias, s)); + cold=ca; + camb=TRUE; + }*/ + } while (camb && !pirate); + + pon_t_desp(ss, ias, ord_sec); + + ss->cost_ac=(float)ca; + if(loguear) + { + wgeolog(LOG_TODO,"olv_limp_t","Coste %lf",ss->cost_ac); + if(esta_repe(thp->sec, thp->namb, TRUE)) + wgeolog(LOG_TODO,"olv_limp_t","Esta repe en calcula costes"); + } + + return TRUE; + + //fuera thread + /*if(permu) + { + thp->pirate=TRUE; + while(thp->nth>0) + Sleep(1); + }*/ +} +//************************************************************************************* +/** + * Calcula el coste de los sectores mediante planificación de sus ámbitos + */ +BOOL Colv_limp_thr::calcula_coste_sectores( Secu_amb * ord_sec,Info_sec *ss,int n_sec, Info_aso *ias, th_param_planif *thp, BOOL loguear ) +{ + int obset=0; + int i; + BOOL res=FALSE; + int j; + + if(!thp) + goto npermu; + + thp->ias=ias; + thp->sec=ord_sec; + thp->tl=this; + thp->abs=TRUE; + thp->milis_sleep=0; + + if(!thp->dth[0].sec) + thp->dth[0].sec=(Secu_amb *)malloc(thp->namb_t*thp->nth*sizeof(Secu_amb)); + if(!thp->dth[0].sec) + goto npermu; + + for (i=1; inth; i++) + { + thp->dth[i].sec=&thp->dth[0].sec[thp->namb_t*i]; + } + +npermu: + + for (j=0; j=n_sec) + res=TRUE; + + + thp->milis_sleep=1; + + return res; +} +//************************************************************************************* +/** + * Comprueba si hay elementos repetidos en las permutaciones + */ +BOOL Colv_limp_thr::esta_repe( Secu_amb *sec, int nsec, BOOL log ) +{ + BOOL res=FALSE; + int i; + for (i=0; i=0) + { + wgeolog(LOG_TODO,"olv_limp_t","Esta repe la secuencia %ld, en posiciones %ld, %ld ",sec[i].iamb, i, sec[sec[i].iamb].flags); + res=TRUE; + } + sec[sec[i].iamb].flags=i; + } + return res; +} +//************************************************************************************* +/** + * Escribe la info resultado de la planificación + */ +void Colv_limp_thr::pon_info_resul() +{ + char msg_[OLV_MAX_MSG_PROCE]; + char msg_aux[64]; + int i,h,m,s; + double tt; + int nsec=0; + + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb!=0) + nsec++; + } + + if(olv_limp->olv->modo_ejec==OLV_EJEC_SECT) + { + //si se ha ejecutado en modo cálculo de sectorización + if(olv_limp->calc_nsec>0) + { + //se ha pedido proponer número de sectores óptimo + sprintf_s(msg_,OLV_MAX_MSG_PROCE, + "Se ha calculado la sectorización para el número de sectores óptimo\ndada la conf. elegida, que es de %ld, de tiempos:\n", + nsec); + } + else + { + //se ha impuesto el número de sectores + sprintf_s(msg_,OLV_MAX_MSG_PROCE,"Se ha calculado la sectorización para %ld sectores, de tiempos:\n", + nsec); + } + } + else if(olv_limp->olv->modo_ejec==OLV_EJEC_PLAN) + { + sprintf_s(msg_,OLV_MAX_MSG_PROCE,"Se ha calculado la planificación para %ld sectores, de tiempos:\n", + nsec); + } + else if(olv_limp->olv->modo_ejec==OLV_EJEC_TODO) + { + sprintf_s(msg_,OLV_MAX_MSG_PROCE,"Resultados de todo el proceso para %ld sectores, de tiempos:\n", + nsec); + } + else + msg_[0]=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + continue; + tt=olv_limp->sec[i].cost_ac+olv_limp->t_desc; + dame_h_m_s(tt, &h, &m, &s); + sprintf_s(msg_aux,64,"Sector %ld: %02d:%02d:%02d h, %03d elementos\n",i+1,h,m,s,olv_limp->sec[i].namb); + strcat_s(msg_,OLV_MAX_MSG_PROCE,msg_aux); + } + pon_mi_msg(msg_); + pon_mi_progre(tarea,100); +} +//************************************************************************************* +/* + * Lanza los multi procesos para el cálculo de cost_amb + */ +BOOL Colv_limp_thr::lanza_tasks(int nthr_def/*=-1*/) +{ + int nn; + char comline[256]; + char app_path[MAX_PATH]; + char app_path_aux[MAX_PATH]; + BOOL ret=TRUE; + + if(nthr_def>0) + nn=nthr_def; + else + nn=n_subthr; + + comline[0]=0; + app_path[0]=0; + app_path_aux[0]=0; + + olv_limp->olv_tasks->get_dll_dir(app_path_aux); + if(!app_path_aux[0]) + return FALSE; + + char *pch=strrchr(app_path_aux,'\\'); + if(!pch) + return FALSE; + + *pch=0; + + sprintf(app_path,"%s\\%s\\%s",app_path_aux,TASKS_FOLDER_NAME,TASKS_APP_NAME); + + //Arranca los tasks + for(int i=0;iolv->olv_sock->ip, + TASKS_PORT, + i); + + if(!olv_limp->olv_tasks->lanza_app(app_path, comline)) + ret=FALSE; + } + + return ret; +} +//************************************************************************************* +/* + * Guarda a disco la matriz de dist entre conjunciones y de ángulos + */ +BOOL Colv_limp_thr::guarda_mats() +{ + pon_mi_progre(OLV_TAREA_GUARD_MAT, 0); + olv_limp->olv_tasks->inidirs(olv_limp->olv->paths.path_temp); + + wgeolog(LOG_TODO,"olv_limp_t","Guardando matrices"); + + //lanza los threads + lanza_subthrs(OLV_LIMP_EV_GUARD_MATS_SUB); + + return TRUE; +} +//************************************************************************************* +/* + * Cada thread de los que guardan a disco la matriz de dist entre conjunciones y de ángulos + */ +void Colv_limp_thr::guarda_mats_sub(int ithr) +{ + int nconj,ic; + int n_ini, n_desp, n_fin, seg; + BOOL mal=FALSE; + Param_olv_limp_thr pp; + HeadCostConj hd; + HeadCostAng hda; + + //////////////// + pp.id_e=OLV_TAREA_GUARD_MAT;//manda de parámetro la tarea de la que es el progreso + nconj=olv_limp->conjs.n; + //las conjunciones que va a hacer + n_desp = (int)ceil(1.0*nconj/n_subthr); + n_ini=ithr*n_desp; + n_fin = min((ithr+1)*n_desp,nconj); + + memset(&hd,0,sizeof(HeadCostConj)); + memset(&hda,0,sizeof(HeadCostAng)); + //////////////// + + wgeolog(LOG_TODO,"olv_limp_t","Subthr %ld, Guardando filas de matrices %04d a %04d", ithr,n_ini, n_fin); + + seg = GetTickCount(); + ///////////////////////////////////// + //bucle por cada conjunción de la carto + Cgarray bufer; + for(ic=n_ini; iccost_conj[ic].guarda(hd,ic,olv_limp->olv_tasks->path_cconj,TASKS_EXT_MAT,&bufer)) + { + mal=TRUE; + continue; + } + + if(olv_limp->ang_conj) + { + if(!olv_limp->ang_conj[ic].guarda(hda,ic,olv_limp->olv_tasks->path_ang, TASKS_EXT_MAT)) + { + mal=TRUE; + continue; + } + } + + //avisa de progreso + if(((ic-n_ini)%500==0) || ((ic-n_ini)==(n_desp-1))) + { + wgeolog(LOG_TODO,"olv_limp_t","Subthr %ld, Guardando matrices, %ld de %ld", ithr, + (ic-n_ini+1),n_desp); + //avisa de progreso + prog_subthr=(1.0*(ic-n_ini+1)/n_desp);/// + thr_padre->encola(OLV_LIMP_EV_SUBTHR_PROG,&pp,FALSE); + } + } + if(mal) + goto va_mal; + +va_mal: + if(mal) + { + wgeolog(LOG_TODO,"olv_limp_t","Subthr %ld, Error en guardado de matrices", ithr); + prog_subthr=-1;//para avisar al padre de que ha habido un error + } + else + { + wgeolog(LOG_TODO,"olv_limp_t","Subthr %ld, Fin guardado matriz, %.3f seg", ithr, 1.0*(GetTickCount()-seg)/1000); + } + + thr_padre->encola(OLV_LIMP_EV_GUARD_MATS_FIN,NULL,FALSE); + +} +//************************************************************************************* +/* + * Cada thread de los que guardan a disco la matriz de dist entre conjunciones y de ángulos + */ +BOOL Colv_limp_thr::guarda_mats_fin() +{ + //////////////// + //para los threads + para_subthrs(); + + //guarda matriz de info aso + guarda_iaso(); + wgeolog(LOG_TODO,"olv_limp_t","Guardada matriz de info aso"); + + //libera esta memoria que ya no le hace falta + olv_limp->tip_conj.clear(); + + wgeolog(LOG_TODO,"olv_limp_t","FIN Guardado Matrices"); + return TRUE; +} +//************************************************************************************* +/* + * Guarda los ic de la info aso del ámbito ia + */ +BOOL Colv_limp_thr::guarda_iaso() +{ + HANDLE hfile = INVALID_HANDLE_VALUE; + int nb, i; + HeadInfoAso hd; + + //crea archivo----------------------------------- + hfile = CreateFile(olv_limp->olv_tasks->file_iaso, GENERIC_WRITE | GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); + if (hfile == INVALID_HANDLE_VALUE) + { + i=GetLastError(); + return FALSE; + } + memset(&hd,0,sizeof(HeadInfoAso)); + hd.nint=olv_limp->n_amb*3; + //graba cabecera------------ + nb = sizeof(hd); + //calcula el nb + if (nb != _lwrite((int)hfile, (LPCCH)&hd, nb)) + { + goto va_mal; + } + + nb=sizeof(int); + //se embucla en los ámbitos guardando sus flags ic[0] e ic[1] + for(i=0;in_amb;i++) + { + if (nb != _lwrite((int)hfile, (LPCCH)&olv_limp->ias[i].ic[0], nb)) + break; + if (nb != _lwrite((int)hfile, (LPCCH)&olv_limp->ias[i].ic[1], nb)) + break; + if (nb != _lwrite((int)hfile, (LPCCH)&olv_limp->ias[i].flgs, nb)) + break; + } + if(in_amb) + goto va_mal; + + CloseHandle(hfile); + return TRUE; + +va_mal: + CloseHandle(hfile); + return FALSE; +} +//************************************************************************************* +void Colv_limp_thr::ini_infotask(int ntasks) +{ + InfoIniTask ii; + memset(&ii,0,sizeof(InfoIniTask)); + ii.KK = olv_limp->tipo_ambit; + ii.n = olv_limp->conjs.n; + ii.namb = olv_limp->n_amb; + ii.nthr=n_subthr; + ii.usa_angs = (olv_limp->ang_conj!=NULL); + ii.id_instal = olv_limp->nod_instal; + ii.id_planta = olv_limp->nod_plant; + strcpy_s(ii.path_temp,MAX_PATH,olv_limp->olv_tasks->path_temp); + strcpy_s(ii.path_cconj,MAX_PATH,olv_limp->olv_tasks->path_cconj); + strcpy_s(ii.path_costamb,MAX_PATH,olv_limp->olv_tasks->path_costamb); + strcpy_s(ii.path_ang,MAX_PATH,olv_limp->olv_tasks->path_ang); + strcpy_s(ii.file_iaso,MAX_PATH,olv_limp->olv_tasks->file_iaso); + strcpy_s(ii.ext,8,TASKS_EXT_MAT); + memcpy(&olv_limp->olv->infotask,&ii,sizeof(InfoIniTask)); +} +//************************************************************************************* +BOOL Colv_limp_thr::task_dj_escucha() +{ + //////////////////////////////////////////////// + //lanza las tasks + //ejecuta n veces OliviaTasks, cada una va a calcular una parte de la matriz de costes entre ambitos + //con sus correspondientes dijkstras y lo va a escribir en disco + //antes de eso, se han guardado en disco la matriz (o maps) de costes entre conjunciones y de ángulos entre conjunciones + //////////////////////////////////////////////// + + int ntasks=1; + pon_mi_progre(OLV_TAREA_MULTITASK, 0); + wgeolog(LOG_TODO,"olv_limp_t","Comienza ejecución Multitask"); + ini_infotask(ntasks); + + //lanza la escucha + olv_limp->soc = new Csock_svThread(); + olv_limp->soc->escucha=olv_limp->olv_tasks; + + if(!olv_limp->soc->liseningThread(TASKS_PORT,olv_limp->olv->olv_sock->ip)) + { + goto mal; + } + + ////////////////////////////////////// + if(!lanza_tasks(ntasks)) + { + pon_mi_msg("Error al lanzar multitask para el cálculo de costes entre ámbitos"); + return FALSE; + } + for(int i=ntasks;iprog_subthr = 0; + + for(int i=0;isoc->close(); + delete olv_limp->soc; + olv_limp->soc=NULL; + return FALSE; +} +//************************************************************************************* +BOOL Colv_limp_thr::task_dj_fin() +{ + //debe iniciar la matriz cost_amb y leerla lo que han rellenado los tasks, y combinarla + + return TRUE; +} +//************************************************************************************* +void Colv_limp_thr::borra_temp_files(BOOL todo/*=TRUE*/) +{ + Cdir_manager dm; + if(todo) + { + //borra los archivos de dijkstra + dm.borra_archivos(olv_limp->olv->paths.path_temp,EXT_ARCH_DIJ_DEFAULT); + } + //borra los archivos asociados al multitask + dm.borra_archivos(olv_limp->olv->paths.path_temp,TASKS_EXT_MAT,TRUE); + dm.borra_archivos(olv_limp->olv->paths.path_temp,TASKS_EXT_DIS,TRUE); +} +//************************************************************************************* +//************************************************************************************* +//************************************************************************************* +//************************************************************************************* +/** + * Thread para cálculo multiproceso de la planificación + */ +UINT th_planificacion(LPVOID pp) +{ + th_param_planif *p=(th_param_planif*)pp; + int id_th=p->id_th; + int id_curro=p->id_curro; + int ini, fin, i, j, entr, entr_m; + int mm[2]; + double d, dm; + p->id_th=-1; + while(!p->pirate) + { + if(id_curro==p->id_curro) + { + //no curro + Sleep(p->milis_sleep); + continue; + } + id_curro=p->id_curro; + //ha currar + switch(p->modo) + { + case (0)://cambio de un elemento en la ruta + i=p->namb/p->nth; + ini=max(i*id_th, 1); + if(id_th+1==p->nth) + fin=p->namb; + else + fin=ini+i; + i=-1; + dm=MAYUSCULO; + entr=0; + while(iniparam[0]) + { + + d=p->tl->dame_coste(p->sec, 0,p->namb-1, p->ias, p->s, p->abs); + + } + else + d=p->tl->dame_coste_ex(p->sec,0,p->namb-1,p->ias, p->s,p->param[0],ini, entr); + if(d=1 || (ini==p->param[0])) + { + ini++; + entr=0; + } + else + entr=1; + + } + p->dth[id_th].coste=dm; + p->dth[id_th].pos[0]=i; + p->dth[id_th].pos[1]=entr_m; + + break; + case (1)://permutaciones de elementos + i=Colv_geom::fact(p->param[1]-p->param[0]); + j=i/p->nth; + ini=max(i*id_th, 1); + if(id_th+1==p->nth) + fin=i; + else + fin=ini+j; + i=-1; + dm=MAYUSCULO; + while(initl->permuta(p->sec, p->param[0], p->param[1], ini, p->dth[id_th].sec)) + { + ini++; + continue; + } + d=p->tl->dame_coste(p->dth[id_th].sec, 0,p->namb-1, p->ias, p->s, p->abs); + if(dtl->permuta(p->sec, p->param[0], p->param[1], i, p->dth[id_th].sec)) + { + p->dth[id_th].coste=MAYUSCULO; + } + else + p->dth[id_th].coste=dm; + p->dth[id_th].pos[0]=i; + break; + case (2)://cambio de un elemento en la ruta (cambiandolo de verdad) + //pilla un entorno de como mucho +-100 ambitos para las permu + //----------------------------------------------- + /*i=p->namb/p->nth; + ini=max(i*id_th, 1); + if(id_th+1==p->nth) + fin=p->namb; + else + fin=ini+i;*/ + mm[0]=max(p->param[0]-50,0); + mm[1]=min(mm[0]+101,p->namb); + i=(mm[1]-mm[0])/p->nth; + ini=mm[0]+max(i*id_th, 1); + if(id_th+1==p->nth) + fin=mm[1]; + else + fin=ini+i; + //----------------------------------------------- + + i=-1; + dm=MAYUSCULO; + entr=entr_m=0; + while(iniparam[0]) + { + d=p->tl->dame_coste(p->sec, 0,p->namb-1, p->ias, p->s, p->abs); + + } + else + { + memcpy(p->dth[id_th].sec,p->sec, p->namb_t*sizeof(Secu_amb)); + p->tl->cambia_elem(p->dth[id_th].sec, p->param[0],ini, entr); + d=p->tl->dame_coste(p->dth[id_th].sec, 0,p->namb-1, p->ias, p->s, p->abs); + } + if(d=1 || (ini==p->param[0])) + { + ini++; + entr=0; + } + else + entr=1; + + } + p->dth[id_th].coste=dm; + p->dth[id_th].pos[0]=i; + p->dth[id_th].pos[1]=entr_m; + + break; + default: + break; + } + p->dth[id_th].currando=FALSE; + } + //salida de thread------------------------- + p->dth[id_th].activo=FALSE; + igt_sum_atm(&p->nth,-1); + + return 0; +} +//************************************************************************************* +//************************************************************************************* +//************************************************************************************* +//************************************************************************************* +//************************************************************************************* +#endif \ No newline at end of file diff --git a/Olivia/olv_reco.cpp b/Olivia/olv_reco.cpp new file mode 100644 index 0000000..ee92ded --- /dev/null +++ b/Olivia/olv_reco.cpp @@ -0,0 +1,371 @@ +#include "stdafx.h" +#ifdef OLIVIA_COMPILA +#include "olv_reco.h" +#include "olv_reco_thr.h" +#include "olv_geom.h" +#include "olv_sens_ws.h" +#include "ini_file.h" +/** +* @file olv_reco.cpp +* Archivo de definiciones y variables de la utilidad de recogida de residuos del programa Olivia. +*/ +Colv_reco::Colv_reco(COlivia *olv) : Colv_limp(olv) +{ + this->olv = olv; + thr_reco = new Colv_reco_thr(this); + + //rellena_campos(); + t_vaci=t_sal=0; + kg_max=kg_reco_def=0; + anch_vehi=0; + giro_vehi=OLV_LIMP_GIRO_VEHIC; + memset(coor_plant,0,3*sizeof(double)); + nod_instal=nod_plant=-1; + ptos_vaci=NULL; + dens_frac=150; + info_carg=NULL; + // +} + +Colv_reco::~Colv_reco(void) +{ + + cancela(); + delete(thr_reco); + + if(ptos_vaci) + free(ptos_vaci); + + if(info_carg) + free(info_carg); + + if(ord_sec_plan) + { + if(ord_sec_plan[1].ctnod[0] && ord_sec_plan[1].ctnod[0]==ord_sec_plan[0].ctnod[0]) + ord_sec_plan[1].ctnod[0]=NULL; + + //solo libera la segunda parte parte, el destructor de limp hace el resto + if(ord_sec_plan[1].ctnod[0]) + { + ord_sec_plan[1].libera(0,conjs.n); + free(ord_sec_plan[1].ctnod[0]); + } + ord_sec_plan[1].ctnod[0]=NULL; + } + +} +//************************************************************************************* +/** + * Termina las tareas + */ +void Colv_reco::cancela() +{ + thr_reco->termina_th(); +} +//************************************************************************************* +/** + * Inicia las variables que son propias de limpieza + */ +void Colv_reco::inicia_limp() +{ + res_circ=OLV_RES_RECOGER_SOLO_LADO_Y_GIROS; + t_tto=t_vaci; + //ang_lim = giro_vehi*OLV_PI/180; + tipo_ambit=OLV_AMB_PUN; + v_despl=0; + uds_tto=OliviaDef::GeneralDef::OlvTipTtoMin; +} +//************************************************************************************* +/** + * Rellena los campos de la dbf + */ +void Colv_reco::rellena_campos() +{ + camps_r.campo_uds[0]=0; + camps_r.campo_capa[0]=0; + camps_r.campo_kgcont[0]=0; + Colv_limp::rellena_campos(); + rellena_campos_sens(); +} +//************************************************************************************* +/** + * Pone las opciones de configuración de lo que recibe por el socket + */ +int Colv_reco::pon_config(char *config_) +{ + int j; + char *token; + char config[2048]; + + if(!config) + return 0; + + strcpy_s(config,2048,config_); + + j=Colv_limp::pon_config(config); + + //los parámetros son: + token = strtok(config, OliviaDef::GeneralDef::EjecGeoParamSep); + //avanza al siguiente token, el primero indica "\CONFIGURACION" + token = strtok(NULL, OliviaDef::GeneralDef::EjecGeoParamSep); + + while (token != NULL) + { + if(strstr(token,OliviaDef::GeneralDef::GR_kgM)) + { + if(!olv->dame_param(token, &kg_max)) + break; + } + else if(strstr(token,OliviaDef::GeneralDef::GR_dens)) + { + if(!olv->dame_param(token, &dens_frac)) + break; + } + else if(strstr(token,OliviaDef::GeneralDef::GR_camp_uds)) + { + if(!olv->dame_param(token, camps_r.campo_uds,sizeof(camps_r.campo_uds))) + break; + } + else if(strstr(token,OliviaDef::GeneralDef::GR_camp_kgrec)) + { + if(!olv->dame_param(token, camps_r.campo_kgcont,sizeof(camps_r.campo_kgcont))) + break; + } + else if(strstr(token,OliviaDef::GeneralDef::GR_camp_cap)) + { + if(!olv->dame_param(token, camps_r.campo_capa,sizeof(camps_r.campo_capa))) + break; + } + else if(strstr(token,OliviaDef::GeneralDef::GR_kgrecog)) + { + if(!olv->dame_param(token, &kg_reco_def)) + break; + } + else if(strstr(token,OliviaDef::GeneralDef::GR_tvc)) + { + if(!olv->dame_param(token, &t_vaci)) + break; + } + else if(strstr(token,OliviaDef::GeneralDef::GR_tdca)) + { + if(!olv->dame_param(token, &t_descarg)) + break; + t_descarg=t_descarg*60;//porque viene en minutos + } + else if(strstr(token,OliviaDef::GeneralDef::GR_tsal)) + { + if(!olv->dame_param(token, &t_sal)) + break; + t_sal=t_sal*60;//porque viene en minutos + } + else if(strstr(token,OliviaDef::GeneralDef::GR_anc)) + { + if(!olv->dame_param(token, &anch_vehi)) + break; + } + else if(strstr(token,OliviaDef::GeneralDef::GR_gir)) + { + if(!olv->dame_param(token, &giro_vehi)) + break; + } + else if(strstr(token,OliviaDef::GeneralDef::GR_descx)) + { + if(!olv->dame_param(token, &coor_plant[0])) + break; + } + else if(strstr(token,OliviaDef::GeneralDef::GR_descy)) + { + if(!olv->dame_param(token, &coor_plant[1])) + break; + } + else if(strstr(token,OliviaDef::GeneralDef::GR_carga_cont)) + { + if(!olv->dame_param(token, &info_sens.porc_lim)) + break; + } + else if(strstr(token,OliviaDef::GeneralDef::GR_sens_modo)) + { + if(!olv->dame_param(token, &info_sens.modo_pet)) + break; + } + else if(strstr(token,OliviaDef::GeneralDef::GR_sens_url)) + { + if(!olv->dame_param(token, info_sens.url,sizeof(info_sens.url))) + break; + for(int i=0;info_sens.url[i]; i++ ) + { + if(info_sens.url[i]=='\\') + info_sens.url[i]='/'; + } + } + else if(strstr(token,OliviaDef::GeneralDef::GR_sens_id)) + { + if(!olv->dame_param(token, info_sens.camps.id,sizeof(info_sens.camps.id))) + break; + } + else if(strstr(token,OliviaDef::GeneralDef::GR_sens_fecha)) + { + if(!olv->dame_param(token, info_sens.fecha_ini,sizeof(info_sens.fecha_ini))) + break; + } + else if(strstr(token,OliviaDef::GeneralDef::GR_sens_fechaf)) + { + if(!olv->dame_param(token, info_sens.fecha_fin,sizeof(info_sens.fecha_fin))) + break; + } + else if(strstr(token, OliviaDef::GeneralDef::GR_lateral)) + { + if(!olv->dame_param(token, &lateral)) + break; + } + else + { + token = strtok(NULL, OliviaDef::GeneralDef::EjecGeoParamSep); + continue; + } + token = strtok(NULL, OliviaDef::GeneralDef::EjecGeoParamSep); + j++; + } + + strcpy_s(olv->paths.path_res_rut,MAX_PATH,olv->paths.path_data); + strcpy_s(olv->paths.path_res_pt,MAX_PATH,olv->paths.path_data); + + inicia_limp(); + + return j; +} +//************************************************************************************* +/** + * Inicia las tareas de la utilidad de limpieza viaria + */ +BOOL Colv_reco::inicia() +{ + //arranca el thread + thr_reco->inicia_th(); + //empieza importando + thr_reco->encola(thr_reco->OLV_LIMP_EV_ABRE_DAT,NULL,FALSE); + + return TRUE; +} +//************************************************************************************* +void Colv_reco::dame_cost( double ltot, int ia, float *cost, float *cost2 ) +{ + Colv_limp::dame_cost(ltot,ia,cost,cost2); + //sustituye el caso de que sea contenedor + if((iaso[ia].flgs & OLV_LIMP_FLG_AMB) && (tipo_ambit==OLV_AMB_PUN)) + { + *cost=*cost2=(float)(t_tto*iaso[ia].inf_r.uds); //en segundos, el tiempo que tarda en vaciar un contenedor, por el número de contenedores + } +} +//************************************************************************************* +/** + * Rellena los campos del método POST para lectura de los sensores + */ +void Colv_reco::rellena_campos_sens() +{ + //info para el cuerpo del envío post + sprintf_s(info_sens.camps.fn,OLV_MAX_CAMP_HTTP,"fn"); + sprintf_s(info_sens.camps.id,OLV_MAX_CAMP_HTTP,"id"); + sprintf_s(info_sens.camps.usr,OLV_MAX_CAMP_HTTP,"usr"); + sprintf_s(info_sens.camps.pwd,OLV_MAX_CAMP_HTTP,"pwd"); + sprintf_s(info_sens.camps.startdate,OLV_MAX_CAMP_HTTP,"startdate"); + sprintf_s(info_sens.camps.enddate,OLV_MAX_CAMP_HTTP,"enddate"); + + //el envío del POST al web service + sprintf_s(info_sens.fn_cont_status,OLV_MAX_URL,"get_container_status"); + sprintf_s(info_sens.usr,OLV_MAX_CAMP_HTTP,"VSM"); + sprintf_s(info_sens.pwd,OLV_MAX_CAMP_HTTP,"VSM2017"); + sprintf_s(info_sens.url,OLV_MAX_URL,"http://localiza.info/Utilidades/APIManager.aspx"); + + //la respuesta del servicio en JSON + sprintf_s(info_sens.camps_json.histo,OLV_MAX_CAMP_HTTP_LONG,"HistoricalFillingData"); + sprintf_s(info_sens.camps_json.id,OLV_MAX_CAMP_HTTP_LONG,"ContainerID"); + sprintf_s(info_sens.camps_json.porc,OLV_MAX_CAMP_HTTP_LONG,"FillingPercentage"); + sprintf_s(info_sens.camps_json.resp_code,OLV_MAX_CAMP_HTTP_LONG,"ResponseCode"); + sprintf_s(info_sens.camps_json.resp_code_err,OLV_MAX_CAMP_HTTP_LONG,"ERROR"); + sprintf_s(info_sens.camps_json.resp_data,OLV_MAX_CAMP_HTTP_LONG,"ResponseData"); + + CTime tt = CTime::GetCurrentTime(); + sprintf_s(info_sens.fecha_fin,OLV_MAX_CAMP_HTTP_LONG,"%04d-%02d-%02dT%02d%%%%3A00%02d%%%%3A00%02d",tt.GetYear(),tt.GetMonth(),tt.GetDay(), + tt.GetHour(),tt.GetMinute(),tt.GetSecond());//"2017-10-19T13:44:00"); + + tt = tt - CTimeSpan(0,1,0,0); //una hora menos + sprintf_s(info_sens.fecha_ini,OLV_MAX_CAMP_HTTP_LONG,"%04d-%02d-%02dT%02d%%%%3A00%02d%%%%3A00%02d",tt.GetYear(),tt.GetMonth(),tt.GetDay(), + tt.GetHour(),tt.GetMinute(),tt.GetSecond());//"2017-10-19T13:44:00"); + + info_sens.modo_pet=OLV_SENS_PET_UNICO; + info_sens.porc_lim= 0; + + if(olv->paths.path_cfg_geo[0]) + { + if(!lee_campos_sens_ini(olv->paths.path_cfg_geo)) + guarda_campos_sens_ini(olv->paths.path_cfg_geo); + } +} +//************************************************************************************* +BOOL Colv_reco::lee_campos_sens_ini(char *path) +{ + Cini_file ini; + int ig; + + if(!ini.lee(path)) + return FALSE; + ig=ini.get_grupo(OLV_RECO_GRUPO_SENS); + if(ig<0) + return FALSE;//no existe grupo + + //leer campos del ini + ini.dame_valor(ig,OLV_RECO_PARAM_FN,info_sens.camps.fn,"fn"); + ini.dame_valor(ig,OLV_RECO_PARAM_ID,info_sens.camps.id,"id"); + ini.dame_valor(ig,OLV_RECO_PARAM_USR,info_sens.camps.usr,"usr"); + ini.dame_valor(ig,OLV_RECO_PARAM_PWD,info_sens.camps.pwd,"pwd"); + ini.dame_valor(ig,OLV_RECO_PARAM_STRD,info_sens.camps.startdate,"startdate"); + ini.dame_valor(ig,OLV_RECO_PARAM_ENDD,info_sens.camps.enddate,"enddate"); + + ini.dame_valor(ig,OLV_RECO_PARAM_FN_STAT,info_sens.fn_cont_status,"get_container_status"); + ini.dame_valor(ig,OLV_RECO_PARAM_USR_USR,info_sens.usr,"VSM"); + ini.dame_valor(ig,OLV_RECO_PARAM_PWD_PWD,info_sens.pwd,"VSM2017"); + + ini.dame_valor(ig,OLV_RECO_PARAM_JS_ID,info_sens.camps_json.id,"ContainerID"); + ini.dame_valor(ig,OLV_RECO_PARAM_JS_HISTO,info_sens.camps_json.histo,"HistoricalFillingData"); + ini.dame_valor(ig,OLV_RECO_PARAM_JS_PORC,info_sens.camps_json.porc,"FillingPercentage"); + ini.dame_valor(ig,OLV_RECO_PARAM_JS_R_CODE,info_sens.camps_json.resp_code,"ResponseCode"); + ini.dame_valor(ig,OLV_RECO_PARAM_JS_R_CODE_ERR,info_sens.camps_json.resp_code_err,"ERROR"); + ini.dame_valor(ig,OLV_RECO_PARAM_JS_R_DATA,info_sens.camps_json.resp_data,"ResponseData"); + + return TRUE; +} +//************************************************************************************* +BOOL Colv_reco::guarda_campos_sens_ini(char *path) +{ + Cini_file ini; + + int ig =ini.add_grupo(OLV_RECO_GRUPO_SENS); + if(ig<0) + return FALSE; + + ini.add(ig,OLV_RECO_PARAM_FN,info_sens.camps.fn); + ini.add(ig,OLV_RECO_PARAM_ID,info_sens.camps.id); + ini.add(ig,OLV_RECO_PARAM_USR,info_sens.camps.usr); + ini.add(ig,OLV_RECO_PARAM_PWD,info_sens.camps.pwd); + ini.add(ig,OLV_RECO_PARAM_STRD,info_sens.camps.startdate); + ini.add(ig,OLV_RECO_PARAM_ENDD,info_sens.camps.enddate); + + ini.add(ig,OLV_RECO_PARAM_FN_STAT,info_sens.fn_cont_status); + ini.add(ig,OLV_RECO_PARAM_USR_USR,info_sens.usr); + ini.add(ig,OLV_RECO_PARAM_PWD_PWD,info_sens.pwd); + + ini.add(ig,OLV_RECO_PARAM_JS_ID,info_sens.camps_json.id); + ini.add(ig,OLV_RECO_PARAM_JS_HISTO,info_sens.camps_json.histo); + ini.add(ig,OLV_RECO_PARAM_JS_PORC,info_sens.camps_json.porc); + ini.add(ig,OLV_RECO_PARAM_JS_R_CODE,info_sens.camps_json.resp_code); + ini.add(ig,OLV_RECO_PARAM_JS_R_CODE_ERR,info_sens.camps_json.resp_code_err); + ini.add(ig,OLV_RECO_PARAM_JS_R_DATA,info_sens.camps_json.resp_data); + + if(!ini.guarda(path)) + return FALSE; + + return TRUE; +} +//************************************************************************************* +#endif \ No newline at end of file diff --git a/Olivia/olv_reco.h b/Olivia/olv_reco.h new file mode 100644 index 0000000..f1c689c --- /dev/null +++ b/Olivia/olv_reco.h @@ -0,0 +1,84 @@ +#pragma once +#ifdef OLIVIA_COMPILA +#include "olv_limp.h" +#include "olv_sens_ws.h" + +class COlivia; +class Colv_reco_thr; + +#define OLV_RECO_GRUPO_SENS "CAMPOS_SENS" +#define OLV_RECO_PARAM_FN "fn" +#define OLV_RECO_PARAM_ID "id" +#define OLV_RECO_PARAM_USR "usr" +#define OLV_RECO_PARAM_PWD "pwd" +#define OLV_RECO_PARAM_STRD "startd" +#define OLV_RECO_PARAM_ENDD "endd" +#define OLV_RECO_PARAM_FN_STAT "fn_status" +#define OLV_RECO_PARAM_USR_USR "usr_usr" +#define OLV_RECO_PARAM_PWD_PWD "pwd_pwd" +#define OLV_RECO_PARAM_JS_ID "js_id" +#define OLV_RECO_PARAM_JS_HISTO "js_histo" +#define OLV_RECO_PARAM_JS_PORC "js_porc" +#define OLV_RECO_PARAM_JS_R_CODE "js_r_cd" +#define OLV_RECO_PARAM_JS_R_CODE_ERR "js_r_cd_err" +#define OLV_RECO_PARAM_JS_R_DATA "js_r_dt" + +/** + * @file olv_reco.h + * Archivo de definiciones y variables de la utilidad de recogida de residuos del programa Olivia. + */ + +/** + * Estructura que contiene los nombres de los campos a leer + */ +typedef struct Campos_dbf_reco +{ + char campo_uds[OLV_LIMP_MAX_CAMP]; + char campo_capa[OLV_LIMP_MAX_CAMP]; + char campo_kgcont[OLV_LIMP_MAX_CAMP]; +}Campos_dbf_reco; + +/** + * Enumeración para identificar si es instalación de salida llegada o planta de descarga + */ +enum InstalPlant{ + OLV_INSTAL, + OLV_PLANT, +}; +/** + * Clase de definiciones y variables de la utilidad de recogida de residuos del programa Olivia. + */ +class Colv_reco : public Colv_limp +{ +public: + //************************************************************************************* + //Variables + Colv_reco_thr *thr_reco; /// +#include +#include +//utiles +#include "b_file.h" +#include "Fdbf.h" +#include "ManagerDbfGdataTable.h" +using namespace std; +/** +* @file olv_limp_thr.h +* Archivo de implementaciones del thread de control de la utilidad de recogida de residuos del programa Olivia. +*/ +Colv_reco_thr::Colv_reco_thr(Colv_reco *olv_reco) : Colv_limp_thr(olv_reco) +{ + this->olv_reco = olv_reco; +} + +Colv_reco_thr::~Colv_reco_thr(void) +{ + //destruye los subthreads + if(subthrs) + { + for(int i=0;itramos) + delete [] olv_limp->tramos; +} +//************************************************************************************* +void Colv_reco_thr::inicia_th() +{ + inicia(OLV_MILIS_COLA,&cola_proc,-1,"reco_thr"); + olvlog(LOG_TODO,"olv_limp_t","Thread de recogida reco_thr arrancado"); + borra_temp_files(); + pirate=FALSE; +} +//************************************************************************************* +/** + * Cola de procesos en la que itera el thr cuando es recogida. Override de limpieza, así que se implementan\n + * solo los eventos que tienen sentido en recogida y son diferentes que en limpieza + */ +void Colv_reco_thr::cola_proc(int evento, OlvAsync_cola *clase,Param_olv_limp_thr *e) +{ + BOOL bien=TRUE; + BOOL hecho=FALSE; + + Colv_reco_thr *this_i=static_cast(clase); + switch (evento) + { + case OLV_LIMP_EV_RELL_DAT: + { + hecho=TRUE; + bien=this_i->rellena_datos(); + if(bien && (this_i->olv->modo_ejecpirate)//sigue + { + if(this_i->olv_reco->info_sens.url[0]==0) + this_i->encola(OLV_LIMP_EV_UNE_AMB_NW,NULL,FALSE); + else + this_i->encola(OLV_RECO_EV_SENS,NULL,FALSE); + } + break; + } + case OLV_RECO_EV_SENS: + { + //esta tarea lanza varios subthreads para realizar las peticiones de carga a los + //sensores(les encola la tarea pide_info_sensores_sub), + //y estos cuando acaban le encolan al padre (el que los ha lanzado) + //la tarea de dist_conj_fin + hecho=TRUE; + bien=this_i->pide_info_sens(); + break; + } + case OLV_RECO_EV_SENS_SUB: + { + //aquí entran los subthreads para hacer los cálculos de ángulos, cuando acaban + //encolan al padre la tarea de fin + int ithr; + hecho=TRUE; + if(e!=NULL) + ithr=e->id_e; + this_i->pide_info_sens_sub(ithr); + break; + } + case OLV_RECO_EV_SENS_FIN: + { + //aquí entra el padre cuando van acabando los subthreads + //si han terminado todos encola la siguiente tarea + int i; + int nno; + hecho=TRUE; + this_i->n_subthr_fin++; + nno=0; + if(this_i->n_subthr_fin==this_i->n_subthr) + { + this_i->n_subthr_fin=0; + for(i=0;in_subthr;i++) + { + if(this_i->subthrs[i]->prog_subthr<0) + break; + nno+=(int)this_i->subthrs[i]->prog_subthr; + } + if(in_subthr) + { + bien=FALSE; + this_i->pon_mi_msg("Errores en la conexión con la base de datos de los sensores"); + break; + } + bien=this_i->pide_info_sens_fin(nno); + if(bien && (this_i->olv->modo_ejecpirate)//sigue + this_i->encola(OLV_LIMP_EV_UNE_AMB_NW,NULL,FALSE); + } + break; + } + } + if(!bien) + { + this_i->pon_mi_progre(OLV_TAREA_FIN_NOK,0); + } + if(!hecho) + Colv_limp_thr::cola_proc(evento, clase,e); +} +//************************************************************************************* +/** + * Rellena la información asociada de la red navegable y los datos de limpieza + */ +BOOL Colv_reco_thr::rellena_datos() +{ + int icampu,icampkg,ia,uds_,icampcap,icampid,icampoid, capa_, idd; + char nfile[MAX_PATH]; + Cb_file f; + Fdbf dbf; + char *uds, *kg, *capa, *id; + double kg_,auxi; + BOOL ret=TRUE; + + olvlog(LOG_TODO,"olv_limp_t","Rellenando matriz de info asociada a ámbitos"); + pon_mi_progre(OLV_TAREA_IMP, (int) (OliviaDef::GeneralDef::ProgrMax*2/3)); + + uds=kg=capa=id=0; + + //lee dbf del shp + strcpy_s(nfile,MAX_PATH,olv->paths.path_data); + //cambiaext(nfile,".shp",".dbf"); + strcpy((Cdir_manager::extension_archivo(nfile)),"dbf"); + + if(!f.abre(nfile,1) || !dbf.lee(&f)) + { + pon_mi_msg("Error al abrir %s",nfile); + ret=FALSE; + goto fin; + } + + //busca el campo de unidades + icampu=dbf.findCol(olv_reco->camps_r.campo_uds); + if(icampu==-1) + { + sprintf_s(err_str,OLV_MAX_ERR,"No encontrado campo %s en\n%s",olv_reco->camps_r.campo_uds,olv_limp->camps.campo_anch, + olv_limp->camps.campo_tipo_ap,olv_limp->camps.campo_tipo_ent,nfile); + ret=FALSE; + goto fin; + } + icampoid=dbf.findCol(OLV_NOMB_OID); + icampkg=icampcap=icampid=-1; + //busca el campo de kgrec, si es el caso + //si es 0 los kg por defecto, se lee el campo de kg, si es negativo, se lee el campo de capacidad porque o bien están + //llenos o bien se lee la info de los sensores, pero tiene densidad + if(olv_reco->kg_reco_def==0) + { + icampkg=dbf.findCol(olv_reco->camps_r.campo_kgcont); + if(icampkg==-1) + { + sprintf_s(err_str,OLV_MAX_ERR,"No encontrado campo %s en\n%s",olv_reco->camps_r.campo_kgcont,nfile); + ret=FALSE; + goto fin; + } + } + else if(olv_reco->kg_reco_def<=0)//busca el campo de capacidad, si es el caso + { + icampcap=dbf.findCol(olv_reco->camps_r.campo_capa); + if(icampcap==-1) + { + sprintf_s(err_str,OLV_MAX_ERR,"No encontrado campo %s en\n%s",olv_reco->camps_r.campo_capa,nfile); + ret=FALSE; + goto fin; + } + if(olv_reco->info_sens.camps.id[0])//es el caso de los sensores + { + icampid=dbf.findCol(olv_reco->info_sens.camps.id); + if(icampid==-1) + { + sprintf_s(err_str,OLV_MAX_ERR,"No encontrado campo %s en\n%s",olv_reco->info_sens.camps.id,nfile); + ret=FALSE; + goto fin; + } + } + } + + idd =dbf.leeNexRow(); + ia=0; + while(idd == 1) + { + /////////////////////////////// + uds_=1; + uds_=dbf.getI(icampu); + if(uds_<0 || uds_>50) + { + uds_=1;//pone por def + olvlog(LOG_TODO,"olv_limp_t","Cuidado, info asociada %ld, puesto unidades por defecto a 1",ia+1); + } + olv_limp->iaso[ia].inf_r.uds=uds_; + + /////////////////////////////// + if(icampkg>-1) + { + kg_=dbf.getI(icampkg); + /*//por si viene con notación científica + stringstream ss(kg); + ss >> kg_; + if (ss.fail()) {kg_=0;} + ///////////////////////////////// + //kg_=atof(dd);*/ + if(kg_<0 || kg_>10000) + { + kg_=50;//pone por def + olvlog(LOG_TODO,"olv_limp_t","Cuidado, info asociada %ld, puesto kg por defecto a 50",ia+1); + } + uds_=1; //pone las uds a 1 para no multiplicar: en caso de que venga el campo de carga ya está multiplicado + } + else if(icampcap>-1) + { + capa_=dbf.getI(icampcap); + if(capa_<0 || capa_>100000) + { + capa_=3000;//pone por def + olvlog(LOG_TODO,"olv_limp_t","Cuidado, info asociada %ld, puesto capacidad por defecto a 3000 l",ia+1); + } + kg_=capa_*olv_reco->dens_frac/1000; //en kg /1000 para pasar de m3 a l + } + else + kg_=olv_reco->kg_reco_def; + olv_limp->iaso[ia].inf_r.kg=kg_*uds_;//pone la carga total como la carga por el número de contenedores + + /////////////////////////////// + + if(icampid>=0) + { + olv_limp->iaso[ia].inf_r.id = (char*)malloc(dbf.getSize(icampid)+1); + if(!olv_limp->iaso[ia].inf_r.id) + break; + + olv_limp->iaso[ia].inf_r.id[0]=0; + if(dbf.getType(icampid)==DBF_TYPE_DATA_STR) + { + strcpy(olv_limp->iaso[ia].inf_r.id,dbf.getStr(icampid)); + } + else + { + auxi=dbf.getD(icampid); + if(auxi==(double)(int)auxi) + { + sprintf(olv_limp->iaso[ia].inf_r.id,"%ld",(int)auxi); + } + else + { + sprintf(olv_limp->iaso[ia].inf_r.id,"%lf",auxi); + } + } + } + + if(icampoid>=0) + olv_limp->iaso[ia].oid = dbf.getI(icampoid); + + //olvlog(LOG_TODO,"olv_limp_t","Rellena %0d %3.1f %ld %04d",ia, kg_,uds_,olv_limp->iaso[ia].oid); + + /////////////////////////////// + //avisa de progreso + if((ia%100==0) || (ia==(olv_limp->n_amb-1))) + { + pon_mi_progre(OLV_TAREA_IMP, (int) (OliviaDef::GeneralDef::ProgrMax* + ((1.0*(ia+1)/olv_limp->n_amb)/3)+2/3)); + olvlog(LOG_TODO,"olv_limp_t","Rellenando info asociada a ámbitos, %ld de %ld", + ia+1,olv_limp->n_amb); + } + + ia++; + idd =dbf.leeNexRow(); + } + if(ian_amb) + { + sprintf_s(err_str,OLV_MAX_ERR,"Error al leer información asociada %ld en\n%s",ia,nfile); + ret=FALSE; + goto fin; + } + + olvlog(LOG_TODO,"olv_limp_t","Finaliza Matriz de info asociada a ámbitos"); + +fin: + if(!ret) + olvlog(LOG_TODO,"olv_limp_t","Fallos en Matriz de info asociada a ámbitos"); + + olvlog(LOG_TODO,"olv_limp_t","Giro límite %lf",olv_limp->ang_lim); + + return ret; +} +//************************************************************************************* +/** + * Para la conexión a la lectura de sensores + */ +BOOL Colv_reco_thr::pide_info_sens() +{ + olvlog(LOG_TODO,"olv_limp_t","Leyendo info de los sensores"); + pon_mi_progre(OLV_TAREA_SENS, 0); + + //Inicia el array donde se guarda la info de carga + olv_reco->info_carg = (int *)malloc(olv_limp->n_amb*sizeof(int)); + if(!olv_reco->info_carg) + { + sprintf_s(err_str,OLV_MAX_ERR,"Error, sin memoria para info de carga"); + return FALSE; + } + + //lanza los threads + lanza_subthrs(OLV_RECO_EV_SENS_SUB); + + return TRUE; +} +//************************************************************************************* +/** + * Rellena los valores de los sensores de cada contenedor + * El thread entra aquí cuando los subthreads que realizan la tarea realmente han finalizado + */ +BOOL Colv_reco_thr::pide_info_sens_fin(int nno) +{ + class AddColPorc : public IAddColDbf + { + public: + Colv_reco *olv_reco; + AddColPorc(Colv_reco *rr) + { + this->olv_reco=rr; + } + virtual void setData(int i, void *data) + { + if(data) + { + memcpy(data,(void*)&olv_reco->info_carg[i],sizeof(int)); + } + + }; + }; + AddColPorc dataDbf(olv_reco); + ManagerDbfGdataTable dbfmgr; + char path_dbf[MAX_PATH]; + //////////////// + //para los threads + para_subthrs(); + + //guarda la info al shp + strcpy_s(path_dbf,MAX_PATH,olv_limp->olv->paths.path_data); + //cambiaext(path_dbf,".shp",".dbf"); + strcpy((Cdir_manager::extension_archivo(path_dbf)),"dbf"); + if(!dbfmgr.AddCol(path_dbf,"PORC_RECO",GdataTable::Tint,&dataDbf)) + //if(!olv_limp->olv->olv_sh->add_col_dbf(path_dbf,olv_limp->n_amb,TIPO_IA_INT,(char*)olv_reco->info_carg,"PORC_RECO",err_str,OLV_MAX_ERR)) + { + free(olv_reco->info_carg); + olv_reco->info_carg=NULL; + return FALSE; + } + + olvlog(LOG_TODO,"olv_limp_t","FIN %ld peticiones de carga a sensores", + olv_limp->n_amb); + + free(olv_reco->info_carg); + olv_reco->info_carg=NULL; + return TRUE; +} +//************************************************************************************* +/** + * Rellena los valores de los sensores, es la parte de cálculos que + * realizan los subthreads. 'ithr' indica qué thread es, para calcular qué ámbitos le tocan. + */ +void Colv_reco_thr::pide_info_sens_sub(int ithr) +{ + int na_ini,na_fin,na_desp,na,nno; + int KK, seg; + Param_olv_limp_thr pp; + Colv_sens_ws sens; + double carg; + BOOL mal=FALSE; + + const int SZ_CAMP =32; + const int SZ_SENTEN =1024; + char nfile[MAX_PATH]; + + strcpy_s(nfile,MAX_PATH,olv->paths.path_data); + //cambiaext(nfile,".shp",".dbf"); + strcpy((Cdir_manager::extension_archivo(nfile)),"dbf"); + + //////////////// + pp.id_e=OLV_TAREA_SENS;//manda de parámetro la tarea de la que es el progreso + KK=olv_limp->tipo_ambit; + na_desp = (int)ceil(1.0*(olv_limp->n_amb)/n_subthr); + na_ini=ithr*na_desp; + na_fin = min((ithr+1)*na_desp,olv_limp->n_amb); + nno=0; + //////////////// + + olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Ambs %04d a %04d", ithr,na_ini, na_fin); + + seg = GetTickCount(); + + ///////////////////////////////////// + //Conecta con el servicio + sens.inicia(&olv_reco->info_sens); + ///////////////////////////////////// + + ///////////////////////////////////// + //Bucle por cada ámbito de los que le tocan a este thread para pedir su carga + ///////////////////////////////////// + for(na=na_ini;naiaso[na].inf_r.id || strlen(olv_limp->iaso[na].inf_r.id)==0) + { + olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Error en la petición de carga de contenedor %ld, no hay ID", + ithr,na); + carg=100; + olv_reco->info_carg[na]=(int) carg; + continue; + } + + ///////////////////////////////////// + //Tiene el id en info2 + carg = sens.dame_porc_cont_i(olv_limp->iaso[na].inf_r.id); + if(carg==0) + { + olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Error en la petición de carga de contenedor %s: %s",ithr, + olv_limp->iaso[na].inf_r.id,sens.err_str); + carg=100; + } + olv_reco->info_carg[na]=(int) carg; + + ///////////////////////////////////// + //Pone la carga recibida + if(carg>=olv_reco->info_sens.porc_lim)//Si la carga supera el valor límite, la pone + olv_limp->iaso[na].inf_r.kg *= carg/100; //info1 contiene antes los kg del contenedor si estuviera lleno + else + { + olv_limp->iaso[na].flgs |= OLV_LIMP_FLG_AMB_NO; //lo marca para no recogerlo + nno++; + } + + //avisa de progreso + if(((na-na_ini)%50==0) || ((na-na_ini)==(na_desp-1))) + { + olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Pidiendo info de carga a sensores %ld de %ld", ithr, + (na-na_ini+1),na_desp); + //avisa de progreso + prog_subthr=(1.0*(na-na_ini+1)/na_desp); + thr_padre->encola(OLV_LIMP_EV_SUBTHR_PROG,&pp,FALSE); + } + } + + if(mal) + { + olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Error al pedir info de carga a sensores"); + prog_subthr=-1;//para avisar al padre de que ha habido un error + + } + else + { + olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Fin peticiones de carga a sensores, %.3f seg", ithr, 1.0*(GetTickCount()-seg)/1000); + prog_subthr=nno; + } + thr_padre->encola(OLV_RECO_EV_SENS_FIN,NULL,FALSE); + + ///////////////////////////////////// +} +//************************************************************************************* +/** + * Añade a la red de conjunciones en qué conjunción está la planta y la instalación + */ +BOOL Colv_reco_thr::pon_nodos_planta(double pt[3]) +{ + double pt_[3]; + memcpy(pt_,pt,3*sizeof(double)); + + if(!Colv_limp_thr::pon_nodos_planta(pt))//es la instalación olv_limp->coor_instal + return FALSE; + + if(Colv_geom::pto_equals(pt_, olv_reco->coor_plant)) + { + memcpy(olv_reco->coor_plant,pt,3*sizeof(double)); + } + else + { + if(!Colv_limp_thr::pon_nodos_planta(olv_reco->coor_plant)) + return FALSE; + } + + return TRUE; +} +//************************************************************************************* +/** + * Apunta en qué nodos está la planta y la instalación + */ +BOOL Colv_reco_thr::busca_conjs_planta(double pt[3], int *nod) +{ + double pt_[3]; + memcpy(pt_,pt,3*sizeof(double)); + + if(!Colv_limp_thr::busca_conjs_planta(pt,nod))//es la instalación olv_limp->coor_instal, olv_limp->nod_instal + return FALSE; + + if(Colv_geom::pto_equals(pt_, olv_reco->coor_plant)) + { + olv_reco->nod_plant=*nod; + } + else + { + if(!Colv_limp_thr::busca_conjs_planta(olv_reco->coor_plant,&olv_reco->nod_plant)) + return FALSE; + } + + return TRUE; +} +//************************************************************************************* +double Colv_reco_thr::dame_cost_jornada() +{ + return olv_limp->t_conv-olv_reco->t_sal*2-olv_limp->t_desc; +} +//************************************************************************************* +/** + * Calcula el coste de los ámbitos a la planta e instalación + */ +BOOL Colv_reco_thr::calcula_cost_plant() +{ + int ic,ia,ka,nais, KK, ref_ia; + Djkt_nodo *costes_nodos; + BOOL mal=FALSE; + + //Inicia el array de orden /secuencia + olv_reco->ord_sec_plan=(Secu_amb*)malloc(sizeof(Secu_amb)*2); + if(!olv_reco->ord_sec_plan) + { + pon_mi_msg("Error, sin memoria para matriz de orden y secuencia"); + return FALSE; + } + memset(olv_reco->ord_sec_plan,0,sizeof(Secu_amb)*2); + olvlog(LOG_TODO,"olv_limp_t","Calculando coste a planta e instalación"); + + costes_nodos=NULL; + if(olv_reco->nod_plant==olv_reco->nod_instal) + KK=1; + else + KK=2; + for(int k=0;knod_plant; + else if(k==OLV_INSTAL)//instal + ic=olv_reco->nod_instal; + + if(!Colv_geom::dijkstra_ang_inv_ok(olv_limp->cost_conj, olv_limp->ang_conj, olv_limp->conjs.n, + ic, &costes_nodos, &visto_ang)) + { + mal=TRUE; + break; + } + + olv_reco->ord_sec_plan[k].ctnod[0]=costes_nodos; + olv_reco->ord_sec_plan[k].ctnod[1]=NULL; + + costes_nodos=NULL; + + //revisa si está aislado de algún ámbito + nais=0; + for(ia=0;ian_amb;ia++) + { + ref_ia=olv_limp->carto.get(ia).entity()->ref; + if(olv_limp->iaso[ref_ia].flgs & OLV_LIMP_FLG_AMB_NO) + continue; + for(ka=0;katipo_ambit;ka++) + { + if(olv_reco->ord_sec_plan[k].ctnod[0][olv_limp->iaso[ref_ia].inod[ka]].dis>=MAYUSCULO) + { + nais++; + } + } + } + if(nais) + { + mal=TRUE; + break; + } + } + + if(mal) + { + pon_mi_msg("Error al calcular costes de ámbitos a instalación"); + return FALSE; + } + + if(KK==1) + { + olv_reco->ord_sec_plan[OLV_PLANT].ctnod[0]=olv_reco->ord_sec_plan[OLV_INSTAL].ctnod[0]; + olv_reco->ord_sec_plan[OLV_PLANT].ctnod[1]=olv_reco->ord_sec_plan[OLV_INSTAL].ctnod[1]; + } + + //////////////////// + //inicializa array + olv_reco->ptos_vaci=(short*)malloc(olv_limp->n_amb*sizeof(short)); + if(!olv_reco->ptos_vaci) + return FALSE; + memset(olv_reco->ptos_vaci,0,olv_limp->n_amb*sizeof(short)); + + return TRUE; +} +//************************************************************************************* +/** + * Calcula el coste de desplazamiento de ir de ir por todos los ambitos sec desde ini hasta fin + */ +double Colv_reco_thr::dame_coste( Secu_amb * sec, int ini, int fin, Info_sec *s, BOOL ind_abs) +{ + double d=0; + int ind_cost, ind_cost1; + int fin_old=fin; + int id_ambf, ref_ambf; + int id_ambf1; + double capac_v=olv_reco->kg_max, cap_act=0,cap_h, cap_t; + int nv_p, i, sel;//numero de veces por ir a planta + double coste; + double cap_g, dd; + cap_t=cap_act; + + while(iniiamb[sec[fin].iamb]; + id_ambf1=s->iamb[sec[fin-1].iamb]; + + ref_ambf = olv_limp->carto.get(id_ambf).entity()->ref; + + + if (ind_abs) + ind_cost=id_ambf; + else + ind_cost=sec[fin].iamb; + + cap_t+=olv_reco->iaso[ref_ambf].inf_r.kg;//suma a la carga la basura del ambito + d+=olv_limp->cost_amb[id_ambf][id_ambf];//suma el coste del ambito + d+=olv_limp->arch_dj.dame_dis(id_ambf1, 0, id_ambf,sec[fin].entrada); + + fin--; + } + + + if (ind_abs) + ind_cost=s->iamb[sec[ini].iamb]; + else + ind_cost=sec[ini].iamb; + id_ambf=s->iamb[sec[ini].iamb]; + d+=olv_reco->cost_amb[id_ambf][id_ambf];//suma el coste de hacer el primer ambito + + if(ini==0)//si ini es 0 falta sumar el coste de la planta a el primer ambito + { + d+=olv_limp->arch_dj.dame_dis(olv_limp->arch_dj.id_instal, 0, s->iamb[sec[ini].iamb],0); + d+=olv_reco->t_sal; + } + + cap_t+=olv_limp->iaso[olv_limp->carto.get(id_ambf).entity()->ref].inf_r.kg;//suma a la carga total la basura del primer ambito + + nv_p=(int)(cap_t/capac_v +1);//numero de veces que se tendra que ir a planta + cap_h=nv_p*capac_v-cap_t;//carga con la que se puede jugar (holgura) capacidad desaprovechada + if(cap_h>=capac_v) + { + cap_h-=capac_v; + nv_p--; + } + + cap_t+=olv_reco->iaso[olv_limp->carto.get(ind_cost).entity()->ref].inf_r.kg; + //suma coste de ir a planta + + if (ind_abs) + ind_cost=s->iamb[sec[fin_old].iamb]; + else + ind_cost=sec[fin_old].iamb; + id_ambf=s->iamb[sec[fin_old].iamb];//id del ultimo ambito + + nv_p--;//se descuenta uno porque se tiene que terminar en planta + d+=olv_reco->ord_sec_plan[OLV_PLANT].ctnod[0][olv_reco->iaso[olv_limp->carto.get(id_ambf).entity()->ref].inod[0]].dis;//suma el coste de ir del ultimo ambito a la planta + d+=olv_reco->t_descarg;//suma el coste de descargar + d+=olv_reco->ord_sec_plan[OLV_INSTAL].ctnod[0][olv_reco->nod_plant].dis;//suma el coste de ir de planta a instalacion + d+=olv_reco->t_sal;//suma el coste de la llegada + + int iold=-1; + BOOL errores=FALSE; + double cos_tray=d; + int veces_plan=nv_p; + BOOL salir=FALSE; + double cap_ult_cont; + while (!salir) + { + salir=TRUE; + cap_h=(1+veces_plan)*capac_v-cap_t; + nv_p=veces_plan; + coste=MAYUSCULO; + cap_g=0; + sel=-1; + d=cos_tray; + cap_act=0; + int isel_old=-1; + double cap_old; + i=ini; + + while(nv_p>0 && i<=fin_old) + { + if (ind_abs) + ind_cost=s->iamb[sec[i].iamb]; + else + ind_cost=sec[i].iamb; + id_ambf=s->iamb[sec[i].iamb];//id del ambito iesimo de la secuen + ref_ambf = olv_limp->carto.get(id_ambf).entity()->ref; + cap_old=cap_act; + cap_act+=olv_reco->iaso[ref_ambf].inf_r.kg;//suma capacidad del ambito de la secuencia iesima + cap_ult_cont=olv_reco->iaso[ref_ambf].inf_r.kg; + i++; + if(i>fin_old) + { + if(cap_actiamb[sec[i].iamb];//id del ambito iesimo+1 de la secuen + if (ind_abs) + ind_cost1=s->iamb[sec[i].iamb]; + else + ind_cost1=sec[i].iamb; + if((capac_v-cap_act)>cap_h) + { + //calcula si el siguiente entra + + if((cap_act+olv_reco->iaso[olv_limp->carto.get(id_ambf1).entity()->ref].inf_r.kg)>capac_v) + { + nv_p++; + cap_h=cap_h+capac_v; + } + else + continue; + } + if(cap_act-capac_v<=0) + { + //prueba candidato + //calcula el coste de ir a planta desde el i-1 y de planta a el i y se le resta el coste de ir del i-1 al i + dd=olv_reco->ord_sec_plan[OLV_PLANT].ctnod[0][olv_reco->iaso[ref_ambf].inod[0]].dis;//coste del i-1 a planta + dd+=olv_limp->arch_dj.dame_dis(olv_limp->arch_dj.id_plan,0,id_ambf1, 0); + dd-=olv_limp->arch_dj.dame_dis(id_ambf,0,id_ambf1, 0); + + dd+=olv_reco->t_descarg;//suma el coste de descargar + if(dd>=MAYUSCULO) + errores=TRUE;//existen errores + if(coste>dd) + { + sel=i; + coste=dd; + cap_g=capac_v-cap_act; + } + } + else + { + //pone candidato + //suma coste de ir a la planta y el de volver de ella + if(coste>=MAYUSCULO) + { + if(errores) + olvlog(LOG_TODO,"olv_limp_t","No conseguido candidato para ir a descargar");//algo va mal + //pone una vuelta mas a planta en el i-1; + salir=FALSE; + veces_plan++; + if(cap_ult_cont>capac_v) + { + olvlog(LOG_TODO,"olv_limp_t","Capacidad de contenedor %ld mas grande que la del vehiculo ", i);//algo va mal + return MAYUSCULO; + } + break; + //calcula coste + + } + cap_act=0; + cap_h-=cap_g; + iold=i; + isel_old=sel; + i=sel; + d+=coste; + cap_g=0; + coste=MAYUSCULO; + sel=-1; + nv_p--; + + } + } + } + return d; +} +//************************************************************************************* +/** + * Rellena los tiempos de desplazamiento + */ +void Colv_reco_thr::pon_t_desp(Info_sec *s, Secu_amb *sec) +{ + if((olv_limp->nod_instal>=0) && (s->namb>1)) + { + s->t_despl[0]=olv_limp->arch_dj.dame_dis(olv_limp->arch_dj.id_instal,0 ,s->iamb[sec[0].iamb],sec[0].entrada); + s->t_despl[1]=olv_limp->ord_sec_plan[OLV_PLANT].ctnod[0][olv_reco->nod_instal].dis; + + } +} +//************************************************************************************* +/** + * Calcula el coste de desplazamiento de ir por todos los ambitos sec desde ini hasta fin, e indica en qué puntos se va a vaciar + */ +double Colv_reco_thr::dame_coste_pon_viajes( Secu_amb * sec, int ini, int fin, Info_sec *s, int *nvac) +{ + double d=0; + int ind_cost, ind_cost1; + int fin_old=fin; + int id_ambf, ref_ambf; + int id_ambf1; + double capac_v=olv_reco->kg_max, cap_act=0,cap_h, cap_t; + int nv_p, i, sel;//numero de veces por ir a planta + double coste; + double cap_g, dd; + cap_t=cap_act; + + BOOL ind_abs=TRUE; + + while(iniiamb[sec[fin].iamb]; + id_ambf1=s->iamb[sec[fin-1].iamb]; + + + if (ind_abs) + ind_cost=id_ambf; + else + ind_cost=sec[fin].iamb; + ref_ambf = olv_limp->carto.get(id_ambf).entity()->ref; + + cap_t+=olv_reco->iaso[ref_ambf].inf_r.kg;//suma a la carga la basura del ambito + d+=olv_limp->cost_amb[id_ambf][id_ambf];//suma el coste del ambito + d+=olv_limp->arch_dj.dame_dis(id_ambf1, 0, id_ambf,sec[fin].entrada); + fin--; + } + if (ind_abs) + ind_cost=s->iamb[sec[ini].iamb]; + else + ind_cost=sec[ini].iamb; + id_ambf=s->iamb[sec[ini].iamb]; + d+=olv_reco->cost_amb[id_ambf][id_ambf];//suma el coste de hacer el primer ambito + + if(ini==0)//si ini es 0 falta sumar el coste de la planta a el primer ambito + { + d+=olv_limp->arch_dj.dame_dis(olv_limp->arch_dj.id_instal, 0, s->iamb[sec[ini].iamb],0); + d+=olv_reco->t_sal;//suma el coste de la llegada + } + + cap_t+=olv_limp->iaso[olv_limp->carto.get(id_ambf).entity()->ref].inf_r.kg;//suma a la carga total la basura del primer ambito + + ////////////////// + //lo almacena + s->dis_med=(float)cap_t; + ////////////////// + + nv_p=(int)(cap_t/capac_v +1);//numero de veces que se tendra que ir a planta + cap_h=nv_p*capac_v-cap_t;//carga con la que se puede jugar (holgura) capacidad desaprovechada + if(cap_h>=capac_v) + { + cap_h-=capac_v; + nv_p--; + } + + cap_t+=olv_reco->iaso[olv_limp->carto.get(ind_cost).entity()->ref].inf_r.kg; + + //suma coste de ir a planta + if (ind_abs) + ind_cost=s->iamb[sec[fin_old].iamb]; + else + ind_cost=sec[fin_old].iamb; + id_ambf=s->iamb[sec[fin_old].iamb];//id del ultimo ambito + + nv_p--;//se descuenta uno porque se tiene que terminar en planta + d+=olv_reco->ord_sec_plan[OLV_PLANT].ctnod[0][olv_reco->iaso[olv_limp->carto.get(id_ambf).entity()->ref].inod[0]].dis;//suma el coste de ir del ultimo ambito a la planta + d+=olv_reco->ord_sec_plan[OLV_INSTAL].ctnod[0][olv_reco->nod_plant].dis;//suma el coste de ir de planta a instalacion + d+=olv_reco->t_descarg;//suma el coste de descargar + d+=olv_reco->t_sal;//suma el coste de la llegada + /////////////////////////// + coste=MAYUSCULO; + + int iold=-1; + BOOL errores=FALSE; + double cos_tray=d; + int veces_plan=nv_p; + BOOL salir=FALSE; + double cap_ult_cont; + while (!salir) + { + salir=TRUE; + cap_h=(1+veces_plan)*capac_v-cap_t; + nv_p=veces_plan; + coste=MAYUSCULO; + cap_g=0; + sel=-1; + d=cos_tray; + cap_act=0; + int isel_old=-1; + double cap_old; + i=ini; + //borra marcas------------ + for(int ii=0; iiiamb[sec[ii].iamb]; + olv_reco->ptos_vaci[id_ambf]=0; + } + while(nv_p>0 && i<=fin_old) + { + if (ind_abs) + ind_cost=s->iamb[sec[i].iamb]; + else + ind_cost=sec[i].iamb; + id_ambf=s->iamb[sec[i].iamb];//id del ambito iesimo de la secuen + ref_ambf = olv_limp->carto.get(id_ambf).entity()->ref; + cap_old=cap_act; + cap_act+=olv_reco->iaso[ref_ambf].inf_r.kg;//suma capacidad del ambito de la secuencia iesima + cap_ult_cont=olv_reco->iaso[ref_ambf].inf_r.kg; + i++; + if(i>fin_old) + { + if(cap_actiamb[sec[i].iamb];//id del ambito iesimo+1 de la secuen + if (ind_abs) + ind_cost1=s->iamb[sec[i].iamb]; + else + ind_cost1=sec[i].iamb; + if((capac_v-cap_act)>cap_h) + { + //calcula si el siguiente entra + + if((cap_act+olv_reco->iaso[olv_limp->carto.get(id_ambf1).entity()->ref].inf_r.kg)>capac_v) + { + nv_p++; + cap_h=cap_h+capac_v; + } + else + continue; + } + if(cap_act-capac_v<=0) + { + + //prueba candidato + //calcula el coste de ir a planta desde el i-1 y de planta a el i y se le resta el coste de ir del i-1 al i + dd=olv_reco->ord_sec_plan[OLV_PLANT].ctnod[0][olv_reco->iaso[ref_ambf].inod[0]].dis;//coste del i-1 a planta + + dd+=olv_limp->arch_dj.dame_dis(olv_limp->arch_dj.id_plan,0,s->iamb[sec[i].iamb],0); + dd-=olv_limp->arch_dj.dame_dis(id_ambf, 0, s->iamb[sec[i].iamb],0); + + dd+=olv_reco->t_descarg;//suma el coste de descargar + if(dd>=MAYUSCULO) + errores=TRUE;//existen errores + if(sel==-1 + || (coste>dd)) + { + sel=i; + coste=dd; + cap_g=capac_v-cap_act; + } + } + else + { + //suma coste de ir a la planta y el de volver de ella + if(coste>=MAYUSCULO) + { + if(errores) + olvlog(LOG_TODO,"olv_limp_t","No conseguido candidato para ir a descargar");//algo va mal + //pone una vuelta mas a planta en el i-1; + salir=FALSE; + veces_plan++; + if(cap_ult_cont>capac_v) + { + olvlog(LOG_TODO,"olv_limp_t","Capacidad de contenedor %ld mas grande que la del vehiculo ", i);//algo va mal + return MAYUSCULO; + } + break; + //calcula coste + + } + cap_act=0; + cap_h-=cap_g; + iold=i; + isel_old=sel; + i=sel; + /////////////// + //pone candidato + olv_reco->ptos_vaci[s->iamb[sec[i-1].iamb]]=(short)OLV_IDA_PLANT; + /////////////// + d+=coste; + cap_g=0; + coste=MAYUSCULO; + sel=-1; + nv_p--; + + } + } + } + + //Cuenta el número de veces que va a vaciar + sel=0; + for(i=0;inamb;i++) + { + if(olv_reco->ptos_vaci[s->iamb[sec[i].iamb]]) + sel++; + } + id_ambf=s->iamb[sec[fin_old].iamb];//id del ultimo ambito + olv_reco->ptos_vaci[id_ambf]=(short)OLV_IDA_PLANT_ULT; //indica que en el último se va a planta + + *nvac=sel; + + return d; +} +//************************************************************************************* +/** + * Lanza sub-threads + */ +void Colv_reco_thr::lanza_subthrs(int tar, int nthr_def/*=-1*/) +{ + char nomb[32]; + Param_olv_limp_thr pp; + int nn; + if((nthr_def>0) && (nthr_defn_subthr = nn; + subthrs[i]->thr_padre=this; + subthrs[i]->pirate=FALSE; + subthrs[i]->inicia(OLV_MILIS_COLA,&cola_proc,-1,nomb); + subthrs[i]->encola(tar,&pp,FALSE); + } + + //fuerza fin para que avance olivia + for(int i=nn;iprog_subthr = 0; + } + for(int i=0;i &cost_amb) +{ + Info_sec *s; + Info_amb_sec *aa; + int i,iaux,is_ini,is_fin,is_desp,is,jmin,nvac; + + BOOL log_debug=FALSE; + BOOL sal,sig; + Djkt_nodo *costes_nodos; + int nsecu,KK,ic_aux,ss; + int nsecu2; + Secu_amb *secu_ambi=NULL; + Param_olv_limp_thr pp; + Djkt_nodo *buf_aux=NULL; + int msecu1, msecu2; + + int *secu, *secu2; + costes_nodos=NULL; + msecu2 = msecu1 = olv_limp->conjs.n; + secu=(int *)malloc(olv_limp->conjs.n*sizeof(int)); + if(!secu) + { + sal=TRUE; + goto fin; + } + memset(secu,0,olv_limp->conjs.n*sizeof(int)); + secu2=(int *)malloc(olv_limp->conjs.n*sizeof(int)); + if(!secu2) + { + sal=TRUE; + goto fin; + } + memset(secu2,0,olv_limp->conjs.n*sizeof(int)); + nsecu2=0; + ////////////////////////// + pp.id_e=OLV_TAREA_PLANIF;//manda de parámetro la tarea de la que es el progreso + ic_aux=0; + KK=olv_limp->tipo_ambit; + sal=sig=FALSE; + jmin=0; + prog_subthr=0; + //cost_amb=olv_limp->cost_amb; + aa=olv_limp->amb_sec; + iaux=-1; + + //////////////////////////////////////////////////// + //mira a ver cuántos sectores le tocan a este thread + if(olv_limp->nsecnsec) + { + //solo hace un sector, el ithr-esimo + is_ini=ithr; + is_fin=ithr+1; + } + else + { + //no hace ningún sector, no hace falta + is_ini=0; + is_fin=0; + } + } + else + { + //hay más sectores que threads, le tocan más de uno + is_desp=(int)ceil(1.0*(olv_limp->nsec)/n_subthr); + is_ini=ithr*is_desp; + is_fin=min((ithr+1)*is_desp,olv_limp->nsec); + } + ////////////////////////// + if(is_fin==is_ini) + olvlog(LOG_TODO,"olv_limp_t","Subthr %02d, No Planifica ningún sector", ithr); + else if(is_fin-is_ini-1==0) + olvlog(LOG_TODO,"olv_limp_t","Subthr %02d, Planifica sector %02d", ithr,is_ini); + else + olvlog(LOG_TODO,"olv_limp_t","Subthr %02d, Planifica sectores %02d a %02d", ithr,is_ini, is_fin-1); + + buf_aux=olv_limp->arch_dj.dame_buf_nodos(); + if(!buf_aux) + { + olvlog(LOG_TODO,"olv_limp_t","Error en planifica_sub 1 th: %ld sin memo para buffer", ithr); + sal=TRUE; + } + ////////////////////////// + //bucle en todos los sectores que le tocan al thread + for(is=is_ini;issec[is]; + if(s->namb<=0) + continue; + s->cost_despl_aux=0; + sig=FALSE; + + //busca el ámbito inicial de la planificiación + secu_ambi=planifica_sect(s,olv_limp->ang_conj,OLV_LIMP_FACT_PERM); + if(!secu_ambi) + { + olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Imposible planificar sector %02d",ithr,is); + sal=TRUE; + continue; + } + if(esta_repe(secu_ambi, s->namb)) + { + olvlog(LOG_TODO,"olv_limp_t","Esta repe despues de planifica sec"); + sal=TRUE; + continue; + } + nvac=0; + s->cost_despl_aux=(float)dame_coste_pon_viajes(secu_ambi,0,s->namb-1,s,&nvac); + + if(s->cost_despl_aux==0) + { + olvlog(LOG_TODO,"olv_limp_t","Error al calcular viajes"); + sal=TRUE; + continue; + } + olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Sector %02d, va a vaciar %ld veces",ithr,is,nvac); + + /////////////////////////////////////////// + //Añade la ruta de la instalación al primer punto + + olv_limp->arch_dj.get_b(s->iamb[secu_ambi[0].iamb],secu_ambi[0].entrada, buf_aux); + Colv_geom::ruta_dj_inv_ok( + olv_reco->nod_instal,//id conjuncion inicial + &secu2[0], //puntero a secuencia + buf_aux, //nodos djktra conj final + olv_limp->conjs.n, + &nsecu2); + + if(!genera_planif_vaci(is,0, nsecu2, secu2,OLV_IDA_INST)) + sal=TRUE; + /////////////////////////////////////////// + + + secu[0]=olv_limp->iaso[olv_limp->carto.get(s->iamb[secu_ambi[0].iamb]).entity()->ref].inod[secu_ambi[0].entrada]; + aa[s->iamb[secu_ambi[0].iamb]].iseq=0; + //olv_limp->t_conv + double cc=0, cc1=0; + ss=1; + int iam_ped; + int iam_ent; + for (i=1; inamb; i++) + { + /////////////////////////////////////////// + //Comprueba si hay que ir a vaciar + if(olv_reco->ptos_vaci[s->iamb[secu_ambi[i-1].iamb]]==(short)OLV_IDA_PLANT) + { + //de i-1 a planta + cc+=Colv_geom::ruta_dj_inv_ok( + olv_limp->iaso[olv_limp->carto.get(s->iamb[secu_ambi[i-1].iamb]).entity()->ref].inod[(secu_ambi[i-1].entrada+1)%2], + &secu2[0], //puntero a secuencia + olv_reco->ord_sec_plan[OLV_PLANT].ctnod[0], //nodos djktra conj final + olv_limp->conjs.n, + &nsecu2); + if(!genera_planif_vaci(is,0, nsecu2, secu2,OLV_IDA_PLANT)) + { + sal=TRUE; + break; + } + //de planta a i + olv_limp->arch_dj.get_b(s->iamb[secu_ambi[i].iamb],secu_ambi[i].entrada, buf_aux); + iam_ped=s->iamb[secu_ambi[i].iamb]; + iam_ent=secu_ambi[i].entrada; + cc+=Colv_geom::ruta_dj_inv_ok( + olv_reco->nod_plant, + &secu2[0], //puntero a secuencia + buf_aux, //nodos djktra conj final + olv_limp->conjs.n, + &nsecu2); + + if(!genera_planif_vaci(is,0, nsecu2, secu2,OLV_VUELTA_PLANT)) + { + sal=TRUE; + break; + } + + } + else + iam_ped=iam_ent=-1; + if(i==s->namb) + continue; + /////////////////////////////////////////// + + if(iam_ped!=s->iamb[secu_ambi[i].iamb] || iam_ent!=secu_ambi[i].entrada) + olv_limp->arch_dj.get_b(s->iamb[secu_ambi[i].iamb],secu_ambi[i].entrada, buf_aux); + Colv_geom::ruta_dj_inv_ok( + olv_limp->iaso[olv_limp->carto.get(s->iamb[secu_ambi[i-1].iamb]).entity()->ref].inod[(secu_ambi[i-1].entrada+1)%2],//id conjuncion inicial + &secu[ss], //puntero a secuencia + buf_aux, //nodos djktra conj final + olv_limp->conjs.n, + &nsecu); + ss+=nsecu; + + //almacena el coste acumulado + aa[s->iamb[secu_ambi[i].iamb]].iseq=i; + + ////////////////// + if((i%50)==0 || (i==s->namb-1)) + { + //avisa de progreso + olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Planificando sector %02d, amb %ld de %ld", ithr,is, + (i+1),(s->namb)); + prog_subthr=(1.0*(i+1)/(s->namb))*((is+1)/(is_fin-is_ini)); //porque son varios sectores + thr_padre->encola(OLV_LIMP_EV_SUBTHR_PROG,&pp,FALSE); + } + ///////////////// + + } + if(olv_limp->tipo_ambit==OLV_AMB_LIN)//añade el coste del último ámbito si es lineal + { + secu[ss++]=olv_limp->iaso[olv_limp->carto.get(s->iamb[secu_ambi[s->namb-1].iamb]).entity()->ref].inod[(secu_ambi[s->namb-1].entrada+1)%2]; + } + + /////////////////////////////////////////// + //Añade la ruta del último punto a descargar + cc+=Colv_geom::ruta_dj_inv_ok( + olv_limp->iaso[olv_limp->carto.get(s->iamb[secu_ambi[s->namb-1].iamb]).entity()->ref].inod[(secu_ambi[s->namb-1].entrada+1)%2], + &secu2[0], //puntero a secuencia + olv_reco->ord_sec_plan[OLV_PLANT].ctnod[0], //nodos djktra conj final + olv_limp->conjs.n, + &nsecu2); + if(!genera_planif_vaci(is,0, nsecu2, secu2,OLV_IDA_PLANT)) + { + sal=TRUE; + break; + } + if(olv_reco->nod_instal!=olv_reco->nod_plant) + { + //de descargar a la instalación + cc+=Colv_geom::ruta_dj_inv_ok( + olv_reco->nod_plant, + &secu2[0], //puntero a secuencia + olv_reco->ord_sec_plan[OLV_INSTAL].ctnod[0], //nodos djktra conj final + olv_limp->conjs.n, + &nsecu2); + if(!genera_planif_vaci(is,0, nsecu2, secu2,OLV_VUELTA_INST)) + { + sal=TRUE; + break; + } + } + /////////////////////////////////////////// + + if(esta_repe(secu_ambi, s->namb, FALSE)) + olvlog(LOG_TODO,"olv_limp_t","Esta repe despues de planificar"); + + olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Planificando sector %02d, coste total %lf",ithr,is,s->cost_despl_aux); + + if(!pirate && !sal) + { + ////////////////////////////////// + //genera la ruta y los puntos de control + if(!genera_planif(is,s->cost_despl_aux/*-cc*/, ss, secu,OLV_PLAN_RECO)) + sal=TRUE; + olv_limp->sec[is].cost_ac=s->cost_despl_aux; + //olv_limp->sec[is].cost_ac=(float)(olv_limp->plan[is].elem[olv_limp->plan[is].nelem-1].coste+olv_limp->sec[is].t_despl[0]+olv_limp->sec[is].t_despl[1]); + } + ////////////////////////////////// + if( secu_ambi) + { + free(secu_ambi); + secu_ambi=NULL; + } + } + free(secu); + free(secu2); +fin: + //Ha terminado, encola al padre + olv_limp->arch_dj.libera_buf(buf_aux); + if(sal) + { + prog_subthr=-1;//para avisar al padre de que ha habido un error + } + thr_padre->encola(OLV_LIMP_EV_PLANIFICA_FIN,NULL,FALSE); +} +//************************************************************************************* +/** + * Pone en la ruta en qué contenedores corresponden los puntos de control + */ +void Colv_reco_thr::pon_ptos_ctrl(Info_planif *pp, int npt_ctrl, double cost_ctrl) +{ + double cost_acum, cost_viajes; + int i, ipc, iviaje; + /////////////////////////////////////////////////////////////// + //Inicializa el array de puntos de control + pp->pts_ctrl=(Info_planif_ctrl*)malloc((olv_limp->npts_ctrl-2+1)*sizeof(Info_planif_ctrl)); + if(!pp->pts_ctrl) + return; + memset(pp->pts_ctrl,0,(olv_limp->npts_ctrl-2+1)*sizeof(Info_planif_ctrl)); + ipc=0; + + ///////////////////////////// + cost_acum=cost_viajes=0; + iviaje=1;//la primera ida será en el viaje 1 (ida desde inst,ida a planta) + for(i=0;inelem;i++) + { + ///////////////////////////// + cost_acum=pp->elem[i].coste+cost_viajes; + + //mira si toca punto de control + if((cost_acum-ipc*(cost_ctrl/*+olv_limp->t_desc*/))>(cost_ctrl+1)) + { + if(ipcpts_ctrl[ipc].ipt=i-1; + ipc++; + } + else + ipc=ipc; + } + + if(pp->elem[i].tp==OLV_PLAN_TIP_AMB) + { + if(olv_reco->ptos_vaci[olv_limp->iaso[pp->elem[i].refe].iamb]==(short)OLV_IDA_PLANT) + { + cost_viajes+=pp->planif_insta[iviaje].elem[pp->planif_insta[iviaje].nelem-1].coste;//ida + iviaje++; + cost_viajes+=olv_reco->t_descarg; + cost_viajes+=pp->planif_insta[iviaje].elem[pp->planif_insta[iviaje].nelem-1].coste;//vuelta + iviaje++; + } + } + } + + for(i=0;ipts_ctrl[i].ipt<0) + pp->pts_ctrl[i].ipt=pp->nelem-1; + } +} +//************************************************************************************* +/** + * Dada la secuencia de las conjunciones que sigue la ruta para ir a vaciar, genera el obg + */ +BOOL Colv_reco_thr::genera_planif_vaci(int is, int ini, int fin, int *secu, int tip_viaje) +{ + int i,nvaciados; + Info_planif *pp,*pp_insta; + Info_sec *ss; + + ss=&olv_limp->sec[is]; + pp=&olv_limp->plan[is]; + pp_insta = pp->planif_insta; + nvaciados=0; + if(!pp_insta) + { + nvaciados=1;//siempre está el último, que va a vaciar + for(i=0;inamb;i++) + { + if(olv_reco->ptos_vaci[ss->iamb[i]]==(short)OLV_IDA_PLANT) + nvaciados++;//por cada vez que va a descargar + } + } + if(!genera_planif_instala(is, nvaciados, ini, fin, secu, tip_viaje)) + return FALSE; + + return TRUE; +} +//************************************************************************************* +/** + * Añade una línea al listado csv con el viaje a vaciar y vuelta + */ +BOOL Colv_reco_thr::genera_list_fila_vaci(Colv_csv *cc, char *fila0, int ielem, int isec, int secu, double tt, double *t0,BOOL is_fin) +{ + int h,m,seg,i,iplan; + Info_planif *pp; + double cost_despl,ltot,kgac; + int iamb, iamb2; + + iamb=olv_limp->iaso[ielem].iamb; + if(iamb<0) + iamb=olv_limp->iaso[ielem].refe2; + + if(iamb<0 || !olv_reco->ptos_vaci[iamb]) + return TRUE;//no es punto en el que se va a vaciar + + if(!is_fin && (olv_reco->ptos_vaci[iamb]!=(short)OLV_IDA_PLANT)) + return TRUE;//no es punto en el que se va a vaciar + + //busca la ruta de este punto en el que se va a vaciar + if(!olv_limp->plan[isec].planif_insta || !olv_limp->plan[isec].ninsta) + return FALSE; + + for(i=0;iplan[isec].ninsta;i++) + { + if(olv_limp->plan[isec].planif_insta[i].elem[0].refe==ielem) + break; + } + if(i>=olv_limp->plan[isec].ninsta) + return FALSE; + + iplan=i; + + //ha encontrado la planificación, coge el tiempo de desplazamiento + pp = &olv_limp->plan[isec].planif_insta[i]; + if(!pp->nelem) + return FALSE; + cost_despl = pp->elem[pp->nelem-1].coste; + ltot=pp->m[OLV_DESP]; + + ////////////////// + //pone el tiempo acumulado, aprovecha y lo guarda aquí + pp->t[OLV_TTO]=tt; + ////////////////// + + ////////////////// + //Calcula los kg acumulados + kgac=0; + for(i=0;iplan[isec].nelem;i++) + { + if(olv_limp->plan[isec].elem[i].tp!=OLV_PLAN_TIP_AMB) + continue; + iamb2=olv_limp->iaso[olv_limp->plan[isec].elem[i].refe].refe2; + kgac+=olv_limp->iaso[iamb2].inf_r.kg; + if(olv_limp->plan[isec].elem[i].refe==ielem) + break; + } + if(i>=olv_limp->plan[isec].nelem) + return FALSE; + + //le resta los kg acumulados en el viaje anterior + i=iplan; + while((i-2)>0)//dos antes está la anterior planif a vaciar, si la hubiera + { + kgac-=olv_limp->plan[isec].planif_insta[i-2].m[OLV_TTO];//aprovecha y lo guarda aquí + i-=2; + } + pp->m[OLV_TTO]=kgac; + ////////////////// + + *t0+=cost_despl+olv_reco->t_descarg; + tt+=cost_despl+olv_reco->t_descarg; + dame_h_m_s(tt, &h, &m, &seg); + sprintf_s(fila0,256,"%02d;%04d;%s;%.1f;%s;%.1f;%02d:%02d:%02d;\r\n",isec+1,secu,"",kgac,"Descarga",ltot,h,m,seg); + if(!cc->escribe(fila0)) + { + return FALSE; + } + + if(olv_reco->ptos_vaci[iamb]!=(short)OLV_IDA_PLANT) + return TRUE; + + //escribe la vuelta de la descarga + if((iplan+1)>=olv_limp->plan[isec].ninsta) + return TRUE; + pp = &olv_limp->plan[isec].planif_insta[iplan+1]; + if(!pp->nelem) + return FALSE; + cost_despl = pp->elem[pp->nelem-1].coste; + ltot=pp->m[OLV_DESP]; + + ////////////////// + //pone el tiempo acumulado + pp->t[OLV_TTO]=tt; + ////////////////// + + *t0+=cost_despl; + tt+=cost_despl; + dame_h_m_s(tt, &h, &m, &seg); + sprintf_s(fila0,256,"%02d;%04d;%s;%s;%s;%.1f;%02d:%02d:%02d;\r\n",isec+1,secu,"","","Vuelta de Descarga",ltot,h,m,seg); + if(!cc->escribe(fila0)) + { + return FALSE; + } + + //reinicia, para que no vuelva a entrar + olv_reco->ptos_vaci[iamb]=0; + + return TRUE; +} +//************************************************************************************* +/** + * Quita al tiempo total el del último desplazamiento y la última descarga, solo para reco + */ +void Colv_reco_thr::quita_t_ult_desc(int s, double *t) +{ + int tt=(int)*t; + if(olv_limp->plan[s].ninsta>2 && olv_limp->plan[s].planif_insta[olv_limp->plan[s].ninsta-2].nelem>0) //quita el tiempo de desplazamiento de la instalación a la planta + tt-=(int)olv_limp->plan[s].planif_insta[olv_limp->plan[s].ninsta-2].elem[olv_limp->plan[s].planif_insta[olv_limp->plan[s].ninsta-2].nelem-1].coste; + tt-=olv_reco->t_descarg; + *t=tt; +} +//************************************************************************************* +/** + * Añade una columna de observación al listado si es contenedores + */ +void Colv_reco_thr::dame_observ_cont(int iamb, char *observ) +{ + int i=olv_limp->iaso[iamb].iamb; + if(i<0) + i=olv_limp->iaso[iamb].refe2; + sprintf_s(observ,32,"%ld",olv_limp->iaso[i].inf_r.uds); +} +//************************************************************************************* +/** + * Añade las columnas de información a la ruta, tiempos, longitudes, y demás + */ +BOOL Colv_reco_thr::guarda_cols_ruta(char *path_shp) +{ + char *info; + char path_dbf[MAX_PATH]; + double tt; + int h,m,s,j; + int nsec, i, isec_novac; + ManagerDbfGdataTable dbfmgr; + + //cuenta el número de sectores no vacíos + nsec=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb!=0) + nsec++; + } + + ///////////////////////////////////// + + if(!Colv_limp_thr::guarda_cols_ruta(path_shp)) + return FALSE; + + //añade una columna a la ruta de tiempo de ruta + strcpy_s(path_dbf,MAX_PATH,path_shp); + //cambiaext(path_dbf,".shp",".dbf"); + strcpy((Cdir_manager::extension_archivo(path_dbf)),"dbf"); + + info = (char *)malloc(nsec*OLV_SHP_SZ_CAMP_CHAR); + if(!info) + { + return FALSE; + } + memset(info,0,nsec*OLV_SHP_SZ_CAMP_CHAR); + AddColsDbf dataDbf(info); + + //sustituye la info de hora final + isec_novac=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + { + continue; + } + tt=olv_limp->t_ini+ olv_limp->sec[i].cost_ac + olv_limp->t_desc; + + dame_h_m_s(tt, &h, &m, &s); + sprintf_s(&info[isec_novac*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%02d:%02d:%02d h",h,m,s); + isec_novac++; + } + if(!dbfmgr.AddCol(path_dbf,"H_FIN",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) + { + free(info); + return FALSE; + } + memset(info,0,nsec*OLV_SHP_SZ_CAMP_CHAR); + + //sustituye la columna de uds de tratamiento porque hay contenedores que son varias unidades + isec_novac=0; + for(i=0;isec[i].namb==0) + continue; + tt=0; + for(j=0;jsec[i].namb;j++) + tt+=olv_limp->iaso[olv_limp->sec[i].iamb[j]].inf_r.uds; + sprintf_s(&info[isec_novac*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%ld",(int)tt); + isec_novac++; + } + if(!dbfmgr.AddCol(path_dbf,"UDS_TRAT",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) + { + free(info); + return FALSE; + } + memset(info,0,nsec*OLV_SHP_SZ_CAMP_CHAR); + + //Kg recogidos + isec_novac=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + continue; + tt=olv_limp->sec[i].dis_med; + sprintf_s(&info[isec_novac*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%.1f",tt); + isec_novac++; + } + if(!dbfmgr.AddCol(path_dbf,"KG_TOT_REC",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) + { + free(info); + return FALSE; + } + memset(info,0,nsec*OLV_SHP_SZ_CAMP_CHAR); + + //número de descargas + isec_novac=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + continue; + tt=(olv_limp->plan[i].ninsta-1)/2; + sprintf_s(&info[isec_novac*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%ld",(int)tt); + isec_novac++; + } + if(!dbfmgr.AddCol(path_dbf,"N_DESCARG",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) + { + free(info); + return FALSE; + } + memset(info,0,nsec*OLV_SHP_SZ_CAMP_CHAR); + + //rellena la info de duración de los desplazamientos a descargar + isec_novac=0; + int p; + for(i=0;insec;i++) + { + tt=0; + if(olv_limp->sec[i].namb==0) + continue; + for(p=1;pplan[i].ninsta;p++) + { + if(olv_limp->plan[i].planif_insta[p].nelem==0) + continue; + tt+=olv_limp->plan[i].planif_insta[p].elem[olv_limp->plan[i].planif_insta[p].nelem-1].coste; + } + //tt=olv_limp->sec[i].cost_ac-olv_limp->plan[i].elem[olv_limp->plan[i].nelem-1].coste-olv_limp->sec[i].t_despl[0]-olv_limp->sec[i].t_despl[1]-olv_reco->t_sal; + dame_h_m_s(tt, &h, &m, &s); + sprintf_s(&info[isec_novac*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%02d:%02d:%02d h",h,m,s); + isec_novac++; + } + if(!dbfmgr.AddCol(path_dbf,"T_DESCARG",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) + { + free(info); + return FALSE; + } + memset(info,0,nsec*OLV_SHP_SZ_CAMP_CHAR); + + free(info); + return TRUE; +} +//************************************************************************************* +/** + * Añade las columnas de información a la ruta, tiempos, longitudes, y demás + */ +BOOL Colv_reco_thr::guarda_cols_insta(char *path_shp) +{ + char *info; + char path_dbf[MAX_PATH]; + double tt; + //int h; + int insta, ninsta_parc,ninsta,ninsta_novac; + ManagerDbfGdataTable dbfmgr; + + ///////////////////////////////////// + + if(!Colv_limp_thr::guarda_cols_insta(path_shp)) + return FALSE; + + //cuenta el número de instalaciones + ninsta=0; + for(int i=0;insec;i++) + { + for(insta=0;instaplan[i].ninsta;insta++) + { + if(olv_limp->plan[i].planif_insta[insta].nelem!=0) + ninsta++; + } + } + + //añade una columna a la ruta de tiempo de ruta + strcpy_s(path_dbf,MAX_PATH,path_shp); + //cambiaext(path_dbf,".shp",".dbf"); + strcpy((Cdir_manager::extension_archivo(path_dbf)),"dbf"); + + info = (char *)malloc(ninsta*OLV_SHP_SZ_CAMP_CHAR); + if(!info) + { + return FALSE; + } + memset(info,0,ninsta*OLV_SHP_SZ_CAMP_CHAR); + AddColsDbf dataDbf(info); + + //kg descargados + ninsta_parc=0; + for(int i=0;insec;i++) + { + ninsta_novac=0; + for(insta=0;instaplan[i].ninsta;insta++) + { + if(olv_limp->plan[i].planif_insta[insta].nelem==0) + continue; + + if(olv_limp->plan[i].planif_insta[insta].ninsta==OLV_IDA_PLANT) + tt=olv_limp->plan[i].planif_insta[insta].m[OLV_TTO]; + else + tt=0; + + sprintf_s(&info[(insta+ninsta_parc)*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%.1f",tt); + ninsta_novac++; + } + ninsta_parc+=ninsta_novac; + } + if(!dbfmgr.AddCol(path_dbf,"KG_DESCARG",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) + { + free(info); + return FALSE; + } + memset(info,0,ninsta*OLV_SHP_SZ_CAMP_CHAR); + + //num de trayecto a descargar + ninsta_parc=0; + tt=0; + int tt2=0; + for(int i=0;insec;i++) + { + ninsta_novac=0; + tt2=0; + for(insta=0;instaplan[i].ninsta;insta++) + { + if(olv_limp->plan[i].planif_insta[insta].nelem==0) + continue; + + if(olv_limp->plan[i].planif_insta[insta].ninsta==OLV_IDA_PLANT || + olv_limp->plan[i].planif_insta[insta].ninsta==OLV_VUELTA_INST) + { + tt2++; + tt=tt2; + } + else if(olv_limp->plan[i].planif_insta[insta].ninsta==OLV_VUELTA_PLANT) + tt=tt2; + else + tt=0; + + sprintf_s(&info[(insta+ninsta_parc)*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%ld",(int)tt); + ninsta_novac++; + } + ninsta_parc+=ninsta_novac; + } + if(!dbfmgr.AddCol(path_dbf,"VIAJE",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) + { + free(info); + return FALSE; + } + memset(info,0,ninsta*OLV_SHP_SZ_CAMP_CHAR); + + free(info); + return TRUE; +} +//************************************************************************************* +/** + * Comprueba si en este elemento se va a descargar y en ese caso no se cuenta el desplazamiento hasta el siguiente + */ +BOOL Colv_reco_thr::comprueba_descarg(int iamb) +{ + return (olv_reco->ptos_vaci[iamb]==(short)OLV_IDA_PLANT); +} +//************************************************************************************* +/** + * Añade las columnas de información a la ruta, tiempos, longitudes, y demás + */ +BOOL Colv_reco_thr::guarda_cols_ruta_tram(char *path_shp) +{ + char *info; + char path_dbf[MAX_PATH]; + double tt; + int i, it,ntram,nt,nt_parc; + ManagerDbfGdataTable dbfmgr; + + if(!Colv_limp_thr::guarda_cols_ruta_tram(path_shp)) + return FALSE; + + //añade + + //cuenta el número de sectores no vacíos + ntram=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + continue; + ntram+=(int)olv_limp->tramos[i].size(); + } + + //añade una columna a la ruta de tiempo de ruta + strcpy_s(path_dbf,MAX_PATH,path_shp); + //cambiaext(path_dbf,".shp",".dbf"); + strcpy((Cdir_manager::extension_archivo(path_dbf)),"dbf"); + + info = (char *)malloc(ntram*OLV_SHP_SZ_CAMP_CHAR); + if(!info) + { + return FALSE; + } + memset(info,0,ntram*OLV_SHP_SZ_CAMP_CHAR); + AddColsDbf dataDbf(info); + + //M_DESP + nt_parc=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + continue; + nt=(int)olv_limp->tramos[i].size(); + for(it=0;ittramos[i][it].long_tr; + sprintf_s(&info[(nt_parc+it)*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%.1f",tt); + } + nt_parc+=nt; + } + if(!dbfmgr.AddCol(path_dbf,"M_DESP",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) + { + free(info); + return FALSE; + } + memset(info,0,ntram*OLV_SHP_SZ_CAMP_CHAR); + + //N_AMB + nt_parc=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + continue; + nt=(int)olv_limp->tramos[i].size(); + for(it=0;ittramos[i][it].namb; + sprintf_s(&info[(nt_parc+it)*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%ld",(int)tt); + } + nt_parc+=nt; + } + if(!dbfmgr.AddCol(path_dbf,"N_AMB",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) + { + free(info); + return FALSE; + } + memset(info,0,ntram*OLV_SHP_SZ_CAMP_CHAR); + + //UDS_TTO + nt_parc=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + continue; + nt=(int)olv_limp->tramos[i].size(); + for(it=0;ittramos[i][it].ncont; + sprintf_s(&info[(nt_parc+it)*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%ld",(int)tt); + } + nt_parc+=nt; + } + if(!dbfmgr.AddCol(path_dbf,"UDS_TTO",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) + { + free(info); + return FALSE; + } + memset(info,0,ntram*OLV_SHP_SZ_CAMP_CHAR); + + //KG_RECO + nt_parc=0; + for(i=0;insec;i++) + { + if(olv_limp->sec[i].namb==0) + continue; + nt=(int)olv_limp->tramos[i].size(); + for(it=0;itplan[i].planif_insta[2*it+1].m[OLV_TTO]; + sprintf_s(&info[(nt_parc+it)*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%.1f",tt); + } + nt_parc+=nt; + } + if(!dbfmgr.AddCol(path_dbf,"KG_RECO",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) + { + free(info); + return FALSE; + } + memset(info,0,ntram*OLV_SHP_SZ_CAMP_CHAR); + return TRUE; +} +//************************************************************************************* +/** + * Rellena la info de los tramos + */ +void Colv_reco_thr::rellena_tramos() +{ + Info_planif *pp; + Info_tramos *tramo; + int ie,it,nt; + + for(int is=0;isnsec;is++) + { + pp=&olv_limp->plan[is]; + nt=(int)olv_limp->tramos[is].size(); + for(it=0;ittramos[is][it]; + tramo->namb=0; + tramo->ncont=0; + for(ie=tramo->ie[0]; ie<=tramo->ie[1];ie++) + { + tramo->long_tr+=(float) pp->elem[ie].ltot; + if(pp->elem[ie].tp!=OLV_PLAN_TIP_AMB) + continue; + + tramo->namb++; + tramo->ncont+=olv_limp->iaso[olv_limp->iaso[pp->elem[ie].refe].refe2].inf_r.uds; + } + + tramo->t_tto_tr = (float)(tramo->ncont*olv_reco->t_tto); + if(it==0) + tramo->t_ini = (float)(olv_limp->t_ini+pp->planif_insta[0].elem[pp->planif_insta[0].nelem-1].coste); + else + tramo->t_ini = (float)(pp->planif_insta[2*it].t[OLV_TTO]+pp->planif_insta[2*it].elem[pp->planif_insta[2*it].nelem-1].coste); + + tramo->t_fin = (float)pp->planif_insta[2*it+1].t[OLV_TTO]; + + tramo->t_total_tr = (float) (tramo->t_fin-tramo->t_ini); + } + } +} +//************************************************************************************* +/** + * Como los viajes a instalaciones están ordenados, y los tramos también + * le corresponde a cada tramo it el viaje it y el it+1, excepto al último, que le pueden + * corresponder 3 viajes si la instalación y la descarga no son en el mismo sitio + * Además, actualiza el tiempo de los tramos + */ +int Colv_reco_thr::rellena_insta_tramos() +{ + int it, nt, nins,ii; + Info_planif *pinsta; + Info_tramos *tramo; + + ii=0; //para saber si hace algún tramo o no + for(int is=0;isnsec;is++) + { + nt=(int)olv_limp->tramos[is].size(); + nins = olv_limp->plan[is].ninsta; + if(!nins) + continue; + if(olv_limp->plan[is].planif_insta[nins-1].nelem==0) + nins--; //es porque la descarga y planta son la misma + pinsta = olv_limp->plan[is].planif_insta; + for(it=0;ittramos[is][it]; + tramo->iins[0]=2*it; + tramo->iins[1]=2*it+1; + + /////////////////////////////////////// + //Actualiza los tiempos del tramo sumando los tiempos del viaje a inst + tramo->t_ini -= (float)pinsta[tramo->iins[0]].elem[pinsta[tramo->iins[0]].nelem-1].coste; + tramo->t_fin += (float)pinsta[tramo->iins[1]].elem[pinsta[tramo->iins[1]].nelem-1].coste; + tramo->t_total_tr=(float) (tramo->t_fin-tramo->t_ini); + } + //para el último tramo + tramo = &olv_limp->tramos[is][it]; + tramo->iins[0]=2*it; + tramo->iins[1]=nins-1; + tramo->t_ini -= (float)pinsta[tramo->iins[0]].elem[pinsta[tramo->iins[0]].nelem-1].coste; + //si la instalación no es la misma que la descarga, le suma el tiempo de ir a descargar y el de ir a la instalación + BOOL notdesc=TRUE; + for(int i=tramo->iins[0]+1;i<=tramo->iins[1];i++) + { + if(notdesc) + { + tramo->t_fin += olv_reco->t_descarg; + notdesc=FALSE; + } + tramo->t_fin += (float)pinsta[i].elem[pinsta[i].nelem-1].coste; + } + tramo->t_total_tr=(float) (tramo->t_fin-tramo->t_ini); + ii++; + } + return ii; +} +//************************************************************************************* +#endif \ No newline at end of file diff --git a/Olivia/olv_reco_thr.h b/Olivia/olv_reco_thr.h new file mode 100644 index 0000000..0f86eaf --- /dev/null +++ b/Olivia/olv_reco_thr.h @@ -0,0 +1,76 @@ +#pragma once +#ifdef OLIVIA_COMPILA +#include "olv_limp_def.h" +#include "olv_limp_thr.h" +//#include "vector.h" + +/** +* @file olv_reco_thr.h +* Archivo de definiciones del thread de control de la utilidad de recogida de residuos del programa Olivia. +*/ +class Colv_reco; +struct Info_conjs; + +///////////////////////// +/** +* Clase del thread de control de la utilidad de recogida de residuos del programa Olivia. +*/ +class Colv_reco_thr : public Colv_limp_thr +{ +public: + //************************************************************************************* + enum Ev_olv_reco_thr + { + OLV_RECO_EV_SENS = Colv_limp_thr::OLV_LIMP_EV_N, + OLV_RECO_EV_SENS_SUB, + OLV_RECO_EV_SENS_FIN, + OLV_RECO_EV_N + }Ev_olv_reco_thr; + + //************************************************************************************* + //Variables + Colv_reco *olv_reco; + + //************************************************************************************* + //Constructor + Colv_reco_thr(Colv_reco *olv_reco); + ~Colv_reco_thr(void); + + //************************************************************************************* + //Funciones + void inicia_th(); + static void cola_proc(int evento,OlvAsync_cola *clase,Param_olv_limp_thr *e); + void lanza_subthrs(int tar, int nthr_def=-1); + + ///////////////////// + BOOL rellena_datos(); + BOOL pide_info_sens(); + void pide_info_sens_sub(int ithr); + BOOL pide_info_sens_fin(int nno); + + //calcular el nodo de la planta + BOOL pon_nodos_planta(double pt[3]); + BOOL busca_conjs_planta(double pt[3], int *nod); + BOOL calcula_cost_plant(); + + //costes para planificación + double dame_cost_jornada(); + double dame_coste( Secu_amb * sec, int ini, int fin, Info_sec *s, BOOL ind_abs); + void planifica_sub_1(int ithr, Matrix2d &cost_amb); + double dame_coste_pon_viajes( Secu_amb * sec, int ini, int fin, Info_sec *s, int *nvac); + + //Funciones para informes de planificación + BOOL genera_planif_vaci(int is, int ini, int fin, int *secu, int tip_viaje); + BOOL genera_list_fila_vaci(Colv_csv *cc, char *fila0, int ielem, int isec, int secu, double tt, double *t0,BOOL is_fin); + void quita_t_ult_desc(int s, double *t); + BOOL guarda_cols_ruta(char *path_shp); + void pon_t_desp(Info_sec *s, Secu_amb *sec); + BOOL comprueba_descarg(int iamb); + void dame_observ_cont(int iamb, char *observ); + BOOL guarda_cols_insta(char *path_shp); + void pon_ptos_ctrl(Info_planif *pp, int npt_ctrl, double cost_ctrl); + void rellena_tramos(); + BOOL guarda_cols_ruta_tram(char *path_shp); + int rellena_insta_tramos(); +}; +#endif \ No newline at end of file diff --git a/Olivia/olv_sens_ws.cpp b/Olivia/olv_sens_ws.cpp new file mode 100644 index 0000000..c58a766 --- /dev/null +++ b/Olivia/olv_sens_ws.cpp @@ -0,0 +1,243 @@ +#include "stdafx.h" +#ifdef OLIVIA_COMPILA +#include "olv_sens_ws.h" +#ifndef OLIVIA_NSENS + +#include +#include +#include +#endif +/** +* @file olv_sens_ws.cpp +* Archivo de implementaciones de la utilidad para conexión al Web Service para lectura de los sensores de la herramienta Olivia. +*/ +/** +* Clase para conexión al Web Service para lectura de los sensores de la herramienta Olivia. +*/ +Colv_sens_ws::Colv_sens_ws(void) +{ + info=NULL; + cuerpo[0]=0; +} + +Colv_sens_ws::~Colv_sens_ws(void) +{ +} +//************************************************************************************* +void Colv_sens_ws::inicia(Info_sens *info_) +{ + info=info_; + + strcpy_s(url,OLV_MAX_URL,info->url ); + + sprintf_s(cuerpo,OLV_MAX_CUERPO,"?%s=%s&id=%s&%s=%s&%s=%s&%s=%s&%s=%s", + info->camps.fn,info->fn_cont_status, + "%s",//deja abierto para meter el id del sensor que toque + info->camps.startdate,info->fecha_ini, + info->camps.enddate,info->fecha_fin, + info->camps.usr,info->usr, + info->camps.pwd,info->pwd); + +} +//************************************************************************************* +/* +Pide el porcentaje de llenado en tanto por cien del contenedor id +*/ +double Colv_sens_ws::dame_porc_cont_i(char *id) +{ + int ndata; + int ini; + int *data_vol; + double perc; + + //manda pregunta + if(!get_status_cont_i(id)) + return FALSE; + + //recibe respuesta + ndata=0; + data_vol=NULL; + if(!answer_json(id,&ndata,&data_vol)) + return FALSE; + + perc=0; + if(ndata>0) + { + if(info->modo_pet==OLV_SENS_PET_UNICO) + ini=ndata-1;//solo se queda con el valor único último + else if(info->modo_pet==OLV_SENS_PET_MEDIA) + ini=0; + for (int i=ini;icURL_JSON_data.push_back(buf[c]); + } + return siz*nmemb; +#endif + return 0; +} +//************************************************************************************* +BOOL Colv_sens_ws::answer_json(char *id_, int *ndata_, int **data_vol_) +{ + #ifndef OLIVIA_NSENS + int ndata,i; + int *data_vol; + std::string id; + std::string err_code; + Json::Reader jsonReader; + Json::Value jsonData; + Json::Value histoData; + + ndata=0; + data_vol=0; + + if (jsonReader.parse(cURL_JSON_data, jsonData)) + { + //comprueba que sea el id elegido + id = jsonData[info->camps_json.id].asString(); + if(id.length()==0) + { + //mira a ver si ha habido error + err_code=jsonData[info->camps_json.resp_code].asString(); + if(err_code.length()>0 && err_code.compare(info->camps_json.resp_code_err)) + { + sprintf_s(err_str, "Error en la petición %s\n",jsonData[info->camps_json.resp_data].asString()); + jsonData.clear(); + return FALSE; + } + } + if(strcmp(id.data(),id_)) + { + sprintf_s(err_str, "Error, no se ha recibido el id del contenedor solicitado %s %s\n",id,id_); + jsonData.clear(); + return FALSE; + } + //coge la info histórica de carga + histoData = jsonData[info->camps_json.histo]; + ndata = (int) histoData.size(); + //crea el array para almacenar los valores de carga + data_vol=(int*)malloc(ndata*sizeof(int)); + if(!data_vol) + { + sprintf_s(err_str, "Error, sin memoria al leer info JSON\n"); + jsonData.clear(); + return FALSE; + } + i=0; + for (Json::ValueConstIterator it = histoData.begin(); it != histoData.end(); ++it) + { + const Json::Value data = *it; + data_vol[i]=data[info->camps_json.porc].asInt(); + i++; + } + if(i!=ndata) + return FALSE; + } + else + { + sprintf_s(err_str, "Error al leer info JSON: %s\n", + jsonReader.getFormattedErrorMessages()); + return FALSE; + } + + + jsonData.clear(); + + *data_vol_=data_vol; + *ndata_=ndata; +#endif + return TRUE; +} +#endif + diff --git a/Olivia/olv_sens_ws.h b/Olivia/olv_sens_ws.h new file mode 100644 index 0000000..80bb19b --- /dev/null +++ b/Olivia/olv_sens_ws.h @@ -0,0 +1,87 @@ +#pragma once +#ifndef OLIVIA_NSENS +#endif +#ifdef OLIVIA_COMPILA +#include "olv.h" +#include +/** +* @file olv_sens_ws.h +* Archivo de definiciones y variables de la utilidad para conexión al Web Service para lectura de los sensores de la herramienta Olivia. +*/ + +#define OLV_MAX_CAMP_HTTP 16 +#define OLV_MAX_CAMP_HTTP_LONG 32 +#define OLV_MAX_URL 256 +#define OLV_MAX_CUERPO 1024 + +enum ModosPet +{ + OLV_SENS_PET_UNICO, + OLV_SENS_PET_MEDIA, +}; +/** + * Estructura para campos de los parámetros del método HTTP POST + */ +typedef struct Camps_post +{ + char fn[OLV_MAX_CAMP_HTTP]; + char id[OLV_MAX_CAMP_HTTP]; + char usr[OLV_MAX_CAMP_HTTP]; + char pwd[OLV_MAX_CAMP_HTTP]; + char startdate[OLV_MAX_CAMP_HTTP]; + char enddate[OLV_MAX_CAMP_HTTP]; +}Camps_post; + +/** + * Estructura para campos de los parámetros de la respuesta del servicio en formato JSON + */ +typedef struct Camps_json +{ + char id[OLV_MAX_CAMP_HTTP_LONG]; + char histo[OLV_MAX_CAMP_HTTP_LONG]; + char porc[OLV_MAX_CAMP_HTTP_LONG]; + char resp_code[OLV_MAX_CAMP_HTTP_LONG]; + char resp_code_err[OLV_MAX_CAMP_HTTP_LONG]; + char resp_data[OLV_MAX_CAMP_HTTP_LONG]; +}Camps_json; + +/** + * Estructura para conexión al web service de los sensores + */ +typedef struct Info_sens +{ + char url[OLV_MAX_URL]; + char fn_cont_status[OLV_MAX_URL]; + char usr[OLV_MAX_CAMP_HTTP]; + char pwd[OLV_MAX_CAMP_HTTP]; + char fecha_ini[OLV_MAX_CAMP_HTTP_LONG]; + char fecha_fin[OLV_MAX_CAMP_HTTP_LONG]; + int modo_pet; + double porc_lim;//en % + Camps_post camps; + Camps_json camps_json; +}Info_sens; + +class Colv_sens_ws +{ +public: + //************************************************************************************* + //Variables + Info_sens *info; + char cuerpo[OLV_MAX_CUERPO]; + char err_str[OLV_MAX_ERR]; + char url[OLV_MAX_URL]; + std::string cURL_JSON_data; + //************************************************************************************* + //Funciones + Colv_sens_ws(void); + ~Colv_sens_ws(void); + void inicia(Info_sens *info_); + double dame_porc_cont_i(char *id); + BOOL get_status_cont_i(char *id); + BOOL post_curl(char *body); + static size_t writeJSONURLCallback(char* buf, size_t size, size_t nmemb, void* up); + BOOL answer_json(char *id_, int *ndata_, int **data_vol_); + +}; +#endif diff --git a/Olivia/olv_sock.cpp b/Olivia/olv_sock.cpp new file mode 100644 index 0000000..021ee77 --- /dev/null +++ b/Olivia/olv_sock.cpp @@ -0,0 +1,88 @@ +#include "stdafx.h" +#ifdef OLIVIA_COMPILA +#include "olv.h" +#include "olv_sock.h" + +Colv_sock::Colv_sock(COlivia *olv) +{ + this->olv = olv; + sprintf_s(ip,32,"0.0.0.0"); + puerto=19933; +} + +Colv_sock::~Colv_sock(void) +{ +} +//************************************************************************************* +BOOL Colv_sock::on_datos_recibidos( char *txt ) +{ + int pr; + char *ch = NULL; + const int SZMSG = OLV_MAX_TAREA+OLV_MAX_MSG_PROCE+10; + char msgtar[SZMSG]; + char *secto=NULL; + BOOL ret=TRUE; + + if((strstr(txt,OliviaDef::GeneralDef::SockConf)) || (strstr(txt,OliviaDef::GeneralDef::SockConfPlan)) || + (strstr(txt,OliviaDef::GeneralDef::SockConfTodo)) && !olv->ya_config) + { + if(olv->pon_config(txt)) + { + ch = strdup(OliviaDef::GeneralDef::SockConfOk); + } + else + { + ch = strdup(OliviaDef::GeneralDef::SockConfNOk); + } + if(!envia(ch)) + { + ret= FALSE; + } + } + else if(strcmp(txt,OliviaDef::GeneralDef::SockProgr)==0) + { + pr=olv->dame_progre(); + if(!envia("%ld", pr)) + { + ret= FALSE; + } + } + else if(strcmp(txt,OliviaDef::GeneralDef::SockTarea)==0) + { + pr=olv->dame_tarea(); + strcpy_s(msgtar, SZMSG,olv->tareas_str[pr]); + if(strlen(olv->msg_proce)>0) + strcat_s(msgtar,olv->msg_proce); + /////////////////// + if(!envia("%s", msgtar )) + { + ret= FALSE; + } + } + else if(strcmp(txt,OliviaDef::GeneralDef::SockCanc)==0) + { + //Cancela... + ch = strdup(OliviaDef::GeneralDef::SockCancOk); + if(!envia(ch)) + ret= FALSE; + olv->cancela(); + } + + txt[0]=0; + + if(ch) + free(ch); + if(secto) + free(secto); + + return ret; +} +//************************************************************************************* +Cstr_socket_srv* Colv_sock::crea_cliente() +{ + Colv_sock *s; + s= new Colv_sock(olv); + return s; +} +//************************************************************************************* +#endif \ No newline at end of file diff --git a/Olivia/olv_sock.h b/Olivia/olv_sock.h new file mode 100644 index 0000000..6d7c580 --- /dev/null +++ b/Olivia/olv_sock.h @@ -0,0 +1,30 @@ +#pragma once +#ifdef OLIVIA_COMPILA +#include "str_socket.h" + +/** +* @file olv_sock.h +* Archivo de definiciones del socket de comunicaciones del programa Olivia. +*/ +class COlivia; +/** +* Clase extendida de socket para conexión con Olivia AddIn +*/ +class Colv_sock : public Cstr_socket_srv +{ +public: + //************************************************************************************* + //Variables + char ip[32]; /// +#include +#include "olv_tasks_def.h" +#include "olv.h" +#include "sock_task.h" +#include "StrArray.h" +#include "dir_manager.h" +Colv_tasks::Colv_tasks(COlivia *ool) +{ + olv = ool; + path_ang[0]=path_cconj[0]=file_iaso[0]=path_temp[0]=0; +} + +Colv_tasks::~Colv_tasks(void) +{ +} +//************************************************************************************* +/* + * Arranca una aplicación + */ +BOOL Colv_tasks::lanza_app(char *appName, char *comline) +{ + // additional information + STARTUPINFO si; + PROCESS_INFORMATION pi; + BOOL is_alive=FALSE; + + // set the size of the structures + ZeroMemory( &si, sizeof(si) ); + si.cb = sizeof(si); + ZeroMemory( &pi, sizeof(pi) ); + + // start the program up + CreateProcess( appName, // the path + comline, // Command line + NULL, // Process handle not inheritable + NULL, // Thread handle not inheritable + FALSE, // Set handle inheritance to FALSE + 0, // No creation flags + NULL, // Use parent's environment block + NULL, // Use parent's starting directory + &si, // Pointer to STARTUPINFO structure + &pi // Pointer to PROCESS_INFORMATION structure (removed extra parentheses) + ); + + //check is alive + DWORD lpExitCode; + GetExitCodeProcess(pi.hProcess,&lpExitCode); + is_alive=(lpExitCode==STILL_ACTIVE); + + // Close process and thread handles. + CloseHandle( pi.hProcess ); + CloseHandle( pi.hThread ); + + return is_alive; +} +//************************************************************************************* +/* + * Consigue el dir de una dll + */ +void Colv_tasks::get_dll_dir(char *dlldir) +{ + char path[MAX_PATH]; + HMODULE hm = NULL; + + path[0]=0; + + hm=GetModuleHandle(OLV_DLL_NAME); + + if (GetModuleFileName(hm, path, sizeof(path)) == 0) + { + int ret = GetLastError(); + fprintf(stderr, "GetModuleFileName failed, error = %d\n", ret); + } + + strcpy_s(dlldir,MAX_PATH,path); +} +//************************************************************************************* +/* + * Inicializa la ruta de los dirs + */ +void Colv_tasks::inidirs( char *path_temp ) +{ + char st1[MAX_PATH]; + strcpy_s(st1,MAX_PATH,path_temp); + if(path_temp[strlen(path_temp)-1]=='\\') + { + st1[strlen(st1)-1]=0; + } + sprintf_s(path_cconj,MAX_PATH,"%s\\%s\\",st1,TASKS_NOMB_COSTCONJ); + sprintf_s(path_costamb,MAX_PATH,"%s\\%s\\",st1,TASKS_NOMB_COSTAMB); + sprintf_s(path_ang,MAX_PATH,"%s\\%s\\",st1,TASKS_NOMB_COSTANG); + sprintf_s(file_iaso,MAX_PATH,"%s\\%s.%s",st1,TASKS_NOMB_IASO,TASKS_EXT_MAT); + strcpy_s(this->path_temp,MAX_PATH,st1); + + Cdir_manager dm; + dm.crea_dir(st1); + dm.crea_dir(path_cconj); + dm.crea_dir(path_costamb); + dm.crea_dir(path_ang); +} +//************************************************************************************* +float minFloat(float a, float b) +{ + return min(a,b); +} +//************************************************************************************* +BOOL Colv_tasks::lee_cost_amb(Matrix2d &cost_amb) +{ + class floatMinCom: public ComClasFunction + { + public: + floatMinCom(){} + virtual float comp(float a, float b) + { + return min(a, b); + } + }; + floatMinCom ccom; + StrArray files; + //pilla archivos----------------------- + if(!Cdir_manager::listar(path_costamb, &files)) + return FALSE; + char *f; + for (int i = 0; ipirate_soc = pirate; + soc->olv = olv; + + return soc; +} +//#endif \ No newline at end of file diff --git a/Olivia/olv_tasks.h b/Olivia/olv_tasks.h new file mode 100644 index 0000000..b19fc03 --- /dev/null +++ b/Olivia/olv_tasks.h @@ -0,0 +1,33 @@ +#pragma once + +class COlivia; +class CoptiMemo; +#include "sock_sv.h" +/** + * Clase para ejecución de Olivia en modo multitask EN DESUSO EN VERSIÓN 2.0 + */ +class Colv_tasks : public Cescucha_sock_sv + +{ +public: + //////////////////////////////////// + //variables + COlivia *olv; + char path_temp[MAX_PATH]; + char path_cconj[MAX_PATH]; + char path_costamb[MAX_PATH]; + char path_ang[MAX_PATH]; + char file_iaso[MAX_PATH]; + //////////////////////////////////// + //métodos + Colv_tasks(COlivia *ool); + ~Colv_tasks(void); + + virtual Cproceso_cliente* crea_cliente(BOOL *pirate); + + void inidirs(char *path_temp); + BOOL lanza_app(char *appName, char *comline); + void get_dll_dir(char *dlldir); + BOOL lee_cost_amb(Matrix2d &cost_amb); + BOOL guarda_cost_amb(); +}; diff --git a/Olivia/olv_tasks_def.h b/Olivia/olv_tasks_def.h new file mode 100644 index 0000000..b2de728 --- /dev/null +++ b/Olivia/olv_tasks_def.h @@ -0,0 +1,200 @@ +#pragma once +#include +#include "windows.h" + +#define OLV_TASKS_MAXCONJROW 100 +#define OLV_TASKS_PORCMEM32 0.9 +#define OLV_TASKS_PORCMEM64 0.9 +#define OLV_TASKS_PORCCOLADJ 0.25 +#define OLV_TASKS_MAXMEMNOMULTI 600*1024*1024 +#define OLV_TASKS_MAXMEM32 1200*1024*1024 +#define OLV_TASKS_MARGENMEM 20*1024*1024 +#define TASKS_APP_NAME "OliviaTasks.exe" +#define TASKS_FOLDER_NAME "OliviaTasks" +#define OLV_DLL_NAME "Olivia.dll" +#define TASKS_PORT 19996 +#define TASKS_NOMB_COSTCONJ "costconj" +#define TASKS_NOMB_COSTAMB "costamb" +#define TASKS_NOMB_COSTANG "costang" +#define TASKS_NOMB_IASO "iaso" +#define TASKS_EXT_MAT "otk" +#define TASKS_EXT_DIS "dis" +#define TASKS_PARAM_SEP " " + +typedef enum TareasMultitask +{ + CALC_COST_AMB=1, +}TareasMultitask; + +typedef struct HeadInfoAso +{ + int nint; //número de enteros guardados (3xnamb) +}HeadInfoAso; + +typedef struct InfoIniTask +{ + char path_temp[MAX_PATH]; + char path_cconj[MAX_PATH]; + char path_ang[MAX_PATH]; + char path_costamb[MAX_PATH]; + char file_iaso[MAX_PATH]; + char ext[8]; + bool usa_angs; + int KK; + int namb;//numero de ambitos + int nthr;//numero de threads + int ntsks;//numero de tasks + int n;//numero de nodos + int id_instal; + int id_planta; +}InfoIniTask; + +class CoptiMemo +{ + +public: + //********************************* + //Variables + int div; //es 8 si es multitask, porque la mat de visto_ang ocupa n*n/8, si no es 1, porque ocupa n*n + INT64 memo; + double porc; + //********************************* + //Métodos + CoptiMemo(BOOL mm=FALSE) + { + if(mm) + { + div=8; + memo = dame_AvailPhysMem64(); + porc = OLV_TASKS_PORCMEM64; + } + else + { + div=1; + memo= dame_AvailPhysMem64(); + porc = OLV_TASKS_PORCMEM32; + } + } + ~CoptiMemo(void) + { + } + //************************************************************************************* + /* + * Pide la memoria disponible del sistema + */ + inline INT64 CoptiMemo::dame_AvailPhysMem64() + { + MEMORYSTATUSEX status; + status.dwLength = sizeof(status); + GlobalMemoryStatusEx(&status); + return (INT64)status.ullAvailPhys; + } + //************************************************************************************* + /* + * Pide la memoria disponible en 32, que es 1,2 GB aprox menos la usada por el proceso + */ + inline INT64 CoptiMemo::dame_AvailPhysMem32() + { + return (INT64)OLV_TASKS_MAXMEM32-dame_UsedPhysMem(); + } + //************************************************************************************* + /* + * Pide la memoria usada por el proceso + */ + inline INT64 CoptiMemo::dame_UsedPhysMem() + { + PROCESS_MEMORY_COUNTERS_EX pmc; + GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*)&pmc, (DWORD)sizeof(pmc)); + //SIZE_T virtualMemUsedByMe = pmc.PrivateUsage; + + return (INT64) pmc.WorkingSetSize; + } + //************************************************************************************* + /* + * Calcula el número de filas de mapmatrix que pueden ser vector en el master + */ + inline int CoptiMemo::calc_nvect_master(int nconj) + { + //lo calcula en base a lo que van a ocupar aprox las matrices + /*mem_cost=(nvectxnconj+(nconj-nvect)*OLV_TASKS_MAXCONJROW)*sizeof(float) + mem_tip=(nvectxnconj+(nconj-nvect)*OLV_TASKS_MAXCONJROW)*sizeof(int) + mem_ang=nconj*OLV_TASKS_MAXCONJROW*sizeof(BYTE) + mem_cost_amb, se va a calcular, cuando llegue el momento, si no cabe y se hace multitask + margen=OLV_TASKS_MARGENMEM + mem_cost+mem_tip+mem_ang+margen<=mem_memo*porc*/ + INT64 a,b,c,d; + INT64 nvect; + int sf, si; + sf=sizeof(float); + si=sizeof(int); + + if(memo<0) + return -1; + + a=(INT64)((double)memo*porc); + b=(INT64)nconj*OLV_TASKS_MAXCONJROW*(1+sf+si); + c=(INT64)OLV_TASKS_MARGENMEM; + d=(INT64)(sf+si)*(nconj-OLV_TASKS_MAXCONJROW); + nvect = (a-b-c)/d; + + nvect=min(nconj,nvect); + nvect=max(nvect,0); + + return (int)nvect; + } + //************************************************************************************* + /* + * Calcula el número de filas de mapmatrix que pueden ser vector en multitask + * se tiene que tener en cuenta que luego se va a pedir para nthr el cálculo de cost_amb + */ + inline int CoptiMemo::calc_nvect_multi(int nconj, int nthr, int nbcola) + { + //lo calcula en base a lo que van a ocupar aprox las matrices + /*mem_cost=(nvectxnconj+(nconj-nvect)*OLV_TASKS_MAXCONJROW)*sizeof(float) + mem_tip=(nvectxnconj+(nconj-nvect)*OLV_TASKS_MAXCONJROW)*sizeof(int) + mem_ang=nconj*OLV_TASKS_MAXCONJROW*sizeof(BYTE) + mem_cost_amb=nthr*(nconj*nconj*sizeof(byte)*1/8+nconj*OLV_TASKS_PORCCOLADJ*sizeof(cola)) + margen=OLV_TASKS_MARGENMEM + mem_cost+mem_tip+mem_ang+margen<=mem_disp*porc*/ + INT64 a,b,c,d, e; + INT64 nvect; + int sf, si; + sf=sizeof(float); + si=sizeof(int); + + if(memo<0) + return -1; + + a=(INT64)((double)memo*porc); + b=((INT64)nconj)*OLV_TASKS_MAXCONJROW*(1+sf+si); + c=(INT64)OLV_TASKS_MARGENMEM; + e=(INT64)((INT64)nthr)*((INT64)nconj)*((INT64)(nconj*1.0/div+OLV_TASKS_PORCCOLADJ*nbcola)); + d=(INT64)(sf+si)*(nconj-OLV_TASKS_MAXCONJROW); + nvect = (a-b-c-e)/d; + + nvect=min(nconj,nvect); + nvect=max(nvect,0); + + return (int)nvect; + } + //************************************************************************************* + /* + * Calcula si se va a poder hacer en monotask o no + * para ello, deben caber en memoria al menos los 8 thr de cálculo de dj + */ + inline int is_multi(int nconj, int nthr, int nbcola) + { + //mem_cost_amb=nthr*(nconj*nconj*sizeof(byte)+nconj*OLV_TASKS_PORCCOLADJ*sizeof(cola)) + //mem_cost_amb+margen<=mem_disp*porc + INT64 a,b,c; + + if(memo<0) + return FALSE; + + a=(INT64)((double)memo*porc); + b=(INT64)OLV_TASKS_MARGENMEM; + c=(INT64)((INT64)nthr)*((INT64)nconj)*((INT64)(nconj+OLV_TASKS_PORCCOLADJ*nbcola)); + + return (a-b-c<0); + } +}; \ No newline at end of file diff --git a/Olivia/olv_thr.cpp b/Olivia/olv_thr.cpp new file mode 100644 index 0000000..806cb6b --- /dev/null +++ b/Olivia/olv_thr.cpp @@ -0,0 +1,67 @@ +#include "stdafx.h" +#ifdef OLIVIA_COMPILA +//olivia +#include "olv_thr.h" +#include "olv.h" +#include "lock.h" + +Colv_thr::Colv_thr(COlivia *olv) +{ + this->olv=olv; + progreso=tarea=0; + msg_proce[0]=0; +} + +Colv_thr::~Colv_thr(void) +{ +} +//************************************************************************************* +/** + * Actualiza el progreso y la tarea por la que va + */ +void Colv_thr::pon_mi_progre(int tar, int prog) +{ + tarea=tar; + progreso=prog; + + pon_olv_progre(); +} +//************************************************************************************* +/** + * Actualiza el mensaje de tarea + */ +void Colv_thr::pon_mi_msg(char *fmt, ...) +{ + //formatea el string que llega + int k; + va_list arg_ptr; + + if(strlen(fmt)==0) + { + msg_proce[0]=0; + return; + } + va_start(arg_ptr, fmt); + k = _vsnprintf(msg_proce,OLV_MAX_MSG_PROCE, fmt, arg_ptr); + va_end(arg_ptr); + if(k<0) + msg_proce[0]=0; + + olvlog(LOG_TODO,"olv_limp_t",msg_proce); + + pon_olv_progre(); +} +//************************************************************************************* +/** + * Actualiza el progreso y la tarea por la que va al olivia general + */ +void Colv_thr::pon_olv_progre() +{ + olv->lock->entro(); + olv->progreso=progreso; + olv->tarea=tarea; + strcpy_s(olv->msg_proce,OLV_MAX_MSG_PROCE,msg_proce); + olv->lock->salgo(); +} +//************************************************************************************* +#endif \ No newline at end of file diff --git a/Olivia/olv_thr.h b/Olivia/olv_thr.h new file mode 100644 index 0000000..c8384f2 --- /dev/null +++ b/Olivia/olv_thr.h @@ -0,0 +1,32 @@ +#pragma once +#ifdef OLIVIA_COMPILA +#include "olv.h" +/** +* @file olv_thr.h +* Archivo de variables comunes a los threads de cálculo de Olivia. +*/ +class COlivia; +#define OLV_MILIS_COLA 200 //! Milisegundos de iteración de la cola +/** +* Clase de variables y funciones comunes a los threads de cálculo de Olivia. +*/ +class Colv_thr +{ +public: + //************************************************************************************* + //Variables + int progreso; + int tarea; + char msg_proce[OLV_MAX_MSG_PROCE]; + COlivia *olv; + //************************************************************************************* + //Funciones +public: + Colv_thr(COlivia *olv); + ~Colv_thr(void); + + void pon_mi_progre(int tar, int prog); + void pon_mi_msg(char *fmt, ...); + void pon_olv_progre(); +}; +#endif diff --git a/Olivia/res/Olivia.rc2 b/Olivia/res/Olivia.rc2 new file mode 100644 index 0000000..0fb55b2 --- /dev/null +++ b/Olivia/res/Olivia.rc2 @@ -0,0 +1,13 @@ +// +// Olivia.RC2 - resources Microsoft Visual C++ does not edit directly +// + +#ifdef APSTUDIO_INVOKED +#error this file is not editable by Microsoft Visual C++ +#endif //APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// Add manually edited resources here... + +///////////////////////////////////////////////////////////////////////////// diff --git a/Olivia/res/favicon.ico b/Olivia/res/favicon.ico new file mode 100644 index 0000000..df53e93 Binary files /dev/null and b/Olivia/res/favicon.ico differ diff --git a/Olivia/sock_task.cpp b/Olivia/sock_task.cpp new file mode 100644 index 0000000..99e682b --- /dev/null +++ b/Olivia/sock_task.cpp @@ -0,0 +1,149 @@ +#include "StdAfx.h" +//#ifdef OLV_UTILES32 +#include "sock_task.h" +#include "olv.h" +#include "olv_limp.h" +#include "olv_limp_thr.h" +#include "olv_reco.h" +#include "olv_reco_thr.h" +#include "sock_sv.h" +#include "utiles_def.h" +//#include "wvarios.h" + +Csock_task::Csock_task(COlivia *ol) +{ + olv=ol; +} + +Csock_task::~Csock_task(void) +{ +} +//************************************************************************************* +void Csock_task::run() +{ + int id, ithr; + BOOL sal=FALSE; + BOOL fin_ok=FALSE; + __int64 t1=_time64(NULL); + __int64 timeout; + timeout=20000;//20 seg + ithr=-1; + Param_olv_limp_thr pp; + pp.id_e=0; + BOOL *pirate=NULL; +#ifndef _DEBUG + __int64 t2; +#endif + + if(olv->olv_limp) + pirate=&olv->olv_limp->thr_limp->pirate; + else if(olv->olv_reco) + pirate=&olv->olv_reco->thr_limp->pirate; + if (pirate==NULL) + { + pirate=new BOOL(); + *pirate=FALSE; + } + do + { +#ifndef _DEBUG + t2 = _time64(NULL); + if((t2-t1)>=timeout) + { + sal=TRUE; + continue; + } +#endif + if(!soc->recibe_package(0)) + { + Sleep(1); + continue; + } + t1=_time64(NULL); + + if(soc->nbbuf) + { + case PETICION_GENERAL_OK: + { + id=PETICION_GENERAL_OK; + if(!soc->envia_package((BYTE*)&id,sizeof(int))) + { + sal=TRUE; + continue; + } + break; + } + case PETICION_GENERAL_PRESENTA: + { + if(soc->nb<2*sizeof(int)) + { + sal=TRUE; + continue; + } + //pilla ithr, contesta ok + ithr = ((int*)soc->buf)[1]; + id=PETICION_GENERAL_OK; + if(!soc->envia_package((BYTE*)&id,sizeof(int))) + { + sal=TRUE; + continue; + } + //envía la info de la task + if(!soc->envia_package((BYTE*)&olv->infotask,sizeof(InfoIniTask))) + { + sal=TRUE; + continue; + } + break; + } + case PETICION_GENERAL_FIN: + { + sal=TRUE; + if(soc->nb<2*sizeof(int)) + { + continue; + } + if(((int*)soc->buf)[1]==PETICION_GENERAL_OK) + fin_ok=TRUE; + id=PETICION_GENERAL_FIN; + if(!soc->envia_package((BYTE*)&id,sizeof(id))) + { + sal=TRUE; + continue; + } + //mira si ok o no + break; + } + case PETICION_GENERAL_DAME_LOG: + { + soc->buf[soc->nb-1] = 0; + olvlog(LOG_TODO,"LogSock",(char*)&((int*)soc->buf)[1]); + break; + } + } + } while (!*soc->pirate && !sal && !*pirate_soc && !soc->sock_cerrado && !*pirate); + + if(ithr>=0) + { + if(!fin_ok && (sal || soc->sock_cerrado)) + { + //avisar en encola de que ha ido mal + pp.id_e=-1; + } + } + else + pp.id_e=-2; + + if(olv->olv_limp) + olv->olv_limp->thr_limp->encola(olv->olv_limp->thr_limp->OLV_LIMP_EV_TASK_FIN,&pp,FALSE); + else if(olv->olv_reco) + olv->olv_reco->thr_reco->encola(olv->olv_reco->thr_limp->OLV_LIMP_EV_TASK_FIN,&pp,FALSE); + olvlog(LOG_TODO,"LogSock","Saliendo sock ithr %ld %s", ithr, fin_ok ? "Bien" : "Mal"); + +} +//#endif \ No newline at end of file diff --git a/Olivia/sock_task.h b/Olivia/sock_task.h new file mode 100644 index 0000000..44c98ed --- /dev/null +++ b/Olivia/sock_task.h @@ -0,0 +1,14 @@ +#pragma once +//#ifdef OLV_UTILES32 +#include "proceso_cliente.h" +class COlivia; +class Csock_task : public Cproceso_cliente +{ +public: + COlivia *olv; + BOOL *pirate_soc; + virtual void run(); + Csock_task(COlivia *ol); + ~Csock_task(void); +}; +//#endif diff --git a/Olivia/stdafx.cpp b/Olivia/stdafx.cpp new file mode 100644 index 0000000..318672e --- /dev/null +++ b/Olivia/stdafx.cpp @@ -0,0 +1,7 @@ +// stdafx.cpp : source file that includes just the standard includes +// Olivia.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + + diff --git a/Olivia/stdafx.h b/Olivia/stdafx.h new file mode 100644 index 0000000..1925f1c --- /dev/null +++ b/Olivia/stdafx.h @@ -0,0 +1,42 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently + +#pragma once + +#ifndef VC_EXTRALEAN +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers +#endif + +#include "targetver.h" + +#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit + +#include // MFC core and standard components +#include // MFC extensions + +#ifndef _AFX_NO_OLE_SUPPORT +#include // MFC OLE classes +#include // MFC OLE dialog classes +#include // MFC Automation classes +#endif // _AFX_NO_OLE_SUPPORT + +#ifndef _AFX_NO_DB_SUPPORT +#include // MFC ODBC database classes +#endif // _AFX_NO_DB_SUPPORT + +#ifndef _AFX_NO_DAO_SUPPORT +#include // MFC DAO database classes +#endif // _AFX_NO_DAO_SUPPORT + +#ifndef _AFX_NO_OLE_SUPPORT +#include // MFC support for Internet Explorer 4 Common Controls +#endif +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include // MFC support for Windows Common Controls +#endif // _AFX_NO_AFXCMN_SUPPORT + +#include // MFC socket extensions +#include "base_head.h" +#include "olv_dll.h" +#include "Matrix2d.h" \ No newline at end of file diff --git a/Olivia/targetver.h b/Olivia/targetver.h new file mode 100644 index 0000000..11730d5 --- /dev/null +++ b/Olivia/targetver.h @@ -0,0 +1,26 @@ + +#pragma once + +// The following macros define the minimum required platform. The minimum required platform +// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run +// your application. The macros work by enabling all features available on platform versions up to and +// including the version specified. + +// Modify the following defines if you have to target a platform prior to the ones specified below. +// Refer to MSDN for the latest info on corresponding values for different platforms. +#ifndef WINVER // Specifies that the minimum required platform is Windows Vista. +#define WINVER 0x0600 // Change this to the appropriate value to target other versions of Windows. +#endif + +#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows Vista. +#define _WIN32_WINNT 0x0600 // Change this to the appropriate value to target other versions of Windows. +#endif + +#ifndef _WIN32_WINDOWS // Specifies that the minimum required platform is Windows 98. +#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later. +#endif + +#ifndef _WIN32_IE // Specifies that the minimum required platform is Internet Explorer 7.0. +#define _WIN32_IE 0x0700 // Change this to the appropriate value to target other versions of IE. +#endif + diff --git a/OliviaTasks/.vs/OliviaTasks/v15/.suo b/OliviaTasks/.vs/OliviaTasks/v15/.suo new file mode 100644 index 0000000..11f2e18 Binary files /dev/null and b/OliviaTasks/.vs/OliviaTasks/v15/.suo differ diff --git a/OliviaTasks/.vs/OliviaTasks/v15/Solution.VC.db b/OliviaTasks/.vs/OliviaTasks/v15/Solution.VC.db new file mode 100644 index 0000000..4d0862a Binary files /dev/null and b/OliviaTasks/.vs/OliviaTasks/v15/Solution.VC.db differ diff --git a/OliviaTasks/OliviaTasks.cpp b/OliviaTasks/OliviaTasks.cpp new file mode 100644 index 0000000..fd1ccc5 --- /dev/null +++ b/OliviaTasks/OliviaTasks.cpp @@ -0,0 +1,173 @@ +// OliviaTasks.cpp : Defines the entry point for the console application. +// + +#include "stdafx.h" +#include "OliviaTasks.h" +#include "olv_task.h" +#include "OlvTaskProcess.h" +#include "utl.h" +#include "olv_dll.h" +#include "olv.h" +#include "_log.h" +#include "Msmain.h" +#ifdef _DEBUG +#define new DEBUG_NEW +#endif +#include "GeometryFunction.h" +#include "StrArray.h" +#include "ClienteLicencias.h" +#include "_app.h" + +// The one and only application object + +//! Clase principal de OliviaTasks +/*! + * Es la interface entre el AddIn de Olivia y el core de calculos Olivia.dll + * + */ + +CWinApp theApp; + +using namespace std; + +BOOL coge_param(char *cmdline, OlvTaskProcess *task); + +//! Funcion principal +/** + * Funcion principal que inicia la aplicacion al ser llamada por el AddIn + */ +int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) +{ + + int nRetCode = 0; + + if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0)) + { + _tprintf(_T("Fatal Error: MFC initialization failed\n")); + nRetCode = 1; + } + else + { + OlvApp.olv = new COlivia(); + Msmain mp; + OlvApp.olv->mfrm = ∓ + mp.olv = OlvApp.olv; + + //inicia log------------------------------------------------- + C_app* app = C_app::GetApp(); + app->archi.rellena_dirs_ejecucion(); +#ifdef _DEBUG + + HWND Stealth; + AllocConsole(); + + Stealth = FindWindowA("ConsoleWindowClass", NULL); + ShowWindow(Stealth,SW_SHOWNORMAL); + + #endif + //pilla path temporal + StrArray buf; + strcpy(app->log.nombre,"Olivia"); + int nn = Cutl::stringSplit(lpCmdLine,"/path_temp:", &buf)->n_i; + if(nn>=2 && Cutl::stringSplit(buf.get(1)," /", &buf)->n_i>nn) + strcpy(app->log.path,buf.get(nn)); + buf.borra(); + + //verifica versión----------------------------------- +#ifdef _DEBUG + system("pause"); +#endif; + ClienteLicencias lic; + char strtem[MAX_PATH]; + app->archi.rellena_dirs_ejecucion(); + strcpy_s(strtem,MAX_PATH,app->archi.path_ejecutable); + Cdir_manager::dir_anterior(strtem); + sprintf(lic.dirLic,"%s\\", strtem); + sprintf(lic.dirTemp,"%s\\", app->log.path); + if(!lic.cargaLicencia()) + { + C_log::log("_tmain", "Error al comprobar versión"); +#ifdef _DEBUG + system("pause"); +#endif; + } + +#ifdef _DEBUG + system("pause"); +#endif; + C_log::log("_tmain","Inicio OliviaTask: %s", lpCmdLine); + mp.Despacha_log(); + //verifica modo debug---------------------------------------- + if(strstr(lpCmdLine,"debug")) + { + OlvApp.olv->modo_ejec=OLV_EJEC_DEBUG_SIGUE; + } + + + char err[1024]; + if(!OlvApp.olv->inicia(lpCmdLine, err,1024)) + { + C_log::log("_tmain",err); + } + else + { + if(OlvApp.olv->isDebug) + { +#ifdef _DEBUG + system("pause"); +#endif; + OlvApp.olv->prueba(); + } + mp.Despacha(); + } + C_log::log("_tmain","Final feliz!!"); + mp.Despacha_log(); + OlvApp.olv->mfrm =NULL; + +#ifdef _DEBUG + system("pause"); +#endif + } + + return nRetCode; +} +//************************************************************************************* +/** + * Dada la línea de comandos, la divide en los parámetros necesarios + * (Funcion para modo multitask) + */ +BOOL coge_param(char *cmdline, OlvTaskProcess *task) +{ + char *token; + int j; + + //los parámetros son: + //\olivia \tipo_oliv \cfg.ini \ip \puerto \toutsock + token = strtok(cmdline, TASKS_PARAM_SEP); + + //Lee parámetros + j=0; + while (token != NULL) + { + if(j==0) + { + //ip + strcpy_s(OlvApp.ip,64,token); + } + else if(j==1) + { + //puerto + OlvApp.port=atoi(token); + } + else if(j==2) + { + //ithr + task->ithr = atoi(token); + } + token = strtok(NULL, TASKS_PARAM_SEP); + j++; + } + if(j<3) + return FALSE; //no ha leído los param suficientes + return TRUE; +} diff --git a/OliviaTasks/OliviaTasks.h b/OliviaTasks/OliviaTasks.h new file mode 100644 index 0000000..49ab1a0 --- /dev/null +++ b/OliviaTasks/OliviaTasks.h @@ -0,0 +1,3 @@ +#pragma once + +#include "resource.h" \ No newline at end of file diff --git a/OliviaTasks/OliviaTasks.rc b/OliviaTasks/OliviaTasks.rc new file mode 100644 index 0000000..b59c076 --- /dev/null +++ b/OliviaTasks/OliviaTasks.rc @@ -0,0 +1,134 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDS_APP_TITLE "OliviaTasks" +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Spanish resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ESN) +#ifdef _WIN32 +LANGUAGE LANG_SPANISH, SUBLANG_SPANISH_MODERN +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +MAINICON ICON "favicon.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 2,0,0,3 + PRODUCTVERSION 2,0,0,3 + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "0c0a04b0" + BEGIN + VALUE "CompanyName", "VSM" + VALUE "FileDescription", "Launcher de la aplicación Olivia" + VALUE "FileVersion", "2.0.0.3" + VALUE "InternalName", "OliviaTasks" + VALUE "LegalCopyright", "OLIVIA (c) VSM 2020. All rights reserved." + VALUE "OriginalFilename", "OliviaTasks.exe" + VALUE "ProductName", "OliviaTasks" + VALUE "ProductVersion", "2.0.0.3" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0xc0a, 1200 + END +END + +#endif // Spanish resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/OliviaTasks/OliviaTasks.vcxproj b/OliviaTasks/OliviaTasks.vcxproj new file mode 100644 index 0000000..712826f --- /dev/null +++ b/OliviaTasks/OliviaTasks.vcxproj @@ -0,0 +1,247 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {A8C66186-EDEF-4041-B7DD-B4FAFCC528EA} + OliviaTasks + Win32Proj + + + + Application + v141 + Dynamic + MultiByte + true + + + Application + v141 + Dynamic + MultiByte + + + Application + v141 + Dynamic + MultiByte + true + + + Application + v141 + Dynamic + MultiByte + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>15.0.28127.55 + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + true + MinimumRecommendedRules.ruleset + + + + + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + true + MinimumRecommendedRules.ruleset + + + + + $(SolutionDir)\$(Configuration)\ + $(Configuration)\ + false + MinimumRecommendedRules.ruleset + + + + + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + false + MinimumRecommendedRules.ruleset + + + + + + Disabled + ..\includes\Utiles;..\Olivia\;..\includes\olivia;..\includes\ClientLic;..\includes\FileTransfer;..\includes\LicUtiles + WIN32;_DEBUG;_CONSOLE;OLIVIA_COMPILA;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + Use + Level3 + EditAndContinue + + + utiles.lib;psapi.lib;Olivia.lib;ClientLic.lib;%(AdditionalDependencies) + ..\lib\$(IntDir) + true + Windows + MachineX86 + + + copy $(OutDir)$(TargetFileName) ..\bin\$(IntDir) +copy ..\Licencia\OliviaTasks.lic ..\bin\$(IntDir) + + + + + X64 + + + Disabled + ..\includes\Utiles;..\Olivia\;..\includes\olivia;..\includes\ClientLic;..\includes\FileTransfer;..\includes\LicUtiles + WIN32;_DEBUG;_CONSOLE;OLIVIA_COMPILA;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + Use + Level3 + EditAndContinue + + + utiles.lib;psapi.lib;Olivia.lib;ClientLic.lib;%(AdditionalDependencies) + ..\lib\$(IntDir) + true + Windows + + MachineX64 + + + copy $(OutDir)$(TargetFileName) ..\bin\$(IntDir) +copy ..\Licencia\OliviaTasks.lic ..\bin\$(IntDir) + + + + + MaxSpeed + true + ..\includes\Utiles;..\Olivia\;..\includes\olivia;..\includes\ClientLic;..\includes\FileTransfer;..\includes\LicUtiles + WIN32;NDEBUG;_CONSOLE;OLIVIA_COMPILA;%(PreprocessorDefinitions) + MultiThreadedDLL + true + Use + Level3 + ProgramDatabase + + + utiles.lib;psapi.lib;Olivia.lib;ClientLic.lib;%(AdditionalDependencies) + ..\lib\$(IntDir) + true + Windows + true + true + MachineX86 + + + copy $(OutDir)$(TargetFileName) ..\bin\$(IntDir) +copy ..\Licencia\OliviaTasks.lic ..\bin\$(IntDir) + + + + + X64 + + + MaxSpeed + true + ..\includes\Utiles;..\Olivia\;..\includes\olivia;..\includes\ClientLic;..\includes\FileTransfer;..\includes\LicUtiles + WIN32;NDEBUG;_CONSOLE;OLIVIA_COMPILA;%(PreprocessorDefinitions) + MultiThreadedDLL + true + Use + Level3 + ProgramDatabase + + + utiles.lib;psapi.lib;Olivia.lib;ClientLic.lib;%(AdditionalDependencies) + ..\lib\$(IntDir) + true + Windows + true + true + + MachineX64 + + + copy $(OutDir)$(TargetFileName) ..\bin\$(IntDir) +copy ..\Licencia\OliviaTasks.lic ..\bin\$(IntDir) + + + + + + + + Create + Create + Create + Create + + + + + + + + + + + + + + + + + + + + {192bcb82-d8b4-4fb0-807a-7cc9b6ea623b} + false + + + + + + \ No newline at end of file diff --git a/OliviaTasks/OliviaTasks.vcxproj.filters b/OliviaTasks/OliviaTasks.vcxproj.filters new file mode 100644 index 0000000..800a85d --- /dev/null +++ b/OliviaTasks/OliviaTasks.vcxproj.filters @@ -0,0 +1,62 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Resource Files + + + + + + Resource Files + + + \ No newline at end of file diff --git a/OliviaTasks/OliviaTasks.vcxproj.user b/OliviaTasks/OliviaTasks.vcxproj.user new file mode 100644 index 0000000..602ad4f --- /dev/null +++ b/OliviaTasks/OliviaTasks.vcxproj.user @@ -0,0 +1,19 @@ + + + + ..\bin\$(IntDir) + WindowsLocalDebugger + + + ..\bin\$(IntDir) + WindowsLocalDebugger + + + ..\bin\$(IntDir) + WindowsLocalDebugger + + + ..\bin\$(IntDir) + WindowsLocalDebugger + + \ No newline at end of file diff --git a/OliviaTasks/OlvTaskProcess.cpp b/OliviaTasks/OlvTaskProcess.cpp new file mode 100644 index 0000000..8b8b3fc --- /dev/null +++ b/OliviaTasks/OlvTaskProcess.cpp @@ -0,0 +1,497 @@ +#include "StdAfx.h" +#include "OlvTaskProcess.h" +#include "olivia_def.h" +#include +#include +#include "olv_task.h" + +#define MODULO "OlvTaskProcess" + +std::string to_string(double& d) +{ + char dig[256]; + dig[0]=0; + return dig; +} + +//******************************************************************************************************* +OlvTaskProcess::OlvTaskProcess(void) +{ + costes.clear(); + va_mal=FALSE; + angs=NULL; +} +OlvTaskProcess::~OlvTaskProcess( void ) +{ + costes.clear(); + if(angs) + { + for(int i=0;icalcula_cost_amb_sub(ini,fin,ithr)) + mal=TRUE; +} +//******************************************************************************************************* +BOOL OlvTaskProcess::calcula_cost_amb_sub(int amb_ini,int amb_fin, int ith) +{ + int na,i,k; + int seg; + Djkt_nodo *costes_nodos; + BOOL mal=FALSE; + + //---------------------------------------- + //////////////// + int na_desp = amb_fin-amb_ini; + costes_nodos=NULL; + //////////////// + FlagsArray visto_ang;//buffer de flags + + C_log::log(MODULO,"Subthr %ld, Ambs %04d a %04d, numero ambitos totales %ld", ith,amb_ini, amb_fin, info.namb); + + seg = GetTickCount(); + ///////////////////////////////////// + //Bucle por cada ámbito de los que le tocan a este thread + ///////////////////////////////////// + //el coste de un ámbito a sí mismo es el de trabajar ese ámbito, + //que es el coste de ir de su conj inicial a la final + //na=na_ini; + ///////////////////////////////////// + for(na=amb_ini;naias[i].ic_ini está almacenado el índice de la conjunción del nodo inicial del ámbito + //y en olv_limp->ias[i].ic_fin el del final. Se puede acceder con i directamente al array ias porque + //la info asociada está añadida por orden, primero los ámbitos + ///////////////////////////////////////////// + //calcula el coste máximo del ámbito na a todos los demás + //los añade a la fila na de la matriz de costes + //es coste máximo porque hace el máximo de: + //inicio(na)->inicio(ni), inicio(na)->final(ni), final(na)->inicio(ni), final(na)->final(ni) + ///////////////////////////////////////////// + //k==0, calcula las distancias del nodo inicial de ese ámbito a todas las demás conjunciones + //k==1, calucla las distancias del nodo final + + for(k=0;kcostes_nodos[ia.get(i,0)].dis) + cost_amb[i][na]=costes_nodos[ia.get(i,0)].dis; + if(info.KK==OLV_AMB_LIN) + { + if(cost_amb[i][na]>costes_nodos[ia.get(i,1)].dis) + cost_amb[i][na]=costes_nodos[ia.get(i,1)].dis; + } + } + } + if(!arch_dj.add_b(costes_nodos, na, k, TRUE)) + { + C_log::log(MODULO,"Subthr %ld,Error %ld no se ha podido guardar dj iref: %ld k: %ld", ith, + GetLastError(),na,k); + } + } + if(mal) + break; + //avisa de progreso + if(((na-amb_ini)%20==0)) + { + C_log::log(MODULO,"Subthr %ld, Rellenando matriz de dist entre ambs %ld de %ld", ith, + (na-amb_ini+1),na_desp); + + } + } + + if(mal || pirate) + { + C_log::log(MODULO,"Subthr %ld, Error en cálculo de matriz de distancias entre ámbitos", ith); + + return FALSE; + } + + C_log::log(MODULO,"Subthr %ld, Fin Matriz de dist entre ambs, %.3f seg", ith, 1.0*(GetTickCount()-seg)/1000); + + return TRUE; + + ///////////////////////////////////// +} +//******************************************************************************************************* +BOOL OlvTaskProcess::lee_mats() +{ + //lee archivos de costes, angulos e informacion asociada + //si !usa_angs, angs=NULL; + + BOOL mal=FALSE; + CoptiMemo oo(TRUE); + C_log::log(MODULO,"Task %ld, Memo disp %I64d",ithr, oo.memo); + int nvect=oo.calc_nvect_multi(info.n,info.nthr,sizeof(Djkt_elem_cola)); + if(nvect<0) + { + C_log::log(MODULO,"Task %ld, Error sin memoria al calcular nvect",ithr); + goto va_mal; + } + C_log::log(MODULO,"Task %ld, Calculando con nvect %ld de %ld",ithr, nvect,info.n); + //inicializa los arrays + costes.inicializa(info.n,info.nthr,nvect); + + C_log::log(MODULO,"Task %ld, Lee matriz de costes",ithr); + if(!costes.leeThread(info.path_cconj,info.ext,info.nthr,FALSE)) //el false es para forzar a que todos sean vect, que no los haga igual que los archivos + { + C_log::log(MODULO,"Task %ld, Error al leer matriz de costes: %s",ithr, info.path_cconj ); + goto va_mal; + } + + C_log::log(MODULO,"Task %ld, Lee matriz de angulos",ithr); + if(info.usa_angs) + { + angs = new Djkt_ang_ady[info.n]; + if(!angs) + { + C_log::log(MODULO,"Task %ld, Error lee_mat sin memoria para %ld Djkt_ang_ady",ithr, info.n); + + mal=TRUE; + } + for(int ic=0; ic dat; + int getFlags(int na) + { + return dat[na*3+2]; + } + virtual int get(int iamb, int iextremo) + { + return dat[iamb*3+iextremo]; + } + inline void clear() + { + dat.borra(); + } + + BOOL leeFile(char* path); +}; + +struct InfoIniTask; +/*! + * Clase para cálculos de Olivia en modo Multitask + * + */ +class OlvTaskProcess : public TaskProcess +{ +public: + //info de procesos + bool va_mal; + int ithr;//id del thread, lo recibe al arrancar como arg + int amb_ini;//ambito inicio, lo calcula + int amb_fin;//ambito fin, lo calcula + ///////////////////////// + //variables para run + Cdijkstra_arch arch_dj; + InfoIndiceEx ia;//puntero a info asoc + CmapMatFloat costes;//matriz de costes entre nodos + Djkt_ang_ady *angs;//angulos entre nodos + Matrix2d cost_amb;//matriz de costes entre ambitos + ///////////////////////// + //recibe por socket + InfoIniTask info; + ////////////////////////// + OlvTaskProcess(void); + ~OlvTaskProcess(void); + virtual void preTask(); + virtual void inTask(); + virtual void postTask(); + virtual void run(); + virtual void desconecta(); + ///////////////////////// + //funciones run + BOOL calcula_cost_amb_sub(int amb_ini,int amb_fin, int ith); + BOOL lee_mats(); + BOOL guarda_cost_amb(); + void enviaLog(); + BOOL calcula_cost_ambThr(); + BOOL lanza_thr_calc(); +}; + +class ThCalcCostes: public Cth +{ +public: + OlvTaskProcess *pclas; + int ithr; + int ini;//fila inicio + int fin;//fila fin + BOOL mal;//indica si ha ido bien + virtual void run(); +}; \ No newline at end of file diff --git a/OliviaTasks/ReadMe.txt b/OliviaTasks/ReadMe.txt new file mode 100644 index 0000000..3e06bdf --- /dev/null +++ b/OliviaTasks/ReadMe.txt @@ -0,0 +1,46 @@ +======================================================================== + CONSOLE APPLICATION : OliviaTasks Project Overview +======================================================================== + +AppWizard has created this OliviaTasks application for you. + +This file contains a summary of what you will find in each of the files that +make up your OliviaTasks application. + + +OliviaTasks.vcproj + This is the main project file for VC++ projects generated using an Application Wizard. + It contains information about the version of Visual C++ that generated the file, and + information about the platforms, configurations, and project features selected with the + Application Wizard. + +OliviaTasks.cpp + This is the main application source file. + +///////////////////////////////////////////////////////////////////////////// +AppWizard has created the following resources: + +OliviaTasks.rc + This is a listing of all of the Microsoft Windows resources that the + program uses. It includes the icons, bitmaps, and cursors that are stored + in the RES subdirectory. This file can be directly edited in Microsoft + Visual C++. + +Resource.h + This is the standard header file, which defines new resource IDs. + Microsoft Visual C++ reads and updates this file. + +///////////////////////////////////////////////////////////////////////////// +Other standard files: + +StdAfx.h, StdAfx.cpp + These files are used to build a precompiled header (PCH) file + named OliviaTasks.pch and a precompiled types file named StdAfx.obj. + +///////////////////////////////////////////////////////////////////////////// +Other notes: + +AppWizard uses "TODO:" comments to indicate parts of the source code you +should add to or customize. + +///////////////////////////////////////////////////////////////////////////// diff --git a/OliviaTasks/Resource.h b/OliviaTasks/Resource.h new file mode 100644 index 0000000..d88ce1b --- /dev/null +++ b/OliviaTasks/Resource.h @@ -0,0 +1,17 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by OliviaTasks.rc +// +#define IDI_ICON1 102 +#define IDS_APP_TITLE 103 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 103 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/OliviaTasks/favicon.ico b/OliviaTasks/favicon.ico new file mode 100644 index 0000000..df53e93 Binary files /dev/null and b/OliviaTasks/favicon.ico differ diff --git a/OliviaTasks/olivia_def.h b/OliviaTasks/olivia_def.h new file mode 100644 index 0000000..b22ab72 --- /dev/null +++ b/OliviaTasks/olivia_def.h @@ -0,0 +1,59 @@ +#pragma once +////////////////////////////////////////////////// +//Defines +#define OLV_LIMP_AMB_NW_NODEF USHRT_MAX//-1 // +#include +#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit + +#ifndef VC_EXTRALEAN +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers +#endif + +#include +#include // MFC core and standard components +#include // MFC extensions +#ifndef _AFX_NO_OLE_SUPPORT +#include // MFC support for Internet Explorer 4 Common Controls +#endif +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include // MFC support for Windows Common Controls +#endif // _AFX_NO_AFXCMN_SUPPORT + +#include +#include <_app.h> +#include "garray.h" +#include "utiles_def.h" +// TODO: reference additional headers your program requires here diff --git a/OliviaTasks/targetver.h b/OliviaTasks/targetver.h new file mode 100644 index 0000000..203dfbc --- /dev/null +++ b/OliviaTasks/targetver.h @@ -0,0 +1,24 @@ +#pragma once + +// The following macros define the minimum required platform. The minimum required platform +// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run +// your application. The macros work by enabling all features available on platform versions up to and +// including the version specified. + +// Modify the following defines if you have to target a platform prior to the ones specified below. +// Refer to MSDN for the latest info on corresponding values for different platforms. +#ifndef WINVER // Specifies that the minimum required platform is Windows Vista. +#define WINVER 0x0600 // Change this to the appropriate value to target other versions of Windows. +#endif + +#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows Vista. +#define _WIN32_WINNT 0x0600 // Change this to the appropriate value to target other versions of Windows. +#endif + +#ifndef _WIN32_WINDOWS // Specifies that the minimum required platform is Windows 98. +#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later. +#endif + +#ifndef _WIN32_IE // Specifies that the minimum required platform is Internet Explorer 7.0. +#define _WIN32_IE 0x0700 // Change this to the appropriate value to target other versions of IE. +#endif diff --git a/bin/Debug/ClientLic.dll b/bin/Debug/ClientLic.dll new file mode 100644 index 0000000..80faa93 Binary files /dev/null and b/bin/Debug/ClientLic.dll differ diff --git a/bin/Debug/FileTransfer.dll b/bin/Debug/FileTransfer.dll new file mode 100644 index 0000000..72f6017 Binary files /dev/null and b/bin/Debug/FileTransfer.dll differ diff --git a/bin/Debug/Olivia.dll b/bin/Debug/Olivia.dll new file mode 100644 index 0000000..5a7e53f Binary files /dev/null and b/bin/Debug/Olivia.dll differ diff --git a/bin/Debug/OliviaTasks.exe b/bin/Debug/OliviaTasks.exe new file mode 100644 index 0000000..edad466 Binary files /dev/null and b/bin/Debug/OliviaTasks.exe differ diff --git a/bin/Debug/OliviaTasks.lic b/bin/Debug/OliviaTasks.lic new file mode 100644 index 0000000..c7711a6 Binary files /dev/null and b/bin/Debug/OliviaTasks.lic differ diff --git a/bin/Debug/licUtiles.dll b/bin/Debug/licUtiles.dll new file mode 100644 index 0000000..205fd68 Binary files /dev/null and b/bin/Debug/licUtiles.dll differ diff --git a/bin/Debug/sqlite3.dll b/bin/Debug/sqlite3.dll new file mode 100644 index 0000000..d5d1586 Binary files /dev/null and b/bin/Debug/sqlite3.dll differ diff --git a/bin/Debug/utiles.dll b/bin/Debug/utiles.dll new file mode 100644 index 0000000..2fd2d63 Binary files /dev/null and b/bin/Debug/utiles.dll differ diff --git a/bin/Release/ClientLic.dll b/bin/Release/ClientLic.dll new file mode 100644 index 0000000..8dd2acc Binary files /dev/null and b/bin/Release/ClientLic.dll differ diff --git a/bin/Release/FileTransfer.dll b/bin/Release/FileTransfer.dll new file mode 100644 index 0000000..4ff39eb Binary files /dev/null and b/bin/Release/FileTransfer.dll differ diff --git a/bin/Release/Olivia.dll b/bin/Release/Olivia.dll new file mode 100644 index 0000000..c9c33af Binary files /dev/null and b/bin/Release/Olivia.dll differ diff --git a/bin/Release/OliviaTasks.exe b/bin/Release/OliviaTasks.exe new file mode 100644 index 0000000..084b6a7 Binary files /dev/null and b/bin/Release/OliviaTasks.exe differ diff --git a/bin/Release/OliviaTasks.lic b/bin/Release/OliviaTasks.lic new file mode 100644 index 0000000..c7711a6 Binary files /dev/null and b/bin/Release/OliviaTasks.lic differ diff --git a/bin/Release/licUtiles.dll b/bin/Release/licUtiles.dll new file mode 100644 index 0000000..77c2439 Binary files /dev/null and b/bin/Release/licUtiles.dll differ diff --git a/bin/Release/sqlite3.dll b/bin/Release/sqlite3.dll new file mode 100644 index 0000000..d5d1586 Binary files /dev/null and b/bin/Release/sqlite3.dll differ diff --git a/bin/Release/utiles.dll b/bin/Release/utiles.dll new file mode 100644 index 0000000..2b895be Binary files /dev/null and b/bin/Release/utiles.dll differ diff --git a/bin/x64/debug/ClientLic.dll b/bin/x64/debug/ClientLic.dll new file mode 100644 index 0000000..9df4c79 Binary files /dev/null and b/bin/x64/debug/ClientLic.dll differ diff --git a/bin/x64/debug/FileTransfer.dll b/bin/x64/debug/FileTransfer.dll new file mode 100644 index 0000000..5508c47 Binary files /dev/null and b/bin/x64/debug/FileTransfer.dll differ diff --git a/bin/x64/debug/FileTransfer.lib b/bin/x64/debug/FileTransfer.lib new file mode 100644 index 0000000..e929ef0 Binary files /dev/null and b/bin/x64/debug/FileTransfer.lib differ diff --git a/bin/x64/debug/Olivia.dll b/bin/x64/debug/Olivia.dll new file mode 100644 index 0000000..687115f Binary files /dev/null and b/bin/x64/debug/Olivia.dll differ diff --git a/bin/x64/debug/OliviaTasks.exe b/bin/x64/debug/OliviaTasks.exe new file mode 100644 index 0000000..cc73179 Binary files /dev/null and b/bin/x64/debug/OliviaTasks.exe differ diff --git a/bin/x64/debug/OliviaTasks.lic b/bin/x64/debug/OliviaTasks.lic new file mode 100644 index 0000000..1522724 Binary files /dev/null and b/bin/x64/debug/OliviaTasks.lic differ diff --git a/bin/x64/debug/Olivia_2020_04_05_h23.log b/bin/x64/debug/Olivia_2020_04_05_h23.log new file mode 100644 index 0000000..5243264 --- /dev/null +++ b/bin/x64/debug/Olivia_2020_04_05_h23.log @@ -0,0 +1,4 @@ +2020-04-05 23:08:31 _tmain Inicio OliviaTask: +2020-04-05 23:08:31 _tmain Error al iniciar OliviaTasks para OLIVIA: +Error al leer parámetros, menos de los esperados +2020-04-05 23:08:31 _tmain Final feliz!! diff --git a/bin/x64/debug/licUtiles.dll b/bin/x64/debug/licUtiles.dll new file mode 100644 index 0000000..9b029d9 Binary files /dev/null and b/bin/x64/debug/licUtiles.dll differ diff --git a/bin/x64/debug/licUtiles.lib b/bin/x64/debug/licUtiles.lib new file mode 100644 index 0000000..a13d670 Binary files /dev/null and b/bin/x64/debug/licUtiles.lib differ diff --git a/bin/x64/debug/sqlite3.dll b/bin/x64/debug/sqlite3.dll new file mode 100644 index 0000000..6fda325 Binary files /dev/null and b/bin/x64/debug/sqlite3.dll differ diff --git a/bin/x64/debug/utiles.dll b/bin/x64/debug/utiles.dll new file mode 100644 index 0000000..bf3710c Binary files /dev/null and b/bin/x64/debug/utiles.dll differ diff --git a/bin/x64/debug/utiles.lib b/bin/x64/debug/utiles.lib new file mode 100644 index 0000000..9b0fc1a Binary files /dev/null and b/bin/x64/debug/utiles.lib differ diff --git a/bin/x64/release/ClientLic.dll b/bin/x64/release/ClientLic.dll new file mode 100644 index 0000000..44eefee Binary files /dev/null and b/bin/x64/release/ClientLic.dll differ diff --git a/bin/x64/release/FileTransfer.dll b/bin/x64/release/FileTransfer.dll new file mode 100644 index 0000000..75b2be6 Binary files /dev/null and b/bin/x64/release/FileTransfer.dll differ diff --git a/bin/x64/release/Olivia.dll b/bin/x64/release/Olivia.dll new file mode 100644 index 0000000..2ed1aa9 Binary files /dev/null and b/bin/x64/release/Olivia.dll differ diff --git a/bin/x64/release/OliviaTasks.exe b/bin/x64/release/OliviaTasks.exe new file mode 100644 index 0000000..1e27bd1 Binary files /dev/null and b/bin/x64/release/OliviaTasks.exe differ diff --git a/bin/x64/release/OliviaTasks.lic b/bin/x64/release/OliviaTasks.lic new file mode 100644 index 0000000..c7711a6 Binary files /dev/null and b/bin/x64/release/OliviaTasks.lic differ diff --git a/bin/x64/release/licUtiles.dll b/bin/x64/release/licUtiles.dll new file mode 100644 index 0000000..79ad031 Binary files /dev/null and b/bin/x64/release/licUtiles.dll differ diff --git a/bin/x64/release/sqlite3.dll b/bin/x64/release/sqlite3.dll new file mode 100644 index 0000000..6fda325 Binary files /dev/null and b/bin/x64/release/sqlite3.dll differ diff --git a/bin/x64/release/utiles.dll b/bin/x64/release/utiles.dll new file mode 100644 index 0000000..91e50f5 Binary files /dev/null and b/bin/x64/release/utiles.dll differ diff --git a/includes/ClientLic/ClientLicDef.h b/includes/ClientLic/ClientLicDef.h new file mode 100644 index 0000000..56aa9fb --- /dev/null +++ b/includes/ClientLic/ClientLicDef.h @@ -0,0 +1,9 @@ +#pragma once +#ifndef CLIC_EXPORT +#ifdef _WINDLL +#define CLIC_EXPORT __declspec(dllexport) +#else +#define CLIC_EXPORT __declspec(dllimport) +#endif + +#endif diff --git a/includes/ClientLic/ClienteLicencias.h b/includes/ClientLic/ClienteLicencias.h new file mode 100644 index 0000000..ed0a608 --- /dev/null +++ b/includes/ClientLic/ClienteLicencias.h @@ -0,0 +1,43 @@ +#pragma once +#include "LicUtilesDef.h" +#include "ClientLicDef.h" +#include "FileTransferDef.h" + + +class FileTransferClient; +class CLIC_EXPORT ClienteLicencias: public LicClientEscucha, public FileTransferClientLisener +{ + CDialog *dprog; + double porcen; +public: + FileTransferClient *ft; + int dias_pregun; + bool cancelaDescarga; + bool espera_dlg; + char dirTemp[256];//directorio temporal para dejar el instalador + char dirLic[256];//path para guardar la licencia y la ultima vez que se pregunto si descargar lic + + ClienteLicencias(void); + ~ClienteLicencias(void); + + bool cargaLicencia(); + + virtual bool getClave(char* clave, char* producto ); + + virtual void muestaError( char* info, char* producto ); + + virtual bool descargaInstalador( Licencia *lic ); + + void descargaVersion( Licencia *lic); + + virtual void setStatus( double porcent ); + + virtual void finTransfer( bool finalFeliz ); + + virtual bool getPathLic( char* path, char* producto ); + + virtual bool cancelTransfer(); + + private: + bool preguntarDescarga(); +}; diff --git a/includes/FileTransfer/FileTransferDef.h b/includes/FileTransfer/FileTransferDef.h new file mode 100644 index 0000000..7b79ff8 --- /dev/null +++ b/includes/FileTransfer/FileTransferDef.h @@ -0,0 +1,28 @@ +#ifndef FT_EXPORT +#ifdef _WINDLL +#define FT_EXPORT __declspec(dllexport) +#else +#define FT_EXPORT __declspec(dllimport) +#endif +struct Usuario_conx_0; +class FT_EXPORT IDataUserProvider +{ +public: + virtual bool fill(Usuario_conx_0 *user, char *pathRaid) = 0; + virtual bool getConf(char *ip, int *port) = 0; + + +}; + +#define FILE_TRANSMISION_GET_FILES 7 +#define FILE_TRANSMISION_GET_DIRS 8 + +class FT_EXPORT FileTransferClientLisener +{ +public: + virtual void setStatus(double porcent){}; + virtual void finTransfer(bool finalFeliz){}; + virtual bool cancelTransfer(){ return false;}; + +}; +#endif diff --git a/includes/LicUtiles/LicUtilesDef.h b/includes/LicUtiles/LicUtilesDef.h new file mode 100644 index 0000000..9c8d6cc --- /dev/null +++ b/includes/LicUtiles/LicUtilesDef.h @@ -0,0 +1,44 @@ +#pragma once +#ifndef LICUTL_EXPORT +#ifdef _WINDLL +#define LICUTL_EXPORT __declspec(dllexport) +#else +#define LICUTL_EXPORT __declspec(dllimport) +#endif + +#define VERSION_LICENCIA 100 + +#define LU_LICENCIA_CADUCA 1 //licencia normal +#define LU_LICENCIA_PROPIETARIA 2 //licencia propietaria, por defecto da licencia + + +#define LU_DEFAULT_FILE "data.lic" +#define LU_DEFAULT_SERVER "desa.narvaling.com" +//#define LU_DEFAULT_SERVER "192.168.1.60" + +#define LU_DEFAULT_PUERTO 8051 + +class Licencia; +//structuras +class LICUTL_EXPORT DBLicProvider +{ +public: + virtual bool fill( Licencia* lic )=0;//rellena datos licencia + virtual int licCount( Licencia* lic )=0;//cuenta numero de licencias + virtual bool fillInstal( Licencia* lic )=0;//rellena instalador + virtual bool setAcceso( Licencia* lic, __int64 *ultAcc, __int64 *actualAcceso)=0; + virtual bool getConf( char *ip, int *port )=0;//configuracion de escucha +}; + +class LICUTL_EXPORT LicClientEscucha +{ +public: + virtual bool getClave(char* clave, char* producto )=0;//pide clave (pidiendosela al usuario) + virtual bool getServer( char*server, int *puerto, char* producto){ server[0]=0;*puerto=0;return false;}//pide servidor de licencias (no obligada) + virtual bool getPathLic( char* path, char* producto ){path[0]=0; return true;}//pide path de archivo de licencia (no obligada) + virtual void muestaError(char* info, char* producto){} + virtual bool descargaInstalador(Licencia *lic){return true;}//true si revisamos instalador, false si no + +}; + +#endif diff --git a/includes/Olivia/OliviaDef.cs b/includes/Olivia/OliviaDef.cs new file mode 100644 index 0000000..6d696fb --- /dev/null +++ b/includes/Olivia/OliviaDef.cs @@ -0,0 +1,591 @@ +/** +* @file GeneralDef.cs +* Clase con definiciones globales comunes al proyecto Olivia y a OliviaTasks. +*/ +/** +* Clase con definiciones globales comunes al proyecto Olivia y a OliviaTasks. +*/ +namespace OliviaDef +{ + public static class GeneralDef + { + //************************************************************************************* + //Enums y structs generales + /** + * Tipos de ejecución de la herramienta Olivia + */ + public enum TiposOliv + { + OlivNoDef = -1, + OlivLimp, // +/* +hacer el memoryclear +guardar dbf ia +*/ +class Cb_file; +class UTILES_EXPORT CartoBase: public SetEntities, public SetPtsR, public DataIaCartoBase +{ + //clases amigo----------------- + friend class CartoBaseInfoEntity; + friend class CartoBaseInfoPto; + friend class CartoBaseInfoLine; + friend class CartoBaseInfoBuilder; + friend class CartoPto; + friend class CartoLine; +private: + //info interna------------------------------- + int ref;//referencia para el siguiente elemento + CartoBasePaintedProps _defaultpaintedProps; + CartoBaseColor _defaultColor; + //array de informacion de entidades + Cgarray _entities;//entidades + Cgarray _points;//coordenadas + Cgarray _lines;//lineas + Cgarray _paintedProps;//propiedades de pintado + Cgarray _colors; + std::map refIndex;//indexado por referencias; + //datos de ia----------------------------------------- + char iaName[12];//nombre columna ia tipo IntIa + int typeIA;//indica el tipo de informacion asociada que se utilizara +public: + + IaDataTable dataIa; + DataIaCartoBase *iaEx; + enum TypedataIa + { + NIa=0,//sin informacion asociada + IntIa,//usa solo un entero por entidad como ia con nombre de columna iaName + DtIa,//usa la dataIa para almacenar info asociada + ExIa//informacion asociada externa + }; + + CartoBase(void); + ~CartoBase(void); + + //funciones----------------------------------------------------------------- + CartoBaseInfoEntity get(int i);//acceso a entidad iesima (modo lectura) + CartoBaseInfoEntity getRef(int r);//acceso a entidad con referencia r (modo lectura) + + + //añade elementos + bool add(CartoEntity& element); + bool add(CartoBase& cad); + + bool remove(int i);//pone marca de flag de borrado (pero sigue siendo accesible) + bool removeRef(int r); + + bool FastClear();//solo borra entidades y rehace las referencias + bool clear();//limpia elementos borrados y ajusta memoria + bool MemClear();//limpia memoria de todos los arrays + + EntitiesArray* filter(EntitiesArray* dst, FilterEntities *filter); + + virtual bool leer(char *path); + virtual bool grabar(char *path); + virtual bool leer(Cb_file *f); + virtual bool grabar(Cb_file *f); + + int addDefaultPaintedProps();//crea unas propiedades de pintado como las por defecto + + bool importShp(char* path);//importa shp + bool exportShp(char* path);//exporta a shp (todos los tipos que cuinciden con la primera) + bool ptosExportShp(char* path); + bool linesExportShp(char* path); + + void del();//limpia toda la carto (sin liberar memoria) + + //funciones de ia------------------------------------------------------------------- + void* getIa(int refEnt);//devuelve informacion asociada externa de la entidad refEnt + int getTypeIA(){return typeIA;}//devuelve el tipo de ia que tiene actualmente + void setExIa(DataIaCartoBase* ia);//setea un ia externo + int getEntityRef(int ientity);//devuelve la referencia + void setNameIa(char *name);//pone el nombre de la col + + //funciones por ser SetEntities + virtual CartoBaseInfoEntity getEntity(int i); + virtual int getNumberEntities(); + //funciones por ser SetPts + virtual double* getPto(int i); + virtual int getNumberPtos(); + //funciones auxiliares------------ + int getNexRef(){return ref;}; + + //funciones DataIaCartoBase + virtual bool IaGetSize( int *ncolm ); + virtual bool IaGetColm( int icol, char* name, BYTE *type, int *size, int*ndecimal ); + virtual bool IaGetVal( int refEnt, int icol, int* v ); + virtual bool IaFinW(){return true;} + +private: + + int add(CartoBaseEntity* src); + int add(CartoBasePoint* src); + int add(CartoBaseLine* src); + int add(CartoBasePaintedProps* src); + int add(CartoBaseColor* src); + + bool fexportShp(char* path, int type = CartoBaseTypes::Ndef); + + void indexRef(bool buscaRepes=false);//indexa referencias + void iniIndexRef();//crea indexado + void reIndexRef(); +}; + +class FiterCartoBase: public SetEntities +{ +public: + CartoBase* cb; + Cgarray ind; + + virtual CartoBaseInfoEntity getEntity( int i ); + + virtual int getNumberEntities(); +}; +#endif \ No newline at end of file diff --git a/includes/Utiles/CartoBaseDBFManager.h b/includes/Utiles/CartoBaseDBFManager.h new file mode 100644 index 0000000..44f616c --- /dev/null +++ b/includes/Utiles/CartoBaseDBFManager.h @@ -0,0 +1,49 @@ +#pragma once +#include "base_head.h" +#include "Fdbf.h" +#include "CartoBase.h" + +//clase helper para imporacion de un dbf a informacion asociada de cartobase +class UTILES_EXPORT CartoBaseDBFManager: public ListenerDbf_W, public ListenerDbf_R +{ + CartoBase *cb; + int _oldRef; + int _icol; + int _nncol; + int _nnrow; + CartoBaseInfoEntity e; + int rowE; + SetEntities *setEnt; + DataIaCartoBase* ia; +public: + + CartoBaseDBFManager(void); + ~CartoBaseDBFManager(void); + virtual bool leer(char *path, CartoBase*cartb); + virtual bool grabar(char *path, DataIaCartoBase* iawx, SetEntities* s); + + + //funciones auxiliares----------------------------------- + //funciones de lectura de shp-------------------------- + virtual bool DbfSet( int nrow, int ncolm ); + virtual bool DbfSetColm( char* name, BYTE type, int size ); + virtual bool DbfaddVal( int icol, int v ); + virtual bool DbfaddVal( int icol, double v ); + virtual bool DbfaddVal( int icol, __int64 v ); + virtual bool DbfaddVal( int icol, char* v ); + virtual bool DbfaddVal( int icol, void* v ); + virtual bool DbfFinRow(); + virtual bool DbfFinR(); + + //funciones de escritura de dbf----------------------- + virtual bool DbfGet( int *nrow, int *ncolm); + virtual bool DbfGetColm( int icol, char* name, BYTE *type, int *size, int*ndecimal ); + virtual bool DbfGetVal( int irow, int icol, int* v ); + virtual bool DbfGetVal( int irow, int icol, double* v ); + virtual bool DbfGetVal( int irow, int icol, __int64* v ); + virtual bool DbfGetVal( int irow, int icol, char** v ); + virtual bool DbfGetVal( int irow, int icol, void** v ); + virtual bool DbfFinW(); + + +}; diff --git a/includes/Utiles/CartoBaseDef.h b/includes/Utiles/CartoBaseDef.h new file mode 100644 index 0000000..1358893 --- /dev/null +++ b/includes/Utiles/CartoBaseDef.h @@ -0,0 +1,75 @@ +#pragma once +#ifndef CartoBaseDef_H +#define CartoBaseDef_H +#include "base_head.h" + +namespace CartoBaseTypes{ + enum { + Ndef = 0, + Point, + Line + }; +}; + +//calse coleccion de puntos (double[3]) solo lectura +class UTILES_EXPORT SetPtsR +{ +public: + virtual double* getPto(int i)=0;//devuelve el punto iesimo + virtual int getNumberPtos()=0;//devuelve numero de puntos totales +}; +//coleccion de puntos al que se le puede añadir mas +class UTILES_EXPORT SetPtsW +{ +public: + virtual bool addPto(double* p)=0;//añade el punto p al conjunto +}; +//constructor de setPtsW +class UTILES_EXPORT SetPtsWBuilder +{ +public: + virtual SetPtsW *build()=0;//devuelve una nueva clase SetPtsW +}; +class CartoBase; +//interface de ia +class UTILES_EXPORT DataIaCartoBase +{ +public: + virtual void* IaGet(int refEnt){return NULL;} + + virtual void CBSet(CartoBase* cb){} + virtual void IaRemove(int refEnt){} + virtual void IaRemoveAll(){} + virtual void IaAdd(int refEnt){} + + //informa del numero de filas y columnas que tiene la ia + virtual bool IaSet(int nrow, int ncolm){return true;} + virtual bool IaSetColm(int icol, char* name, BYTE type, int size){return true;} + virtual bool IaAddVal(int refEnt, int icol, int v){return true;} + virtual bool IaAddVal(int refEnt, int icol, double v){return true;} + virtual bool IaAddVal(int refEnt, int icol, __int64 v){return true;} + virtual bool IaAddVal(int refEnt, int icol, char* v){return true;} + virtual bool IaAddVal(int refEnt, int icol, void* v){return true;} + virtual bool IaFinRow(int refEnt){return true;} + virtual bool IaFinR(){return true;} + + + virtual bool IaGetSize( int *ncolm ){return false;} + virtual bool IaGetColm( int icol, char* name, BYTE *type, int *size, int*ndecimal ){return false;} + virtual bool IaGetVal( int refEnt, int icol, int* v ){return false;} + virtual bool IaGetVal( int refEnt, int icol, double* v ){return false;} + virtual bool IaGetVal( int refEnt, int icol, __int64* v ){return false;} + virtual bool IaGetVal( int refEnt, int icol, char** v ){return false;} + virtual bool IaGetVal( int refEnt, int icol, void** v ){return false;} + virtual bool IaFinW(){return true;} +}; + +#define TYPE_FILE "CartoBase" +#define VERSION_CART_BASE 100 +//falgs de entidades-------------- +#define CARTOBASE_DELETED_ENTITY 0x01 + + + +#endif + diff --git a/includes/Utiles/CartoBaseElements.h b/includes/Utiles/CartoBaseElements.h new file mode 100644 index 0000000..eab9336 --- /dev/null +++ b/includes/Utiles/CartoBaseElements.h @@ -0,0 +1,172 @@ +#pragma once +#include "base_head.h" +#include "cartoBaseDef.h" +#include "garray.h" +#ifndef CartoBaseElements_H +#define CartoBaseElements_H +class CartoEntity; +//clases internas de cartobase---------------------------------------------- +class UTILES_EXPORT CartoBaseEntity +{ +public: + int id; //indice a objeto + int type; //tipo de entidad + int idPaintp; //inide a propiedades + int flagsUser; //flags para uso de usuario + int flagsInt; //flags para uso interno + int ref; //referencia unica por elemento + + //tamaño--------- + int mima[2]; //indice a punto maximo y minimo (el elemento esta contenido entre dichos puntos) + int ia; //indice a informacion adicional + + CartoBaseEntity() + { + id = -1; + idPaintp = -1; + flagsInt = 0; + } +}; +//entidad interna de putno +class UTILES_EXPORT CartoBasePoint +{ +public: + double pts[3];//coordenadas del punto + + CartoBasePoint(){ + pts[0]=pts[1]=pts[2]=0; + } +}; + +//entidad interna de linea +class UTILES_EXPORT CartoBaseLine +{ +public: + int ini; //inidce a punto inicio + int n; //numero de puntos del lineal + CartoBaseLine() + { + n = 0; + ini = -1; + } +}; +//entidad interna de propiedades de pintado +class UTILES_EXPORT CartoBasePaintedProps +{ +public: + int color; //indice a color + int peso; //grosor o tamaño de letra (segun entidad) + int prioridad; //prioridad de pintado + int flags; //flags internos 0x1 (visto para los clear) + CartoBasePaintedProps() + { + color = -1; + peso = 1; + flags = 0; + } +}; +//entidad interna de color +class UTILES_EXPORT CartoBaseColor +{ +public: + + int color; + int flags; //flags internos 0x1 (visto para los clear) + CartoBaseColor() + { + color = 0; + flags = 0; + } +}; + +//entidad base de informacion +class CartoBase; +class UTILES_EXPORT CartoBaseInfoEntity: public SetPtsR +{ +public: + //funciones externas + CartoBasePoint* (*fpto)(CartoBaseInfoEntity *c); + CartoBaseLine* (*fline)(CartoBaseInfoEntity *c); + int i_entity; + + CartoBase* ptr; + + CartoBaseInfoEntity(); + + virtual bool isValid(); //dice si es valido o no la entidad de informacion + virtual CartoBaseInfoEntity next(); //devuelve entidad siguiente + virtual CartoBaseInfoEntity prev(); //devuelve entidad anterior + + //acceso a informacion interna + virtual CartoBasePoint* pto(); + virtual CartoBaseEntity* entity(); + virtual CartoBaseLine* line(); + virtual CartoBasePaintedProps* paintp(); + virtual CartoBaseColor* color(); + virtual CartoEntity* getCopy(CartoEntity *buf=NULL); + //funciones SetPts-------------------------- + virtual double* getPto(int i); + virtual int getNumberPtos(); + + void* getIa(); + double getLong(); + double disMedLines(SetPtsR *line2, double l_avan, double *desv=NULL); + double disMedLines(SetPtsR *line2, double *desv=NULL); + double DisPtoLine(double*p, int* idpto=NULL, double *lamb=NULL); + SetPtsW *GetNPrimePtos(SetPtsW *ldst, int nptos, double dis, BOOL avanza); + bool DivLine(SetPtsW* ldst1, SetPtsW* ldst2, int ip, double lamb); + double *GetPtoDis(double dis, double *dst, double *distTot); + double *PtInLine(int ip, double lamb, double *pp); + double DplineSeg(double* s1, double *s2,int *n=NULL, double *lamd1=NULL,double *lamb2=NULL); +}; +//calse coleccion de entidades +class UTILES_EXPORT SetEntities +{ +public: + virtual CartoBaseInfoEntity getEntity(int i)=0; + virtual int getNumberEntities()=0; +}; + +//clase de filtrado de entidades +class UTILES_EXPORT FilterEntities +{ +public: + virtual bool IsSeletedEntity(CartoBaseInfoEntity *e)=0; +}; + +//array de entidades +class UTILES_EXPORT EntitiesArray: public Cgarray, public SetEntities, public SetPtsR +{ +public: + virtual CartoBaseInfoEntity getEntity(int i); + virtual int getNumberEntities(); + + virtual double* getPto(int i); + virtual int getNumberPtos(); + + EntitiesArray* filter(EntitiesArray* dst, FilterEntities* filter); + bool exportShp(char* path, int type = CartoBaseTypes::Ndef); +}; +//entidad de informacion punto +class UTILES_EXPORT CartoBaseInfoPto +{ +public: + static CartoBasePoint* pto(CartoBaseInfoEntity*c); +}; +//entidad de informacion linea +class UTILES_EXPORT CartoBaseInfoLine +{ +public: + + static CartoBasePoint* pto(CartoBaseInfoEntity*c); + static CartoBaseLine* line(CartoBaseInfoEntity*c); +}; + +//clase constructor de entidades info +class UTILES_EXPORT CartoBaseInfoBuilder +{ +public: + static CartoBaseInfoEntity get(int i, CartoBase* ptr); + static CartoEntity* get(int type); +}; +#endif diff --git a/includes/Utiles/CartoBaseShpManager.h b/includes/Utiles/CartoBaseShpManager.h new file mode 100644 index 0000000..53554de --- /dev/null +++ b/includes/Utiles/CartoBaseShpManager.h @@ -0,0 +1,28 @@ +#pragma once +#include "base_head.h" +#include "garray.h" +#include "CartoBase.h" + +class Cb_file; +class Fshape; +//clase helper para inportacion de shp a un carto base +class UTILES_EXPORT CartoBaseShpManager +{ + CartoBase* cad; + bool ImportPoints(Fshape *shp); + bool Importline(Fshape *shp); + bool ImportPoligon(Fshape *shp); + bool ExportLine(Cb_file *file, Cb_file *fshx, SetEntities *entities); + bool ExportPts(Cb_file *file, Cb_file *fshx, SetEntities *entities); + +public: + CartoBaseShpManager(void); + ~CartoBaseShpManager(void); + + void set(CartoBase* cb){cad = cb;} + + bool ImportShp(Cb_file *file); + + bool ExportShp(Cb_file *file,Cb_file *fshx, SetEntities *entities, int type = CartoBaseTypes::Ndef); + +}; diff --git a/includes/Utiles/CartoElements.h b/includes/Utiles/CartoElements.h new file mode 100644 index 0000000..aaffae3 --- /dev/null +++ b/includes/Utiles/CartoElements.h @@ -0,0 +1,107 @@ +#pragma once + +#include "base_head.h" +#include "CartoBaseDef.h" + +class CartoBaseEntity; +class CartoBasePaintedProps; +class CartoBaseColor; +//clases de elmentos de cartobase +class UTILES_EXPORT CartoEntity : public SetPtsR +{ +public: + virtual int getType()//devuelve tipo de entidad + { + return CartoBaseTypes::Ndef; + }; + + virtual int getnLines() + { + return 0; + } + + virtual CartoEntity* set(CartoBaseInfoEntity *src) + { + return 0; + } + virtual int CopyInTo(CartoBase *src) + { + return -1; + } + virtual double* getPto(int i){return 0;} + + virtual int getNumberPtos(){return 0;} + virtual double disMedLines(SetPtsR *line2, double *desv=NULL); + +}; + +class UTILES_EXPORT CartoComun: public CartoEntity +{ +public: + int flagsUser; + int color; + int peso; + int id;//ide de entidad + int ia; + int idPropsP;//ide de propiedades de pintado al que se va a poner + + CartoComun() + { + flagsUser =0; + color = 0; + peso = 0; + id = -1; + ia=0; + idPropsP = -1; + } + + //auxiliary funcition + bool setInfo(CartoBaseInfoEntity * info); + + CartoBaseEntity* get(CartoBaseEntity * dst); + CartoBasePaintedProps* get(CartoBasePaintedProps * dst); + CartoBaseColor* get(CartoBaseColor * dst); + + +}; + +class UTILES_EXPORT CartoPto: public CartoComun +{ +public: + + double pt[3]; + CartoPto(){}; + virtual int getType()//devuelve tipo de entidad + { + return CartoBaseTypes::Point; + }; + + virtual CartoEntity* set(CartoBaseInfoEntity *src); + + virtual int CopyInTo(CartoBase *src); + virtual double* getPto(int i); + + virtual int getNumberPtos(){return 1;} +}; + +class UTILES_EXPORT CartoLine: public CartoComun, public SetPtsW +{ +public: + Cgarray pts; + CartoLine(){}; + + virtual int getType()//devuelve tipo de entidad + { + return CartoBaseTypes::Line; + }; + + virtual CartoEntity* set(CartoBaseInfoEntity *src); + virtual int CopyInTo(CartoBase *src); + virtual int getNumberPtos(){return pts.n;} + virtual double* getPto(int i); + virtual bool addPto(double* p); + //funciones de geometria---------------------------------- + void invert();//invierte el sentido de los pts + double getLong(); + double *GetPtoDis(double dis, double *dst, double *distTot = NULL); +}; diff --git a/includes/Utiles/Csock_cl.h b/includes/Utiles/Csock_cl.h new file mode 100644 index 0000000..29fe83a --- /dev/null +++ b/includes/Utiles/Csock_cl.h @@ -0,0 +1,50 @@ +#if !defined(AFX_SOCK_SIMPLE_H__8491F9CB_65AF_44E1_80A3_52176804CD08__INCLUDED_) +#define AFX_SOCK_SIMPLE_H__8491F9CB_65AF_44E1_80A3_52176804CD08__INCLUDED_ + +#include +#include "utiles_def.h" +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +#endif +#define MODULO_CSOCK_CL "Csock_cl" +#include + +class C_error; +//socket cliente--------------------------------- +class UTILES_EXPORT Csock_cl : public CAsyncSocket +{ +public: + //variables---------------------------------- + BOOL *pirate; + BOOL borra_pirate; + BYTE *buf; + int mb,nb; + Package_head_0 cab; + C_error* er; + int time_sleep;//tiempo espera + int intentos; + bool creado; + //variables aux------------------------------ +private: + BOOL borra_er; + //cons--------------------------------------- +public: + Csock_cl(BOOL*sal=NULL,C_error*e=NULL); + virtual ~Csock_cl(void); + + //funciones---------------------------------- + BOOL Create( UINT puerto=0 , int tipo=SOCK_STREAM , + long evento=FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE , + LPCTSTR ip=NULL ); + + BOOL conectar(char *ipdot,int puerto);//conecta con un puerto y ip + + BOOL recibe_package(int indice);//recibe package y lo pone en buffer apartir de indice; + BOOL envia_package(BYTE* buff, int n, int encrip=0);//envia el buffer en packages si encrip=1 (hacemos encrip1) + //funciones auxiliares----------------------- + void cuida_buf(int n);//asegura en buf un espacio de n bytes; + BOOL recibe(BYTE*b, int n);//recive n bytes y lo pone en b; + BOOL envia(BYTE*buff, int n);//envia bytes sin mas; + +}; diff --git a/includes/Utiles/DijkstraUtiles.h b/includes/Utiles/DijkstraUtiles.h new file mode 100644 index 0000000..241b782 --- /dev/null +++ b/includes/Utiles/DijkstraUtiles.h @@ -0,0 +1,206 @@ +#pragma once +#ifndef DijkstraUtiles_h +#define DijkstraUtiles_h +#include +#include +#include +#include "mapmatrix.h" +#ifndef MAYUSCULO +#define MAYUSCULO (double) 1.e+30 + +#endif +#ifndef MINUSCULO +#define MINUSCULO (double) 1.e-20 +#endif + +#define EXT_ARCH_DIJ_DEFAULT "ndj" +#define NOMB_ARCH_DIJ_DEF "snodos_dj" + +/** + * Estructura de elemento de la cola para el cálculo de caminos óptimos por Dijkstra + */ +struct Djkt_elem_cola +{ + int id; // dat; + inline BOOL operator[](__int64 i) + { + BYTE j =(BYTE)(1<<(i%(sizeof(BYTE)*8))); + return (BOOL)((dat[(int)(i/(sizeof(BYTE)*8.))] & j) == j); + } + inline void set(__int64 i, BOOL v) + { + BYTE j; + j =(BYTE)(1<<(i%(sizeof(BYTE)*8))); + + if(!v) + { + j = ~j; + dat[(int)(i/(sizeof(BYTE)*8.))] &= j; + return; + } + dat[(int)(i/(sizeof(BYTE)*8.))] |= j; + } + + inline BOOL dimensiona(__int64 n) + { + dat.n = 0; + int nn = (int)(0.5+n/(sizeof(BYTE)*8.)); + if(!(dat+=nn)) + return FALSE; + dat.n = nn; + return TRUE; + } + inline void setAll(BOOL v) + { + BYTE j = 0; + if(v) + j =~j; + memset(dat.ptr, j, dat.n*sizeof(BYTE)); + } +}; +//************************************************************************************* +class UTILES_EXPORT DijkstraUtiles +{ +public: + static BOOL dijkstra_ang_inv_ok(CmapMatFloat &costes, Djkt_ang_ady *angs, int n, int fin, Djkt_nodo **nodos, FlagsArray *visto_ang_); + static double ruta_dj_inv_ok(int id_ini, int *secu, Djkt_nodo *nodos, int nmax, int *n); + static double ruta_dj_inv(int id_ini, int *secu, Djkt_nodo *nodos, int nmax, int *n); +}; + +//************************************************************************************* +/** +* Clase de manejo de archivos de nodos djtra +* cada archivo tiene un numero de bloques o array de nodos de longitud fija "nnod" +*/ +//estructura cabecera de archivo +typedef struct Head_dj_arch +{ + int version; //version del archivo + int nn; //numero de nodos por bloque + int nb; //numero de bloques del dj + int max_conex; //maximo de conexiones por nodo + +}Head_dj_arch; +#define VERSION_DJ_ARCHI 100 +#define MAX_CONEX_DJ_ARCHI 16 + +class UTILES_EXPORT InfoIndice +{ +public: + virtual int get(int iamb, int iextremo) = 0;//da del ambito iamb el indice a inicio o a fin //si iextremo es o o 1 +}; + +class UTILES_EXPORT Cdijkstra_arch +{ +public: + char extension[16];//extension de archivos + char path[MAX_PATH];//nombre sin extension + Head_dj_arch hd;//cabecera de archivo + int sizn;//tamaño en BYTES de cada nodo + BOOL salta_ids_padres; + //int flags;//0x1-->modo escritura 0x2-->modo lectura + //info de distancias ambitos + float *dis;//distancia de un nodo a otro (matriz de nnod*nnod) + int nod_amb;//nodos por ambito + int nambi;//numero de ambitos + int nnod;//numero de nodos por fila + int id_instal;//fila planta + int id_plan;//fila instal + int nod_instal;//nodo instalacion + int nod_plan;//nodo planta + int tip_ambitos; + + InfoIndice* ia;//puntero a info asoc + + //funciones-------------------------------------------------------------------------- + Cdijkstra_arch(); + ~Cdijkstra_arch(); + + BOOL inicia(char* path_arch, BOOL nuevo=FALSE, BOOL borra = TRUE, int n_nod=0, int max_conex=MAX_CONEX_DJ_ARCHI);//si nuevo -> crea vacio + BOOL add_b(Djkt_nodo* blq, int iref, int inod, BOOL pon_inf=FALSE);//añade un bloque a el archivo + BOOL inicia_inf_amb(InfoIndice* ina, int namb,int tip_amb, int id_instal=-1, int id_plan=-1); + void pon_info_amb(Djkt_nodo* nodos, int iref,int ib); + Djkt_nodo* get_b(int iref, int ibloq, Djkt_nodo* buf=NULL);//develve el bloque ibloq-esimo + float dame_dis(int aorig,int norig, int ades, int n_des); + + Djkt_nodo* dame_buf_nodos(BOOL angulos=FALSE ); + void libera_buf(Djkt_nodo* buf ); + BOOL graba_dis(int id); + BOOL lee_dis(); +}; +#endif \ No newline at end of file diff --git a/includes/Utiles/Fdbf.h b/includes/Utiles/Fdbf.h new file mode 100644 index 0000000..94a7eef --- /dev/null +++ b/includes/Utiles/Fdbf.h @@ -0,0 +1,184 @@ +#pragma once +#ifndef Fdbf_H +#define Fdbf_H +#include "base_head.h" +#include "b_file.h" +#include "garray.h" +#pragma pack(1) + +typedef struct Hdr_dbf +{ + BYTE ver,year,mes,dia; // cuatro primeros bytes + long nrec; // nº de records (filas) + short nb_cab; // nº de bytes de la cabecera + short nb_rec; // nº de bytes de cada record + BYTE res[20]; +} Hdr_dbf; + +typedef struct Fld_dbf +{ + char nombre[11]; // nombre del campo + BYTE tipo; // tipo de campo + // C caracter + // N número + // L lógico (Y/N,T/F, y mas) + // D fecha (YYYYMMDD) + // F float, double + BYTE res1[4]; + BYTE nb; // nº de bytes del campo + //Nuevo elena 201709 + union + { + BYTE res2[15]; + struct{ + + + BYTE nd; //nº de decimales + BYTE res2_[14]; + }; + }; +} Fld_dbf; + +#pragma pack(8) + +#define DBF_TYPE_DATA_STR 'C' +#define DBF_TYPE_DATA_I64 'D' +#define DBF_TYPE_DATA_D 'F' +#define DBF_TYPE_DATA_BOOL 'L' +#define DBF_TYPE_DATA_BIN 'M' +#define DBF_TYPE_DATA_I 'N' + +//clase base de dbf------------------------------------- +class UTILES_EXPORT Fdbf +{ + Hdr_dbf head; + Cgarraycolm; + Cgarray buf;//buffer de fila + Cgarray buf2;//buffer auxi + + CgarrayiniCol;//indice a el bite deonde empieza la columna iesima dentro de una fila + Cb_file *f; + int nReadRow;//numero de filas leidas actualmente +public: + Fdbf(void); + ~Fdbf(void); + + //funciones de lectura + bool lee( Cb_file *file); + int leeNexRow();//devuelve 1 si ok 0 si no mas -1 si error + + double getD(int ncol); + int getI(int ncol); + char* getStr(int ncol); + __int64 getI64(int ncol); + char* get(int ncol);//devuelve buffer tal cual + + BYTE getType(int ncol); + char* getName(int ncol); + int findCol(char *name); + + int getSize(int ncol); + int getNrow(); + int getNcolm(); + //funciones de escritura + bool set(int ncol, int nRow, Cb_file *file); + bool setCol(int icol, char *name, BYTE type, int size, int ndecimals=0); + + bool addVal(int icol, int v); + bool addVal(int icol, double v); + bool addVal(int icol, __int64 v); + bool addVal(int icol, char* v); + bool addVal(int icol, void* v); + bool finRow(); + +private: + bool bufMem(int ncol); + bool iniciaRecords(); +}; + +//clase lisener de lectura +class UTILES_EXPORT ListenerDbf_W +{ +public: + virtual bool DbfSet(int nrow, int ncolm){return true;} + virtual bool DbfSetColm(char* name, BYTE type, int size){return true;} + virtual bool DbfaddVal(int icol, int v){return true;} + virtual bool DbfaddVal(int icol, double v){return true;} + virtual bool DbfaddVal(int icol, __int64 v){return true;} + virtual bool DbfaddVal(int icol, char* v){return true;} + virtual bool DbfaddVal(int icol, void* v){return true;} + virtual bool DbfFinRow(){return true;} + virtual bool DbfFinR(){return true;} + +}; +//clase lisener de escritura +class UTILES_EXPORT ListenerDbf_R +{ +public: + virtual bool DbfGet(int *nrow, int *ncolm){return false;} + virtual bool DbfGetColm(int icol, char* name, BYTE *type, int *size, int*ndecimal){return false;} + virtual bool DbfGetVal(int irow, int icol, int* v){return false;} + virtual bool DbfGetVal(int irow, int icol, double* v){return false;} + virtual bool DbfGetVal(int irow, int icol, __int64* v){return false;} + virtual bool DbfGetVal(int irow, int icol, char** v){return false;} + virtual bool DbfGetVal(int irow, int icol, void** v){return false;} + virtual bool DbfFinW(){return false;} + +}; + + +//clase manager dbf------------------------- +class UTILES_EXPORT ManagerDbf +{ +public: + static bool leer(Cb_file *file, ListenerDbf_W* lr); + static bool grabar(Cb_file *file, ListenerDbf_R* lw); + + static bool leer(char* file, ListenerDbf_W* lr); + static bool grabar(char* file, ListenerDbf_R* lw); +}; + +#endif +/* +ejemplo de uso-------------------------------- +escritura--------- +if(!f.abre("d:\\temp\\p2.dbf",2,true)) +error =true; +if(!dbf.set(3,5,&f)) +error = true; +if(!dbf.setCol(0,"id",DBF_TYPE_DATA_I,10)) +error = true; +if(!dbf.setCol(1,"idf",DBF_TYPE_DATA_D,10,3)) +error = true; +if(!dbf.setCol(2,"str",DBF_TYPE_DATA_STR,128)) +error = true; +for(int i =0; i<5; i++) +{ +if(!dbf.addVal(0,i)) +error = true; +if(!dbf.addVal(1,i+(i*1./10))) +error = true; +if(!dbf.addVal(2,"holaHolita")) +error = true; +if(!dbf.finRow()) +error = true; +} +f.cierra(); +//lectura +if(!f.abre("d:\\temp\\p2.dbf",1)) +error =true; +if(!dbf.lee(&f)) +error = true; +idd =dbf.leeNexRow(); +while(idd ==1) +{ +int ii = dbf.getI(0); +double d= dbf.getD(1); +char* ss = dbf.getStr(2); + +ii++; +d++; +ss[0]=0; +idd =dbf.leeNexRow(); +} +*/ \ No newline at end of file diff --git a/includes/Utiles/GdataTable.h b/includes/Utiles/GdataTable.h new file mode 100644 index 0000000..8c472f4 --- /dev/null +++ b/includes/Utiles/GdataTable.h @@ -0,0 +1,73 @@ +#pragma once +#ifndef GdataTable_h +#define GdataTable_h +//tabla de datos generica +//tabla con nombre de columnas +#include "base_head.h" +#include "garray.h" +#include "StrArray.h" +class UTILES_EXPORT GdataTableColum +{ +public: + int type;//tipo de dato + int nb;//numero de bytes de informacion + int flags; +}; + +class UTILES_EXPORT GdataTable +{ + Cgarraybuf; //array de Garray de datos + Cgarraycolm; //datos de columnas + StrArray colmName; //nombre de columnas + +public: + enum TypedataTable + { + Tndef=0, + Tbool, + Tint, + Tdouble, + Tint64, + Tstring, + Tbin, + Tntip + }; + GdataTable(void); + ~GdataTable(void); + + //funciones de lectura y set------------ + int getType(int icol); + int getInd(char* colName); + int nRow(); + int nColm(); + int getSize(int icol); + int getSizeASCII(int icol); + + char* getName(int icol); + int* getI(int row, int colm); + __int64* getI64(int row, int colm); + double* getD(int row, int colm); + char* getS(int row, int colm); + void* getBin(int row, int colm); + bool* getBool(int row, int col); + + void* get(int row, int colm); + //funciones de modificacion------------- + + //adicionar----------------------------- + bool addColm(char* name, int type, int size=0); + bool addRow(int nrow); + bool addMemRow(int nrow); + //borrado------------------------------- + void delAllRow();//borra todas las filas + void delAll();//borra todo + + void removeRow(int i); + void removeColm(int i); + + //ajusta memoria + void clear(); + //funciones auxiliares-------------------- +private: +}; +#endif \ No newline at end of file diff --git a/includes/Utiles/GeometryFunction.h b/includes/Utiles/GeometryFunction.h new file mode 100644 index 0000000..90095c8 --- /dev/null +++ b/includes/Utiles/GeometryFunction.h @@ -0,0 +1,78 @@ +#pragma once +#ifndef GeometriFunction_h +#define GeometriFunction_h +#include "base_head.h" +#include "cartoBaseDef.h" +#include "garray.h" + +class UTILES_EXPORT GeometryFunction +{ +public: + //distancia entre 2 ptos + static double Dist2d(double*p1, double*p2); + //longitud de la linea + static double LongLine2d(SetPtsR *line); + //distancia de un punto p a una linea infinita de puntos l1 y l2 + static double Dpline(double* l1, double *l2, double *p, double *lamb = 0); + //distancia de punto p a segmento s1-s2 + static double DpSeg(double* s1, double *s2, double *p, double *lamb = 0); + //interseccion entre lineas (formada por l11-l12) a otra linea (formada por l21-l22) + static double* intersecLine(double* l11, double *l12, double* l21, double *l22, double *p_inters); + //distancia entre linea (l1-l2)y segmento(s1,s2) + static double DLineSeg(double* l1, double *l2, double* s1, double *s2, double *lamdl,double *lambs, bool*paralelos ); + + //distancia entre linea (l1-l2)y segmento(s1,s2) + static double DsegSeg(double* s11, double *s12, double* s21, double *s22, double *lamd1,double *lamb2); + //distancia de polilinea a segmento + static double DplineSeg(SetPtsR* line1, double* s1, double *s2,int *n=NULL, double *lamd1=NULL,double *lamb2=NULL); + + + //calcula coordenadas minimas y maximas + static void CompMima(double dst[2][3], SetPtsR* pts); + //calcula envoltura convexa + static Cgarray* EnvConvex(SetPtsR* pts, Cgarray* dst); + //distancia de un punto a una linea + static double DisPtoLine(SetPtsR* line, double*p, int* idpto=NULL, double *lamb=NULL); + //distancia media entre dos líneas + static double DisMedLines( SetPtsR* line1, SetPtsR* line2, double *desv=NULL); + static double DisMedLines( SetPtsR* line1, SetPtsR* line2, double l_avan, double *desv=NULL); + //parte una linea en 2 + static bool DivLine(SetPtsR* linesrc, SetPtsW* ldst1, SetPtsW* ldst2, double dis); + //dado el ip y el lamb da la distancia desde el principio de la linea + static double DisInLine(SetPtsR* linesrc, int ip, double lamb); + //dado el ip y el lamb da la distancia desde el punto contenido en la línea + static double *PtInLine( SetPtsR* linesrc, int ip, double lamb , double *pp ); + //devuelve los nptos primeros puntos de line, equiespaciados dis + //si avanza, los coge del principio, si no, del final + static SetPtsW *GetNPrimePtos(SetPtsR* line, SetPtsW *ldst, int nptos, double dis, BOOL avanza); + + //divide la linea en partes equidistantes + static bool DivLine(SetPtsR* line, SetPtsWBuilder *manager, double dis); + + //devuelve el punto que esta en la polilinea a una distancia dist + static double* GetPto(SetPtsR* line, double dis, double *dst, double *distTot = NULL); + + static double ang_vect_ptos(double (*ptos1)[][3], double (*ptos2)[][3]); + + //devuelve el angulo que forman los 2 vectores + static double AngVect(double v1[2], double v2[2]); + //dice si el punto p esta a la derecha de la linea que forman los puntos ip1 y ip2 + static bool IsDer(SetPtsR* ptos, double *p, int ip1, int ip2); + static double ProdEscalar(SetPtsR* line1, SetPtsR* line2); + + //funcion auxiliar potencia + static inline double Poten(double bas, int exp = 2) + { + if(exp<=0) + return 0; + double res = bas; + while(exp>1) + { + res = res * bas; + exp--; + } + return res; + } +}; + +#endif \ No newline at end of file diff --git a/includes/Utiles/IaDataTable.h b/includes/Utiles/IaDataTable.h new file mode 100644 index 0000000..6199b1d --- /dev/null +++ b/includes/Utiles/IaDataTable.h @@ -0,0 +1,45 @@ +#pragma once + +#ifndef IaDataTable_h +#define IaDataTable_h +#include "gdatatable.h" +#include "base_head.h" +#include "CartoBaseDef.h" +#include +class CartoBase; +//tabla de datos para albergar informacion asiciada generica (diseñada para el cartobase) +class UTILES_EXPORT IaDataTable : + public GdataTable, public DataIaCartoBase +{ + std::map RefIndex;//indexado por referencias; + std::map rowIndex;//indexado por filas; + CartoBase* _cb; + int auxnrow,auxcolm,auxref,auxc; +public: + IaDataTable(void); + ~IaDataTable(void); + + virtual void* IaGet( int refEnt ); + virtual void CBSet( CartoBase* cb ); + virtual void IaRemove( int refEnt ); + virtual void IaRemoveAll(); + virtual void IaAdd( int refEnt ); + virtual bool IaSet( int nrow, int ncolm ); + virtual bool IaSetColm( int icol, char* name, BYTE type, int size ); + virtual bool IaAddVal( int refEnt, int icol, int v ); + virtual bool IaAddVal( int refEnt, int icol, double v ); + virtual bool IaAddVal( int refEnt, int icol, __int64 v ); + virtual bool IaAddVal( int refEnt, int icol, char* v ); + virtual bool IaAddVal( int refEnt, int icol, void* v ); + virtual bool IaFinRow( int refEnt ); + virtual bool IaFinR(); + virtual bool IaGetSize( int *ncolm ); + virtual bool IaGetColm( int icol, char* name, BYTE *type, int *size, int*ndecimal ); + virtual bool IaGetVal( int refEnt, int icol, int* v ); + virtual bool IaGetVal( int refEnt, int icol, double* v ); + virtual bool IaGetVal( int refEnt, int icol, __int64* v ); + virtual bool IaGetVal( int refEnt, int icol, char** v ); + virtual bool IaGetVal( int refEnt, int icol, void** v ); + virtual bool IaFinW(); +}; +#endif \ No newline at end of file diff --git a/includes/Utiles/ManagerDbfGdataTable.h b/includes/Utiles/ManagerDbfGdataTable.h new file mode 100644 index 0000000..020c3bb --- /dev/null +++ b/includes/Utiles/ManagerDbfGdataTable.h @@ -0,0 +1,50 @@ +#pragma once + +#ifndef ManagerDbfGdataTable_H +#define ManagerDbfGdataTable_H + +#include "base_head.h" +#include "Fdbf.h" + +class IAddColDbf +{ +public: + virtual void setData(int i, void *data)=0; +}; +class GdataTable; +class UTILES_EXPORT ManagerDbfGdataTable: public ListenerDbf_W, public ListenerDbf_R +{ + + GdataTable *_dt; + int _nrow; + int _ncolm; + public: + ManagerDbfGdataTable(void); + ~ManagerDbfGdataTable(void); + + bool LeeDbf(char* path, GdataTable *dt); + bool grabaDbf(char* path, GdataTable *dt); + bool AddCol( char* path, char* name, BYTE type,IAddColDbf *dt, int size=0); + + //funciones de herencia---------------------------------------- + //LisenerDbf_R------------------------------------------------- + virtual bool DbfSet( int nrow, int ncolm ); + virtual bool DbfSetColm( char* name, BYTE type, int size ); + virtual bool DbfaddVal( int icol, int v ); + virtual bool DbfaddVal( int icol, double v ); + virtual bool DbfaddVal( int icol, __int64 v ); + virtual bool DbfaddVal( int icol, char* v ); + virtual bool DbfaddVal( int icol, void* v ); + virtual bool DbfFinRow(); + virtual bool DbfFinR(); + //LisenerDbf_W---------------------------------------------------- + virtual bool DbfGet( int *nrow, int *ncolm ); + virtual bool DbfGetColm(int icol, char* name, BYTE *type, int *size, int*ndecimal ); + virtual bool DbfGetVal(int irow, int icol, int* v ); + virtual bool DbfGetVal(int irow, int icol, double* v ); + virtual bool DbfGetVal(int irow, int icol, __int64* v ); + virtual bool DbfGetVal(int irow, int icol, char** v ); + virtual bool DbfGetVal(int irow, int icol, void** v ); + virtual bool DbfFinW(); +}; +#endif \ No newline at end of file diff --git a/includes/Utiles/Matrix2d.h b/includes/Utiles/Matrix2d.h new file mode 100644 index 0000000..126a5b3 --- /dev/null +++ b/includes/Utiles/Matrix2d.h @@ -0,0 +1,104 @@ + +#pragma once + +#ifndef Matrix2d_h +#define Matrix2d_H + +#include "b_file.h" +#include "garray.h" +//matiz de clases genericas de 2 dimensiones +template +class ComClasFunction +{ +public: + virtual Tc comp(Tc a, Tc b) = 0; +}; +template +class Matrix2d +{ + Cgarray dat; + int ysize; +public: + Matrix2d() + { + ysize = 0; + } + bool inline inicia(int xmax, int ymax) + { + ysize = ymax; + dat.borra(); + if(!(dat+=xmax*ymax)) + return false; + dat.n = xmax*ymax; + return true; + } + + inline ClasVal* operator[](int x)//devuelve puntero a fila x + { + return dat.get(x*ysize); + } + + //******************************************************************************************************* + + inline bool graba( char* path ) + { + Cb_file file; + if(!file.abre(path,2,TRUE)) + return false; + if(!file.escribe(&ysize, sizeof(ysize))) + return false; + if(!dat.graba(&file)) + return false; + return true; + } + inline bool lee( char* path ) + { + Cb_file file; + if(!file.abre(path,1,FALSE,TRUE)) + return false; + if(!file.lee(&ysize, sizeof(ysize))) + return false; + if(!dat.leer(&file)) + return false; + return true; + } + inline void clear() + { + dat.borra(); + } + inline bool fileMix( char* path, ComClasFunction *ccomp ) + { + if(ysize<=0) + return false; + Cgarray fdat; + int yfile, xfile; + Cb_file file; + if(!file.abre(path,1,FALSE,TRUE)) + return false; + //lee tamaño matriz + if(!file.lee(&yfile, sizeof(yfile))) + return false; + if(!file.lee(&xfile, sizeof(xfile))) + return false; + xfile = xfile/yfile; + //inicia buffer + if(!(fdat+=yfile)) + return false; + //calcula numero de bytes a leer y margenes de matriz + int nb = sizeof(ClasVal)*yfile; + xfile = min(xfile, dat.n/ysize); + yfile = min(yfile, ysize); + for(int x = 0 ; xcomp(dat.get(x*ysize)[y], fdat[y]); + } + + return true; + } +}; +#endif \ No newline at end of file diff --git a/includes/Utiles/StrArray.h b/includes/Utiles/StrArray.h new file mode 100644 index 0000000..df3a0d6 --- /dev/null +++ b/includes/Utiles/StrArray.h @@ -0,0 +1,36 @@ +#pragma once +#ifndef StrArray_h +#define StrArray_H + +#include "base_head.h" +class UTILES_EXPORT StrArray +{ + //variables------------------------------ + int incremento_char; + int incremento_str; +public: + char *str; + int n_str;//numero de chars + int m_str;//memoria reser + int (*ind)[]; + int n_i;//numero de str + int m_i;//memoria reser + //constructor---------------------------- +public: + StrArray(void); + ~StrArray(void); + //funciones------------------------------ + char* get(int i);//da string i + void add(char*c);//mete str + void add(char*c, int ncharReser);//mete str y reserva en memoria un minimo de ncharReser; + void add( StrArray* st );//mete un array entero de caracteres + void borra(int i);//borra el elemento iesimo + int size();//da numero de str + void borra();//borra todo + void compacta();//reduce al minimo la memoria necesaria para comtener la informacion + StrArray* filtra(StrArray*buf, char *filter); + //funciones aux------------------------- +private: + void cuida_memoria(int n,int ni=1);//asegura tener memoria para un str mas +}; +#endif \ No newline at end of file diff --git a/includes/Utiles/TaskProcess.h b/includes/Utiles/TaskProcess.h new file mode 100644 index 0000000..3009a32 --- /dev/null +++ b/includes/Utiles/TaskProcess.h @@ -0,0 +1,32 @@ +#pragma once +#include +#include "th.h" +#ifndef TaskProcess_h +#define TaskProcess_h +/* +Tarea delegada en otro proceso(normalmente en programa de consola) +definir en funcion override run la tarea +*/ +class Csock_cl; +class UTILES_EXPORT TaskProcess: public Cth +{ + Csock_cl *sc; +public: + bool pirate;//indica que hay que irse + + TaskProcess(void); + ~TaskProcess(void); + bool initTask(char* url, int port, __int64 timer); + bool envia(void * buf, int nb);//envia buffer al proceso principal + void* recibe(int *nb );//recibe del proceso principal nb da el numero de bytes recib + //overrides---------------------------------- + void cancela();//cancela tarea; + virtual void preTask()=0; + virtual void inTask()=0; + virtual void postTask()=0; + + virtual bool conecta(char* url, int port); + virtual void desconecta(); + +}; +#endif \ No newline at end of file diff --git a/includes/Utiles/_app.h b/includes/Utiles/_app.h new file mode 100644 index 0000000..76cfdcb --- /dev/null +++ b/includes/Utiles/_app.h @@ -0,0 +1,36 @@ +#pragma once +#include "base_head.h" +#include +#include "_error.h" +#include "dir_manager.h" +#include "_log.h" + +class UTILES_EXPORT C_app //clase aplicacion---- +{ + static C_app *p_app;//puntero a la clase aplicacion + +public: + //variables globales----------------------- + Cdir_manager archi;//manager de archivos + C_log log;//clase de trazas (log) + C_error er;//clase de manejo de errores; + //variables de thread; + BOOL pirate;//indica a los thread que hay que irse + long nth;//indica el numero de thread que hay activos + C_app(void); + virtual ~C_app(void); + //funciones y overrides------------ + static C_app* GetApp(); + BOOL inicio(); + int fin(); + void suma_th();//añade al conteo de thread +1 + void resta_th();//disminulle el conteo de thread en 1 + virtual BOOL on_inicia();//funcion inicia lo necesario para el programa + virtual BOOL on_cierra();//funcion que se ejecuta al final del todo antes de cerrar + + virtual void cierra();//fuerza el fin de la aplicacion; +protected: + +}; + + diff --git a/includes/Utiles/_error.h b/includes/Utiles/_error.h new file mode 100644 index 0000000..addbae9 --- /dev/null +++ b/includes/Utiles/_error.h @@ -0,0 +1,19 @@ +#pragma once +#include "base_head.h" + +class UTILES_EXPORT C_error +{ +public: + //variables----------------------------- + char modulo[32];//parte del programa que causa el error + char msg[256];//mensaje de error + int tipo;//codigo de error + //constructor--------------------------- + C_error(void); + virtual ~C_error(void); + //funciones----------------------------- + void pon(char *mod, char *mens, int tip=-1);//pone error propio + void pon_win(char *modulo);//pone error windows + void aclara(char *mens);//pone aclaracion + void limpia();//limpia error +}; diff --git a/includes/Utiles/_log.h b/includes/Utiles/_log.h new file mode 100644 index 0000000..0f56f96 --- /dev/null +++ b/includes/Utiles/_log.h @@ -0,0 +1,42 @@ +#pragma once +#include "base_head.h" +#include "lock.h" +#include +typedef struct Msg_evento_log +{ + int id_e; + char nivel[64]; + char mensage[256]; + __time64_t tiempo; +}Msg_evento_log; +class C_error; +class UTILES_EXPORT C_escucha_log//clase para escuchar eventos de log +{ +public: + virtual void log_ext(__time64_t tiemp, char *modulo, char *fmt)=0; +}; +class UTILES_EXPORT C_log//clase para logear eventos +{ +public: + //variavles----------------------------------------- + HFILE archivo_log; + int nb; + Clock cerrojo; + C_escucha_log *l_lisener;//puntero a escucha actual + //BOOL log_consola; + char nombre[32]; + char path[256]; + + void (*log_ext)(__time64_t tiemp, char *modulo, char *fmt);//funcion de log externa + C_log(void); + ~C_log(void); + //funcion------------------------------------------- + void loguea(__time64_t tiemp, char *modulo, char *fmt);//añade un suceso + void loguea(char *modulo, char *fmt);//añade suceso actual + void loguea(C_error *er);//añade el error como suceso + static void log(char *modulo, char *fmt,...);//funcion estatica para loguear + static void log( C_error *er ); + //static void log(std::string &mod, std::string &msg); + +}; + diff --git a/includes/Utiles/_proceso.h b/includes/Utiles/_proceso.h new file mode 100644 index 0000000..9451101 --- /dev/null +++ b/includes/Utiles/_proceso.h @@ -0,0 +1,28 @@ +#pragma once +#include "base_head.h" + +const DWORD MS_VC_EXCEPTION_PROCESO_UTILES=0x406D1388; + +#pragma pack(push,8) +typedef struct tagTHREADNAME_INFO +{ + DWORD dwType; // Must be 0x1000. + LPCSTR szName; // Pointer to name (in user addr space). + DWORD dwThreadID; // Thread ID (-1=caller thread). + DWORD dwFlags; // Reserved for future use, must be zero. +} THREADNAME_INFO; +#pragma pack(pop) + +class UTILES_EXPORT C_proceso//proceso base +{ +public: + C_proceso(void); + char nombre[32]; + CWinThread * m_thread; + virtual ~C_proceso(void); + BOOL lanza(char *nombre=NULL);//lanzar thread + virtual void run();//funcion que hace el thread + void join();//espera al thread +}; +UINT main_c_proceso(LPVOID pp); +UTILES_EXPORT void SetThreadName( DWORD dwThreadID, char* threadName); \ No newline at end of file diff --git a/includes/Utiles/b_file.h b/includes/Utiles/b_file.h new file mode 100644 index 0000000..7926eed --- /dev/null +++ b/includes/Utiles/b_file.h @@ -0,0 +1,175 @@ +#pragma once +#include "base_head.h" +#include "_error.h" +#include "utiles_def.h" +class UTILES_EXPORT Cb_file: public IdataTransfer//manejo de archivos binarios +{ +private: + HANDLE hfile;//hanled del archivo + LARGE_INTEGER li;//se usa para dividir enteros de 64 + DWORD dw;//bites movidos y respuestas al escribir +public: + C_error *er; + + Cb_file(void); + ~Cb_file(void); + //****************************************************************************************************************** + //funciones-------------------------------------------------------------------- + //****************************************************************************************************************** + inline BOOL abierto() + { + return hfile != INVALID_HANDLE_VALUE; + }; + //****************************************************************************************************************** + BOOL abre(char* path,int modo, BOOL sobre_escri=FALSE, BOOL shared=FALSE);//modo 1 lectura modo 2 escritura modo 3 ambos + //****************************************************************************************************************** + inline void cierra()//cierra archivo; + { + if (hfile != INVALID_HANDLE_VALUE) + { + CloseHandle(hfile); + hfile=INVALID_HANDLE_VALUE; + } + } + //****************************************************************************************************************** + QWORD size();//te devuelve el tamaño del archivo en bytes + //****************************************************************************************************************** + inline BOOL lee(void* buf,int nb)//lee un numero de bites y lo pone en buf + { + if (!ReadFile(hfile, (LPSTR) buf ,nb,&dw,NULL)) + { + if (er) + er->pon_win("Cb_file"); + //cierra--------------------- + if (hfile != INVALID_HANDLE_VALUE) + { + CloseHandle(hfile); + hfile=INVALID_HANDLE_VALUE; + } + //--------------------------- + return FALSE; + } + return TRUE; + } + //****************************************************************************************************************** + inline BOOL escribe(void* buf,int nb)//escribe numero de bites + { + if (!WriteFile(hfile, (LPSTR) buf ,nb,&dw,NULL)) + { + if (er) + er->pon_win("Cb_file"); + //cierra--------------------- + if (hfile != INVALID_HANDLE_VALUE) + { + CloseHandle(hfile); + hfile=INVALID_HANDLE_VALUE; + } + //--------------------------- + return FALSE; + } + return TRUE; + } + //****************************************************************************************************************** + inline BOOL irAfin()//va a la posicion del final del archivo + { + dw=SetFilePointer(hfile,0,NULL,FILE_END); + if(dw==INVALID_SET_FILE_POINTER) + { + if (er) + er->pon_win("Cb_file"); + //cierra--------------------- + if (hfile != INVALID_HANDLE_VALUE) + { + CloseHandle(hfile); + hfile=INVALID_HANDLE_VALUE; + } + //--------------------------- + return FALSE; + } + return TRUE; + } + //****************************************************************************************************************** + BOOL irAini(int nb=0)//va al inicio del archivo + nb bytes; + { + + dw=SetFilePointer(hfile,nb,NULL,FILE_BEGIN); + if(dw==INVALID_SET_FILE_POINTER) + { + if (er) + er->pon_win("Cb_file"); + //cierra--------------------- + if (hfile != INVALID_HANDLE_VALUE) + { + CloseHandle(hfile); + hfile=INVALID_HANDLE_VALUE; + } + //--------------------------- + return FALSE; + } + return TRUE; + } + //****************************************************************************************************************** + BOOL irA(int nb=0)//salta nbites; + { + + dw=SetFilePointer(hfile,nb,NULL,FILE_CURRENT); + if(dw==INVALID_SET_FILE_POINTER) + { + if (er) + er->pon_win("Cb_file"); + //cierra--------------------- + if (hfile != INVALID_HANDLE_VALUE) + { + CloseHandle(hfile); + hfile=INVALID_HANDLE_VALUE; + } + //--------------------------- + return FALSE; + } + return TRUE; + } + //****************************************************************************************************************** + inline BOOL irAini( QWORD nb)//entero de 64 bytes + { + li.QuadPart = nb; + dw=SetFilePointer(hfile,li.LowPart,&li.HighPart,FILE_BEGIN); + if(dw==INVALID_SET_FILE_POINTER) + { + if (er) + er->pon_win("Cb_file"); + //cierra--------------------- + if (hfile != INVALID_HANDLE_VALUE) + { + CloseHandle(hfile); + hfile=INVALID_HANDLE_VALUE; + } + //--------------------------- + return FALSE; + } + return TRUE; + } + + virtual __int64 getNB_it() + { + return size(); + } + + virtual __int64 getNext_it( void* buf,__int64 nb ) + { + if(lee(buf,(int)nb)) + return nb; + return -1; + } + + virtual bool setPosition_it( __int64 nb ) + { + return irAini((int)nb) ==TRUE; + } + + virtual bool set_it( void* buf, __int64 nb ) + { + return escribe(buf,(int)nb) == TRUE; + } + //****************************************************************************************************************** + +}; diff --git a/includes/Utiles/base_head.h b/includes/Utiles/base_head.h new file mode 100644 index 0000000..c5648ce --- /dev/null +++ b/includes/Utiles/base_head.h @@ -0,0 +1,22 @@ +#pragma once + +#ifndef UTILES_EXPORT +#ifdef _WINDLL +#define UTILES_EXPORT __declspec(dllexport) +#else +#define UTILES_EXPORT __declspec(dllimport) +#endif +#endif + +#include +#ifndef UINT16_MAX +#define UINT16_MAX 0xffff +#endif +#ifdef _WIN64 +typedef __int64 ssize_t; +#else +typedef _w64 int ssize_t; + +#endif + +#pragma warning(disable:4996) diff --git a/includes/Utiles/dir_manager.h b/includes/Utiles/dir_manager.h new file mode 100644 index 0000000..b89f7ec --- /dev/null +++ b/includes/Utiles/dir_manager.h @@ -0,0 +1,43 @@ +#pragma once +#include "base_head.h" + +class C_error; +class StrArray; +class UTILES_EXPORT Cdir_manager//clase para manejar carpetas +{ +public: + + //carpetas------------------------------------------------------- + char dir_work[FILENAME_MAX]; + char dir_exe[FILENAME_MAX]; + char dir_log[FILENAME_MAX]; + char dir_datos[FILENAME_MAX]; + //archivos------------------------------------------------------- + char path_conf[FILENAME_MAX]; + //rutas de ejecucion--------------------------------------------- + char dir_ejecucion[FILENAME_MAX]; + char path_ejecutable[FILENAME_MAX]; + //funciones------------------------------------------------------ + Cdir_manager(void); + ~Cdir_manager(void); + //funciones------------------------------------------------------ + void absoluta(char *ruta); + void relativa(char *ruta); + + BOOL lee_reg(char* clave, C_error *er=NULL); + BOOL rellena_dirs_ejecucion(); + //funciones estaticas--------------------------------------- + static char* dir_anterior(char*dir);//da el directorio anterior + static char* nombre_archivo(char *path,char*nombre);//devuelve en nombre el nombre del archivo + static char* extension_archivo(char *path);//te da la extension de un path o de un nombre de archivo + static char* cambia_extension_archivo(char *path, char *pathDst, char *newext);//te da la extension de un path o de un nombre de archivo + static BOOL crea_dir(char *path);//asegura que existe los directorios indicados + static BOOL borra_archivos(char *paht, char *ext, BOOL recursivo = FALSE);//borra archivos de una extension dada, si ext es null borra todos + //funciones de listado----------- + static BOOL listar_elementos(char *dir,StrArray *files,StrArray *dirs,C_error *er=NULL);//dice los files y las dir dentro de un dir(no recursivo) + static BOOL lista_files(char *dir,StrArray *files,BOOL recursivo=FALSE,C_error *er=NULL,char *omite=NULL); + + static BOOL listar( char* dir,StrArray *files,StrArray *dirs=NULL,BOOL recursivo=FALSE,C_error *er=NULL,char *omite=NULL );//funcion generica de listar + //devuelve version de el archivo + static char* getVersionFile(char *path, char *buf);//buffer de 64 sobra +}; diff --git a/includes/Utiles/garray.h b/includes/Utiles/garray.h new file mode 100644 index 0000000..573257f --- /dev/null +++ b/includes/Utiles/garray.h @@ -0,0 +1,261 @@ + +#pragma once +#ifndef Cgarray_H +#define Cgarray_H + +#define GARRAY_INCREMENT 100 +#include "b_file.h" +//array generico--------------------------------- +/* +Clase para manejar arrays genericos de cualquier tipo de clase o estructura +*/ +template +class Cgarray +{ +public: + //variables---------------------------------------------------------------------------------- + int m; //cache del array + int n; //numero de elementos en array + int increment; //valor a incrementar en la cache + T* ptr; //array de elementos + //************************************************************** + //constructores------------------------------------------------------------------------------- + //************************************************************** + Cgarray() + { + m=0; + ptr=NULL; + n=0; + increment=GARRAY_INCREMENT; + }; + //************************************************************** + Cgarray(int cache)//constructor poniendo en memoria posiciones + { + m=cache; + ptr=(T*)malloc(sizeof(T)*m); + if (ptr) + memset(ptr,0,m * sizeof(T)); + else + m=0; + n=0; + increment=GARRAY_INCREMENT; + }; + //************************************************************** + ~Cgarray() + { + if (ptr) + free(ptr); + }; + //************************************************************** + //funciones----------------------------------------------------------------------------------- + //************************************************************** + inline T& operator[](int i)//da el elemento i-esimo por referencia + { + return ptr[i]; + }; + //************************************************************** + inline T* get(int i)//da el elemento i-esimo + { + return &ptr[i] ; + }; + //************************************************************** + inline void remove(int ini, int nelem = 1) + { + if(ini<0) + ini =0; + if(ini>=n || nelem<1) + return; + int fin = ini+nelem; + if(fin>=n) + { + n =ini; + return; + } + + memmove(&ptr[ini], &ptr[fin], (n-fin)*sizeof(T)); + n-=(fin-ini); + }; + //************************************************************** + inline BOOL operator+(T &e )//añade nuevo elemento + { + T*pp; + if (m0) + { + if (inc &e) //añade una lista entera + { + int inc=n+e.n-m; + T*pp; + if (inc>0) + { + if (inc *e) //añade una lista entera + { + int inc=n+e->n-m; + T*pp; + if (inc>0) + { + if (incptr,e.n*sizeof(T)); + n+=e->n; + return TRUE ; + };*/ + //************************************************************** + inline BOOL add(T *e, int ne) //añade una lista de elementos + { + int inc=n+ne-m; + if (!e || ne<=0) + return FALSE; + T*pp; + if (inc>0) + { + if (incescribe(&n,sizeof(n))) + return FALSE; + if(!file->escribe(ptr,n*sizeof(T))) + return FALSE; + return TRUE; + } + //************************************************************** + inline BOOL leer(Cb_file *file)//lee de archivo el array + { + int nn; + if(!file->lee(&nn,sizeof(n))) + return FALSE; + if( nn<=0 || !((*this)+=nn)) + return FALSE; + if(!file->lee(&ptr[n],nn*sizeof(T))) + return FALSE; + n+=nn; + return TRUE; + } + //************************************************************** +}; +#endif \ No newline at end of file diff --git a/includes/Utiles/gcola.h b/includes/Utiles/gcola.h new file mode 100644 index 0000000..15da222 --- /dev/null +++ b/includes/Utiles/gcola.h @@ -0,0 +1,141 @@ +#pragma once +#define GARRAY_INCREMENT 100 +//cola generico--------------------------------- +//+cosas por le final +//-por el inicio +template +struct Element_Cgcola +{ + T t; + Element_Cgcola *ant; + Element_Cgcola *sig; +}; +template +class Cgcola +{ +public: + //variables---------------------------------------------------------------------------------- + int n; //numero de elementos en array + Element_Cgcola *ini; //inicio del array + Element_Cgcola *fin; //fin del array + //************************************************************** + //constructores------------------------------------------------------------------------------- + //************************************************************** + Cgcola() + { + ini=fin=NULL; + n=0; + }; + //************************************************************** + ~Cgcola() + { + borra(); + }; + //************************************************************** + //funciones----------------------------------------------------------------------------------- + //************************************************************** + virtual inline T* operator++()//da puntero al ultimo elemento + { + if (fin) + return &fin->t; + return NULL; + + }; + //************************************************************** + virtual inline T* operator--()//da puntero al primero + { + if(ini) + return &ini->t; + return NULL; + }; + //************************************************************** + virtual inline BOOL operator+(T &e )//añade al final + { + if (fin) + { + fin->sig=(Element_Cgcola*)malloc(sizeof(Element_Cgcola)); + if (!fin->sig) + return FALSE; + fin->sig->ant=fin; + fin=fin->sig; + } + else + { + fin=(Element_Cgcola*)malloc(sizeof(Element_Cgcola)); + if (!fin) + return FALSE; + ini=fin; + fin->ant=NULL; + } + fin->t=e; + fin->sig=NULL; + n++; + return TRUE ; + }; + //************************************************************** + virtual inline BOOL operator-(T &e) //añade al principio + { + if (ini) + { + ini->ant=(Element_Cgcola*)malloc(sizeof(Element_Cgcola)); + if (!ini->ant) + return FALSE; + ini->ant->sig=ini; + ini=ini->ant; + } + else + { + ini=(Element_Cgcola*)malloc(sizeof(Element_Cgcola)); + if (!ini) + return FALSE; + fin=ini; + ini->sig=NULL; + } + ini->t=e; + ini->ant=NULL; + n++; + return TRUE ; + }; + //************************************************************** + virtual inline BOOL operator+=(T* e )//da el ultimo u lo elimina + { + if (!fin) + return FALSE; + *e=fin->t; + Element_Cgcola *el=fin; + fin=fin->ant; + fin->sig=NULL; + if (!fin) + ini=fin; + free(el); + n--; + return TRUE ; + }; + //************************************************************** + virtual inline BOOL operator-=(T* e )//da el primero y lo elimina + { + if (!ini) + return FALSE; + *e=ini->t; + Element_Cgcola *el=ini; + ini=ini->sig; + if (!ini) + fin=ini; + else + ini->ant=NULL; + free(el); + n--; + return TRUE ; + }; + //************************************************************** + virtual inline void borra()//libera la memoria del array + { + while(ini) + { + fin=ini->sig; + free(ini); + ini=fin; + } + } + //************************************************************** +}; \ No newline at end of file diff --git a/includes/Utiles/gcola_con.h b/includes/Utiles/gcola_con.h new file mode 100644 index 0000000..2e9dd26 --- /dev/null +++ b/includes/Utiles/gcola_con.h @@ -0,0 +1,118 @@ +#pragma once +#include "gcola.h" +#include "lock.h" +//cola concurrente para usar con multiples thread +template +class Cgcola_con : + public Cgcola +{ +public: + //variables-------------------------------------------------------------------------------- + Clock cerrojo;//interlock para protejer la cola + int modo;//modo 0 bloqueante, modo 1 no bloqueante + //funciones-------------------------------------------------------------------------------- + //************************************************************************* + Cgcola_con(void) + :Cgcola() + { + modo=0; + }; + //************************************************************************* + virtual ~Cgcola_con(void) + { + borra(); + }; + //************************************************************************* + //************************************************************************* + virtual inline T* operator++()//da puntero al ultimo elemento + { + T* res=NULL; + if (modo) + { + if(!cerrojo.puedo()) + return NULL; + } + else + cerrojo.entro(); + res= Cgcola::operator++(); + cerrojo.salgo(); + return res; + + }; + //************************************************************************* + virtual inline T* operator--()//da puntero al primero + { + T* res=NULL; + if (modo) + { + if(!cerrojo.puedo()) + return NULL; + } + else + cerrojo.entro(); + res= Cgcola::operator--(); + cerrojo.salgo(); + return res; + }; + //************************************************************************* + virtual inline BOOL operator+(T &e )//añade al final + { + BOOL res=FALSE; + if (modo) + { + if(!cerrojo.puedo()) + return FALSE; + } + else + cerrojo.entro(); + res= Cgcola::operator+(e); + cerrojo.salgo(); + return res; + }; + //************************************************************************* + virtual inline BOOL operator-(T &e) //añade al principio + { + BOOL res=FALSE; + if (modo) + { + if(!cerrojo.puedo()) + return FALSE; + } + else + cerrojo.entro(); + res= Cgcola::operator-(e); + cerrojo.salgo(); + return res; + }; + //************************************************************************* + virtual inline BOOL operator+=(T* e )//da el ultimo y lo elimina + { + BOOL res=FALSE; + if (modo) + { + if(!cerrojo.puedo()) + return FALSE; + } + else + cerrojo.entro(); + res= Cgcola::operator+=(e); + cerrojo.salgo(); + return res; + }; + //************************************************************************* + virtual inline BOOL operator-=(T* e )//da el primero y lo elimina + { + BOOL res=FALSE; + if (modo) + { + if(!cerrojo.puedo()) + return FALSE; + } + else + cerrojo.entro(); + res= Cgcola::operator-=(e); + cerrojo.salgo(); + return res; + }; + //************************************************************************* +}; diff --git a/includes/Utiles/ini_file.h b/includes/Utiles/ini_file.h new file mode 100644 index 0000000..0c2de1d --- /dev/null +++ b/includes/Utiles/ini_file.h @@ -0,0 +1,88 @@ +#pragma once +#include "base_head.h" +#include "StrArray.h" +#include "static_array.h" +#define INI_FILE_FLAGS_VACIO 0x0001 +#define MODULO_INI_FILE "Cini_file" +//estructuras necesarias------------------------------------------------------------------ +typedef struct Ini_file_props +{ + short flags; + int p;//propiedad + int v;//valor +}Ini_file_props; + +typedef struct Ini_file_grupo//cabecera base de la cumunicación +{ + int n; //indice a nombre + short flags; + Cstatic_array prop; + Ini_file_grupo() + { + inicia(); + n=0; + } + void inicia() + { + prop.n=prop.m=0; + prop.buf=NULL; + prop.z=sizeof(Ini_file_props); + prop.incremento=100; + } + Ini_file_props* get(int i)//da la propiedad i + { + return (Ini_file_props*) prop.get(i); + } + Ini_file_props* set_coun()//reserva para una propiedad mas y da el puntero + { + prop.reserva(); + prop.n++; + return (Ini_file_props*) &prop.buf[prop.z*(prop.n-1)]; + } +}Ini_file_grupo; + + +//------------------------------------------------------------------------------------------------------------ +class C_error; +class UTILES_EXPORT Cini_file +{ + //variables-------------------------- +private: + StrArray str; + Cstatic_array grupos; + BOOL borra_error; +public: + C_error *er; + + Cini_file(C_error* err=NULL); + ~Cini_file(void); + //funciones-------------------------- + BOOL lee(char *path_);//lee archivo ini y lo carga en memoria + + + int get_grupo(char* gr); + int geti_valor(int gr,char *pro);//devuelve el indice del str valor + + //funciones que dan el valor-------------- + char* get(int gr,char *pro);// valor en forma de char* + int get(int gr,char *pro, int def); + double get(int gr,char *pro, double def); + char* get( int gr,char *pro, char *def); + void dame_valor( int gr,char *pro, char* dst,char *def); + //funciones de escritura----------------- + void borra(); + BOOL guarda(char *path);//guarda ini cargado en memoria en un archivo; + int add_grupo(char *gr);//añade un grupo nuevo y da el indice + int add(int gr,char *pro,char *val);//añade valor de propiedad + + //sobrecarga escritura----------------- + int add(int gr,char *pro,int val);//añade valor de propiedad + int add(int gr,char *pro,double val);//añade valor de propiedad + //funciones aux------------------------ +private: + //funciones ayuda para leer + char* busca(char *st,char c);//busca en str el char c o el nulo + char* buscamos_grupo(char *st);//busca el siguiente grupo en str + char* busca_prop(char* st); + Ini_file_grupo* set_coun(); +}; diff --git a/includes/Utiles/lock.h b/includes/Utiles/lock.h new file mode 100644 index 0000000..a3036bd --- /dev/null +++ b/includes/Utiles/lock.h @@ -0,0 +1,29 @@ +#pragma once +#include "base_head.h" + +#define CLOCK_ESTADO_BLOQUEADO 1 +#define CLOCK_ESTADO_DESBLOQUEADO 0 + +class UTILES_EXPORT Clock//estructura para concurrencia +{ +public: + + long t_sleep;//tiempo de sleep en milisegundos + + Clock(void); + ~Clock(void); + + void entro();//pilla el cerrojo durmiendo si es necesario + void salgo();//libera el cerrojo + BOOL puedo();//intenta pillar el cerrojo, si ya estaba pillado devuelve false si no true + +private: + long volatile cerrojo;//variable volatile + long cliente;//id del thred que tiene el cerrojo + CRITICAL_SECTION cerrojo1; + int modo;//indica si usa cerrojo 0 o 1 + + + +}; +UTILES_EXPORT long lck_sum_atm(long *n,int i);//suma de manera atomica i a n \ No newline at end of file diff --git a/includes/Utiles/mapmatrix.h b/includes/Utiles/mapmatrix.h new file mode 100644 index 0000000..8daf54a --- /dev/null +++ b/includes/Utiles/mapmatrix.h @@ -0,0 +1,354 @@ +#pragma once +#ifndef CmapMat_H +#define CmapMat_H + +#include "stdafx.h" +#include +#include +#define VALNOEXIST_FLOAT (float) 1.e+30 +#define VALNOEXIST_INT (int) -1 +#include "garray.h" +#include "th.h" + +#pragma pack(8) +typedef struct HeadCostConj +{ + int ver; //versión + bool isVect; // vect o map + int n; //num de elems guardados +}HeadCostConj; +typedef struct HeadCostAng +{ + int ver; //versión + int n; //num de elems guardados +}HeadCostAng; +#pragma pack (1) +typedef struct MapDataFloat{ + int k; + float v; +}MapDataFloat; +typedef struct MapDataInt{ + int k; + int v; +}MapDataInt; +#pragma pack(16) +#define MAX_THREAD_LEE 8 +//matixFloat--------------------------------------------- +class UTILES_EXPORT CmapRowFloat +{ + +public: + //********************************* + //Variables + bool isVect; + int imin, imax; + std::map dat; + std::vector datv; + //********************************* + //Métodos + CmapRowFloat() + { + isVect = false; + imin=INT_MAX; + imax=INT_MIN; + } + ~CmapRowFloat(void) + { + } + //****************************************************** + inline void set(int i, float v) + { + + + if(isVect) + datv[i]=v; + else + { + if(v== VALNOEXIST_FLOAT) + return; + dat[i] = v; + if(iimax) + imax=i; + } + } + //****************************************************** + inline float operator[](int irow) + { + if(isVect) + return datv[irow]; + if(irow< imin || irow>imax) + return VALNOEXIST_FLOAT; + //si tiene esa clave la devuelve, si no, devuelve MAYUSCULO + std::map::iterator elem = dat.find(irow); + if(elem == dat.end()) + //no tiene la clave + return VALNOEXIST_FLOAT; + return elem->second; + } + inline void configVector(int ymax) + { + isVect = true; + dat.clear(); + + //datv.reserve(ymax); + datv.insert(datv.begin(),ymax,VALNOEXIST_FLOAT); + + bool inVector = false; + /*for (int i =0 ; i *bufer = NULL); + BOOL lee(int ic, char *path , char *ext, int ntot, BOOL mismosvect=TRUE, Cgarray *bufer = NULL); +}; +#define MAX_MEM_MAPFLOAT 1024.*1024.*300./sizeof(float) + +class UTILES_EXPORT CmapMatFloat +{ +public: + //********************************* + //Variables + std::vector dat; + + //********************************* + //Métodos + CmapMatFloat() + { + } + ~CmapMatFloat(void) + { + } + //****************************************************** + inline CmapRowFloat& operator[](int irow) + { + return dat[irow]; + } + + inline void set(int x, int y, float val) + { + if(val>= VALNOEXIST_FLOAT) + return; + + dat[x].set(y,val); + } + //ajusta los map a la memoria minima posible + inline void memAjust() + { + for(std::vector::iterator elem = dat.begin(); elem!= dat.end(); elem++) + { + elem->memAjust(); + } + } + inline void clear() + { + dat.clear(); + } + + //reparte los nvect disponibles entre los threads, poniendo las primeras filas de cada uno de vect + inline void inicializa(int xmax, int nthr, int nvect=-1) + { + dat.reserve(xmax); + bool inVector = false; + if(nvect<0) + nvect =(int)(MAX_MEM_MAPFLOAT/xmax); + + int vectthr=0,novecthr=0,iparc=0; + if(nvect=xmax) + dat[i].configVector(xmax); + else if(nvect>0) + { + if((i-iparc)=(vectthr+novecthr)) + iparc+=vectthr+novecthr; + } + } + } + BOOL lee(char *path, char *ext, BOOL mismosvect=TRUE); + BOOL leeThread( char *path, char *ext, int nthread, BOOL mismosvect/*=TRUE*/); +}; +class UTILES_EXPORT ThMapMatFloatLee: public Cth +{ +public: + CmapMatFloat *pclas; + int ini;//fila inicio + int fin;//fila fin + int ithr; + BOOL mal;//indica si ha ido bien + BOOL mismosvect; + char*path; + char*ext; + virtual void run(); +}; +class UTILES_EXPORT CmapRowInt +{ +public: + //********************************* + //Variables + std::map dat; + std::vector datv; + int imin, imax; + bool isVect; + //********************************* + //Métodos + CmapRowInt() + { + imin=INT_MAX; + imax=INT_MIN; + isVect = false; + } + ~CmapRowInt(void) + { + } + //****************************************************** + inline void set(int i, int v) + { + if(v== VALNOEXIST_INT) + return; + + if(isVect) + datv[i]=v; + else + dat[i] = v; + + if(iimax) + imax=i; + } + //****************************************************** + inline int operator[](int irow) + { + if(isVect) + return datv[irow]; + if(irow< imin || irow>imax) + return -1; + + //si tiene esa clave la devuelve, si no, devuelve MAYUSCULO + std::map::iterator elem = dat.find(irow); + if(elem == dat.end()) + //no tiene la clave + return VALNOEXIST_INT; + return elem->second; + } + //ajusta map a memoria justa + inline void memAjust() + { + + } + inline void configVector(int ymax) + { + isVect = true; + dat.clear(); + datv.insert(datv.begin(),ymax,VALNOEXIST_INT); + /*datv.reserve(ymax); + for (int i =0 ; i dat; + + //********************************* + //Métodos + CmapMatInt() + { + } + ~CmapMatInt(void) + { + } + //****************************************************** + inline CmapRowInt& operator[](int irow) + { + return dat[irow]; + } + + inline void set(int x, int y, int val) + { + if(val== VALNOEXIST_INT) + return; + dat[x].set(y,val); + } + //ajusta los map a la memoria minima posible + inline void memAjust() + { + for(std::vector::iterator elem = dat.begin(); elem!= dat.end(); elem++) + { + elem->memAjust(); + } + } + inline void clear() + { + dat.clear(); + } + + inline void inicializa(int xmax, int nthr, int nvect=-1) + { + dat.reserve(xmax); + bool inVector = false; + if(nthr<=0) + nthr=1; + if(nvect<0) + nvect =(int)(MAX_MEM_MAPINT/xmax); + int vectthr=0,novecthr=0,iparc=0; + if(nvect=xmax)//nvec>=xmax + dat[i].configVector(xmax); + else if(nvect==0) + continue; + else + { + if((i-iparc)=(vectthr+novecthr)) + iparc+=vectthr+novecthr; + } + } + } + +}; + +#endif \ No newline at end of file diff --git a/includes/Utiles/proceso_cliente.h b/includes/Utiles/proceso_cliente.h new file mode 100644 index 0000000..d1cb232 --- /dev/null +++ b/includes/Utiles/proceso_cliente.h @@ -0,0 +1,12 @@ +#pragma once +#include "_proceso.h" +#include "base_head.h" +class Csock_sv; +class UTILES_EXPORT Cproceso_cliente: public C_proceso +{ +public: + Csock_sv *soc; + Cproceso_cliente(void); + ~Cproceso_cliente(void); + //virtual void run(){}; +}; diff --git a/includes/Utiles/sock_sv.h b/includes/Utiles/sock_sv.h new file mode 100644 index 0000000..15a762a --- /dev/null +++ b/includes/Utiles/sock_sv.h @@ -0,0 +1,50 @@ +#pragma once +#include "Csock_cl.h" +#include "th.h" +#include +class Cproceso_cliente; +class UTILES_EXPORT Cescucha_sock_sv//interface para que te entren los accept +{ +public: + virtual Cproceso_cliente* crea_cliente(BOOL *pirate)=0;//funcion que crea los procesos cliente en el accept (devuelve null si no se acepta) +}; +//socket generico si se pone una escucha crea los socket cliente desde la escucha +//si no desde la funcion crea_cliente +//si el proceso cliente ya tiene un socket creado no se crea si no se crea un socket cliente +class UTILES_EXPORT Csock_sv : public Csock_cl +{ +public: + BOOL sock_cerrado; + Cescucha_sock_sv *escucha; + Csock_sv(BOOL* sal=NULL, C_error*e=NULL); + virtual ~Csock_sv(void); + Cproceso_cliente* (*crea_cliente)(BOOL *pirate ); + //funciones servidor------------------------------------ + virtual void OnAccept(int nErrorCode); + virtual void OnClose(int nErrorCode); + //virtual void run(); + //funciones virtuales de thread win +}; +//socket servidor con thread y cola de evntos propia + +class UTILES_EXPORT Csock_svThread :public CWinThread +{ + //DECLARE_DYNCREATE(Csock_svThread) + BOOL isLisening; + BOOL pireateTread; + int port, type, evenFlag; + char * url; + +public: + Cescucha_sock_sv *escucha; + Cproceso_cliente* (*crea_cliente)(BOOL *pirate ); + BOOL liseningThread(int port, char * url, int type = SOCK_STREAM, int evenFlag = FD_ACCEPT | FD_READ | FD_CLOSE );//inicia escucha + void close();//cierra escucha + //funciones aux------------------------ + ~Csock_svThread(); + Csock_svThread(); +//AfxSocketInit() + virtual BOOL InitInstance() ; + virtual int Run() ; + CString sName ;//nombre thread +}; \ No newline at end of file diff --git a/includes/Utiles/static_array.h b/includes/Utiles/static_array.h new file mode 100644 index 0000000..00191e9 --- /dev/null +++ b/includes/Utiles/static_array.h @@ -0,0 +1,20 @@ +#pragma once +#include "base_head.h" +class UTILES_EXPORT Cstatic_array +{ +public: + int z;//tamaño de la memoria + int n;//capacidad usada de la memoria + int m;//capacidad total de la memoria + int incremento; + BYTE* buf; + Cstatic_array(int size=1); + ~Cstatic_array(void); + //funciones--------------------------------------- + BYTE* get(int i);//da el elemento i + BYTE* get_cp(int i);//da una copia del elemento i + void add(BYTE* e);//añade elemento + void borra();//borra elementos + //funciones aux---------------------------------- + BOOL reserva(int p=1);//reserva memoria para p posiciones mas +}; diff --git a/includes/Utiles/stdint.h b/includes/Utiles/stdint.h new file mode 100644 index 0000000..d02608a --- /dev/null +++ b/includes/Utiles/stdint.h @@ -0,0 +1,247 @@ +// ISO C9x compliant stdint.h for Microsoft Visual Studio +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +// Copyright (c) 2006-2008 Alexander Chemeris +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. The name of the author may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _MSC_VER // [ +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif // _MSC_VER ] + +#ifndef _MSC_STDINT_H_ // [ +#define _MSC_STDINT_H_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +#include + +// For Visual Studio 6 in C++ mode and for many Visual Studio versions when +// compiling for ARM we should wrap include with 'extern "C++" {}' +// or compiler give many errors like this: +// error C2733: second C linkage of overloaded function 'wmemchr' not allowed +#ifdef __cplusplus +extern "C" { +#endif +# include +#ifdef __cplusplus +} +#endif + +// Define _W64 macros to mark types changing their size, like intptr_t. +#ifndef _W64 +# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 +# define _W64 __w64 +# else +# define _W64 +# endif +#endif + + +// 7.18.1 Integer types + +// 7.18.1.1 Exact-width integer types + +// Visual Studio 6 and Embedded Visual C++ 4 doesn't +// realize that, e.g. char has the same size as __int8 +// so we give up on __intX for them. +#if (_MSC_VER < 1300) + typedef signed char int8_t; + typedef signed short int16_t; + typedef signed int int32_t; + typedef unsigned char uint8_t; + typedef unsigned short uint16_t; + typedef unsigned int uint32_t; +#else + typedef signed __int8 int8_t; + typedef signed __int16 int16_t; + typedef signed __int32 int32_t; + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; +#endif +typedef signed __int64 int64_t; +typedef unsigned __int64 uint64_t; + + +// 7.18.1.2 Minimum-width integer types +typedef int8_t int_least8_t; +typedef int16_t int_least16_t; +typedef int32_t int_least32_t; +typedef int64_t int_least64_t; +typedef uint8_t uint_least8_t; +typedef uint16_t uint_least16_t; +typedef uint32_t uint_least32_t; +typedef uint64_t uint_least64_t; + +// 7.18.1.3 Fastest minimum-width integer types +typedef int8_t int_fast8_t; +typedef int16_t int_fast16_t; +typedef int32_t int_fast32_t; +typedef int64_t int_fast64_t; +typedef uint8_t uint_fast8_t; +typedef uint16_t uint_fast16_t; +typedef uint32_t uint_fast32_t; +typedef uint64_t uint_fast64_t; + +// 7.18.1.4 Integer types capable of holding object pointers +#ifdef _WIN64 // [ + typedef signed __int64 intptr_t; + typedef unsigned __int64 uintptr_t; +#else // _WIN64 ][ + typedef _W64 signed int intptr_t; + typedef _W64 unsigned int uintptr_t; +#endif // _WIN64 ] + +// 7.18.1.5 Greatest-width integer types +typedef int64_t intmax_t; +typedef uint64_t uintmax_t; + + +// 7.18.2 Limits of specified-width integer types + +#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 + +// 7.18.2.1 Limits of exact-width integer types +#define INT8_MIN ((int8_t)_I8_MIN) +#define INT8_MAX _I8_MAX +#define INT16_MIN ((int16_t)_I16_MIN) +#define INT16_MAX _I16_MAX +#define INT32_MIN ((int32_t)_I32_MIN) +#define INT32_MAX _I32_MAX +#define INT64_MIN ((int64_t)_I64_MIN) +#define INT64_MAX _I64_MAX +#define UINT8_MAX _UI8_MAX +#define UINT16_MAX _UI16_MAX +#define UINT32_MAX _UI32_MAX +#define UINT64_MAX _UI64_MAX + +// 7.18.2.2 Limits of minimum-width integer types +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MIN INT64_MIN +#define INT_LEAST64_MAX INT64_MAX +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +// 7.18.2.3 Limits of fastest minimum-width integer types +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST8_MAX INT8_MAX +#define INT_FAST16_MIN INT16_MIN +#define INT_FAST16_MAX INT16_MAX +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST32_MAX INT32_MAX +#define INT_FAST64_MIN INT64_MIN +#define INT_FAST64_MAX INT64_MAX +#define UINT_FAST8_MAX UINT8_MAX +#define UINT_FAST16_MAX UINT16_MAX +#define UINT_FAST32_MAX UINT32_MAX +#define UINT_FAST64_MAX UINT64_MAX + +// 7.18.2.4 Limits of integer types capable of holding object pointers +#ifdef _WIN64 // [ +# define INTPTR_MIN INT64_MIN +# define INTPTR_MAX INT64_MAX +# define UINTPTR_MAX UINT64_MAX +#else // _WIN64 ][ +# define INTPTR_MIN INT32_MIN +# define INTPTR_MAX INT32_MAX +# define UINTPTR_MAX UINT32_MAX +#endif // _WIN64 ] + +// 7.18.2.5 Limits of greatest-width integer types +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +// 7.18.3 Limits of other integer types + +#ifdef _WIN64 // [ +# define PTRDIFF_MIN _I64_MIN +# define PTRDIFF_MAX _I64_MAX +#else // _WIN64 ][ +# define PTRDIFF_MIN _I32_MIN +# define PTRDIFF_MAX _I32_MAX +#endif // _WIN64 ] + +#define SIG_ATOMIC_MIN INT_MIN +#define SIG_ATOMIC_MAX INT_MAX + +#ifndef SIZE_MAX // [ +# ifdef _WIN64 // [ +# define SIZE_MAX _UI64_MAX +# else // _WIN64 ][ +# define SIZE_MAX _UI32_MAX +# endif // _WIN64 ] +#endif // SIZE_MAX ] + +// WCHAR_MIN and WCHAR_MAX are also defined in +#ifndef WCHAR_MIN // [ +# define WCHAR_MIN 0 +#endif // WCHAR_MIN ] +#ifndef WCHAR_MAX // [ +# define WCHAR_MAX _UI16_MAX +#endif // WCHAR_MAX ] + +#define WINT_MIN 0 +#define WINT_MAX _UI16_MAX + +#endif // __STDC_LIMIT_MACROS ] + + +// 7.18.4 Limits of other integer types + +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 + +// 7.18.4.1 Macros for minimum-width integer constants + +#define INT8_C(val) val##i8 +#define INT16_C(val) val##i16 +#define INT32_C(val) val##i32 +#define INT64_C(val) val##i64 + +#define UINT8_C(val) val##ui8 +#define UINT16_C(val) val##ui16 +#define UINT32_C(val) val##ui32 +#define UINT64_C(val) val##ui64 + +// 7.18.4.2 Macros for greatest-width integer constants +#define INTMAX_C INT64_C +#define UINTMAX_C UINT64_C + +#endif // __STDC_CONSTANT_MACROS ] + + +#endif // _MSC_STDINT_H_ ] diff --git a/includes/Utiles/str_socket.h b/includes/Utiles/str_socket.h new file mode 100644 index 0000000..559f3fe --- /dev/null +++ b/includes/Utiles/str_socket.h @@ -0,0 +1,87 @@ +#pragma once +#include +#include "base_head.h" +#define MAX_CHAR_BLOQ_STRSOCKET 1024 //Maximo de caracteres por envio +#include "_error.h" + +#define ESPERA_STRSOCKET 1 //milis en sleep +#define ESPERA_SEG_STRSOCKET 3//SEGUNDOS MAXIMOS INTENTANDO RECIBIR ENVITOS +#define VECES_ESPERA_STRSOCKET ((1000 * ESPERA_SEG_STRSOCKET) / ESPERA_STRSOCKET) +#define MIN_REALLOC_STR_SOC 512 //bytes +/* +Socket cliente para envio de informacion ascii (string) +*/ +class UTILES_EXPORT Cstr_socket : public CAsyncSocket +{ +public: + //variables-------------------------------------- + C_error er;//variable que da info de posibles errores + BOOL pirate;//==TRUE -> se cancela todas las tareas del socket + long cli_currando;//indica que el socket esta en uso + Cstr_socket *pp; //puntero al padre + //variables aux---------------------------------- +private: + char *buf;//buffer de envios + int n, m;//ocupacion y capacidad del buffer + int nb;//indica el numero de bytes que va por envio total + +public: + //c y d------------------------------------------ + Cstr_socket(void); + ~Cstr_socket(void); +public: + //funciones-------------------------------------- + BOOL crear(char *ip=NULL, int puerto=0);//crea el socket en la ip y puerto de salida indicados + BOOL conecta(char *ip, int puerto);//contecta a servidor + char* recibir();//recibe string; + BOOL envia( char *fmt, ...);//envia string + void cierra();//cierra socket + char *getbuf();//devuelve buffer del socket + //funciones auxiliares--------------------------- +private: + BOOL cuida_mem(int nbb);//pide memoria si hace falta + int recibir(BYTE *b, int nbb);//recive nbb bytes y los deja en b + BOOL enviar(int nbb,BYTE *b); + +}; +/* +Socket servidor para envio de informacion ascii (string) +*/ +class UTILES_EXPORT Cstr_socket_srv : public Cstr_socket +{ + //variables aux---------------------------------- +private: + HWND wnd;//ventana a la que mandar eventos + int id_even, id_comman; + BOOL *sal_soc; + int t_out;//tiempo de salida sin hacer nada + __int64 t; +public: + //c y d------------------------------------------ + Cstr_socket_srv(void); + ~Cstr_socket_srv(void); + //funciones-------------------------------------- + virtual BOOL on_datos_recibidos(char *txt)=0;//funcion donde procesar los datos + virtual Cstr_socket_srv* crea_cliente()=0;//funcion donde procesar los datos + + BOOL pon_escucha(char *ip, int puerto); + void pon_wnd_destruc(HWND wnd,int id_comman,int id_even); + //funciones auxiliares--------------------------- +private: + + +public: + void run(); + virtual void OnAccept(int nErrorCode); + virtual void OnClose(int nErrorCode); + static UINT th_funcion(LPVOID pp); + void pon_tout( int t_out ); +}; +//funciones de socket cliente para pinvoke----------------------------------------------------- +extern "C" UTILES_EXPORT Cstr_socket *str_socket_crea(); +extern "C" UTILES_EXPORT BOOL str_socket_conecta(Cstr_socket *soc, char *ip, int puerto); +extern "C" UTILES_EXPORT BOOL str_socket_envia(Cstr_socket *soc, char *txt); +extern "C" UTILES_EXPORT int str_socket_recive(Cstr_socket* soc); +extern "C" UTILES_EXPORT void str_socket_dame_buf(Cstr_socket* soc, char* buf); +extern "C" UTILES_EXPORT void str_socket_dame_error(Cstr_socket* soc, char* error); +extern "C" UTILES_EXPORT void str_socket_borra(Cstr_socket* soc); \ No newline at end of file diff --git a/includes/Utiles/th.h b/includes/Utiles/th.h new file mode 100644 index 0000000..b2f91ea --- /dev/null +++ b/includes/Utiles/th.h @@ -0,0 +1,38 @@ +#pragma once +#ifndef INCLUDE_TH_UTILES +#define INCLUDE_TH_UTILES + +#include "base_head.h" +const DWORD MS_VC_EXCEPTION_TH_UTILES=0x406D1388; +//funciones necesarias------------- +UTILES_EXPORT void SetThName( DWORD dwThreadID, char* threadName); +UINT main_th_proceso(LPVOID pp); +//thead basico--------------------- +class UTILES_EXPORT Cth +{ + +public: + bool running;//variable interna no usar + //variables + + char nombre[32];//nombre del thread + CWinThread * m_thread;//puntero a thread + //cosntructor y destructor--------------- + Cth(void); + ~Cth(void); + //funicones------------------------------ + virtual void run()=0;//funcion que hace el thread + bool isRunning();//indica si se esta currando o no + + BOOL lanza(char *nombre=NULL);//lanzar thread + + //******************************** + void join();//espera a que el thread termine +}; + +class UTILES_EXPORT Crunable +{ +public: + virtual void frun(int modo=0)=0; +}; +#endif \ No newline at end of file diff --git a/includes/Utiles/th_cola.h b/includes/Utiles/th_cola.h new file mode 100644 index 0000000..065e11c --- /dev/null +++ b/includes/Utiles/th_cola.h @@ -0,0 +1,141 @@ +#pragma once +#include "th.h" +#include "gcola_con.h" + + +template +struct Timers_Cth_cola +{ + T tarea;//tarea a encadenar + __int64 t;//tiempo desde la ultima ejecucion + int dt;//periodo del timer +}; +//------------------------------------------------------------ +class Cth_rimers_cola : //tread para los timers + public Cth +{ +public: + Crunable *clase_run; + inline virtual void run() + { + clase_run->frun(0); + } +}; +//cola asincrona-------------------------------------------- +//thread de tareas tipico----------------------------------- +template +class Cth_cola : //falta probar, poner timers + public Cth, Crunable +{ +public: + Cgcola_con cola;//cola de tareas pendientes + Cgcola_con> timers;//tareas periodicas activas + BOOL pirate;//indica al tread que hay que terminar + BOOL eje_fin;//indica que hay que ejecutar la tarea final + int time_sleep;//tiempo de espera cuando no hay tareas + int tp_max;//maximo de tareas pendientes en cola + T tfin;//tarea final; + Cth_rimers_cola thtimers;//thread de control de tareas periodicas + //constructor y destructor-------------------------------- + //************************************************** + Cth_cola(void) + { + pirate=FALSE; + time_sleep=1; + tp_max=1000; + eje_fin=FALSE; + thtimers.clase_run=this; + thtimers.join(); + + + }; + //************************************************** + ~Cth_cola(void) + { + fin(); + }; + //funciones----------------------------------------------- + void pon_tfin(T &e) + { + tfin=e; + eje_fin=TRUE; + }; + //************************************************** + virtual inline BOOL operator+(T &e )//añade tarea + { + return !pirate && cola.n<=tp_max && cola+e; + }; + //************************************************** + virtual inline BOOL operator-(T &e )//añade tarea y elimina el resto + { + if (pirate) + return FALSE; + cola.cerrojo.entro(); + cola.borra(); + cola.cerrojo.salgo(); + return cola+e; + }; + //************************************************** + virtual void fin()//termina el proceso + { + pirate=TRUE; + thtimers.join(); + join(); + + }; + //************************************************** + BOOL pon_timer(int seg, T &tar)//pone una tarea periodica siendo t el periodo en seg + { + Timers_Cth_cola tim; + tim.t=0; + tim.tarea=tar; + tim.dt=seg; + timers+tim; + return TRUE; + }; + //************************************************** + virtual void procesa(T &t)//override de procesado que hay que sobreescribir + { + + }; + //************************************************** + virtual void run()//proceso que despacha + { + T tarea; + sprintf(thtimers.nombre,"%s_timers",nombre); + if (timers.n) + thtimers.lanza(); + while (!pirate) + { + if (cola-=&tarea) + procesa(tarea); + else + Sleep(time_sleep); + } + if(eje_fin) + procesa(tfin); + }; + //************************************************** + virtual void frun(int modo=0)//proceso del timer + { + __int64 t; + Element_Cgcola> *e; + while(!pirate) + { + timers.cerrojo.entro(); + e=timers.ini; + t=_time64(NULL); + while(e) + { + if (e->t.tt.tarea)) + e->t.t=t+e->t.dt; + } + e=e->sig; + } + Sleep(500); + } + }; + //************************************************** +}; diff --git a/includes/Utiles/utiles_def.h b/includes/Utiles/utiles_def.h new file mode 100644 index 0000000..3c00f81 --- /dev/null +++ b/includes/Utiles/utiles_def.h @@ -0,0 +1,85 @@ +#pragma once +//defines de carpetas----------------------------------------------------------------------- + +#define D_WORK "%dir_work%" +#define D_LOG "%dir_log%" +#define D_APP "%dir_exe%" +#define D_DAT "%dir_dat%" +#define P_CONG "%p_config%" + +//define para comunicacion------------------------------------------------------------------ +#define VERSION_PACKAGE_HEAD 1 //version de metodo de comunicacion +#define MAX_LONG_PACKAGE_0 0x04000 //maximo de bytes por package +//flags de cabecera + +/* +#define FLAG_PACKAGE_HEAD_0_INICIO 0x00000001 +#define FLAG_PACKAGE_HEAD_0_CONTINUACION 0x00000002 +#define FLAG_PACKAGE_HEAD_0_FINAL 0x00000004*/ + +#define FLAG_PACKAGE_HEAD_0_ENCRIPT1 0x00000001 +#define FLAG_PACKAGE_HEAD_0_REPLICADO 0x00000002 +//estructuras para comunicacion------------------------------------------------------------- +typedef struct Package_head_0//cabecera base de la cumunicación +{ + int version; //version de comunicacion + int flags; //flags + int nb; //numero de bytes del paquete + int n; //numero de bloques de este paquete +}Package_head_0; +//en esta version el identificador de los paquetes sera un entero (int) +//paquetes generales de envio---------------------------------------------------------------- +#define PETICION_GENERAL_NO 0//paquete de negacion + +#define PETICION_GENERAL_PRESENTA 1//peticion de presentacion usuario y key +#define PETICION_GENERAL_OK 2//respuesta ok automatica +#define PETICION_GENERAL_DESCONECTA 3//peticion de desconexion +#define PETICION_GENERAL_DAME_LOG 4//peticion de eventos (normalmente con id) +#define PETICION_GENERAL_TOMA_COMANDO 5//peticionde comando para servidor +#define PETICION_GENERAL_FIN 6 + + +//define para usuarios------------------------------------------------------------------------ +#define VERSION_USUARIO_CONEXION 1 //version de usuarios +//flags usuarios +#define FLAG_USUARIO_CONEXION_INDI 0x00000001//indica que solo se acepta una conexion por dicho usuario +#define FLAG_USUARIO_CONEXION_EN_USO 0x00000002//indica que el usuario esta en uso actualmente +#define FLAG_USUARIO_CONEXION_VACIO 0x00000004//indica que el usuario esta borrado +#define FLAG_USUARIO_CONEXION_BLOQ 0x00000008//indica que el usuario esta bloqueado (no se puede usar) +//flags archivo +#define FLAG_FILE_USUARIO_CONEX_ENCRIP 0x00000001//indica que el archivo esta encriptado +//flags permisos + +//estructura para usuarios--------------------------------------------------------------------- +typedef struct Usuario_conx_0//informacion de usuario +{ + int flags; + int id; //identificador de usuario + int permisos; //flags de permisos + int ia; //informacion adicional + int ncon; //numero de conectados con este usuario + char nombre[32]; //nombre de usuario + char clave[32]; //calve de usuario +}Usuario_conx_0; + +typedef struct Head_usuario_conex_0//cabecera de archivo de usuario +{ + int version; //version informacion de usuaros + int flags; //flags + int n; //numero de usuarios en archivo +}Head_usuario_conex_0; + +//interface de elemento que se transfiere---------------------------------- +class IdataTransfer +{ +public: + //para lectura + virtual __int64 getNB_it()=0;//devuelve numero de bites totales de informacion + virtual __int64 getNext_it(void* buf,__int64 nb)=0;//copia en buffer buf el los siguientes nb bytes y devuelve el numero total de bites leidos + + //lectura y escritura + inline virtual bool setPosition_it(__int64 nb){ return false; };//se posiciona en el byte nb los datos + + //para escritura----------- + inline virtual bool set_it(void* buf, __int64 nb){ return true; };//prepara datos para recivir nb bites +}; \ No newline at end of file diff --git a/includes/Utiles/utl.h b/includes/Utiles/utl.h new file mode 100644 index 0000000..7b3b388 --- /dev/null +++ b/includes/Utiles/utl.h @@ -0,0 +1,33 @@ +#pragma once +#include "base_head.h" +class StrArray; +class UTILES_EXPORT Cutl +{ +public: + Cutl(void); + ~Cutl(void); + //cifra y descifra datos con FLAG_PACKAGE_HEAD_0_ENCRIPT1 + static void cifra1(BYTE*b,int nb); + static void cifra1(char*b);//ojo con los char despues de cifrar no usar stlen ni semejantes + static void descifra1(char*b); + static void descifra1(BYTE* b,int nb); + //-------------------------------------------------------- + static void big_little(BYTE* b,int nb);//cambia de little a big_endian y viceversa + //ordenacion---------------------------------------------- + static int busca(BYTE*lista,int n,int sizeElement,BYTE *e, int (*funcion)(BYTE*,BYTE*) );//busqueda dicotomica + static StrArray* stringSplit(char *orig,char* subStr, StrArray*buf); + + //identificador pc---------------------------------------- + static char* id_pc(char*idm, int nb);//proporciona un identificador unico de la computadora + static DWORDLONG getMemoDisp();//devuelve la memoria disponible + static DWORDLONG getMemoDisp1Malloc();//devuelve la memoria disponible real en mem1 en un malloc + + //identificacion de usuario de windows-------------------- + static char* getWinUser(char* buf);//leng de 256 + + //funciones de string-------------------------------- + static int str_hex2int(char* st);//pasa de cadena de caracteres tipo 0xff a entero + static void int2str_hex( char* st , int n); + + static bool lanza_exe(char *appName, char *comline, DWORD *processId = NULL);//ejecuta appName +}; diff --git a/lib/Debug/ClientLic.lib b/lib/Debug/ClientLic.lib new file mode 100644 index 0000000..cdf819b Binary files /dev/null and b/lib/Debug/ClientLic.lib differ diff --git a/lib/Debug/FileTransfer.lib b/lib/Debug/FileTransfer.lib new file mode 100644 index 0000000..fffeb93 Binary files /dev/null and b/lib/Debug/FileTransfer.lib differ diff --git a/lib/Debug/Olivia.lib b/lib/Debug/Olivia.lib new file mode 100644 index 0000000..1ac744a Binary files /dev/null and b/lib/Debug/Olivia.lib differ diff --git a/lib/Debug/licUtiles.lib b/lib/Debug/licUtiles.lib new file mode 100644 index 0000000..aa09b1e Binary files /dev/null and b/lib/Debug/licUtiles.lib differ diff --git a/lib/Debug/sqlite3.lib b/lib/Debug/sqlite3.lib new file mode 100644 index 0000000..ed40f91 Binary files /dev/null and b/lib/Debug/sqlite3.lib differ diff --git a/lib/Debug/utiles.lib b/lib/Debug/utiles.lib new file mode 100644 index 0000000..113cd8a Binary files /dev/null and b/lib/Debug/utiles.lib differ diff --git a/lib/Release/ClientLic.lib b/lib/Release/ClientLic.lib new file mode 100644 index 0000000..c08d66b Binary files /dev/null and b/lib/Release/ClientLic.lib differ diff --git a/lib/Release/FileTransfer.lib b/lib/Release/FileTransfer.lib new file mode 100644 index 0000000..4b0e68d Binary files /dev/null and b/lib/Release/FileTransfer.lib differ diff --git a/lib/Release/Olivia.lib b/lib/Release/Olivia.lib new file mode 100644 index 0000000..3f33953 Binary files /dev/null and b/lib/Release/Olivia.lib differ diff --git a/lib/Release/licUtiles.lib b/lib/Release/licUtiles.lib new file mode 100644 index 0000000..3394c33 Binary files /dev/null and b/lib/Release/licUtiles.lib differ diff --git a/lib/Release/sqlite3.lib b/lib/Release/sqlite3.lib new file mode 100644 index 0000000..ed40f91 Binary files /dev/null and b/lib/Release/sqlite3.lib differ diff --git a/lib/Release/utiles.lib b/lib/Release/utiles.lib new file mode 100644 index 0000000..b30f882 Binary files /dev/null and b/lib/Release/utiles.lib differ diff --git a/lib/x64/debug/ClientLic.lib b/lib/x64/debug/ClientLic.lib new file mode 100644 index 0000000..864dce9 Binary files /dev/null and b/lib/x64/debug/ClientLic.lib differ diff --git a/lib/x64/debug/FileTransfer.lib b/lib/x64/debug/FileTransfer.lib new file mode 100644 index 0000000..3b118c9 Binary files /dev/null and b/lib/x64/debug/FileTransfer.lib differ diff --git a/lib/x64/debug/Olivia.lib b/lib/x64/debug/Olivia.lib new file mode 100644 index 0000000..c06dc6b Binary files /dev/null and b/lib/x64/debug/Olivia.lib differ diff --git a/lib/x64/debug/licUtiles.lib b/lib/x64/debug/licUtiles.lib new file mode 100644 index 0000000..ed3e12a Binary files /dev/null and b/lib/x64/debug/licUtiles.lib differ diff --git a/lib/x64/debug/sqlite3.lib b/lib/x64/debug/sqlite3.lib new file mode 100644 index 0000000..727e29c Binary files /dev/null and b/lib/x64/debug/sqlite3.lib differ diff --git a/lib/x64/debug/utiles.lib b/lib/x64/debug/utiles.lib new file mode 100644 index 0000000..9d82ef7 Binary files /dev/null and b/lib/x64/debug/utiles.lib differ diff --git a/lib/x64/release/ClientLic.lib b/lib/x64/release/ClientLic.lib new file mode 100644 index 0000000..9f6e3c4 Binary files /dev/null and b/lib/x64/release/ClientLic.lib differ diff --git a/lib/x64/release/FileTransfer.lib b/lib/x64/release/FileTransfer.lib new file mode 100644 index 0000000..f296c09 Binary files /dev/null and b/lib/x64/release/FileTransfer.lib differ diff --git a/lib/x64/release/Olivia.lib b/lib/x64/release/Olivia.lib new file mode 100644 index 0000000..21e257d Binary files /dev/null and b/lib/x64/release/Olivia.lib differ diff --git a/lib/x64/release/licUtiles.lib b/lib/x64/release/licUtiles.lib new file mode 100644 index 0000000..e76fecf Binary files /dev/null and b/lib/x64/release/licUtiles.lib differ diff --git a/lib/x64/release/sqlite3.lib b/lib/x64/release/sqlite3.lib new file mode 100644 index 0000000..727e29c Binary files /dev/null and b/lib/x64/release/sqlite3.lib differ diff --git a/lib/x64/release/utiles.lib b/lib/x64/release/utiles.lib new file mode 100644 index 0000000..14ee671 Binary files /dev/null and b/lib/x64/release/utiles.lib differ diff --git a/limpia.bat b/limpia.bat new file mode 100644 index 0000000..3853bfc --- /dev/null +++ b/limpia.bat @@ -0,0 +1,26 @@ +@echo off +del "%~dp0"\*.ncb +del "%~dp0"\*.suo +del "%~dp0"\*.bak + +del "%~dp0"\Olivia\*.bak +del "%~dp0"\Olivia\*.aps +del "%~dp0"\OliviaTasks\*.bak +del "%~dp0"\OliviaTasks\*.aps + +Echo Borra release Olivia. +rmdir /s /q "%~dp0"\Olivia\release +Echo Borra debug Olivia. +rmdir /s /q "%~dp0"\Olivia\debug +Echo Borra x64 Olivia. +rmdir /s /q "%~dp0"\Olivia\x64 + +Echo Borra release OliviaTasks. +rmdir /s /q "%~dp0"\OliviaTasks\release +Echo Borra debug OliviaTasks. +rmdir /s /q "%~dp0"\OliviaTasks\debug +Echo Borra x64 OliviaTasks. +rmdir /s /q "%~dp0"\OliviaTasks\x64 + + +pause \ No newline at end of file