Set/Get node & link tags added

This commit is contained in:
Lew Rossman
2025-02-19 09:49:09 -05:00
parent c8db9c1655
commit 7a1673994c
20 changed files with 252 additions and 61 deletions

View File

@@ -7,7 +7,7 @@
Authors: see AUTHORS
Copyright: see AUTHORS
License: see LICENSE
Last Updated: 06/26/2024
Last Updated: 02/14/2025
******************************************************************************
*/
@@ -203,7 +203,6 @@ int DLLEXPORT EN_openX(EN_Project p, const char *inpFile,
return openproject(p, inpFile, rptFile, outFile, TRUE);
}
int DLLEXPORT EN_gettitle(EN_Project p, char *line1, char *line2, char *line3)
/*----------------------------------------------------------------
** Input: None
@@ -263,6 +262,32 @@ int DLLEXPORT EN_setcomment(EN_Project p, int object, int index,
return setcomment(&p->network, object, index, comment);
}
int DLLEXPORT EN_gettag(EN_Project p, int object, int index, char *tag)
/*----------------------------------------------------------------
** Input: object = either EN_NODE or EN_LINK
** index = the object's index
** Output: tag = the tag string assigned to the object
** Returns: error code
** Purpose: Retrieves an object's tag string
**----------------------------------------------------------------
*/
{
return gettag(&p->network, object, index, tag);
}
int DLLEXPORT EN_settag(EN_Project p, int object, int index,
const char *tag)
/*----------------------------------------------------------------
** Input: object = either EN_NODE or EN_LINK
** index = the object's index
** tag = a descriptive comment to assign
** Returns: error code
** Purpose: Assigns a tag string to an object
**----------------------------------------------------------------
*/
{
return settag(&p->network, object, index, tag);
}
int DLLEXPORT EN_getcount(EN_Project p, int object, int *count)
/*----------------------------------------------------------------
** Input: object = type of object to count (see EN_CountType)
@@ -1790,7 +1815,6 @@ int DLLEXPORT EN_setqualtype(EN_Project p, int qualType, const char *chemName,
qual->Ctol *= Ucf[QUALITY];
if (qual->Qualflag == CHEM) // Chemical analysis
{
qual->TraceNode = 0;
strncpy(qual->ChemName, chemName, MAXID);
strncpy(qual->ChemUnits, chemUnits, MAXID);
strncpy(rpt->Field[QUALITY].Units, qual->ChemUnits, MAXID);
@@ -1808,16 +1832,10 @@ int DLLEXPORT EN_setqualtype(EN_Project p, int qualType, const char *chemName,
}
if (qual->Qualflag == AGE) // Water age analysis
{
qual->TraceNode = 0;
strncpy(qual->ChemName, w_AGE, MAXID);
strncpy(qual->ChemUnits, u_HOURS, MAXID);
strcpy(rpt->Field[QUALITY].Units, u_HOURS);
}
if (qual->Qualflag == NONE)
{
qual->TraceNode = 0;
strcpy(qual->ChemName, "");
}
// When changing from CHEM to AGE or TRACE, nodes initial quality
// values must be returned to their original ones
@@ -1923,8 +1941,6 @@ int DLLEXPORT EN_addnode(EN_Project p, const char *id, int nodeType, int *index)
}
// adjust indices of tanks/reservoirs in Rule premises (see RULES.C)
adjusttankrules(p, 1);
// adjust index of trace node
if (qual->TraceNode > net->Njuncs - 1) qual->TraceNode += 1;
}
// Actions taken when a new Tank/Reservoir is added
@@ -1974,6 +1990,7 @@ int DLLEXPORT EN_addnode(EN_Project p, const char *id, int nodeType, int *index)
node->X = MISSING;
node->Y = MISSING;
node->Comment = NULL;
node->Tag = NULL;
// Insert new node into hash table
hashtable_insert(net->NodeHashTable, node->ID, nIdx);
@@ -1996,7 +2013,6 @@ int DLLEXPORT EN_deletenode(EN_Project p, int index, int actionCode)
*/
{
Network *net = &p->network;
Quality *qual = &p->quality;
int i, nodeType, tankindex;
Snode *node;
@@ -2034,6 +2050,7 @@ int DLLEXPORT EN_deletenode(EN_Project p, int index, int actionCode)
freedemands(node);
free(node->S);
free(node->Comment);
free(node->Tag);
// Shift position of higher entries in Node & Coord arrays down one
for (i = index; i <= net->Nnodes - 1; i++)
@@ -2042,9 +2059,6 @@ int DLLEXPORT EN_deletenode(EN_Project p, int index, int actionCode)
// ... update node's entry in the hash table
hashtable_update(net->NodeHashTable, net->Node[i].ID, i);
}
// Adjust index of water quality trace node
if (qual->TraceNode > index) qual->TraceNode -= 1;
// If deleted node is a tank, remove it from the Tank array
if (nodeType != EN_JUNCTION)
@@ -3396,6 +3410,7 @@ int DLLEXPORT EN_addlink(EN_Project p, const char *id, int linkType,
link->Rpt = 0;
link->ResultIndex = 0;
link->Comment = NULL;
link->Tag = NULL;
link->Vertices = NULL;
hashtable_insert(net->LinkHashTable, link->ID, n);
@@ -3448,6 +3463,7 @@ int DLLEXPORT EN_deletelink(EN_Project p, int index, int actionCode)
// Remove link's comment and vertices
free(link->Comment);
free(link->Tag);
freelinkvertices(link);
// Shift position of higher entries in Link array down one

View File

@@ -1,13 +1,13 @@
/*
******************************************************************************
Project: OWA EPANET
Version: 2.2
Version: 2.3
Module: epanet2.c
Description: implementation of the legacy EPANET API functions
Authors: see AUTHORS
Copyright: see AUTHORS
License: see LICENSE
Last Updated: 09/28/2023
Last Updated: 02/14/2025
******************************************************************************
*/
@@ -127,6 +127,15 @@ int DLLEXPORT ENsetcomment(int object, int index, const char *comment)
return EN_setcomment(_defaultProject, object, index, comment);
}
int DLLEXPORT ENgettag(int object, int index, char *tag)
{
return EN_gettag(_defaultProject, object, index, tag);
}
int DLLEXPORT ENsettag(int object, int index, const char *tag)
{
return EN_settag(_defaultProject, object, index, tag);
}
int DLLEXPORT ENgetcount(int object, int *count)
{
return EN_getcount(_defaultProject, object, count);

View File

@@ -1,13 +1,13 @@
/*
******************************************************************************
Project: OWA EPANET
Version: 2.2
Version: 2.3
Module: funcs.h
Description: prototypes of external functions called by various modules
Authors: see AUTHORS
Copyright: see AUTHORS
License: see LICENSE
Last Updated: 06/26/2024
Last Updated: 02/14/2025
******************************************************************************
*/
#ifndef FUNCS_H
@@ -54,6 +54,8 @@ int setcontrol(Project *, int, int, double, int, double, Scontrol *);
int getcomment(Network *, int, int, char *);
int setcomment(Network *, int, int, const char *);
int gettag(Network *, int, int, char *);
int settag(Network *, int, int, const char *);
int namevalid(const char *);
void getTmpName(char *);
@@ -109,6 +111,7 @@ int reportdata(Project *);
int timedata(Project *);
int optiondata(Project *);
int vertexdata(Project *);
int tagdata(Project *);
// ------- RULES.C ------------------

View File

@@ -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: 02/11/2025
Last Updated: 02/14/2025
******************************************************************************
*/
@@ -44,7 +44,6 @@ void saveauxdata(Project *pr, FILE *f)
{
int sect, newsect;
char *tok;
char write;
char line[MAXLINE + 1];
char s[MAXLINE + 1];
FILE *InFile = pr->parser.InFile;
@@ -79,7 +78,6 @@ void saveauxdata(Project *pr, FILE *f)
{
case _LABELS:
case _BACKDROP:
case _TAGS:
fprintf(f, "\n%s", line);
}
}
@@ -88,22 +86,15 @@ void saveauxdata(Project *pr, FILE *f)
// Write line of auxilary data to file
else
{
write = FALSE;
switch (sect)
{
case _TAGS:
if (*tok == ';' ||
(match("NODE", tok) && findnode(&pr->network, strtok(NULL, SEPSTR))) ||
(match("LINK", tok) && findlink(&pr->network, strtok(NULL, SEPSTR))))
write = TRUE;
break;
case _LABELS:
case _BACKDROP:
write = TRUE; break;
fprintf(f, "%s", line);
break;
default:
break;
}
if (write) fprintf(f, "%s", line);
}
}
fclose(InFile);
@@ -834,7 +825,23 @@ int saveinpfile(Project *pr, const char *fname)
}
else fprintf(f, "\n %-20sNO",field->Name);
}
// Write [TAGS] section
fprintf(f, "\n\n");
fprintf(f, s_TAGS);
fprintf(f, "\n;;%-8s\t%-31s\t%s", "Object", "ID", "Tag");
for (i = 1; i <= net->Nnodes; i++)
{
node = &net->Node[i];
if (node->Tag == NULL || strlen(node->Tag) == 0) continue;
fprintf(f, "\n %-8s\t%-31s\t%s", "NODE", node->ID, node->Tag);
}
for (i = 1; i <= net->Nlinks; i++)
{
link = &net->Link[i];
if (link->Tag == NULL || strlen(link->Tag) == 0) continue;
fprintf(f, "\n %-8s\t%-31s\t%s", "LINK", link->ID, link->Tag);
}
// Write [COORDINATES] section
fprintf(f, "\n\n");
fprintf(f, s_COORDS);

