Quellcode durchsuchen

Merge branch 'master' into project-local-jg

dengsixing vor 8 Monaten
Ursprung
Commit
ec12f0a614
100 geänderte Dateien mit 7002 neuen und 27 gelöschten Zeilen
  1. 7 1
      4dkankan-common-utils/pom.xml
  2. 1 0
      4dkankan-common-utils/src/main/java/com/fdkankan/common/constant/ErrorCode.java
  3. 3 1
      4dkankan-common-utils/src/main/java/com/fdkankan/common/constant/FileBizType.java
  4. 3 1
      4dkankan-common-utils/src/main/java/com/fdkankan/common/constant/SceneAsynFuncType.java
  5. 2 0
      4dkankan-common-utils/src/main/java/com/fdkankan/common/constant/SceneSource.java
  6. 71 20
      4dkankan-common-utils/src/main/java/com/fdkankan/common/util/AesUtil.java
  7. 99 0
      4dkankan-common-utils/src/main/java/com/fdkankan/common/util/CmdUtils.java
  8. 42 0
      4dkankan-common-utils/src/main/java/com/fdkankan/common/util/EncryptDecrypt.java
  9. 72 0
      4dkankan-common-utils/src/main/java/com/fdkankan/common/util/RsaUtil.java
  10. 79 0
      4dkankan-common-utils/src/main/java/com/fdkankan/common/util/StreamGobblerLine.java
  11. 18 0
      4dkankan-common-web/pom.xml
  12. 2 0
      4dkankan-common-web/src/main/java/com/fdkankan/web/interceptor/CheckInnerApiPermitAspect.java
  13. 15 2
      4dkankan-common-web/src/main/java/com/fdkankan/web/response/BaseResponseAdvice.java
  14. 26 2
      4dkankan-common-web/src/main/java/com/fdkankan/web/util/WebUtil.java
  15. 43 0
      4dkankan-utils-disruptormq/pom.xml
  16. 84 0
      4dkankan-utils-disruptormq/src/main/java/com/fdkankan/disruptormq/BaseDisruptorQueue.java
  17. 12 0
      4dkankan-utils-disruptormq/src/main/java/com/fdkankan/disruptormq/DisruptorEvent.java
  18. 26 0
      4dkankan-utils-disruptormq/src/main/java/com/fdkankan/disruptormq/DisruptorExcepitonHandler.java
  19. 29 0
      4dkankan-utils-disruptormq/src/main/java/com/fdkankan/disruptormq/DisruptorHandler.java
  20. 73 0
      4dkankan-utils-disruptormq/src/main/java/com/fdkankan/disruptormq/DisruptorProperties.java
  21. 1 0
      4dkankan-utils-disruptormq/src/main/resources/META-INF/spring.factories
  22. 62 0
      4dkankan-utils-dxf/pom.xml
  23. 13 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/fdjson/vo/FdFloors.java
  24. 15 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/fdjson/vo/FdFloorsPanJson.java
  25. 28 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/fdjson/vo/FdPoints.java
  26. 18 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/fdjson/vo/FdWalls.java
  27. 405 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/DxfDocWriter.java
  28. 37 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/DxfGenSupport.java
  29. 22 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/Vector3.java
  30. 111 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/enums/LineWidthEnum.java
  31. 76 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/kml/CGCS2000ToWGS84.java
  32. 225 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/kml/GenerateKml.java
  33. 35 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/model/DxfArc.java
  34. 45 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/model/DxfCircle.java
  35. 68 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/model/DxfEllipse.java
  36. 39 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/model/DxfHatch.java
  37. 45 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/model/DxfLine.java
  38. 90 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/model/DxfLwPolyLine.java
  39. 46 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/model/DxfPoint.java
  40. 42 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/model/DxfRay.java
  41. 81 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/model/DxfSolid.java
  42. 100 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/model/DxfText.java
  43. 24 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/model/DxfXLine.java
  44. 94 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/model/base/BaseDxfEntity.java
  45. 298 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/model/base/Color.java
  46. 42 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/model/base/DxfEntity.java
  47. 33 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/model/support/DxfExtent.java
  48. 42 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/util/DxfLineBuilder.java
  49. 69 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/util/DxfUtil.java
  50. 29 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/util/FileUtil.java
  51. 90 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/util/FreemarkerSupport.java
  52. 127 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/util/PicAnalysis.java
  53. 63 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/util/StreamUtil.java
  54. 49 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/util/StringUtil.java
  55. 60 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/ParseDXF.java
  56. 170 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/analysis/DxfAnalysis.java
  57. 796 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/analysis/DxfEntitiesParse.java
  58. 114 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/analysis/DxfHeaderParse.java
  59. 38 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/constant/EntityNameConstant.java
  60. 19 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/constant/PolyLineConstant.java
  61. 55 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/enums/CadVersionEnum.java
  62. 40 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/enums/DxfEntitiesBaseEnum.java
  63. 102 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/enums/DxfSystemEnum.java
  64. 67 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/enums/entities/ArcEnum.java
  65. 56 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/enums/entities/CircleEnum.java
  66. 77 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/enums/entities/EllipseEnum.java
  67. 44 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/enums/entities/InsertEnum.java
  68. 65 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/enums/entities/LineEnum.java
  69. 71 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/enums/entities/MTextEnum.java
  70. 49 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/enums/entities/PointEnum.java
  71. 99 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/enums/entities/PolyLineEnum.java
  72. 71 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/enums/entities/TextEnum.java
  73. 77 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/enums/error/DxfAnalysisErrorEnum.java
  74. 27 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/enums/error/DxfFileErrorEnum.java
  75. 40 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/exception/DxfAnalysisException.java
  76. 22 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/exception/DxfException.java
  77. 29 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/exception/DxfFileException.java
  78. 53 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/model/DxfModel.java
  79. 58 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/model/GeometricModel.java
  80. 57 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/model/entities/GeometricArc.java
  81. 45 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/model/entities/GeometricCircle.java
  82. 75 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/model/entities/GeometricLine.java
  83. 41 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/model/entities/GeometricPoint.java
  84. 56 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/model/entities/GeometricPolyLine.java
  85. 65 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/model/entities/GeometricText.java
  86. 43 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/model/entities/GeometricVertex.java
  87. 91 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/model/headers/HeaderModel.java
  88. 76 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/resolver/DxfResolver.java
  89. 145 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/resolver/impl/DxfResolverImpl.java
  90. 69 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/transformation/DxfLineTransformation.java
  91. 21 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/transformation/GeometricTransform.java
  92. 44 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/transformation/TransformBuilder.java
  93. 292 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/transformation/impl/DxfLineTransformationImpl.java
  94. 52 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/transformation/impl/GeometricArcTransformImpl.java
  95. 53 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/transformation/impl/GeometricCircleTransformImpl.java
  96. 52 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/transformation/impl/GeometricLineTransformImpl.java
  97. 52 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/transformation/impl/GeometricPointTransformImpl.java
  98. 51 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/transformation/impl/GeometricPolyLineTransformImpl.java
  99. 52 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/transformation/impl/GeometricTextTransformImpl.java
  100. 0 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/transformation/model/DxfLine.java

+ 7 - 1
4dkankan-common-utils/pom.xml

@@ -84,5 +84,11 @@
             <artifactId>okhttp</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>com.github.ulisesbocchio</groupId>
+            <artifactId>jasypt-spring-boot-starter</artifactId>
+            <version>3.0.5</version>
+        </dependency>
+
     </dependencies>
-</project>
+</project>

+ 1 - 0
4dkankan-common-utils/src/main/java/com/fdkankan/common/constant/ErrorCode.java

@@ -23,6 +23,7 @@ public enum ErrorCode {
     MISSING_REQUIRED_PARAMETERS(4007,"缺少必要参数"),
     USER_NOT_LOGIN(4008, "用户未登录"),
     NOT_RECORD(4009, "暂无记录"),
+    USERNAME_PASSWORD_REQUIRE(4010, "账号密码不能为空"),
     ERROR_MSG(40010, "操作失败"),
     EMPTY_FILE(40011, "空文件"),
     AGENT_EXIST(40012, "经销商已存在"),

+ 3 - 1
4dkankan-common-utils/src/main/java/com/fdkankan/common/constant/FileBizType.java

@@ -14,7 +14,9 @@ public enum FileBizType {
     LINK_STYLE("link-style", "场景关联图标"),
     WATERMARK("waterMark", "水印"),
     BOX_POSTER("box-poster", "空间视频封面图"),
-    BILLBOARD_ICON("billboard-icon", "指示牌")
+    BILLBOARD_ICON("billboard-icon", "指示牌"),
+
+    CUT_MODEL("cutModel", "模型裁剪"),
     ;
 
     private String code;

+ 3 - 1
4dkankan-common-utils/src/main/java/com/fdkankan/common/constant/SceneAsynFuncType.java

@@ -2,7 +2,9 @@ package com.fdkankan.common.constant;
 
 public enum SceneAsynFuncType {
 
-    PANORAMIC_IMAGE("panorama", "全景图");
+    PANORAMIC_IMAGE("panorama", "全景图"),
+
+    MODEL("model", "模型");
 
     private String code;
     private String message;

+ 2 - 0
4dkankan-common-utils/src/main/java/com/fdkankan/common/constant/SceneSource.java

@@ -10,6 +10,8 @@ public enum SceneSource {
     ZT(3, "转台"),
     JG(4, "激光"),
     SG(5, "深光"),
+
+    QJKK(6, "全景看看"),
     YJHZ(11, "一键换装");
 
     private Integer code;

+ 71 - 20
4dkankan-common-utils/src/main/java/com/fdkankan/common/util/AesUtil.java

@@ -1,12 +1,16 @@
 package com.fdkankan.common.util;
 
-import com.aliyuncs.utils.Base64Helper;
+import org.apache.commons.codec.binary.Base64;
 
 import javax.crypto.Cipher;
 import javax.crypto.spec.IvParameterSpec;
 import javax.crypto.spec.SecretKeySpec;
+import java.nio.charset.StandardCharsets;
 
 public class AesUtil {
+
+    public static final String ALMODE_CBC_NOPADDING = "AES/CBC/NoPadding";
+
     /**
      * @author miracle.qu
      * AES算法加密明文
@@ -16,30 +20,77 @@ public class AesUtil {
      * @return 密文
      */
     public static String encryptAES(String data,String key,String iv) throws Exception {
-        try {
-            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
-            int blockSize = cipher.getBlockSize();
-            byte[] dataBytes = data.getBytes();
-            int plaintextLength = dataBytes.length;
+        return encryptCBC(data,key,iv,ALMODE_CBC_NOPADDING);
+    }
 
-            if (plaintextLength % blockSize != 0) {
-                plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize));
-            }
+    public static String encryptCBC(String data,String key,String iv,String alMode) throws Exception {
+        Cipher cipher = Cipher.getInstance(alMode);
+        int blockSize = cipher.getBlockSize();
+        byte[] dataBytes = data.getBytes();
+        int plaintextLength = dataBytes.length;
 
-            byte[] plaintext = new byte[plaintextLength];
-            System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);
+        if (plaintextLength % blockSize != 0) {
+            plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize));
+        }
 
-            SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
-            IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());
+        byte[] plaintext = new byte[plaintextLength];
+        System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);
 
-            cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
-            byte[] encrypted = cipher.doFinal(plaintext);
+        SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
+        IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());
 
-            return Base64Helper.encode(encrypted).trim();
+        cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
+        byte[] encrypted = cipher.doFinal(plaintext);
 
-        } catch (Exception e) {
-            e.printStackTrace();
-            return null;
-        }
+        return new Base64().encodeToString(encrypted).trim();
+    }
+
+    public static String decryptCBC(String data, String key, String iv, String alMode) throws Exception {
+        byte[] encrypted1 = new Base64().decode(data);
+
+        Cipher cipher = Cipher.getInstance(alMode);
+        SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
+        IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());
+
+        cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec); //使用密钥初始化,设置为解密模式
+
+        byte[] original = cipher.doFinal(encrypted1);	//执行操作
+        String originalString = new String(original);
+        return originalString.trim();
+    }
+
+    public static String encryptECB(String data,String key,String alMode) throws Exception {
+        byte[] raw = key.getBytes(StandardCharsets.UTF_8);
+        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
+        Cipher cipher = Cipher.getInstance(alMode);
+        cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
+        byte[] byteEncode = data.getBytes(StandardCharsets.UTF_8);
+        byte[] byteAes = cipher.doFinal(byteEncode, 0, byteEncode.length);
+
+        return java.util.Base64.getEncoder().encodeToString(byteAes);
+    }
+
+    public static String decryptECB(String data,String key,String alMode) throws Exception {
+        byte[] raw = key.getBytes(StandardCharsets.UTF_8);
+        Cipher cipher = Cipher.getInstance(alMode);
+        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
+        cipher.init(Cipher.DECRYPT_MODE, skeySpec);
+        byte[] encrypted1 = java.util.Base64.getDecoder().decode(data);
+        byte[] original = cipher.doFinal(encrypted1);
+
+        //字节转换字符串
+        return new String(original, StandardCharsets.UTF_8).trim();
     }
+
+    public static void main(String[] args) throws Exception {
+//        final String encode = cn.hutool.core.codec.Base64.encode("Aa1234567".getBytes());
+//        System.out.println(encode);
+
+        String data = "linjunbo@192.168.0.30@1695872675";
+        String s = encryptECB(data, "3d8904474ebbdbbd81c5952524dad646", "AES/ECB/PKCS5Padding");
+        System.out.println(s);
+    }
+
+
+
 }

+ 99 - 0
4dkankan-common-utils/src/main/java/com/fdkankan/common/util/CmdUtils.java

@@ -0,0 +1,99 @@
+package com.fdkankan.common.util;
+
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * Created by Xiewj on 2021/1/4 0004 14:53
+ */
+@Slf4j
+public class CmdUtils {
+
+
+    /**
+     * 调用算法 xx.sh 脚本
+     * @param command
+     */
+//    public static void callshell(String command){
+//        try {
+//            String[] cmd = new String[]{"/bin/sh", "-c", command};
+//            Process process = Runtime.getRuntime().exec(cmd);
+//            StreamGobbler errorGobbler = new StreamGobbler(process.getErrorStream(), "ERROR");
+//            errorGobbler.start();
+//            StreamGobbler outGobbler = new StreamGobbler(process.getInputStream(), "STDOUT");
+//            outGobbler.start();
+//            process.waitFor();
+//        } catch (Exception e) {
+//            e.printStackTrace();
+//        }
+//    }
+
+
+
+    public static void callLineSh(String command) throws Exception {
+        callLineSh(command, null);
+
+    }
+
+    /**
+     * 直接java调用命令
+     * @param command
+     */
+    public static void callLine(String command) throws Exception {
+        callLine(command, null);
+
+    }
+
+    /**
+     * 直接java调用命令
+     * @param command
+     */
+    public static void callLine(String command, Integer lineSize) throws Exception {
+        log.info("cmd: " + command);
+        Process process = Runtime.getRuntime().exec(command);
+        log.info("开始运行");
+        StreamGobblerLine errorGobbler = new StreamGobblerLine(process.getErrorStream(), "ERROR");
+        errorGobbler.start();
+        // 200行打印一次日志
+        StreamGobblerLine outGobbler = new StreamGobblerLine(process.getInputStream(), "STDOUT", lineSize);
+        outGobbler.start();
+        process.waitFor();
+    }
+
+    /**
+     *
+     * @param command 命令
+     * @param lineSize 日志输出行数 ,可以为null
+     */
+    public static void callLineSh(String command, Integer lineSize) throws Exception {
+        log.info("cmd: " + command);
+        String[] cmd = new String[]{"/bin/sh", "-c", command};
+        Process process = Runtime.getRuntime().exec(cmd);
+        log.info("开始运行");
+        StreamGobblerLine errorGobbler = new StreamGobblerLine(process.getErrorStream(), "ERROR");
+        errorGobbler.start();
+        // 200行打印一次日志
+        StreamGobblerLine outGobbler = new StreamGobblerLine(process.getInputStream(), "STDOUT", lineSize);
+        outGobbler.start();
+        process.waitFor();
+    }
+
+    /**
+     * 调用sh脚本上传oss
+     */
+//    public static void ossUploadDir(String sceneCode, String uploadDir, String target){
+//
+//        String cmd = CmdConstant.OSSUTIL_UPLOAD_DIR;
+//        cmd = cmd.replaceAll("@sceneCode", sceneCode);
+//        cmd = cmd.replaceAll("@uploadDir", uploadDir);
+//        cmd = cmd.replaceAll("@target", target);
+//
+//        log.info("ossCmd: " + cmd);
+//        long start = System.currentTimeMillis();
+//        CmdUtils.callLineSh(cmd);
+//        long end = System.currentTimeMillis();
+//        log.info("场景码目录:{} 上传完成, 耗时:{} s" , sceneCode, (end-start)/1000 );
+//    }
+
+
+
+}

+ 42 - 0
4dkankan-common-utils/src/main/java/com/fdkankan/common/util/EncryptDecrypt.java

@@ -0,0 +1,42 @@
+package com.fdkankan.common.util;
+
+import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
+
+/**
+ * @author ys
+ * @create 2021/9/22
+ * @desc Jasypt安全框架加密类工具包
+ **/
+public class EncryptDecrypt {
+    public static String algorithm = "PBEWithMD5AndDES";
+    public static String password = "4dage168...";
+
+   static StandardPBEStringEncryptor standardPBEStringEncryptor = new StandardPBEStringEncryptor();
+   static {
+       standardPBEStringEncryptor.setAlgorithm(algorithm);
+       standardPBEStringEncryptor.setPassword(password);
+   }
+
+    public static void main(String[] args) {
+        System.out.println(getEncrypt("JK20220120%JIK"));
+//        System.out.println(getEncrypt("LTAI5tJZBJwP5qazE6b3b4Gr"));
+//        System.out.println(getEncrypt("zSQCG0yyvRJISPokNZGhbhaAfh4hGX"));
+//        System.out.println(getEncrypt("4dkankan524%40123*"));
+//        System.out.println(getEncrypt("admin"));
+//        System.out.println(getEncrypt("admin1231"));
+    }
+
+   private static String getEncrypt(String value){
+       String password = standardPBEStringEncryptor.encrypt(value);
+       return  "ENC(" +password +")";
+   }
+
+    private static String getDecrypt(String value){
+       if(value.contains("ENC(")){
+           value = value.replace("ENC(","");
+           value = value.replace(")","");
+       }
+        return standardPBEStringEncryptor.decrypt(value);
+    }
+}
+

Datei-Diff unterdrückt, da er zu groß ist
+ 72 - 0
4dkankan-common-utils/src/main/java/com/fdkankan/common/util/RsaUtil.java


+ 79 - 0
4dkankan-common-utils/src/main/java/com/fdkankan/common/util/StreamGobblerLine.java

