Prechádzať zdrojové kódy

Merge remote-tracking branch 'origin/utils-dxf'

# Conflicts:
#	pom.xml
lyhzzz 10 mesiacov pred
rodič
commit
d99f37c5c9
91 zmenil súbory, kde vykonal 15840 pridanie a 0 odobranie
  1. 62 0
      4dkankan-utils-dxf/pom.xml
  2. 13 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/fdjson/vo/FdFloors.java
  3. 15 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/fdjson/vo/FdFloorsPanJson.java
  4. 28 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/fdjson/vo/FdPoints.java
  5. 18 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/fdjson/vo/FdWalls.java
  6. 405 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/DxfDocWriter.java
  7. 37 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/DxfGenSupport.java
  8. 22 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/Vector3.java
  9. 111 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/enums/LineWidthEnum.java
  10. 76 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/kml/CGCS2000ToWGS84.java
  11. 225 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/kml/GenerateKml.java
  12. 35 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/model/DxfArc.java
  13. 45 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/model/DxfCircle.java
  14. 68 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/model/DxfEllipse.java
  15. 39 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/model/DxfHatch.java
  16. 45 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/model/DxfLine.java
  17. 90 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/model/DxfLwPolyLine.java
  18. 46 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/model/DxfPoint.java
  19. 42 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/model/DxfRay.java
  20. 81 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/model/DxfSolid.java
  21. 100 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/model/DxfText.java
  22. 24 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/model/DxfXLine.java
  23. 94 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/model/base/BaseDxfEntity.java
  24. 298 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/model/base/Color.java
  25. 42 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/model/base/DxfEntity.java
  26. 33 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/model/support/DxfExtent.java
  27. 42 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/util/DxfLineBuilder.java
  28. 69 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/util/DxfUtil.java
  29. 29 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/util/FileUtil.java
  30. 90 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/util/FreemarkerSupport.java
  31. 127 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/util/PicAnalysis.java
  32. 63 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/util/StreamUtil.java
  33. 49 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/generate/util/StringUtil.java
  34. 60 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/ParseDXF.java
  35. 170 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/analysis/DxfAnalysis.java
  36. 796 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/analysis/DxfEntitiesParse.java
  37. 114 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/analysis/DxfHeaderParse.java
  38. 38 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/constant/EntityNameConstant.java
  39. 19 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/constant/PolyLineConstant.java
  40. 55 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/enums/CadVersionEnum.java
  41. 40 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/enums/DxfEntitiesBaseEnum.java
  42. 102 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/enums/DxfSystemEnum.java
  43. 67 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/enums/entities/ArcEnum.java
  44. 56 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/enums/entities/CircleEnum.java
  45. 77 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/enums/entities/EllipseEnum.java
  46. 44 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/enums/entities/InsertEnum.java
  47. 65 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/enums/entities/LineEnum.java
  48. 71 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/enums/entities/MTextEnum.java
  49. 49 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/enums/entities/PointEnum.java
  50. 99 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/enums/entities/PolyLineEnum.java
  51. 71 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/enums/entities/TextEnum.java
  52. 77 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/enums/error/DxfAnalysisErrorEnum.java
  53. 27 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/enums/error/DxfFileErrorEnum.java
  54. 40 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/exception/DxfAnalysisException.java
  55. 22 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/exception/DxfException.java
  56. 29 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/exception/DxfFileException.java
  57. 53 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/model/DxfModel.java
  58. 58 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/model/GeometricModel.java
  59. 57 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/model/entities/GeometricArc.java
  60. 45 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/model/entities/GeometricCircle.java
  61. 75 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/model/entities/GeometricLine.java
  62. 41 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/model/entities/GeometricPoint.java
  63. 56 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/model/entities/GeometricPolyLine.java
  64. 65 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/model/entities/GeometricText.java
  65. 43 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/model/entities/GeometricVertex.java
  66. 91 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/model/headers/HeaderModel.java
  67. 76 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/resolver/DxfResolver.java
  68. 145 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/resolver/impl/DxfResolverImpl.java
  69. 69 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/transformation/DxfLineTransformation.java
  70. 21 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/transformation/GeometricTransform.java
  71. 44 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/transformation/TransformBuilder.java
  72. 292 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/transformation/impl/DxfLineTransformationImpl.java
  73. 52 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/transformation/impl/GeometricArcTransformImpl.java
  74. 53 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/transformation/impl/GeometricCircleTransformImpl.java
  75. 52 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/transformation/impl/GeometricLineTransformImpl.java
  76. 52 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/transformation/impl/GeometricPointTransformImpl.java
  77. 51 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/transformation/impl/GeometricPolyLineTransformImpl.java
  78. 52 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/transformation/impl/GeometricTextTransformImpl.java
  79. 34 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/transformation/model/DxfLine.java
  80. 66 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/transformation/model/DxfPoint.java
  81. 44 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/utils/DateUtils.java
  82. 24 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/utils/DecimalCheckUtil.java
  83. 60 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/utils/DxfLineTransformUtil.java
  84. 134 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/utils/FdJsonToDxfUtil.java
  85. 86 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/utils/GeometricTransformUtil.java
  86. 78 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/utils/MTextStyleParse.java
  87. 22 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/utils/ParseFdJsonUtil.java
  88. 16 0
      4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/utils/WriteStringToFile.java
  89. 1277 0
      4dkankan-utils-dxf/src/main/resources/dxf/color.json
  90. 7704 0
      4dkankan-utils-dxf/src/main/resources/dxf/empty.dxf.ftl
  91. 1 0
      pom.xml

