# NanoDXF
**Repository Path**: selfspring/nano-dxf
## Basic Information
- **Project Name**: NanoDXF
- **Description**: NanoDXF是一个专注于DXF文件格式解析与生成的开源项目,提供简洁高效的API,支持多种CAD应用开发。
- **Primary Language**: Java
- **License**: MulanPSL-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 7
- **Created**: 2026-07-17
- **Last Updated**: 2026-07-17
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# NanoDXF
**轻量级 DXF 文件解析库,面向 GIS / 测绘场景。**
纯 Java 实现,无第三方 CAD 依赖,支持 GBK / UTF-8 自动编码检测,输出 JTS 几何对象与 GeoJSON。
---
## 特性
- **全主流实体解析**:LINE / ARC / CIRCLE / ELLIPSE / POINT / TEXT / MTEXT / LWPOLYLINE / POLYLINE / SPLINE / HATCH / INSERT / 3DFACE / SOLID / DIMENSION / LEADER / MULTILEADER / ATTDEF
- **OCS/WCS 坐标变换**:自动应用任意轴算法(Arbitrary Axis Algorithm),正确还原三维/旋转实体坐标(v1.6.0)
- **INSERT 块递归展开**:仿射变换(缩放 → 旋转 → 平移)、路径集合循环引用检测
- **国内测绘软件适配**:CASS / EPS / MapMatrix / MapGIS / SuperMap XDATA 地物编码提取,内置约 80 条 GB/T 20257 映射
- **BYLAYER 颜色继承**:ACI 256 色表 → 图层颜色 → 实体颜色完整链路
- **编码自适应**:UTF-8 BOM → juniversalchardet 检测 → 版本号推断 → GBK 兜底
- **容错解析**:截断文件、损坏实体、未知实体类型均不中断,错误分级收集(FATAL / WARN / INFO)
- **解析过滤**:`includeLayers` / `excludeLayers` / `includeTypes`,大文件按需跳过无关图层(v1.6.0)
- **多格式输出**:GeoJSON、Shapefile(2D/3D)、GeoPackage、**SVG**(v1.6.0,零依赖矢量预览)
- **DXF 写出**:16 种实体类型 + 块定义,R12 / R2007 双路径,浩辰 CAD / AutoCAD 验证通过
- **流式解析 API**:`parseStream(Path)` 两阶段惰性流,大文件低内存占用
- **测绘专项 API**:`ContourHelper`(等高线分组/验证)、`ElevationAnnotation`(高程点注记配对)(v1.6.0)
- **拓扑检查 API**:`TopologyChecker` 5 条规则(重复实体/自相交/零长度/悬挂端点/等高线交叉),零额外依赖(v1.6.0)
- **拓扑修复 API**:`TopologyFixer` 自动去重/去零长/端点吸附(v1.7.0)
- **多边形重建**:`PolygonBuilder` LinearRing→Polygon,JTS Polygonizer 孔洞识别(v1.7.0)
- **几何简化**:`GeomSimplifier` 顶点抽稀(拓扑保持 / Douglas-Peucker)(v1.7.0)
- **图层统计**:`LayerStats` 按图层汇总实体数/总长/总面积,支持单位换算(v1.7.0)
- **点云 CSV 输出**:`CsvWriter` 灵活字段配置,RFC 4180 引号转义(v1.7.0)
- **DEM 构建 + ASCII Grid 输出**:`DemBuilder` Delaunay TIN 插值,`AscGridWriter` ESRI .asc 格式(v1.7.0)
- **坡度/坡向分析**:`SlopeAnalyzer` Horn's method 3×3 邻域有限差分(v1.7.0)
- **图幅接边检查**:`SheetEdgeMatcher` 线状要素端点竖直/水平/任意方向接边检查(v1.7.0)
---
## 快速开始
### Maven 依赖
```xml
io.github.z-double
nano-dxf
1.7.0
```
### 最简用法
```java
import com.nanodxf.CADParser;
import com.nanodxf.ParseResult;
import com.nanodxf.entity.CADEntity;
// 解析文件(自动检测 GBK / UTF-8 编码)
ParseResult result = new CADParser().parse(Paths.get("drawing.dxf"));
// 遍历实体
for (CADEntity entity : result.getEntities()) {
System.out.println(entity.getType() + " 图层=" + entity.getLayer());
System.out.println(" 几何=" + entity.geometry());
}
// 查看错误与统计
result.getErrors().forEach(System.err::println);
System.out.println(result.getStats());
```
### 带配置解析
```java
ParseConfig config = ParseConfig.builder()
.crs("EPSG:4545") // CGCS2000 / 3度带 117°E
.arcTolerance(0.001) // 弧线离散精度(米)
.coordinateDecimalPlaces(4)// 坐标小数位数
.build();
ParseResult result = new CADParser(config).parse(Paths.get("drawing.dxf"));
```
### 输出 GeoJSON
```java
GeoJsonSerializer ser = new GeoJsonSerializer(result.getMetadata());
String geojson = ser.serialize(result.getEntities(), result.getMetadata());
Files.writeString(Paths.get("output.geojson"), geojson);
```
---
## API 概览
### CADParser
| 方法 | 说明 |
|---|---|
| `parse(Path path)` | 解析 DXF 文件(自动编码检测) |
| `parse(Reader reader)` | 从 Reader 解析(单元测试常用) |
### ParseConfig(Builder 模式)
| 参数 | 默认值 | 说明 |
|---|---|---|
| `crs` | null | 坐标参考系标识(如 `EPSG:4545`) |
| `arcTolerance` | 0.01 | 弧线/样条离散弦高误差(坐标单位) |
| `coordinateDecimalPlaces` | 4 | GeoJSON 坐标小数位数(0~15) |
### ParseResult
| 方法 | 返回值 | 说明 |
|---|---|---|
| `getEntities()` | `List` | 模型空间实体(已展开 INSERT)|
| `getErrors()` | `List` | 分级错误列表 |
| `getStats()` | `ParseStats` | 耗时、实体数、错误数 |
| `getMetadata()` | `DrawingMetadata` | 版本、单位、CRS 等图纸元数据 |
### CADEntity
```java
entity.getType() // "LINE" / "ARC" / "INSERT" 等
entity.getLayer() // 图层名
entity.getHandle() // DXF handle(唯一标识)
entity.geometry() // JTS Geometry(Point/LineString/Polygon 等)
entity.getProperties() // Map,含颜色、文字、地物编码等附加属性
```
常见属性键:
| 键 | 类型 | 说明 |
|---|---|---|
| `colorRgb` | `int[3]` | RGB 颜色(True Color > ACI > BYLAYER 继承) |
| `colorAci` | `Integer` | ACI 颜色号(仅显式指定时存在) |
| `text` | `String` | TEXT / MTEXT 清洗后的文字内容 |
| `elevation` | `Double` | LWPOLYLINE / POINT 高程(Z 值) |
| `featureCode` | `String` | 地物编码(来自 CASS / EPS 等 XDATA) |
| `featureType` | `String` | 地物名称(GB/T 20257 映射,如"普通房屋") |
| `featureCategory` | `String` | 地物分类(如"建筑") |
| `blockName` | `String` | INSERT 引用的块名 |
| `xdata` | `Map` | 原始 XDATA(所有应用名) |
---
## DXF 输出
### 快速写出
```java
import com.nanodxf.output.DXFWriter;
import com.nanodxf.output.DXFWriteConfig;
import com.nanodxf.model.DXFVersion;
import com.nanodxf.entity.CADEntity;
List entities = List.of(
CADEntity.builder(CADEntity.Types.LINE)
.layer("道路")
.geometry(GF.createLineString(new Coordinate[]{
new Coordinate(0, 0), new Coordinate(100, 0)}))
.property(EntityProperty.COLOR_ACI, AciColor.WHITE)
.build()
);
// R2007 + GBK(推荐,兼容浩辰 CAD / AutoCAD)
DXFWriteConfig config = DXFWriteConfig.builder()
.version(DXFVersion.R2007)
.encoding("GBK") // 含中文图层名时必须指定
.coordinateDecimalPlaces(4)
.build();
new DXFWriter(config).write(entities, Paths.get("output.dxf"));
```
### 流式解析(大文件内存友好)
```java
// parseStream 两阶段:预解析 BLOCKS → 惰性流出 ENTITIES
// 必须在 try-with-resources 中使用(流持有文件句柄)
try (Stream stream = new CADParser().parseStream(Paths.get("large.dxf"))) {
stream.filter(e -> CADEntity.Types.LWPOLYLINE.equals(e.getType()))
.limit(10_000)
.forEach(myProcessor::accept);
}
```
### Shapefile 输出
```java
import com.nanodxf.output.ShapefileWriter;
import com.nanodxf.output.ShapefileWriteConfig;
ShapefileWriteConfig cfg = ShapefileWriteConfig.builder()
.crs("EPSG:4545") // 写入 .prj WKT(v1.4.0:内置 EPSG:4326/4490/4534–4554/32644–32654)
.encoding("GBK") // DBF 属性文件编码
.coordinateDecimalPlaces(4) // ELEVATION 字段小数位(影响 DBF 字段宽度)
// .dimension(ShapefileWriteConfig.ShapeDimension.AUTO) // 默认:有 Z 自动写 PointZ/PolylineZ/PolygonZ
.build();
// 输出:output.shp + output.shx + output.dbf + output.prj
new ShapefileWriter(cfg).write(result.getEntities(), Paths.get("output.shp"));
```
### 写出 ARC / CIRCLE / HATCH / INSERT / ELLIPSE / SOLID / 3DFACE / SPLINE
```java
// ARC:圆心 Point + radius/startAngle/endAngle 属性
entities.add(CADEntity.builder(CADEntity.Types.ARC)
.layer("弧形")
.geometry(GF.createPoint(new Coordinate(50, 50)))
.property(EntityProperty.RADIUS, 25.0)
.property(EntityProperty.START_ANGLE, 0.0)
.property(EntityProperty.END_ANGLE, 270.0)
.build());
// CIRCLE:圆心 Point + radius 属性
entities.add(CADEntity.builder(CADEntity.Types.CIRCLE)
.layer("圆形")
.geometry(GF.createPoint(new Coordinate(150, 50)))
.property(EntityProperty.RADIUS, 30.0)
.build());
// HATCH SOLID:Polygon 几何(支持洞)
entities.add(CADEntity.builder(CADEntity.Types.HATCH)
.layer("填充")
.geometry(polygon)
.property(EntityProperty.COLOR_ACI, AciColor.GREEN)
.build());
// 块定义 + INSERT
CADBlock symbol = new CADBlock("ARROW");
symbol.setInsertionPoint(0, 0, 0);
symbol.addEntity(CADEntity.builder(CADEntity.Types.LINE)
.layer("0").geometry(lineGeom).build());
entities.add(CADEntity.builder(CADEntity.Types.INSERT)
.layer("符号")
.geometry(GF.createPoint(new Coordinate(100, 100)))
.property(EntityProperty.BLOCK_NAME, "ARROW")
.property(EntityProperty.SCALE_X, 2.0)
.build());
// 写出时传入块定义列表
new DXFWriter(config).write(List.of(symbol), entities, Paths.get("output.dxf"));
// ELLIPSE:圆心 Point + 长轴向量 + 轴比(v1.3.0)
entities.add(CADEntity.builder(CADEntity.Types.ELLIPSE)
.layer("椭圆")
.geometry(GF.createPoint(new Coordinate(200, 100)))
.property(EntityProperty.MAJOR_AXIS_X, 50.0)
.property(EntityProperty.MAJOR_AXIS_Y, 0.0)
.property(EntityProperty.AXIS_RATIO, 0.5) // 短轴/长轴
.property(EntityProperty.START_ANGLE, 0.0) // 弧度
.property(EntityProperty.END_ANGLE, 2 * Math.PI)
.build());
// SOLID:4 顶点 Polygon(v1.3.0)
entities.add(CADEntity.builder(CADEntity.Types.SOLID)
.layer("实体")
.geometry(solidPolygon) // 外环前 4 顶点将写为 SOLID
.build());
// SPLINE:带控制点的样条曲线(v1.3.0)
List ctrlPts = List.of(
new double[]{0, 0, 0}, new double[]{10, 20, 0},
new double[]{30, 15, 0}, new double[]{40, 0, 0});
entities.add(CADEntity.builder(CADEntity.Types.SPLINE)
.layer("样条")
.geometry(GF.createLineString(/* discretized coords */))
.property(EntityProperty.CONTROL_POINTS, ctrlPts)
.build());
```
### DXFWriteConfig 参数
| 参数 | 默认值 | 说明 |
|---|---|---|
| `version` | `R2007` | 输出版本(`R12` 或 `R2007`) |
| `encoding` | 自动 | R2007+ 默认 UTF-8,其他默认 GBK;含中文内容建议显式指定 GBK |
| `coordinateDecimalPlaces` | `4` | 坐标小数位数(0~15) |
### 支持输出的实体类型
| 类型(`CADEntity.Types.*`) | 输入几何 | 输出实体 |
|---|---|---|
| `LINE` | `LineString`(2 点) | LINE |
| `LWPOLYLINE` | `LineString`(多点)/ `LinearRing` | LWPOLYLINE |
| `LWPOLYLINE` | `Polygon` | 外环 + 各洞,每个 LWPOLYLINE |
| `POINT` | `Point` | POINT |
| `TEXT` | `Point` | TEXT(需 `text` 属性) |
| `MTEXT` | `Point` | MTEXT(需 `text` 属性) |
| `ARC` | `Point`(圆心) | ARC(需 `radius`/`startAngle`/`endAngle` 属性)|
| `CIRCLE` | `Point`(圆心) | CIRCLE(需 `radius` 属性)|
| `HATCH` | `Polygon`/`MultiPolygon` | HATCH(SOLID 填充,支持洞)|
| `INSERT` | `Point`(插入点) | INSERT(需 `blockName` 属性)|
| `ELLIPSE` | `Point`(圆心) | ELLIPSE(R2007)/ 72 段 POLYLINE 折线近似(R12,v1.3.1)|
| `SOLID` | `Polygon` / `LinearRing`(4 顶点) | SOLID(v1.3.0)|
| `FACE3D` | `LinearRing` / `Polygon`(3~4 顶点) | 3DFACE(v1.3.0)|
| `SPLINE` | `LineString` + `controlPoints` 属性 | SPLINE(R2007)/ POLYLINE 折线(R12,v1.3.1)|
| 任意 | `GeometryCollection` | 递归展开子几何 |
### 支持的实体属性(写出)
| 属性键 | 类型 | 作用 |
|---|---|---|
| `colorAci` | `Integer` | ACI 颜色号(同时写入图层颜色) |
| `colorRgb` | `int[3]` | True Color(仅 R2004+,code 420) |
| `text` | `String` | TEXT / MTEXT 文字内容 |
| `height` | `Double` | 文字高度(默认 2.5) |
| `rotation` | `Double` | 文字旋转角度(度,默认 0) |
| `style` | `String` | TEXT 文字样式(默认 "Standard") |
| `radius` | `Double` | ARC / CIRCLE 半径 |
| `startAngle` | `Double` | ARC 起始角(度)|
| `endAngle` | `Double` | ARC 终止角(度)|
| `hatchPattern` | `String` | HATCH 图案名(默认 `"SOLID"`)|
| `blockName` | `String` | INSERT 引用的块名 |
| `scaleX`/`scaleY`/`scaleZ` | `Double` | INSERT 缩放因子(默认 1.0)|
| `lineType` | `String` | 图层线型名(默认 `"Continuous"`)|
| `lineWeight` | `Integer` | 图层线宽码(默认 -3=ByLayer)|
| `xdata` | `Map` | XDATA 写出(地物编码保留)|
| `majorAxisX`/`majorAxisY` | `Double` | ELLIPSE 长轴端点向量(v1.3.0)|
| `axisRatio` | `Double` | ELLIPSE 短轴/长轴比(v1.3.0)|
| `controlPoints` | `List` | SPLINE 控制点(v1.3.0)|
### 格式版本对比
| | R12 | R2007 |
|---|---|---|
| 子类标记(`100 AcDbXxx`) | ✗ | ✅ |
| owner handle(`330`) | ✗ | ✅ |
| BLOCKS / OBJECTS 段 | ✗ | ✅ |
| True Color(code 420) | ✗ | ✅(R2004+) |
| 浩辰 CAD 兼容 | ✅ | ✅ |
| AutoCAD 2020+ 兼容 | ✅ | ✅ |
| QGIS / LibreCAD 兼容 | ✅ | ✅ |
### 实体类型常量
`CADEntity.Types` 提供所有 DXF 实体类型的字符串常量,避免硬编码魔法字符串:
```java
// 解析侧
if (CADEntity.Types.LINE.equals(entity.getType())) { ... }
result.getEntities().stream()
.filter(e -> CADEntity.Types.LWPOLYLINE.equals(e.getType()))
.forEach(...);
// 写出侧
CADEntity.builder(CADEntity.Types.LWPOLYLINE).layer("建筑").geometry(ring).build();
```
常量列表:`LINE` / `ARC` / `CIRCLE` / `ELLIPSE` / `POINT` / `LWPOLYLINE` / `POLYLINE` / `VERTEX` / `SPLINE` / `TEXT` / `MTEXT` / `ATTRIB` / `HATCH` / `SOLID` / `FACE3D`(值 `"3DFACE"`)/ `INSERT` / `BLOCK` / `ENDBLK` / `SEQEND` / `DIMENSION` / `LEADER` / `VIEWPORT`
### 其他常量类
| 类 | 用途 | 典型常量 |
|---|---|---|
| `AciColor` | ACI 颜色码 | `RED=1` / `WHITE=7` / `BYLAYER=256` / `ORANGE=30` |
| `EntityProperty` | 实体属性键字符串 | `COLOR_ACI` / `TEXT` / `ELEVATION` / `FEATURE_CODE` |
| `InsUnit` | `$INSUNITS` 单位码 | `METERS=6` / `MILLIMETERS=4` / `FEET=2` |
| `output.LineTypeName` | 标准线型名 | `CONTINUOUS` / `DASHED` / `CENTER` / `HIDDEN` |
```java
// EntityProperty 消除属性键魔法字符串
String text = (String) entity.getProperties().get(EntityProperty.TEXT);
Double elev = (Double) entity.getProperties().get(EntityProperty.ELEVATION);
// InsUnit 单位换算
double meters = InsUnit.toMeters(coord, result.getMetadata().getInsUnits());
// 写出时组合使用
CADEntity.builder(CADEntity.Types.TEXT)
.layer("注记")
.property(EntityProperty.TEXT, "高程点 H=25.3")
.property(EntityProperty.HEIGHT, 2.5)
.property(EntityProperty.COLOR_ACI, AciColor.WHITE)
.build();
```
---
## 支持的 DXF 版本
### 解析(读入)
| 版本字符串 | AutoCAD 版本 | 支持状态 |
|---|---|---|
| AC1009 | R12 | ✅ |
| AC1015 | R2000 | ✅ |
| AC1018 | R2004 | ✅ |
| AC1021 | R2007 | ✅ |
| AC1024+ | R2010~R2018 | ✅ |
### 写出(生成)
| 版本 | 说明 | 推荐场景 |
|---|---|---|
| R12(AC1009) | 最简兼容格式,无子类标记 | 跨软件通用,文件最小 |
| R2007(AC1021) | 完整格式,通过浩辰CAD验证 | 国内 CAD 软件(浩辰、中望等) |
---
## 依赖
| 依赖 | 版本 | 用途 |
|---|---|---|
| `org.locationtech.jts:jts-core` | 1.19.0 | JTS 几何库 |
| `com.googlecode.juniversalchardet:juniversalchardet` | 1.0.3 | 编码自动检测 |
运行时无其他依赖。需要 Java 17+。
---
## 构建
```bash
mvn clean package
mvn test
```
---
## 许可证
Apache License 2.0