@@ -0,0 +1,79 @@
+package com.fdkankan.common.util;
+
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.*;
+
+@Slf4j
+public class StreamGobblerLine extends Thread {
+
+	InputStream is;
+    String type;
+    OutputStream os;
+    Integer lineSize;  // 多少行打印日志一次
+
+    public StreamGobblerLine(InputStream is, String type) {
+        this(is, type, null, null);
+    }
+
+    public StreamGobblerLine(InputStream is, String type, Integer lineSize) {
+        this(is, type, null, lineSize);
+    }
+
+    StreamGobblerLine(InputStream is, String type, OutputStream redirect, Integer lineSize) {
+        this.is = is;
+        this.type = type;
+        this.os = redirect;
+        this.lineSize = lineSize;
+    }
+
+    public void run() {
+        log.info("run StreamGobblerLine");
+
+        InputStreamReader isr = null;
+        BufferedReader br = null;
+        PrintWriter pw = null;
+        try {
+            if (os != null)
+                pw = new PrintWriter(os);
+
+            isr = new InputStreamReader(is);
+            br = new BufferedReader(isr);
+            String line=null;
+            int i = 1;
+            while ( (line = br.readLine()) != null) {
+                if (lineSize != null) {
+                    if (i % lineSize == 0) {
+                        log.info(type + "," + i +" : >" + line);
+                    }
+                } else {
+                    log.info(type + ","  + i +" : >" + line);
+                }
+                i++;
+
+            }
+
+            if (pw != null)
+                pw.flush();
+        } catch (IOException ioe) {
+            ioe.printStackTrace();
+        } finally{
+            try {
+            	if(pw!=null)
+            	{
+            		 pw.close();
+            	}
+            	if(br!=null)
+            	{
+            		br.close();
+            	}
+            	if(isr!=null)
+            	{
+            		isr.close();
+            	}
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+}

+ 18 - 0
4dkankan-common-web/pom.xml

@@ -38,6 +38,12 @@
     <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-webflux</artifactId>
+      <exclusions>
+        <exclusion>
+          <groupId>org.springframework</groupId>
+          <artifactId>spring-web</artifactId>
+        </exclusion>
+      </exclusions>
     </dependency>
 
     <dependency>
@@ -81,6 +87,18 @@
     <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-web</artifactId>
+      <exclusions>
+        <exclusion>
+          <groupId>org.springframework</groupId>
+          <artifactId>spring-web</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-web</artifactId>
+      <version>5.2.16.RELEASE</version>
     </dependency>
 
     <dependency>

+ 2 - 0
4dkankan-common-web/src/main/java/com/fdkankan/web/interceptor/CheckInnerApiPermitAspect.java

@@ -11,6 +11,7 @@ import org.aspectj.lang.annotation.Aspect;
 import org.aspectj.lang.annotation.Before;
 import org.aspectj.lang.annotation.Pointcut;
 import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.core.annotation.Order;
 import org.springframework.stereotype.Component;
 import org.springframework.web.context.request.RequestContextHolder;
@@ -19,6 +20,7 @@ import org.springframework.web.context.request.ServletRequestAttributes;
 @Log4j2
 @Aspect
 @Component
+@ConditionalOnProperty(name = "inner.check", havingValue = "true")
 @Order(101)
 public class CheckInnerApiPermitAspect {
 

+ 15 - 2
4dkankan-common-web/src/main/java/com/fdkankan/web/response/BaseResponseAdvice.java

@@ -5,6 +5,7 @@ import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.fdkankan.web.annotation.NotResponseAdvice;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
 import org.springframework.core.MethodParameter;
 import org.springframework.http.MediaType;
@@ -20,6 +21,10 @@ import java.util.Objects;
 @RestControllerAdvice
 @Slf4j
 public class BaseResponseAdvice implements ResponseBodyAdvice<Object> {
+
+    @Value("${language:zh_CN}")
+    private String language;
+
     @Override
     public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
         NotResponseAdvice methodAnnotation = methodParameter.getMethodAnnotation(NotResponseAdvice.class);
@@ -49,10 +54,18 @@ public class BaseResponseAdvice implements ResponseBodyAdvice<Object> {
             return JSONObject.toJSONString(ResultData.ok(body));
         }
         if (body instanceof ResultData) {
-            return body;
+            return getI18n((ResultData) body);
         } else {
-            return ResultData.ok(body);
+            return getI18n(ResultData.ok(body));
+        }
+    }
+
+    private ResultData getI18n(ResultData data){
+        if("zh_CN".equals(language)){
+           return data;
         }
+        data.setMessage(null);
+        return data;
     }
 
 }

+ 26 - 2
4dkankan-common-web/src/main/java/com/fdkankan/web/util/WebUtil.java

@@ -1,11 +1,15 @@
 package com.fdkankan.web.util;
 
+import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.http.ContentType;
 import cn.hutool.http.useragent.UserAgent;
 import cn.hutool.http.useragent.UserAgentUtil;
 import com.alibaba.fastjson.JSON;
+
+import java.util.Enumeration;
 import java.util.HashMap;
+import java.util.Map;
 import javax.servlet.http.HttpServletRequest;
 import org.aspectj.lang.JoinPoint;
 import org.springframework.http.HttpHeaders;
@@ -32,13 +36,33 @@ public class WebUtil {
     public static String getParameter(String paramName, JoinPoint pjp, HttpServletRequest request){
         Object[] args = pjp.getArgs();
         String contentType = request.getContentType();
-        if(contentType.contains(ContentType.JSON.getValue())){
+        if(StrUtil.isNotEmpty(contentType) && contentType.contains(ContentType.JSON.getValue())){
             HashMap hashMap = JSON.parseObject(JSON.toJSONString(args[0]), HashMap.class);
             return (String) hashMap.get(paramName);
         }
         return request.getParameter(paramName);
     }
 
+    public static Map<String, Object> getParameter(JoinPoint pjp, HttpServletRequest request) {
+        Object[] args = pjp.getArgs();
+        String contentType = request.getContentType();
+        if (StrUtil.isNotEmpty(contentType) && contentType.contains(ContentType.JSON.getValue())) {
+            return JSON.parseObject(JSON.toJSONString(args[0]), HashMap.class);
+        } else {
+            Enumeration<String> parameterNames = request.getParameterNames();
+            if(CollUtil.isEmpty(parameterNames)){
+                return null;
+            }
+            Map<String, Object> params = new HashMap<>();
+            String name = null;
+            do {
+                name = parameterNames.nextElement();
+                params.put(name, request.getParameter(name));
+            }while (parameterNames.hasMoreElements());
+            return params;
+        }
+    }
+
     /**
      * 获取客户端请求终端地址
      * @param request  客户端请求request
@@ -52,7 +76,7 @@ public class WebUtil {
                 return ip;
             }
         }
-            ip = request.getHeader("Proxy-Client-IP");
+        ip = request.getHeader("Proxy-Client-IP");
         if(StrUtil.isNotBlank(ip)) return ip;
             ip = request.getHeader("WL-Proxy-Client-IP");
         if(StrUtil.isNotBlank(ip)) return ip;

+ 43 - 0
4dkankan-utils-disruptormq/pom.xml

@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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">
+    <parent>
+        <artifactId>4dkankan-utils</artifactId>
+        <groupId>com.fdkankan</groupId>
+        <version>3.0.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>4dkankan-utils-disruptormq</artifactId>
+
+    <properties>
+        <disruptor.version>3.4.4</disruptor.version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-classic</artifactId>
+            <version>1.2.11</version>
+        </dependency>
+        <dependency>
+            <groupId>com.lmax</groupId>
+            <artifactId>disruptor</artifactId>
+            <version>${disruptor.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-configuration-processor</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-autoconfigure</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter</artifactId>
+        </dependency>
+    </dependencies>
+</project>

+ 84 - 0
4dkankan-utils-disruptormq/src/main/java/com/fdkankan/disruptormq/BaseDisruptorQueue.java

@@ -0,0 +1,84 @@
+package com.fdkankan.disruptormq;
+
+/**
+ * @author Xiewj
+ * @date 2024/1/17
+ */
+
+import com.fdkankan.disruptormq.DisruptorExcepitonHandler;
+import com.lmax.disruptor.dsl.Disruptor;
+import com.lmax.disruptor.dsl.ProducerType;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.scheduling.concurrent.CustomizableThreadFactory;
+import org.springframework.util.CollectionUtils;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+
+/**
+ * 可以在sprinboot中使用,不同业务可以声明不同的DisruptorQueue,使用不同的Handler处理
+ */
+@SuppressWarnings("all")
+public abstract class BaseDisruptorQueue<T> implements ApplicationContextAware {
+    @Autowired
+    private  DisruptorProperties disruptorProperties;
+    private Disruptor< DisruptorEvent<T>> disruptor;
+    private Map<String, DisruptorHandler> disruptorHandlerMap;
+
+    public void offer(T t) {
+        if (Objects.nonNull(t)) {
+            disruptor.publishEvent((event, sequence) -> event.setPayload(t));
+        }
+    }
+
+    public void offer(List<T> ts) {
+        if (!CollectionUtils.isEmpty(ts)) {
+            ts.stream().filter(Objects::nonNull).forEach(this::offer);
+        }
+    }
+
+    protected void initDisruptor(String handlerName) {
+        this.disruptor = getDisruptor(handlerName);
+    }
+
+    private Disruptor<DisruptorEvent<T>> getDisruptor(String handlerName) {
+        DisruptorProperties.HandlerProperties handlerProperties = getDisruptorHandlerConfig(handlerName);
+        Disruptor<DisruptorEvent<T>> disruptor = new Disruptor<>(DisruptorEvent::new, handlerProperties.getRingBufferSize(), //
+                new CustomizableThreadFactory(handlerName + "-disruptor-"), //
+                handlerProperties.isMultiProducer() ? ProducerType.MULTI : ProducerType.SINGLE, //
+                disruptorProperties.getWaitType().getWaitStrategy());
+        // 对于一条消息,handleEventsWith方法返回的EventHandlerGroup,Group中的每个消费者都会对消息进行消费,各个消费者之间不存在竞争(类似发布订阅)
+        // disruptor.handleEventsWith(getDisruptorHandler(handlerName));
+        // 对于一条消息,handleEventsWithWorkerPool方法返回的EventHandlerGroup,Group的消费者对于同一条消息不重复消费(类似点对点)
+        disruptor.handleEventsWithWorkerPool(getDisruptorHandler(handlerName));
+        disruptor.setDefaultExceptionHandler(new DisruptorExcepitonHandler<>());
+        disruptor.start();
+        Runtime.getRuntime().addShutdownHook(new Thread(disruptor::shutdown, handlerName + "-disruptor-shutdown"));
+        return disruptor;
+    }
+
+    private DisruptorProperties.HandlerProperties getDisruptorHandlerConfig(String handlerName) {
+        Map<String, DisruptorProperties.HandlerProperties> handlers = disruptorProperties.getHandlers();
+        DisruptorProperties.HandlerProperties handlerProperties = handlers.get(handlerName);
+        return Optional.ofNullable(handlerProperties).orElseGet(() -> {
+            DisruptorProperties.HandlerProperties defaultHandlerProperties = new DisruptorProperties.HandlerProperties();
+            defaultHandlerProperties.setRingBufferSize(1024 * 1024);
+            defaultHandlerProperties.setMultiProducer(false);
+            return defaultHandlerProperties;
+        });
+    }
+
+    private DisruptorHandler<T> getDisruptorHandler(String handlerName) {
+        return disruptorHandlerMap.get(handlerName);
+    }
+
+    @Override
+    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+        disruptorHandlerMap = applicationContext.getBeansOfType(DisruptorHandler.class);
+    }
+}

+ 12 - 0
4dkankan-utils-disruptormq/src/main/java/com/fdkankan/disruptormq/DisruptorEvent.java

@@ -0,0 +1,12 @@
+package com.fdkankan.disruptormq;
+
+import lombok.Data;
+
+/**
+ * @author Xiewj
+ * @date 2024/1/17
+ */
+@Data
+public class DisruptorEvent<T> {
+    private T payload;
+}

+ 26 - 0
4dkankan-utils-disruptormq/src/main/java/com/fdkankan/disruptormq/DisruptorExcepitonHandler.java

@@ -0,0 +1,26 @@
+package com.fdkankan.disruptormq;
+
+import com.lmax.disruptor.ExceptionHandler;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * @author Xiewj
+ * @date 2024/1/17
+ */
+@Slf4j
+public class DisruptorExcepitonHandler<T> implements ExceptionHandler<T> {
+    @Override
+    public void handleEventException(Throwable ex, long sequence, T event) {
+        log.error("DisruptorEvent Handle处理错误,sequence={},event={},e={}", sequence, event.toString(), ex.toString(), ex);
+    }
+
+    @Override
+    public void handleOnStartException(Throwable ex) {
+        log.error("DisruptorEvent handleOnStart处理错误,e={}", ex.toString(), ex);
+    }
+
+    @Override
+    public void handleOnShutdownException(Throwable ex) {
+        log.error("DisruptorEvent handleOnShutdown处理错误,e={}", ex.toString(), ex);
+    }
+}

+ 29 - 0
4dkankan-utils-disruptormq/src/main/java/com/fdkankan/disruptormq/DisruptorHandler.java

@@ -0,0 +1,29 @@
+package com.fdkankan.disruptormq;
+
+/**
+ * @author Xiewj
+ * @date 2024/1/17
+ */
+
+import com.fdkankan.disruptormq.DisruptorEvent;
+import com.lmax.disruptor.EventHandler;
+import com.lmax.disruptor.WorkHandler;
+
+/**
+ * 消费者接口
+ * EventHandler用于EventHandlerGroup,WorkHandler用于WorkPool
+ * 同时实现两接口,该类对象可同时用于EventHandlerGroup和WorkPool
+ */
+public interface DisruptorHandler<T> extends EventHandler<DisruptorEvent<T>>, WorkHandler<DisruptorEvent<T>> {
+    @Override
+    default void onEvent(DisruptorEvent<T> event, long sequence, boolean endOfBatch) throws Exception {
+        onEvent(event);
+    }
+
+    @Override
+    default void onEvent(DisruptorEvent<T> event) throws Exception {
+        consumer(event.getPayload());
+    }
+
+    void consumer(T t) throws Exception;
+}

+ 73 - 0
4dkankan-utils-disruptormq/src/main/java/com/fdkankan/disruptormq/DisruptorProperties.java

@@ -0,0 +1,73 @@
+package com.fdkankan.disruptormq;
+
+import com.lmax.disruptor.*;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.Getter;
+import lombok.ToString;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * @author Xiewj
+ * @date 2024/1/17
+ */
+@Data
+@Component
+@ConditionalOnProperty(prefix  = "disruptor",name = "wait-type")
+public class DisruptorProperties {
+    /**
+     * 等待类型
+     */
+    private WaitType waitType = WaitType.BLOCKING_WAIT;
+    /**
+     * handler配置参数
+     */
+    private Map<String, HandlerProperties> handlers = new LinkedHashMap<>();
+
+    @Data
+    public static class HandlerProperties {
+        /**
+         * 缓冲区大小,默认1024*1024,必须是2的N次幂
+         */
+        private int ringBufferSize = 1024 * 1024;
+        /**
+         * 单生产者/多生产者
+         */
+        private boolean multiProducer = false;
+    }
+
+    /**
+     * 决定一个消费者将如何等待生产者将Event置入Disruptor的策略,用来权衡当生产者无法将新的事件放进RingBuffer时的处理策略
+     * (例如:当生产者太快,消费者太慢,会导致生成者获取不到新的事件槽来插入新事件,则会根据该策略进行处理,默认会堵塞)
+     */
+    @Getter
+    @ToString
+    @AllArgsConstructor
+    public enum WaitType {
+        /**
+         * BlockingWaitStrategy是最低效的策略,但其对CPU的消耗最小并且在各种不同部署环境中能提供更加一致的性能表现
+         */
+        BLOCKING_WAIT(new BlockingWaitStrategy()),
+        /**
+         * SleepingWaitStrategy的性能表现跟BlockingWaitStrategy差不多,对CPU的消耗也类似,但其对生产者线程的影响最小,适合用于异步日志类似的场景
+         */
+        SLEEPING_WAIT(new SleepingWaitStrategy()),
+        /**
+         * YieldingWaitStrategy是可以被用在低延迟系统中的两个策略之一,这种策略在减低系统延迟的同时也会增加CPU运算量
+         * YieldingWaitStrategy策略会循环等待sequence增加到合适的值,循环中调用Thread.yield()允许其他准备好的线程执行
+         * 如果需要高性能而且事件消费者线程比逻辑内核少的时候,推荐使用YieldingWaitStrategy策略,例如在开启超线程时
+         */
+        YIELDING_WAIT(new YieldingWaitStrategy()),
+        /**
+         * BusySpinWaitStrategy是性能最高的等待策略,同时也是对部署环境要求最高的策略
+         * 这个性能最好用在事件处理线程比物理内核数目还要小的时候,例如在禁用超线程技术时
+         */
+        BUSY_SPIN_WAIT(new BusySpinWaitStrategy());
+        private final WaitStrategy waitStrategy;
+    }
+}

+ 1 - 0
4dkankan-utils-disruptormq/src/main/resources/META-INF/spring.factories

@@ -0,0 +1 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.fdkankan.disruptormq.DisruptorProperties

+ 62 - 0
4dkankan-utils-dxf/pom.xml

@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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">
+    <parent>
+        <artifactId>4dkankan-utils</artifactId>
+        <groupId>com.fdkankan</groupId>
+        <version>3.0.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>4dkankan-utils-dxf</artifactId>
+    <version>3.0.0-SNAPSHOT</version>
+    <packaging>jar</packaging>
+
+    <properties>
+        <maven.compiler.source>8</maven.compiler.source>
+        <maven.compiler.target>8</maven.compiler.target>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <junit.version>4.13.2</junit.version>
+        <lombok.version>1.18.24</lombok.version>
+        <fastjson.version>2.0.26</fastjson.version>
+        <proj4j.version>1.1.3</proj4j.version>
+        <java-api-kml.version>2.2.0</java-api-kml.version>
+        <freemarker.version>2.3.32</freemarker.version>
+        <maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
+    </properties>
+
+    <dependencies>
+        <!--定位点转换-->
+        <dependency>
+            <groupId>org.locationtech.proj4j</groupId>
+            <artifactId>proj4j</artifactId>
+            <version>${proj4j.version}</version>
+        </dependency>
+        <!--java kml解析-->
+        <dependency>
+            <groupId>de.micromata.jak</groupId>
+            <artifactId>JavaAPIforKml</artifactId>
+            <version>${java-api-kml.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>${fastjson.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <version>${lombok.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.freemarker</groupId>
+            <artifactId>freemarker</artifactId>
+            <version>${freemarker.version}</version>
+        </dependency>
+
+
+    </dependencies>
+</project>

+ 13 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/fdjson/vo/FdFloors.java

@@ -0,0 +1,13 @@
+package com.fdkankan.dxf.fdjson.vo;
+
+import com.alibaba.fastjson.JSONObject;
+import lombok.Data;
+
+@Data
+public class FdFloors {
+    private Integer num = 0;            // 楼层顺序(自增长)                 必填
+    private Integer subgroup = 0;       // 楼层Id(与模型对应)          必填
+    private String name = "一楼";       // 楼层名称                    必填
+    private JSONObject walls = new JSONObject();
+    private JSONObject points = new JSONObject();
+}

+ 15 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/fdjson/vo/FdFloorsPanJson.java

@@ -0,0 +1,15 @@
+package com.fdkankan.dxf.fdjson.vo;
+
+import lombok.Data;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Data
+public class FdFloorsPanJson {
+    private String version = "v4.0";        // 数据版本号, 必填,默认值
+    private Integer angle = 0;              // 旋转角度, 必填,默认值
+    private String type = "cad";            // 数据类型, 必填,默认值
+    private Integer currentId = 0;          // 组件全局标识符(自增长),非必填
+    private List<FdFloors> floors = new ArrayList<>();
+}

+ 28 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/fdjson/vo/FdPoints.java

@@ -0,0 +1,28 @@
+package com.fdkankan.dxf.fdjson.vo;
+
+import com.alibaba.fastjson.JSONObject;
+import lombok.Data;
+
+@Data
+public class FdPoints {
+    private Integer floor = 0 ;
+    private String geoType = "Point";   //表示类型是墙的端点
+    private String vectorId;        //墙的端点的唯一标识符
+    private Double x;               //点的横坐标,与三维模型的横坐标一致
+    private Double y;               //点的纵坐标,与三维模型的纵坐标一致
+    /**
+     * parent: { //表示所属的墙                                                   必填
+     * 						Wall92: "start", //所属墙的vectorId以及是起始点还是终点             必填
+     * 						Wall300: "end"
+     *    },
+     */
+    private JSONObject parent;      //表示所属的墙
+
+    public FdPoints(Double x, Double y) {
+        this.x = x;
+        this.y = y;
+    }
+
+    public FdPoints() {
+    }
+}

+ 18 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/fdjson/vo/FdWalls.java

@@ -0,0 +1,18 @@
+package com.fdkankan.dxf.fdjson.vo;
+
+import lombok.Data;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Data
+public class FdWalls {
+    private Boolean important = false;
+    private Boolean out = false;            //是否外墙,这个全部设置成false也可以      选填
+    private Integer floor = 0;              //表示所在楼层是第一层                选填
+    private String vectorId ;               //墙的唯一标识符
+    private String geoType = "Wall";        //表示类型是墙            必填
+    private String start ;                  //起始点的vectorId       必填
+    private String end ;                    //终点的vectorId           必填
+    private List<String> children = new ArrayList<>();           //墙上门或者窗的vectorId     必填
+}

+ 405 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/DxfDocWriter.java

@@ -0,0 +1,405 @@
+package com.fdkankan.dxf.generate;
+
+import com.fdkankan.dxf.generate.model.*;
+import com.fdkankan.dxf.generate.model.base.BaseDxfEntity;
+import com.fdkankan.dxf.generate.model.base.DxfEntity;
+import com.fdkankan.dxf.generate.model.support.DxfExtent;
+import com.fdkankan.dxf.generate.util.DxfUtil;
+import com.fdkankan.dxf.generate.util.FreemarkerSupport;
+import com.fdkankan.dxf.generate.util.StreamUtil;
+import com.fdkankan.dxf.generate.util.StringUtil;
+
+import java.io.*;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.util.*;
+
+/**
+ * Dxf处理类,支持向矿图中添加自定义图形,目前支持的图形有圆形Circle,圆弧Arc,直线Line,多线段LwPolyLine,文字Text 目前仅仅支持对圆形Circle和其子类Arc的颜色填充。 可以通过调用 {@link #addEntity(DxfEntity)} 和 {@link #removeEntity(DxfEntity)} 进行自定义图元的添加和删除。
+ * <p>
+ * 并支持对新dxf文件的导出,可以选择调用函数 {@link #save(String, boolean)} 导出所有文件,这样的文件可以在AutoCad中打开 也可以通过函数 {@link #saveEntities(String, boolean)} 仅仅导出entity图元信息,这样的文件仅仅支持使用解析库进行解析
+ * <p>
+ * 另外和文件流一样,dxfDocument对象也需要在使用结束后关闭,通过调用 {@link #close()} 函数进行关闭,可以以想流式对象那样使用,如 <blockquote>
+ *
+ * <pre>
+ *     try(DxfDocument dxf = new DxfDocument(path)) {
+ *         body
+ *     }
+ * </pre>
+ *
+ * </blockquote>
+ *
+ * @author YTZJJ
+ */
+@SuppressWarnings("unused")
+public class DxfDocWriter implements Closeable {
+    /**
+     * 当选择保存为dxf文件的时候,要保留的Entities类型的数组,不在数组中的对象将会被忽略掉(不包含自定义加入的图元)
+     */
+    public static final String[] DEFAULT_ENTITY_NO_REDUCE_PART = {"LINE", "CIRCLE", "ARC", "TEXT", "MTEXT", "LWPOLYLINE"};
+    private List<String> entityNoReducePart = Arrays.asList(DEFAULT_ENTITY_NO_REDUCE_PART);
+    private List<DxfEntity> newDxfEntityList;
+    private long maxMeta;
+    private Charset charset;
+    private DxfExtent extent;
+
+    private BufferedReader br;
+    private File dxfFile;
+
+    /**
+     * 加载dxf文件,默认的文件加载编码为UFT8
+     *
+     * @param dxfFilePath dxf文件位置
+     */
+    public DxfDocWriter(String dxfFilePath, DxfExtent extent) {
+        this(dxfFilePath, extent, StandardCharsets.UTF_8);
+    }
+
+    /**
+     * 以指定编码格式加载dxf文件
+     *
+     * @param dxfFilePath dxf文件位置
+     * @param charset     文件编码
+     * @see StandardCharsets
+     */
+    public DxfDocWriter(String dxfFilePath, DxfExtent extent, Charset charset) {
+        this.charset = charset;
+        this.extent = extent;
+        newDxfEntityList = new ArrayList<>();
+        if (dxfFilePath != null) {
+            this.dxfFile = new File(dxfFilePath);
+            try {
+                this.br = StreamUtil.getFileReader(dxfFile.getAbsolutePath(), charset);
+            } catch (FileNotFoundException e) {
+                System.err.println("file " + dxfFilePath + "not exists" + e.getMessage());
+            }
+            maxMeta = DxfUtil.readMaxMeta(dxfFilePath);
+        } else {
+            maxMeta = Long.parseLong("1F6", 16);
+        }
+    }
+
+    /**
+     * 创建一个空的dxf文件
+     */
+    public DxfDocWriter() {
+        this(null, null, StandardCharsets.UTF_8);
+    }
+
+    /**
+     * 向矿图文件中添加一个图元,目前仅仅支持 {@link DxfCircle},{@link DxfArc},{@link DxfLine},{@link DxfLwPolyLine},{@link DxfText}
+     * <p>
+     * 也可以通过继承 {@link BaseDxfEntity} 或实现 {@link DxfEntity} 接口来扩展图元
+     *
+     * @param dxfEntity 图元
+     */
+    public void addEntity(DxfEntity dxfEntity) {
+        if (dxfEntity instanceof DxfRay) {
+            if (Vector3.ZERO.equals(((DxfRay) dxfEntity).getDirection())) {
+                System.err.println(dxfEntity.getEntityName() + " direction cant be zero!!, will ignore this entity");
+                return;
+            }
+        }
+        if (dxfEntity instanceof DxfLwPolyLine) {
+            if (((DxfLwPolyLine) dxfEntity).isEmpty()) {
+                System.err.println("LwPolyLine not contains any point, will ignore this entity");
+                return;
+            }
+        }
+        dxfEntity.setMeta(++maxMeta);
+        this.newDxfEntityList.add(dxfEntity);
+        if (dxfEntity instanceof DxfCircle || dxfEntity instanceof DxfLwPolyLine) {
+            if (((BaseDxfEntity) dxfEntity).isSolid()) {
+                addEntity(DxfHatch.buildHatchBy((BaseDxfEntity) dxfEntity));
+            }
+
+        }
+    }
+
+    /**
+     * 移除一个自定义的图元
+     *
+     * @param dxfEntity 图元
+     */
+    public void removeEntity(DxfEntity dxfEntity) {
+        this.newDxfEntityList.remove(dxfEntity);
+        for (DxfEntity entity : newDxfEntityList) {
+            if (entity instanceof DxfHatch) {
+                if (((DxfHatch) dxfEntity).getDxfSolid().getDxfEntity() == dxfEntity) {
+                    this.newDxfEntityList.remove(dxfEntity);
+                }
+            }
+        }
+    }
+
+    /**
+     * 设置要保存的矿图文件中要保留的图元类型列表,如果设置为 null, 那么原矿图中的所有图元都将会被保留 默认的要保存的图元列表表为 {@link #DEFAULT_ENTITY_NO_REDUCE_PART}
+     *
+     * @param entityNoReducePart 要保留的图元列表
+     */
+    public void setEntityNoReducePart(String... entityNoReducePart) {
+        if (entityNoReducePart == null) {
+            this.entityNoReducePart = null;
+        } else {
+            this.entityNoReducePart = Arrays.asList(entityNoReducePart);
+        }
+    }
+
+    /**
+     * 仅仅保存矿图中的图元信息(ENTITIES 部分)到文件中,其他部分(HEADER, CLASSES, TABLES...)都将被舍弃 通过 {@link #setEntityNoReducePart(String...)} 可以自定义保留那些类型的图元
+     *
+     * @param entitiesFilePath 要保存的文件位置
+     * @param containNewEntity 是否包含自定义添加进去的图元信息
+     */
+    public void saveEntities(String entitiesFilePath, boolean containNewEntity) {
+        save(entitiesFilePath, true, containNewEntity);
+    }
+
+    /**
+     * 保存为新的dxf文件
+     *
+     * @param saveDxfFilePath  要保存的问题件位置
+     * @param containNewEntity 是否报刊自定义添加进去的图元信息
+     */
+    public void save(String saveDxfFilePath, boolean containNewEntity) {
+        save(saveDxfFilePath, false, containNewEntity);
+    }
+
+    public String readString(boolean containNewEntity) {
+        StringBuilder result = new StringBuilder();
+        read(false, containNewEntity, result::append);
+        return result.toString();
+    }
+
+    private void read(boolean justSaveEntity, boolean containNewEntity, ReadDxfConsumer readStr) {
+        FreemarkerSupport.getInstance();
+        try {
+            if (dxfFile != null) {
+                br.mark((int) (dxfFile.length() + 1));
+            } else {
+
+                String value = FreemarkerSupport.getInstance().processPath("/dxf/empty.dxf.ftl", extent);
+                br = StreamUtil.getReader(new ByteArrayInputStream(value.getBytes()));
+//
+
+//				br = StreamUtil.getReader(StreamUtil.getResourceStream("empty.dxf"));
+            }
+            StringBuffer writeBuffer = new StringBuffer();
+            while (true) {
+                String[] pair = StreamUtil.readNextPair(br);
+                if (pair == null) {
+                    break;
+                }
+                if ("0".equals(pair[0].trim()) && "SECTION".equals(pair[1].trim())) {
+                    // nextPartStart
+                    String[] nextPairTitleTag = StreamUtil.readNextPair(br);
+                    if (nextPairTitleTag == null) {
+                        continue;
+                    }
+                    String nextPartName = nextPairTitleTag[1].trim();
+                    if (justSaveEntity) {
+                        justSaveEntity(writeBuffer, pair, nextPairTitleTag, containNewEntity);
+                    } else {
+                        handleAll(writeBuffer, pair, nextPairTitleTag, containNewEntity);
+                    }
+                    readStr.accept(writeBuffer.toString());
+                    writeBuffer = new StringBuffer();
+                    System.out.println("handle part " + nextPartName + " end");
+                } else if ("EOF".equals(pair[1].trim())) {
+                    StringUtil.appendLnCrLf(writeBuffer, pair);
+                    readStr.accept(writeBuffer.toString());
+                    System.out.println("completed!! dxf reduce end<<<<<<<<<<<<<");
+                    break;
+                }
+            }
+        } catch (Exception e) {
+            System.err.println("Reduce dxf fail!!!!!!" + e.getMessage());
+        } finally {
+            try {
+                if (dxfFile != null) {
+                    br.reset();
+                } else {
+                    br.close();
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    private void save(String saveDxfFilePath, boolean justSaveEntity, boolean containNewEntity) {
+        try (BufferedWriter fileWriter = StreamUtil.getFileWriter(saveDxfFilePath, charset)) {
+            read(justSaveEntity, containNewEntity, fileWriter::write);
+            fileWriter.flush();
+        } catch (IOException e) {
+            System.err.println("save fail" + e.getLocalizedMessage());
+        }
+
+    }
+
+    private void justSaveEntity(StringBuffer writeBuffer, String[] pair, String[] nextPairTitleTag, boolean containNewEntity) throws IOException {
+        String nextPartName = nextPairTitleTag[1].trim();
+        if ("ENTITIES".equals(nextPartName)) {
+            StringUtil.appendLnCrLf(writeBuffer, pair);
+            StringUtil.appendLnCrLf(writeBuffer, nextPairTitleTag);
+            handEntities(writeBuffer, containNewEntity);
+        } else {
+            ignoreNextPart();
+        }
+    }
+
+    private void handleAll(StringBuffer writeBuffer, String[] pair, String[] nextPairTitleTag, boolean containNewEntity) throws IOException {
+        String nextPartName = nextPairTitleTag[1].trim();
+        switch (nextPartName) {
+            case "HEADER":
+                StringUtil.appendLnCrLf(writeBuffer, pair);
+                StringUtil.appendLnCrLf(writeBuffer, nextPairTitleTag);
+                handHeader(writeBuffer);
+                break;
+            case "ENTITIES":
+                StringUtil.appendLnCrLf(writeBuffer, pair);
+                StringUtil.appendLnCrLf(writeBuffer, nextPairTitleTag);
+                handEntities(writeBuffer, containNewEntity);
+                break;
+            case "CLASSES":
+            case "TABLES":
+            case "BLOCKS":
+            case "OBJECTS":
+                StringUtil.appendLnCrLf(writeBuffer, pair);
+                StringUtil.appendLnCrLf(writeBuffer, nextPairTitleTag);
+                justOutput(writeBuffer);
+                break;
+            default:
+                ignoreNextPart();
+                break;
+        }
+    }
+
+    private void ignoreNextPart() throws IOException {
+        while (true) {
+            String[] piar = StreamUtil.readNextPair(br);
+            if (piar == null) {
+                break;
+            }
+            if ("ENDSEC".equals(piar[1].trim())) {
+                // header end, endsec is the end tag
+                break;
+            }
+        }
+    }
+
+    private void justOutput(StringBuffer writeBuffer) throws IOException {
+        System.out.println("part keep raw info");
+        while (true) {
+            String[] piar = StreamUtil.readNextPair(br);
+            if (piar == null) {
+                break;
+            }
+            StringUtil.appendLnCrLf(writeBuffer, piar);
+            if ("ENDSEC".equals(piar[1].trim())) {
+                // header end, endsec is the end tag
+                break;
+            }
+        }
+    }
+
+    private void handEntities(StringBuffer writeBuffer, boolean containNewEntity) throws IOException {
+        Map<String, Integer> keepMapResult = new HashMap<>(4);
+        Map<String, Integer> ignoreMapResult = new HashMap<>(4);
+        String[] nextPair = StreamUtil.readNextPair(br);
+        while (true) {
+            if (nextPair == null) {
+                break;
+            }
+            if ("ENDSEC".equals(nextPair[1].trim())) {
+                // read entities end
+                if (containNewEntity) {
+                    appendNewEntities(writeBuffer);
+                }
+                StringUtil.appendLnCrLf(writeBuffer, nextPair);
+                break;
+            } else {
+                // read entities body
+                String nextEntityName = nextPair[1].trim();
+                boolean isReduced = entityNoReducePart != null && !entityNoReducePart.contains(nextEntityName);
+                if (!isReduced) {
+                    StringUtil.appendLnCrLf(writeBuffer, nextPair);
+                    keepMapResult.put(nextEntityName, keepMapResult.getOrDefault(nextEntityName, 0) + 1);
+                } else {
+                    ignoreMapResult.put(nextEntityName, ignoreMapResult.getOrDefault(nextEntityName, 0) + 1);
+                }
+                nextPair = readNextEntity(writeBuffer, isReduced);
+            }
+        }
+        System.out.println("[Entities]keep=>" + keepMapResult + "ignore=>" + ignoreMapResult);
+    }
+
+    private void appendNewEntities(StringBuffer buffer) {
+        for (DxfEntity dxfEntity : newDxfEntityList) {
+            buffer.append(dxfEntity.getDxfStr());
+        }
+    }
+
+    /**
+     * add not reduce tag content to writeBuffer, and return next entity title tag
+     *
+     * @param writeBuffer content buffer
+     * @return next entity title tag
+     * @throws IOException if read file error throw this exception
+     */
+    private String[] readNextEntity(StringBuffer writeBuffer, boolean isReduced) throws IOException {
+        // check tag is need to reduce
+        while (true) {
+            String[] pair = StreamUtil.readNextPair(br);
+            if (pair == null) {
+                return null;
+            }
+            // code equals zero mean meet next entity tag title, and mean this entity end
+            if ("0".equals(pair[0].trim())) {
+                return pair;
+            }
+            if (!isReduced) {
+                StringUtil.appendLnCrLf(writeBuffer, pair);
+            }
+        }
+    }
+
+    private void handHeader(StringBuffer writeBuffer) throws IOException {
+        while (true) {
+            String[] pair = StreamUtil.readNextPair(br);
+            if (pair == null) {
+                break;
+            }
+            StringUtil.appendLnCrLf(writeBuffer, pair);
+            if (!newDxfEntityList.isEmpty() && DxfUtil.isPairNameEquals(pair, "$HANDSEED")) {
+                pair = StreamUtil.readNextPair(br);
+                if (pair == null) {
+                    return;
+                }
+                if ("5".equals(pair[0].trim())) {
+                    pair[1] = DxfUtil.formatMeta(maxMeta + 2);
+                }
+                StringUtil.appendLnCrLf(writeBuffer, pair);
+            }
+            if ("ENDSEC".equals(pair[1].trim())) {
+                // header end, endsec is the end tag
+                break;
+            }
+        }
+    }
+
+    /**
+     * close
+     *
+     * @throws IOException IOException
+     */
+    @Override
+    public void close() throws IOException {
+        StreamUtil.closeStream(br);
+        System.out.println("Dxf document has been closed.");
+    }
+
+    interface ReadDxfConsumer {
+        void accept(String string) throws IOException;
+    }
+}

+ 37 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/DxfGenSupport.java

@@ -0,0 +1,37 @@
+package com.fdkankan.dxf.generate;
+
+import com.fdkankan.dxf.generate.model.base.BaseDxfEntity;
+import com.fdkankan.dxf.generate.model.support.DxfExtent;
+import com.fdkankan.dxf.generate.util.FileUtil;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import java.util.function.Function;
+
+public class DxfGenSupport {
+
+	public static void appendDxf(String dxfFilePath, String generateNewDxf, Function<Integer, BaseDxfEntity> fun) throws Exception {
+		try (DxfDocWriter dxfDocWriter = new DxfDocWriter(dxfFilePath, null, StandardCharsets.UTF_8)) {
+			for (int i = 0; i < 50; i++) {
+				BaseDxfEntity apply = fun.apply(i);
+				dxfDocWriter.addEntity(apply);
+			}
+			FileUtil.deleteFile(new File(generateNewDxf));
+			dxfDocWriter.save(generateNewDxf, true);
+		}
+	}
+
+	public static <T extends BaseDxfEntity> void generateDxf(String generateNewDxf, DxfExtent extent, List<T> entity) {
+		try (DxfDocWriter dxfDocWriter = new DxfDocWriter(null, extent, StandardCharsets.UTF_8)) {
+			for (T t : entity) {
+				dxfDocWriter.addEntity(t);
+			}
+			FileUtil.deleteFile(new File(generateNewDxf));
+			dxfDocWriter.save(generateNewDxf, true);
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+	}
+}

+ 22 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/Vector3.java

@@ -0,0 +1,22 @@
+package com.fdkankan.dxf.generate;
+
+import lombok.AllArgsConstructor;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+
+/**
+ * Vector for 3 dimension
+ *
+ * @author YTZJJ
+ */
+@AllArgsConstructor
+@Getter
+@EqualsAndHashCode
+public class Vector3 {
+
+	private double x;
+	private double y;
+	private double z;
+
+	public static Vector3 ZERO = new Vector3(0, 0, 0);
+}

+ 111 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/enums/LineWidthEnum.java

@@ -0,0 +1,111 @@
+package com.fdkankan.dxf.generate.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * @author YTZJJ
+ */
+@Getter
+@AllArgsConstructor
+public enum LineWidthEnum {
+
+	/**
+	 * line width 0 mm
+	 */
+	LW_0(0),
+	/**
+	 * line width 5 mm
+	 */
+	LW_5(5),
+	/**
+	 * line width 9 mm
+	 */
+	LW_9(9),
+	/**
+	 * line width 13 mm
+	 */
+	LW_13(13),
+	/**
+	 * line width 15 mm
+	 */
+	LW_15(15),
+	/**
+	 * line width 18 mm
+	 */
+	LW_18(18),
+	/**
+	 * line width 20 mm
+	 */
+	LW_20(20),
+	/**
+	 * line width 25 mm
+	 */
+	LW_25(25),
+	/**
+	 * line width 30 mm
+	 */
+	LW_30(30),
+	/**
+	 * line width 35 mm
+	 */
+	LW_35(35),
+	/**
+	 * line width 40 mm
+	 */
+	LW_40(40),
+	/**
+	 * line width 50 mm
+	 */
+	LW_50(50),
+	/**
+	 * line width 53 mm
+	 */
+	LW_53(53),
+	/**
+	 * line width 60 mm
+	 */
+	LW_60(60),
+	/**
+	 * line width 70 mm
+	 */
+	LW_70(70),
+	/**
+	 * line width 80 mm
+	 */
+	LW_80(80),
+	/**
+	 * line width 90 mm
+	 */
+	LW_90(90),
+	/**
+	 * line width 100 mm
+	 */
+	LW_100(100),
+	/**
+	 * line width 106 mm
+	 */
+	LW_106(106),
+	/**
+	 * line width 120 mm
+	 */
+	LW_120(120),
+	/**
+	 * line width 140 mm
+	 */
+	LW_140(140),
+	/**
+	 * line width 158 mm
+	 */
+	LW_158(158),
+	/**
+	 * line width 200 mm
+	 */
+	LW_200(200),
+	/**
+	 * line width 211 mm
+	 */
+	LW_211(211);
+
+	private int code;
+}

+ 76 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/kml/CGCS2000ToWGS84.java

@@ -0,0 +1,76 @@
+package com.fdkankan.dxf.generate.kml;
+
+import org.locationtech.proj4j.*;
+
+public class CGCS2000ToWGS84 {
+
+    /**
+     * 经纬度坐标转换
+     * 坐标代码:authority是PROJ.4支持的名称空间的代码。目前支持的取值为EPSG、ESRI、WORLD、NA83、NAD27。如果没有提供权限,则假定使用EPSG名称空间。
+     * 代码是权威名称空间中坐标系统的id。例如,在EPSG命名空间中,代码是一个整数值,用于标识EPSG数据库中的CRS定义。(代码作为字符串读取和处理)
+     *
+     * @param sourceFromName 源坐标空间代码,如:EPSG:4524
+     * @param targetFromName 目标坐标空间代码, 如: EPSG:4326
+     * @param x              经度
+     * @param y              纬度
+     * @return
+     */
+    public static ProjCoordinate converter(String sourceFromName, String targetFromName, Double x, Double y, Double z) {
+        CRSFactory crsFactory = new CRSFactory();
+        CoordinateReferenceSystem sourceCRS = crsFactory.createFromName(sourceFromName); // 大地2000坐标系
+        CoordinateReferenceSystem targetCRS = crsFactory.createFromName(targetFromName); // 正常经纬度坐标系
+
+
+        CoordinateTransformFactory ctf = new CoordinateTransformFactory();
+        CoordinateTransform transform = ctf.createTransform(sourceCRS, targetCRS);
+
+
+        // 3. 将大地2000坐标转换为正常经纬度坐标
+        ProjCoordinate sourceCoordinate = new ProjCoordinate(x, y, z); // 大地2000坐标点
+        ProjCoordinate targetCoordinate = new ProjCoordinate(); // 用于存储转换后的坐标点
+        transform.transform(sourceCoordinate, targetCoordinate);
+
+        return targetCoordinate;
+    }
+
+
+    /**
+     * 经纬度坐标转换
+     * 坐标代码:authority是PROJ.4支持的名称空间的代码。目前支持的取值为EPSG、ESRI、WORLD、NA83、NAD27。如果没有提供权限,则假定使用EPSG名称空间。
+     * 代码是权威名称空间中坐标系统的id。例如,在EPSG命名空间中,代码是一个整数值,用于标识EPSG数据库中的CRS定义。(代码作为字符串读取和处理)
+     *
+     * @param sourceFromName 源坐标空间代码,如:EPSG:4524
+     * @param targetFromName 目标坐标空间代码, 如:
+     * @param x              经度
+     * @param y              纬度
+     * @return
+     */
+    public static ProjCoordinate converter(String sourceFromName, String targetFromName, Double x, Double y) {
+        return converter(sourceFromName, targetFromName, x, y, 0D);
+    }
+
+    /**
+     * CGCS2000 3度带 中央经线108 带号36 转 wgs84
+     * 经纬度坐标转换 (EPSG: 4524, EPSG: 4326)
+     *
+     * @param x 经度
+     * @param y 纬度
+     * @return
+     */
+    public static ProjCoordinate converter(Double x, Double y) {
+        return converter("EPSG:4524", "EPSG:4326", x, y, 0D);
+    }
+
+    /**
+     * CGCS2000 3度带 中央经线108 带号36 转 wgs84
+     * 经纬度坐标转换 (EPSG: 4524, EPSG: 4326)
+     *
+     * @param x 经度
+     * @param y 纬度
+     * @param z 高程
+     * @return
+     */
+    public static ProjCoordinate converter(Double x, Double y, Double z) {
+        return converter("EPSG:4524", "EPSG:4326", x, y, z);
+    }
+}

+ 225 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/kml/GenerateKml.java

@@ -0,0 +1,225 @@
+package com.fdkankan.dxf.generate.kml;
+
+import com.fdkankan.dxf.parse.constant.EntityNameConstant;
+import com.fdkankan.dxf.parse.model.GeometricModel;
+import com.fdkankan.dxf.parse.model.entities.*;
+import com.fdkankan.dxf.parse.resolver.DxfResolver;
+import com.fdkankan.dxf.parse.transformation.DxfLineTransformation;
+import com.fdkankan.dxf.parse.transformation.impl.DxfLineTransformationImpl;
+import com.fdkankan.dxf.parse.transformation.model.DxfLine;
+import com.fdkankan.dxf.parse.transformation.model.DxfPoint;
+import de.micromata.opengis.kml.v_2_2_0.*;
+import org.locationtech.proj4j.ProjCoordinate;
+
+import java.io.File;
+import java.util.*;
+
+/**
+ * @Author ytzjj
+ * @DateTime 2023/11/28 9:25
+ * @Description kml文件生成
+ */
+public class GenerateKml {
+
+
+    public static Kml gemerateKmlFile(File file, DxfResolver dxfResolver) {
+        Kml kml = new Kml();
+        // 构建kml
+        Folder rootFolder = buildKml(kml, UUID.randomUUID().toString().replaceAll("-", ""), file.getName().substring(0, file.getName().indexOf(".")));
+
+        Set<String> keyedSet = dxfResolver.getStructureMap().keySet();
+        for (String key : keyedSet) {
+            if (EntityNameConstant.POINT_NAME.equals(key)) {
+                // 点
+                List<GeometricPoint> geometricPointList = dxfResolver.getGeometricPointList();
+                for (GeometricPoint geometricPoint : geometricPointList) {
+                    Placemark placemark = rootFolder.createAndAddPlacemark();
+                    placemark.setOpen(true);
+                    String vertexId = String.valueOf(geometricPoint.getId());
+                    placemark.setId(Optional.ofNullable(String.valueOf(vertexId)).filter(id -> !"".equals(id) && !"null".equals(id)).orElse(UUID.randomUUID().toString().replaceAll("-", "")));
+                    placemark.setName(geometricPoint.getName());
+
+                    Style style = placemark.createAndAddStyle();
+                    LabelStyle labelStyle = new LabelStyle();
+                    labelStyle.setColor(geometricPoint.getColor());
+                    labelStyle.setColorMode(ColorMode.NORMAL);
+                    labelStyle.setScale(1);
+                    style.setLabelStyle(labelStyle);
+
+
+                    Point point = new Point();
+                    List<Coordinate> andSetCoordinates = point.createAndSetCoordinates();
+                    Double x = geometricPoint.getX() != null ? geometricPoint.getX().doubleValue() : 0.0D;
+                    Double y = geometricPoint.getY() != null ? geometricPoint.getY().doubleValue() : 0.0D;
+                    Double z = geometricPoint.getZ() != null ? geometricPoint.getZ().doubleValue() : 0.0D;
+                    ProjCoordinate projCoordinate = CGCS2000ToWGS84.converter(x, y, z);
+                    projCoordinate.z = Double.isNaN(projCoordinate.z) ? 0D : projCoordinate.z;
+                    andSetCoordinates.add(new Coordinate(projCoordinate.x, projCoordinate.y, projCoordinate.z));
+                    placemark.setGeometry(point);
+                }
+            } else if (EntityNameConstant.LINE_NAME.equals(key)) {
+                // 线条
+                List<GeometricLine> geometricLineList = dxfResolver.getGeometricLineList();
+
+
+                for (GeometricLine geometricLine : geometricLineList) {
+                    Placemark placemark = rootFolder.createAndAddPlacemark();
+
+                    Style andAddStyle = placemark.createAndAddStyle();
+                    LabelStyle labelStyle = new LabelStyle();
+                    labelStyle.setColor(geometricLine.getColor());
+                    labelStyle.setColorMode(ColorMode.NORMAL);
+                    andAddStyle.setLabelStyle(labelStyle);
+
+                    placemark.setOpen(true);
+                    String vertexId = String.valueOf(geometricLine.getId());
+                    placemark.setId(Optional.ofNullable(String.valueOf(vertexId)).filter(id -> !"".equals(id) && !"null".equals(id)).orElse(UUID.randomUUID().toString().replaceAll("-", "")));
+                    placemark.setName(geometricLine.getName());
+                    LineString lineString = new LineString();
+                    List<Coordinate> andSetCoordinates = lineString.createAndSetCoordinates();
+
+                    Double x1 = geometricLine.getStartX() != null ? geometricLine.getStartX().doubleValue() : 0.0D;
+                    Double y1 = geometricLine.getStartY() != null ? geometricLine.getStartY().doubleValue() : 0.0D;
+                    Double z1 = geometricLine.getStartZ() != null ? geometricLine.getStartZ().doubleValue() : 0.0D;
+                    ProjCoordinate projCoordinate1 = CGCS2000ToWGS84.converter(x1, y1, z1);
+                    projCoordinate1.z = Double.isNaN(projCoordinate1.z) ? 0D : projCoordinate1.z;
+                    andSetCoordinates.add(new Coordinate(projCoordinate1.x, projCoordinate1.y, projCoordinate1.z));
+
+
+                    Double x2 = geometricLine.getEndX() != null ? geometricLine.getEndX().doubleValue() : 0.0D;
+                    Double y2 = geometricLine.getEndY() != null ? geometricLine.getEndY().doubleValue() : 0.0D;
+                    Double z2 = geometricLine.getEndZ() != null ? geometricLine.getEndZ().doubleValue() : 0.0D;
+                    ProjCoordinate projCoordinate2 = CGCS2000ToWGS84.converter(x2, y2, z2);
+                    projCoordinate2.z = Double.isNaN(projCoordinate2.z) ? 0D : projCoordinate2.z;
+                    andSetCoordinates.add(new Coordinate(projCoordinate2.x, projCoordinate2.y, projCoordinate2.z));
+
+                    placemark.setGeometry(lineString);
+                }
+
+            } else if (EntityNameConstant.POLY_LINE_NAME.equals(key)) {
+                // 多线
+                List<GeometricPolyLine> geometricPolyLineList = dxfResolver.getGeometricPolyLineList();
+
+                for (GeometricPolyLine geometricPolyLine : geometricPolyLineList) {
+                    List<GeometricVertex> vertexList = geometricPolyLine.getVertexList();
+
+                    Placemark placemark = rootFolder.createAndAddPlacemark();
+                    Style andAddStyle = placemark.createAndAddStyle();
+                    LineStyle lineStyle = new LineStyle();
+                    lineStyle.setColor(geometricPolyLine.getColor());
+                    lineStyle.setColorMode(ColorMode.NORMAL);
+                    lineStyle.setWidth(!Objects.equals(geometricPolyLine.getLineWidth(), 0D) ? geometricPolyLine.getLineWidth() : 1D);
+
+                    String vertexId = String.valueOf(geometricPolyLine.getId());
+                    placemark.setId(Optional.ofNullable(String.valueOf(vertexId)).filter(id -> !"".equals(id) && !"null".equals(id)).orElse(UUID.randomUUID().toString().replaceAll("-", "")));
+                    placemark.setName(geometricPolyLine.getName());
+                    LineString lineString = new LineString();
+                    List<Coordinate> andSetCoordinates = lineString.createAndSetCoordinates();
+                    for (GeometricVertex geometricVertex : vertexList) {
+                        andAddStyle.setLineStyle(lineStyle);
+                        Double x = geometricVertex.getX() != null ? geometricVertex.getX().doubleValue() : 0.0D;
+                        Double y = geometricVertex.getY() != null ? geometricVertex.getY().doubleValue() : 0.0D;
+                        Double z = geometricVertex.getZ() != null ? geometricVertex.getZ().doubleValue() : 0.0D;
+                        ProjCoordinate projCoordinate = CGCS2000ToWGS84.converter(x, y, z);
+                        projCoordinate.z = Double.isNaN(projCoordinate.z) ? 0D : projCoordinate.z;
+                        andSetCoordinates.add(new Coordinate(projCoordinate.x, projCoordinate.y, projCoordinate.z));
+                    }
+                    placemark.setGeometry(lineString);
+                }
+
+            } else if (EntityNameConstant.ARC_NAME.equals(key)) {
+                // 弧度
+                List<GeometricArc> geometricArcList = dxfResolver.getGeometricArcList();
+                List<GeometricModel> geometricModelList = new ArrayList<>(geometricArcList);
+                // 将几何弧线、转换为点弧线数据
+                DxfLineTransformation dxfLineTransformation = DxfLineTransformationImpl.getSingleInstance();
+                List<DxfLine> dxfLines = dxfLineTransformation.arcTransform(geometricModelList);
+
+                // 循环点弧线数据
+                for (DxfLine dxfLine : dxfLines) {
+                    List<DxfPoint> dataPointList = dxfLine.getDataPointList();
+                    Placemark placemark = rootFolder.createAndAddPlacemark();
+                    placemark.setId(UUID.randomUUID().toString().replaceAll("-", ""));
+                    placemark.setName(dxfLine.getLayerName());
+                    LineString lineString = new LineString();
+                    List<Coordinate> andSetCoordinates = lineString.createAndSetCoordinates();
+                    // 循环弧线内的点数据
+                    for (DxfPoint dxfPoint : dataPointList) {
+                        Double x = dxfPoint.getX() != null ? dxfPoint.getX().doubleValue() : 0.0D;
+                        Double y = dxfPoint.getY() != null ? dxfPoint.getY().doubleValue() : 0.0D;
+                        Double z = dxfPoint.getZ() != null ? dxfPoint.getZ().doubleValue() : 0.0D;
+                        ProjCoordinate projCoordinate = CGCS2000ToWGS84.converter(x, y, z);
+                        projCoordinate.z = Double.isNaN(projCoordinate.z) ? 0D : projCoordinate.z;
+                        andSetCoordinates.add(new Coordinate(projCoordinate.x, projCoordinate.y, projCoordinate.z));
+                    }
+                    placemark.setGeometry(lineString);
+                }
+            } else if (EntityNameConstant.CIRCLE_NAME.equals(key)) {
+                // 圆形
+                List<GeometricCircle> geometricCircleList = dxfResolver.getGeometricCircleList();
+                for (GeometricCircle geometricCircle : geometricCircleList) {
+                    Placemark placemark = rootFolder.createAndAddPlacemark();
+
+                    Style andAddStyle = placemark.createAndAddStyle();
+                    LabelStyle labelStyle = new LabelStyle();
+                    labelStyle.setColor(geometricCircle.getColor());
+                    labelStyle.setColorMode(ColorMode.NORMAL);
+                    andAddStyle.setLabelStyle(labelStyle);
+
+
+                    String vertexId = String.valueOf(geometricCircle.getId());
+                    placemark.setId(Optional.ofNullable(String.valueOf(vertexId)).filter(id -> !"".equals(id) && !"null".equals(id)).orElse(UUID.randomUUID().toString().replaceAll("-", "")));
+                    placemark.setName(geometricCircle.getName());
+                    Point point = new Point();
+                    List<Coordinate> andSetCoordinates = point.createAndSetCoordinates();
+                    Double x = geometricCircle.getX() != null ? geometricCircle.getX().doubleValue() : 0.0D;
+                    Double y = geometricCircle.getY() != null ? geometricCircle.getY().doubleValue() : 0.0D;
+                    Double z = geometricCircle.getZ() != null ? geometricCircle.getZ().doubleValue() : 0.0D;
+                    ProjCoordinate projCoordinate = CGCS2000ToWGS84.converter(x, y, z);
+                    projCoordinate.z = Double.isNaN(projCoordinate.z) ? 0D : projCoordinate.z;
+                    andSetCoordinates.add(new Coordinate(projCoordinate.x, projCoordinate.y, projCoordinate.z));
+                    placemark.setGeometry(point);
+                }
+
+            } else if (EntityNameConstant.TEXT_NAME.equals(key)) {
+                // 文本
+                List<GeometricText> geometricTextList = dxfResolver.getGeometricTextList();
+                for (GeometricText geometricText : geometricTextList) {
+                    Placemark placemark = rootFolder.createAndAddPlacemark();
+
+                    Style andAddStyle = placemark.createAndAddStyle();
+                    LabelStyle labelStyle = new LabelStyle();
+                    labelStyle.setColor(geometricText.getColor());
+                    labelStyle.setColorMode(ColorMode.NORMAL);
+                    andAddStyle.setLabelStyle(labelStyle);
+
+
+                    String vertexId = String.valueOf(geometricText.getId());
+                    placemark.setId(Optional.ofNullable(String.valueOf(vertexId)).filter(id -> !"".equals(id) && !"null".equals(id)).orElse(UUID.randomUUID().toString().replaceAll("-", "")));
+                    placemark.setName(geometricText.getText());
+                    Point point = new Point();
+                    List<Coordinate> andSetCoordinates = point.createAndSetCoordinates();
+                    Double x = geometricText.getX() != null ? geometricText.getX().doubleValue() : 0.0D;
+                    Double y = geometricText.getY() != null ? geometricText.getY().doubleValue() : 0.0D;
+                    Double z = geometricText.getZ() != null ? geometricText.getZ().doubleValue() : 0.0D;
+                    ProjCoordinate projCoordinate = CGCS2000ToWGS84.converter(x, y, z);
+                    projCoordinate.z = Double.isNaN(projCoordinate.z) ? 0D : projCoordinate.z;
+                    andSetCoordinates.add(new Coordinate(projCoordinate.x, projCoordinate.y, projCoordinate.z));
+                    placemark.setGeometry(point);
+                }
+            }
+        }
+        return kml;
+    }
+
+    public static Folder buildKml(Kml kml, String rootId, String rootName) {
+        // 创建KML文档
+        Document document = kml.createAndSetDocument();
+        Folder rootFolder = document.createAndAddFolder();
+        rootFolder.setId(rootId);
+        rootFolder.setName(rootName);
+        rootFolder.setOpen(true);
+        return rootFolder;
+    }
+
+}

+ 35 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/model/DxfArc.java

@@ -0,0 +1,35 @@
+package com.fdkankan.dxf.generate.model;
+
+import com.fdkankan.dxf.generate.util.DxfLineBuilder;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 圆弧
+ *
+ * @author YTZJJ
+ */
+@Getter
+@Setter
+public class DxfArc extends DxfCircle {
+	/**
+	 * 起始角度(0-360)
+	 */
+	private double startAngle;
+	/**
+	 * 结束角度(0-360)
+	 */
+	private double endAngle;
+
+	@Override
+	protected String getChildDxfStr() {
+
+		return DxfLineBuilder.build().append(super.getChildDxfStr()).append(100, "AcDbArc").append(50, startAngle).append(51, endAngle).toString();
+	}
+
+	@Override
+	public String getEntityName() {
+		return "ARC";
+	}
+
+}

+ 45 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/model/DxfCircle.java

@@ -0,0 +1,45 @@
+package com.fdkankan.dxf.generate.model;
+
+import com.fdkankan.dxf.generate.Vector3;
+import com.fdkankan.dxf.generate.model.base.BaseDxfEntity;
+import com.fdkankan.dxf.generate.util.DxfLineBuilder;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * 圆
+ *
+ * @author YTZJJ
+ */
+@Getter
+@Setter
+@AllArgsConstructor
+@NoArgsConstructor
+public class DxfCircle extends BaseDxfEntity {
+
+	/**
+	 * 圆心位置
+	 */
+	private Vector3 center;
+	/**
+	 * 半径
+	 */
+	private double radius;
+
+	@Override
+	public String getEntityName() {
+		return "CIRCLE";
+	}
+
+	@Override
+	public String getEntityClassName() {
+		return "AcDbCircle";
+	}
+
+	@Override
+	protected String getChildDxfStr() {
+		return DxfLineBuilder.build().append(10, center.getX()).append(20, center.getY()).append(30, center.getZ()).append(40, radius).toString();
+	}
+}

+ 68 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/model/DxfEllipse.java

@@ -0,0 +1,68 @@
+package com.fdkankan.dxf.generate.model;
+
+import com.fdkankan.dxf.generate.Vector3;
+import com.fdkankan.dxf.generate.model.base.BaseDxfEntity;
+import com.fdkankan.dxf.generate.util.DxfLineBuilder;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 椭圆
+ *
+ * @author YTZJJ
+ */
+@Getter
+@Setter
+public class DxfEllipse extends BaseDxfEntity {
+
+	/**
+	 * 中心点
+	 */
+	private Vector3 centerPoint;
+	/**
+	 * 长轴相对于中心点的坐标
+	 */
+	private Vector3 majorAxisPoint;
+	/**
+	 * 短轴相对于长轴的缩放比例
+	 */
+	private double shortAxisScale = 1.0;
+	/**
+	 * 图形是否闭合
+	 */
+	private boolean close = true;
+	/**
+	 * 开始角度(0-360),当图形闭合时默认为0
+	 */
+	private double startAngle = 0;
+	/**
+	 * 结束角度(0-360),当图形闭合时,默认是360
+	 */
+	private double endAngle = 360;
+
+	@Override
+	protected String getChildDxfStr() {
+		DxfLineBuilder lineBuilder = DxfLineBuilder.build();
+		lineBuilder.append(10, centerPoint.getX()).append(20, centerPoint.getY()).append(30, centerPoint.getZ()).append(11, majorAxisPoint.getX()).append(21, majorAxisPoint.getY())
+				.append(31, majorAxisPoint.getZ()).append(40, shortAxisScale);
+		if (close) {
+			lineBuilder.append(41, 0);
+			lineBuilder.append(42, 2 * Math.PI);
+		} else {
+			lineBuilder.append(41, startAngle / 180 * Math.PI);
+			lineBuilder.append(42, endAngle / 180 * Math.PI);
+		}
+
+		return lineBuilder.toString();
+	}
+
+	@Override
+	public String getEntityName() {
+		return "ELLIPSE";
+	}
+
+	@Override
+	public String getEntityClassName() {
+		return "AcDbEllipse";
+	}
+}

+ 39 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/model/DxfHatch.java

@@ -0,0 +1,39 @@
+package com.fdkankan.dxf.generate.model;
+
+import com.fdkankan.dxf.generate.model.base.BaseDxfEntity;
+import com.fdkankan.dxf.generate.util.DxfLineBuilder;
+import lombok.Getter;
+
+/**
+ * @author YTZJJ
+ */
+@Getter
+public class DxfHatch extends BaseDxfEntity {
+
+	private DxfSolid dxfSolid;
+
+	public static DxfHatch buildHatchBy(BaseDxfEntity dxfCircle) {
+		DxfHatch dxfHatch = new DxfHatch();
+		dxfHatch.dxfSolid = new DxfSolid();
+		dxfHatch.dxfSolid.setDxfEntity(dxfCircle);
+		dxfHatch.color = dxfCircle.getSolidColor() == null ? dxfCircle.getColor() : dxfCircle.getSolidColor();
+		dxfHatch.alpha = dxfCircle.getSolidAlpha();
+		return dxfHatch;
+	}
+
+	@Override
+	protected String getChildDxfStr() {
+		return DxfLineBuilder.build().append(10, 0.0).append(20, 0.0).append(30, 0.0).append(210, 0.0).append(220, 0.0).append(230, 1.0).append(dxfSolid.getDxfStr()).toString();
+	}
+
+	@Override
+	public String getEntityName() {
+		return "HATCH";
+	}
+
+	@Override
+	public String getEntityClassName() {
+		return "AcDbHatch";
+	}
+
+}

+ 45 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/model/DxfLine.java

@@ -0,0 +1,45 @@
+package com.fdkankan.dxf.generate.model;
+
+import com.fdkankan.dxf.generate.Vector3;
+import com.fdkankan.dxf.generate.model.base.BaseDxfEntity;
+import com.fdkankan.dxf.generate.util.DxfLineBuilder;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * 线段
+ *
+ * @author YTZJJ
+ */
+@Getter
+@Setter
+@AllArgsConstructor
+@NoArgsConstructor
+public class DxfLine extends BaseDxfEntity {
+	/**
+	 * 起始点位置
+	 */
+	private Vector3 startPoint;
+	/**
+	 * 结束点位置
+	 */
+	private Vector3 endPoint;
+
+	@Override
+	protected String getChildDxfStr() {
+		return DxfLineBuilder.build().append(10, startPoint.getX()).append(20, startPoint.getY()).append(30, startPoint.getZ()).append(11, endPoint.getX()).append(21, endPoint.getY())
+				.append(31, endPoint.getZ()).toString();
+	}
+
+	@Override
+	public String getEntityName() {
+		return "LINE";
+	}
+
+	@Override
+	public String getEntityClassName() {
+		return "AcDbLine";
+	}
+}

+ 90 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/model/DxfLwPolyLine.java

@@ -0,0 +1,90 @@
+package com.fdkankan.dxf.generate.model;
+
+import com.fdkankan.dxf.generate.Vector3;
+import com.fdkankan.dxf.generate.model.base.BaseDxfEntity;
+import com.fdkankan.dxf.generate.util.DxfLineBuilder;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 多段线图元
+ *
+ * @author YTZJJ
+ */
+@AllArgsConstructor
+@Getter
+@Setter
+public class DxfLwPolyLine extends BaseDxfEntity {
+
+    /**
+     * 各个点的集合
+     */
+    private List<Vector3> points;
+    /**
+     * 多线段是否闭合
+     */
+    private boolean isClose = false;
+
+
+
+    public DxfLwPolyLine() {
+        points = new ArrayList<>();
+    }
+
+    /**
+     * 向多线段中添加一个坐标点
+     *
+     * @param p 坐标点
+     */
+    public void addPoint(Vector3 p) {
+        points.add(p);
+    }
+
+    public void addPoints(List<Vector3> p) {
+        points.addAll(p);
+    }
+
+    /***
+     * 从多线段中移除一个坐标点
+     *
+     * @param p 坐标点
+     */
+    public void removePoint(Vector3 p) {
+        points.remove(p);
+    }
+
+    /**
+     * 多线段图元中内容是否为空
+     *
+     * @return 若图元空不包含任何坐标点返回true
+     */
+    public boolean isEmpty() {
+        return points.isEmpty();
+    }
+
+    @Override
+    protected String getChildDxfStr() {
+        DxfLineBuilder lineBuilder = DxfLineBuilder.build();
+        lineBuilder.append(90, points.size());
+        lineBuilder.append(70, isClose ? 1 : 0);
+        lineBuilder.append(43, 0.0);
+        for (Vector3 point : points) {
+            lineBuilder.append(10, point.getX()).append(20, point.getY()).append(30, point.getZ());
+        }
+        return lineBuilder.toString();
+    }
+
+    @Override
+    public String getEntityName() {
+        return "LWPOLYLINE";
+    }
+
+    @Override
+    public String getEntityClassName() {
+        return "AcDbPolyline";
+    }
+}

+ 46 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/model/DxfPoint.java

@@ -0,0 +1,46 @@
+package com.fdkankan.dxf.generate.model;
+
+import com.fdkankan.dxf.generate.Vector3;
+import com.fdkankan.dxf.generate.model.base.BaseDxfEntity;
+import com.fdkankan.dxf.generate.util.DxfLineBuilder;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 点实体对象
+ **/
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class DxfPoint extends BaseDxfEntity {
+    private Vector3 point = new Vector3(0, 0, 0);
+
+    public DxfPoint() {
+
+    }
+
+    public DxfPoint(double x, double y, double z) {
+        this.point = new Vector3(x, y, z);
+    }
+
+    public DxfPoint(Vector3 point) {
+        this.point = point;
+    }
+
+    @Override
+    protected String getChildDxfStr() {
+        return DxfLineBuilder.build()
+                .append(10, String.format("%.6f", point.getX()))
+                .append(20, String.format("%.6f", point.getY()))
+                .append(30, String.format("%.6f", point.getZ())).toString();
+    }
+
+    @Override
+    public String getEntityName() {
+        return "POINT";
+    }
+
+    @Override
+    public String getEntityClassName() {
+        return "AcDbPoint";
+    }
+}

+ 42 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/model/DxfRay.java

@@ -0,0 +1,42 @@
+package com.fdkankan.dxf.generate.model;
+
+import com.fdkankan.dxf.generate.Vector3;
+import com.fdkankan.dxf.generate.model.base.BaseDxfEntity;
+import com.fdkankan.dxf.generate.util.DxfLineBuilder;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 射线
+ *
+ * @author YTZJJ
+ */
+@Getter
+@Setter
+public class DxfRay extends BaseDxfEntity {
+
+	/**
+	 * 起始点位置
+	 */
+	private Vector3 start;
+	/**
+	 * 射线方向
+	 */
+	private Vector3 direction;
+
+	@Override
+	protected String getChildDxfStr() {
+		return DxfLineBuilder.build().append(10, start.getX()).append(20, start.getY()).append(30, start.getZ()).append(11, direction.getX()).append(21, direction.getY()).append(31, direction.getZ())
+				.toString();
+	}
+
+	@Override
+	public String getEntityName() {
+		return "RAY";
+	}
+
+	@Override
+	public String getEntityClassName() {
+		return "AcDbRay";
+	}
+}

+ 81 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/model/DxfSolid.java

@@ -0,0 +1,81 @@
+package com.fdkankan.dxf.generate.model;
+
+import com.fdkankan.dxf.generate.Vector3;
+import com.fdkankan.dxf.generate.model.base.DxfEntity;
+import com.fdkankan.dxf.generate.util.DxfLineBuilder;
+import com.fdkankan.dxf.generate.util.DxfUtil;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+
+/**
+ * 图案填充,目前仅仅支持实体颜色填充,不支持图案填充与渐变填充
+ *
+ * @author YTZJJ
+ */
+@Getter
+@Setter
+public class DxfSolid {
+    private DxfEntity dxfEntity;
+
+    public String getDxfStr() {
+
+        DxfLineBuilder builder = DxfLineBuilder.build(2, "SOLID")
+                // 实体填充标志(实体填充 = 1;图案填充 = 0)
+                .append(70, 1)
+                // 关联性标志(关联 = 1;无关联 = 0)
+                .append(71, 1)
+                // 边界数
+                .append(91, 1)
+                // 边界路径类型标志0 = 默认;1 = 外部;2 = 多段线;4 = 导出;8 = 文本框;16 = 最外层
+                .append(92, 1);
+        // 顶点数(93=)?
+        // 边界类型(72=) 1 = 直线;2 = 圆弧;3 = 椭圆弧;4 = 样条曲线
+        if (dxfEntity instanceof DxfLwPolyLine) {
+            builder.append(93, ((DxfLwPolyLine) dxfEntity).getPoints().size());
+            int size = ((DxfLwPolyLine) dxfEntity).getPoints().size();
+            List<Vector3> points = ((DxfLwPolyLine) dxfEntity).getPoints();
+            for (int i = 0; i < size; i++) {
+                builder.append(72, 1);
+                builder.append(10, points.get(i).getX());
+                builder.append(20, points.get(i).getY());
+                builder.append(30, points.get(i).getZ());
+                builder.append(11, points.get((i + 1) % size).getX());
+                builder.append(21, points.get((i + 1) % size).getY());
+            }
+
+        } else if (dxfEntity instanceof DxfCircle) {
+            builder.append(93, 1);
+            builder.append(72, 2).append(10, ((DxfCircle) dxfEntity).getCenter().getX()).append(20, ((DxfCircle) dxfEntity).getCenter().getY()).append(30, ((DxfCircle) dxfEntity).getCenter().getZ())
+                    .append(40, ((DxfCircle) dxfEntity).getRadius());
+            // 下面是圆弧的属性,50-起始角度,51-端点角度, 73-逆时针标志
+            if (dxfEntity instanceof DxfArc) {
+                builder.append(50, ((DxfArc) dxfEntity).getStartAngle());
+                builder.append(51, ((DxfArc) dxfEntity).getEndAngle());
+            } else {
+                builder.append(50, 0.0).append(51, 360);
+            }
+            builder.append(73, 1);
+        }
+
+        // 源边界对象数
+        builder.append(97, 1)
+                // 源边界对象的参照
+                .append(330, DxfUtil.formatMeta(dxfEntity.getMeta()))
+                // 图案填充样式:,0 = 填充“奇数奇偶校验”区域(普通样式),1 = 仅填充最外层区域(“外部”样式),2 = 填充整个区域(“忽略”样式)
+                .append(75, 0)
+                // 填充图案类型:0 = 用户定义;1 = 预定义;2 = 自定义
+                .append(76, 1)
+                // 种子点数
+                .append(98, 1);
+        // 种子点位置 10-x, 20-y
+        if (dxfEntity instanceof DxfCircle) {
+            builder.append(10, ((DxfCircle) dxfEntity).getCenter().getX()).append(20, ((DxfCircle) dxfEntity).getCenter().getY());
+        } else {
+            builder.append(10, 0.);
+            builder.append(20, 0.);
+        }
+        return builder.toString();
+    }
+}

+ 100 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/model/DxfText.java

@@ -0,0 +1,100 @@
+package com.fdkankan.dxf.generate.model;
+
+import com.fdkankan.dxf.generate.Vector3;
+import com.fdkankan.dxf.generate.model.base.BaseDxfEntity;
+import com.fdkankan.dxf.generate.util.DxfLineBuilder;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 文字
+ *
+ * @author YTZJJ
+ */
+@Getter
+@Setter
+public class DxfText extends BaseDxfEntity {
+
+	/**
+	 * 不翻转
+	 */
+	public static final int REVERSE_TYPE_NONE = 0;
+	/**
+	 * 沿X轴方向镜像翻转
+	 */
+	public static final int REVERSE_TYPE_X = 2;
+	/**
+	 * 沿Y轴方向镜像翻转
+	 */
+	public static final int REVERSE_TYPE_Y = 4;
+
+//    public static final int ALIGN_HORIZONTAL_LEFT = 0;
+//    public static final int ALIGN_HORIZONTAL_CENTER = 1;
+//    public static final int ALIGN_HORIZONTAL_RIGHT = 2;
+
+//    public static final int ALIGN_VERTICAL_BASE_LINE = 0;
+//    public static final int ALIGN_VERTICAL_BASE_BOTTOM = 1;
+//    public static final int ALIGN_VERTICAL_BASE_CENTER = 2;
+//    public static final int ALIGN_VERTICAL_BASE_TOP = 3;
+
+	/**
+	 * 文字的起始位置
+	 */
+	private Vector3 startPoint;
+	/**
+	 * 文字的高度
+	 */
+	private double high = 0;
+	/**
+	 * 文字的宽度
+	 */
+	private int width = 1;
+	/**
+	 * 文字内容
+	 */
+	private String text;
+	/**
+	 * 旋转角度
+	 */
+	private double angle = 0;
+	/**
+	 * 倾斜角度
+	 */
+	private double inclination = 0;
+//    private String textStyle = "标准";
+	private int reverseType = REVERSE_TYPE_NONE;
+	// 暂时不使用这两个属性
+	// private int alignHorizontal = ALIGN_HORIZONTAL_LEFT;
+//    private int alignVertical = ALIGN_VERTICAL_BASE_LINE;
+	// 这个值暂时也没用,只有当上面两个属性使用的时候这个值才有使用的必要
+//    private Vector3 endPoint;
+
+	@Override
+	protected String getChildDxfStr() {
+		DxfLineBuilder lineBuilder = DxfLineBuilder.build().append(10, startPoint.getX()).append(20, startPoint.getY()).append(30, startPoint.getZ()).append(40, high).append(1, text);
+		if (angle != 0) {
+			lineBuilder.append(50, angle);
+		}
+		if (width != 1) {
+			lineBuilder.append(41, width);
+		}
+		if (inclination != 0) {
+			lineBuilder.append(51, inclination);
+		}
+		if (reverseType != REVERSE_TYPE_NONE) {
+			lineBuilder.append(71, reverseType);
+		}
+		lineBuilder.append(100, getEntityClassName());
+		return lineBuilder.toString();
+	}
+
+	@Override
+	public String getEntityName() {
+		return "TEXT";
+	}
+
+	@Override
+	public String getEntityClassName() {
+		return "AcDbText";
+	}
+}

+ 24 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/model/DxfXLine.java

@@ -0,0 +1,24 @@
+package com.fdkankan.dxf.generate.model;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 构造线
+ *
+ * @author YTZJJ
+ */
+@Getter
+@Setter
+public class DxfXLine extends DxfRay {
+
+	@Override
+	public String getEntityName() {
+		return "XLINE";
+	}
+
+	@Override
+	public String getEntityClassName() {
+		return "AcDbXline";
+	}
+}

+ 94 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/model/base/BaseDxfEntity.java

@@ -0,0 +1,94 @@
+package com.fdkankan.dxf.generate.model.base;
+
+import com.fdkankan.dxf.generate.enums.LineWidthEnum;
+import com.fdkankan.dxf.generate.util.DxfLineBuilder;
+import com.fdkankan.dxf.generate.util.DxfUtil;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 所有Entity的基础类,其中定义了一些Entity的基础操作,作为组装Entity信息的中间桥梁也定义了 所有Entity都应该具备的一些基础设置,包括1.颜色。2.线宽。3.是否填充。4.填充颜色 <br>
+ * 所有的dxf文件的entity都应该去通过实现这个类来方便定义其结构
+ *
+ * @author YTZJJ
+ */
+@Getter
+@Setter
+public abstract class BaseDxfEntity implements DxfEntity {
+    protected long meta;
+    /**
+     * 颜色
+     */
+    protected Color color = Color.BLACK;
+    /**
+     * 线宽
+     */
+    protected LineWidthEnum lineWidth = LineWidthEnum.LW_0;
+    /**
+     * 是否填充
+     */
+    protected boolean solid = false;
+    /**
+     * 填充颜色
+     */
+    protected Color solidColor = null;
+    /**
+     * 图形透明度,取值范围为0-100,当alpha为0时,为不透明,当alpha为100的时候,图形将不可见
+     */
+    protected int alpha = 0;
+    /**
+     * 填充透明度
+     */
+    protected int solidAlpha = 0;
+    /**
+     * 图层名称
+     */
+    protected String layerName = "默认图层";
+
+    @Override
+    public String getDxfStr() {
+        return DxfLineBuilder.build(getEntityName())
+				.append(5, DxfUtil.formatMeta(meta))
+				.append(330, "1F")
+				.append(100, "AcDbEntity")
+				.append(8, layerName)
+				.append(420, formatDxfColor(color))
+                .append(440, alpha)
+				.append(370, lineWidth.getCode())
+				.append(100, getEntityClassName())
+				.append(getChildDxfStr()).toString();
+    }
+
+    /**
+     * 子类Entity的字符串格式,由继承此类的子类自己实现仅需实现其包含的数据项元组即可,无需返回子类名称信息, 例如Circle对象仅需返回其坐标值与半径即可,例如: <blockquote>
+     *
+     * <pre>
+     * 10
+     * 0.0
+     * 20
+     * 0.0
+     * 30
+     * 0.0
+     * 40
+     * 50.0
+     * </pre>
+     *
+     * </blockquote>
+     *
+     * @return Entity数据元组字符串
+     */
+    protected abstract String getChildDxfStr();
+
+    /**
+     * format color to dxf type, case color hex code to integer
+     *
+     * @param color color
+     * @return color
+     */
+    public static int formatDxfColor(Color color) {
+        if (color == null) {
+            color = Color.BLACK;
+        }
+        return (color.getRed() << 16) + (color.getGreen() << 8) + color.getBlue();
+    }
+}

+ 298 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/model/base/Color.java

@@ -0,0 +1,298 @@
+package com.fdkankan.dxf.generate.model.base;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class Color {
+    /**
+     * The color white.  In the default sRGB space.
+     */
+    public final static Color white = new Color(255, 255, 255);
+
+    /**
+     * The color white.  In the default sRGB space.
+     *
+     * @since 1.4
+     */
+    public final static Color WHITE = white;
+
+
+    /**
+     * The color light gray.  In the default sRGB space.
+     */
+    public final static Color lightGray = new Color(192, 192, 192);
+
+    /**
+     * The color light gray.  In the default sRGB space.
+     *
+     * @since 1.4
+     */
+    public final static Color LIGHT_GRAY = lightGray;
+
+    /**
+     * The color gray.  In the default sRGB space.
+     */
+    public final static Color gray = new Color(128, 128, 128);
+
+    /**
+     * The color gray.  In the default sRGB space.
+     *
+     * @since 1.4
+     */
+    public final static Color GRAY = gray;
+
+    /**
+     * The color dark gray.  In the default sRGB space.
+     */
+    public final static Color darkGray = new Color(64, 64, 64);
+
+    /**
+     * The color dark gray.  In the default sRGB space.
+     *
+     * @since 1.4
+     */
+    public final static Color DARK_GRAY = darkGray;
+
+    /**
+     * The color black.  In the default sRGB space.
+     */
+    public final static Color black = new Color(0, 0, 0);
+
+    /**
+     * The color black.  In the default sRGB space.
+     *
+     * @since 1.4
+     */
+    public final static Color BLACK = black;
+
+    /**
+     * The color red.  In the default sRGB space.
+     */
+    public final static Color red = new Color(255, 0, 0);
+
+    /**
+     * The color red.  In the default sRGB space.
+     *
+     * @since 1.4
+     */
+    public final static Color RED = red;
+
+    /**
+     * The color pink.  In the default sRGB space.
+     */
+    public final static Color pink = new Color(255, 175, 175);
+
+    /**
+     * The color pink.  In the default sRGB space.
+     *
+     * @since 1.4
+     */
+    public final static Color PINK = pink;
+
+    /**
+     * The color orange.  In the default sRGB space.
+     */
+    public final static Color orange = new Color(255, 200, 0);
+
+    /**
+     * The color orange.  In the default sRGB space.
+     *
+     * @since 1.4
+     */
+    public final static Color ORANGE = orange;
+
+    /**
+     * The color yellow.  In the default sRGB space.
+     */
+    public final static Color yellow = new Color(255, 255, 0);
+
+    /**
+     * The color yellow.  In the default sRGB space.
+     *
+     * @since 1.4
+     */
+    public final static Color YELLOW = yellow;
+
+    /**
+     * The color green.  In the default sRGB space.
+     */
+    public final static Color green = new Color(0, 255, 0);
+
+    /**
+     * The color green.  In the default sRGB space.
+     *
+     * @since 1.4
+     */
+    public final static Color GREEN = green;
+
+    /**
+     * The color magenta.  In the default sRGB space.
+     */
+    public final static Color magenta = new Color(255, 0, 255);
+
+    /**
+     * The color magenta.  In the default sRGB space.
+     *
+     * @since 1.4
+     */
+    public final static Color MAGENTA = magenta;
+
+    /**
+     * The color cyan.  In the default sRGB space.
+     */
+    public final static Color cyan = new Color(0, 255, 255);
+
+    /**
+     * The color cyan.  In the default sRGB space.
+     *
+     * @since 1.4
+     */
+    public final static Color CYAN = cyan;
+
+    /**
+     * The color blue.  In the default sRGB space.
+     */
+    public final static Color blue = new Color(0, 0, 255);
+
+    /**
+     * The color blue.  In the default sRGB space.
+     *
+     * @since 1.4
+     */
+    public final static Color BLUE = blue;
+
+
+    private int mR;
+    private int mG;
+    private int mB;
+    private float mA;
+
+    public Color(int red, int green, int blue, float alpha) {
+        this.mR = red;
+        this.mG = green;
+        this.mB = blue;
+        this.mA = alpha;
+    }
+
+    public Color(int red, int green, int blue) {
+        this(red, green, blue, 1.0f);
+    }
+
+    public int getRed() {
+        return mR;
+    }
+
+    public void setRed(int red) {
+        this.mR = red;
+    }
+
+    public int getGreen() {
+        return mG;
+    }
+
+    public void setGreen(int green) {
+        this.mG = green;
+    }
+
+    public int getBlue() {
+        return mB;
+    }
+
+    public void setBlue(int blue) {
+        this.mB = blue;
+    }
+
+    public float getAlpha() {
+        return mA;
+    }
+
+    public void setAlpha(float alpha) {
+        this.mA = alpha;
+    }
+
+    @Override
+    public String toString() {
+        return "Color{" +
+                "red=" + mR +
+                ", green=" + mG +
+                ", blue=" + mB +
+                ", alpha=" + mA +
+                '}';
+    }
+
+    public static Color fromRGBA(int red, int green, int blue, float alpha) {
+        return new Color(red, green, blue, alpha);
+    }
+
+    public static Color fromHex(String hex) {
+        hex = hex.replace("#", "");
+        int red = Integer.parseInt(hex.substring(0, 2), 16);
+        int green = Integer.parseInt(hex.substring(2, 4), 16);
+        int blue = Integer.parseInt(hex.substring(4, 6), 16);
+        float alpha = hex.length() == 8 ? Integer.parseInt(hex.substring(6, 8), 16) / 255.0f : 1.0f;
+        return new Color(red, green, blue, alpha);
+    }
+
+
+    public String toHex() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("#");
+        sb.append(Integer.toHexString(mR));
+        sb.append(Integer.toHexString(mG));
+        sb.append(Integer.toHexString(mB));
+        if (mA < 1.0f) {
+            sb.append(String.format("%02X", (int) (mA * 255)));
+        }
+        return sb.toString();
+    }
+
+
+    /**
+     * rgba 或 rgb 格式颜色转Color对象
+     *
+     * @param rgbaString
+     * @return
+     */
+    public static Color fromRGBAString(String rgbaString) throws IllegalArgumentException {
+        Pattern pattern = Pattern.compile("(rgba|rgb)\\((\\d+),\\s*(\\d+),\\s*(\\d+)(?:,\\s*([\\d.]+))?\\)");
+        Matcher matcher = pattern.matcher(rgbaString);
+        if (matcher.matches()) {
+            int red = Integer.parseInt(matcher.group(2));
+            int green = Integer.parseInt(matcher.group(3));
+            int blue = Integer.parseInt(matcher.group(4));
+            float alpha = matcher.group(5) != null ? Float.parseFloat(matcher.group(5)) : 1.0f;
+            return new Color(red, green, blue, alpha);
+        } else {
+            throw new IllegalArgumentException("Invalid RGBA color string: " + rgbaString);
+        }
+    }
+
+    public String toRGBA() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("rgba(");
+        sb.append(mR);
+        sb.append(",");
+        sb.append(mG);
+        sb.append(",");
+        sb.append(mB);
+        sb.append(",");
+        sb.append(mA);
+        sb.append(")");
+        return sb.toString();
+    }
+
+
+    /**
+     * 字符串颜色 支持rgba() rgb  16进制颜色 转为Color对象
+     *
+     * @param colorStr
+     * @return
+     */
+    public static Color colorStringToHex(String colorStr) throws IllegalArgumentException {
+        if (colorStr.contains("rgb") || colorStr.contains("rgba")) {
+            return fromRGBAString(colorStr);
+        } else {
+            return fromHex(colorStr);
+        }
+    }
+}

+ 42 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/model/base/DxfEntity.java

@@ -0,0 +1,42 @@
+package com.fdkankan.dxf.generate.model.base;
+
+/**
+ * @author YTZJJ
+ */
+public interface DxfEntity {
+
+	/**
+	 * 获取图元的dxf字符信息,字符信息应是符合Dxf标准的字符组列表,并且使用CRLF换行符进行换行
+	 *
+	 * @return 图元dxf字符信息
+	 */
+	String getDxfStr();
+
+	/**
+	 * 设置图元句柄
+	 *
+	 * @param meta 句柄值
+	 */
+	void setMeta(long meta);
+
+	/**
+	 * 获取图元的句柄值
+	 *
+	 * @return 图元句柄值
+	 */
+	long getMeta();
+
+	/**
+	 * 获取图元名称
+	 *
+	 * @return 图元名称
+	 */
+	String getEntityName();
+
+	/**
+	 * 获取图元对应的子类名称
+	 *
+	 * @return 子类名称
+	 */
+	String getEntityClassName();
+}

+ 33 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/model/support/DxfExtent.java

@@ -0,0 +1,33 @@
+package com.fdkankan.dxf.generate.model.support;
+
+import lombok.Data;
+
+/**
+ * org.enhance.dxf.model.support-DxfExtent
+ *
+ * @classname: DxfExtent
+ * @description: 对角线两点坐标
+ * @author: YTZJJ
+ * @date: 2023-10-20
+ **/
+@Data
+public class DxfExtent {
+    private double x1;
+    private double y1;
+    private double x2;
+    private double y2;
+    private String centerX;
+    private String centerY;
+    private String height;
+
+    public DxfExtent(double x1, double y1, double x2, double y2) {
+        this.x1 = x1;
+        this.y1 = y1;
+        this.x2 = x2;
+        this.y2 = y2;
+        double d = 114.145;
+        this.centerX = String.format("%.9f", (x1 + x2) / 2);
+        this.centerY = String.format("%.9f", (y1 + y2) / 2);
+        this.height = String.format("%.9f", (y2 - y1) * 1.2);
+    }
+}

+ 42 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/util/DxfLineBuilder.java

@@ -0,0 +1,42 @@
+package com.fdkankan.dxf.generate.util;
+
+/**
+ * dxf file format string assembly tool
+ *
+ * @author YTZJJ
+ */
+public class DxfLineBuilder {
+
+	private StringBuilder lineBuilder;
+
+	private DxfLineBuilder() {
+		this.lineBuilder = new StringBuilder();
+	}
+
+	public static DxfLineBuilder build(int code, String name) {
+		return new DxfLineBuilder().append(code, name);
+	}
+
+	public static DxfLineBuilder build(String name) {
+		return new DxfLineBuilder().append(0, name);
+	}
+
+	public static DxfLineBuilder build() {
+		return new DxfLineBuilder();
+	}
+
+	public DxfLineBuilder append(int code, Object value) {
+		lineBuilder.append(code).append("\r\n").append(value).append("\r\n");
+		return this;
+	}
+
+	public DxfLineBuilder append(String line) {
+		lineBuilder.append(line);
+		return this;
+	}
+
+	@Override
+	public String toString() {
+		return lineBuilder.toString();
+	}
+}

+ 69 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/util/DxfUtil.java

@@ -0,0 +1,69 @@
+package com.fdkankan.dxf.generate.util;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.util.Objects;
+
+/**
+ * @author YTZJJ
+ */
+public class DxfUtil {
+
+	public static boolean isPairNameEquals(String[] pair, String name) {
+		if (pair == null) {
+			return false;
+		}
+		return Objects.equals(name, pair[1].trim());
+	}
+
+	public static String formatMeta(long meta) {
+		return StringUtil.appendStart('0', 3, Long.toHexString(meta)).toUpperCase();
+	}
+
+	public static long readMaxMeta(String dxfFilePath) {
+		long maxMeta = 0;
+		try (BufferedReader br = StreamUtil.getFileReader(dxfFilePath)) {
+			while (true) {
+				String[] pair = StreamUtil.readNextPair(br);
+				if (pair == null) {
+					break;
+				}
+				if ("5".equals(pair[0].trim())) {
+					maxMeta = Math.max(maxMeta, Long.parseLong(pair[1].trim(), 16));
+				}
+			}
+		} catch (IOException e) {
+			System.err.println("read maxMeta error"+ e.getMessage());
+		}
+		return maxMeta;
+	}
+
+
+	/**
+	 * 将整数的颜色值,转为16进制 类似html16进制颜色表示形式
+	 *
+	 * @param colorValue
+	 * @return
+	 */
+	public static String convertToHtmlColor(int colorValue) {
+		// 将整数值转为16进制字符串
+		StringBuilder hexString = new StringBuilder(Integer.toHexString(colorValue));
+
+		// 补足到6位
+		while (hexString.length() < 6) {
+			hexString.insert(0, "0");
+		}
+
+		// 提取透明度和颜色值的部分
+		String alpha = hexString.substring(0, 2);
+		String blue = hexString.substring(2, 4);
+		String green = hexString.substring(4, 6);
+		String red = hexString.substring(6);
+
+		// 组合为KML的RGBA格式
+		String kmlColor = alpha + blue + green + red;
+
+		return kmlColor.toUpperCase();
+	}
+
+}

+ 29 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/util/FileUtil.java

@@ -0,0 +1,29 @@
+package com.fdkankan.dxf.generate.util;
+
+import java.io.File;
+
+public class FileUtil {
+
+	public static void deleteFile(File file) {
+		if (file.exists()) {
+			// dir type
+			if (file.isDirectory()) {
+				File[] files = file.listFiles();
+				if (files == null || files.length == 0) {
+					if (!file.delete()) {
+						System.err.println("delete dir fail," + file.getAbsolutePath());
+					}
+				} else {
+					System.err.println("can't delete a not empty dir," + file.getAbsolutePath());
+				}
+			} else { // file type
+				if (!file.delete()) {
+					System.err.println("delete File fail" + file.getAbsolutePath());
+				}
+			}
+		} else {
+			System.err.println("file not exists or not's a file" + file.getAbsolutePath());
+		}
+	}
+
+}

+ 90 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/util/FreemarkerSupport.java

@@ -0,0 +1,90 @@
+package com.fdkankan.dxf.generate.util;
+
+import freemarker.cache.ClassTemplateLoader;
+import freemarker.cache.MultiTemplateLoader;
+import freemarker.cache.TemplateLoader;
+import freemarker.ext.beans.BeansWrapperBuilder;
+import freemarker.template.Configuration;
+import freemarker.template.Template;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.StringReader;
+import java.io.StringWriter;
+
+public class FreemarkerSupport {
+
+    private Configuration configuration;
+
+    private FreemarkerSupport() {
+        configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
+
+        ClassTemplateLoader classTemplateLoader = new ClassTemplateLoader(ClassTemplateLoader.class, "/");
+        TemplateLoader[] loaders = new TemplateLoader[]{classTemplateLoader};
+
+        configuration.setTemplateLoader(new MultiTemplateLoader(loaders));
+        configuration.setObjectWrapper(new BeansWrapperBuilder(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS).build());
+    }
+
+    private static class SingletonHelper {
+        private static FreemarkerSupport instance = new FreemarkerSupport();
+    }
+
+    public static FreemarkerSupport getInstance() {
+        return SingletonHelper.instance;
+    }
+
+    public String processPath(String templatePath, Object object) {
+        return processPath(templatePath, object, false);
+    }
+
+    private String processPath(String templatePath, Object object, boolean removeBlankLines) {
+        Template template;
+        try {
+            template = configuration.getTemplate(templatePath);
+        } catch (IOException e) {
+            System.err.println(e.getMessage());
+            throw new RuntimeException("failed to get template by (templatePath=" + templatePath + ")", e);
+        }
+        String templateStr = this.processTemplate(template, object);
+        if (removeBlankLines) {
+            templateStr = removeBlankLines(templateStr);
+        }
+        return templateStr;
+    }
+
+    private String processTemplate(Template template, Object object) {
+        StringWriter writer = new StringWriter();
+        try {
+            if (template == null) {
+                throw new RuntimeException("错误模板为空");
+            }
+            template.process(object, writer);
+        } catch (Exception e) {
+            System.err.println(e.getMessage());
+            throw new RuntimeException("failed to get template by (template=" + template + ")", e);
+        }
+        return writer.toString();
+    }
+
+    private String removeBlankLines(String src) {
+        if (src != null && !src.trim().equals("")) {
+            StringBuilder sb = new StringBuilder();
+            String inputLine;
+            String lineSepartor = System.getProperty("line.separator");
+            try (BufferedReader bufferedReader = new BufferedReader(new StringReader(src))) {
+                while ((inputLine = bufferedReader.readLine()) != null) {
+                    if (inputLine.length() == 0 || inputLine.trim().length() == 0) {
+                        continue;
+                    }
+                    sb.append(inputLine).append(lineSepartor);
+                }
+            } catch (IOException e) {
+                System.err.println(e.getMessage());
+                throw new RuntimeException("failed to read source string (src=" + src + ")", e);
+            }
+            return sb.toString();
+        }
+        return src;
+    }
+}

+ 127 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/util/PicAnalysis.java

@@ -0,0 +1,127 @@
+package com.fdkankan.dxf.generate.util;/*
+package com.fdkankan.dxf.generate.util;
+
+import javax.imageio.ImageIO;
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Stack;
+
+public class PicAnalysis {
+	private static final int abs = 30;
+	public static final Color black = new Color(0, 0, 0);
+	public static final Color white = new Color(255, 255, 255);
+
+	public static int[][][] analysisPicture(BufferedImage img) {
+		int[][][] data = new int[0][][];
+		if (img != null) {
+			int width = img.getWidth();
+			int height = img.getHeight();
+			data = new int[width][height][3]; // [0]:0、1:黑;2:白;[1]next;[2]实际
+			// 分析图片获取数据
+			for (int x = 1; x < width - 1; x++) {
+				for (int y = 1; y < height - 1; y++) {
+					int rgb = img.getRGB(x, y);
+					Color colors = new Color(rgb);
+					data[x][y][2] = rgb;
+
+					double red = (new Color(data[x - 1][y][2]).getRed() + new Color(data[x + 1][y][2]).getRed() - new Color(data[x][y - 1][2]).getRed() - new Color(data[x][y + 1][2]).getRed()
+							+ 0.5 * (new Color(data[x - 1][y - 1][2]).getRed() - new Color(data[x + 1][y + 1][2]).getRed())
+							+ 0.5 * (new Color(data[x + 1][y - 1][2]).getRed() - new Color(data[x - 1][y + 1][2]).getRed()));
+					double green = (new Color(data[x - 1][y][2]).getGreen() + new Color(data[x + 1][y][2]).getGreen() - new Color(data[x][y - 1][2]).getGreen()
+							- new Color(data[x][y + 1][2]).getGreen() + 0.5 * (new Color(data[x - 1][y - 1][2]).getGreen() - new Color(data[x + 1][y + 1][2]).getGreen())
+							+ 0.5 * (new Color(data[x + 1][y - 1][2]).getGreen() - new Color(data[x - 1][y + 1][2]).getGreen()));
+					double blue = (new Color(data[x - 1][y][2]).getBlue() + new Color(data[x + 1][y][2]).getBlue() - new Color(data[x][y - 1][2]).getBlue() - new Color(data[x][y + 1][2]).getBlue()
+							+ 0.5 * (new Color(data[x - 1][y - 1][2]).getBlue() - new Color(data[x + 1][y + 1][2]).getBlue())
+							+ 0.5 * (new Color(data[x + 1][y - 1][2]).getBlue() - new Color(data[x - 1][y + 1][2]).getBlue()));
+
+					if (Math.abs(red) + Math.abs(green) + Math.abs(blue) < abs) {
+						data[x][y][0] = 1;
+					}
+
+					if ((colors.getRed() + colors.getBlue() + colors.getGreen()) > 255 * 2.95) {
+						data[x][y][0] = 2;
+					}
+				}
+			}
+			// 获取黑色数据
+			for (int y = 1; y < height - 1; y++) {
+				for (int x = 1; x < width - 1; x++) {
+					if (data[x][y][1] <= 0) {
+						Stack<Integer> q = new Stack<>();
+						q.add(x * 10000 + y);
+						pro(data, q, width, height);
+					}
+				}
+			}
+		}
+		return data;
+	}
+
+	private static void pro(int[][][] data, Stack<Integer> queue, int width, int height) {
+		while (queue.size() > 0) {
+			int a = queue.pop();
+			int x = a / 10000;
+			int y = a % 10000;
+
+			if (data[x][y][0] == 0 && data[x][y][1] <= 0) {
+				data[x][y][1] = 1;
+
+				if (queue.size() < 1000) {
+					if (x < width - 1 && data[x + 1][y][1] <= 0) {
+						int ad = (x + 1) * 10000 + y;
+						queue.add(ad);
+					}
+					if (y < height - 1 && data[x][y + 1][1] <= 0) {
+						int ad = (x) * 10000 + y + 1;
+						queue.add(ad);
+					}
+					if (x > 0 && data[x - 1][y][1] <= 0) {
+						int ad = (x - 1) * 10000 + y;
+						queue.add(ad);
+					}
+					if (y > 0 && data[x][y - 1][1] <= 0) {
+						int ad = (x) * 10000 + y - 1;
+						queue.add(ad);
+					}
+				}
+			}
+		}
+	}
+
+	public static void main(String[] args) throws IOException {
+		BufferedImage img = ImageIO.read(new File("E:\\test\\企业微信截图_20240118165835.png"));
+		int[][][] data = analysisPicture(img);
+		int width = data.length;
+		int height = data[0].length;
+//		for (int x = 1; x < width - 1; x++) {
+//			for (int y = 1; y < height - 1; y++) {
+//				String txt = "x:%s;y:%s;value=%s";
+//				System.out.println(String.format(txt, x, y, data[x - 1][y - 1][0]));
+//			}
+//		}
+		try {
+			BufferedImage testImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
+			for (int x = 1; x < width - 1; x++) {
+				for (int y = 1; y < height - 1; y++) {
+					testImage.setRGB(x, y, data[x - 1][y - 1][0] == 2 ? black.getRGB() : white.getRGB());
+				}
+			}
+			data = analysisPicture(img);
+			width = data.length;
+			height = data[0].length;
+			testImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
+			for (int x = 1; x < width - 1; x++) {
+				for (int y = 1; y < height - 1; y++) {
+					testImage.setRGB(x, y, data[x - 1][y - 1][0] == 2 ? black.getRGB() : white.getRGB());
+				}
+			}
+			ImageIO.write(testImage, "JPEG", new FileOutputStream("D:\\test1.png"));
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+	}
+}
+*/

+ 63 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/util/StreamUtil.java

@@ -0,0 +1,63 @@
+package com.fdkankan.dxf.generate.util;
+
+import java.io.*;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * @author YTZJJ
+ */
+public class StreamUtil {
+
+	/**
+	 * close all stream
+	 */
+	public static void closeStream(Closeable... cs) throws IOException {
+		if (cs == null) {
+			return;
+		}
+		for (Closeable c : cs) {
+			c.close();
+		}
+	}
+
+	public static BufferedReader getFileReader(String filePath) throws FileNotFoundException {
+		return getReader(new FileInputStream(filePath), StandardCharsets.UTF_8);
+	}
+
+	public static BufferedReader getFileReader(String filePath, Charset charset) throws FileNotFoundException {
+		return getReader(new FileInputStream(filePath), charset);
+	}
+
+	public static BufferedReader getReader(InputStream is, Charset charset) {
+		return new BufferedReader(new InputStreamReader(is, charset));
+	}
+
+	public static BufferedReader getReader(InputStream is) {
+		return getReader(is, StandardCharsets.UTF_8);
+	}
+
+	public static BufferedWriter getFileWriter(String filePath, Charset charset) throws FileNotFoundException {
+		return new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filePath), charset));
+	}
+
+	public static InputStream getResourceStream(String fileName) {
+		return StreamUtil.class.getClassLoader().getResourceAsStream(fileName);
+	}
+
+	/**
+	 * at dxf, every information tag is combine by code-data, so, we can read next part by read file two lines
+	 *
+	 * @param br BufferedReader
+	 * @return next tag info
+	 * @throws IOException if read file error,will throw this exception
+	 */
+	public static String[] readNextPair(BufferedReader br) throws IOException {
+		String code = br.readLine();
+		if (code == null) {
+			return null;
+		}
+		String codedata = br.readLine();
+		return new String[] { code, codedata };
+	}
+}

+ 49 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/util/StringUtil.java

@@ -0,0 +1,49 @@
+package com.fdkankan.dxf.generate.util;
+
+public class StringUtil {
+
+	/**
+	 * append line with line separators 'CRLF'
+	 *
+	 * @param buffer will append content buffer
+	 * @param lines  lines
+	 */
+	public static void appendLnCrLf(StringBuffer buffer, String... lines) {
+		buffer.append(appendLnCrLf(lines));
+	}
+
+	/**
+	 * append line with line separators 'CRLF'
+	 *
+	 * @param lines lines
+	 */
+	public static String appendLnCrLf(String... lines) {
+		StringBuilder result = new StringBuilder();
+		for (String str : lines) {
+			result.append(str).append("\r\n");
+		}
+		return result.toString();
+	}
+
+	/**
+	 * append chart to res start, until the result length equals strLength
+	 *
+	 * @param start     the chart you want append rec start
+	 * @param strLength output result length
+	 * @param res       res
+	 * @return append to strLength by start chart
+	 */
+	public static String appendStart(char start, int strLength, String res) {
+		if (res.length() >= strLength) {
+			return res;
+		}
+		int len = strLength - res.length();
+		StringBuilder buffer = new StringBuilder();
+		for (int i = 0; i < len; i++) {
+			buffer.append(start);
+		}
+		buffer.append(res);
+		return buffer.toString();
+	}
+
+}

+ 60 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/ParseDXF.java

@@ -0,0 +1,60 @@
+package com.fdkankan.dxf.parse;
+
+import com.fdkankan.dxf.parse.enums.error.DxfFileErrorEnum;
+import com.fdkankan.dxf.parse.exception.DxfFileException;
+import com.fdkankan.dxf.parse.resolver.DxfResolver;
+import com.fdkankan.dxf.parse.resolver.impl.DxfResolverImpl;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+
+/**
+ * @Author ytzjj
+ * @DateTime 2023/11/24 16:21
+ * @Description 解析DXF文件
+ */
+public class ParseDXF {
+
+
+    /**
+     * 上传文件、返回DXF数据采集者
+     *
+     * @return Dxf解析器
+     * @throws IOException io异常
+     */
+    public static DxfResolver build(InputStream inputStream) throws IOException {
+        return new DxfResolverImpl(inputStream);
+    }
+
+
+    /**
+     * 上传文件、返回DXF数据采集者
+     *
+     * @return Dxf解析器
+     * @throws IOException io异常
+     */
+    public static DxfResolver build(String filePath) throws IOException {
+        File file = new File(filePath);
+        if (!file.exists()) {
+            throw new DxfFileException(DxfFileErrorEnum.DXF_FILE_TYPE_ERROR);
+        }
+        return new DxfResolverImpl(Files.newInputStream(file.toPath()));
+    }
+
+
+
+    /**
+     * 上传文件、返回DXF数据采集者
+     *
+     * @return Dxf解析器
+     * @throws IOException io异常
+     */
+    public static DxfResolver build(File file) throws IOException {
+        if (!file.exists()) {
+            throw new DxfFileException(DxfFileErrorEnum.DXF_FILE_TYPE_ERROR);
+        }
+        return new DxfResolverImpl(Files.newInputStream(file.toPath()));
+    }
+}

+ 170 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/analysis/DxfAnalysis.java

@@ -0,0 +1,170 @@
+package com.fdkankan.dxf.parse.analysis;
+
+import com.fdkankan.dxf.parse.enums.CadVersionEnum;
+import com.fdkankan.dxf.parse.enums.DxfSystemEnum;
+import com.fdkankan.dxf.parse.enums.entities.*;
+import com.fdkankan.dxf.parse.model.GeometricModel;
+import com.fdkankan.dxf.parse.model.headers.HeaderModel;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * @AUTHOR ZhangJunJie
+ * @DATE 2023/11/25
+ * <p/>
+ * 概要:DXF 文件解析
+ */
+public class DxfAnalysis {
+
+
+    /**
+     * 读取所有的行
+     *
+     * @param reader BufferedReader
+     * @return 返回文件的所有数据,以每一行数据为一个item
+     * @throws IOException IO异常
+     */
+    private static List<String> readAllLine(BufferedReader reader) throws IOException {
+        List<String> list = new ArrayList<>();;
+        String line = null;
+        while ((line = reader.readLine()) != null) {
+            list.add(line.trim());
+        }
+        return list;
+    }
+
+    /**
+     * 解析dxf文件头信息,形成对象模型
+     *
+     * @param inputStream 文件流
+     * @param charset     字符编码 (UTF-8  GBK)
+     * @return
+     * @throws IOException
+     */
+    public static HeaderModel parseDxfHeaderModel(InputStream inputStream, String charset) throws IOException {
+        try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, charset))) {
+            List<String> dxfAllLine = readAllLine(reader);
+            return DxfHeaderParse.getHeaderParse(dxfAllLine);
+        }
+    }
+
+
+    /**
+     * 返回几何图像解析数据
+     *
+     * @param inputStream    dxf文件流
+     * @param dxfHeaderModel dxf解析出的头信息
+     * @return
+     * @throws IOException
+     */
+    public static Map<String, List<GeometricModel>> parseDxfGeometricList(InputStream inputStream, HeaderModel dxfHeaderModel) throws IOException {
+        /**
+         * 从cad版本信息中获取字符编码
+         */
+        CadVersionEnum cadVersionEnum = CadVersionEnum.getCadVersion(dxfHeaderModel.getCadVersion());
+        try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, cadVersionEnum.getCharset()))) {
+            Map<String, List<GeometricModel>> map = new HashMap<>();
+            //读取dxf所有的数据
+            List<String> lineList = readAllLine(reader);
+            // 解析dxf文件结构
+            parseFile(lineList, map, dxfHeaderModel);
+            return map;
+        }
+    }
+
+    /**
+     * 解析dxf文件结构
+     *
+     * @param lineList 总数据
+     * @param map      接收解析的数据map
+     */
+    private static void parseFile(List<String> lineList, Map<String, List<GeometricModel>> map, HeaderModel dxfHeaderModel) {
+        if (lineList == null || lineList.isEmpty()) {
+            return;
+        }
+        int i = 0;
+        String str = lineList.get(i);
+        //未到文件结束标志
+        while (!DxfSystemEnum.FILE_END.getCode().equals(str)) {
+            str = lineList.get(++i);
+            //实体段开始
+            if (DxfSystemEnum.ENTITIES_START.getCode().equals(str)) {
+                //解析实体
+                parseEntities(i, lineList, map, dxfHeaderModel);
+            }
+            // 文件循环语句结束
+        }
+        // 解析函数结束
+
+    }
+
+    /**
+     * 解析实体
+     *
+     * @param i              实体开始读取的行数
+     * @param lineList       总数据
+     * @param map            接收解析的数据map
+     * @param dxfHeaderModel dxf文件的头信息模型
+     */
+    private static void parseEntities(int i, List<String> lineList, Map<String, List<GeometricModel>> map, HeaderModel dxfHeaderModel) {
+        String str = null;
+        while (true) {
+            str = lineList.get(++i);
+
+            //点开始
+            if (PointEnum.POINT_NAME.getCode().equals(str)) {
+                i = DxfEntitiesParse.getPoint(i, lineList, map);
+            }
+            //圆开始
+            if (CircleEnum.CIRCLE_NAME.getCode().equals(str)) {
+                i = DxfEntitiesParse.getCircle(i, lineList, map);
+            }
+            // 椭圆开始
+            if (EllipseEnum.ELLIPSE_NAME.getCode().equals(str)) {
+                // TODO 解析椭圆
+            }
+            // 圆弧开始
+            if (ArcEnum.ARC_NAME.getCode().equals(str)) {
+                i = DxfEntitiesParse.getArc(i, lineList, map);
+            }
+            //直线开始
+            if (LineEnum.LINE_NAME.getCode().equals(str)) {
+                i = DxfEntitiesParse.getLine(i, lineList, map);
+            }
+            //多线段
+            if (PolyLineEnum.LWPOLYLINE_NAME.getCode().equals(str)) {
+                i = DxfEntitiesParse.getLWPolyLine(i, lineList, map);
+            }
+            // 多线段
+            if (PolyLineEnum.POLYLINE_NAME.getCode().equals(str)) {
+                i = DxfEntitiesParse.getPolyLine(i, lineList, map);
+            }
+            // 文本
+            if (TextEnum.TEXT_NAME.getCode().equals(str)) {
+                i = DxfEntitiesParse.getText(i, lineList, map);
+            }
+            // 多文本
+            if (MTextEnum.MTEXT_NAME.getCode().equals(str)) {
+                i = DxfEntitiesParse.getMText(i, lineList, map);
+            }
+            // 插入图元
+            if (InsertEnum.INSERT_NAME.getCode().equals(str)) {
+                i = DxfEntitiesParse.getInsert(i, lineList, map);
+            }
+            //实体结束
+            if (DxfSystemEnum.END_SEC.getCode().equals(str)) {
+                break;
+            }
+        }
+    }
+
+
+}

+ 796 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/analysis/DxfEntitiesParse.java

@@ -0,0 +1,796 @@
+package com.fdkankan.dxf.parse.analysis;
+
+import com.fdkankan.dxf.generate.util.DxfUtil;
+import com.fdkankan.dxf.parse.constant.EntityNameConstant;
+import com.fdkankan.dxf.parse.constant.PolyLineConstant;
+import com.fdkankan.dxf.parse.enums.DxfEntitiesBaseEnum;
+import com.fdkankan.dxf.parse.enums.entities.*;
+import com.fdkankan.dxf.parse.enums.error.DxfAnalysisErrorEnum;
+import com.fdkankan.dxf.parse.exception.DxfAnalysisException;
+import com.fdkankan.dxf.parse.model.GeometricModel;
+import com.fdkankan.dxf.parse.model.entities.*;
+import com.fdkankan.dxf.parse.utils.DecimalCheckUtil;
+import com.fdkankan.dxf.parse.utils.MTextStyleParse;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @Author ytzjj
+ * @DateTime 2023/11/27 11:00
+ * @Description dxf 解析entities 节点
+ */
+public class DxfEntitiesParse {
+
+    public static final Integer DECIMAL_SIZE = 10;
+
+    /**
+     * 获取图元
+     *
+     * @param i        多线段开始读取的行数
+     * @param lineList 总数据
+     * @param map      接收解析的数据map
+     * @return 返回多线段读完最后行数
+     */
+    public static int getInsert(int i, List<String> lineList, Map<String, List<GeometricModel>> map) {
+        String str;
+        GeometricPoint point = new GeometricPoint();
+        while (true) {
+            str = lineList.get(++i);
+
+            i = getGeometricBase(i, lineList, str, point);
+
+            if (InsertEnum.LAYER_NAME.getCode().equals(str)) {
+                str = lineList.get(++i);
+                point.setLayerName(str);
+            }
+            if (InsertEnum.COORDINATE_X.getCode().equals(str)) {
+                str = lineList.get(++i);
+                if (!DecimalCheckUtil.check(str.trim())) {
+                    throw new DxfAnalysisException(DxfAnalysisErrorEnum.POINT_NOT_X);
+                }
+                point.setX(new BigDecimal(str.trim()).setScale(DECIMAL_SIZE, RoundingMode.HALF_UP));
+            }
+            if (InsertEnum.COORDINATE_Y.getCode().equals(str)) {
+                str = lineList.get(++i);
+                if (!DecimalCheckUtil.check(str.trim())) {
+                    throw new DxfAnalysisException(DxfAnalysisErrorEnum.POINT_NOT_Y);
+                }
+                point.setY(new BigDecimal(str.trim()).setScale(DECIMAL_SIZE, RoundingMode.HALF_UP));
+            }
+            if (InsertEnum.COORDINATE_Z.getCode().equals(str)) {
+                str = lineList.get(++i);
+                if (!DecimalCheckUtil.check(str.trim())) {
+                    throw new DxfAnalysisException(DxfAnalysisErrorEnum.POINT_NOT_Z);
+                }
+                point.setZ(new BigDecimal(str.trim()).setScale(DECIMAL_SIZE, RoundingMode.HALF_UP));
+            }
+            if (str.equals("0") && "5".equals(lineList.get(i + 2))) {
+                // 实体结束
+                break;
+            }
+        }
+        List<GeometricModel> pointList = map.get(EntityNameConstant.POINT_NAME);
+        if (pointList == null) {
+            pointList = new ArrayList<>();
+            ;
+        }
+        pointList.add(point);
+        map.put(EntityNameConstant.POINT_NAME, pointList);
+        return i;
+    }
+
+
+    /**
+     * 获取多文本
+     *
+     * @param i        多线段开始读取的行数
+     * @param lineList 总数据
+     * @param map      接收解析的数据map
+     * @return 返回多线段读完最后行数
+     */
+    public static int getMText(int i, List<String> lineList, Map<String, List<GeometricModel>> map) {
+        String str = null;
+        GeometricText point = new GeometricText();
+        while (true) {
+            str = lineList.get(++i);
+
+            i = getGeometricBase(i, lineList, str, point);
+
+            if (MTextEnum.LAYER_NAME.getCode().equals(str)) {
+                str = lineList.get(++i);
+                point.setLayerName(str);
+            } else if (MTextEnum.COORDINATE_X.getCode().equals(str)) {
+                str = lineList.get(++i);
+                if (!DecimalCheckUtil.check(str.trim())) {
+                    throw new DxfAnalysisException(DxfAnalysisErrorEnum.POINT_NOT_X);
+                }
+                point.setX(new BigDecimal(str.trim()).setScale(DECIMAL_SIZE, RoundingMode.HALF_UP));
+            } else if (MTextEnum.COORDINATE_Y.getCode().equals(str)) {
+                str = lineList.get(++i);
+                if (!DecimalCheckUtil.check(str.trim())) {
+                    throw new DxfAnalysisException(DxfAnalysisErrorEnum.POINT_NOT_Y);
+                }
+                point.setY(new BigDecimal(str.trim()).setScale(DECIMAL_SIZE, RoundingMode.HALF_UP));
+            } else if (MTextEnum.COORDINATE_Z.getCode().equals(str)) {
+                str = lineList.get(++i);
+                if (!DecimalCheckUtil.check(str.trim())) {
+                    throw new DxfAnalysisException(DxfAnalysisErrorEnum.POINT_NOT_Z);
+                }
+                point.setZ(new BigDecimal(str.trim()).setScale(DECIMAL_SIZE, RoundingMode.HALF_UP));
+            } else if (MTextEnum.MTEXT_CONTENT.getCode().equals(str)) {
+                str = lineList.get(++i);
+                String rule = "[{]\\\\fSimSun([|][a-z\\d]+){4};";
+                String end = "(?<!\\\\)}";
+                String changeLine = "\\P";
+                str = str.replaceAll(rule, "");
+                str = str.replaceAll(end, "");
+                str = str.replace(changeLine, "\n");
+                str = str.replace("\\}", "}");
+                str = str.replace("\\{", "{");
+                str = str.replace("\\\\f", "\\f");
+                point.setText(str);
+            } else if (MTextEnum.HEIGH.getCode().equals(str)) {
+                str = lineList.get(++i);
+                point.setHigh(Double.parseDouble(str));
+            } else if (MTextEnum.WIDTH.getCode().equals(str)) {
+                str = lineList.get(++i);
+                point.setWidth(Double.parseDouble(str));
+            } else if (MTextEnum.ANGLE.getCode().equals(str)) {
+                str = lineList.get(++i);
+                point.setAngle(new BigDecimal(str));
+            } else if (MTextEnum.INCLINATION.getCode().equals(str)) {
+                str = lineList.get(++i);
+                point.setInclination(new BigDecimal(str));
+            } else if (str.equals("0") && "5".equals(lineList.get(i + 2))) {
+                // 实体结束
+                break;
+            } else {
+                i++;
+            }
+        }
+        List<GeometricModel> testList = map.get(EntityNameConstant.TEXT_NAME);
+        if (testList == null) {
+            testList = new ArrayList<>();
+            ;
+        }
+        testList.add(point);
+        map.put(EntityNameConstant.TEXT_NAME, testList);
+        return i;
+    }
+
+    /**
+     * 获取单行文本
+     *
+     * @param i        多线段开始读取的行数
+     * @param lineList 总数据
+     * @param map      接收解析的数据map
+     * @return 返回多线段读完最后行数
+     */
+    public static int getText(int i, List<String> lineList, Map<String, List<GeometricModel>> map) {
+        String str = null;
+        GeometricText point = new GeometricText();
+        while (true) {
+            str = lineList.get(++i);
+
+            i = getGeometricBase(i, lineList, str, point);
+
+            if (TextEnum.LAYER_NAME.getCode().equals(str)) {
+                str = lineList.get(++i);
+                point.setLayerName(str);
+            }
+            if (TextEnum.COORDINATE_X.getCode().equals(str)) {
+                str = lineList.get(++i);
+                if (!DecimalCheckUtil.check(str.trim())) {
+                    throw new DxfAnalysisException(DxfAnalysisErrorEnum.POINT_NOT_X);
+                }
+                point.setX(new BigDecimal(str.trim()).setScale(DECIMAL_SIZE, RoundingMode.HALF_UP));
+            }
+            if (TextEnum.COORDINATE_Y.getCode().equals(str)) {
+                str = lineList.get(++i);
+                if (!DecimalCheckUtil.check(str.trim())) {
+                    throw new DxfAnalysisException(DxfAnalysisErrorEnum.POINT_NOT_Y);
+                }
+                point.setY(new BigDecimal(str.trim()).setScale(DECIMAL_SIZE, RoundingMode.HALF_UP));
+            }
+            if (TextEnum.COORDINATE_Z.getCode().equals(str)) {
+                str = lineList.get(++i);
+                if (!DecimalCheckUtil.check(str.trim())) {
+                    throw new DxfAnalysisException(DxfAnalysisErrorEnum.POINT_NOT_Z);
+                }
+                point.setZ(new BigDecimal(str.trim()).setScale(DECIMAL_SIZE, RoundingMode.HALF_UP));
+            }
+            if (TextEnum.TEXT_CONTENT.getCode().equals(str)) {
+                str = lineList.get(++i);
+                point.setText(str);
+            }
+
+            if (TextEnum.HEIGH.getCode().equals(str)) {
+                str = lineList.get(++i);
+                point.setHigh(Double.parseDouble(str));
+            }
+            if (TextEnum.WIDTH.getCode().equals(str)) {
+                str = lineList.get(++i);
+                point.setWidth(Double.parseDouble(str));
+            }
+            if (TextEnum.ANGLE.getCode().equals(str)) {
+                str = lineList.get(++i);
+                point.setAngle(new BigDecimal(str));
+            }
+            if (TextEnum.INCLINATION.getCode().equals(str)) {
+                str = lineList.get(++i);
+                point.setInclination(new BigDecimal(str));
+            }
+
+            if (str.equals("0") && "5".equals(lineList.get(i + 2))) {
+                // 实体结束
+                break;
+            }
+        }
+        List<GeometricModel> testList = map.get(EntityNameConstant.TEXT_NAME);
+        if (testList == null) {
+            testList = new ArrayList<>();
+            ;
+        }
+        testList.add(point);
+        map.put(EntityNameConstant.TEXT_NAME, testList);
+        return i;
+    }
+
+    /**
+     * 获取多线段
+     *
+     * @param i        多线段开始读取的行数
+     * @param lineList 总数据
+     * @param map      接收解析的数据map
+     * @return 返回多线段读完最后行数
+     */
+    public static int getLWPolyLine(int i, List<String> lineList, Map<String, List<GeometricModel>> map) {
+        String str = null;
+        GeometricPolyLine polyLine = new GeometricPolyLine();
+        polyLine.setLogicClose(false);
+        List<GeometricVertex> vertices = new ArrayList<>();
+        int vertexNum = 0;
+        while (true) {
+            str = lineList.get(++i);
+            // 多段线闭合
+            if (PolyLineEnum.CLOSE.getCode().equals(str)) {
+                str = lineList.get(++i);
+                // 多段线的标志,表明这是一个闭合的多段线
+                if (str.equals(PolyLineConstant.POLYLINE_LOGIC_CLOSE)) {
+                    polyLine.setLogicClose(true);
+                } else if (str.equals(PolyLineConstant.POLYLINE_LOGIC_CLOSE_1)) {
+                    polyLine.setLogicClose(true);
+                }
+            }
+            // 图层名称
+            if (PolyLineEnum.LAYER_NAME.getCode().equals(str)) {
+                str = lineList.get(++i);
+                polyLine.setLayerName(str);
+            }
+            // 获取矢量图形的基本信息
+            i = getGeometricBase(i, lineList, str, polyLine);
+
+            // 线条类型
+            if (PolyLineEnum.LINE_TYPE.getCode().equals(str)) {
+                str = lineList.get(++i);
+                polyLine.setLineType(str);
+            }
+            // 填充色
+            if (PolyLineEnum.FILL_COLOR.getCode().equals(str)) {
+                str = lineList.get(++i);
+                polyLine.setFillColor(MTextStyleParse.parseCadColorToHexColorCode(str));
+            }
+            // 顶点数量
+            if (PolyLineEnum.VERTEX_NUM.getCode().equals(str)) {
+                str = lineList.get(++i);
+                vertexNum = Integer.parseInt(str.trim());
+                polyLine.setVertexNum(vertexNum);
+            } else if (PolyLineEnum.COORDINATE_X.getCode().equals(str)) {
+                for (int j = 0; j < vertexNum; j++) {
+                    GeometricVertex vertex = new GeometricVertex();
+                    //顶点的x坐标
+                    if (PolyLineEnum.COORDINATE_X.getCode().equals(str)) {
+                        str = lineList.get(++i);
+                        if (DecimalCheckUtil.check(str.trim())) {
+                            vertex.setX(new BigDecimal(str.trim()).setScale(DECIMAL_SIZE, RoundingMode.HALF_UP));
+                            str = lineList.get(++i);
+                        } else {
+                            break;
+                        }
+                    }
+                    //顶点的y坐标
+                    if (PolyLineEnum.COORDINATE_Y.getCode().equals(str)) {
+                        str = lineList.get(++i);
+                        vertex.setY(new BigDecimal(str.trim()));
+                        if (DecimalCheckUtil.check(str.trim())) {
+                            vertex.setY(new BigDecimal(str.trim()).setScale(DECIMAL_SIZE, RoundingMode.HALF_UP));
+                            str = lineList.get(++i);
+                        }
+                        vertices.add(vertex);
+                    }
+                    //起点宽度
+                    if (PolyLineEnum.START_WIDTH.getCode().equals(str)) {
+                        i += 2;
+                        str = lineList.get(i);
+                    }
+                    //端点宽度
+                    if (PolyLineEnum.END_WIDTH.getCode().equals(str)) {
+                        i += 2;
+                        str = lineList.get(i);
+                    }
+                    //凸度
+                    if (PolyLineEnum.OUT_DO.getCode().equals(str)) {
+                        i += 2;
+                        str = lineList.get(i);
+                    }
+                    // 最后一个点位 重置 flag 字段为 -1
+                    if (j == vertexNum - 1) {
+                        vertexNum = -1;
+                    }
+                }
+            }
+            // 顶点结束
+            if (vertexNum < 0) {
+                break;
+            }
+        }
+        polyLine.setVertexList(vertices);
+        List<GeometricModel> polyLines = map.get(EntityNameConstant.POLY_LINE_NAME);
+        if (polyLines == null) {
+            polyLines = new ArrayList<>();
+            ;
+            map.put(EntityNameConstant.POLY_LINE_NAME, polyLines);
+        }
+        polyLines.add(polyLine);
+        return i;
+
+    }
+
+
+    /**
+     * 解析多段线
+     *
+     * @param i        多线段开始读取的行数
+     * @param lineList 总数据
+     * @param map      接收解析的数据map
+     * @return: 返回多线段读完最后行数
+     **/
+    public static int getPolyLine(int i, List<String> lineList, Map<String, List<GeometricModel>> map) {
+        String str = null;
+        GeometricPolyLine polyLine = new GeometricPolyLine();
+        polyLine.setLogicClose(false);
+        List<GeometricVertex> vertices = new ArrayList<>();
+        while (true) {
+            str = lineList.get(++i);
+            // 逻辑闭合
+            if (PolyLineEnum.CLOSE.getCode().equals(str)) {
+                str = lineList.get(++i);
+                if (str.equals(PolyLineConstant.POLYLINE_LOGIC_CLOSE)) {
+                    polyLine.setLogicClose(true);
+                } else if (str.equals(PolyLineConstant.POLYLINE_LOGIC_CLOSE_1)) {
+                    polyLine.setLogicClose(true);
+                }
+            }
+            // 图层名称
+            if (PolyLineEnum.LAYER_NAME.getCode().equals(str)) {
+                str = lineList.get(++i);
+                polyLine.setLayerName(str);
+            }
+            // 获取矢量图形的基本信息
+            i = getGeometricBase(i, lineList, str, polyLine);
+
+            // 线条类型
+            if (PolyLineEnum.LINE_TYPE.getCode().equals(str)) {
+                str = lineList.get(++i);
+                polyLine.setLineType(str);
+            }
+            // 填充色
+            if (PolyLineEnum.FILL_COLOR.getCode().equals(str)) {
+                str = lineList.get(++i);
+                polyLine.setFillColor(MTextStyleParse.parseCadColorToHexColorCode(str));
+            }
+
+            if (PolyLineEnum.BLOCK.getCode().equals(str)) {
+                str = lineList.get(++i);
+                if (PolyLineEnum.VERTEX_NAME.getCode().equals(str)) {
+                    GeometricVertex vertex = new GeometricVertex();
+                    //顶点的x坐标
+                    while (!PolyLineEnum.COORDINATE_X.getCode().equals(str)) {
+                        str = lineList.get(++i);
+                    }
+                    if (PolyLineEnum.COORDINATE_X.getCode().equals(str)) {
+                        str = lineList.get(++i);
+                        if (DecimalCheckUtil.check(str.trim())) {
+                            vertex.setX(new BigDecimal(str.trim()).setScale(DECIMAL_SIZE, RoundingMode.HALF_UP));
+                            str = lineList.get(++i);
+                        } else {
+                            break;
+                        }
+                    }
+                    //顶点的y坐标
+                    if (PolyLineEnum.COORDINATE_Y.getCode().equals(str)) {
+                        str = lineList.get(++i);
+                        if (DecimalCheckUtil.check(str.trim())) {
+                            vertex.setY(new BigDecimal(str.trim()).setScale(DECIMAL_SIZE, RoundingMode.HALF_UP));
+                            str = lineList.get(++i);
+                        }
+                        vertices.add(vertex);
+                    }
+
+                    //顶点的z坐标
+                    if (PolyLineEnum.COORDINATE_Z.getCode().equals(str)) {
+                        str = lineList.get(++i);
+                        if (DecimalCheckUtil.check(str.trim())) {
+                            vertex.setZ(new BigDecimal(str.trim()).setScale(DECIMAL_SIZE, RoundingMode.HALF_UP));
+                            str = lineList.get(++i);
+                        }
+                        vertices.add(vertex);
+                    }
+                } else if (PolyLineEnum.SEQEND.getCode().equals(str)) {
+                    break;
+                }
+            }
+        }
+        polyLine.setVertexList(vertices);
+        List<GeometricModel> polyLines = map.computeIfAbsent(EntityNameConstant.POLY_LINE_NAME, k -> new ArrayList<>());
+        polyLines.add(polyLine);
+        return i;
+    }
+
+    /**
+     * 获取线
+     *
+     * @param i        线开始读取的行数
+     * @param lineList 总数据
+     * @param map      接收解析的数据map
+     * @return 返回直线读完的最后行数
+     */
+    public static int getLine(int i, List<String> lineList, Map<String, List<GeometricModel>> map) {
+        String str = null;
+        GeometricLine line = new GeometricLine();
+        while (true) {
+            str = lineList.get(++i);
+
+            i = getGeometricBase(i, lineList, str, line);
+
+            //图层名称
+            if (LineEnum.LAYER_NAME.getCode().equals(str)) {
+                str = lineList.get(++i);
+                line.setLayerName(str);
+            }
+            //起点x坐标
+            if (LineEnum.COORDINATE_X.getCode().equals(str)) {
+                str = lineList.get(++i);
+                if (!DecimalCheckUtil.check(str.trim())) {
+                    throw new DxfAnalysisException(DxfAnalysisErrorEnum.LINE_START_NOT_X);
+                }
+                line.setStartX(new BigDecimal(str.trim()).setScale(DECIMAL_SIZE, RoundingMode.HALF_UP));
+            }
+            //起点y的坐标
+            if (LineEnum.COORDINATE_Y.getCode().equals(str)) {
+                str = lineList.get(++i);
+                if (!DecimalCheckUtil.check(str.trim())) {
+                    throw new DxfAnalysisException(DxfAnalysisErrorEnum.LINE_START_NOT_Y);
+                }
+                line.setStartY(new BigDecimal(str.trim()).setScale(DECIMAL_SIZE, RoundingMode.HALF_UP));
+            }
+            //起点z的坐标
+            if (LineEnum.COORDINATE_Z.getCode().equals(str)) {
+                str = lineList.get(++i);
+                if (!DecimalCheckUtil.check(str.trim())) {
+                    throw new DxfAnalysisException(DxfAnalysisErrorEnum.LINE_START_NOT_Z);
+                }
+                line.setStartZ(new BigDecimal(str.trim()).setScale(DECIMAL_SIZE, RoundingMode.HALF_UP));
+            }
+            //终点的x坐标
+            if (LineEnum.LINE_END_X_COORDINATES.getCode().equals(str)) {
+                str = lineList.get(++i);
+                if (!DecimalCheckUtil.check(str.trim())) {
+                    throw new DxfAnalysisException(DxfAnalysisErrorEnum.LINE_END_NOT_X);
+                }
+                line.setEndX(new BigDecimal(str.trim()).setScale(DECIMAL_SIZE, RoundingMode.HALF_UP));
+            }
+            //终点的y坐标
+            if (LineEnum.LINE_END_Y_COORDINATES.getCode().equals(str)) {
+                str = lineList.get(++i);
+                if (!DecimalCheckUtil.check(str.trim())) {
+                    throw new DxfAnalysisException(DxfAnalysisErrorEnum.LINE_END_NOT_Y);
+                }
+                line.setEndY(new BigDecimal(str.trim()).setScale(DECIMAL_SIZE, RoundingMode.HALF_UP));
+            }
+            //终点的z坐标
+            if (LineEnum.LINE_END_Z_COORDINATES.getCode().equals(str)) {
+                str = lineList.get(++i);
+                if (!DecimalCheckUtil.check(str.trim())) {
+                    throw new DxfAnalysisException(DxfAnalysisErrorEnum.LINE_END_NOT_Z);
+                }
+                line.setEndZ(new BigDecimal(str.trim()).setScale(DECIMAL_SIZE, RoundingMode.HALF_UP));
+            }
+
+            if (ArcEnum.COLOR.getCode().equals(str)) {
+                str = lineList.get(++i);
+                line.setColor(MTextStyleParse.parseCadColorToHexColorCode(str));
+            }
+
+            if (str.equals("0") && "5".equals(lineList.get(i + 2))) {
+                // 实体结束
+                break;
+            }
+        }
+        List<GeometricModel> linesList = map.get(EntityNameConstant.LINE_NAME);
+        if (linesList == null) {
+            linesList = new ArrayList<>();
+            ;
+        }
+        linesList.add(line);
+        map.put(EntityNameConstant.LINE_NAME, linesList);
+        return i;
+    }
+
+
+    /**
+     * 获取圆
+     *
+     * @param i        圆开始读取的行数
+     * @param lineList 总数据
+     * @param map      接收解析的数据map
+     * @return 返回圆读完的最后行数
+     */
+    public static int getCircle(int i, List<String> lineList, Map<String, List<GeometricModel>> map) {
+        String str = null;
+        GeometricCircle circle = new GeometricCircle();
+        while (true) {
+            str = lineList.get(++i);
+
+            i = getGeometricBase(i, lineList, str, circle);
+
+            //图层名
+            if (CircleEnum.LAYER_NAME.getCode().equals(str)) {
+                str = lineList.get(++i);
+                circle.setLayerName(str);
+            }
+            //圆心的x坐标
+            if (CircleEnum.COORDINATE_X.getCode().equals(str)) {
+                str = lineList.get(++i);
+                if (!DecimalCheckUtil.check(str.trim())) {
+                    throw new DxfAnalysisException(DxfAnalysisErrorEnum.CIRCLE_NOT_X);
+                }
+                circle.setX(new BigDecimal(str.trim()).setScale(DECIMAL_SIZE, RoundingMode.HALF_UP));
+            }
+            //圆心的y坐标
+            if (CircleEnum.COORDINATE_Y.getCode().equals(str)) {
+                str = lineList.get(++i);
+                if (!DecimalCheckUtil.check(str.trim())) {
+                    throw new DxfAnalysisException(DxfAnalysisErrorEnum.CIRCLE_NOT_Y);
+                }
+                circle.setY(new BigDecimal(str.trim()).setScale(DECIMAL_SIZE, RoundingMode.HALF_UP));
+            }
+            //圆心的z坐标
+            if (CircleEnum.COORDINATE_Z.getCode().equals(str)) {
+                str = lineList.get(++i);
+                if (!DecimalCheckUtil.check(str.trim())) {
+                    throw new DxfAnalysisException(DxfAnalysisErrorEnum.CIRCLE_NOT_Z);
+                }
+                circle.setZ(new BigDecimal(str.trim()).setScale(DECIMAL_SIZE, RoundingMode.HALF_UP));
+            }
+            //解析圆的半径
+            if (CircleEnum.CIRCULAR_RADIUS.getCode().equals(str)) {
+                str = lineList.get(++i);
+                if (!DecimalCheckUtil.check(str.trim())) {
+                    throw new DxfAnalysisException(DxfAnalysisErrorEnum.CIRCLE_NOT_RADIUS);
+                }
+                circle.setRadius(new BigDecimal(str.trim()).setScale(DECIMAL_SIZE, RoundingMode.HALF_UP));
+            }
+            if (CircleEnum.COLOR.getCode().equals(str)) {
+                str = lineList.get(++i);
+                circle.setColor(MTextStyleParse.parseCadColorToHexColorCode(str));
+            }
+            if (str.equals("0") && "5".equals(lineList.get(i + 2))) {
+                // 实体结束
+                break;
+            }
+        }
+        List<GeometricModel> circleList = map.get(EntityNameConstant.CIRCLE_NAME);
+        if (circleList == null) {
+            circleList = new ArrayList<>();
+            ;
+        }
+        circleList.add(circle);
+        map.put(EntityNameConstant.CIRCLE_NAME, circleList);
+        return i;
+    }
+
+
+    /**
+     * 解析点
+     *
+     * @param i        点开始读取的行数
+     * @param lineList 总数据
+     * @param map      接收解析的数据map
+     * @return 返回点读完的最后行数
+     */
+    public static int getPoint(int i, List<String> lineList, Map<String, List<GeometricModel>> map) {
+        String str = null;
+        GeometricPoint point = new GeometricPoint();
+
+        while (true) {
+            str = lineList.get(++i);
+
+            i = getGeometricBase(i, lineList, str, point);
+
+            if (PointEnum.LAYER_NAME.getCode().equals(str)) {
+                str = lineList.get(++i);
+                point.setLayerName(str);
+            }
+            if (PointEnum.COORDINATE_X.getCode().equals(str)) {
+                str = lineList.get(++i);
+                if (!DecimalCheckUtil.check(str.trim())) {
+                    throw new DxfAnalysisException(DxfAnalysisErrorEnum.POINT_NOT_X);
+                }
+                point.setX(new BigDecimal(str.trim()).setScale(DECIMAL_SIZE, RoundingMode.HALF_UP));
+            }
+            if (PointEnum.COORDINATE_Y.getCode().equals(str)) {
+                str = lineList.get(++i);
+                if (!DecimalCheckUtil.check(str.trim())) {
+                    throw new DxfAnalysisException(DxfAnalysisErrorEnum.POINT_NOT_Y);
+                }
+                point.setY(new BigDecimal(str.trim()).setScale(DECIMAL_SIZE, RoundingMode.HALF_UP));
+            }
+            if (PointEnum.COORDINATE_Z.getCode().equals(str)) {
+                str = lineList.get(++i);
+                if (!DecimalCheckUtil.check(str.trim())) {
+                    throw new DxfAnalysisException(DxfAnalysisErrorEnum.POINT_NOT_Z);
+                }
+                point.setZ(new BigDecimal(str.trim()).setScale(DECIMAL_SIZE, RoundingMode.HALF_UP));
+            }
+            if (PointEnum.COLOR.getCode().equals(str)) {
+                str = lineList.get(++i);
+                point.setColor(MTextStyleParse.parseCadColorToHexColorCode(str));
+            }
+
+            if (str.equals("0") && "5".equals(lineList.get(i + 2))) {
+                // 实体结束
+                break;
+            }
+        }
+        List<GeometricModel> pointList = map.get(EntityNameConstant.POINT_NAME);
+        if (pointList == null) {
+            pointList = new ArrayList<>();
+            ;
+        }
+        pointList.add(point);
+        map.put(EntityNameConstant.POINT_NAME, pointList);
+        return i;
+    }
+
+
+    /**
+     * 获取弧线
+     *
+     * @param i        弧线开始读取的行数
+     * @param lineList 总数据
+     * @param map      接收解析的数据map
+     * @return 返回弧线读完的最后行数
+     */
+    public static int getArc(int i, List<String> lineList, Map<String, List<GeometricModel>> map) {
+        String str = null;
+        GeometricArc arc = new GeometricArc();
+        while (true) {
+            str = lineList.get(++i);
+
+            i = getGeometricBase(i, lineList, str, arc);
+
+            //图层名
+            if (ArcEnum.LAYER_NAME.getCode().equals(str)) {
+                str = lineList.get(++i);
+                arc.setLayerName(str);
+            }
+            //圆弧圆心x坐标
+            if (ArcEnum.COORDINATE_X.getCode().equals(str)) {
+                str = lineList.get(++i);
+                if (!DecimalCheckUtil.check(str.trim())) {
+                    throw new DxfAnalysisException(DxfAnalysisErrorEnum.ARC_NOT_X);
+                }
+                arc.setX(new BigDecimal(str.trim()).setScale(DECIMAL_SIZE, RoundingMode.HALF_UP));
+            }
+            //圆弧圆心y坐标
+            if (ArcEnum.COORDINATE_Y.getCode().equals(str)) {
+                str = lineList.get(++i);
+                if (!DecimalCheckUtil.check(str.trim())) {
+                    throw new DxfAnalysisException(DxfAnalysisErrorEnum.ARC_NOT_Y);
+                }
+                arc.setY(new BigDecimal(str.trim()).setScale(DECIMAL_SIZE, RoundingMode.HALF_UP));
+            }
+            //圆弧圆心z坐标
+            if (ArcEnum.COORDINATE_Z.getCode().equals(str)) {
+                str = lineList.get(++i);
+                if (!DecimalCheckUtil.check(str.trim())) {
+                    throw new DxfAnalysisException(DxfAnalysisErrorEnum.ARC_NOT_Z);
+                }
+                arc.setZ(new BigDecimal(str.trim()).setScale(DECIMAL_SIZE, RoundingMode.HALF_UP));
+            }
+            //圆弧半径
+            if (ArcEnum.ARC_RADIUS.getCode().equals(str)) {
+                str = lineList.get(++i);
+                if (!DecimalCheckUtil.check(str.trim())) {
+                    throw new DxfAnalysisException(DxfAnalysisErrorEnum.ARC_NOT_RADIUS);
+                }
+                arc.setRadius(new BigDecimal(str.trim()).setScale(DECIMAL_SIZE, RoundingMode.HALF_UP));
+            }
+            //圆弧起始角度
+            if (ArcEnum.ARC_START_ANGLE.getCode().equals(str)) {
+                str = lineList.get(++i);
+                if (!DecimalCheckUtil.check(str.trim())) {
+                    throw new DxfAnalysisException(DxfAnalysisErrorEnum.ARC_NOT_START_ANGLE);
+                }
+                arc.setStartArc(new BigDecimal(str.trim()).setScale(DECIMAL_SIZE, RoundingMode.HALF_UP));
+            }
+            //圆弧中止角度
+            if (ArcEnum.ARC_END_ANGLE.getCode().equals(str)) {
+                str = lineList.get(++i);
+                if (!DecimalCheckUtil.check(str.trim())) {
+                    throw new DxfAnalysisException(DxfAnalysisErrorEnum.ARC_NOT_END_ANGLE);
+                }
+                arc.setEndArc(new BigDecimal(str.trim()).setScale(DECIMAL_SIZE, RoundingMode.HALF_UP));
+            }
+
+            if (ArcEnum.COLOR.getCode().equals(str)) {
+                str = lineList.get(++i);
+                arc.setColor(MTextStyleParse.parseCadColorToHexColorCode(str));
+            }
+
+            if (str.equals("0") && "5".equals(lineList.get(i + 2))) {
+                // 实体结束
+                break;
+            }
+        }
+        List<GeometricModel> arcList = map.get(EntityNameConstant.ARC_NAME);
+        if (arcList == null) {
+            arcList = new ArrayList<>();
+            ;
+        }
+        arcList.add(arc);
+        map.put(EntityNameConstant.ARC_NAME, arcList);
+        return i;
+    }
+
+
+    /**
+     * 获取矢量图形的基本信息
+     *
+     * @param i
+     * @param lineList
+     * @param str
+     * @param geomertic
+     * @return
+     */
+    public static int getGeometricBase(int i, List<String> lineList, String str, GeometricModel geomertic) {
+        if (DxfEntitiesBaseEnum.COLOR_16.getCode().equals(str)) {
+            str = lineList.get(++i);
+            geomertic.setColor(DxfUtil.convertToHtmlColor(Integer.parseInt(str)));
+        }
+
+        if (DxfEntitiesBaseEnum.COLOR_CODE.getCode().equals(str)) {
+            str = lineList.get(++i);
+            geomertic.setColor(MTextStyleParse.parseCadColorToHexColorCode(str));
+        }
+
+        if (DxfEntitiesBaseEnum.ALPHA.getCode().equals(str)) {
+            str = lineList.get(++i);
+            geomertic.setAlpha(Integer.parseInt(str));
+        }
+        if (DxfEntitiesBaseEnum.LINE_WIDTH.getCode().equals(str)) {
+            str = lineList.get(++i);
+            geomertic.setLineWidth(Double.parseDouble(str));
+        }
+        if (DxfEntitiesBaseEnum.HEIGHT.getCode().equals(str)) {
+            str = lineList.get(++i);
+            geomertic.setHeight(Double.parseDouble(str));
+        }
+        return i;
+    }
+}

+ 114 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/analysis/DxfHeaderParse.java

@@ -0,0 +1,114 @@
+package com.fdkankan.dxf.parse.analysis;
+
+import com.fdkankan.dxf.parse.enums.CadVersionEnum;
+import com.fdkankan.dxf.parse.enums.DxfSystemEnum;
+import com.fdkankan.dxf.parse.model.headers.HeaderModel;
+import com.fdkankan.dxf.parse.utils.DateUtils;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * @Author ytzjj
+ * @DateTime 2023/11/27 15:22
+ * @Description dxf 的头信息解析
+ */
+public class DxfHeaderParse {
+
+
+    /**
+     * 从dxf文件中解析需要的头信息,并封装模型
+     *
+     * @param dxfAllLine
+     * @return
+     */
+    public static HeaderModel getHeaderParse(List<String> dxfAllLine) {
+        String str;
+        CadVersionEnum cadVersion = CadVersionEnum.AC1032;
+        HeaderModel headerModel = new HeaderModel();
+        for (int i = 0; i < dxfAllLine.size(); i++) {
+            str = dxfAllLine.get(i);
+            if (DxfSystemEnum.ACADVER.getCode().equals(str)) {
+                ++i;
+                str = dxfAllLine.get(++i);
+                cadVersion = CadVersionEnum.getCadVersion(str);
+                headerModel.setCadVersion(cadVersion.getVersion());
+            } else if (DxfSystemEnum.ACADMAINTVER.getCode().equals(str)) {
+                ++i;
+                str = dxfAllLine.get(++i);
+                headerModel.setCadMaintenanceRelease(str);
+            } else if (DxfSystemEnum.DWGCODEPAGE.getCode().equals(str)) {
+                ++i;
+                str = dxfAllLine.get(++i);
+                headerModel.setCadANSICoding(str);
+            } else if (DxfSystemEnum.INBASE.getCode().equals(str)) {
+                while (true) {
+                    ++i;
+                    String line = dxfAllLine.get(i);
+                    if ("10".equals(line)) {
+                        headerModel.setInBaseX(new BigDecimal(dxfAllLine.get(++i)));
+                    } else if ("20".equals(line)) {
+                        headerModel.setInBaseY(new BigDecimal(dxfAllLine.get(++i)));
+                    } else if ("30".equals(line)) {
+                        headerModel.setInBaseZ(new BigDecimal(dxfAllLine.get(++i)));
+                    } else if ("9".equals(line)) {
+                        break;
+                    }
+                }
+            } else if (DxfSystemEnum.EXTMIN.getCode().equals(str)) {
+                while (true) {
+                    ++i;
+                    String line = dxfAllLine.get(i);
+                    if ("10".equals(line)) {
+                        headerModel.setExtMinX(new BigDecimal(dxfAllLine.get(++i)));
+                    } else if ("20".equals(line)) {
+                        headerModel.setExtMinY(new BigDecimal(dxfAllLine.get(++i)));
+                    } else if ("30".equals(line)) {
+                        headerModel.setExtMinZ(new BigDecimal(dxfAllLine.get(++i)));
+                    } else if ("9".equals(line)) {
+                        break;
+                    }
+                }
+            } else if (DxfSystemEnum.EXTMAX.getCode().equals(str)) {
+                while (true) {
+                    ++i;
+                    String line = dxfAllLine.get(i);
+                    if ("10".equals(line)) {
+                        headerModel.setExtMaxX(new BigDecimal(dxfAllLine.get(++i)));
+                    } else if ("20".equals(line)) {
+                        headerModel.setExtMaxY(new BigDecimal(dxfAllLine.get(++i)));
+                    } else if ("30".equals(line)) {
+                        headerModel.setExtMaxZ(new BigDecimal(dxfAllLine.get(++i)));
+                    } else if ("9".equals(line)) {
+                        break;
+                    }
+                }
+            } else if (DxfSystemEnum.TEXTSIZE.getCode().equals(str)) {
+                ++i;
+                str = dxfAllLine.get(++i);
+                headerModel.setTextSize(Double.parseDouble(str));
+            } else if (DxfSystemEnum.CLAYER.getCode().equals(str)) {
+                ++i;
+                str = dxfAllLine.get(++i);
+                headerModel.setCurrentLayer(str);
+            } else if (DxfSystemEnum.TDCREATE.getCode().equals(str)) {
+                ++i;
+                str = dxfAllLine.get(++i);
+                headerModel.setCreateDate(DateUtils.dxfTime2Date(str, cadVersion.getJulianDay()));
+            } else if (DxfSystemEnum.TDUPDATE.getCode().equals(str)) {
+                ++i;
+                str = dxfAllLine.get(++i);
+                headerModel.setUpdateDate(DateUtils.dxfTime2Date(str, cadVersion.getJulianDay()));
+            } else if (DxfSystemEnum.FINGERPRINTGUID.getCode().equals(str)) {
+                ++i;
+                str = dxfAllLine.get(++i);
+                headerModel.setSingleGuid(str);
+            } else if (DxfSystemEnum.VERSIONGUID.getCode().equals(str)) {
+                ++i;
+                str = dxfAllLine.get(++i);
+                headerModel.setVersionGuid(str);
+            }
+        }
+        return headerModel;
+    }
+}

+ 38 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/constant/EntityNameConstant.java

@@ -0,0 +1,38 @@
+package com.fdkankan.dxf.parse.constant;
+
+
+/**
+ * 类型常量
+ */
+public interface EntityNameConstant {
+
+    /**
+     * 点的名称
+     */
+    String POINT_NAME = "POINT";
+    /**
+     * 文本的名称
+     */
+    String TEXT_NAME = "TEXT";
+
+    /**
+     * 线的名称
+     */
+    String LINE_NAME = "LINE";
+
+    /**
+     * 弧线的名称
+     */
+    String ARC_NAME = "ARC";
+
+    /**
+     * 圆的名称
+     */
+    String CIRCLE_NAME = "CIRCLE";
+
+    /**
+     * 多线段
+     */
+    String POLY_LINE_NAME = "POLY_LINE";
+
+}

+ 19 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/constant/PolyLineConstant.java

@@ -0,0 +1,19 @@
+package com.fdkankan.dxf.parse.constant;
+
+/**
+ * 多段线属性字面量
+ *
+ * @author jintaotao
+ * @version 1.0
+ * @date 2022/10/10 13:18
+ */
+public interface PolyLineConstant {
+    /**
+     *
+     */
+    String POLYLINE_LOGIC_CLOSE = "129";
+    /**
+     *
+     */
+    String POLYLINE_LOGIC_CLOSE_1 = "1";
+}

+ 55 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/enums/CadVersionEnum.java

@@ -0,0 +1,55 @@
+package com.fdkankan.dxf.parse.enums;
+
+
+import com.fdkankan.dxf.parse.utils.DateUtils;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * cad版本,默认字符编码,默认的时间 儒略日
+ *
+ * @author ytzjj
+ * @date 2023/11/27
+ */
+@AllArgsConstructor
+@Getter
+public enum CadVersionEnum {
+
+    /**
+     * 文件版本
+     */
+    // AutoCAD 2000
+    AC1015("AC1015", "GBK", DateUtils.CAD_LESS_THAN_2010_JULIAN_DAY),
+    //AutoCAD 2004
+    AC1018("AC1018", "GBK", DateUtils.CAD_LESS_THAN_2010_JULIAN_DAY),
+    //AutoCAD 2010
+    AC1021("AC2021", "UTF-8", DateUtils.CAD_LESS_THAN_2010_JULIAN_DAY),
+    //AutoCAD 2013
+    AC1024("AC1024", "UTF-8", DateUtils.CAD_GREATER_THAN_2010_JULIAN_DAY),
+    //AutoCAD 2018
+    AC1027("AC1027", "UTF-8", DateUtils.CAD_GREATER_THAN_2010_JULIAN_DAY),
+    //AutoCAD 2023
+    AC1032("AC1032", "UTF-8", DateUtils.CAD_GREATER_THAN_2010_JULIAN_DAY),
+    ;
+
+    private final String version;
+    private final String charset;
+    private final Double julianDay;
+
+    /**
+     * 根据CAD版本获取枚举对象
+     *
+     * @param version
+     * @return
+     */
+    public static CadVersionEnum getCadVersion(String version) {
+        for (CadVersionEnum value : CadVersionEnum.values()) {
+            if (version.equals(value.getVersion())) {
+                return value;
+            }
+        }
+        return CadVersionEnum.AC1032;
+    }
+
+
+}

+ 40 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/enums/DxfEntitiesBaseEnum.java

@@ -0,0 +1,40 @@
+package com.fdkankan.dxf.parse.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * @Author ytzjj
+ * @DateTime 2023/11/27 17:21
+ * @Description entities的基础信息枚举
+ */
+
+@Getter
+@AllArgsConstructor
+public enum DxfEntitiesBaseEnum {
+
+
+
+    COLOR_16("420", "颜色16进制"),
+
+    COLOR_CODE("62", "颜色编码"),
+
+    ALPHA("440", "图形透明度"),
+
+    LINE_WIDTH("370", "线宽"),
+
+    HEIGHT("38", "标高"),
+
+
+    ;
+
+    /**
+     * 组码
+     */
+    private String code;
+    /**
+     * 组码名称
+     */
+    private String fieldName;
+
+}

+ 102 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/enums/DxfSystemEnum.java

@@ -0,0 +1,102 @@
+package com.fdkankan.dxf.parse.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * @AUTHOR ZhangJunJie
+ * @DATE 2023/11/25
+ * <p/>
+ * 概要:dxf 文件系统节点枚举
+ */
+
+@Getter
+@AllArgsConstructor
+public enum DxfSystemEnum {
+
+    /**
+     * cad版本的标志
+     */
+    ACADVER("$ACADVER", "cad版本"),
+
+    /**
+     * CAD 维护版本号
+     */
+    ACADMAINTVER("$ACADMAINTVER", "cad 维护版本号"),
+    /**
+     * CAD 字符编码(cad格式)
+     */
+    DWGCODEPAGE("$DWGCODEPAGE", "CAD 字符编码(cad格式)"),
+
+    /**
+     * CAD 基点
+     */
+    INBASE("zu", "CAD 基点"),
+
+    /**
+     * 图形边界框最小边界
+     */
+    EXTMIN("$EXTMIN", "CAD 基点"),
+
+    /**
+     * 图形边界框最大边界
+     */
+    EXTMAX("$EXTMAX", "CAD 基点"),
+
+    /**
+     * 图形文本大小
+     */
+    TEXTSIZE("$TEXTSIZE", "文本大小"),
+
+    /**
+     * 当前图层名称
+     */
+    CLAYER("$CLAYER", "当前图层名称"),
+
+    /**
+     * 当前图形创建时间
+     */
+    TDCREATE("$TDCREATE", "当前图层名称"),
+
+    /**
+     * 当前图形修改时间
+     */
+    TDUPDATE("$TDUPDATE", "当前图层名称"),
+
+    /**
+     * 当前图形唯一guid
+     */
+    FINGERPRINTGUID("$FINGERPRINTGUID", "当前图形唯一guid"),
+
+    /**
+     * 当前图形版本唯一guid
+     */
+    VERSIONGUID("$VERSIONGUID", "当前图形版本唯一guid"),
+
+
+    /**
+     * 文件结束的标志
+     */
+    FILE_END("EOF", "文件结束"),
+
+    /**
+     * 实体段开始(DXF的四大模块之一)
+     */
+    ENTITIES_START("ENTITIES", "实体开始"),
+
+    /**
+     * 每个4大模块结束标志
+     */
+    END_SEC("ENDSEC", "模块结束"),
+
+    ;
+    /**
+     * 字段码
+     */
+    private final String code;
+
+    /**
+     * 组码名称
+     */
+    private final String fieldName;
+}

+ 67 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/enums/entities/ArcEnum.java

@@ -0,0 +1,67 @@
+package com.fdkankan.dxf.parse.enums.entities;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor
+public enum ArcEnum {
+
+    /**
+     * 弧线名
+     */
+    ARC_NAME("ARC", "弧线名"),
+
+    /**
+     * 图层名称
+     */
+    LAYER_NAME("8", "图层名称"),
+
+    /**
+     * x坐标
+     */
+    COORDINATE_X("10", "x坐标"),
+
+    /**
+     * y坐标
+     */
+    COORDINATE_Y("20", "y坐标"),
+
+    /**
+     * z坐标
+     */
+    COORDINATE_Z("30", "z坐标"),
+
+    /**
+     * 圆弧半径
+     */
+    ARC_RADIUS("40", "圆弧半径"),
+
+    /**
+     * 圆弧起始角度
+     */
+    ARC_START_ANGLE("50", "圆弧起始角度"),
+
+    /**
+     * 圆弧终止角度
+     */
+    ARC_END_ANGLE("51", "圆弧终止角度"),
+
+
+    /**
+     * 颜色
+     */
+    COLOR("62", "颜色");
+
+
+    /**
+     * 组码
+     */
+    private String code;
+
+    /**
+     * 组码名称
+     */
+    private String fieldName;
+
+}

+ 56 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/enums/entities/CircleEnum.java

@@ -0,0 +1,56 @@
+package com.fdkankan.dxf.parse.enums.entities;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor
+public enum CircleEnum {
+
+    /**
+     * 圆名称
+     */
+    CIRCLE_NAME("CIRCLE", "圆名称"),
+
+    /**
+     * 图层名称
+     */
+    LAYER_NAME("8", "图层名称"),
+
+    /**
+     * x坐标
+     */
+    COORDINATE_X("10", "x坐标"),
+
+    /**
+     * y坐标
+     */
+    COORDINATE_Y("20", "y坐标"),
+
+    /**
+     * z坐标
+     */
+    COORDINATE_Z("30", "z坐标"),
+
+    /**
+     * 圆半径
+     */
+    CIRCULAR_RADIUS("40", "圆半径"),
+
+
+    /**
+     * 颜色
+     */
+    COLOR("62", "颜色");
+
+    /**
+     * 组码
+     */
+    private String code;
+
+    /**
+     * 组码名称
+     */
+    private String fieldName;
+
+}

+ 77 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/enums/entities/EllipseEnum.java

@@ -0,0 +1,77 @@
+package com.fdkankan.dxf.parse.enums.entities;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor
+public enum EllipseEnum {
+
+    /**
+     * 椭圆名称
+     */
+    ELLIPSE_NAME("ELLIPSE", "椭圆名称"),
+
+    /**
+     * 图层名称
+     */
+    LAYER_NAME("8", "图层名称"),
+
+    /**
+     * 椭圆圆心X坐标
+     */
+    COORDINATES_X("10", "X坐标组码"),
+
+    /**
+     * 椭圆圆心Y坐标
+     */
+    COORDINATES_Y("20", "椭圆圆心Y坐标"),
+
+    /**
+     * 椭圆圆心Z坐标组码
+     */
+    COORDINATES_Z("30", "椭圆圆心Z坐标组码"),
+
+    /**
+     * 椭圆长轴的端点x
+     */
+    ELLIPSE_LONG_AXIS_X("11", "椭圆长轴的端点x"),
+
+    /**
+     * 椭圆长轴的端点Y
+     */
+    ELLIPSE_LONG_AXIS_Y("21", "椭圆长轴的端点Y"),
+
+    /**
+     * 椭圆长轴的端点Z
+     */
+    ELLIPSE_LONG_AXIS_Z("31", "椭圆长轴的端点Z"),
+
+    /**
+     * 椭圆长轴与短轴的比例
+     */
+    ELLIPSE_RATIC_LONG_SHOW("40", "椭圆长轴与短轴的比例"),
+
+    /**
+     * 椭圆起始参数
+     */
+    ELLIPSE_START_PARAM("41", "椭圆起始参数"),
+
+    /**
+     * 椭圆结束参数
+     */
+    ELLIPSE_END_PARAM("42", "椭圆结束参数");
+
+
+    /**
+     * 组码
+     */
+    private String code;
+
+    /**
+     * 组码名称
+     */
+    private String fieldName;
+
+
+}

+ 44 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/enums/entities/InsertEnum.java

@@ -0,0 +1,44 @@
+package com.fdkankan.dxf.parse.enums.entities;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 插入图元
+ *
+ * @author ytzjj
+ * @date 2023/11/27
+ **/
+@Getter
+@AllArgsConstructor
+public enum InsertEnum {
+    /**
+     * 插入图元
+     */
+    INSERT_NAME("INSERT", "插入图元"),
+    /**
+     * 图层名称
+     */
+    LAYER_NAME("8", "图层名称"),
+    /**
+     * x坐标
+     */
+    COORDINATE_X("10", "x坐标"),
+    /**
+     * y坐标
+     */
+    COORDINATE_Y("20", "y坐标"),
+    /**
+     * z坐标
+     */
+    COORDINATE_Z("30", "z坐标");
+    /**
+     * 组码
+     */
+    private String code;
+
+    /**
+     * 组码名称
+     */
+    private String fieldName;
+}

+ 65 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/enums/entities/LineEnum.java

@@ -0,0 +1,65 @@
+package com.fdkankan.dxf.parse.enums.entities;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor
+public enum LineEnum {
+
+    /**
+     * 直线名称
+     */
+    LINE_NAME("LINE", "直线名称"),
+
+    /**
+     * 颜色
+     */
+    COLOR("62", "颜色"),
+
+    /**
+     * 图层名称
+     */
+    LAYER_NAME("8", "图层名称"),
+
+    /**
+     * x坐标
+     */
+    COORDINATE_X("10", "x坐标"),
+
+    /**
+     * 直线终点X坐标
+     */
+    LINE_END_X_COORDINATES("11", "直线终点x的坐标"),
+
+    /**
+     * y坐标
+     */
+    COORDINATE_Y("20", "y坐标"),
+
+    /**
+     * 直线终点y坐标
+     */
+    LINE_END_Y_COORDINATES("21", "直线终点y的坐标"),
+
+    /**
+     * z坐标
+     */
+    COORDINATE_Z("30", "z坐标"),
+
+    /**
+     * 直线终点z坐标
+     */
+    LINE_END_Z_COORDINATES("31", "直线终点z的坐标");
+
+    /**
+     * 组码
+     */
+    private String code;
+
+    /**
+     * 组码名称
+     */
+    private String fieldName;
+
+}

+ 71 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/enums/entities/MTextEnum.java

@@ -0,0 +1,71 @@
+package com.fdkankan.dxf.parse.enums.entities;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 多行文本枚举
+ *
+ * @author ytzjj
+ * @date 2023/11/27
+ */
+@Getter
+@AllArgsConstructor
+public enum MTextEnum {
+
+    /**
+     * 颜色
+     */
+    COLOR("62", "颜色"),
+
+    /**
+     * 文字高度
+     */
+    HEIGH("40", "文字高度"),
+
+    /**
+     * 文字宽度
+     */
+    WIDTH("41", "文字宽度"),
+    /**
+     * 文字旋转角度
+     */
+    ANGLE("50", "文字旋转角度"),
+    /**
+     * 文字倾斜角度
+     */
+    INCLINATION("51", "文字倾斜角度"),
+    /**
+     * 文本名称
+     */
+    MTEXT_NAME("MTEXT", "文本名称"),
+    /**
+     * 文本内容
+     */
+    MTEXT_CONTENT("1", "文本内容"),
+    /**
+     * 图层名称
+     */
+    LAYER_NAME("8", "图层名称"),
+    /**
+     * 中心点x坐标
+     */
+    COORDINATE_X("10", "中心点x坐标"),
+    /**
+     * 中心点y坐标
+     */
+    COORDINATE_Y("20", "中心点y坐标"),
+    /**
+     * 中心点z坐标
+     */
+    COORDINATE_Z("30", "中心点z坐标");
+    /**
+     * 组码
+     */
+    private String code;
+
+    /**
+     * 组码名称
+     */
+    private String fieldName;
+}

+ 49 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/enums/entities/PointEnum.java

@@ -0,0 +1,49 @@
+package com.fdkankan.dxf.parse.enums.entities;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor
+public enum PointEnum {
+
+    /**
+     * 点名称
+     */
+    POINT_NAME("POINT", "点名称"),
+
+    /**
+     * 颜色
+     */
+    COLOR("62", "颜色"),
+
+    /**
+     * 图层名称
+     */
+    LAYER_NAME("8", "图层名称"),
+
+    /**
+     * x坐标
+     */
+    COORDINATE_X("10", "x坐标"),
+
+    /**
+     * y坐标
+     */
+    COORDINATE_Y("20", "y坐标"),
+
+    /**
+     * z坐标
+     */
+    COORDINATE_Z("30", "z坐标");
+    /**
+     * 组码
+     */
+    private String code;
+
+    /**
+     * 组码名称
+     */
+    private String fieldName;
+
+}

+ 99 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/enums/entities/PolyLineEnum.java

@@ -0,0 +1,99 @@
+package com.fdkankan.dxf.parse.enums.entities;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor
+public enum PolyLineEnum {
+
+    /**
+     * 块开始
+     */
+    BLOCK("0", "模块开始结束标记"),
+    /**
+     * 多线段名称
+     */
+    LWPOLYLINE_NAME("LWPOLYLINE", "多线段名称"),
+    /**
+     * 二号多段名称
+     */
+    POLYLINE_NAME("POLYLINE", "二号多段线"),
+
+    /**
+     * 图层名称
+     */
+    LAYER_NAME("8", "图层名称"),
+
+    /**
+     * x坐标
+     */
+    COORDINATE_X("10", "x坐标"),
+
+    /**
+     * y坐标
+     */
+    COORDINATE_Y("20", "y坐标"),
+
+    /**
+     * z坐标
+     */
+    COORDINATE_Z("30", "z坐标"),
+
+    /**
+     * 顶点数量
+     */
+    VERTEX_NUM("90", "顶点数量"),
+    /**
+     * 起点宽度
+     */
+    START_WIDTH("40", "起点宽度"),
+    /**
+     * 端点宽度
+     */
+    END_WIDTH("41", "端点宽度"),
+    /**
+     * 凸度
+     */
+    OUT_DO("42", "凸度"),
+    /**
+     * 顶点名称
+     */
+    VERTEX_NAME("VERTEX", "顶点名称"),
+
+
+    /**
+     * 多线段结束
+     */
+    SEQEND("SEQEND", "多线段结束"),
+
+    /**
+     * 多段线闭合
+     */
+    CLOSE("70", "多段线闭合"),
+
+
+    /**
+     * 线条类型 "CONTINUOUS"(实线),"DASHED"(虚线),"DOT"(点线
+     */
+    LINE_TYPE("6", "线条类型"),
+
+    /**
+     * 填充色
+     */
+    FILL_COLOR("63", "填充色"),
+
+
+    ;
+
+    /**
+     * 组码
+     */
+    private final String code;
+
+    /**
+     * 组码名称
+     */
+    private final String fieldName;
+
+}

+ 71 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/enums/entities/TextEnum.java

@@ -0,0 +1,71 @@
+package com.fdkankan.dxf.parse.enums.entities;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * dxf 文本枚举
+ *
+ * @author ytzjj
+ * @date 2023/11/27
+ */
+@Getter
+@AllArgsConstructor
+public enum TextEnum {
+    /**
+     * 文本名称
+     */
+    TEXT_NAME("TEXT", "文本名称"),
+
+    /**
+     * 颜色
+     */
+    COLOR("62", "颜色"),
+
+    /**
+     * 文字高度
+     */
+    HEIGH("40", "文字高度"),
+
+    /**
+     * 文字宽度
+     */
+    WIDTH("41", "文字宽度"),
+    /**
+     * 文字旋转角度
+     */
+    ANGLE("50", "文字旋转角度"),
+     /**
+     * 文字倾斜角度
+     */
+    INCLINATION("51", "文字倾斜角度"),
+    /**
+     * 文本内容
+     */
+    TEXT_CONTENT("1", "文本内容"),
+    /**
+     * 图层名称
+     */
+    LAYER_NAME("8", "图层名称"),
+    /**
+     * 中心点x坐标
+     */
+    COORDINATE_X("10", "中心点x坐标"),
+    /**
+     * 中心点y坐标
+     */
+    COORDINATE_Y("20", "中心点y坐标"),
+    /**
+     * 中心点z坐标
+     */
+    COORDINATE_Z("30", "中心点z坐标");
+    /**
+     * 组码
+     */
+    private String code;
+
+    /**
+     * 组码名称
+     */
+    private String fieldName;
+}

+ 77 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/enums/error/DxfAnalysisErrorEnum.java

@@ -0,0 +1,77 @@
+package com.fdkankan.dxf.parse.enums.error;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * @Author ytzjj
+ * @DateTime 2023/11/24 16:32
+ * @Description DXF 文件解析过程错误枚举
+ */
+
+
+@AllArgsConstructor
+@Getter
+public enum DxfAnalysisErrorEnum {
+
+
+    /**
+     * DXF文件解析未知错误
+     */
+    FILE_ANALYSIS_UNKNOWN_ERROR(2000, "DXF文件解析未知错误"),
+
+    /**
+     * 圆002x
+     */
+    CIRCLE_NOT_X(2020, "dxf解析圆数据没有获取到圆心x坐标"),
+    CIRCLE_NOT_Y(2021, "dxf解析圆数据没有获取到圆心y坐标"),
+    CIRCLE_NOT_Z(2022, "dxf解析圆数据没有获取到圆心z坐标"),
+    CIRCLE_NOT_RADIUS(2023, "dxf解析圆数据没有获取到半径值"),
+
+    /**
+     * 点003x
+     */
+    POINT_NOT_X(2030, "dxf解析点数据没有获取到点x坐标"),
+    POINT_NOT_Y(2031, "dxf解析点数据没有获取到点y坐标"),
+    POINT_NOT_Z(2032, "dxf解析点数据没有获取到点z坐标"),
+
+    /**
+     * 直线004x
+     */
+    LINE_START_NOT_X(2040, "dxf解析直线数据没有获取到起点x坐标"),
+    LINE_START_NOT_Y(2041, "dxf解析直线数据没有获取到起点y坐标"),
+    LINE_START_NOT_Z(2042, "dxf解析直线数据没有获取到起点z坐标"),
+    LINE_END_NOT_X(2043, "dxf解析直线数据没有获取到终点x坐标"),
+    LINE_END_NOT_Y(2044, "dxf解析直线数据没有获取到终点y坐标"),
+    LINE_END_NOT_Z(2045, "dxf解析直线数据没有获取到终点z坐标"),
+
+    /**
+     * 弧线005x
+     */
+    ARC_NOT_X(2050, "dxf解析弧线数据没有获取到圆心x坐标"),
+    ARC_NOT_Y(2051, "dxf解析弧线数据没有获取到圆心y坐标"),
+    ARC_NOT_Z(2052, "dxf解析弧线数据没有获取到圆心z坐标"),
+    ARC_NOT_RADIUS(2053, "dxf解析弧线数据没有获取到半径"),
+    ARC_NOT_START_ANGLE(2054, "dxf解析弧线数据没有获取到起始角度"),
+    ARC_NOT_END_ANGLE(2055, "dxf解析弧线数据没有获取到中止角度"),
+
+
+    /**
+     * 多线段006x
+     */
+    POLY_LINE_NOT_COORDINATE_X(2060, "dxf解析多线段时没有获取到顶点x坐标"),
+    POLY_LINE_NOT_COORDINATE_Y(2061, "dxf解析多线段时没有获取到顶点y坐标"),
+    POLY_LINE_NOT_COORDINATE_Z(2062, "dxf解析多线段时没有获取到顶点z坐标"),
+    POLY_LINE_NOT_SEQEND(2063, "dxf解析多线段时没有获取到结束标记");
+
+
+    /**
+     * 错误码
+     */
+    private final Integer code;
+
+    /**
+     * 错误信息
+     */
+    private final String message;
+}

+ 27 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/enums/error/DxfFileErrorEnum.java

@@ -0,0 +1,27 @@
+package com.fdkankan.dxf.parse.enums.error;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * @Author ytzjj
+ * @DateTime 2023/11/24 16:25
+ * @Description DXF 异常枚举
+ */
+
+
+@Getter
+@AllArgsConstructor
+public enum DxfFileErrorEnum {
+
+
+    DXF_FILE_TYPE_ERROR(1000, "DXF文件路径或IO访问错误"),
+
+    DXF_FILE_READ_ERROR(1001, "DXF文件读取错误");
+
+
+    private final Integer code;
+
+
+    private final String message;
+}

+ 40 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/exception/DxfAnalysisException.java

@@ -0,0 +1,40 @@
+package com.fdkankan.dxf.parse.exception;
+
+import com.fdkankan.dxf.parse.enums.error.DxfAnalysisErrorEnum;
+
+/**
+ * @Author ytzjj
+ * @DateTime 2023/11/27 9:58
+ * @Description
+ */
+public class DxfAnalysisException extends DxfException {
+    private static final long serialVersionUID = 2297430522517097373L;
+
+    /**
+     * 构造函数
+     *
+     * @param message 错误信息
+     * @param cause   异常
+     */
+    public DxfAnalysisException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    /**
+     * 构造函数
+     *
+     * @param message 错误信息
+     */
+    public DxfAnalysisException(String message) {
+        super(message);
+    }
+
+    /**
+     * 构造函数
+     *
+     * @param errorEnum DxfAnalysisErrorEnum
+     */
+    public DxfAnalysisException(DxfAnalysisErrorEnum errorEnum) {
+        super(errorEnum.getMessage());
+    }
+}

+ 22 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/exception/DxfException.java

@@ -0,0 +1,22 @@
+package com.fdkankan.dxf.parse.exception;
+
+/**
+ * @Author ytzjj
+ * @DateTime 2023/11/24 16:23
+ * @Description DXF 根异常
+ */
+public class DxfException extends RuntimeException {
+
+    public DxfException(String message) {
+        super(message);
+    }
+
+    public DxfException(Throwable cause) {
+        super(cause);
+    }
+
+    public DxfException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+}

+ 29 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/exception/DxfFileException.java

@@ -0,0 +1,29 @@
+package com.fdkankan.dxf.parse.exception;
+
+import com.fdkankan.dxf.parse.enums.error.DxfFileErrorEnum;
+
+/**
+ * @Author ytzjj
+ * @DateTime 2023/11/24 16:28
+ * @Description DXF 文件类型异常
+ */
+
+public class DxfFileException extends DxfException {
+
+
+    public DxfFileException(String message) {
+        super(message);
+    }
+
+    public DxfFileException(Throwable cause) {
+        super(cause);
+    }
+
+    public DxfFileException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public DxfFileException(DxfFileErrorEnum errorEnum) {
+        super("ERROR CODE: " + errorEnum.getCode() + "; ERROR MESSAGE: " + errorEnum.getMessage());
+    }
+}

+ 53 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/model/DxfModel.java

@@ -0,0 +1,53 @@
+package com.fdkankan.dxf.parse.model;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * @Author ytzjj
+ * @DateTime 2023/11/24 17:23
+ * @Description DXF系统变量
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Accessors(chain = true)
+public class DxfModel implements Serializable {
+
+    private static final long serialVersionUID = 6102011992053173970L;
+
+    /**
+     * 当前图层
+     */
+    private String currentLayer;
+
+
+    /**
+     * 图形的创建日期
+     */
+    private Date createDate;
+
+    /**
+     * 图形的保存(修改)日期
+     */
+    private Date updateDate;
+
+
+    /**
+     * 图形唯一ID
+     */
+    private String singleGuid;
+
+
+    /**
+     * 图形唯一版本
+     */
+    private String versionGuid;
+
+
+}

+ 58 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/model/GeometricModel.java

@@ -0,0 +1,58 @@
+package com.fdkankan.dxf.parse.model;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+
+/**
+ * @Author ytzjj
+ * @DateTime 2023/11/24 16:54
+ * @Description DXF实例根模型
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Accessors(chain = true)
+public class GeometricModel implements Serializable {
+
+
+    private static final long serialVersionUID = 154930463320039374L;
+
+    /**
+     * dxf 对象id
+     */
+    private String id;
+
+    /**
+     * dxf 对象名称
+     */
+    private String name;
+
+    /**
+     * dxf 对象图层名称
+     */
+    private String layerName;
+
+    /**
+     * 颜色
+     */
+    private String color;
+
+    /**
+     * 线宽
+     */
+    private Double lineWidth = 1D;
+
+    /**
+     * 图形透明度,取值范围为0-100,当alpha为0时,为不透明,当alpha为100的时候,图形将不可见
+     */
+    private int alpha = 0;
+
+    /**
+     * 标高
+     */
+    private Double height = 0.0;
+}

