diff --git a/ReleaseNotes2_2.md b/ReleaseNotes2_2.md
index d2087e0..e565f1a 100644
--- a/ReleaseNotes2_2.md
+++ b/ReleaseNotes2_2.md
@@ -200,6 +200,10 @@ With this change EPANET 2.2 now produces perfect mass balances when tested again
|`EN_setcomment` |Assigns a descriptive comment to an object|
|`EN_clearreport` |Clears the contents of a project's report file |
|`EN_copyreport` | Copies the contents of a project's report file |
+|`EN_getresultindex` | Gets the order in which a node or link was saved to file |
+|`EN_getvertexcount` | Gets the number of vertex points in a link |
+|`EN_getvertex` | Gets the coordinates of a vertex point in a link |
+|`EN_setvertices` | Assigns a new set of vertex points to a link |
In addition to these new functions, a tank's volume curve `EN_VOLCURVE` can be set using `EN_setnodevalue` and `EN_setlinkvalue` can now be used to set the following pump properties:
- `EN_PUMP_POWER` (constant power rating)
- `EN_PUMP_HCURVE` (head characteristic curve)
diff --git a/doc/input-file.dox b/doc/input-file.dox
index 2a3e45b..cd4c103 100644
--- a/doc/input-file.dox
+++ b/doc/input-file.dox
@@ -4,16 +4,16 @@ The Input file is a standard EPANET input data file that describes the system be
The file is organized by sections where each section begins with a keyword enclosed in brackets. The various keywords are listed below. Click on a section to see the format of the data it contains.
-|Network Components |System Operation |Water Quality |Options & Reporting |
-|:-------------------------------|:-------------------------------|:--------------------------------|:-------------------------------|
-|@subpage TitlePage "[Title]" |@subpage CurvesPage "[Curves]" |@subpage QualPage "[Quality]" |@subpage OptionsPage "[Options]"|
-|@subpage JuncsPage "[Junctions]"|@subpage PatsPage "[Patterns]" |@subpage ReactsPage "[Reactions]"|@subpage TimesPage "[Times]" |
-|@subpage ResvPage "[Reservoirs]"|@subpage EnergyPage "[Energy]" |@subpage SourcesPage "[Sources]" |@subpage ReportPage "[Report]" |
-|@subpage TanksPage "[Tanks]" |@subpage StatusPage "[Status]" |@subpage MixingPage "[Mixing]" | |
-|@subpage PipesPage "[Pipes]" |@subpage CtrlsPage "[Controls]" | | |
-|@subpage PumpsPage "[Pumps]" |@subpage RulesPage "[Rules]" | | |
-|@subpage ValvesPage "[Valves]" |@subpage DmndsPage "[Demands]" | | |
-|@subpage EmitsPage "[Emitters]" | | | |
+|Network Components |System Operation |Water Quality |Options & Reporting |GUI Support |
+|:-------------------------------|:-------------------------------|:--------------------------------|:-------------------------------|------------------------------------|
+|@subpage TitlePage "[Title]" |@subpage CurvesPage "[Curves]" |@subpage QualPage "[Quality]" |@subpage OptionsPage "[Options]"|@subpage BackdropPage "[Backdrop]" |
+|@subpage JuncsPage "[Junctions]"|@subpage PatsPage "[Patterns]" |@subpage ReactsPage "[Reactions]"|@subpage TimesPage "[Times]" |@subpage CoordsPage "[Coordinates]" |
+|@subpage ResvPage "[Reservoirs]"|@subpage EnergyPage "[Energy]" |@subpage SourcesPage "[Sources]" |@subpage ReportPage "[Report]" |@subpage VertexPage "[Vertices]" |
+|@subpage TanksPage "[Tanks]" |@subpage StatusPage "[Status]" |@subpage MixingPage "[Mixing]" | |@subpage LabelsPage "[Labels]" |
+|@subpage PipesPage "[Pipes]" |@subpage CtrlsPage "[Controls]" | | | |
+|@subpage PumpsPage "[Pumps]" |@subpage RulesPage "[Rules]" | | | |
+|@subpage ValvesPage "[Valves]" |@subpage DmndsPage "[Demands]" | | | |
+|@subpage EmitsPage "[Emitters]" | | | | |
The order of sections is not important. However, whenever a node or link is referred to in a section it must have already been defined in the [JUNCTIONS], [RESERVOIRS], [TANKS], [PIPES], [PUMPS], or [VALVES] sections. Thus it is recommended that these sections be placed first.
@@ -21,6 +21,8 @@ Each section can contain one or more lines of data. Blank lines can appear anywh
The ID labels used to identify nodes, links, curves and patterns can be any combination of up to 31 characters and numbers.
+The GUI Support sections are provided to assist an external program that wishes to draw a visual representation of a project's network.
+
*/
/**
@@ -1040,3 +1042,111 @@ __Remarks:__
|GPV (general purpose valve) | ID of head loss curve |
2. Shutoff valves and check valves are considered to be part of a pipe, not a separate control valve component (see @ref PipesPage).
*/
+
+/**
+@page BackdropPage [BACKDROP]
+
+__Purpose:__
+
+Identifies a backdrop image and dimensions for visualizing the network's layout.
+
+__Formats:__
+
+ | DIMENSIONS | LLx LLy URx URy |
+ | UNITS | FEET/METERS/DEGREES/NONE |
+ | FILE | filename |
+ | OFFSET | X Y |
+
+
+__Definitions:__
+
+DIMENSIONS provides the X and Y coordinates of the lower-left and upper-right corners of the network's
+bounding rectangle. Defaults are the extents of the nodal coordinates supplied in the @ref CoordsPage "[COORDINATES]" section.
+
+UNITS specifies the units that the network's dimensions are given in. Default is NONE.
+
+FILE supplies the name of the file that contains a backdrop image for the network.
+
+OFFSET lists the X and Y distance that the upper-left corner of the backdrop image is offset from the
+upper-left corner of the network’s bounding rectangle. Default is zero offset.
+
+__Remarks:__
+
+1. The [BACKDROP] section is optional and only provides support for an external GUI program that uses the EPANET engine.
+
+2. Only Windows Enhanced Metafiles and bitmap files can be used as backdrops.
+*/
+
+/**
+@page CoordsPage [COORDINATES]
+
+__Purpose:__
+
+Assigns map coordinates to network's nodes.
+
+__Format__:
+
+One line for each node containing:
+- Node ID label
+- X-coordinate
+- Y-coordinate
+
+__Remarks:__
+
+1. Include one line for each node that has coordinates.
+
+2. The coordinates represent the distance from the node to an arbitrary origin at the lower left of the network. Any convenient units of measure for this distance can be used.
+
+3. The locations of the nodes need not be to actual scale.
+
+4. A [COORDINATES] section is optional and only provides support for an external GUI program that uses the EPANET engine.
+*/
+
+/**
+@page VertexPage [VERTICES]
+
+__Purpose:__
+
+Assigns interior vertex points that describe the shape of network links.
+
+__Format:__
+
+One line for each vertex point in each link containing such points that includes:
+- Link ID label
+- X-coordinate
+- Y-coordinate
+
+__Remarks:__
+
+1. Vertex points allow links to be drawn as polylines instead of simple straight-lines between their end nodes.
+
+2. The coordinates refer to the same coordinate system used for node and label coordinates.
+
+3. A [VERTICES] section is optional and only provides support for an external GUI program that uses the EPANET engine.
+*/
+
+/**
+@page LabelsPage [LABELS]
+
+__Purpose:__
+
+Assigns coordinates to labels added to a network's visualization.
+
+__Format:__
+
+One line for each label containing:
+- X-coordinate
+- Y-coordinate
+- Text of label in double quotes
+- ID label of an anchor node (optional)
+
+__Remarks:__
+
+1. Include one line for each label.
+
+2. The coordinates refer to the upper left corner of the label and are with respect to an arbitrary origin at the lower left of the network.
+
+3. The optional anchor node anchors the label to the node when the network layout is re-scaled during zoom-in operations.
+
+4. The [LABELS] section is optional and only provides support for an external GUI program that uses the EPANET engine.
+*/
diff --git a/doc/modules.dox b/doc/modules.dox
index f0dd117..a26ec22 100644
--- a/doc/modules.dox
+++ b/doc/modules.dox
@@ -120,6 +120,8 @@ These are the toolkit's enumerated types whose members are used as function argu
@fn int EN_getversion(int *version)
@fn int EN_geterror(int errcode, char *errmsg, int maxLen)
@fn int EN_getstatistic(EN_Project ph, int type, double* value)
+@fn int EN_getresultindex(EN_Project ph, int type, int index, int *value)
+
@}
*/
@@ -193,6 +195,9 @@ These are the toolkit's enumerated types whose members are used as function argu
@fn int EN_getpumptype(EN_Project ph, int linkIndex, int *pumpType)
@fn int EN_getheadcurveindex(EN_Project ph, int pumpIndex, int *curveIndex)
@fn int EN_setheadcurveindex(EN_Project ph, int pumpIndex, int curveIndex)
+@fn int EN_getvertexcount(EN_Project ph, int index, int *count)
+@fn int EN_getvertex(EN_Project ph, int index, int vertex, double *x, double *y)
+@fn int EN_setvertices(EN_Project ph, int index, double *x, double *y, int count)
@}
*/
diff --git a/doc/toolkit-files.dox b/doc/toolkit-files.dox
index 799ded9..28266ff 100644
--- a/doc/toolkit-files.dox
+++ b/doc/toolkit-files.dox
@@ -151,7 +151,7 @@ The Toolkit provides several header files that are needed to develop C/C++ appli
- `epanet2_2.h` contains declarations of the multi-threaded version of the Toolkit (the EN_xxx named functions).
- `epanet2_enums.h` contains definitions of the symbolic constants used by the Toolkit.
- `epanet2.lib` must be linked in to any Toolkit application compiled for Windows using MS Visual C++.
-Developers need to issue an `#include` directive for either `epanet2.h` or `epanet2_2.h` in their C/C++ code depending on whether they are building a single-threaded or multi-threaded application. There is no need to explicitly include `epanet2_enums.h` as it is automatically included by both of the other header files.
+Developers need to issue an include directive for either `epanet2.h` or `epanet2_2.h` in their C/C++ code depending on whether they are building a single-threaded or multi-threaded application. There is no need to explicitly include `epanet2_enums.h` as it is automatically included by both of the other header files.
Several additional function declaration files that provide bindings for other programming languages are included with the Toolkit package:
- `epanet2.bas` for Visual Basic for Applications and Visual Basic 6
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..d5c823a 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
******************************************************************************
*/
@@ -638,6 +638,20 @@ typedef struct Project *EN_Project;
*/
int DLLEXPORT EN_getstatistic(EN_Project ph, int type, double* value);
+ /**
+ @brief Retrieves the order in which a node or link appears in an @ref OutFile "output file".
+ @param ph an EPANET project handle.
+ @param type a type of element (either @ref EN_NODE or @ref EN_LINK).
+ @param index the element's current index (starting from 1).
+ @param[out] value the order in which the element's results were written to file.
+ @return an error code.
+
+ If the element does not appear in the file then its result index is 0.
+
+ This function can be used to correctly retrieve results from an EPANET binary output file
+ after the order of nodes or links in a network's database has been changed due to editing
+ operations.
+ */
int DLLEXPORT EN_getresultindex(EN_Project ph, int type, int index, int *value);
/********************************************************************
@@ -1214,6 +1228,38 @@ 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 (starting from 1).
+ @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 (starting from 1).
+ @param vertex a vertex point index (starting from 1).
+ @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 (starting from 1).
+ @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.
+
+ Replaces any existing vertices previously assigned to the link.
+ */
+ 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..434c6dc 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
******************************************************************************
*/
@@ -3240,6 +3240,7 @@ int DLLEXPORT EN_addlink(EN_Project p, char *id, int linkType,
link->Rpt = 0;
link->ResultIndex = 0;
link->Comment = NULL;
+ link->Vertices = NULL;
hashtable_insert(net->LinkHashTable, link->ID, n);
*index = n;
@@ -3289,8 +3290,9 @@ int DLLEXPORT EN_deletelink(EN_Project p, int index, int actionCode)
// Remove link from its hash table
hashtable_delete(net->LinkHashTable, link->ID);
- // Remove link's comment
- free(net->Link[index].Comment);
+ // Remove link's comment and vertices
+ free(link->Comment);
+ freelinkvertices(link);
// Shift position of higher entries in Link array down one
for (i = index; i <= net->Nlinks - 1; i++)
@@ -3985,17 +3987,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 +4026,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