From 53350880c9c1c14f251eb2a2af2606fae79e0054 Mon Sep 17 00:00:00 2001 From: "Marios S. Kyriakou" Date: Wed, 31 Jul 2024 19:48:19 +0300 Subject: [PATCH 1/5] Add EN_loadpatternfile, ENloadpatternfile --- include/epanet2.h | 4 ++- include/epanet2_2.h | 9 +++++++ src/epanet.c | 63 +++++++++++++++++++++++++++++++++++++++++++++ src/epanet2.c | 5 ++++ 4 files changed, 80 insertions(+), 1 deletion(-) diff --git a/include/epanet2.h b/include/epanet2.h index 18a7345f..fc99a067 100644 --- a/include/epanet2.h +++ b/include/epanet2.h @@ -328,7 +328,7 @@ extern "C" { ********************************************************************/ int DLLEXPORT ENaddpattern(const char *id); - + int DLLEXPORT ENdeletepattern(int index); int DLLEXPORT ENgetpatternindex(const char *id, int *index); @@ -346,6 +346,8 @@ extern "C" { int DLLEXPORT ENgetaveragepatternvalue(int index, EN_API_FLOAT_TYPE *value); int DLLEXPORT ENsetpattern(int index, EN_API_FLOAT_TYPE *values, int len); + + int DLLEXPORT ENloadpatternfile(const char *filename, const char *id); /******************************************************************** diff --git a/include/epanet2_2.h b/include/epanet2_2.h index 1094280d..81f2f9f0 100644 --- a/include/epanet2_2.h +++ b/include/epanet2_2.h @@ -1478,6 +1478,15 @@ typedef struct Project *EN_Project; use @ref EN_setpatternvalue to revise pattern factors one at a time. */ int DLLEXPORT EN_setpattern(EN_Project ph, int index, double *values, int len); + + /** + @brief Loads time patterns from a file into a project under a specific pattern ID. + @param ph an EPANET project handle. + @param filename the name of the file containing pattern data. + @param id the ID name of the new pattern to load. + @return an error code. + */ + int DLLEXPORT EN_loadpatternfile(EN_Project p, const char *filename, const char *id); /******************************************************************** diff --git a/src/epanet.c b/src/epanet.c index 7e68c9d3..493f16c7 100644 --- a/src/epanet.c +++ b/src/epanet.c @@ -4514,6 +4514,69 @@ int DLLEXPORT EN_addpattern(EN_Project p, const char *id) return 0; } +int DLLEXPORT EN_loadpatternfile(EN_Project p, const char *filename, const char *id) +/*---------------------------------------------------------------- +** Input: filename = name of the file containing pattern data +** id = ID for the new pattern +** Output: none +** Returns: error code +** Purpose: loads time patterns from a file into a project under a specific pattern ID +**---------------------------------------------------------------- +*/ +{ + FILE *file; + char line[1024]; + int err = 0; + int i; + double value; + Spattern *pat; + + if (!p->Openflag) return 102; + + file = fopen(filename, "r"); + if (file == NULL) return 102; // Update with new error code + + // Add the new pattern + if ((err = EN_addpattern(p, id)) != 0) { + fclose(file); + return err; + } + + // Get the index of the newly added pattern + if ((err = EN_getpatternindex(p, id, &i)) != 0) { + fclose(file); + return err; + } + + pat = &p->network.Pattern[i]; + // Free the initial allocation + free(pat->F); + pat->F = NULL; + pat->Length = 0; + + // Read pattern values + while (fgets(line, sizeof(line), file) != NULL) { + // Skip comments and empty lines + if (line[0] == ';' || line[0] == '\n') continue; + + // Convert line to a double value + value = atof(line); + if (value == 0 && line[0] != '0') continue; // Skip invalid lines + + pat->Length++; + pat->F = (double *)realloc(pat->F, pat->Length * sizeof(double)); + // Abort if memory allocation error + if (pat->F == NULL) { + fclose(file); + return 101; + } + pat->F[pat->Length - 1] = value; + } + + fclose(file); + return 0; +} + int DLLEXPORT EN_deletepattern(EN_Project p, int index) /*---------------------------------------------------------------- ** Input: index = index of the pattern to delete diff --git a/src/epanet2.c b/src/epanet2.c index c3c8fa29..435a571c 100644 --- a/src/epanet2.c +++ b/src/epanet2.c @@ -676,6 +676,11 @@ int DLLEXPORT ENsetpattern(int index, EN_API_FLOAT_TYPE *values, int len) return errcode; } +int DLLEXPORT ENloadpatternfile(const char *filename, const char *id) +{ + return EN_loadpatternfile(_defaultProject, filename, id); +} + /******************************************************************** Data Curve Functions From 03e889d6751351cff44703fe19c20935c5bc5b2a Mon Sep 17 00:00:00 2001 From: "Marios S. Kyriakou" Date: Thu, 1 Aug 2024 08:58:13 +0300 Subject: [PATCH 2/5] Update epanet.c Co-Authored-By: Lew Rossman --- src/epanet.c | 50 +++++++++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/src/epanet.c b/src/epanet.c index 493f16c7..ff56e200 100644 --- a/src/epanet.c +++ b/src/epanet.c @@ -4525,16 +4525,18 @@ int DLLEXPORT EN_loadpatternfile(EN_Project p, const char *filename, const char */ { FILE *file; - char line[1024]; + char line[MAXLINE+1]; int err = 0; int i; + int len = 0; double value; - Spattern *pat; + double *values = NULL; + int CHUNK = 50; if (!p->Openflag) return 102; file = fopen(filename, "r"); - if (file == NULL) return 102; // Update with new error code + if (file == NULL) return 302; // Add the new pattern if ((err = EN_addpattern(p, id)) != 0) { @@ -4548,33 +4550,31 @@ int DLLEXPORT EN_loadpatternfile(EN_Project p, const char *filename, const char return err; } - pat = &p->network.Pattern[i]; - // Free the initial allocation - free(pat->F); - pat->F = NULL; - pat->Length = 0; - // Read pattern values while (fgets(line, sizeof(line), file) != NULL) { - // Skip comments and empty lines - if (line[0] == ';' || line[0] == '\n') continue; - - // Convert line to a double value - value = atof(line); - if (value == 0 && line[0] != '0') continue; // Skip invalid lines - - pat->Length++; - pat->F = (double *)realloc(pat->F, pat->Length * sizeof(double)); - // Abort if memory allocation error - if (pat->F == NULL) { - fclose(file); - return 101; + + // Skip lines that don't contain valid numbers + if (!getfloat(line, &value) continue; + + // Resize multiplier array if it's full + if (len % CHUNK == 0) { + values = (double *) realloc(values, (len + CHUNK) * sizeof(double)); + + // Abort if memory allocation error + if (values == NULL) { + fclose(file); + return 101; + } } - pat->F[pat->Length - 1] = value; + values[len] = value; + len++; } - fclose(file); - return 0; + + // Transfer multipliers to pattern + err = EN_setpattern(p, i, values, len); + free(values); + return err; } int DLLEXPORT EN_deletepattern(EN_Project p, int index) From 17b14e2178605b4916dffc9e507249f01566a8fa Mon Sep 17 00:00:00 2001 From: "Marios S. Kyriakou" Date: Thu, 1 Aug 2024 09:06:04 +0300 Subject: [PATCH 3/5] fix missing ')' --- src/epanet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/epanet.c b/src/epanet.c index ff56e200..52c5a5ad 100644 --- a/src/epanet.c +++ b/src/epanet.c @@ -4554,7 +4554,7 @@ int DLLEXPORT EN_loadpatternfile(EN_Project p, const char *filename, const char while (fgets(line, sizeof(line), file) != NULL) { // Skip lines that don't contain valid numbers - if (!getfloat(line, &value) continue; + if (!getfloat(line, &value)) continue; // Resize multiplier array if it's full if (len % CHUNK == 0) { From b16dacb87e348b8ebe2ee3547bd4ce04373b2fc6 Mon Sep 17 00:00:00 2001 From: "Marios S. Kyriakou" Date: Thu, 1 Aug 2024 17:06:32 +0300 Subject: [PATCH 4/5] Add a new pattern or use an existing pattern - EN_loadpatternfile Co-Authored-By: Lew Rossman --- src/epanet.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/epanet.c b/src/epanet.c index 52c5a5ad..16e7bf6f 100644 --- a/src/epanet.c +++ b/src/epanet.c @@ -4538,16 +4538,14 @@ int DLLEXPORT EN_loadpatternfile(EN_Project p, const char *filename, const char file = fopen(filename, "r"); if (file == NULL) return 302; - // Add the new pattern - if ((err = EN_addpattern(p, id)) != 0) { - fclose(file); - return err; - } - - // Get the index of the newly added pattern - if ((err = EN_getpatternindex(p, id, &i)) != 0) { - fclose(file); - return err; + // Add a new pattern or use an existing pattern. + err = EN_getpatternindex(p, id, &i); + if (err == 205) { + if ((err = EN_addpattern(p, id)) != 0) { + fclose(file); + return err; + } + i = p->network.Npats; } // Read pattern values From 3604f3f69312aa7591356bc047ebf0cffec4bfc4 Mon Sep 17 00:00:00 2001 From: "Marios S. Kyriakou" Date: Thu, 1 Aug 2024 22:45:42 +0300 Subject: [PATCH 5/5] fix Co-Authored-By: Lew Rossman --- src/epanet.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/epanet.c b/src/epanet.c index 16e7bf6f..71cad747 100644 --- a/src/epanet.c +++ b/src/epanet.c @@ -4526,6 +4526,7 @@ int DLLEXPORT EN_loadpatternfile(EN_Project p, const char *filename, const char { FILE *file; char line[MAXLINE+1]; + char *tok; int err = 0; int i; int len = 0; @@ -4552,7 +4553,9 @@ int DLLEXPORT EN_loadpatternfile(EN_Project p, const char *filename, const char while (fgets(line, sizeof(line), file) != NULL) { // Skip lines that don't contain valid numbers - if (!getfloat(line, &value)) continue; + tok = strtok(line, SEPSTR); + if (tok == NULL) continue; + if (!getfloat(tok, &value)) continue; // Resize multiplier array if it's full if (len % CHUNK == 0) {