+ 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;
+    }
+}

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

@@ -0,0 +1,34 @@
+package com.fdkankan.dxf.parse.transformation.model;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Accessors(chain = true)
+public class DxfLine implements Serializable {
+
+    private static final long serialVersionUID = -8270659674597044220L;
+
+    /**
+     * 线编号
+     */
+    private Long lineNum;
+
+    /**
+     * 图层名
+     */
+    private String layerName;
+
+    /**
+     * 组成线的点
+     */
+    private List<DxfPoint> dataPointList;
+
+}

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

@@ -0,0 +1,66 @@
+package com.fdkankan.dxf.parse.transformation.model;
+
+import com.fdkankan.dxf.parse.model.entities.GeometricPoint;
+import com.fdkankan.dxf.parse.model.entities.GeometricText;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Accessors(chain = true)
+public class DxfPoint implements Serializable {
+
+    private static final long serialVersionUID = 496109316666003262L;
+
+    /**
+     * 点编号
+     */
+    private Long pointNum;
+
+    /**
+     * 点的x坐标
+     */
+    private BigDecimal x;
+
+    /**
+     * 点的y坐标
+     */
+    private BigDecimal y;
+
+    /**
+     * 点的z坐标
+     */
+    private BigDecimal z;
+
+
+    /**
+     * 将GeometricPoint转化成DxfPoint
+     *
+     * @param point
+     */
+    public DxfPoint(Long num, GeometricPoint point) {
+        this.pointNum = num;
+        this.x = point.getX();
+        this.y = point.getY();
+        this.z = point.getZ();
+    }
+
+    /**
+     * 将GeometricText转化成DxfPoint
+     *
+     * @param text
+     */
+    public DxfPoint(Long num, GeometricText text) {
+        this.pointNum = num;
+        this.x = text.getX();
+        this.y = text.getY();
+        this.z = text.getZ();
+    }
+
+}

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