View File

@@ -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: 09/28/2023
Last Updated: 02/14/2025
******************************************************************************
*/
@@ -320,6 +320,7 @@ int newline(Project *pr, int sect, char *line)
case _REPORT: return (reportdata(pr));
case _TIMES: return (timedata(pr));
case _OPTIONS: return (optiondata(pr));
case _TAGS: return (tagdata(pr));
case _COORDS: return (coordata(pr));
case _VERTICES: return (vertexdata(pr));

View File

@@ -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: 02/11/2025
Last Updated: 02/14/2025
******************************************************************************
*/
@@ -2023,7 +2023,7 @@ int optionchoice(Project *pr, int n)
int optionvalue(Project *pr, int n)
/*
**-------------------------------------------------------------
** Input: *line = line read from input file
** Input: n = index of last input token
** Output: returns error code
** Purpose: processes numerical value [OPTIONS] data
** Formats:
@@ -2170,7 +2170,42 @@ int optionvalue(Project *pr, int n)
return 0;
}
int tagdata(Project *pr)
/*
**-------------------------------------------------------------
** Input: none
** Output: returns error code
** Purpose: processes [TAGS] data
** Formats:
** NODE id tag
** LINK id tag
**--------------------------------------------------------------
*/
{
Network *net = &pr->network;
Parser *parser = &pr->parser;
int j, n;
// Check for sufficient data
n = parser->Ntokens;
if (n < 3) return 201;
// First keyword is NODE
if (match(parser->Tok[0], w_NODE))
{
if ((j = findnode(net, parser->Tok[1])) == 0) return setError(parser, 0, 203);
xstrcpy(&net->Node[j].Tag, parser->Tok[2], MAXMSG);
}
// First keyword is LINK
else if (match(parser->Tok[0], w_LINK))
{
if ((j = findlink(net, parser->Tok[1])) == 0) return setError(parser, 0, 203);
xstrcpy(&net->Link[j].Tag, parser->Tok[2], MAXMSG);
}
return 0;
}
void changestatus(Network *net, int j, StatusType status, double y)
/*
**--------------------------------------------------------------

View File

@@ -9,7 +9,7 @@
License: see LICENSE
Last Updated: 08/02/2023
This module is based code by Steve Hill in Graphics Gems III,
This module is based on code by Steve Hill in Graphics Gems III,
David Kirk (ed.), Academic Press, Boston, MA, 1992
******************************************************************************
*/

