欧阳劲驰 vor 1 Monat
Commit
b91a2a7ec9

+ 38 - 0
.gitignore

@@ -0,0 +1,38 @@
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### IntelliJ IDEA ###
+.idea/modules.xml
+.idea/jarRepositories.xml
+.idea/compiler.xml
+.idea/libraries/
+*.iws
+*.iml
+*.ipr
+
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+.DS_Store

+ 61 - 0
pom.xml

@@ -0,0 +1,61 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <!--公司组织或名称-->
+    <groupId>com.shkpr</groupId>
+    <!--工件名-->
+    <artifactId>epanet-core</artifactId>
+    <!--版本号-->
+    <version>1.0.0</version>
+    <!--项目名-->
+    <name>EpanetCore</name>
+    <!--项目描述-->
+    <description>
+        EPANET 依赖库
+    </description>
+
+    <!--属性配置+统一版本管理-->
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+        <java.version>1.8</java.version>
+        <maven.compiler.source>1.8</maven.compiler.source>
+        <maven.compiler.target>1.8</maven.compiler.target>
+
+        <jna.version>5.17.0</jna.version>
+    </properties>
+
+    <!--依赖项-->
+    <dependencies>
+        <!--jna-->
+        <dependency>
+            <groupId>net.java.dev.jna</groupId>
+            <artifactId>jna</artifactId>
+            <version>${jna.version}</version>
+        </dependency>
+        <!--jna-platform-->
+        <dependency>
+            <groupId>net.java.dev.jna</groupId>
+            <artifactId>jna-platform</artifactId>
+            <version>${jna.version}</version>
+        </dependency>
+    </dependencies>
+
+    <!--构建脚本-->
+    <build>
+        <!--插件项-->
+        <plugins>
+            <!--maven-compiler-->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.8.1</version>
+                <configuration>
+                    <source>${maven.compiler.source}</source>
+                    <target>${maven.compiler.target}</target>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>

+ 11 - 0
src/main/java/com/shkpr/epanet/code/Epanet.java

@@ -0,0 +1,11 @@
+package com.shkpr.epanet.code;
+
+/**
+ * epanet
+ *
+ * @author 欧阳劲驰
+ * @since 1.0.0
+ */
+public interface Epanet {
+
+}

+ 27 - 0
src/main/java/com/shkpr/epanet/code/EpanetDefaultImpl.java

