From 7aadc83ddf358374432c9ab0b37eb45ed6338754 Mon Sep 17 00:00:00 2001 From: Lew Rossman Date: Tue, 29 Oct 2019 16:33:40 -0400 Subject: [PATCH] Adds link vertex get/set functions to the API --- include/epanet2.bas | 5 +- include/epanet2.def | 5 +- include/epanet2.h | 8 +++- include/epanet2.pas | 6 ++- include/epanet2.vb | 5 +- include/epanet2_2.h | 32 ++++++++++++- src/epanet.c | 114 +++++++++++++++++++++++++++++++++++++++----- src/epanet2.c | 16 ++++++- src/errors.dat | 1 + src/funcs.h | 6 ++- src/inpfile.c | 19 ++++++-- src/input2.c | 4 +- src/input3.c | 33 ++++++++++++- src/project.c | 63 ++++++++++++++++++++++-- src/types.h | 12 ++++- 15 files changed, 297 insertions(+), 32 deletions(-) diff --git a/include/epanet2.bas b/include/epanet2.bas index 9d7aa51..6ac1044 100644 --- a/include/epanet2.bas +++ b/include/epanet2.bas @@ -5,7 +5,7 @@ Attribute VB_Name = "Module1" 'Declarations of functions in the EPANET PROGRAMMERs TOOLKIT '(EPANET2.DLL) -'Last updated on 10/26/2019 +'Last updated on 10/29/2019 ' These are codes used by the DLL functions Public Const EN_ELEVATION = 0 ' Node parameters @@ -336,6 +336,9 @@ Public Const EN_R_IS_ACTIVE = 3 Declare Function ENgetlinkvalue Lib "epanet2.dll" (ByVal index As Long, ByVal property As Long, value As Single) As Long Declare Function ENsetlinkvalue Lib "epanet2.dll" (ByVal index As Long, ByVal property As Long, ByVal value As Single) As Long Declare Function ENsetpipedata Lib "epanet2.dll" (ByVal index As Long, ByVal length As Single, ByVal diam As Single, ByVal rough As Single, ByVal mloss As Single) As Long + Declare Function ENgetvertexcount Lib "epanet2.dll" (ByVal index As Long, count As Long) As Long + Declare Function ENgetvertex Lib "epanet2.dll" (ByVal index As Long, ByVal vertex As Long, x As Double, y As Double) As Long + Declare Function ENsetvertices Lib "epanet2.dll" (ByVal index As Long, xCoords As Any, yCoords As Any, ByVal count As Long) As Long 'Pump Functions Declare Function ENgetheadcurveindex Lib "epanet2.dll" (ByVal linkIndex As Long, curveIndex As Long) As Long diff --git a/include/epanet2.def b/include/epanet2.def index fd528a9..9bf41b4 100644 --- a/include/epanet2.def +++ b/include/epanet2.def @@ -46,7 +46,7 @@ EXPORTS ENgetlinknodes = _ENgetlinknodes@12 ENsetlinknodes = _ENsetlinknodes@12 ENgetlinktype = _ENgetlinktype@8 - ENgetlinkvalue = _ENgetlinkvalue@12 + ENgetlinkvalue = _ENgetlinkvalue@12 ENgetnodeid = _ENgetnodeid@8 ENgetnodeindex = _ENgetnodeindex@8 ENgetnodetype = _ENgetnodetype@8 @@ -69,6 +69,8 @@ EXPORTS ENgettimeparam = _ENgettimeparam@8 ENgettitle = _ENgettitle@12 ENgetversion = _ENgetversion@4 + ENgetvertex = _ENgetvertex@16 + ENgetvertexcount = _ENgetvertexcount@8 ENinit = _ENinit@16 ENinitH = _ENinitH@4 ENinitQ = _ENinitQ@4 @@ -121,6 +123,7 @@ EXPORTS ENsetthenaction = _ENsetthenaction@20 ENsettimeparam = _ENsettimeparam@8 ENsettitle = _ENsettitle@12 + ENsetvertices = _ENsetvertices@16 ENsolveH = _ENsolveH@0 ENsolveQ = _ENsolveQ@0 ENstepQ = _ENstepQ@4 diff --git a/include/epanet2.h b/include/epanet2.h index 807f9a9..19c9c67 100644 --- a/include/epanet2.h +++ b/include/epanet2.h @@ -7,7 +7,7 @@ Authors: see AUTHORS Copyright: see AUTHORS License: see LICENSE - Last Updated: 10/26/2019 + Last Updated: 10/29/2019 ****************************************************************************** */ @@ -285,6 +285,12 @@ extern "C" { int DLLEXPORT ENsetpipedata(int index, EN_API_FLOAT_TYPE length, EN_API_FLOAT_TYPE diam, EN_API_FLOAT_TYPE rough, EN_API_FLOAT_TYPE mloss); + + int DLLEXPORT ENgetvertexcount(int index, int *count); + + int DLLEXPORT ENgetvertex(int index, int vertex, double *x, double *y); + + int DLLEXPORT ENsetvertices(int index, double *x, double *y, int count); /******************************************************************** diff --git a/include/epanet2.pas b/include/epanet2.pas index 491258f..3c5345d 100644 --- a/include/epanet2.pas +++ b/include/epanet2.pas @@ -3,7 +3,7 @@ unit epanet2; { Declarations of imported procedures from the EPANET PROGRAMMERs TOOLKIT } { (EPANET2.DLL) } -{Last updated on 10/26/19} +{Last updated on 10/29/19} interface @@ -353,6 +353,10 @@ const function ENsetlinkvalue(Index: Integer; Code: Integer; Value: Single): Integer; stdcall; external EpanetLib; function ENsetpipedata(Index: Integer; Length: Single; Diam: Single; Rough: Single; Mloss:Single): Integer; stdcall; external EpanetLib; + function ENgetvertexcount(Index: Integer; var Count: Integer): Integer; stdcall; external EpanetLib; + function ENgetvertex(Index: Integer; Vertex: Integer; var X: Double; var Y: Double): Integer; stdcall; external EpanetLib; + function ENsetvertices(Index: Integer; X: array of Double; Y: array of Double; Count: Integer): Integer; stdcall; external EpanetLib; + {Pump Functions} function ENgetpumptype(LinkIndex: Integer; var PumpType: Integer): Integer; stdcall; external EpanetLib; function ENgetheadcurveindex(LinkIndex: Integer; var CurveIndex: Integer): Integer; stdcall; external EpanetLib; diff --git a/include/epanet2.vb b/include/epanet2.vb index 47f9709..e7c61e4 100644 --- a/include/epanet2.vb +++ b/include/epanet2.vb @@ -4,7 +4,7 @@ 'Declarations of functions in the EPANET PROGRAMMERs TOOLKIT '(EPANET2.DLL) for use with VB.Net. -'Last updated on 10/26/2019 +'Last updated on 10/29/2019 Imports System.Runtime.InteropServices Imports System.Text @@ -341,6 +341,9 @@ Public Const EN_R_IS_ACTIVE = 3 Declare Function ENgetlinkvalue Lib "epanet2.dll" (ByVal index As Int32, ByVal property As Int32, value As Single) As Int32 Declare Function ENsetlinkvalue Lib "epanet2.dll" (ByVal index As Int32, ByVal property As Int32, ByVal value As Single) As Int32 Declare Function ENsetpipedata Lib "epanet2.dll" (ByVal index As Int32, ByVal length As Single, ByVal diam As Single, ByVal rough As Single, ByVal mloss As Single) As Int32 + Declare Function ENgetvertexcount Lib "epanet2.dll" (ByVal index As Int32, count As Int32) As Int32 + Declare Function ENgetvertex Lib "epanet2.dll" (ByVal index As Int32, ByVal vertex As Int32, x As Double, y As Double) As Int32 + Declare Function ENsetvertices Lib "epanet2.dll" (ByVal index As Int32, xCoords As Any, yCoords As Any, ByVal count As Int32) As Int32 'Pump Functions Declare Function ENgetheadcurveindex Lib "epanet2.dll" (ByVal linkIndex As Int32, curveIndex As Int32) As Int32 diff --git a/include/epanet2_2.h b/include/epanet2_2.h index d8eb33c..926ab7d 100644 --- a/include/epanet2_2.h +++ b/include/epanet2_2.h @@ -11,7 +11,7 @@ Authors: see AUTHORS Copyright: see AUTHORS License: see LICENSE - Last Updated: 10/26/2019 + Last Updated: 10/29/2019 ****************************************************************************** */ @@ -1214,6 +1214,36 @@ typedef struct Project *EN_Project; int DLLEXPORT EN_setpipedata(EN_Project ph, int index, double length, double diam, double rough, double mloss); + /** + @brief Retrieves the number of internal vertex points assigned to a link. + @param ph an EPANET project handle. + @param index a link's index. + @param[out] count the number of vertex points that describe the link's shape. + @return an error code. + */ + int DLLEXPORT EN_getvertexcount(EN_Project ph, int index, int *count); + + /** + @brief Retrieves the coordinate's of a vertex point assigned to a link. + @param ph an EPANET project handle. + @param index a link's index. + @param vertex a vertex point index. + @param[out] x the vertex's X-coordinate value. + @param[out] y the vertex's Y-coordinate value. + @return an error code. + */ + int DLLEXPORT EN_getvertex(EN_Project ph, int index, int vertex, double *x, double *y); + + /** + @brief Assigns a set of internal vertex points to a link. + @param ph an EPANET project handle. + @param index a link's index. + @param x an array of X-coordinates for the vertex points. + @param y an array of Y-coordinates for the vertex points. + @param count the number of vertex points being assigned. + @return an error code. + */ + int DLLEXPORT EN_setvertices(EN_Project ph, int index, double *x, double *y, int count); /******************************************************************** diff --git a/src/epanet.c b/src/epanet.c index d476e0d..f31ef69 100644 --- a/src/epanet.c +++ b/src/epanet.c @@ -7,7 +7,7 @@ Authors: see AUTHORS Copyright: see AUTHORS License: see LICENSE - Last Updated: 10/26/2019 + Last Updated: 10/29/2019 ****************************************************************************** */ @@ -3985,17 +3985,17 @@ int DLLEXPORT EN_setlinkvalue(EN_Project p, int index, int property, double valu int DLLEXPORT EN_setpipedata(EN_Project p, int index, double length, double diam, double rough, double mloss) - /*---------------------------------------------------------------- - ** Input: index = pipe link index - ** length = pipe length - ** diam = pipe diameter - ** rough = pipe roughness coefficient - ** mloss = minor loss coefficient - ** Output: none - ** Returns: error code - ** Purpose: sets several properties for a pipe link - **---------------------------------------------------------------- - */ +/*---------------------------------------------------------------- +** Input: index = pipe link index +** length = pipe length +** diam = pipe diameter +** rough = pipe roughness coefficient +** mloss = minor loss coefficient +** Output: none +** Returns: error code +** Purpose: sets several properties for a pipe link +**---------------------------------------------------------------- +*/ { Network *net = &p->network; @@ -4024,6 +4024,96 @@ int DLLEXPORT EN_setpipedata(EN_Project p, int index, double length, return 0; } +int DLLEXPORT EN_getvertexcount(EN_Project p, int index, int *count) +/*---------------------------------------------------------------- +** Input: index = link index +** Output: count = number of link's vertex points +** Returns: error code +** Purpose: retrieves number of vertex points in a link +**---------------------------------------------------------------- +*/ +{ + Network *net = &p->network; + + Slink *Link = net->Link; + Pvertices vertices; + + // Check that link exists + *count = 0; + if (!p->Openflag) return 102; + if (index <= 0 || index > net->Nlinks) return 204; + + // Set count to number of vertices + vertices = Link[index].Vertices; + if (vertices) *count = vertices->Npts; + return 0; +} + +int DLLEXPORT EN_getvertex(EN_Project p, int index, int vertex, double *x, double *y) +/*---------------------------------------------------------------- +** Input: index = link index +** vertex = index of a link vertex point +** Output: x = vertex point's X-coordinate +** y = vertex point's Y-coordinate +** Returns: error code +** Purpose: retrieves the coordinates of a vertex point in a link +**---------------------------------------------------------------- +*/ +{ + Network *net = &p->network; + + Slink *Link = net->Link; + Pvertices vertices; + + // Check that link exists + *x = MISSING; + *y = MISSING; + if (!p->Openflag) return 102; + if (index <= 0 || index > net->Nlinks) return 204; + + // Check that vertex exists + vertices = Link[index].Vertices; + if (vertices == NULL) return 255; + if (vertex <= 0 || vertex > vertices->Npts) return 255; + *x = vertices->X[vertex - 1]; + *y = vertices->Y[vertex - 1]; + return 0; +} + +int DLLEXPORT EN_setvertices(EN_Project p, int index, double *x, double *y, int count) +/*---------------------------------------------------------------- +** Input: index = link index +** x = array of X-coordinates for vertex points +** y = array of Y-coordinates for vertex points +** count = number of vertex points +** Returns: error code +** Purpose: assigns a set of vertex points to a link +**---------------------------------------------------------------- +*/ +{ + Network *net = &p->network; + + Slink *link; + int i; + int err = 0; + + // Check that link exists + if (!p->Openflag) return 102; + if (index <= 0 || index > net->Nlinks) return 204; + link = &net->Link[index]; + + // Delete existing set of vertices + freelinkvertices(link); + + // Add each new vertex to the link + for (i = 0; i < count; i++) + { + err = addlinkvertex(link, x[i], y[i]); + if (err) break; + } + if (err) freelinkvertices(link); + return err; +} /******************************************************************** diff --git a/src/epanet2.c b/src/epanet2.c index ac2e210..2226277 100644 --- a/src/epanet2.c +++ b/src/epanet2.c @@ -7,7 +7,7 @@ Authors: see AUTHORS Copyright: see AUTHORS License: see LICENSE - Last Updated: 10/26/2019 + Last Updated: 10/29/2019 ****************************************************************************** */ @@ -512,6 +512,20 @@ int DLLEXPORT ENsetpipedata(int index, EN_API_FLOAT_TYPE length, return EN_setpipedata(_defaultProject, index, length, diam, rough, mloss); } +int DLLEXPORT ENgetvertexcount(int index, int *count) +{ + return EN_getvertexcount(_defaultProject, index, count); +} + +int DLLEXPORT ENgetvertex(int index, int vertex, double *x, double *y) +{ + return EN_getvertex(_defaultProject, index, vertex, x, y); +} + +int DLLEXPORT ENsetvertices(int index, double *x, double *y, int count) +{ + return EN_setvertices(_defaultProject, index, x, y, count); +} /******************************************************************** diff --git a/src/errors.dat b/src/errors.dat index 6d3a142..0930b52 100644 --- a/src/errors.dat +++ b/src/errors.dat @@ -53,6 +53,7 @@ DAT(251,"invalid parameter code") DAT(252,"invalid ID name") DAT(253,"nonexistent demand category") DAT(254,"node with no coordinates") +DAT(255,"invalid link vertex") DAT(257,"nonexistent rule") DAT(258,"nonexistent rule clause") DAT(259,"attempt to delete a node that still has links connected to it") diff --git a/src/funcs.h b/src/funcs.h index 95aa66a..ff2303f 100755 --- a/src/funcs.h +++ b/src/funcs.h @@ -7,7 +7,7 @@ Authors: see AUTHORS Copyright: see AUTHORS License: see LICENSE - Last Updated: 07/08/2019 + Last Updated: 10/29/2019 ****************************************************************************** */ #ifndef FUNCS_H @@ -41,6 +41,9 @@ Pdemand finddemand(Pdemand, int); int adddemand(Snode *, double, int, char *); void freedemands(Snode *); +int addlinkvertex(Slink *, double, double); +void freelinkvertices(Slink *); + void adjustpatterns(Network *, int); void adjustcurves(Network *, int); int resizecurve(Scurve *, int); @@ -101,6 +104,7 @@ int statusdata(Project *); int reportdata(Project *); int timedata(Project *); int optiondata(Project *); +int vertexdata(Project *); // ------- RULES.C ------------------ diff --git a/src/inpfile.c b/src/inpfile.c index 7060119..39e361f 100644 --- a/src/inpfile.c +++ b/src/inpfile.c @@ -7,7 +7,7 @@ Description: saves network data to an EPANET formatted text file Authors: see AUTHORS Copyright: see AUTHORS License: see LICENSE -Last Updated: 05/15/2019 +Last Updated: 10/29/2019 ****************************************************************************** */ @@ -76,7 +76,6 @@ void saveauxdata(Project *pr, FILE *f) // Write section heading to file switch (sect) { - case _VERTICES: case _LABELS: case _BACKDROP: case _TAGS: @@ -91,8 +90,6 @@ void saveauxdata(Project *pr, FILE *f) write = FALSE; switch (sect) { - case _VERTICES: - if (findlink(&pr->network, tok) || *tok == ';') write = TRUE; break; case _TAGS: if (*tok == ';' || (match("NODE", tok) && findnode(&pr->network, strtok(NULL, SEPSTR))) || @@ -788,6 +785,20 @@ int saveinpfile(Project *pr, const char *fname) fprintf(f, "\n %-31s %14.6f %14.6f", node->ID, node->X, node->Y); } + // Write [VERTICES] section + fprintf(f, "\n\n"); + fprintf(f, s_VERTICES); + for (i = 1; i <= net->Nlinks; i++) + { + link = &net->Link[i]; + if (link->Vertices != NULL) + { + for (j = 0; j < link->Vertices->Npts; j++) + fprintf(f, "\n %-31s %14.6f %14.6f", + link->ID, link->Vertices->X[j], link->Vertices->Y[j]); + } + } + // Save auxilary data to new input file fprintf(f, "\n"); saveauxdata(pr, f); diff --git a/src/input2.c b/src/input2.c index 6b89bfb..766ce24 100644 --- a/src/input2.c +++ b/src/input2.c @@ -7,7 +7,7 @@ Description: reads and interprets network data from an EPANET input file Authors: see AUTHORS Copyright: see AUTHORS License: see LICENSE -Last Updated: 05/15/2019 +Last Updated: 10/29/2019 ****************************************************************************** */ @@ -330,11 +330,11 @@ int newline(Project *pr, int sect, char *line) case _TIMES: return (timedata(pr)); case _OPTIONS: return (optiondata(pr)); case _COORDS: return (coordata(pr)); + case _VERTICES: return (vertexdata(pr)); // Data in these sections are not used for any computations case _LABELS: case _TAGS: - case _VERTICES: case _BACKDROP: return (0); } diff --git a/src/input3.c b/src/input3.c index c43866f..a6a6613 100644 --- a/src/input3.c +++ b/src/input3.c @@ -7,7 +7,7 @@ Description: parses network data from a line of an EPANET input file Authors: see AUTHORS Copyright: see AUTHORS License: see LICENSE -Last Updated: 10/26/2019 +Last Updated: 10/29/2019 ****************************************************************************** */ @@ -716,6 +716,37 @@ int coordata(Project *pr) return 0; } +int vertexdata(Project *pr) +/* + **-------------------------------------------------------------- + ** Input: none + ** Output: returns error code + ** Purpose: processes link vertex data + ** Format: + ** [VERTICES] + ** id x y + **-------------------------------------------------------------- + */ +{ + Network *net = &pr->network; + Parser *parser = &pr->parser; + + int j; + double x, y; + + // Check for valid link ID + if (parser->Ntokens < 3) return 201; + if ((j = findlink(net, parser->Tok[0])) == 0) return setError(parser, 0, 204); + + // Check for valid coordinate data + if (!getfloat(parser->Tok[1], &x)) return setError(parser, 1, 202); + if (!getfloat(parser->Tok[2], &y)) return setError(parser, 2, 202); + + // Add to link's list of vertex points + return addlinkvertex(&net->Link[j], x, y); +} + + int demanddata(Project *pr) /* **-------------------------------------------------------------- diff --git a/src/project.c b/src/project.c index bfe901c..e04459c 100644 --- a/src/project.c +++ b/src/project.c @@ -7,7 +7,7 @@ Authors: see AUTHORS Copyright: see AUTHORS License: see LICENSE - Last Updated: 10/26/2019 + Last Updated: 10/29/2019 ****************************************************************************** */ @@ -18,8 +18,6 @@ //*** For the Windows SDK _tempnam function ***// #ifdef _WIN32 #include -//#else -//#include #endif #include "types.h" @@ -363,6 +361,7 @@ int allocdata(Project *pr) } for (n = 0; n <= pr->parser.MaxLinks; n++) { + pr->network.Link[n].Vertices = NULL; pr->network.Link[n].Comment = NULL; } } @@ -409,8 +408,9 @@ void freedata(Project *pr) // Free memory for link data if (pr->network.Link != NULL) { - for (j = 0; j <= pr->parser.MaxLinks; j++) + for (j = 1; j <= pr->parser.MaxLinks; j++) { + freelinkvertices(&pr->network.Link[j]); free(pr->network.Link[j].Comment); } } @@ -538,6 +538,61 @@ void freedemands(Snode *node) node->D = NULL; } +int addlinkvertex(Slink *link, double x, double y) +/*---------------------------------------------------------------- +** Input: link = pointer to a network link +** x = x-coordinate of a new vertex +** y = y-coordiante of a new vertex +** Returns: an error code +** Purpose: adds to a link's collection of vertex points. +**---------------------------------------------------------------- +*/ +{ + static int CHUNKSIZE = 5; + int n; + Pvertices vertices; + if (link->Vertices == NULL) + { + vertices = (struct Svertices *) malloc(sizeof(struct Svertices)); + if (vertices == NULL) return 101; + vertices->Npts = 0; + vertices->Capacity = CHUNKSIZE; + vertices->X = (double *) calloc(vertices->Capacity, sizeof(double)); + vertices->Y = (double *) calloc(vertices->Capacity, sizeof(double)); + link->Vertices = vertices; + } + vertices = link->Vertices; + if (vertices->Npts >= vertices->Capacity) + { + vertices->Capacity += CHUNKSIZE; + vertices->X = realloc(vertices->X, vertices->Capacity * sizeof(double)); + vertices->Y = realloc(vertices->Y, vertices->Capacity * sizeof(double)); + } + if (vertices->X == NULL || vertices->Y == NULL) return 101; + n = vertices->Npts; + vertices->X[n] = x; + vertices->Y[n] = y; + vertices->Npts++; + return 0; +} + +void freelinkvertices(Slink *link) +/*---------------------------------------------------------------- +** Input: vertices = list of link vertex points +** Output: none +** Purpose: frees the memory used for a link's list of vertices. +**---------------------------------------------------------------- +*/ +{ + if (link->Vertices) + { + free(link->Vertices->X); + free(link->Vertices->Y); + free(link->Vertices); + link->Vertices = NULL; + } +} + int buildadjlists(Network *net) /* **-------------------------------------------------------------- diff --git a/src/types.h b/src/types.h index 326e615..713adc2 100755 --- a/src/types.h +++ b/src/types.h @@ -7,7 +7,7 @@ Authors: see AUTHORS Copyright: see AUTHORS License: see LICENSE - Last Updated: 10/26/2019 + Last Updated: 10/29/2019 ****************************************************************************** */ @@ -366,6 +366,15 @@ struct Ssource // Water Quality Source Object }; typedef struct Ssource *Psource; // Pointer to source object +struct Svertices // Coordinates of a link's vertices +{ + double *X; // array of x-coordinates + double *Y; // array of y-coordinates + int Npts; // number of vertex points + int Capacity; // capacity of coordinate arrays +}; +typedef struct Svertices *Pvertices; // Pointer to a link's vertices + typedef struct // Node Object { char ID[MAXID+1]; // node ID @@ -397,6 +406,7 @@ typedef struct // Link Object double Rc; // reaction coeff. LinkType Type; // link type StatusType Status; // initial status + Pvertices Vertices; // internal vertex coordinates int Rpt; // reporting flag int ResultIndex; // saved result index char *Comment; // link comment