@@ -0,0 +1,44 @@
+package com.fdkankan.dxf.parse.utils;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ * @AUTHOR ZhangJunJie
+ * @DATE 2023/11/25
+ * <p/>
+ * 概要:时间工具类
+ */
+public class DateUtils {
+
+    /**
+     * CAD 版本大于 2010 儒略日
+     */
+    public static final Double CAD_GREATER_THAN_2010_JULIAN_DAY = 2440587.5;
+    /**
+     * CAD 版本小于等于 2010 儒略日
+     */
+    public static final Double CAD_LESS_THAN_2010_JULIAN_DAY = 2415020.5;
+
+    /**
+     * @param dxfTime   dxf中的时间
+     * @param julianDay 儒略日(CAD中AutoCAD 2010 及更早版本基准儒略日更改为 2415020.5)
+     * @return
+     */
+    public static Date dxfTime2Date(String dxfTime, Double julianDay) {
+        double days = Double.parseDouble(dxfTime);
+        double milliseconds = (days - julianDay) * 86400000; // 转换为毫秒数
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        String dateString = sdf.format(new Date((long) milliseconds));
+
+        try {
+            Date date = sdf.parse(dateString);
+            return date;
+        } catch (ParseException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+}

+ 24 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/utils/DecimalCheckUtil.java

@@ -0,0 +1,24 @@
+package com.fdkankan.dxf.parse.utils;
+
+import java.util.Objects;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class DecimalCheckUtil {
+
+    /**
+     * 判断是否为数字
+     *
+     * @param checkStr
+     * @return
+     */
+    public static boolean check(String checkStr) {
+        if (checkStr != null && !Objects.equals("", checkStr)) {
+            String regExp = "^(-?\\d+)(\\.\\d+)?$";
+            Pattern pattern = Pattern.compile(regExp);
+            Matcher matcher = pattern.matcher(checkStr);
+            return matcher.matches();
+        }
+        return false;
+    }
+}

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

@@ -0,0 +1,60 @@
+package com.fdkankan.dxf.parse.utils;
+
+import com.fdkankan.dxf.parse.enums.entities.*;
+import com.fdkankan.dxf.parse.model.GeometricModel;
+import com.fdkankan.dxf.parse.transformation.DxfLineTransformation;
+import com.fdkankan.dxf.parse.transformation.impl.DxfLineTransformationImpl;
+import com.fdkankan.dxf.parse.transformation.model.DxfLine;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+public class DxfLineTransformUtil {
+
+    /**
+     * 具体的进行转换的实现类
+     */
+    private static DxfLineTransformation transformation = new DxfLineTransformationImpl();
+
+    /**
+     * 几何数据转换为点线数据
+     *
+     * @param map 需要转换的map数据
+     * @return 转换后的点线数据
+     */
+    public static List<DxfLine> geometricTransform(Map<String, List<GeometricModel>> map) {
+        List<DxfLine> dxfLineList = new ArrayList<>();
+
+        //将获取的几何数据转换为适配RTAS的点线数据
+        List<DxfLine> arcList = transformation.arcTransform(map.get(ArcEnum.ARC_NAME.getCode()));
+        List<DxfLine> circleList = transformation.circleTransform(map.get(CircleEnum.CIRCLE_NAME.getCode()));
+        List<DxfLine> lineList = transformation.lineTransform(map.get(LineEnum.LINE_NAME.getCode()));
+        List<DxfLine> pointList = transformation.pointTransform(map.get(PointEnum.POINT_NAME.getCode()));
+        List<DxfLine> polyLineList = transformation.polyLineTransform(map.get(PolyLineEnum.POLYLINE_NAME.getCode()));
+        List<DxfLine> textList = transformation.textTransform(map.get(TextEnum.TEXT_NAME.getCode()));
+
+        //将获取的数据添加到一个总的集合中
+        if (!(arcList == null || arcList.isEmpty())) {
+            dxfLineList.addAll(arcList);
+        }
+        if (!(circleList == null || circleList.isEmpty())) {
+            dxfLineList.addAll(circleList);
+        }
+        if (!(lineList == null || lineList.isEmpty())) {
+            dxfLineList.addAll(lineList);
+        }
+        if (!(pointList == null || pointList.isEmpty())) {
+            dxfLineList.addAll(pointList);
+        }
+        if (!(polyLineList == null || polyLineList.isEmpty())) {
+            dxfLineList.addAll(polyLineList);
+        }
+        if (!(textList == null || textList.isEmpty())) {
+            dxfLineList.addAll(textList);
+        }
+        return dxfLineList;
+    }
+
+
+}

+ 134 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/utils/FdJsonToDxfUtil.java

@@ -0,0 +1,134 @@
+package com.fdkankan.dxf.parse.utils;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.fdkankan.dxf.fdjson.vo.FdFloors;
+import com.fdkankan.dxf.fdjson.vo.FdFloorsPanJson;
+import com.fdkankan.dxf.fdjson.vo.FdPoints;
+import com.fdkankan.dxf.fdjson.vo.FdWalls;
+import com.fdkankan.dxf.generate.DxfDocWriter;
+import com.fdkankan.dxf.generate.Vector3;
+import com.fdkankan.dxf.generate.model.DxfLine;
+import com.fdkankan.dxf.generate.model.base.Color;
+import com.fdkankan.dxf.parse.ParseDXF;
+import com.fdkankan.dxf.parse.model.entities.GeometricLine;
+import com.fdkankan.dxf.parse.resolver.DxfResolver;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+
+public class FdJsonToDxfUtil {
+
+    /**
+     * floorplan_user.json 转 dxf
+     * @param fdJsonPath floorplan_user.json 路径
+     * @param dxfPath   dxf生成路径
+     */
+    public static void fdJsonToDxf(String fdJsonPath,String dxfPath)  {
+        try {
+            String msg = new String(Files.readAllBytes(Paths.get(fdJsonPath)));
+            JSONObject jsonObject = JSONObject.parseObject(msg);
+            JSONArray floors = jsonObject.getJSONArray("floors");
+            for (Object obj : floors) {
+                JSONObject floor = (JSONObject) (obj);
+                plantWall(dxfPath,floor);
+            }
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+
+    }
+
+    /**
+     * 墙,根据起始点画线
+     */
+    private static void plantWall(String filePath, JSONObject fools) {
+        HashMap<String, FdPoints> wallMap= new HashMap<>();
+
+        JSONObject walls = fools.getJSONObject("walls");
+        JSONObject points = fools.getJSONObject("points");
+        for (String key : points.keySet()) {
+            JSONObject obj = points.getJSONObject(key);
+            FdPoints point = new FdPoints(obj.getDouble("x") * 100, obj.getDouble("y") * 100);
+            wallMap.put(key,point);
+        }
+        DxfDocWriter dxfDocWriter = new DxfDocWriter();
+        for (String key : walls.keySet()) {
+            JSONObject wall = walls.getJSONObject(key);
+            String start = wall.getString("start");
+            String end = wall.getString("end");
+            drawLinePoint(filePath,wallMap.get(start),wallMap.get(end),dxfDocWriter);
+        }
+        dxfDocWriter.save(filePath, true);
+    }
+
+    public static void drawLinePoint(String filePath,FdPoints point,FdPoints point2,DxfDocWriter dxfDocWriter){
+
+        DxfLine dxfLine = new DxfLine();
+        dxfLine.setStartPoint(new Vector3(point.getX(), point.getY(), 0));
+        dxfLine.setEndPoint(new Vector3(point2.getX(), point2.getY(), 0));
+        dxfLine.setColor(Color.GREEN);
+        dxfDocWriter.addEntity(dxfLine);
+
+
+    }
+
+
+
+
+    /**
+     * dxf 转 floorplan_user.json
+     * @param dxfPath   dxf生成路径
+     * @param jsonPath floorplan_user.json 路径
+     */
+    public static String dxfToFdJson(String dxfPath,String jsonPath){
+        try {
+            FdFloorsPanJson fdFloorsPanJson = new FdFloorsPanJson();
+            FdFloors fdFloors = new FdFloors();
+            JSONObject walls = fdFloors.getWalls();
+            JSONObject points = fdFloors.getPoints();
+            fdFloorsPanJson.getFloors().add(fdFloors);
+
+            DxfResolver build = ParseDXF.build(dxfPath);
+            List<GeometricLine> geometricLineList = build.getGeometricLineList();
+            writeFdLine(geometricLineList,points,walls);
+            String jsonString = JSONObject.toJSONString(fdFloorsPanJson);
+            WriteStringToFile.writeFile(jsonString,jsonPath);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        return null;
+    }
+
+    private static void writeFdLine(List<GeometricLine> geometricLineList,JSONObject points,JSONObject walls) {
+        HashSet<String> pointSet = new HashSet<>();
+        HashMap<String,String> pointMap = new HashMap<>();
+        for (GeometricLine geometricLine : geometricLineList) {
+            pointSet.add(geometricLine.getStartX() + "," + geometricLine.getStartY());
+            pointSet.add(geometricLine.getEndX() + "," + geometricLine.getEndY());
+        }
+        int pointIndex = 0;
+        for (String xy : pointSet) {
+            FdPoints fdPoints = new FdPoints();
+            fdPoints.setX(Double.valueOf(xy.split(",")[0])/100);
+            fdPoints.setY(Double.valueOf(xy.split(",")[1])/100);
+            points.put("point"+pointIndex,fdPoints);
+            pointMap.put(xy,"point"+pointIndex);
+            pointIndex ++;
+        }
+        Integer wallIndex = 0;
+        for (GeometricLine geometricLine : geometricLineList) {
+            FdWalls fdWalls = new FdWalls();
+            String pointNameStart = pointMap.get(geometricLine.getStartX() + "," + geometricLine.getStartY());
+            String pointNameEnd = pointMap.get(geometricLine.getEndX() + "," + geometricLine.getEndY());
+            fdWalls.setStart(pointNameStart);
+            fdWalls.setEnd(pointNameEnd);
+            walls.put("wall"+wallIndex,fdWalls);
+            wallIndex ++;
+        }
+    }
+}

+ 86 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/utils/GeometricTransformUtil.java

@@ -0,0 +1,86 @@
+package com.fdkankan.dxf.parse.utils;
+
+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.transformation.GeometricTransform;
+import com.fdkankan.dxf.parse.transformation.TransformBuilder;
+
+import java.util.List;
+
+/**
+ * @Author ytzjj
+ * @DateTime 2023/11/27 13:40
+ * @Description
+ */
+public class GeometricTransformUtil {
+
+
+    /**
+     * 转换GeometricObject为GeometricPoint
+     *
+     * @param objectList 需要转换的GeometricObject数据
+     * @return 转换GeometricPoint
+     */
+    public static List<GeometricPoint> transformGeometricPoint(List<GeometricModel> objectList) {
+        GeometricTransform geometricTransform = TransformBuilder.builder(EntityNameConstant.POINT_NAME);
+        return geometricTransform.transform(objectList);
+    }
+
+
+    /**
+     * 转换GeometricObject为GeometricLine
+     *
+     * @param objectList 需要转换的GeometricObject数据
+     * @return 转换GeometricLine
+     */
+    public static List<GeometricLine> transformGeometricLine(List<GeometricModel> objectList) {
+        GeometricTransform geometricTransform = TransformBuilder.builder(EntityNameConstant.LINE_NAME);
+        return geometricTransform.transform(objectList);
+    }
+
+    /**
+     * 转换GeometricObject为GeometricArc
+     *
+     * @param objectList 需要转换的GeometricObject数据
+     * @return 转换GeometricArc
+     */
+    public static List<GeometricArc> transformGeometricArc(List<GeometricModel> objectList) {
+        GeometricTransform geometricTransform = TransformBuilder.builder(EntityNameConstant.ARC_NAME);
+        return geometricTransform.transform(objectList);
+    }
+
+    /**
+     * 转换GeometricObject为GeometricCircle
+     *
+     * @param objectList 需要转换的GeometricObject数据
+     * @return 转换GeometricCircle
+     */
+    public static List<GeometricCircle> transformGeometricCircle(List<GeometricModel> objectList) {
+        GeometricTransform geometricTransform = TransformBuilder.builder(EntityNameConstant.CIRCLE_NAME);
+        return geometricTransform.transform(objectList);
+    }
+
+
+    /**
+     * 转换GeometricObject为GeometricPolyLine
+     *
+     * @param objectList 需要转换的GeometricObject数据
+     * @return 转换GeometricPolyLine
+     */
+    public static List<GeometricPolyLine> transformGeometricPolyLine(List<GeometricModel> objectList) {
+        GeometricTransform geometricTransform = TransformBuilder.builder(EntityNameConstant.POLY_LINE_NAME);
+        return geometricTransform.transform(objectList);
+    }
+
+    /**
+     * 转换GeometricObject为GeometricText
+     *
+     * @param objectList 需要转换的GeometricObject数据
+     * @return 转换GeometricText
+     */
+    public static List<GeometricText> transformGeometricText(List<GeometricModel> objectList) {
+        GeometricTransform geometricTransform = TransformBuilder.builder(EntityNameConstant.TEXT_NAME);
+        return geometricTransform.transform(objectList);
+    }
+}

+ 78 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/utils/MTextStyleParse.java

@@ -0,0 +1,78 @@
+package com.fdkankan.dxf.parse.utils;
+
+import com.fdkankan.dxf.generate.util.StreamUtil;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.JSONReader;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * @Author ytzjj
+ * @DateTime 2023/11/24 10:05
+ * @Description 多文本样式解析
+ */
+public class MTextStyleParse {
+
+    /**
+     * cad默认颜色ACI编码
+     */
+    private static final String DEFAULT_COLOR_ACI_CODE = "7";
+
+    /**
+     * cad默认颜色与16进制颜色转换文件
+     */
+    private static final String DEFAULT_COLOR_JSON_FILE_PATH = "dxf/color.json";
+
+    /**
+     * CAD颜色列表
+     */
+    private static JSONArray colorReflection = null;
+
+
+    static {
+        try (
+                InputStream resourceStream = StreamUtil.getResourceStream(DEFAULT_COLOR_JSON_FILE_PATH);
+                JSONReader reader = new JSONReader(new InputStreamReader(resourceStream, StandardCharsets.UTF_8));
+        ) {
+            colorReflection = reader.readObject(JSONArray.class);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+
+    /**
+     * 解析CAD ACI色号为16进制颜色标识
+     *
+     * @param cadCode
+     * @return
+     */
+    public static String parseCadColorToHexColorCode(String cadCode) {
+        String defaultHexColor = "";
+        for (int i = 0; i < colorReflection.size(); i++) {
+            JSONObject json = colorReflection.getJSONObject(i);
+            if (json.getString("code").equals(cadCode)) {
+                defaultHexColor = json.getString("color");
+                if (defaultHexColor.startsWith("#")) {
+                    defaultHexColor = defaultHexColor.substring(1);
+                }
+                // 添加透明度信息,默认为不透明(FF)
+                defaultHexColor = (defaultHexColor + "FF").toUpperCase();
+            } else if (json.getString("code").equals(DEFAULT_COLOR_ACI_CODE)) {
+                defaultHexColor = json.getString("color");
+                if (defaultHexColor.startsWith("#")) {
+                    defaultHexColor = defaultHexColor.substring(1);
+                }
+                // 添加透明度信息,默认为不透明(FF)
+                defaultHexColor = (defaultHexColor + "FF").toUpperCase();
+            }
+        }
+        return defaultHexColor;
+    }
+
+
+}

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

@@ -0,0 +1,22 @@
+package com.fdkankan.dxf.parse.utils;
+
+import com.alibaba.fastjson.JSONObject;
+import com.fdkankan.dxf.fdjson.vo.FdFloors;
+import com.fdkankan.dxf.fdjson.vo.FdFloorsPanJson;
+import com.fdkankan.dxf.fdjson.vo.FdPoints;
+import com.fdkankan.dxf.fdjson.vo.FdWalls;
+import com.fdkankan.dxf.parse.ParseDXF;
+import com.fdkankan.dxf.parse.model.entities.GeometricLine;
+import com.fdkankan.dxf.parse.resolver.DxfResolver;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+
+public class ParseFdJsonUtil {
+
+
+
+
+}

+ 16 - 0
4dkankan-utils-dxf/src/main/java/com/fdkankan/dxf/parse/utils/WriteStringToFile.java

@@ -0,0 +1,16 @@
+package com.fdkankan.dxf.parse.utils;
+import java.io.BufferedWriter;
+import java.io.FileWriter;
+import java.io.IOException;
+
+public class WriteStringToFile {
+
+    public static void writeFile(String content,String path ){
+        try (BufferedWriter writer = new BufferedWriter(new FileWriter(path))) {
+            writer.write(content);
+        } catch (IOException e) {
+            System.out.println("An error occurred while writing to the file: " + e.getMessage());
+            e.printStackTrace();
+        }
+    }
+}

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 1277 - 0
4dkankan-utils-dxf/src/main/resources/dxf/color.json


Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 7704 - 0
4dkankan-utils-dxf/src/main/resources/dxf/empty.dxf.ftl


+ 1 - 0
pom.xml

@@ -32,6 +32,7 @@
         <module>4dkankan-utils-reg</module>
         <module>4dkankan-utils-filestorage</module>
         <module>4dkankan-utils-disruptormq</module>
+        <module>4dkankan-utils-dxf</module>
         <module>4dkankan-utils-geo-query</module>
     </modules>