@@ -0,0 +1,27 @@
+package com.shkpr.epanet.code;
+
+import java.io.IOException;
+
+import static com.shkpr.epanet.code.LibraryMetadata.LIBRARY_NAME;
+
+/**
+ * epanet默认实现
+ *
+ * @author 欧阳劲驰
+ * @since 1.0.0
+ */
+public class EpanetDefaultImpl implements Epanet {
+    /**
+     * 库
+     */
+    private static final EpanetLibrary library;
+
+    static {
+        try {
+            library = LibraryLoader.load(LIBRARY_NAME, EpanetLibrary.class);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+}

+ 329 - 0
src/main/java/com/shkpr/epanet/code/EpanetLibrary.java

@@ -0,0 +1,329 @@
+package com.shkpr.epanet.code;
+
+import com.sun.jna.Library;
+import com.sun.jna.Pointer;
+import com.sun.jna.ptr.IntByReference;
+import com.sun.jna.ptr.PointerByReference;
+
+/**
+ * 本地库
+ *
+ * @author 欧阳劲驰
+ * @since 1.0.0
+ */
+public interface EpanetLibrary extends Library {
+    /*===================================================================
+       Project Functions
+    ===================================================================*/
+
+    /**
+     * Creates an EPANET project.
+     *
+     * @param ph an EPANET project handle that is passed into all other API functions.
+     * @return an error code.
+     * <p>
+     * EN_createproject must be called before any other API functions are used.
+     */
+    int EN_createproject(PointerByReference ph);
+
+    /**
+     * Deletes a currently opened EPANET project.
+     *
+     * @param ph an EPANET project handle which is returned as NULL.
+     * @return an error code.
+     * <p>
+     * EN_deleteproject should be called after all network analysis has been completed.
+     */
+    int EN_deleteproject(PointerByReference ph);
+
+    /**
+     * Runs a complete EPANET simulation.
+     *
+     * @param ph        an EPANET project handle.
+     * @param inpFile   the name of an existing EPANET-formatted input file.
+     * @param rptFile   the name of a report file to be created (or "" if not needed)
+     * @param outFile   the name of a binary output file to be created (or "" if not needed)
+     * @param pviewprog a callback function that takes a character string (char *) as its only parameter.
+     * @return an error code
+     * <p>
+     * The callback function should reside in and be used by the calling code to display
+     * the progress messages that EPANET generates as it carries out its computations.
+     */
+    int EN_runproject(Pointer ph, String inpFile, String rptFile, String outFile, Object pviewprog);
+
+    /**
+     * Initializes an EPANET project.
+     *
+     * @param ph           an EPANET project handle.
+     * @param rptFile      the name of a report file to be created (or "" if not needed).
+     * @param outFile      the name of a binary output file to be created (or "" if not needed).
+     * @param unitsType    the choice of flow units (see EN_FlowUnits).
+     * @param headLossType the choice of head loss formula (see EN_HeadLossType).
+     * @return an error code.
+     * <p>
+     * This function should be called immediately after EN_createproject if an EPANET-formatted input
+     * file will not be used to supply network data.
+     */
+    int EN_init(Pointer ph, String rptFile, String outFile, int unitsType, int headLossType);
+
+    /**
+     * Reads an EPANET input file with no errors allowed.
+     *
+     * @param ph      an EPANET project handle.
+     * @param inpFile the name of an existing EPANET-formatted input file.
+     * @param rptFile the name of a report file to be created (or "" if not needed).
+     * @param outFile the name of a binary output file to be created (or "" if not needed).
+     * @return an error code.
+     * <p>
+     * This function should be called immediately after EN_createproject if an EPANET-formatted
+     * input file will be used to supply network data.
+     */
+    int EN_open(Pointer ph, String inpFile, String rptFile, String outFile);
+
+    /**
+     * Retrieves the title lines of the project
+     *
+     * @param ph        an EPANET project handle.
+     * @param out_line1 first title line
+     * @param out_line2 second title line
+     * @param out_line3 third title line
+     * @return an error code
+     */
+    int EN_gettitle(Pointer ph, byte[] out_line1, byte[] out_line2, byte[] out_line3);
+
+    /**
+     * Sets the title lines of the project
+     *
+     * @param ph    an EPANET project handle.
+     * @param line1 first title line
+     * @param line2 second title line
+     * @param line3 third title line
+     * @return an error code
+     */
+    int EN_settitle(Pointer ph, String line1, String line2, String line3);
+
+    /*===================================================================
+       Hydraulic Analysis Functions
+    ===================================================================*/
+
+    /**
+     * Runs a complete hydraulic simulation with results for all time periods
+     * written to a temporary hydraulics file.
+     *
+     * @param ph an EPANET project handle.
+     * @return an error code.
+     * <p>
+     * Use EN_solveH to generate a complete hydraulic solution which can stand alone
+     * or be used as input to a water quality analysis.
+     */
+    int EN_solveH(Pointer ph);
+
+    /**
+     * Uses a previously saved binary hydraulics file to supply a project's hydraulics.
+     *
+     * @param ph       an EPANET project handle.
+     * @param filename the name of the binary file containing hydraulic results.
+     * @return an error code.
+     * <p>
+     * Call this function to re-use a set of hydraulic analysis results saved previously.
+     */
+    int EN_usehydfile(Pointer ph, String filename);
+
+    /**
+     * Opens a project's hydraulic solver.
+     *
+     * @param ph an EPANET project handle.
+     * @return an error code.
+     * <p>
+     * Call EN_openH prior to running the first hydraulic analysis.
+     */
+    int EN_openH(Pointer ph);
+
+    /*===================================================================
+       Water Quality Analysis Functions
+    ===================================================================*/
+
+    /**
+     * Runs a complete water quality simulation with results at uniform
+     * reporting intervals written to the project's binary output file.
+     *
+     * @param ph an EPANET project handle.
+     * @return an error code.
+     * <p>
+     * A hydraulic analysis must have been run and saved to a hydraulics file before
+     * calling EN_solveQ.
+     */
+    int EN_solveQ(Pointer ph);
+
+    /**
+     * Opens a project's water quality solver.
+     *
+     * @param ph an EPANET project handle.
+     * @return an error code.
+     * <p>
+     * Call EN_openQ prior to running the first water quality analysis.
+     */
+    int EN_openQ(Pointer ph);
+
+    /*===================================================================
+       Reporting Functions
+    ===================================================================*/
+
+    /**
+     * Sets a user-supplied callback function for reporting
+     *
+     * @param ph       an EPANET project handle.
+     * @param callback a function pointer used for reporting.
+     * @return an error code.
+     * <p>
+     * The callback function replaces the project's report file as
+     * the destination for all output written by EN_writeline.
+     */
+    int EN_setreportcallback(Pointer ph, Object callback);
+
+    /**
+     * Writes a line of text to a project's report file.
+     *
+     * @param ph   an EPANET project handle.
+     * @param line a text string to write.
+     * @return an error code.
+     */
+    int EN_writeline(Pointer ph, String line);
+
+    /**
+     * Writes simulation results in a tabular format to a project's report file.
+     *
+     * @param ph an EPANET project handle.
+     * @return an error code
+     * <p>
+     * Either a full hydraulic analysis or full hydraulic and water quality analysis must
+     * have been run, with results saved to file, before EN_report is called.
+     */
+    int EN_report(Pointer ph);
+
+    /*===================================================================
+       Node Functions
+    ===================================================================*/
+
+    /**
+     * Adds a new node to a project.
+     *
+     * @param ph        an EPANET project handle.
+     * @param id        the ID name of the node to be added.
+     * @param nodeType  the type of node being added (see EN_NodeType)
+     * @param out_index the index of the newly added node
+     * @return an error code.
+     * <p>
+     * When a new node is created all of its properties are set to 0.
+     */
+    int EN_addnode(Pointer ph, String id, int nodeType, IntByReference out_index);
+
+    /**
+     * Gets the index of a node given its ID name.
+     *
+     * @param ph        an EPANET project handle.
+     * @param id        a node ID name.
+     * @param out_index the node's index (starting from 1).
+     * @return an error code
+     */
+    int EN_getnodeindex(Pointer ph, String id, IntByReference out_index);
+
+    /**
+     * Gets the ID name of a node given its index.
+     *
+     * @param ph     an EPANET project handle.
+     * @param index  a node's index (starting from 1).
+     * @param out_id the node's ID name.
+     * @return an error code
+     */
+    int EN_getnodeid(Pointer ph, int index, byte[] out_id);
+
+    /*===================================================================
+       Link Functions
+    ===================================================================*/
+
+    /**
+     * Adds a new link to a project.
+     *
+     * @param ph        an EPANET project handle.
+     * @param id        the ID name of the link to be added.
+     * @param linkType  The type of link being added (see EN_LinkType)
+     * @param fromNode  The ID name of the link's starting node.
+     * @param toNode    The ID name of the link's ending node.
+     * @param out_index the index of the newly added link.
+     * @return an error code.
+     */
+    int EN_addlink(Pointer ph, String id, int linkType, String fromNode, String toNode, IntByReference out_index);
+
+    /**
+     * Gets the index of a link given its ID name.
+     *
+     * @param ph        an EPANET project handle.
+     * @param id        a link's ID name.
+     * @param out_index the link's index (starting from 1).
+     * @return an error code.
+     */
+    int EN_getlinkindex(Pointer ph, String id, IntByReference out_index);
+
+    /*===================================================================
+       Time Pattern Functions
+    ===================================================================*/
+
+    /**
+     * Adds a new time pattern to a project.
+     *
+     * @param ph an EPANET project handle.
+     * @param id the ID name of the pattern to add.
+     * @return an error code.
+     * <p>
+     * The new pattern contains a single time period whose factor is 1.0.
+     */
+    int EN_addpattern(Pointer ph, String id);
+
+    /*===================================================================
+       Data Curve Functions
+    ===================================================================*/
+
+    /**
+     * Adds a new data curve to a project.
+     *
+     * @param ph an EPANET project handle.
+     * @param id The ID name of the curve to be added.
+     * @return an error code.
+     * <p>
+     * The new curve contains a single data point (1.0, 1.0).
+     */
+    int EN_addcurve(Pointer ph, String id);
+
+    /*===================================================================
+       Simple Controls Functions
+    ===================================================================*/
+
+    /**
+     * Adds a new simple control to a project.
+     *
+     * @param ph        an EPANET project handle.
+     * @param type      the type of control to add (see EN_ControlType).
+     * @param linkIndex the index of a link to control (starting from 1).
+     * @param setting   control setting applied to the link.
+     * @param nodeIndex index of the node used to control the link
+     * @param level     action level that triggers the control.
+     * @param out_index index of the new control.
+     * @return an error code.
+     */
+    int EN_addcontrol(Pointer ph, int type, int linkIndex, double setting,
+                      int nodeIndex, double level, IntByReference out_index);
+
+    /*===================================================================
+       Rule-Based Controls Functions
+    ===================================================================*/
+
+    /**
+     * Adds a new rule-based control to a project.
+     *
+     * @param ph   an EPANET project handle.
+     * @param rule text of the rule following the format used in an EPANET input file.
+     * @return an error code.
+     */
+    int EN_addrule(Pointer ph, String rule);
+}

+ 101 - 0
src/main/java/com/shkpr/epanet/code/LibraryLoader.java

@@ -0,0 +1,101 @@
+package com.shkpr.epanet.code;
+
+import com.sun.jna.Library;
+import com.sun.jna.Native;
+import com.sun.jna.Platform;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+
+/**
+ * 库加载器
+ *
+ * @author 欧阳劲驰
+ * @since 1.0.0
+ */
+public class LibraryLoader {
+    /**
+     * 加载库
+     *
+     * @param name           库文件名
+     * @param interfaceClass 库类型
+     * @param <T>            库类型
+     * @return 库实例
+     * @throws IOException 文件提取过程中IO异常
+     */
+    public static <T extends Library> T load(String name, Class<T> interfaceClass) throws IOException {
+        String libPath = extractLibrary(name);
+        return Native.load(libPath, interfaceClass);
+    }
+
+
+    /**
+     * 提取本地库文件
+     *
+     * @param libraryName 库文件名称
+     * @return 提取后的库文件路径
+     * @throws IOException 文件提取过程中IO异常
+     */
+    private static String extractLibrary(String libraryName) throws IOException {
+        if (libraryName == null || libraryName.trim().isEmpty())
+            throw new IllegalArgumentException("库文件名称不能为空");
+
+        // 追加后缀
+        Path sourcePath = appendLibrarySuffix(libraryName);
+        String resourcePath = sourcePath.toString().replace(File.separatorChar, '/');
+
+        // 从resource提取库文件
+        File sourceFile = Native.extractFromResourcePath(resourcePath, null);
+
+        // 创建临时文件
+        Path tempFile = Files.createTempFile(LibraryMetadata.TEMP_DIR_PREFIX, "-" + sourcePath.getFileName());
+        tempFile.toFile().deleteOnExit();
+
+        // 复制库文件到临时文件
+        try (InputStream inputStream = Files.newInputStream(sourceFile.toPath())) {
+            Files.copy(inputStream, tempFile, StandardCopyOption.REPLACE_EXISTING);
+        }
+
+        return tempFile.toString();
+    }
+
+    /**
+     * 为本地库文件路径添加平台相关的后缀名
+     * <li> Windows: .dll
+     * <li> MacOS: .dylib
+     * <li> Linux/其他: .so
+     *
+     * @param path 库文件路径(可以是绝对路径或相对路径)
+     * @return 添加了对应平台后缀的完整路径
+     * @throws IllegalArgumentException 如果path为null或为空
+     */
+    private static Path appendLibrarySuffix(String path) {
+        if (path == null || path.trim().isEmpty()) throw new IllegalArgumentException("路径不能为空");
+
+        // 文件路径
+        Path filePath = Paths.get(path);
+
+        // 获取文件名
+        String fileName = filePath.getFileName().toString();
+        // 如果文件名已包含扩展名,直接返回原路径
+        if (fileName.contains(".")) return filePath;
+
+        // 获取父目录路径
+        Path directory = filePath.getParent();
+
+        // 根据不同操作系统平台添加对应的库文件后缀
+        String libName = fileName + (Platform.isWindows() ? ".dll" :
+                Platform.isMac() ? ".dylib" :
+                        ".so");
+        // 添加前缀
+        if (!libName.startsWith("lib")) libName = "lib" + libName;
+
+        // 拼接路径
+        return directory == null ? Paths.get(libName) : directory.resolve(libName);
+    }
+}

+ 22 - 0
src/main/java/com/shkpr/epanet/code/LibraryMetadata.java

@@ -0,0 +1,22 @@
+package com.shkpr.epanet.code;
+
+/**
+ * 库元数据
+ *
+ * @author 欧阳劲驰
+ * @since 1.0.0
+ */
+public interface LibraryMetadata {
+    /**
+     * 临时目录前缀
+     */
+    String TEMP_DIR_PREFIX = "native-lib-";
+    /**
+     * 库名称
+     */
+    String LIBRARY_NAME = "epanet2";
+    /**
+     * 库版本
+     */
+    String LIBRARY_VERSION = "2.3.0";
+}

BIN
src/main/resources/libepanet2.dylib