+ 57 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/model/entities/GeometricArc.java

@@ -0,0 +1,57 @@
+package com.fdkankan.dxf.parse.model.entities;
+
+import com.fdkankan.dxf.parse.model.GeometricModel;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * @Author ytzjj
+ * @DateTime 2023/11/27 9:16
+ * @Description 弧度
+ */
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Accessors(chain = true)
+public class GeometricArc extends GeometricModel implements Serializable {
+
+    private static final long serialVersionUID = 1685606296528470644L;
+
+    /**
+     * 弧线的半径
+     */
+    private BigDecimal radius;
+
+    /**
+     * 弧的起始角度
+     */
+    private BigDecimal startArc;
+
+    /**
+     * 弧的终止角度
+     */
+    private BigDecimal endArc;
+
+    /**
+     * 弧线圆心的x坐标
+     */
+    private BigDecimal x;
+
+    /**
+     * 弧线圆心的y坐标
+     */
+    private BigDecimal y;
+
+    /**
+     * 弧线圆心的z坐标
+     */
+    private BigDecimal z;
+}

+ 45 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/model/entities/GeometricCircle.java

@@ -0,0 +1,45 @@
+package com.fdkankan.dxf.parse.model.entities;
+
+import com.fdkankan.dxf.parse.model.GeometricModel;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * @Author ytzjj
+ * @DateTime 2023/11/27 9:17
+ * @Description 圆
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Accessors(chain = true)
+public class GeometricCircle extends GeometricModel implements Serializable {
+
+    private static final long serialVersionUID = 1301011989021713849L;
+    /**
+     * 圆心的半径
+     */
+    private BigDecimal radius;
+
+    /**
+     * 圆心的x坐标
+     */
+    private BigDecimal x;
+
+    /**
+     * 圆心的y坐标
+     */
+    private BigDecimal y;
+
+    /**
+     * 圆心的z坐标
+     */
+    private BigDecimal z;
+}

