@bitbybit-dev/base 0.20.11 → 0.20.13
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/lib/api/GlobalCDNProvider.d.ts +3 -0
- package/lib/api/GlobalCDNProvider.js +3 -0
- package/lib/api/index.d.ts +1 -0
- package/lib/api/index.js +1 -0
- package/lib/api/inputs/io-inputs.d.ts +15 -1
- package/lib/api/inputs/io-inputs.js +21 -1
- package/lib/api/services/helpers/dxf/dxf-generator.d.ts +40 -1
- package/lib/api/services/helpers/dxf/dxf-generator.js +361 -74
- package/package.json +1 -1
package/lib/api/index.d.ts
CHANGED
package/lib/api/index.js
CHANGED
|
@@ -143,11 +143,25 @@ export declare namespace IO {
|
|
|
143
143
|
* Main DXF model containing all path parts
|
|
144
144
|
*/
|
|
145
145
|
class DxfModelDto {
|
|
146
|
-
constructor(dxfPathsParts?: DxfPathsPartDto[]);
|
|
146
|
+
constructor(dxfPathsParts?: DxfPathsPartDto[], colorFormat?: "aci" | "truecolor", acadVersion?: "AC1009" | "AC1015");
|
|
147
147
|
/**
|
|
148
148
|
* Array of path parts, each containing paths with segments
|
|
149
149
|
* @default undefined
|
|
150
150
|
*/
|
|
151
151
|
dxfPathsParts: DxfPathsPartDto[];
|
|
152
|
+
/**
|
|
153
|
+
* Color format to use in the DXF file
|
|
154
|
+
* - "aci": AutoCAD Color Index (1-255) - Better compatibility with older CAD software like Design CAD 3D Max
|
|
155
|
+
* - "truecolor": 24-bit RGB true color - Full color spectrum, requires newer CAD software
|
|
156
|
+
* @default aci
|
|
157
|
+
*/
|
|
158
|
+
colorFormat?: "aci" | "truecolor";
|
|
159
|
+
/**
|
|
160
|
+
* AutoCAD version format for DXF file
|
|
161
|
+
* - "AC1009": AutoCAD R12/R11 - Maximum compatibility with older CAD software (e.g., Design CAD 3D Max)
|
|
162
|
+
* - "AC1015": AutoCAD 2000 - Modern format with extended features
|
|
163
|
+
* @default AC1009
|
|
164
|
+
*/
|
|
165
|
+
acadVersion?: "AC1009" | "AC1015";
|
|
152
166
|
}
|
|
153
167
|
}
|
|
@@ -142,10 +142,30 @@ export var IO;
|
|
|
142
142
|
* Main DXF model containing all path parts
|
|
143
143
|
*/
|
|
144
144
|
class DxfModelDto {
|
|
145
|
-
constructor(dxfPathsParts) {
|
|
145
|
+
constructor(dxfPathsParts, colorFormat, acadVersion) {
|
|
146
|
+
/**
|
|
147
|
+
* Color format to use in the DXF file
|
|
148
|
+
* - "aci": AutoCAD Color Index (1-255) - Better compatibility with older CAD software like Design CAD 3D Max
|
|
149
|
+
* - "truecolor": 24-bit RGB true color - Full color spectrum, requires newer CAD software
|
|
150
|
+
* @default aci
|
|
151
|
+
*/
|
|
152
|
+
this.colorFormat = "aci";
|
|
153
|
+
/**
|
|
154
|
+
* AutoCAD version format for DXF file
|
|
155
|
+
* - "AC1009": AutoCAD R12/R11 - Maximum compatibility with older CAD software (e.g., Design CAD 3D Max)
|
|
156
|
+
* - "AC1015": AutoCAD 2000 - Modern format with extended features
|
|
157
|
+
* @default AC1009
|
|
158
|
+
*/
|
|
159
|
+
this.acadVersion = "AC1009";
|
|
146
160
|
if (dxfPathsParts !== undefined) {
|
|
147
161
|
this.dxfPathsParts = dxfPathsParts;
|
|
148
162
|
}
|
|
163
|
+
if (colorFormat !== undefined) {
|
|
164
|
+
this.colorFormat = colorFormat;
|
|
165
|
+
}
|
|
166
|
+
if (acadVersion !== undefined) {
|
|
167
|
+
this.acadVersion = acadVersion;
|
|
168
|
+
}
|
|
149
169
|
}
|
|
150
170
|
}
|
|
151
171
|
IO.DxfModelDto = DxfModelDto;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import * as Inputs from "../../../inputs";
|
|
2
2
|
export declare class DxfGenerator {
|
|
3
3
|
private entityHandle;
|
|
4
|
+
private colorFormat;
|
|
5
|
+
private acadVersion;
|
|
4
6
|
/**
|
|
5
7
|
* Generate a complete DXF file content from path-based entities
|
|
6
8
|
*/
|
|
@@ -13,6 +15,38 @@ export declare class DxfGenerator {
|
|
|
13
15
|
* Generate DXF tables section (layers, line types, etc.)
|
|
14
16
|
*/
|
|
15
17
|
private generateTables;
|
|
18
|
+
/**
|
|
19
|
+
* Generate line type table
|
|
20
|
+
*/
|
|
21
|
+
private generateLineTypeTable;
|
|
22
|
+
/**
|
|
23
|
+
* Generate text style table
|
|
24
|
+
*/
|
|
25
|
+
private generateStyleTable;
|
|
26
|
+
/**
|
|
27
|
+
* Generate VPORT table (viewport configuration)
|
|
28
|
+
*/
|
|
29
|
+
private generateVportTable;
|
|
30
|
+
/**
|
|
31
|
+
* Generate VIEW table (empty but required for AC1009)
|
|
32
|
+
*/
|
|
33
|
+
private generateViewTable;
|
|
34
|
+
/**
|
|
35
|
+
* Generate UCS table (user coordinate system - empty but required for AC1009)
|
|
36
|
+
*/
|
|
37
|
+
private generateUcsTable;
|
|
38
|
+
/**
|
|
39
|
+
* Generate APPID table (application ID - required for AC1009)
|
|
40
|
+
*/
|
|
41
|
+
private generateAppidTable;
|
|
42
|
+
/**
|
|
43
|
+
* Generate DIMSTYLE table (dimension style - empty but required for AC1009)
|
|
44
|
+
*/
|
|
45
|
+
private generateDimstyleTable;
|
|
46
|
+
/**
|
|
47
|
+
* Generate blocks section (empty but required)
|
|
48
|
+
*/
|
|
49
|
+
private generateBlocks;
|
|
16
50
|
/**
|
|
17
51
|
* Generate layer table based on unique layers in all parts
|
|
18
52
|
*/
|
|
@@ -76,7 +110,12 @@ export declare class DxfGenerator {
|
|
|
76
110
|
/**
|
|
77
111
|
* Convert color to DXF format
|
|
78
112
|
* Accepts hex color (#RRGGBB) or ACI color index (1-255)
|
|
79
|
-
* Returns appropriate DXF color codes
|
|
113
|
+
* Returns appropriate DXF color codes based on colorFormat setting
|
|
80
114
|
*/
|
|
81
115
|
private convertColorToDxf;
|
|
116
|
+
/**
|
|
117
|
+
* Convert RGB values to nearest AutoCAD Color Index (ACI)
|
|
118
|
+
* Uses a simplified mapping to standard ACI colors
|
|
119
|
+
*/
|
|
120
|
+
private rgbToAciColorIndex;
|
|
82
121
|
}
|
|
@@ -1,16 +1,23 @@
|
|
|
1
1
|
export class DxfGenerator {
|
|
2
2
|
constructor() {
|
|
3
|
-
this.entityHandle =
|
|
3
|
+
this.entityHandle = 256; // Start at 256 to avoid conflicts with system handles
|
|
4
|
+
this.colorFormat = "aci";
|
|
5
|
+
this.acadVersion = "AC1009";
|
|
4
6
|
}
|
|
5
7
|
/**
|
|
6
8
|
* Generate a complete DXF file content from path-based entities
|
|
7
9
|
*/
|
|
8
10
|
generateDxf(dxfInputs) {
|
|
11
|
+
// Set format options from input
|
|
12
|
+
this.colorFormat = dxfInputs.colorFormat || "aci";
|
|
13
|
+
this.acadVersion = dxfInputs.acadVersion || "AC1009";
|
|
9
14
|
const dxfContent = [];
|
|
10
15
|
// Header section
|
|
11
16
|
dxfContent.push(...this.generateHeader());
|
|
12
17
|
// Tables section
|
|
13
18
|
dxfContent.push(...this.generateTables(dxfInputs));
|
|
19
|
+
// Blocks section (required by many CAD programs)
|
|
20
|
+
dxfContent.push(...this.generateBlocks());
|
|
14
21
|
// Entities section
|
|
15
22
|
dxfContent.push(...this.generateEntities(dxfInputs));
|
|
16
23
|
// End of file
|
|
@@ -21,7 +28,7 @@ export class DxfGenerator {
|
|
|
21
28
|
* Generate DXF header section
|
|
22
29
|
*/
|
|
23
30
|
generateHeader() {
|
|
24
|
-
|
|
31
|
+
const header = [
|
|
25
32
|
"0",
|
|
26
33
|
"SECTION",
|
|
27
34
|
"2",
|
|
@@ -29,22 +36,18 @@ export class DxfGenerator {
|
|
|
29
36
|
"9",
|
|
30
37
|
"$ACADVER",
|
|
31
38
|
"1",
|
|
32
|
-
|
|
33
|
-
"9",
|
|
34
|
-
"$DWGCODEPAGE",
|
|
35
|
-
"3",
|
|
36
|
-
"ANSI_1252",
|
|
37
|
-
"9",
|
|
38
|
-
"$LASTSAVEDBY",
|
|
39
|
-
"1",
|
|
40
|
-
"bitbybit.dev",
|
|
41
|
-
"9",
|
|
42
|
-
"$HANDSEED",
|
|
43
|
-
"5",
|
|
44
|
-
"20000",
|
|
45
|
-
"0",
|
|
46
|
-
"ENDSEC"
|
|
39
|
+
this.acadVersion
|
|
47
40
|
];
|
|
41
|
+
if (this.acadVersion === "AC1009") {
|
|
42
|
+
// AC1009 (AutoCAD R12) - minimal header for maximum compatibility
|
|
43
|
+
header.push("9", "$DWGCODEPAGE", "3", "ascii", "9", "$HANDSEED", "5", "0");
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
// AC1015 (AutoCAD 2000) - modern format
|
|
47
|
+
header.push("9", "$DWGCODEPAGE", "3", "ANSI_1252", "9", "$LASTSAVEDBY", "1", "bitbybit.dev", "9", "$HANDSEED", "5", "20000");
|
|
48
|
+
}
|
|
49
|
+
header.push("0", "ENDSEC");
|
|
50
|
+
return header;
|
|
48
51
|
}
|
|
49
52
|
/**
|
|
50
53
|
* Generate DXF tables section (layers, line types, etc.)
|
|
@@ -56,11 +59,236 @@ export class DxfGenerator {
|
|
|
56
59
|
"2",
|
|
57
60
|
"TABLES"
|
|
58
61
|
];
|
|
62
|
+
// VPORT table (required for AC1009)
|
|
63
|
+
if (this.acadVersion === "AC1009") {
|
|
64
|
+
tables.push(...this.generateVportTable());
|
|
65
|
+
}
|
|
66
|
+
// Line type table (required)
|
|
67
|
+
tables.push(...this.generateLineTypeTable());
|
|
59
68
|
// Layer table
|
|
60
69
|
tables.push(...this.generateLayerTable(dxfInputs));
|
|
70
|
+
// Text style table (required for text entities, included for completeness)
|
|
71
|
+
tables.push(...this.generateStyleTable());
|
|
72
|
+
// Additional tables for AC1009
|
|
73
|
+
if (this.acadVersion === "AC1009") {
|
|
74
|
+
tables.push(...this.generateViewTable());
|
|
75
|
+
tables.push(...this.generateUcsTable());
|
|
76
|
+
tables.push(...this.generateAppidTable());
|
|
77
|
+
tables.push(...this.generateDimstyleTable());
|
|
78
|
+
}
|
|
61
79
|
tables.push("0", "ENDSEC");
|
|
62
80
|
return tables;
|
|
63
81
|
}
|
|
82
|
+
/**
|
|
83
|
+
* Generate line type table
|
|
84
|
+
*/
|
|
85
|
+
generateLineTypeTable() {
|
|
86
|
+
const ltype = [
|
|
87
|
+
"0",
|
|
88
|
+
"TABLE",
|
|
89
|
+
"2",
|
|
90
|
+
"LTYPE",
|
|
91
|
+
"70",
|
|
92
|
+
"1" // Number of line types
|
|
93
|
+
];
|
|
94
|
+
if (this.acadVersion === "AC1015") {
|
|
95
|
+
ltype.push("5", "5", "100", "AcDbSymbolTable");
|
|
96
|
+
}
|
|
97
|
+
ltype.push("0", "LTYPE", "2", "CONTINUOUS", "70", this.acadVersion === "AC1009" ? "64" : "0", "3", "Solid line", "72", "65", "73", "0", "40", "0.0");
|
|
98
|
+
if (this.acadVersion === "AC1015") {
|
|
99
|
+
ltype.splice(ltype.indexOf("LTYPE") + 1, 0, "5", "14", "100", "AcDbSymbolTableRecord", "100", "AcDbLinetypeTableRecord");
|
|
100
|
+
}
|
|
101
|
+
ltype.push("0", "ENDTAB");
|
|
102
|
+
return ltype;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Generate text style table
|
|
106
|
+
*/
|
|
107
|
+
generateStyleTable() {
|
|
108
|
+
const style = [
|
|
109
|
+
"0",
|
|
110
|
+
"TABLE",
|
|
111
|
+
"2",
|
|
112
|
+
"STYLE",
|
|
113
|
+
"70",
|
|
114
|
+
"1" // Number of styles
|
|
115
|
+
];
|
|
116
|
+
if (this.acadVersion === "AC1015") {
|
|
117
|
+
style.push("5", "3", "100", "AcDbSymbolTable");
|
|
118
|
+
}
|
|
119
|
+
style.push("0", "STYLE", "2", "STANDARD", "70", "0", "40", "0.0", "41", "1.0", "50", "0.0", "71", "0", "42", "0.2", "3", "txt", "4", "");
|
|
120
|
+
if (this.acadVersion === "AC1015") {
|
|
121
|
+
style.splice(style.indexOf("STYLE") + 1, 0, "5", "11", "100", "AcDbSymbolTableRecord", "100", "AcDbTextStyleTableRecord");
|
|
122
|
+
}
|
|
123
|
+
style.push("0", "ENDTAB");
|
|
124
|
+
return style;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Generate VPORT table (viewport configuration)
|
|
128
|
+
*/
|
|
129
|
+
generateVportTable() {
|
|
130
|
+
return [
|
|
131
|
+
"0",
|
|
132
|
+
"TABLE",
|
|
133
|
+
"2",
|
|
134
|
+
"VPORT",
|
|
135
|
+
"70",
|
|
136
|
+
"2",
|
|
137
|
+
"0",
|
|
138
|
+
"VPORT",
|
|
139
|
+
"2",
|
|
140
|
+
"*ACTIVE",
|
|
141
|
+
"70",
|
|
142
|
+
"0",
|
|
143
|
+
"10",
|
|
144
|
+
"0.0",
|
|
145
|
+
"20",
|
|
146
|
+
"0.0",
|
|
147
|
+
"11",
|
|
148
|
+
"1.0",
|
|
149
|
+
"21",
|
|
150
|
+
"1.0",
|
|
151
|
+
"12",
|
|
152
|
+
"15.0",
|
|
153
|
+
"22",
|
|
154
|
+
"11.101231",
|
|
155
|
+
"13",
|
|
156
|
+
"0.0",
|
|
157
|
+
"23",
|
|
158
|
+
"0.0",
|
|
159
|
+
"14",
|
|
160
|
+
"0.1",
|
|
161
|
+
"24",
|
|
162
|
+
"0.1",
|
|
163
|
+
"15",
|
|
164
|
+
"0.5",
|
|
165
|
+
"25",
|
|
166
|
+
"0.5",
|
|
167
|
+
"16",
|
|
168
|
+
"0.0",
|
|
169
|
+
"26",
|
|
170
|
+
"0.0",
|
|
171
|
+
"36",
|
|
172
|
+
"1.0",
|
|
173
|
+
"17",
|
|
174
|
+
"0.0",
|
|
175
|
+
"27",
|
|
176
|
+
"0.0",
|
|
177
|
+
"37",
|
|
178
|
+
"0.0",
|
|
179
|
+
"40",
|
|
180
|
+
"22.202462",
|
|
181
|
+
"41",
|
|
182
|
+
"1.351201",
|
|
183
|
+
"42",
|
|
184
|
+
"50.0",
|
|
185
|
+
"43",
|
|
186
|
+
"0.0",
|
|
187
|
+
"44",
|
|
188
|
+
"0.0",
|
|
189
|
+
"50",
|
|
190
|
+
"0.0",
|
|
191
|
+
"51",
|
|
192
|
+
"0.0",
|
|
193
|
+
"71",
|
|
194
|
+
"0",
|
|
195
|
+
"72",
|
|
196
|
+
"100",
|
|
197
|
+
"73",
|
|
198
|
+
"1",
|
|
199
|
+
"74",
|
|
200
|
+
"1",
|
|
201
|
+
"75",
|
|
202
|
+
"1",
|
|
203
|
+
"76",
|
|
204
|
+
"0",
|
|
205
|
+
"77",
|
|
206
|
+
"0",
|
|
207
|
+
"78",
|
|
208
|
+
"0",
|
|
209
|
+
"0",
|
|
210
|
+
"ENDTAB"
|
|
211
|
+
];
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Generate VIEW table (empty but required for AC1009)
|
|
215
|
+
*/
|
|
216
|
+
generateViewTable() {
|
|
217
|
+
return [
|
|
218
|
+
"0",
|
|
219
|
+
"TABLE",
|
|
220
|
+
"2",
|
|
221
|
+
"VIEW",
|
|
222
|
+
"70",
|
|
223
|
+
"0",
|
|
224
|
+
"0",
|
|
225
|
+
"ENDTAB"
|
|
226
|
+
];
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Generate UCS table (user coordinate system - empty but required for AC1009)
|
|
230
|
+
*/
|
|
231
|
+
generateUcsTable() {
|
|
232
|
+
return [
|
|
233
|
+
"0",
|
|
234
|
+
"TABLE",
|
|
235
|
+
"2",
|
|
236
|
+
"UCS",
|
|
237
|
+
"70",
|
|
238
|
+
"0",
|
|
239
|
+
"0",
|
|
240
|
+
"ENDTAB"
|
|
241
|
+
];
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Generate APPID table (application ID - required for AC1009)
|
|
245
|
+
*/
|
|
246
|
+
generateAppidTable() {
|
|
247
|
+
return [
|
|
248
|
+
"0",
|
|
249
|
+
"TABLE",
|
|
250
|
+
"2",
|
|
251
|
+
"APPID",
|
|
252
|
+
"70",
|
|
253
|
+
"1",
|
|
254
|
+
"0",
|
|
255
|
+
"APPID",
|
|
256
|
+
"2",
|
|
257
|
+
"ACAD",
|
|
258
|
+
"70",
|
|
259
|
+
"64",
|
|
260
|
+
"0",
|
|
261
|
+
"ENDTAB"
|
|
262
|
+
];
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Generate DIMSTYLE table (dimension style - empty but required for AC1009)
|
|
266
|
+
*/
|
|
267
|
+
generateDimstyleTable() {
|
|
268
|
+
return [
|
|
269
|
+
"0",
|
|
270
|
+
"TABLE",
|
|
271
|
+
"2",
|
|
272
|
+
"DIMSTYLE",
|
|
273
|
+
"70",
|
|
274
|
+
"0",
|
|
275
|
+
"0",
|
|
276
|
+
"ENDTAB"
|
|
277
|
+
];
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Generate blocks section (empty but required)
|
|
281
|
+
*/
|
|
282
|
+
generateBlocks() {
|
|
283
|
+
return [
|
|
284
|
+
"0",
|
|
285
|
+
"SECTION",
|
|
286
|
+
"2",
|
|
287
|
+
"BLOCKS",
|
|
288
|
+
"0",
|
|
289
|
+
"ENDSEC"
|
|
290
|
+
];
|
|
291
|
+
}
|
|
64
292
|
/**
|
|
65
293
|
* Generate layer table based on unique layers in all parts
|
|
66
294
|
*/
|
|
@@ -83,18 +311,22 @@ export class DxfGenerator {
|
|
|
83
311
|
"TABLE",
|
|
84
312
|
"2",
|
|
85
313
|
"LAYER",
|
|
86
|
-
"5",
|
|
87
|
-
"2",
|
|
88
|
-
"100",
|
|
89
|
-
"AcDbSymbolTable",
|
|
90
314
|
"70",
|
|
91
315
|
layers.size.toString()
|
|
92
316
|
];
|
|
317
|
+
if (this.acadVersion === "AC1015") {
|
|
318
|
+
layerTable.splice(4, 0, "5", "2", "100", "AcDbSymbolTable");
|
|
319
|
+
}
|
|
93
320
|
// Generate layer entries
|
|
94
321
|
layers.forEach(layerName => {
|
|
95
|
-
layerTable.push("0", "LAYER", "
|
|
322
|
+
layerTable.push("0", "LAYER", "2", layerName, "70", "0", "62", "7", // Default color (white)
|
|
96
323
|
"6", "CONTINUOUS" // Line type
|
|
97
324
|
);
|
|
325
|
+
// Add AC1015-specific subclass markers
|
|
326
|
+
if (this.acadVersion === "AC1015") {
|
|
327
|
+
const insertIdx = layerTable.lastIndexOf("LAYER") + 1;
|
|
328
|
+
layerTable.splice(insertIdx, 0, "5", this.getNextHandle(), "100", "AcDbSymbolTableRecord", "100", "AcDbLayerTableRecord");
|
|
329
|
+
}
|
|
98
330
|
});
|
|
99
331
|
layerTable.push("0", "ENDTAB");
|
|
100
332
|
return layerTable;
|
|
@@ -184,21 +416,23 @@ export class DxfGenerator {
|
|
|
184
416
|
const entity = [
|
|
185
417
|
"0",
|
|
186
418
|
"LINE",
|
|
187
|
-
"
|
|
188
|
-
|
|
189
|
-
"100",
|
|
190
|
-
"AcDbEntity"
|
|
419
|
+
"8",
|
|
420
|
+
part.layer || "0"
|
|
191
421
|
];
|
|
192
|
-
// Add layer
|
|
193
|
-
entity.push("8", part.layer || "0");
|
|
194
422
|
// Add color if specified
|
|
195
423
|
if (part.color !== undefined) {
|
|
196
424
|
const colorCodes = this.convertColorToDxf(part.color);
|
|
197
425
|
colorCodes.forEach(cc => entity.push(cc.code, cc.value));
|
|
198
426
|
}
|
|
199
|
-
entity.push("
|
|
200
|
-
"11", line.end[0].
|
|
427
|
+
entity.push("10", line.start[0].toFixed(6), "20", line.start[1].toFixed(6), "30", "0.00", // Z coordinate (2D)
|
|
428
|
+
"11", line.end[0].toFixed(6), "21", line.end[1].toFixed(6), "31", "0.00" // Z coordinate (2D)
|
|
201
429
|
);
|
|
430
|
+
// Add AC1015-specific codes
|
|
431
|
+
if (this.acadVersion === "AC1015") {
|
|
432
|
+
entity.splice(2, 0, "5", this.getNextHandle(), "100", "AcDbEntity");
|
|
433
|
+
const coordIdx = entity.indexOf("10");
|
|
434
|
+
entity.splice(coordIdx, 0, "100", "AcDbLine");
|
|
435
|
+
}
|
|
202
436
|
return entity;
|
|
203
437
|
}
|
|
204
438
|
/**
|
|
@@ -208,20 +442,21 @@ export class DxfGenerator {
|
|
|
208
442
|
const entity = [
|
|
209
443
|
"0",
|
|
210
444
|
"CIRCLE",
|
|
211
|
-
"
|
|
212
|
-
|
|
213
|
-
"100",
|
|
214
|
-
"AcDbEntity"
|
|
445
|
+
"8",
|
|
446
|
+
part.layer || "0"
|
|
215
447
|
];
|
|
216
|
-
// Add layer
|
|
217
|
-
entity.push("8", part.layer || "0");
|
|
218
448
|
// Add color if specified
|
|
219
449
|
if (part.color !== undefined) {
|
|
220
450
|
const colorCodes = this.convertColorToDxf(part.color);
|
|
221
451
|
colorCodes.forEach(cc => entity.push(cc.code, cc.value));
|
|
222
452
|
}
|
|
223
|
-
entity.push("
|
|
224
|
-
|
|
453
|
+
entity.push("10", circle.center[0].toFixed(6), "20", circle.center[1].toFixed(6), "30", "0.00", "40", circle.radius.toFixed(6));
|
|
454
|
+
// Add AC1015-specific codes
|
|
455
|
+
if (this.acadVersion === "AC1015") {
|
|
456
|
+
entity.splice(2, 0, "5", this.getNextHandle(), "100", "AcDbEntity");
|
|
457
|
+
const coordIdx = entity.indexOf("10");
|
|
458
|
+
entity.splice(coordIdx, 0, "100", "AcDbCircle");
|
|
459
|
+
}
|
|
225
460
|
return entity;
|
|
226
461
|
}
|
|
227
462
|
/**
|
|
@@ -231,20 +466,27 @@ export class DxfGenerator {
|
|
|
231
466
|
const entity = [
|
|
232
467
|
"0",
|
|
233
468
|
"ARC",
|
|
234
|
-
"
|
|
235
|
-
|
|
236
|
-
"100",
|
|
237
|
-
"AcDbEntity"
|
|
469
|
+
"8",
|
|
470
|
+
part.layer || "0"
|
|
238
471
|
];
|
|
239
|
-
// Add
|
|
240
|
-
|
|
472
|
+
// Add line type for AC1009 (optional empty)
|
|
473
|
+
if (this.acadVersion === "AC1009") {
|
|
474
|
+
entity.push("6", " ");
|
|
475
|
+
}
|
|
241
476
|
// Add color if specified
|
|
242
477
|
if (part.color !== undefined) {
|
|
243
478
|
const colorCodes = this.convertColorToDxf(part.color);
|
|
244
479
|
colorCodes.forEach(cc => entity.push(cc.code, cc.value));
|
|
245
480
|
}
|
|
246
|
-
entity.push("
|
|
247
|
-
|
|
481
|
+
entity.push("10", arc.center[0].toFixed(6), "20", arc.center[1].toFixed(6), "30", this.acadVersion === "AC1009" ? "" : "0.0", "40", arc.radius.toFixed(6), "50", arc.startAngle.toFixed(6), "51", arc.endAngle.toFixed(6));
|
|
482
|
+
// Add AC1015-specific codes
|
|
483
|
+
if (this.acadVersion === "AC1015") {
|
|
484
|
+
entity.splice(2, 0, "5", this.getNextHandle(), "100", "AcDbEntity");
|
|
485
|
+
const coordIdx = entity.indexOf("10");
|
|
486
|
+
entity.splice(coordIdx, 0, "100", "AcDbCircle");
|
|
487
|
+
const angleIdx = entity.indexOf("50");
|
|
488
|
+
entity.splice(angleIdx, 0, "100", "AcDbArc");
|
|
489
|
+
}
|
|
248
490
|
return entity;
|
|
249
491
|
}
|
|
250
492
|
/**
|
|
@@ -254,28 +496,30 @@ export class DxfGenerator {
|
|
|
254
496
|
const entity = [
|
|
255
497
|
"0",
|
|
256
498
|
"LWPOLYLINE",
|
|
257
|
-
"
|
|
258
|
-
|
|
259
|
-
"100",
|
|
260
|
-
"AcDbEntity"
|
|
499
|
+
"8",
|
|
500
|
+
part.layer || "0"
|
|
261
501
|
];
|
|
262
|
-
// Add layer
|
|
263
|
-
entity.push("8", part.layer || "0");
|
|
264
502
|
// Add color if specified
|
|
265
503
|
if (part.color !== undefined) {
|
|
266
504
|
const colorCodes = this.convertColorToDxf(part.color);
|
|
267
505
|
colorCodes.forEach(cc => entity.push(cc.code, cc.value));
|
|
268
506
|
}
|
|
269
507
|
const isClosed = polyline.closed || (polyline.points.length > 2 && this.isClosedPolyline(polyline.points));
|
|
270
|
-
entity.push("
|
|
508
|
+
entity.push("90", polyline.points.length.toString(), "70", isClosed ? "1" : "0");
|
|
509
|
+
// Add AC1015-specific codes
|
|
510
|
+
if (this.acadVersion === "AC1015") {
|
|
511
|
+
entity.splice(2, 0, "5", this.getNextHandle(), "100", "AcDbEntity");
|
|
512
|
+
const pointIdx = entity.indexOf("90");
|
|
513
|
+
entity.splice(pointIdx, 0, "100", "AcDbPolyline");
|
|
514
|
+
}
|
|
271
515
|
// Add vertices
|
|
272
516
|
polyline.points.forEach((point, index) => {
|
|
273
|
-
entity.push("10", point[0].
|
|
517
|
+
entity.push("10", point[0].toFixed(6), "20", point[1].toFixed(6));
|
|
274
518
|
// Add bulge value if specified (for arc segments)
|
|
275
519
|
if (polyline.bulges && polyline.bulges.length > index) {
|
|
276
520
|
const bulge = polyline.bulges[index];
|
|
277
521
|
if (bulge !== 0) {
|
|
278
|
-
entity.push("42", bulge.
|
|
522
|
+
entity.push("42", bulge.toFixed(6));
|
|
279
523
|
}
|
|
280
524
|
}
|
|
281
525
|
});
|
|
@@ -288,13 +532,9 @@ export class DxfGenerator {
|
|
|
288
532
|
const entity = [
|
|
289
533
|
"0",
|
|
290
534
|
"SPLINE",
|
|
291
|
-
"
|
|
292
|
-
|
|
293
|
-
"100",
|
|
294
|
-
"AcDbEntity"
|
|
535
|
+
"8",
|
|
536
|
+
part.layer || "0"
|
|
295
537
|
];
|
|
296
|
-
// Add layer
|
|
297
|
-
entity.push("8", part.layer || "0");
|
|
298
538
|
// Add color if specified
|
|
299
539
|
if (part.color !== undefined) {
|
|
300
540
|
const colorCodes = this.convertColorToDxf(part.color);
|
|
@@ -304,17 +544,23 @@ export class DxfGenerator {
|
|
|
304
544
|
const numControlPoints = spline.controlPoints.length;
|
|
305
545
|
const numKnots = numControlPoints + degree + 1;
|
|
306
546
|
// Spline flags: 1 = closed, 2 = periodic, 4 = rational, 8 = planar, 16 = linear
|
|
307
|
-
const flags = spline.closed ?
|
|
308
|
-
entity.push("
|
|
547
|
+
const flags = spline.closed ? 9 : 8; // Add planar flag (8) for 2D splines
|
|
548
|
+
entity.push("210", "0.0", "220", "0.0", "230", "1.0", // Normal vector (Z-axis for 2D)
|
|
309
549
|
"70", flags.toString(), "71", degree.toString(), "72", numKnots.toString(), "73", numControlPoints.toString(), "74", "0" // Number of fit points (we're using control points)
|
|
310
550
|
);
|
|
551
|
+
// Add AC1015-specific codes
|
|
552
|
+
if (this.acadVersion === "AC1015") {
|
|
553
|
+
entity.splice(2, 0, "5", this.getNextHandle(), "100", "AcDbEntity");
|
|
554
|
+
const normalIdx = entity.indexOf("210");
|
|
555
|
+
entity.splice(normalIdx, 0, "100", "AcDbSpline");
|
|
556
|
+
}
|
|
311
557
|
// Generate knot values (uniform knot vector)
|
|
312
558
|
for (let i = 0; i < numKnots; i++) {
|
|
313
|
-
entity.push("40", i.
|
|
559
|
+
entity.push("40", i.toFixed(6));
|
|
314
560
|
}
|
|
315
561
|
// Add control points
|
|
316
562
|
spline.controlPoints.forEach(point => {
|
|
317
|
-
entity.push("10", point[0].
|
|
563
|
+
entity.push("10", point[0].toFixed(6), "20", point[1].toFixed(6), "30", "0.0" // Z coordinate (2D)
|
|
318
564
|
);
|
|
319
565
|
});
|
|
320
566
|
return entity;
|
|
@@ -339,7 +585,7 @@ export class DxfGenerator {
|
|
|
339
585
|
/**
|
|
340
586
|
* Convert color to DXF format
|
|
341
587
|
* Accepts hex color (#RRGGBB) or ACI color index (1-255)
|
|
342
|
-
* Returns appropriate DXF color codes
|
|
588
|
+
* Returns appropriate DXF color codes based on colorFormat setting
|
|
343
589
|
*/
|
|
344
590
|
convertColorToDxf(color) {
|
|
345
591
|
// If it's already a number (ACI index), use it directly
|
|
@@ -349,23 +595,64 @@ export class DxfGenerator {
|
|
|
349
595
|
return [{ code: "62", value: color }];
|
|
350
596
|
}
|
|
351
597
|
}
|
|
352
|
-
// If it's a hex color,
|
|
598
|
+
// If it's a hex color, handle based on format preference
|
|
353
599
|
if (color.startsWith("#")) {
|
|
354
600
|
const hex = color.substring(1);
|
|
355
601
|
if (hex.length === 6) {
|
|
356
602
|
const r = parseInt(hex.substring(0, 2), 16);
|
|
357
603
|
const g = parseInt(hex.substring(2, 4), 16);
|
|
358
604
|
const b = parseInt(hex.substring(4, 6), 16);
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
605
|
+
if (this.colorFormat === "truecolor") {
|
|
606
|
+
// Use 24-bit true color for full color spectrum (newer CAD software)
|
|
607
|
+
const trueColor = (r * 65536) + (g * 256) + b;
|
|
608
|
+
return [
|
|
609
|
+
{ code: "62", value: "256" },
|
|
610
|
+
{ code: "420", value: trueColor.toString() }
|
|
611
|
+
];
|
|
612
|
+
}
|
|
613
|
+
else {
|
|
614
|
+
// Use ACI color index for better compatibility (older CAD software)
|
|
615
|
+
const aciIndex = this.rgbToAciColorIndex(r, g, b);
|
|
616
|
+
return [{ code: "62", value: aciIndex.toString() }];
|
|
617
|
+
}
|
|
366
618
|
}
|
|
367
619
|
}
|
|
368
620
|
// Default to white (7) if color can't be parsed
|
|
369
621
|
return [{ code: "62", value: "7" }];
|
|
370
622
|
}
|
|
623
|
+
/**
|
|
624
|
+
* Convert RGB values to nearest AutoCAD Color Index (ACI)
|
|
625
|
+
* Uses a simplified mapping to standard ACI colors
|
|
626
|
+
*/
|
|
627
|
+
rgbToAciColorIndex(r, g, b) {
|
|
628
|
+
// ACI standard colors (simplified mapping)
|
|
629
|
+
const aciColors = {
|
|
630
|
+
1: [255, 0, 0],
|
|
631
|
+
2: [255, 255, 0],
|
|
632
|
+
3: [0, 255, 0],
|
|
633
|
+
4: [0, 255, 255],
|
|
634
|
+
5: [0, 0, 255],
|
|
635
|
+
6: [255, 0, 255],
|
|
636
|
+
7: [255, 255, 255],
|
|
637
|
+
8: [128, 128, 128],
|
|
638
|
+
9: [192, 192, 192] // Light gray
|
|
639
|
+
};
|
|
640
|
+
// Special case for black or very dark colors
|
|
641
|
+
if (r < 30 && g < 30 && b < 30) {
|
|
642
|
+
return 7; // Use white for visibility on dark backgrounds
|
|
643
|
+
}
|
|
644
|
+
// Find nearest color
|
|
645
|
+
let nearestIndex = 7;
|
|
646
|
+
let minDistance = Infinity;
|
|
647
|
+
for (const [index, [cr, cg, cb]] of Object.entries(aciColors)) {
|
|
648
|
+
const distance = Math.sqrt(Math.pow(r - cr, 2) +
|
|
649
|
+
Math.pow(g - cg, 2) +
|
|
650
|
+
Math.pow(b - cb, 2));
|
|
651
|
+
if (distance < minDistance) {
|
|
652
|
+
minDistance = distance;
|
|
653
|
+
nearestIndex = parseInt(index);
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
return nearestIndex;
|
|
657
|
+
}
|
|
371
658
|
}
|