View File

@@ -1,13 +1,13 @@
/*
******************************************************************************
Project: OWA EPANET
Version: 2.2
Version: 2.3
Module: project.c
Description: project data management routines
Authors: see AUTHORS
Copyright: see AUTHORS
License: see LICENSE
Last Updated: 02/08/2025
Last Updated: 02/14/2025
******************************************************************************
*/
@@ -448,11 +448,13 @@ int allocdata(Project *pr)
pr->network.Node[n].D = NULL; // node demand
pr->network.Node[n].S = NULL; // node source
pr->network.Node[n].Comment = NULL;
pr->network.Node[n].Tag = NULL;
}
for (n = 0; n <= pr->parser.MaxLinks; n++)
{
pr->network.Link[n].Vertices = NULL;
pr->network.Link[n].Comment = NULL;
pr->network.Link[n].Tag = NULL;
}
}
@@ -495,6 +497,7 @@ void freedata(Project *pr)
freedemands(&(pr->network.Node[j]));
free(pr->network.Node[j].S);
free(pr->network.Node[j].Comment);
free(pr->network.Node[j].Tag);
}
free(pr->network.Node);
}
@@ -506,6 +509,7 @@ void freedata(Project *pr)
{
freelinkvertices(&pr->network.Link[j]);
free(pr->network.Link[j].Comment);
free(pr->network.Link[j].Tag);
}
}
free(pr->network.Link);
@@ -1357,6 +1361,64 @@ int setcomment(Network *network, int object, int index, const char *newcomment)
network->Curve[index].Comment = xstrcpy(&comment, newcomment, MAXMSG);
return 0;
int gettag(Network *network, int object, int index, char *tag)
//----------------------------------------------------------------
// Input: object = a type of network object
// index = index of the specified object
// tag = the object's tag string
// Output: error code
// Purpose: gets the tag string assigned to an object.
//----------------------------------------------------------------
{
char *currenttag;
// Get pointer to specified object's tag
switch (object)
{
case NODE:
if (index < 1 || index > network->Nnodes) return 251;
currenttag = network->Node[index].Tag;
break;
case LINK:
if (index < 1 || index > network->Nlinks) return 251;
currenttag = network->Link[index].Tag;
break;
default:
strcpy(tag, "");
return 251;
}
// Copy the object's tag to the returned string
if (currenttag) strcpy(tag, currenttag);
else tag[0] = '\0';
return 0;
}
int settag(Network *network, int object, int index, const char *newtag)
//----------------------------------------------------------------
// Input: object = a type of network object
// index = index of the specified object
// newtag = new tag string
// Output: error code
// Purpose: sets the tag string of an object.
//----------------------------------------------------------------
{
char *tag;
switch (object)
{
case NODE:
if (index < 1 || index > network->Nnodes) return 251;
tag = network->Node[index].Tag;
network->Node[index].Tag = xstrcpy(&tag, newtag, MAXMSG);
return 0;
case LINK:
if (index < 1 || index > network->Nlinks) return 251;
tag = network->Link[index].Tag;
network->Link[index].Tag = xstrcpy(&tag, newtag, MAXMSG);
return 0;
default: return 251;
}
}