+ 75 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/model/entities/GeometricLine.java

@@ -0,0 +1,75 @@
+package com.fdkankan.dxf.parse.model.entities;
+
+import com.fdkankan.dxf.parse.model.GeometricModel;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * @Author ytzjj
+ * @DateTime 2023/11/27 9:12
+ * @Description 线
+ */
+
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Accessors(chain = true)
+public class GeometricLine extends GeometricModel implements Serializable {
+
+
+    private static final long serialVersionUID = 6401012005110567687L;
+    /**
+     * 线的起点x坐标
+     */
+    private BigDecimal startX;
+
+    /**
+     * 线的起点y坐标
+     */
+    private BigDecimal startY;
+
+    /**
+     * 线的起点z坐标
+     */
+    private BigDecimal startZ;
+
+    /**
+     * 线的终点x坐标
+     */
+    private BigDecimal endX;
+
+    /**
+     * 线的终点y坐标
+     */
+    private BigDecimal endY;
+
+    /**
+     * 线的终点z坐标
+     */
+    private BigDecimal endZ;
+
+
+    /**
+     * 通过两个点来生成线的构造函数
+     *
+     * @param p1 点1
+     * @param p2 点2
+     */
+    public GeometricLine(GeometricPoint p1, GeometricPoint p2) {
+        this.startX = p1.getX();
+        this.startY = p1.getY();
+        this.startZ = p1.getZ();
+        this.endX = p2.getX();
+        this.endY = p2.getY();
+        this.endZ = p2.getZ();
+    }
+
+}

