ofs-dxf-ts 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/API.md +411 -0
- package/CHANGELOG.md +26 -0
- package/LICENSE +21 -0
- package/README.md +119 -0
- package/dist/core/dxf-builder.d.ts +348 -0
- package/dist/core/dxf-builder.js +549 -0
- package/dist/core/dxf-document.d.ts +220 -0
- package/dist/core/dxf-document.js +529 -0
- package/dist/core/dxf-entities.d.ts +327 -0
- package/dist/core/dxf-entities.js +22 -0
- package/dist/core/dxf-serializer.d.ts +48 -0
- package/dist/core/dxf-serializer.js +595 -0
- package/dist/core/hatch-patterns.d.ts +15 -0
- package/dist/core/hatch-patterns.js +214 -0
- package/dist/core/modelspace.d.ts +106 -0
- package/dist/core/modelspace.js +351 -0
- package/dist/geometry/math.utils.d.ts +8 -0
- package/dist/geometry/math.utils.js +43 -0
- package/dist/geometry/offset.utils.d.ts +32 -0
- package/dist/geometry/offset.utils.js +87 -0
- package/dist/geometry/polyline.utils.d.ts +10 -0
- package/dist/geometry/polyline.utils.js +63 -0
- package/dist/geometry/text.utils.d.ts +15 -0
- package/dist/geometry/text.utils.js +28 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.js +29 -0
- package/dist/parser/auto-cad-color-index.d.ts +8 -0
- package/dist/parser/auto-cad-color-index.js +265 -0
- package/dist/parser/dim-style-codes.d.ts +5 -0
- package/dist/parser/dim-style-codes.js +32 -0
- package/dist/parser/dxf-parser.d.ts +16 -0
- package/dist/parser/dxf-parser.js +824 -0
- package/dist/parser/entities/3dface.d.ts +5 -0
- package/dist/parser/entities/3dface.js +76 -0
- package/dist/parser/entities/arc.d.ts +5 -0
- package/dist/parser/entities/arc.js +34 -0
- package/dist/parser/entities/attdef.d.ts +5 -0
- package/dist/parser/entities/attdef.js +86 -0
- package/dist/parser/entities/attribute.d.ts +5 -0
- package/dist/parser/entities/attribute.js +106 -0
- package/dist/parser/entities/circle.d.ts +5 -0
- package/dist/parser/entities/circle.js +40 -0
- package/dist/parser/entities/dimension.d.ts +5 -0
- package/dist/parser/entities/dimension.js +65 -0
- package/dist/parser/entities/ellipse.d.ts +5 -0
- package/dist/parser/entities/ellipse.js +42 -0
- package/dist/parser/entities/hatch.d.ts +5 -0
- package/dist/parser/entities/hatch.js +321 -0
- package/dist/parser/entities/insert.d.ts +5 -0
- package/dist/parser/entities/insert.js +52 -0
- package/dist/parser/entities/line.d.ts +5 -0
- package/dist/parser/entities/line.js +30 -0
- package/dist/parser/entities/lwpolyline.d.ts +5 -0
- package/dist/parser/entities/lwpolyline.js +101 -0
- package/dist/parser/entities/mtext.d.ts +5 -0
- package/dist/parser/entities/mtext.js +54 -0
- package/dist/parser/entities/point.d.ts +5 -0
- package/dist/parser/entities/point.js +30 -0
- package/dist/parser/entities/polyline.d.ts +5 -0
- package/dist/parser/entities/polyline.js +85 -0
- package/dist/parser/entities/solid.d.ts +5 -0
- package/dist/parser/entities/solid.js +35 -0
- package/dist/parser/entities/spline.d.ts +5 -0
- package/dist/parser/entities/spline.js +69 -0
- package/dist/parser/entities/text.d.ts +5 -0
- package/dist/parser/entities/text.js +47 -0
- package/dist/parser/entities/vertex.d.ts +5 -0
- package/dist/parser/entities/vertex.js +59 -0
- package/dist/parser/extended-data-parser.d.ts +18 -0
- package/dist/parser/extended-data-parser.js +100 -0
- package/dist/parser/index.d.ts +10 -0
- package/dist/parser/index.js +9 -0
- package/dist/parser/log.d.ts +14 -0
- package/dist/parser/log.js +39 -0
- package/dist/parser/parse-helpers.d.ts +23 -0
- package/dist/parser/parse-helpers.js +128 -0
- package/dist/parser/scanner.d.ts +29 -0
- package/dist/parser/scanner.js +143 -0
- package/dist/parser/types.d.ts +78 -0
- package/dist/parser/types.js +5 -0
- package/dist/symbols/slope-symbol.d.ts +21 -0
- package/dist/symbols/slope-symbol.js +81 -0
- package/dist/symbols/structures.d.ts +9 -0
- package/dist/symbols/structures.js +120 -0
- package/dist/template/blank-document.d.ts +13 -0
- package/dist/template/blank-document.js +13 -0
- package/dist/template/block-registry.d.ts +16 -0
- package/dist/template/block-registry.js +135 -0
- package/dist/template/index.d.ts +17 -0
- package/dist/template/index.js +17 -0
- package/dist/template/template-injector.d.ts +45 -0
- package/dist/template/template-injector.js +487 -0
- package/dist/template/template-reader.d.ts +28 -0
- package/dist/template/template-reader.js +80 -0
- package/dist/types/index.d.ts +24 -0
- package/dist/types/index.js +8 -0
- package/package.json +59 -0
package/API.md
ADDED
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
# คู่มือการใช้งาน (API Reference)
|
|
2
|
+
|
|
3
|
+
`ofs-dxf-ts` — ไลบรารี TypeScript บริสุทธิ์ (pure, API-agnostic, browser-first) สำหรับสร้างไฟล์ DXF จาก coordinate / label / options ทั่วไป โดยจะวาดบน DXF template หรือสร้างจากศูนย์ก็ได้ ทำงานได้ทั้ง **Node.js** และ **Browser/Angular**
|
|
4
|
+
|
|
5
|
+
> เอกสารนี้อิงตาม public API ที่ export จากแพ็กเกจ (`import { ... } from 'ofs-dxf-ts'`) — type declaration ทั้งหมดมากับแพ็กเกจแล้ว
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 1. เริ่มต้นใช้งาน (Quick Start)
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
import { DxfBuilder } from 'ofs-dxf-ts';
|
|
13
|
+
// หรือระหว่างพัฒนาในโปรเจกต์นี้: import { DxfBuilder } from './src';
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
### สร้างจากศูนย์ (ไม่มี template)
|
|
17
|
+
|
|
18
|
+
```typescript
|
|
19
|
+
const builder = new DxfBuilder();
|
|
20
|
+
|
|
21
|
+
builder.addPolyline([[0, 0], [100, 50], [200, 0]], 'CANAL', 1);
|
|
22
|
+
builder.addCircle(50, 50, 25, 'CANAL', 3);
|
|
23
|
+
builder.addText('KM 0+500', 10, 10, 2.5, 0, 'TEXT', 7);
|
|
24
|
+
|
|
25
|
+
const dxf = builder.saveString();
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
ไฟล์ที่ได้เป็น DXF R2018 (AC1032) หน่วยเมตร โครงสร้างครบ (CLASSES, BLOCK_RECORD, OBJECTS, layouts) เพราะสร้างบนเอกสารเปล่าที่ฝังใน lib — จึงใช้ block, image และ layout ได้เหมือนโหมด template
|
|
29
|
+
|
|
30
|
+
### สร้างบน DXF template
|
|
31
|
+
|
|
32
|
+
| Environment | วิธีโหลด template |
|
|
33
|
+
|-------------|------------------|
|
|
34
|
+
| **Node.js** | `new DxfBuilder('/path/to/template.dxf')` |
|
|
35
|
+
| **Browser/Angular** | `DxfBuilder.fromString(dxfText)` — โหลดผ่าน `HttpClient` แล้วส่ง text เข้ามา |
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
// Node.js
|
|
39
|
+
const builder = new DxfBuilder('./template2018.dxf');
|
|
40
|
+
|
|
41
|
+
// Browser/Angular (เช่นใน service)
|
|
42
|
+
const dxfText = await firstValueFrom(http.get('assets/template2018.dxf', { responseType: 'text' }));
|
|
43
|
+
const builder = DxfBuilder.fromString(dxfText);
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
ทุก section ของ template ถูกคงไว้ตามลำดับเดิม ส่วนที่เพิ่มใหม่ (layer, linetype, style, block, image, layout) จะถูกแทรกเข้าไป — ถ้าชื่อซ้ำกับของเดิมใน template จะใช้ของเดิม (ยกเว้น block / layout ที่ซ้ำจะ `throw`)
|
|
47
|
+
|
|
48
|
+
> ⚠️ ต้องเป็น template DXF R2000 ขึ้นไป (มี BLOCK_RECORD table และ OBJECTS section) จึงจะใช้ block definition, image และ layout ได้ ไฟล์แบบ R12 ยังเพิ่ม layer / entity ได้ตามปกติ
|
|
49
|
+
|
|
50
|
+
### บันทึก / ส่งออก
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
builder.saveString(); // → string (ทุก environment)
|
|
54
|
+
builder.saveas('out.dxf'); // เขียนไฟล์ (Node.js เท่านั้น)
|
|
55
|
+
builder.downloadAs('out.dxf'); // trigger download (Browser เท่านั้น)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
`saveString()` เรียกซ้ำได้และให้ผลเหมือนเดิมทุกครั้ง
|
|
59
|
+
|
|
60
|
+
> ℹ️ `saveas()` / `DxfDocument.readFile()` ใช้ `fs` ของ Node ผ่าน `process.getBuiltinModule` จึงต้องใช้ **Node.js ≥ 20.16** ถ้ารันบน runtime อื่น (browser, worker, Node เก่ากว่านั้น) ให้ใช้ `saveString()` แล้วเขียนไฟล์เอง — แพ็กเกจนี้เป็น ESM อย่างเดียว
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## 2. `DxfBuilder` — API หลัก
|
|
65
|
+
|
|
66
|
+
ทุก method ที่รับ `layer` จะสร้าง layer อัตโนมัติถ้ายังไม่มี (สี 7, `CONTINUOUS`)
|
|
67
|
+
|
|
68
|
+
### การสร้าง / เข้าถึงภายใน
|
|
69
|
+
|
|
70
|
+
| Member | คำอธิบาย |
|
|
71
|
+
|--------|----------|
|
|
72
|
+
| `new DxfBuilder(template?: string \| DxfDocument)` | สร้างใหม่, โหลดจากไฟล์ (Node) หรือห่อ `DxfDocument` ที่มีอยู่ |
|
|
73
|
+
| `static DxfBuilder.fromString(content)` | โหลด template จาก DXF string |
|
|
74
|
+
| `get doc: DxfDocument` | เข้าถึง document |
|
|
75
|
+
| `get msp: Modelspace` | ปลายทางการวาด **ปัจจุบัน** (model space, layout ใน `onLayout`, หรือ block ใน `defineBlock`) สำหรับเรียก API สไตล์ ezdxf เช่น `builder.msp.add_text(...)` |
|
|
76
|
+
|
|
77
|
+
### Geometry
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
addLine(start, end, layer?='0', color?, linetype?)
|
|
81
|
+
addPolyline(points, layer?='0', color?, linetype?, closed?=false) // LWPOLYLINE; รับ [x,y] หรือ [x,y,z]
|
|
82
|
+
addCircle(cx, cy, radius, layer?='0', color?)
|
|
83
|
+
addArc(cx, cy, radius, startAngleDeg, endAngleDeg, layer?='0', color?)
|
|
84
|
+
addEllipse(cx, cy, majorAxisX, majorAxisY, ratio, layer?='0', color?) // ratio = minor/major (0..1)
|
|
85
|
+
addPoint(x, y, layer?='0', color?)
|
|
86
|
+
addSpline(controlPoints, degree?=3, layer?='0', color?)
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Text
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
addText(text, x, y, height?=2, rotationDeg?=0, layer?='TEXT', color?=7)
|
|
93
|
+
addMText(text, x, y, width?=100, height?=2.5, layer?='TEXT', color?) // "\n" = ขึ้นบรรทัดใหม่
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
ต้องการ text style หรือการจัดตำแหน่ง (alignment) ให้ใช้ `builder.msp.add_text(text, { height, style, rotation, layer }).set_placement([x, y], TextEntityAlignment.BOTTOM_CENTER)`
|
|
97
|
+
|
|
98
|
+
### Resources: linetype / text style / layer
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
addLayer(name, color?=7, linetype?='CONTINUOUS')
|
|
102
|
+
addLineType(name, description, pattern) // pattern หน่วยเดียวกับแบบ: + เส้น, − ช่องว่าง, 0 จุด
|
|
103
|
+
addTextStyle(name, font, height?) // เช่น addTextStyle('THAI', 'THSarabunNew.ttf')
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
builder.addLineType('BOUNDARY', '____ . ____', [40, -10, 0, -10]);
|
|
108
|
+
builder.addLayer('ขอบเขตพื้นที่รับประโยชน์', 6, 'BOUNDARY');
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Block
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
defineBlock(name, draw: (b: DxfBuilder) => void, basePoint?=[0,0])
|
|
115
|
+
addBlock(name, x, y, scale, rotationDeg, layer?='0', attributes?={})
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
- `defineBlock` — ทุกคำสั่งใน callback วาดลง block definition (พิกัดเทียบ `basePoint`) วาด entity บน layer `'0'` สีไม่ระบุ เพื่อให้ INSERT รับสี/layer ของตัวที่วาง
|
|
119
|
+
- `addBlock` — ลำดับการ resolve: **block ใน template หรือที่ `defineBlock` ไว้** → INSERT, **block ใน `BLOCK_REGISTRY`** → วาดแยกเป็นเส้น, ไม่พบ → ข้อความ `[Block:name]`
|
|
120
|
+
- `attributes` ถูกวาดเป็นข้อความธรรมดาข้าง block (ยังไม่รองรับ ATTRIB)
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
builder.defineBlock('BM', b => {
|
|
124
|
+
b.addPolyline([[-1, -1], [1, -1], [1, 1], [-1, 1]], '0', undefined, undefined, true);
|
|
125
|
+
b.addHatch('SOLID', [[[0, 0], [1, 0], [1, 1], [0, 1]]], '0');
|
|
126
|
+
});
|
|
127
|
+
builder.addBlock('BM', 519395.838, 1034018.584, 20, 0, 'SYMBOL');
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Hatch
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
addHatch(patternName, boundaries, layer?='0', color?, opts?)
|
|
134
|
+
// patternName: 'SOLID' | ชื่อลายใน HATCH_PATTERNS | ชื่อใดก็ได้ถ้าส่ง opts.patternLines
|
|
135
|
+
// boundaries : [x,y][][] — รูปที่อยู่ในรูปอื่นกลายเป็นรู (odd parity)
|
|
136
|
+
// opts : { scale?, angle?, patternLines? }
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
- ลายในตัวเป็นหน่วย ISO (มม.) — `scale` คูณเข้ากับลาย เช่นแบบเป็นเมตรที่พิมพ์ 1:12,500 ลาย `DOTS` ใช้ `scale ≈ 8`
|
|
140
|
+
- ลายในตัว: `ANGLE, ANSI31–ANSI38, AR-CONC, AR-SAND, BOX, BRICK, CROSS, DASH, DOTS, EARTH, GRASS, GRATE, GRAVEL, HEX, HONEY, INSUL, LINE, NET, NET3, PLAST, SQUARE, STARS, SWAMP, TRIANG, ZIGZAG`
|
|
141
|
+
- ชื่อที่ไม่รู้จักโดยไม่มี `patternLines` จะ `throw`
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
builder.addHatch('SOLID', [[[0,0],[100,0],[100,100],[0,100]]], 'WATER', 5);
|
|
145
|
+
builder.addHatch('ANSI31', [outer, hole], 'AREA', 7, { scale: 10, angle: 45 });
|
|
146
|
+
|
|
147
|
+
// ลายกำหนดเอง: [angleDeg, [baseX, baseY], [offsetX, offsetY], dashes]
|
|
148
|
+
builder.addHatch('MY_DOTS', [outline], 'AREA', 3, { patternLines: [[0, [0, 0], [2, 2], [0, -2]]] });
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Raster image
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
addImage(imagePath, pixelSize, insertion, worldSize, layer?='0', opts?: ImageOptions)
|
|
155
|
+
// pixelSize : [กว้าง, สูง] หน่วย pixel (DXF อ่านไฟล์ภาพเองไม่ได้)
|
|
156
|
+
// insertion : มุมล่างซ้ายของภาพ (หน่วยแบบ)
|
|
157
|
+
// worldSize : [กว้าง, สูง] หน่วยแบบ
|
|
158
|
+
// opts : { rotation?, clip?: [x,y][], brightness?, contrast?, fade? }
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
DXF เก็บเพียง **การอ้างอิงไฟล์** — วางไฟล์ภาพไว้ข้าง `.dxf` (ใช้ชื่อไฟล์) หรือใช้ absolute path; ถ้าหาไฟล์ไม่เจอ CAD จะแสดงเพียงกรอบ `clip` ใช้พิกัดโลก
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
builder.addImage('topo_4927II.jpg', [7087, 7087], [513000, 1027000], [15000, 15000], 'RASTER', { fade: 40 });
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Annotation: callout และตาราง
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
170
|
+
addCallout(anchor, text: string | string[], boxAt, opts?: CalloutOptions): [minX, minY, maxX, maxY]
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
วาดกรอบข้อความ (มุมบนซ้ายที่ `boxAt`) และเส้นชี้จาก `anchor` ไปยังจุดกึ่งกลางขอบกล่องที่ใกล้ที่สุด คืนค่าขอบเขตกล่อง
|
|
174
|
+
|
|
175
|
+
| `CalloutOptions` | ค่าปริยาย | คำอธิบาย |
|
|
176
|
+
|---|---|---|
|
|
177
|
+
| `layer`, `color`, `textColor`, `boxColor`, `style` | `'TEXT'` | |
|
|
178
|
+
| `textHeight` | `2.5` | ความสูงตัวอักษร (หน่วยแบบ) |
|
|
179
|
+
| `lineSpacing` | `1.6` | ระยะบรรทัด × ความสูงตัวอักษร |
|
|
180
|
+
| `padding` | `0.8 × textHeight` | |
|
|
181
|
+
| `boxWidth` | ประมาณจากข้อความ | กำหนดความกว้างเอง |
|
|
182
|
+
| `widthFactor` | `0.75` | ความกว้างเฉลี่ยตัวอักษร / ความสูง (ฟอนต์ไทย ≈ 0.6–0.7) |
|
|
183
|
+
| `align` | `'left'` | `'left' \| 'center'` |
|
|
184
|
+
| `arrow`, `arrowSize` | `'none'` | `'none' \| 'dot' \| 'arrow'` |
|
|
185
|
+
|
|
186
|
+
```typescript
|
|
187
|
+
addTable(position, columnWidths, rowHeight, rows, layer?='0', textHeight?=2.5, opts?)
|
|
188
|
+
// rows : TableCellDef[][] — { text, colSpan?, rowSpan?, alignment?, color?, style? }
|
|
189
|
+
// opts : { headerColor?, gridColor?, textColor?, rowHeights? }
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
การรวมเซลล์ใช้กติกาแบบ HTML table: เซลล์ที่ span จะกินตำแหน่งทางขวา/ด้านล่าง และเซลล์ถัดไปจะข้ามตำแหน่งที่ถูกกินไปแล้ว ตารางถูกวาดเป็น LINE + TEXT (ไม่ใช่ ACAD_TABLE)
|
|
193
|
+
|
|
194
|
+
```typescript
|
|
195
|
+
builder.addTable([650, 300], [14, 26, 42, 42, 22], 7, [
|
|
196
|
+
[{ text: 'ลำดับ', rowSpan: 2 }, { text: 'หมุด', rowSpan: 2 }, { text: 'พิกัด', colSpan: 2 }, { text: 'ค่าระดับ', rowSpan: 2 }],
|
|
197
|
+
[{ text: 'North' }, { text: 'East' }],
|
|
198
|
+
[{ text: '1' }, { text: 'BM.07' }, { text: '1,034,018.584' }, { text: '519,395.838' }, { text: '4.622' }],
|
|
199
|
+
], 'TABLE', 3);
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
อื่น ๆ:
|
|
203
|
+
|
|
204
|
+
```typescript
|
|
205
|
+
addDimension(point1, point2, dimLinePosition, layer?='DIM', color?, text?)
|
|
206
|
+
addLeader(vertices, layer?='0', color?, hasArrowhead?=true)
|
|
207
|
+
addMLeader(vertices, text, textPosition, layer?, color?, opts?) // ⚠️ deprecated → วาดด้วย addCallout
|
|
208
|
+
addLineFromObject(onfarmLine, layer?='structure') // วาด OnfarmLine (ดูหัวข้อ 4)
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Paper space layout
|
|
212
|
+
|
|
213
|
+
```typescript
|
|
214
|
+
addLayout(name, paperWidth, paperHeight, margins?=[10,10,10,10], viewports?: LayoutViewportDef[])
|
|
215
|
+
onLayout(name, draw: (b: DxfBuilder) => void)
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
- หน่วยกระดาษเป็น **มม.** จุดกำเนิดพิกัดอยู่ที่มุมล่างซ้ายของพื้นที่พิมพ์ (ขอบใน margin) ตามแบบ AutoCAD — ใช้ `margins: [0,0,0,0]` ถ้าต้องการให้ตรงกับมุมกระดาษ
|
|
219
|
+
- `onLayout` — ทุกคำสั่งใน callback วาดลง paper space ใช้ได้ทั้ง layout ของ template (`'Layout1'`) และที่สร้างด้วย `addLayout`; ชื่อ `'Model'` = model space; ชื่อที่ไม่มีจะ `throw`
|
|
220
|
+
|
|
221
|
+
| `LayoutViewportDef` | คำอธิบาย |
|
|
222
|
+
|---|---|
|
|
223
|
+
| `center`, `width`, `height` | ตำแหน่ง/ขนาดบนกระดาษ (มม.) |
|
|
224
|
+
| `viewCenter` | จุดกึ่งกลางที่มองใน model space |
|
|
225
|
+
| `viewHeight?` | ความสูงที่มองเห็นใน model space — ถ้าไม่ระบุคำนวณจาก `scale` |
|
|
226
|
+
| `scale?` | ตัวหารมาตราส่วน เช่น `12500` = 1:12,500 → `viewHeight = height × scale × unitFactor` |
|
|
227
|
+
| `unitFactor?` | หน่วย model ต่อ 1 มม. กระดาษที่ 1:1 — ค่าปริยาย `0.001` (model เป็นเมตร) |
|
|
228
|
+
| `frozenLayers?` | layer ที่ซ่อนเฉพาะ viewport นี้ |
|
|
229
|
+
| `locked?` | ล็อก viewport ไม่ให้ zoom/pan เปลี่ยนมาตราส่วน |
|
|
230
|
+
|
|
231
|
+
```typescript
|
|
232
|
+
builder.addLayout('BM-A1', 841, 594, [0, 0, 0, 0], [
|
|
233
|
+
{ center: [330, 330], width: 600, height: 440, viewCenter: [519000, 1033500], scale: 12500, locked: true },
|
|
234
|
+
]);
|
|
235
|
+
builder.onLayout('BM-A1', s => s.addText('แผนที่แสดงตำแหน่งหมุดหลักฐาน', 250, 70, 9, 0, 'SHEET'));
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### View / Zoom
|
|
239
|
+
|
|
240
|
+
```typescript
|
|
241
|
+
zoomExtents(padding?=0) // auto-fit entity ใน model space ($EXTMIN/$EXTMAX/$VIEWCTR/$VIEWSIZE)
|
|
242
|
+
zoomWindow(minX, minY, maxX, maxY)
|
|
243
|
+
setExtents(minX, minY, maxX, maxY)
|
|
244
|
+
setViewCenter(x, y, viewHeight?)
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### Layer control
|
|
248
|
+
|
|
249
|
+
```typescript
|
|
250
|
+
setLayerColor(name, color)
|
|
251
|
+
setLayerLinetype(name, linetype)
|
|
252
|
+
freezeLayer(name) / thawLayer(name) // ซ่อน + ไม่ plot + เลือกไม่ได้
|
|
253
|
+
lockLayer(name) / unlockLayer(name) // เห็นแต่แก้ไม่ได้
|
|
254
|
+
setLayerOff(name) / setLayerOn(name) // ซ่อนแต่ยังเลือกได้
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
> ⚠️ คำสั่งเหล่านี้มีผลกับ layer ที่สร้างใหม่เท่านั้น — layer ที่มีอยู่แล้วใน template ถูกเขียนออกตามเดิม
|
|
258
|
+
|
|
259
|
+
### GeoReference
|
|
260
|
+
|
|
261
|
+
```typescript
|
|
262
|
+
builder.setGeoReference({
|
|
263
|
+
crsId: 'EPSG:32647', // UTM Zone 47N
|
|
264
|
+
designPoint: [0, 0],
|
|
265
|
+
referencePoint: [600000, 1700000],
|
|
266
|
+
northDirection: 0,
|
|
267
|
+
scaleFactor: 1,
|
|
268
|
+
coordinateType: 2,
|
|
269
|
+
});
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
> ⚠️ ปัจจุบันเขียน `$INSUNITS`, `$UCSORG` (= `referencePoint`) และ `$ANGBASE` ลง HEADER — `$UCSORG` อาจทำให้ CAD แสดงพิกัดสัมพัทธ์กับจุดนั้น ถ้าแบบวาดด้วยพิกัด UTM จริงอยู่แล้วไม่จำเป็นต้องเรียก
|
|
273
|
+
|
|
274
|
+
---
|
|
275
|
+
|
|
276
|
+
## 3. `DxfDocument` และ `Modelspace` (ระดับล่าง)
|
|
277
|
+
|
|
278
|
+
```typescript
|
|
279
|
+
DxfDocument.create() // เอกสารเปล่า R2018
|
|
280
|
+
DxfDocument.fromString(dxfText) // จาก template string
|
|
281
|
+
DxfDocument.readFile(path) // Node.js
|
|
282
|
+
|
|
283
|
+
doc.modelspace(): Modelspace
|
|
284
|
+
doc.paperspace(layoutName): Modelspace // collector ของ layout
|
|
285
|
+
doc.addLayer / addLineType / addTextStyle
|
|
286
|
+
doc.addBlockDefinition(name, entities: DxfEntity[], basePoint?)
|
|
287
|
+
doc.addLayout(layoutDef)
|
|
288
|
+
doc.layoutNames / hasLayout(name) / hasBlock(name) / getBlockNames()
|
|
289
|
+
doc.setHeaderVar(name, [{ code, value }]) // แทนค่าเดิมใน HEADER
|
|
290
|
+
doc.toDxfString() / saveas(path) / downloadAs(filename)
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
`Modelspace` เป็นตัวเก็บ entity แบบ ezdxf (`add_line`, `add_lwpolyline`, `add_text(...).set_placement(...)`, `add_hatch`, `add_image`, `add_table`, `add_viewport`, `add_blockref` …) ใช้ทั้งกับ model space, layout และ block
|
|
294
|
+
|
|
295
|
+
```typescript
|
|
296
|
+
const doc = DxfDocument.create();
|
|
297
|
+
doc.modelspace().add_text('ศูนย์กลาง', { height: 3, style: 'THAI', layer: 'NOTE' })
|
|
298
|
+
.set_placement([50, 50], TextEntityAlignment.MIDDLE_CENTER);
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
|
|
303
|
+
## 4. ตัวสร้างสัญลักษณ์ (Symbol generators)
|
|
304
|
+
|
|
305
|
+
ฟังก์ชันบริสุทธิ์ — **คืนค่า geometry ไม่วาดเอง**
|
|
306
|
+
|
|
307
|
+
### อาคารคลอง → `Record<string, OnfarmLine>`
|
|
308
|
+
|
|
309
|
+
```typescript
|
|
310
|
+
objCheck(xyCord, kmUS)
|
|
311
|
+
objCheckDrop(xyCord, kmUS)
|
|
312
|
+
objChangeSlopeStructure(xyCord, kmUS)
|
|
313
|
+
objFlume(xyCord, kmUS, kmDS, centerline)
|
|
314
|
+
objSiphon(xyCord, kmUS, kmDS, centerline)
|
|
315
|
+
objCulvert(xyCord, kmUS, kmDS, roadLength)
|
|
316
|
+
objCheckCulvert(xyCord, kmUS, kmDS, roadLength)
|
|
317
|
+
objCheckDropCulvert(xyCord, kmUS, kmDS, roadLength)
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
```typescript
|
|
321
|
+
const struc = objCheck([[0, 0], [1000, 0]], 500);
|
|
322
|
+
for (const key in struc) builder.addLineFromObject(struc[key]);
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
### สัญลักษณ์ลาด/สันคันนา → segments
|
|
326
|
+
|
|
327
|
+
```typescript
|
|
328
|
+
slopeSymbolSegments(line, interval, side, halfLen, size): [Coordinate, Coordinate][]
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
```typescript
|
|
332
|
+
const segs = slopeSymbolSegments(ridgeLine, 20, 'L', 2, 4);
|
|
333
|
+
for (const [start, end] of segs) builder.addLine(start, end, 'SLOPE_SYMBOL', 8);
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
---
|
|
337
|
+
|
|
338
|
+
## 5. ยูทิลิตี้ (Geometry / Text)
|
|
339
|
+
|
|
340
|
+
```typescript
|
|
341
|
+
// math.utils
|
|
342
|
+
formatDistance(distance) // 1500 → 'KM 1+500'
|
|
343
|
+
calculateDistance(p1, p2)
|
|
344
|
+
calculateAzimuth(x1, y1, x2, y2) // วัดจากแกน Y ตามเข็ม 0..360
|
|
345
|
+
rotatePoint(x, y, angleDeg, shiftX, shiftY)
|
|
346
|
+
rotatePointAzimuth(x, y, azimuthDeg, shiftX, shiftY)
|
|
347
|
+
isPointInBounds(x, y, xmin, ymin, xmax, ymax)
|
|
348
|
+
snapBound(value, step, direction?='down')
|
|
349
|
+
|
|
350
|
+
// polyline.utils
|
|
351
|
+
kmPointPolyline(points, targetDistance) // → { point, az }
|
|
352
|
+
dividePolylineWithDistance(coords, segmentLength=100) // → { points, distances, angles }
|
|
353
|
+
|
|
354
|
+
// offset.utils (ระนาบ หน่วยเดียวกับแบบ — UTM เมตร)
|
|
355
|
+
getLineOffset(points, offsetDistance=1, opts?) // → { left, right } เส้นขนานสองข้าง z=0 (เช่นขอบคลอง)
|
|
356
|
+
offsetPolyline(points, distance, opts?) // ข้างเดียว: distance บวก = ซ้ายของทิศทางเส้น, ลบ = ขวา
|
|
357
|
+
// opts: { closed?, miterLimit?=4 }
|
|
358
|
+
// มุมต่อกันที่จุดตัด (miter); มุมแหลมที่จุดตัดไกลเกิน miterLimit × distance จะถูกตัดมุม (bevel)
|
|
359
|
+
// จุดซ้ำติดกันถูกข้าม; เส้นที่จุดแรก = จุดสุดท้ายถือเป็นวงปิด
|
|
360
|
+
|
|
361
|
+
// text.utils (DXF ไม่มีข้อมูลฟอนต์ — เป็นค่าประมาณ)
|
|
362
|
+
visibleCharCount(text) // ไม่นับสระ/วรรณยุกต์ไทยที่อยู่บน/ล่าง
|
|
363
|
+
estimateTextWidth(text, height, widthFactor?=0.75)
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
---
|
|
367
|
+
|
|
368
|
+
## 6. ชนิดข้อมูล (Types)
|
|
369
|
+
|
|
370
|
+
```typescript
|
|
371
|
+
type Coordinate = [number, number];
|
|
372
|
+
type Coordinate3D = [number, number, number];
|
|
373
|
+
|
|
374
|
+
interface OnfarmLine { coordinate: Coordinate3D[]; type: string; width: number; color: number }
|
|
375
|
+
|
|
376
|
+
type HatchPatternLine = [angleDeg, [baseX, baseY], [offsetX, offsetY], dashes[]];
|
|
377
|
+
const HATCH_PATTERNS: Record<string, HatchPatternLine[]>;
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
ยัง export: `CalloutOptions`, `ImageOptions`, ชนิดจาก `core/dxf-entities` (`DxfEntity`, `TableCellDef`, `LayoutDef`, `LayoutViewportDef`, `GeoReferenceDef`, `TextEntityAlignment` …), template handling (`readTemplate`, `serializeDocument`, `listLayoutNames`, `BLOCK_REGISTRY`) และ parser (หัวข้อ 7) — `serializeWithTemplate` ยังมีอยู่แต่ deprecated
|
|
381
|
+
|
|
382
|
+
---
|
|
383
|
+
|
|
384
|
+
## 7. DXF Parser ในตัว
|
|
385
|
+
|
|
386
|
+
TypeScript port ของ `dxf-parser` (MIT) ทำงานได้ทั้ง Node และ Browser และ **fail-fast บนไฟล์ผิดรูปแทนการค้าง**
|
|
387
|
+
|
|
388
|
+
```typescript
|
|
389
|
+
import { DxfParser, ParsedDxf } from 'ofs-dxf-ts';
|
|
390
|
+
|
|
391
|
+
const parsed: ParsedDxf | null = new DxfParser().parseSync(dxfText);
|
|
392
|
+
parsed?.entities; // ParsedDxfEntity[]
|
|
393
|
+
parsed?.blocks; // Record<string, ParsedDxfBlock>
|
|
394
|
+
parsed?.tables; // layer / lineType / style / dimstyle / viewPort
|
|
395
|
+
parsed?.header; // $ACADVER, $EXTMIN, ...
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
- ใช้ `parseSync(source: string)` เท่านั้น — ฝั่ง browser อ่านไฟล์อัปโหลดด้วย `await file.text()` ก่อน
|
|
399
|
+
- ชนิดฝั่ง parser export ในชื่อ `ParsedDxfEntity` / `ParsedDxfPoint` / `ParsedDxfBlock`
|
|
400
|
+
- ไฟล์ที่ parse ไม่ได้จะ `throw` — ครอบ `try/catch` เมื่อรับไฟล์จากผู้ใช้
|
|
401
|
+
|
|
402
|
+
---
|
|
403
|
+
|
|
404
|
+
## 8. การเปลี่ยนแปลงที่มีผลกับโค้ดเดิม
|
|
405
|
+
|
|
406
|
+
- **ไฟล์ที่สร้างจากศูนย์** เป็น DXF R2018 โครงสร้างครบ (เดิมเป็นไฟล์ย่อที่ไม่มี CLASSES/OBJECTS)
|
|
407
|
+
- **`addMLeader`** deprecated — วาดเป็น callout แทน MULTILEADER (ของเดิมไม่ถูกต้องสำหรับ AutoCAD)
|
|
408
|
+
- **`addHatch`** ที่ใช้ชื่อลายที่ไม่รู้จักจะ `throw` (เดิมเขียนไฟล์ที่ลายว่าง)
|
|
409
|
+
- **`addLayout`** สร้าง layout จริงแล้ว (เดิมไม่ถูกเขียนลงไฟล์); `LayoutViewportDef.viewHeight` เป็น optional เมื่อระบุ `scale`
|
|
410
|
+
- **Modelspace `add_image`** ตีความ `clipBoundary` เป็นพิกัดโลก
|
|
411
|
+
- **ตาราง** เซลล์ที่ข้อความว่างจะไม่สร้าง TEXT entity
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
รูปแบบตาม [Keep a Changelog](https://keepachangelog.com/) และใช้ [Semantic Versioning](https://semver.org/)
|
|
4
|
+
|
|
5
|
+
## [1.0.0] — 2026-09-21
|
|
6
|
+
|
|
7
|
+
เวอร์ชันแรกที่เผยแพร่บน npm ในชื่อ **`ofs-dxf-ts`** (ESM อย่างเดียว, ไม่มี runtime dependency)
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- `DxfBuilder` / `DxfDocument` / `Modelspace` — สร้าง DXF R2018 จากศูนย์ หรือวาดบน DXF template โดยคงทุก section ของ template ไว้ และแจก handle ต่อจาก `$HANDSEED`
|
|
12
|
+
- Entity: Line, Polyline (2D/3D), Circle, Arc, Ellipse, Spline, Text, MText, Hatch, Dimension, Leader, Image, Viewport, Solid, Mesh, Insert
|
|
13
|
+
- `defineBlock()` / `addBlock()` — block definition และการวางซ้ำ
|
|
14
|
+
- Hatch: `SOLID` + ลาย ISO ในตัว 32 ลาย หรือกำหนด `patternLines` เอง รองรับรูใน
|
|
15
|
+
- Raster image พร้อม IMAGEDEF/REACTOR/`ACAD_IMAGE_DICT` และ clip ด้วยพิกัดโลก
|
|
16
|
+
- Paper space layout: `addLayout()` พร้อม viewport ตามมาตราส่วน, freeze layer เฉพาะ viewport, ล็อก viewport และ `onLayout()` สำหรับวาดลง layout (ของใหม่หรือของ template)
|
|
17
|
+
- `addCallout()` (กล่องข้อความพร้อมเส้นชี้) และ `addTable()` ที่รวมเซลล์ได้ (`colSpan` / `rowSpan`)
|
|
18
|
+
- `addLineType()` / `addTextStyle()` / `addLayer()`
|
|
19
|
+
- DXF parser ในตัว (TypeScript port ของ `dxf-parser`, ไม่มี dependency ภายนอก)
|
|
20
|
+
- เรขาคณิตบริสุทธิ์: `getLineOffset()` / `offsetPolyline()` (miter + bevel, รองรับเส้นปิด), azimuth, การแบ่ง polyline, ประมาณความกว้างข้อความ
|
|
21
|
+
- สัญลักษณ์งานชลประทานแบบพารามิเตอร์ (culvert, flume, siphon, check ฯลฯ)
|
|
22
|
+
|
|
23
|
+
### Notes
|
|
24
|
+
|
|
25
|
+
- ต้องใช้ **Node.js ≥ 20.16** สำหรับ `saveas()` / `readFile()` (เข้าถึง `fs` ผ่าน `process.getBuiltinModule`) — runtime อื่นใช้ `saveString()` ได้
|
|
26
|
+
- ตรวจไฟล์ผลลัพธ์ด้วย ezdxf (strict read + audit) ได้ 0 errors / 0 fixes — ยังไม่ได้ทดสอบเปิดใน AutoCAD จริง
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 On-Farm Solution Co.,Ltd.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# ofs-dxf-ts
|
|
2
|
+
|
|
3
|
+
ไลบรารี TypeScript สำหรับสร้างไฟล์ DXF (Drawing Exchange Format) สำหรับงาน GIS และวิศวกรรม พัฒนาต่อยอดจากแนวคิดของ `ezdxf` (Python) ทำงานได้ทั้งบน **Node.js** และ **Browser (Angular/React)**
|
|
4
|
+
|
|
5
|
+
ไลบรารี **บริสุทธิ์และไม่ผูกกับ API ใด ๆ** — รับเฉพาะ coordinate, label และ options ทั่วไป แล้ววาดลงบน DXF template หรือสร้างไฟล์จากศูนย์ ผู้เรียกเป็นผู้เตรียมข้อมูลของตัวเองให้อยู่ในรูป coordinate/options ก่อน
|
|
6
|
+
|
|
7
|
+
## 🌟 คุณสมบัติ
|
|
8
|
+
|
|
9
|
+
- **Template-aware**: วาดลงบนไฟล์ DXF ต้นแบบจาก AutoCAD/Civil 3D โดยคงทุก section เดิมไว้ (Layers, Blocks, Styles, Layouts, CLASSES, OBJECTS …) และแจก handle ใหม่ต่อจาก `$HANDSEED` ของ template จึงไม่ชนกับของเดิม
|
|
10
|
+
- **สร้างจากศูนย์ได้ไฟล์ครบโครงสร้าง**: ใช้เอกสาร DXF R2018 เปล่าที่ฝังในตัว lib เป็นฐาน ทั้งสองโหมดจึงได้โครงสร้างแบบเดียวกัน
|
|
11
|
+
- **Block definition**: สร้างสัญลักษณ์เองด้วย `defineBlock()` แล้ววางซ้ำด้วย `addBlock()` (INSERT)
|
|
12
|
+
- **Hatch**: เติมทึบ (`SOLID`) และลาย ISO ในตัว 32 ลาย (ANSI31, DOTS, GRASS, EARTH, AR-SAND …) หรือกำหนดลายเอง รองรับรูใน (hole)
|
|
13
|
+
- **Raster image**: อ้างอิงไฟล์ภาพเป็นพื้นหลัง (เช่นแผนที่ภูมิประเทศ) พร้อม clip ด้วยพิกัดโลก
|
|
14
|
+
- **Paper space layout**: สร้าง layout พร้อม viewport ตามมาตราส่วน (เช่น 1:12,500) ซ่อน layer เฉพาะ viewport ล็อก viewport และวาดลง paper space ได้ทั้ง layout ใหม่และของ template
|
|
15
|
+
- **Annotation**: กล่องข้อความพร้อมเส้นชี้ (`addCallout`) และตารางที่รวมเซลล์ได้ (`colSpan` / `rowSpan`)
|
|
16
|
+
- **Linetype / Text style**: เพิ่ม linetype และ text style (เช่นฟอนต์ไทย TrueType) ได้ทั้งสองโหมด
|
|
17
|
+
- **Entities**: Line, Polyline, Circle, Arc, Ellipse, Spline, Text, MText, Hatch, Dimension, Leader, Image, Viewport, Solid, Mesh ฯลฯ
|
|
18
|
+
- **Layer & view**: Freeze / Lock / On-Off, Zoom Extents / Zoom Window
|
|
19
|
+
- **Zero runtime dependencies**: parser DXF (TypeScript port ของ `dxf-parser`, fail-fast บนไฟล์ผิดรูปแทนการค้าง) และเรขาคณิต (เช่น offset เส้นขอบคลอง) เขียนเองทั้งหมด คำนวณบนระนาบในหน่วยของแบบ (UTM เมตร)
|
|
20
|
+
- **Universal**: Node.js อ่าน/เขียนไฟล์ผ่าน `fs`; Browser/Angular โหลด template จาก string และดาวน์โหลดผลลัพธ์ได้โดยไม่ต้องใช้ `fs`
|
|
21
|
+
|
|
22
|
+
## 🚀 การติดตั้ง
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npm install ofs-dxf-ts
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**ความต้องการ**
|
|
29
|
+
|
|
30
|
+
| | |
|
|
31
|
+
|---|---|
|
|
32
|
+
| รูปแบบโมดูล | **ESM เท่านั้น** (ไม่มี CommonJS build) พร้อม type declaration ในตัว |
|
|
33
|
+
| Node.js | ≥ 20.16 — `saveas()` / `readFile()` เข้าถึง `fs` ผ่าน `process.getBuiltinModule` เวอร์ชันเก่ากว่านี้ยังใช้ `saveString()` ได้ปกติ |
|
|
34
|
+
| Browser / Angular | bundler ใดก็ได้ ไม่มีการ import `fs`/`path` แบบ static จึงไม่ต้องตั้ง polyfill |
|
|
35
|
+
|
|
36
|
+
## 💡 ตัวอย่างการใช้งาน
|
|
37
|
+
|
|
38
|
+
### 1. วาดบน Template (แนะนำ)
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
import { DxfBuilder } from 'ofs-dxf-ts';
|
|
42
|
+
|
|
43
|
+
// Node.js — โหลดไฟล์ผ่าน constructor
|
|
44
|
+
const builder = new DxfBuilder('./template2018.dxf');
|
|
45
|
+
// Browser/Angular — DxfBuilder.fromString(dxfText)
|
|
46
|
+
|
|
47
|
+
builder.addPolyline([[518600, 1033350], [519000, 1033380]], 'CANAL', 1);
|
|
48
|
+
|
|
49
|
+
builder.saveas('output.dxf'); // Node.js
|
|
50
|
+
// builder.downloadAs('output.dxf'); // Browser
|
|
51
|
+
// const dxf = builder.saveString(); // string (ทุก environment)
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### 2. สัญลักษณ์ กล่องข้อความ และตาราง
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
// linetype / text style / layer
|
|
58
|
+
builder.addTextStyle('THAI', 'THSarabunNew.ttf');
|
|
59
|
+
builder.addLineType('BOUNDARY', '____ . ____', [40, -10, 0, -10]); // หน่วยเดียวกับแบบ (เมตร)
|
|
60
|
+
builder.addLayer('ขอบเขต', 6, 'BOUNDARY');
|
|
61
|
+
|
|
62
|
+
// สัญลักษณ์หมุด BM: วาดในพิกัดของ block แล้ววางด้วย addBlock
|
|
63
|
+
builder.defineBlock('BM', b => {
|
|
64
|
+
b.addPolyline([[-1, -1], [1, -1], [1, 1], [-1, 1]], '0', undefined, undefined, true);
|
|
65
|
+
b.addHatch('SOLID', [[[0, 0], [1, 0], [1, 1], [0, 1]]], '0');
|
|
66
|
+
});
|
|
67
|
+
builder.addBlock('BM', 519395.838, 1034018.584, 20, 0, 'SYMBOL');
|
|
68
|
+
|
|
69
|
+
// กล่องข้อความพร้อมเส้นชี้ (มุมบนซ้ายของกล่องอยู่ที่ boxAt)
|
|
70
|
+
builder.addCallout(
|
|
71
|
+
[519480, 1034100], // จุดที่ชี้
|
|
72
|
+
['ก่อสร้างอาคารทางน้ำเข้า', 'ขนาด 2-1.75x1.75 ม.'],
|
|
73
|
+
[519700, 1035050], // มุมบนซ้ายของกล่อง
|
|
74
|
+
{ layer: 'NOTE', textHeight: 25, style: 'THAI', arrow: 'dot' },
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
// ตารางที่รวมเซลล์
|
|
78
|
+
builder.addTable([650, 300], [14, 26, 42, 42], 7, [
|
|
79
|
+
[{ text: 'ลำดับ', rowSpan: 2 }, { text: 'หมุด', rowSpan: 2 }, { text: 'พิกัด', colSpan: 2 }],
|
|
80
|
+
[{ text: 'North' }, { text: 'East' }],
|
|
81
|
+
[{ text: '1' }, { text: 'BM.07' }, { text: '1,034,018.584' }, { text: '519,395.838' }],
|
|
82
|
+
], 'TABLE', 3);
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### 3. Hatch และภาพพื้นหลัง
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
// ลายจุด (scale คูณกับหน่วยลาย ISO ที่เป็น mm) และลายเส้นเฉียงหมุน 45°
|
|
89
|
+
builder.addHatch('DOTS', [pondOutline], 'POND', 8, { scale: 8 });
|
|
90
|
+
builder.addHatch('ANSI31', [outer, hole], 'AREA', 7, { scale: 10, angle: 45 });
|
|
91
|
+
|
|
92
|
+
// ภาพพื้นหลัง: DXF เก็บเพียงการอ้างอิงไฟล์ — วางไฟล์ภาพไว้ข้าง .dxf
|
|
93
|
+
builder.addImage('topo_background.jpg', [3000, 2000], [516000, 1031500], [6000, 4000], 'RASTER', { fade: 40 });
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### 4. Layout สำหรับพิมพ์ (Paper Space)
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
// A1 (มม.) — viewport แสดง model space ที่ 1:12,500 (model เป็นเมตร)
|
|
100
|
+
builder.addLayout('BM-A1', 841, 594, [0, 0, 0, 0], [
|
|
101
|
+
{ center: [330, 330], width: 600, height: 440, viewCenter: [519000, 1033500], scale: 12500, locked: true },
|
|
102
|
+
{ center: [110, 480], width: 150, height: 100, viewCenter: [519000, 1033500], scale: 100000,
|
|
103
|
+
frozenLayers: ['NOTE', 'GRID'] }, // key map
|
|
104
|
+
]);
|
|
105
|
+
|
|
106
|
+
// ทุกคำสั่งภายใน callback วาดลง paper space ของ layout นั้น (ใช้กับ 'Layout1' ของ template ได้ด้วย)
|
|
107
|
+
builder.onLayout('BM-A1', s => {
|
|
108
|
+
s.addText('แผนที่แสดงตำแหน่งหมุดหลักฐาน', 250, 70, 9, 0, 'SHEET');
|
|
109
|
+
s.addBlock('NORTH', 800, 530, 2, 0, 'SHEET');
|
|
110
|
+
});
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
> 🅰️ **Angular**: โหลด template ผ่าน `HttpClient` แบบ `responseType: 'text'` แล้วใช้ `DxfBuilder.fromString()` และดาวน์โหลดด้วย `downloadAs()` — ไม่มีการใช้ `fs`
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
- 📖 **API ทั้งหมด**: [API.md](./API.md) (แนบมากับแพ็กเกจ)
|
|
118
|
+
- 📝 **ประวัติเวอร์ชัน**: [CHANGELOG.md](./CHANGELOG.md)
|
|
119
|
+
- 📄 สัญญาอนุญาต: MIT
|