View File

@@ -1,13 +1,13 @@
/*
******************************************************************************
Project: OWA EPANET
Version: 2.2
Version: 2.3
Module: quality.c
Description: implements EPANET's water quality engine
Authors: see AUTHORS
Copyright: see AUTHORS
License: see LICENSE
Last Updated: 02/03/2020
Last Updated: 02/14/2025
******************************************************************************
*/
@@ -183,6 +183,7 @@ int initqual(Project *pr)
qual->MassBalance.reacted = 0.0;
qual->MassBalance.final = 0.0;
qual->MassBalance.ratio = 0.0;
qual->MassBalance.segCount = 0;
return errcode;
}

View File

@@ -1,13 +1,13 @@
/*
******************************************************************************
Project: OWA EPANET
Version: 2.2
Version: 2.3
Module: qualroute.c
Description: computes water quality transport over a single time step
Authors: see AUTHORS
Copyright: see AUTHORS
License: see LICENSE
Last Updated: 08/02/2023
Last Updated: 02/14/2025
******************************************************************************
*/
@@ -183,6 +183,7 @@ void evalnodeinflow(Project *pr, int k, long tstep, double *volin,
// ... recycle the used up segment
seg->prev = qual->FreeSeg;
qual->FreeSeg = seg;
qual->MassBalance.segCount--;
}
// ... otherwise just reduce this segment's volume
@@ -691,4 +692,5 @@ void addseg(Project *pr, int k, double v, double c)
if (qual->FirstSeg[k] == NULL) qual->FirstSeg[k] = seg;
if (qual->LastSeg[k] != NULL) qual->LastSeg[k]->prev = seg;
qual->LastSeg[k] = seg;
qual->MassBalance.segCount++;
}

View File

@@ -1,13 +1,13 @@
/*
******************************************************************************
Project: OWA EPANET
Version: 2.2
Version: 2.3
Module: report.c
Description: procedures for writing formatted text to a report file
Authors: see AUTHORS
Copyright: see AUTHORS
License: see LICENSE
Last Updated: 07/22/2019
Last Updated: 02/14/2025
******************************************************************************
*/
@@ -501,6 +501,8 @@ void writemassbalance(Project *pr)
writeline(pr, s1);
snprintf(s1, MAXMSG, "Mass Ratio: %-.5f", qual->MassBalance.ratio);
writeline(pr, s1);
snprintf(s1, MAXMSG, "Total Segments: %d", qual->MassBalance.segCount);
writeline(pr, s1);
snprintf(s1, MAXMSG, "================================\n");
writeline(pr, s1);
}

View File

@@ -7,7 +7,7 @@
Authors: see AUTHORS
Copyright: see AUTHORS
License: see LICENSE
Last Updated: 06/15/2024
Last Updated: 02/14/2025
******************************************************************************
*/
@@ -398,6 +398,7 @@ typedef struct // Node Object
int ResultIndex; // saved result index
NodeType Type; // node type
char *Comment; // node comment
char *Tag; // optional category tag
} Snode;
typedef struct // Link Object
@@ -421,6 +422,7 @@ typedef struct // Link Object
int Rpt; // reporting flag
int ResultIndex; // saved result index
char *Comment; // link comment
char *Tag; // optional category tag
} Slink;
typedef struct // Tank Object
@@ -549,6 +551,7 @@ typedef struct // Mass Balance Components
double reacted; // mass reacted in system
double final; // final mass in system
double ratio; // ratio of mass added to mass lost
int segCount; // total number of pipe segments used
} SmassBalance;
typedef struct