+ 41 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/model/entities/GeometricPoint.java

@@ -0,0 +1,41 @@
+package com.fdkankan.dxf.parse.model.entities;
+
+import com.fdkankan.dxf.parse.model.GeometricModel;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * @Author ytzjj
+ * @DateTime 2023/11/27 9:10
+ * @Description 点
+ */
+
+@AllArgsConstructor
+@NoArgsConstructor
+@Data
+@EqualsAndHashCode(callSuper = true)
+@Accessors(chain = true)
+public class GeometricPoint extends GeometricModel implements Serializable {
+
+    private static final long serialVersionUID = 6202012001043042778L;
+    /**
+     * 点的x坐标
+     */
+    private BigDecimal x;
+
+    /**
+     * 点的y坐标
+     */
+    private BigDecimal y;
+
+    /**
+     * 点的z坐标
+     */
+    private BigDecimal z;
+}

+ 56 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/model/entities/GeometricPolyLine.java

@@ -0,0 +1,56 @@
+package com.fdkankan.dxf.parse.model.entities;
+
+import com.fdkankan.dxf.parse.model.GeometricModel;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @Author ytzjj
+ * @DateTime 2023/11/27 9:18
+ * @Description 多插线
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Accessors(chain = true)
+public class GeometricPolyLine extends GeometricModel implements Serializable {
+
+
+    private static final long serialVersionUID = 6202012001043042478L;
+    /**
+     * 顶点数量
+     */
+    private Integer vertexNum;
+
+    /**
+     * 多个顶点点组成
+     */
+    private List<GeometricVertex> vertexList;
+
+    /**
+     * 逻辑闭合
+     */
+    private boolean logicClose;
+
+    /**
+     * 填充色(闭合的是面)
+     */
+    private String fillColor;
+
+
+    /**
+     * 线条类型其取值为一个字符串,表示线条类型的名称。例如,"CONTINUOUS" 表示实线,"DASHED" 表示虚线,"DOT" 表示点线等
+     */
+    private String lineType;
+
+    public boolean isLogicClose() {
+        return logicClose;
+    }
+}

+ 65 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/model/entities/GeometricText.java

@@ -0,0 +1,65 @@
+package com.fdkankan.dxf.parse.model.entities;
+
+import com.fdkankan.dxf.parse.model.GeometricModel;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * @Author ytzjj
+ * @DateTime 2023/11/27 9:14
+ * @Description 单行文本
+ */
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Accessors(chain = true)
+public class GeometricText extends GeometricModel implements Serializable {
+
+    private static final long serialVersionUID = 6202012001043042428L;
+    /**
+     * 文字名称
+     */
+    private String text;
+    /**
+     * 点的x坐标
+     */
+    private BigDecimal x;
+
+    /**
+     * 点的y坐标
+     */
+    private BigDecimal y;
+
+    /**
+     * 点的z坐标
+     */
+    private BigDecimal z;
+
+    /**
+     * 文字高度
+     */
+    private Double high = 1.0;
+
+    /**
+     * 文字的宽度
+     */
+    private Double width = 1.0;
+
+    /**
+     * 旋转角度
+     */
+    private BigDecimal angle = new BigDecimal(0);
+
+    /**
+     * 倾斜角度
+     */
+    private BigDecimal inclination = new BigDecimal(0);
+}

+ 43 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/model/entities/GeometricVertex.java

@@ -0,0 +1,43 @@
+package com.fdkankan.dxf.parse.model.entities;
+
+import com.fdkankan.dxf.parse.model.GeometricModel;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * @Author ytzjj
+ * @DateTime 2023/11/27 9:20
+ * @Description 顶点
+ */
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Accessors(chain = true)
+public class GeometricVertex extends GeometricModel implements Serializable {
+
+    private static final long serialVersionUID = 6202012001043042018L;
+
+    /**
+     * 顶点的x坐标
+     */
+    private BigDecimal x;
+
+    /**
+     * 顶点的y坐标
+     */
+    private BigDecimal y;
+
+    /**
+     * 顶点的z坐标
+     */
+    private BigDecimal z;
+
+}

+ 91 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/model/headers/HeaderModel.java

@@ -0,0 +1,91 @@
+package com.fdkankan.dxf.parse.model.headers;
+
+
+import com.fdkankan.dxf.parse.model.DxfModel;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * @Author ytzjj
+ * @DateTime 2023/11/24 17:04
+ * @Description 头内容
+ */
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Accessors(chain = true)
+public class HeaderModel extends DxfModel implements Serializable {
+
+    private static final long serialVersionUID = 6301011998061133804L;
+
+    /**
+     * cad主版本
+     */
+    private String cadVersion;
+
+    /**
+     * cad 维护版本
+     */
+    private String cadMaintenanceRelease;
+
+
+    /**
+     * ANSI代码页,字符编码
+     * ANSI_936 代表中文
+     */
+    private String cadANSICoding;
+
+    /**
+     * 基点X坐标
+     */
+    private BigDecimal inBaseX;
+    /**
+     * 基点Y坐标
+     */
+    private BigDecimal inBaseY;
+    /**
+     * 基点Z坐标
+     */
+    private BigDecimal inBaseZ;
+
+
+    /**
+     * 图形的边界框的最小顶点 X
+     */
+    private BigDecimal extMinX;
+    /**
+     * 图形的边界框的最小顶点Y
+     */
+    private BigDecimal extMinY;
+    /**
+     * 图形的边界框的最小顶点Z
+     */
+    private BigDecimal extMinZ;
+
+
+    /**
+     * 图形的边界框的最大顶点 X
+     */
+    private BigDecimal extMaxX;
+    /**
+     * 图形的边界框的最大顶点Y
+     */
+    private BigDecimal extMaxY;
+    /**
+     * 图形的边界框的最大顶点Z
+     */
+    private BigDecimal extMaxZ;
+
+
+    /**
+     * 文本大小
+     */
+    private Double textSize;
+
+}

+ 76 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/resolver/DxfResolver.java

@@ -0,0 +1,76 @@
+package com.fdkankan.dxf.parse.resolver;
+
+import com.fdkankan.dxf.parse.model.GeometricModel;
+import com.fdkankan.dxf.parse.model.entities.*;
+import com.fdkankan.dxf.parse.transformation.model.DxfLine;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @Author ytzjj
+ * @DateTime 2023/11/24 16:37
+ * @Description Dxf解析器
+ */
+public interface DxfResolver {
+
+    /**
+     * 获取dxf几何数据(初步)
+     *
+     * @return 返回map数据
+     */
+    Map<String, List<GeometricModel>> getStructureMap();
+
+
+    /**
+     * 获取点线数据list,这种数据类型是符合rtas项目中使用的
+     *
+     * @return 点线数据
+     */
+    List<DxfLine> getDxfLineList();
+
+    /**
+     * 获取dxf文件中所有的几何点
+     *
+     * @return 所有的几何点
+     */
+    List<GeometricPoint> getGeometricPointList();
+
+    /**
+     * 获取dxf文件中所有的几何线
+     *
+     * @return 所有的几何线
+     */
+    List<GeometricLine> getGeometricLineList();
+
+
+    /**
+     * 获取dxf文件中所有的几何弧线
+     *
+     * @return 所有的几何弧线
+     */
+    List<GeometricArc> getGeometricArcList();
+
+
+    /**
+     * 获取dxf文件中所有的几何圆
+     *
+     * @return 所有的几何圆
+     */
+    List<GeometricCircle> getGeometricCircleList();
+
+    /**
+     * 获取dxf文件中所有的几何多线段
+     *
+     * @return 所有的几何多线段
+     */
+    List<GeometricPolyLine> getGeometricPolyLineList();
+
+    /**
+     * 获取dxf文件中所有的几何文本
+     *
+     * @return 所有的几何文本
+     */
+    List<GeometricText> getGeometricTextList();
+
+}

+ 145 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/resolver/impl/DxfResolverImpl.java

@@ -0,0 +1,145 @@
+package com.fdkankan.dxf.parse.resolver.impl;
+
+import com.fdkankan.dxf.parse.analysis.DxfAnalysis;
+import com.fdkankan.dxf.parse.constant.EntityNameConstant;
+import com.fdkankan.dxf.parse.model.GeometricModel;
+import com.fdkankan.dxf.parse.model.entities.*;
+import com.fdkankan.dxf.parse.model.headers.HeaderModel;
+import com.fdkankan.dxf.parse.resolver.DxfResolver;
+import com.fdkankan.dxf.parse.transformation.model.DxfLine;
+import com.fdkankan.dxf.parse.utils.DxfLineTransformUtil;
+import com.fdkankan.dxf.parse.utils.GeometricTransformUtil;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @Author ytzjj
+ * @DateTime 2023/11/24 16:37
+ * @Description DXF 解析器默认实现
+ */
+public class DxfResolverImpl implements DxfResolver {
+
+
+    /**
+     * dxf 文件流
+     */
+    private InputStream inputStream;
+
+    /**
+     * dxf 编码
+     */
+    private String fileChartSet = "UTF-8";
+
+    /**
+     * dxf 文件头信息
+     */
+    private HeaderModel dxfHeaderModel;
+
+
+    /**
+     * 初步解析的数据
+     */
+    private Map<String, List<GeometricModel>> baseStructureMap;
+
+    public DxfResolverImpl(InputStream inputStream) throws IOException {
+        this.inputStream = inputStream;
+        this.getBaseStructure();
+    }
+
+    /**
+     * 获取dxf基础结构
+     *
+     * @return 返回基础dxf结构Map集合
+     */
+    private Map<String, List<GeometricModel>> getBaseStructure() throws IOException {
+
+        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+        byte[] bytes = new byte[1024];
+        int len;
+        while ((len = this.inputStream.read(bytes)) > -1) {
+            byteArrayOutputStream.write(bytes, 0, len);
+        }
+        byteArrayOutputStream.flush();
+
+        try (InputStream headerStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray())) {
+            // 1. 根据utf-8,读取字节流,解析系统变量生成dxf系统模型存储
+            dxfHeaderModel = DxfAnalysis.parseDxfHeaderModel(headerStream, this.fileChartSet);
+        }
+        try (InputStream geometricStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray())) {
+            // 2. 根据系统变量解析出的字符编码,读取字节流,解析其他数据
+            baseStructureMap = DxfAnalysis.parseDxfGeometricList(geometricStream, this.dxfHeaderModel);
+        }
+
+        //关闭文件流
+        if (this.inputStream != null) {
+            this.inputStream.close();
+        }
+        byteArrayOutputStream.close();
+        return baseStructureMap;
+    }
+
+    /**
+     * 获取dxf几何数据(初步)
+     * map的key: 几何图像名称,比如:‘POINT’
+     * map的value:几何图像集合,比如:List
+     *
+     * @return 返回map数据
+     */
+    @Override
+    public Map<String, List<GeometricModel>> getStructureMap() {
+        return this.baseStructureMap;
+    }
+
+    @Override
+    public List<DxfLine> getDxfLineList() {
+        //几何数据转换点线数据
+        return DxfLineTransformUtil.geometricTransform(this.baseStructureMap);
+    }
+
+    @Override
+    public List<GeometricPoint> getGeometricPointList() {
+        //从map中把所有的GeometricPoint拿出来
+        List<GeometricModel> geometricModels = this.baseStructureMap.get(EntityNameConstant.POINT_NAME);
+        //把GeometricPoint转换为GeometricPoint
+        return GeometricTransformUtil.transformGeometricPoint(geometricModels);
+    }
+
+    @Override
+    public List<GeometricLine> getGeometricLineList() {
+        //从map中把所有的GeometricLine拿出来
+        List<GeometricModel> objectList = this.baseStructureMap.get(EntityNameConstant.LINE_NAME);
+        //把GeometricPoint转换为GeometricLine
+        return GeometricTransformUtil.transformGeometricLine(objectList);
+    }
+
+    @Override
+    public List<GeometricArc> getGeometricArcList() {
+        //从map中把所有的GeometricArc拿出来
+        List<GeometricModel> objectList = this.baseStructureMap.get(EntityNameConstant.ARC_NAME);
+        //把GeometricPoint转换为GeometricArc
+        return GeometricTransformUtil.transformGeometricArc(objectList);
+    }
+
+    @Override
+    public List<GeometricCircle> getGeometricCircleList() {
+        List<GeometricModel> objectList = this.baseStructureMap.get(EntityNameConstant.CIRCLE_NAME);
+        return GeometricTransformUtil.transformGeometricCircle(objectList);
+    }
+
+    @Override
+    public List<GeometricPolyLine> getGeometricPolyLineList() {
+        List<GeometricModel> objectList = this.baseStructureMap.get(EntityNameConstant.POLY_LINE_NAME);
+        return GeometricTransformUtil.transformGeometricPolyLine(objectList);
+    }
+
+    @Override
+    public List<GeometricText> getGeometricTextList() {
+        List<GeometricModel> objectList = this.baseStructureMap.get(EntityNameConstant.TEXT_NAME);
+        return GeometricTransformUtil.transformGeometricText(objectList);
+    }
+}

+ 69 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/transformation/DxfLineTransformation.java

@@ -0,0 +1,69 @@
+package com.fdkankan.dxf.parse.transformation;
+
+
+import com.fdkankan.dxf.parse.model.GeometricModel;
+import com.fdkankan.dxf.parse.transformation.model.DxfLine;
+
+import java.util.List;
+
+public interface DxfLineTransformation {
+
+
+    /**
+     * 将几何点转换为几何线
+     *
+     * @param list 需要转换的数据
+     * @return 返回点线数据
+     */
+    List<DxfLine> pointTransform(List<GeometricModel> list);
+
+    /**
+     * 将几何圆、转换为点圆数据
+     *
+     * @param list 需要转换的数据
+     * @return 返回点线数据
+     */
+    List<DxfLine> circleTransform(List<GeometricModel> list);
+
+
+    /**
+     * 将几何弧线、转换为点弧线数据
+     *
+     * @param list 需要转换的数据
+     * @return 返回点线数据
+     */
+    List<DxfLine> arcTransform(List<GeometricModel> list);
+
+
+    /**
+     * 将几何椭圆、转换为点椭圆数据
+     *
+     * @param list 需要转换的数据
+     * @return 返回点线数据
+     */
+    List<DxfLine> ellipseTransform(List<GeometricModel> list);
+
+    /**
+     * 将几何线、转换为点线数据
+     *
+     * @param list 需要转换的数据
+     * @return 返回点线数据
+     */
+    List<DxfLine> lineTransform(List<GeometricModel> list);
+
+    /**
+     * 将几何多线段、转换为点多线段数据
+     *
+     * @param list 需要转换的数据
+     * @return 返回点线数据
+     */
+    List<DxfLine> polyLineTransform(List<GeometricModel> list);
+
+    /**
+     * 将几何多线段、转换为点多线段数据
+     *
+     * @param list 需要转换的数据
+     * @return 返回点线数据
+     */
+    List<DxfLine> textTransform(List<GeometricModel> list);
+}

+ 21 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/transformation/GeometricTransform.java

@@ -0,0 +1,21 @@
+package com.fdkankan.dxf.parse.transformation;
+
+import com.fdkankan.dxf.parse.model.GeometricModel;
+
+import java.util.List;
+
+/**
+ * @Author ytzjj
+ * @DateTime 2023/11/27 13:44
+ * @Description
+ */
+public interface GeometricTransform<T> {
+
+    /**
+     * 将GeometricObject转换为GeometricLine
+     *
+     * @param objectList 转换的数据
+     * @return List
+     */
+    List<T> transform(List<GeometricModel> objectList);
+}

+ 44 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/transformation/TransformBuilder.java

@@ -0,0 +1,44 @@
+package com.fdkankan.dxf.parse.transformation;
+
+
+import com.fdkankan.dxf.parse.constant.EntityNameConstant;
+import com.fdkankan.dxf.parse.transformation.impl.*;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class TransformBuilder {
+
+    /**
+     * 容器
+     */
+    private Map<String, GeometricTransform> map;
+
+    public TransformBuilder() {
+        map = new HashMap<>();
+        map.put(EntityNameConstant.ARC_NAME, GeometricArcTransformImpl.getSingleInstance());
+        map.put(EntityNameConstant.CIRCLE_NAME, GeometricCircleTransformImpl.getSingleInstance());
+        map.put(EntityNameConstant.LINE_NAME, GeometricLineTransformImpl.getSingleInstance());
+        map.put(EntityNameConstant.POINT_NAME, GeometricPointTransformImpl.getSingleInstance());
+        map.put(EntityNameConstant.TEXT_NAME, GeometricTextTransformImpl.getSingleInstance());
+        map.put(EntityNameConstant.POLY_LINE_NAME, GeometricPolyLineTransformImpl.getSingleInstance());
+    }
+
+    /**
+     * 构建方法
+     *
+     * @param type 类型
+     * @return GeometricTransform
+     */
+    public static GeometricTransform builder(String type) {
+        return Holder.transformBuilder.map.get(type);
+    }
+
+    /**
+     * 静态内部类
+     */
+    public static class Holder {
+        public static TransformBuilder transformBuilder = new TransformBuilder();
+    }
+
+}

+ 292 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/transformation/impl/DxfLineTransformationImpl.java

@@ -0,0 +1,292 @@
+package com.fdkankan.dxf.parse.transformation.impl;
+
+
+import com.fdkankan.dxf.parse.model.GeometricModel;
+import com.fdkankan.dxf.parse.model.entities.*;
+import com.fdkankan.dxf.parse.transformation.DxfLineTransformation;
+import com.fdkankan.dxf.parse.transformation.model.DxfLine;
+import com.fdkankan.dxf.parse.transformation.model.DxfPoint;
+import com.fdkankan.dxf.parse.utils.GeometricTransformUtil;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+
+public class DxfLineTransformationImpl implements DxfLineTransformation {
+
+    /**
+     * 实例对象
+     */
+    private static DxfLineTransformation dxfLineTransformation;
+
+    /**
+     * 采用单例模式
+     *
+     * @return DxfLineTransformation
+     */
+    public static DxfLineTransformation getSingleInstance() {
+        if (dxfLineTransformation == null) {
+            synchronized (DxfLineTransformation.class) {
+                if (dxfLineTransformation == null) {
+                    dxfLineTransformation = new DxfLineTransformationImpl();
+                }
+            }
+        }
+        return dxfLineTransformation;
+    }
+
+    /**
+     * 将几何点转换为几何线
+     *
+     * @param list 需要转换的数据
+     * @return 返回点线数据
+     */
+    @Override
+    public List<DxfLine> pointTransform(List<GeometricModel> list) {
+        List<GeometricPoint> geometricPointList = GeometricTransformUtil.transformGeometricPoint(list);
+        List<DxfLine> dxfLineList = new ArrayList<>();;
+
+        for (GeometricPoint point : geometricPointList) {
+            DxfLine dxfLine = new DxfLine();
+            dxfLine.setLayerName(point.getLayerName());
+            DxfPoint startPoint = new DxfPoint(1L, point);
+            DxfPoint endPoint = new DxfPoint(2L, point);
+            List<DxfPoint> dxfPoints = new ArrayList<>();;
+            dxfPoints.add(startPoint);
+            dxfPoints.add(endPoint);
+            dxfLine.setDataPointList(dxfPoints);
+            dxfLineList.add(dxfLine);
+        }
+        return dxfLineList;
+    }
+
+    /**
+     * 将几何圆、转换为点圆数据
+     *
+     * @param list 需要转换的数据
+     * @return 返回点线数据
+     */
+    @Override
+    public List<DxfLine> circleTransform(List<GeometricModel> list) {
+        List<GeometricCircle> geometricCircleList = GeometricTransformUtil.transformGeometricCircle(list);
+        List<DxfLine> dxfLineList = new ArrayList<>();;
+        for (GeometricCircle geometricCircle : geometricCircleList) {
+
+            DxfLine dxfLine = new DxfLine();
+            dxfLine.setLayerName(geometricCircle.getLayerName());
+
+            Double radius = 2.0;
+            Double end = 360.0;
+
+            //编号从第二个点开始
+            Long num = 2L;
+
+            //圆心x
+            Double x = geometricCircle.getX().doubleValue();
+            //圆心y
+            Double y = geometricCircle.getY().doubleValue();
+            //圆心z
+            Double z = geometricCircle.getZ().doubleValue();
+            //半径
+            Double r = geometricCircle.getRadius().doubleValue();
+            //点集
+            List<DxfPoint> dxfPoints = new ArrayList<>();;
+            //原点,编号为0
+            DxfPoint originPoint = new DxfPoint(0L, BigDecimal.valueOf(0), BigDecimal.valueOf(0), BigDecimal.valueOf(0));
+            //起点
+            DxfPoint startPoint = new DxfPoint(1L, BigDecimal.valueOf(x + r), BigDecimal.valueOf(y), BigDecimal.valueOf(z));
+            dxfPoints.add(originPoint);
+            dxfPoints.add(startPoint);
+            while (radius < end) {
+                Double arc = (Math.PI / 180) * radius;
+                Double x1 = x + r * (Math.cos(arc));
+                Double y1 = y + r * (Math.sin(arc));
+                DxfPoint endPoint = new DxfPoint(num, BigDecimal.valueOf(x1), BigDecimal.valueOf(y1), BigDecimal.valueOf(z));
+                num = num + 1L;
+                dxfPoints.add(endPoint);
+                radius = radius + 2.0;
+            }
+            dxfLine.setDataPointList(dxfPoints);
+            dxfLineList.add(dxfLine);
+        }
+
+        return dxfLineList;
+    }
+
+    /**
+     * 将几何弧线、转换为点弧线数据
+     *
+     * @param list 需要转换的数据
+     * @return 返回点线数据
+     */
+    @Override
+    public List<DxfLine> arcTransform(List<GeometricModel> list) {
+
+        List<GeometricArc> geometricArcList = GeometricTransformUtil.transformGeometricArc(list);
+
+
+        List<DxfLine> dxfLineList = new ArrayList<>();;
+
+        for (GeometricArc geometricArc : geometricArcList) {
+            DxfLine dxfLine = new DxfLine();
+            dxfLine.setLayerName(geometricArc.getLayerName());
+            Double strat = geometricArc.getStartArc().doubleValue();
+            Double end = geometricArc.getEndArc().doubleValue();
+            if (strat > end) {
+                end = end + 360;
+            }
+
+            //编号从第一个点开始
+            Long num = 1L;
+            //圆心x
+            Double x = geometricArc.getX().doubleValue();
+            //圆心y
+            Double y = geometricArc.getY().doubleValue();
+            //圆心z
+            Double z = geometricArc.getZ().doubleValue();
+            //半径
+            Double r = geometricArc.getRadius().doubleValue();
+            //点集
+            List<DxfPoint> dxfPoints = new ArrayList<>();;
+            Double radius = strat;
+
+            //原点,编号为0
+            DxfPoint originPoint = new DxfPoint(0L, BigDecimal.valueOf(0), BigDecimal.valueOf(0), BigDecimal.valueOf(0));
+            dxfPoints.add(originPoint);
+
+            while (radius < end) {
+                Double arc = (Math.PI / 180) * radius;
+                Double x1 = x + r * (Math.cos(arc));
+                Double y1 = y + r * (Math.sin(arc));
+                DxfPoint point2 = new DxfPoint(num, BigDecimal.valueOf(x1), BigDecimal.valueOf(y1), BigDecimal.valueOf(z));
+                dxfPoints.add(point2);
+                radius = radius + 1;
+                num = num + 1L;
+            }
+            if (radius >= end) {
+                radius = radius - 1;
+                radius = radius + (end - radius);
+                Double arc2 = (Math.PI / 180) * radius;
+                Double x2 = x + r * (Math.cos(arc2));
+                Double y2 = y + r * (Math.sin(arc2));
+                DxfPoint point3 = new DxfPoint(num, BigDecimal.valueOf(x2), BigDecimal.valueOf(y2), BigDecimal.valueOf(z));
+                dxfPoints.add(point3);
+                num = num + 1L;
+            }
+            dxfLine.setDataPointList(dxfPoints);
+            dxfLineList.add(dxfLine);
+        }
+
+        return dxfLineList;
+    }
+
+    /**
+     * 将几何椭圆、转换为点椭圆数据
+     *
+     * @param list 需要转换的数据
+     * @return 返回点线数据
+     */
+    @Override
+    public List<DxfLine> ellipseTransform(List<GeometricModel> list) {
+        return null;
+    }
+
+    /**
+     * 将几何线、转换为点线数据
+     *
+     * @param list 需要转换的数据
+     * @return 返回点线数据
+     */
+    @Override
+    public List<DxfLine> lineTransform(List<GeometricModel> list) {
+
+        List<GeometricLine> geometricLineList = GeometricTransformUtil.transformGeometricLine(list);
+
+
+        List<DxfLine> dxfLineList = new ArrayList<>();;
+
+        for (GeometricLine geometricLine : geometricLineList) {
+            DxfLine dxfLine = new DxfLine();
+            dxfLine.setLayerName(geometricLine.getLayerName());
+            //点集
+            List<DxfPoint> dxfPoints = new ArrayList<>();;
+            //原点,编号为0
+            DxfPoint originPoint = new DxfPoint(0L, BigDecimal.valueOf(0), BigDecimal.valueOf(0), BigDecimal.valueOf(0));
+            //起点,编号为1
+            DxfPoint startPoint = new DxfPoint(1L, geometricLine.getStartX(), geometricLine.getStartY(), geometricLine.getStartZ());
+            //终点,编号为2
+            DxfPoint endPoint = new DxfPoint(2L, geometricLine.getEndX(), geometricLine.getEndY(), geometricLine.getEndZ());
+
+            dxfPoints.add(originPoint);
+            dxfPoints.add(startPoint);
+            dxfPoints.add(endPoint);
+            dxfLine.setDataPointList(dxfPoints);
+            dxfLineList.add(dxfLine);
+        }
+
+        return dxfLineList;
+    }
+
+    /**
+     * 将几何多线段、转换为点多线段数据
+     *
+     * @param list 需要转换的数据
+     * @return 返回点线数据
+     */
+    @Override
+    public List<DxfLine> polyLineTransform(List<GeometricModel> list) {
+        List<GeometricPolyLine> geometricPolyLineList = GeometricTransformUtil.transformGeometricPolyLine(list);
+        List<DxfLine> dxfLineList = new ArrayList<>();;
+
+        for (GeometricPolyLine geometricPolyLine : geometricPolyLineList) {
+            DxfLine dxfLine = new DxfLine();
+            dxfLine.setLayerName(geometricPolyLine.getLayerName());
+            //点集
+            List<DxfPoint> dxfPoints = new ArrayList<>();;
+            //原点,编号为0
+            DxfPoint originPoint = new DxfPoint(0L, BigDecimal.valueOf(0), BigDecimal.valueOf(0), BigDecimal.valueOf(0));
+            dxfPoints.add(originPoint);
+
+            //获取顶点集合
+            List<GeometricVertex> vertices = geometricPolyLine.getVertexList();
+            //顶点编号
+            Long number = 1L;
+
+            for (GeometricVertex geometricVertex : vertices) {
+                //解析顶点
+                DxfPoint vertex = new DxfPoint(number, geometricVertex.getX(), geometricVertex.getY(), geometricVertex.getZ());
+                number = number + 1L;
+                dxfPoints.add(vertex);
+            }
+            dxfLine.setDataPointList(dxfPoints);
+            dxfLineList.add(dxfLine);
+        }
+
+        return dxfLineList;
+    }
+
+
+    /**
+     * 将几何
+     * @param list 需要转换的数据
+     * @return
+     */
+    @Override
+    public List<DxfLine> textTransform(List<GeometricModel> list) {
+        List<GeometricText> geometricPointList = GeometricTransformUtil.transformGeometricText(list);
+        List<DxfLine> dxfLineList = new ArrayList<>();;
+
+        for (GeometricText text : geometricPointList) {
+            DxfLine dxfLine = new DxfLine();
+            dxfLine.setLayerName(text.getLayerName());
+            DxfPoint startPoint = new DxfPoint(1L, text);
+            DxfPoint endPoint = new DxfPoint(2L, text);
+            List<DxfPoint> dxfPoints = new ArrayList<>();;
+            dxfPoints.add(startPoint);
+            dxfPoints.add(endPoint);
+            dxfLine.setDataPointList(dxfPoints);
+            dxfLineList.add(dxfLine);
+        }
+        return dxfLineList;
+    }
+}

+ 52 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/transformation/impl/GeometricArcTransformImpl.java

@@ -0,0 +1,52 @@
+package com.fdkankan.dxf.parse.transformation.impl;
+
+import com.fdkankan.dxf.parse.model.GeometricModel;
+import com.fdkankan.dxf.parse.model.entities.GeometricArc;
+import com.fdkankan.dxf.parse.transformation.GeometricTransform;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class GeometricArcTransformImpl implements GeometricTransform<GeometricArc> {
+
+    /**
+     * 实例对象
+     */
+    private static GeometricTransform geometricTransform;
+
+
+    /**
+     * 采用单例模式
+     *
+     * @return 返回实例对象
+     */
+    public static GeometricTransform getSingleInstance() {
+        if (geometricTransform == null) {
+            synchronized (GeometricArcTransformImpl.class) {
+                if (geometricTransform == null) {
+                    geometricTransform = new GeometricArcTransformImpl();
+                }
+            }
+        }
+        return geometricTransform;
+    }
+
+    /**
+     * 转换几何弧线线段
+     *
+     * @param objectList 转换的数据
+     * @return 转换后的几何弧线线段
+     */
+    @Override
+    public List<GeometricArc> transform(List<GeometricModel> objectList) {
+        List<GeometricArc> arcList = new ArrayList<>();
+        if (!(objectList == null || objectList.isEmpty())) {
+            for (GeometricModel object : objectList) {
+                if (object instanceof GeometricArc) {
+                    arcList.add((GeometricArc) object);
+                }
+            }
+        }
+        return arcList;
+    }
+}

+ 53 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/transformation/impl/GeometricCircleTransformImpl.java

@@ -0,0 +1,53 @@
+package com.fdkankan.dxf.parse.transformation.impl;
+
+import com.fdkankan.dxf.parse.model.GeometricModel;
+import com.fdkankan.dxf.parse.model.entities.GeometricCircle;
+import com.fdkankan.dxf.parse.transformation.GeometricTransform;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class GeometricCircleTransformImpl implements GeometricTransform<GeometricCircle> {
+
+    /**
+     * 实例对象
+     */
+    private static GeometricTransform geometricTransform;
+
+
+    /**
+     * 采用单例模式
+     *
+     * @return 返回实例对象
+     */
+    public static GeometricTransform getSingleInstance() {
+        if (geometricTransform == null) {
+            synchronized (GeometricCircleTransformImpl.class) {
+                if (geometricTransform == null) {
+                    geometricTransform = new GeometricCircleTransformImpl();
+                }
+            }
+        }
+        return geometricTransform;
+    }
+
+
+    /**
+     * 转换几何圆
+     *
+     * @param objectList 转换的数据
+     * @return List
+     */
+    @Override
+    public List<GeometricCircle> transform(List<GeometricModel> objectList) {
+        List<GeometricCircle> circleList = new ArrayList<>();;
+        if (!(objectList == null || objectList.isEmpty())) {
+            for (GeometricModel object : objectList) {
+                if (object instanceof GeometricCircle) {
+                    circleList.add((GeometricCircle) object);
+                }
+            }
+        }
+        return circleList;
+    }
+}

+ 52 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/transformation/impl/GeometricLineTransformImpl.java

@@ -0,0 +1,52 @@
+package com.fdkankan.dxf.parse.transformation.impl;
+
+import com.fdkankan.dxf.parse.model.GeometricModel;
+import com.fdkankan.dxf.parse.model.entities.GeometricLine;
+import com.fdkankan.dxf.parse.transformation.GeometricTransform;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class GeometricLineTransformImpl implements GeometricTransform<GeometricLine> {
+
+    /**
+     * 实例对象
+     */
+    private static GeometricTransform geometricTransform;
+
+
+    /**
+     * 采用单例模式
+     *
+     * @return 返回实例对象
+     */
+    public static GeometricTransform getSingleInstance() {
+        if (geometricTransform == null) {
+            synchronized (GeometricLineTransformImpl.class) {
+                if (geometricTransform == null) {
+                    geometricTransform = new GeometricLineTransformImpl();
+                }
+            }
+        }
+        return geometricTransform;
+    }
+
+    /**
+     * 几何线的转换
+     *
+     * @param objectList 转换的数据
+     * @return List<GeometricLine>
+     */
+    @Override
+    public List<GeometricLine> transform(List<GeometricModel> objectList) {
+        List<GeometricLine> lineList = new ArrayList<>();;
+        if (!(objectList == null || objectList.isEmpty())) {
+            for (GeometricModel object : objectList) {
+                if (object instanceof GeometricLine) {
+                    lineList.add((GeometricLine) object);
+                }
+            }
+        }
+        return lineList;
+    }
+}

+ 52 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/transformation/impl/GeometricPointTransformImpl.java

@@ -0,0 +1,52 @@
+package com.fdkankan.dxf.parse.transformation.impl;
+
+import com.fdkankan.dxf.parse.model.GeometricModel;
+import com.fdkankan.dxf.parse.model.entities.GeometricPoint;
+import com.fdkankan.dxf.parse.transformation.GeometricTransform;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class GeometricPointTransformImpl implements GeometricTransform<GeometricPoint> {
+
+    /**
+     * 实例对象
+     */
+    private static GeometricTransform geometricTransform;
+
+
+    /**
+     * 采用单例模式
+     *
+     * @return 返回实例对象
+     */
+    public static GeometricTransform getSingleInstance() {
+        if (geometricTransform == null) {
+            synchronized (GeometricPointTransformImpl.class) {
+                if (geometricTransform == null) {
+                    geometricTransform = new GeometricPointTransformImpl();
+                }
+            }
+        }
+        return geometricTransform;
+    }
+
+    /**
+     * 几何点的转换
+     *
+     * @param objectList 转换的数据
+     * @return List<GeometricPoint>
+     */
+    @Override
+    public List<GeometricPoint> transform(List<GeometricModel> objectList) {
+        List<GeometricPoint> pointList = new ArrayList<>();;
+        if (!(objectList == null || objectList.isEmpty())) {
+            for (GeometricModel object : objectList) {
+                if (object instanceof GeometricPoint) {
+                    pointList.add((GeometricPoint) object);
+                }
+            }
+        }
+        return pointList;
+    }
+}

+ 51 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/transformation/impl/GeometricPolyLineTransformImpl.java

@@ -0,0 +1,51 @@
+package com.fdkankan.dxf.parse.transformation.impl;
+
+import com.fdkankan.dxf.parse.model.GeometricModel;
+import com.fdkankan.dxf.parse.model.entities.GeometricPolyLine;
+import com.fdkankan.dxf.parse.transformation.GeometricTransform;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class GeometricPolyLineTransformImpl implements GeometricTransform<GeometricPolyLine> {
+
+    /**
+     * 实例对象
+     */
+    private static GeometricTransform geometricTransform;
+
+    /**
+     * 采用单例模式
+     *
+     * @return 返回实例对象
+     */
+    public static GeometricTransform getSingleInstance() {
+        if (geometricTransform == null) {
+            synchronized (GeometricPolyLineTransformImpl.class) {
+                if (geometricTransform == null) {
+                    geometricTransform = new GeometricPolyLineTransformImpl();
+                }
+            }
+        }
+        return geometricTransform;
+    }
+
+    /**
+     * 几何多线段转换
+     *
+     * @param objectList 转换的数据
+     * @return List<GeometricPolyLine>
+     */
+    @Override
+    public List<GeometricPolyLine> transform(List<GeometricModel> objectList) {
+        List<GeometricPolyLine> polyLineList = new ArrayList<>();
+        if (!(objectList == null || objectList.isEmpty())) {
+            for (GeometricModel object : objectList) {
+                if (object instanceof GeometricPolyLine) {
+                    polyLineList.add((GeometricPolyLine) object);
+                }
+            }
+        }
+        return polyLineList;
+    }
+}

+ 52 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/transformation/impl/GeometricTextTransformImpl.java

@@ -0,0 +1,52 @@
+package com.fdkankan.dxf.parse.transformation.impl;
+
+import com.fdkankan.dxf.parse.model.GeometricModel;
+import com.fdkankan.dxf.parse.model.entities.GeometricText;
+import com.fdkankan.dxf.parse.transformation.GeometricTransform;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class GeometricTextTransformImpl implements GeometricTransform<GeometricText> {
+
+    /**
+     * 实例对象
+     */
+    private static GeometricTransform geometricTransform;
+
+
+    /**
+     * 采用单例模式
+     *
+     * @return 返回实例对象
+     */
+    public static GeometricTransform getSingleInstance() {
+        if (geometricTransform == null) {
+            synchronized (GeometricTextTransformImpl.class) {
+                if (geometricTransform == null) {
+                    geometricTransform = new GeometricTextTransformImpl();
+                }
+            }
+        }
+        return geometricTransform;
+    }
+
+    /**
+     * 几何点的转换
+     *
+     * @param objectList 转换的数据
+     * @return List<GeometricPoint>
+     */
+    @Override
+    public List<GeometricText> transform(List<GeometricModel> objectList) {
+        List<GeometricText> pointList = new ArrayList<>();;
+        if (!(objectList == null || objectList.isEmpty())) {
+            for (GeometricModel object : objectList) {
+                if (object instanceof GeometricText) {
+                    pointList.add((GeometricText) object);
+                }
+            }
+        }
+        return pointList;
+    }
+}

+ 0 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/transformation/model/DxfLine.java


Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.