dxf-json 0.0.1

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.
Files changed (167) hide show
  1. package/.github/FUNDING.yml +1 -0
  2. package/.github/ISSUE_TEMPLATE/bug_report.md +38 -0
  3. package/.github/ISSUE_TEMPLATE/custom.md +10 -0
  4. package/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  5. package/.github/pull_request_template.md +23 -0
  6. package/.github/workflows/npm-publish.yml +55 -0
  7. package/.swcrc +8 -0
  8. package/LICENSE +674 -0
  9. package/README.md +567 -0
  10. package/jest.config.js +20 -0
  11. package/package.json +56 -0
  12. package/src/consts/block.ts +22 -0
  13. package/src/consts/color.ts +6 -0
  14. package/src/consts/config.ts +2 -0
  15. package/src/consts/dimension.ts +69 -0
  16. package/src/consts/hatch.ts +52 -0
  17. package/src/consts/header.ts +10 -0
  18. package/src/consts/index.ts +9 -0
  19. package/src/consts/lineweight.ts +5 -0
  20. package/src/consts/measurement.ts +4 -0
  21. package/src/consts/obscuredLineTypes.ts +21 -0
  22. package/src/consts/scene.ts +2 -0
  23. package/src/consts/viewport.ts +62 -0
  24. package/src/index.ts +6 -0
  25. package/src/parser/AutoCadColorIndex.ts +265 -0
  26. package/src/parser/DxfArrayScanner.ts +161 -0
  27. package/src/parser/DxfParser.ts +108 -0
  28. package/src/parser/ParseHelpers.ts +124 -0
  29. package/src/parser/blocks/blocks.test.ts +97 -0
  30. package/src/parser/blocks/index.ts +88 -0
  31. package/src/parser/blocks/types.ts +15 -0
  32. package/src/parser/entities/arc/index.ts +2 -0
  33. package/src/parser/entities/arc/parser.ts +67 -0
  34. package/src/parser/entities/arc/types.ts +13 -0
  35. package/src/parser/entities/attdef/consts.ts +12 -0
  36. package/src/parser/entities/attdef/index.ts +3 -0
  37. package/src/parser/entities/attdef/parser.ts +119 -0
  38. package/src/parser/entities/attdef/types.ts +19 -0
  39. package/src/parser/entities/attribute/consts.ts +6 -0
  40. package/src/parser/entities/attribute/index.ts +3 -0
  41. package/src/parser/entities/attribute/parser.ts +198 -0
  42. package/src/parser/entities/attribute/types.ts +31 -0
  43. package/src/parser/entities/circle/index.ts +2 -0
  44. package/src/parser/entities/circle/parser.ts +58 -0
  45. package/src/parser/entities/circle/types.ts +11 -0
  46. package/src/parser/entities/dimension/common.ts +98 -0
  47. package/src/parser/entities/dimension/index.ts +24 -0
  48. package/src/parser/entities/dimension/types.ts +65 -0
  49. package/src/parser/entities/ellipse/index.ts +2 -0
  50. package/src/parser/entities/ellipse/parser.ts +66 -0
  51. package/src/parser/entities/ellipse/types.ts +13 -0
  52. package/src/parser/entities/entities.test.ts +86 -0
  53. package/src/parser/entities/hatch/boundaryPathData/edge.ts +190 -0
  54. package/src/parser/entities/hatch/boundaryPathData/index.ts +27 -0
  55. package/src/parser/entities/hatch/boundaryPathData/polyline.ts +43 -0
  56. package/src/parser/entities/hatch/boundaryPathData/shared.ts +16 -0
  57. package/src/parser/entities/hatch/index.ts +189 -0
  58. package/src/parser/entities/hatch/patternData.ts +57 -0
  59. package/src/parser/entities/hatch/types/boundaryPath.ts +72 -0
  60. package/src/parser/entities/hatch/types/definitionLine.ts +14 -0
  61. package/src/parser/entities/hatch/types/hatch.ts +47 -0
  62. package/src/parser/entities/hatch/types/index.ts +3 -0
  63. package/src/parser/entities/index.ts +87 -0
  64. package/src/parser/entities/insert/index.ts +2 -0
  65. package/src/parser/entities/insert/parser.ts +106 -0
  66. package/src/parser/entities/insert/types.ts +19 -0
  67. package/src/parser/entities/leader/consts.ts +6 -0
  68. package/src/parser/entities/leader/index.ts +3 -0
  69. package/src/parser/entities/leader/parser.ts +119 -0
  70. package/src/parser/entities/leader/types.ts +24 -0
  71. package/src/parser/entities/line/index.ts +2 -0
  72. package/src/parser/entities/line/parser.ts +55 -0
  73. package/src/parser/entities/line/types.ts +11 -0
  74. package/src/parser/entities/lwpolyline/consts.ts +4 -0
  75. package/src/parser/entities/lwpolyline/index.ts +3 -0
  76. package/src/parser/entities/lwpolyline/parser.ts +122 -0
  77. package/src/parser/entities/lwpolyline/types.ts +21 -0
  78. package/src/parser/entities/mtext/consts.ts +5 -0
  79. package/src/parser/entities/mtext/index.ts +3 -0
  80. package/src/parser/entities/mtext/parser.ts +195 -0
  81. package/src/parser/entities/mtext/types.ts +34 -0
  82. package/src/parser/entities/point/index.ts +2 -0
  83. package/src/parser/entities/point/parser.ts +60 -0
  84. package/src/parser/entities/point/types.ts +10 -0
  85. package/src/parser/entities/polyline/consts.ts +17 -0
  86. package/src/parser/entities/polyline/index.ts +3 -0
  87. package/src/parser/entities/polyline/parser.ts +126 -0
  88. package/src/parser/entities/polyline/types.ts +20 -0
  89. package/src/parser/entities/section/index.ts +2 -0
  90. package/src/parser/entities/section/parser.ts +104 -0
  91. package/src/parser/entities/section/types.ts +20 -0
  92. package/src/parser/entities/shared.ts +166 -0
  93. package/src/parser/entities/solid/index.ts +2 -0
  94. package/src/parser/entities/solid/parser.ts +56 -0
  95. package/src/parser/entities/solid/types.ts +10 -0
  96. package/src/parser/entities/spline/consts.ts +8 -0
  97. package/src/parser/entities/spline/index.ts +3 -0
  98. package/src/parser/entities/spline/parser.ts +121 -0
  99. package/src/parser/entities/spline/types.ts +22 -0
  100. package/src/parser/entities/text/consts.ts +21 -0
  101. package/src/parser/entities/text/index.ts +3 -0
  102. package/src/parser/entities/text/parser.ts +117 -0
  103. package/src/parser/entities/text/types.ts +21 -0
  104. package/src/parser/entities/vertex/consts.ts +10 -0
  105. package/src/parser/entities/vertex/index.ts +3 -0
  106. package/src/parser/entities/vertex/parser.ts +90 -0
  107. package/src/parser/entities/vertex/types.ts +17 -0
  108. package/src/parser/entities/viewport/index.ts +178 -0
  109. package/src/parser/entities/viewport/types.ts +58 -0
  110. package/src/parser/filterDummyBlocks.ts +49 -0
  111. package/src/parser/header/index.ts +30 -0
  112. package/src/parser/objects/common.ts +55 -0
  113. package/src/parser/objects/dictionary.ts +61 -0
  114. package/src/parser/objects/index.ts +45 -0
  115. package/src/parser/objects/layout.ts +136 -0
  116. package/src/parser/objects/plotSettings.ts +231 -0
  117. package/src/parser/objects/treefy.ts +53 -0
  118. package/src/parser/objects/types.ts +17 -0
  119. package/src/parser/shared/index.ts +21 -0
  120. package/src/parser/shared/parsePoint.ts +37 -0
  121. package/src/parser/shared/parserGenerator.test.ts +164 -0
  122. package/src/parser/shared/parserGenerator.ts +180 -0
  123. package/src/parser/shared/xdata/index.ts +3 -0
  124. package/src/parser/shared/xdata/interpreter.test.ts +85 -0
  125. package/src/parser/shared/xdata/interpreter.ts +65 -0
  126. package/src/parser/shared/xdata/parser.test.ts +66 -0
  127. package/src/parser/shared/xdata/parser.ts +140 -0
  128. package/src/parser/shared/xdata/types.ts +22 -0
  129. package/src/parser/tables/blockRecord/index.ts +2 -0
  130. package/src/parser/tables/blockRecord/parser.ts +49 -0
  131. package/src/parser/tables/blockRecord/types.ts +11 -0
  132. package/src/parser/tables/dimStyle/consts.ts +428 -0
  133. package/src/parser/tables/dimStyle/index.ts +3 -0
  134. package/src/parser/tables/dimStyle/parser.ts +37 -0
  135. package/src/parser/tables/dimStyle/types.ts +164 -0
  136. package/src/parser/tables/index.ts +2 -0
  137. package/src/parser/tables/layer/index.ts +2 -0
  138. package/src/parser/tables/layer/parser.ts +58 -0
  139. package/src/parser/tables/layer/types.ts +14 -0
  140. package/src/parser/tables/ltype/consts.ts +6 -0
  141. package/src/parser/tables/ltype/index.ts +3 -0
  142. package/src/parser/tables/ltype/parser.ts +110 -0
  143. package/src/parser/tables/ltype/types.ts +23 -0
  144. package/src/parser/tables/parser.ts +100 -0
  145. package/src/parser/tables/shared.ts +32 -0
  146. package/src/parser/tables/style/index.ts +2 -0
  147. package/src/parser/tables/style/parser.ts +70 -0
  148. package/src/parser/tables/style/types.ts +15 -0
  149. package/src/parser/tables/types.ts +15 -0
  150. package/src/parser/tables/vport/index.ts +2 -0
  151. package/src/parser/tables/vport/parser.ts +205 -0
  152. package/src/parser/tables/vport/types.ts +48 -0
  153. package/src/parser/types.ts +30 -0
  154. package/src/types/color.ts +5 -0
  155. package/src/types/dxfHeader.ts +21 -0
  156. package/src/types/entity.ts +7 -0
  157. package/src/types/index.ts +30 -0
  158. package/src/utils/binarySearch.ts +20 -0
  159. package/src/utils/disjointSet.ts +52 -0
  160. package/src/utils/flooding.ts +37 -0
  161. package/src/utils/functional.ts +124 -0
  162. package/src/utils/graph.ts +53 -0
  163. package/src/utils/index.ts +102 -0
  164. package/src/utils/queue.ts +77 -0
  165. package/src/utils/triangle.ts +28 -0
  166. package/tsconfig.json +34 -0
  167. package/webpack.config.js +46 -0
@@ -0,0 +1,85 @@
1
+ import { createXDataControlInterpreter } from './interpreter';
2
+
3
+ describe('xdata:interpreter', () => {
4
+ it('xdata 엔트리들이 name-value 쌍이면 객체에 snippet대로 풀어서 반환한다', () => {
5
+ const interpreter = createXDataControlInterpreter([
6
+ {
7
+ code: 40,
8
+ name: '$DIMSCALE',
9
+ },
10
+ {
11
+ code: 172,
12
+ name: 'dim-line-forced',
13
+ },
14
+ {
15
+ code: 175,
16
+ name: 'dim-line-inside',
17
+ },
18
+ ]);
19
+
20
+ const result = interpreter([
21
+ {
22
+ value: 40,
23
+ },
24
+ {
25
+ value: 2.0,
26
+ },
27
+ {
28
+ value: 175,
29
+ },
30
+ {
31
+ value: 0,
32
+ },
33
+ {
34
+ value: 172,
35
+ },
36
+ {
37
+ value: 1,
38
+ },
39
+ ]);
40
+ // @ts-ignore
41
+ expect(result['$DIMSCALE']).toBe(2.0);
42
+ // @ts-ignore
43
+ expect(result['dim-line-forced']).toBe(1);
44
+ // @ts-ignore
45
+ expect(result['dim-line-inside']).toBe(0);
46
+ });
47
+
48
+ it('snippet에 없는 쌍은 무시한다.', () => {
49
+ const interpreter = createXDataControlInterpreter([
50
+ {
51
+ code: 40,
52
+ name: '$DIMSCALE',
53
+ type: 'real',
54
+ },
55
+ ]);
56
+
57
+ const result = interpreter([
58
+ {
59
+ value: 175,
60
+ },
61
+ {
62
+ value: 0,
63
+ },
64
+ {
65
+ value: 40,
66
+ },
67
+ {
68
+ value: 2.0,
69
+ },
70
+ {
71
+ value: 172,
72
+ },
73
+ {
74
+ value: 1,
75
+ },
76
+ ]);
77
+
78
+ // @ts-ignore
79
+ expect(result['$DIMSCALE']).toBe(2.0);
80
+ // @ts-ignore
81
+ expect(result['dim-line-forced']).toBe(undefined);
82
+ // @ts-ignore
83
+ expect(result['dim-line-inside']).toBe(undefined);
84
+ });
85
+ });
@@ -0,0 +1,65 @@
1
+ import type { XData, XDataEntry } from './types';
2
+
3
+ export type XDataInterpreterSnippet<Name extends string> = {
4
+ code: number;
5
+ name: Name;
6
+ };
7
+
8
+ type PackPairType<Snippets> = Snippets extends readonly [infer X, ...infer R]
9
+ ? X extends XDataInterpreterSnippet<infer N>
10
+ ? { [key in N]?: any } & PackPairType<R>
11
+ : PackPairType<R>
12
+ : {};
13
+
14
+ /**
15
+ * xdata가 code-value의 연속인 경우에 사용 가능
16
+ * ex) DSTYLE
17
+ */
18
+ export function createXDataControlInterpreter<
19
+ T extends readonly XDataInterpreterSnippet<string>[],
20
+ >(snippets: T) {
21
+ return (entries: XDataEntry[]): PackPairType<T> => {
22
+ const result = {} as PackPairType<T>;
23
+
24
+ for (let i = 0; i < entries.length; i += 2) {
25
+ const snippet = snippets.find(
26
+ ({ code }) => code === entries[i].value,
27
+ );
28
+
29
+ if (!snippet) continue;
30
+ // @ts-ignore
31
+ result[snippet.name] = entries[i + 1]?.value;
32
+ }
33
+
34
+ return result;
35
+ };
36
+ }
37
+
38
+ interface CreateXDataCatcherParams {
39
+ appName?: string;
40
+ catcher(entry: XDataEntry): boolean;
41
+ escaper?(entry: XDataEntry, count: number): boolean; // 몇 번째인지. 1부터 셈.
42
+ }
43
+
44
+ export function createXDataCatcher({
45
+ appName = 'ACAD',
46
+ catcher,
47
+ escaper,
48
+ }: CreateXDataCatcherParams) {
49
+ return function* (xdata?: XData) {
50
+ if (xdata?.appName !== appName) return;
51
+
52
+ let isCatchable = false;
53
+ let startIndex = -1;
54
+ for (const [index, entry] of xdata.value.entries()) {
55
+ if (isCatchable) {
56
+ yield entry;
57
+
58
+ if (escaper?.(entry, index - startIndex)) return;
59
+ } else if (catcher(entry)) {
60
+ isCatchable = true;
61
+ startIndex = index;
62
+ }
63
+ }
64
+ };
65
+ }
@@ -0,0 +1,66 @@
1
+ import DxfArrayScanner from '../../DxfArrayScanner';
2
+ import { parseXData } from './parser';
3
+
4
+ describe('xdata:parser', () => {
5
+ it('xdata entry를 순차적으로 파싱하여 배열로 반환해야 한다', () => {
6
+ const scanner = new DxfArrayScanner(
7
+ `1001
8
+ ACAD
9
+ 1000
10
+ DSTYLE
11
+ 1070
12
+ 171
13
+ `.split('\n'),
14
+ );
15
+ const curr = scanner.next();
16
+ const result = parseXData(curr, scanner);
17
+
18
+ expect(result.appName).toBe('ACAD');
19
+ expect(result.value.length).toBe(2);
20
+ expect(result.value[0].value).toBe('DSTYLE');
21
+ expect(result.value[1].value).toBe(171);
22
+ });
23
+
24
+ it('중첩된 xdata entry를 중첩된 배열로 반환해야 한다.', () => {
25
+ const scanner = new DxfArrayScanner(
26
+ `1001
27
+ ACAD
28
+ 1000
29
+ a
30
+ 1002
31
+ {
32
+ 1000
33
+ b
34
+ 1000
35
+ c
36
+ 1002
37
+ }
38
+ 1000
39
+ d
40
+ `.split('\n'),
41
+ );
42
+ const curr = scanner.next();
43
+ const result = parseXData(curr, scanner);
44
+
45
+ expect(result.value).toMatchObject([
46
+ {
47
+ type: 'string',
48
+ value: 'a',
49
+ },
50
+ [
51
+ {
52
+ type: 'string',
53
+ value: 'b',
54
+ },
55
+ {
56
+ type: 'string',
57
+ value: 'c',
58
+ },
59
+ ],
60
+ {
61
+ type: 'string',
62
+ value: 'd',
63
+ },
64
+ ]);
65
+ });
66
+ });
@@ -0,0 +1,140 @@
1
+ import { isMatched } from '..';
2
+ import type { ScannerGroup } from '../../DxfArrayScanner';
3
+ import type DxfArrayScanner from '../../DxfArrayScanner';
4
+ import { parsePoint } from '../parsePoint';
5
+ import { DXFParserSnippet } from '../parserGenerator';
6
+ import type { XData, XDataEntry } from './types';
7
+
8
+ export const XDataParserSnippets: DXFParserSnippet[] = [
9
+ {
10
+ code: 1001,
11
+ name: 'xdata',
12
+ parser: parseXData,
13
+ },
14
+ ];
15
+
16
+ export function parseXData(curr: ScannerGroup, scanner: DxfArrayScanner) {
17
+ if (!isMatched(curr, 1001)) {
18
+ throw new Error('XData must starts with code 1001');
19
+ }
20
+
21
+ const xdata: XData = {
22
+ appName: curr.value,
23
+ value: [] as XDataEntry[],
24
+ };
25
+
26
+ curr = scanner.next();
27
+
28
+ const stack = [xdata.value] as any[][];
29
+
30
+ while (!isMatched(curr, 0, 'EOF') && curr.code >= 1000) {
31
+ const top = stack.at(-1)!;
32
+
33
+ switch (curr.code) {
34
+ case 1002:
35
+ if (curr.value === '{') {
36
+ stack.push([]);
37
+ } else {
38
+ stack.pop();
39
+ stack.at(-1)?.push(top);
40
+ }
41
+ break;
42
+ case 1000: // string
43
+ case 1004: // hex string
44
+ case 1040: // real
45
+ case 1070: // integer
46
+ case 1071: // long
47
+ top.push({
48
+ type: getType(curr.code),
49
+ value: curr.value,
50
+ });
51
+ break;
52
+ case 1003:
53
+ top.push({
54
+ name: 'layer',
55
+ type: getType(curr.code),
56
+ value: curr.value,
57
+ });
58
+ break;
59
+ case 1005:
60
+ top.push({
61
+ name: 'handle',
62
+ type: getType(curr.code),
63
+ value: curr.value,
64
+ });
65
+ break;
66
+ case 1010: // just 3 reals
67
+ top.push({
68
+ type: getType(curr.code),
69
+ value: parsePoint(scanner),
70
+ });
71
+ break;
72
+ case 1011:
73
+ top.push({
74
+ name: 'worldSpacePosition',
75
+ type: getType(curr.code),
76
+ value: parsePoint(scanner),
77
+ });
78
+ break;
79
+ case 1012:
80
+ top.push({
81
+ name: 'worldSpaceDisplacement',
82
+ type: getType(curr.code),
83
+ value: parsePoint(scanner),
84
+ });
85
+ break;
86
+ case 1013:
87
+ top.push({
88
+ name: 'worldSpaceDirection',
89
+ type: getType(curr.code),
90
+ value: parsePoint(scanner),
91
+ });
92
+ break;
93
+ case 1041:
94
+ top.push({
95
+ name: 'distance',
96
+ type: getType(curr.code),
97
+ value: curr.value,
98
+ });
99
+ break;
100
+ case 1042:
101
+ top.push({
102
+ name: 'scale',
103
+ type: getType(curr.code),
104
+ value: curr.value,
105
+ });
106
+ break;
107
+ }
108
+
109
+ curr = scanner.next();
110
+ }
111
+
112
+ scanner.rewind();
113
+ return xdata;
114
+ }
115
+
116
+ function getType(code: number) {
117
+ switch (code) {
118
+ case 1000:
119
+ case 1003:
120
+ case 1005:
121
+ return 'string';
122
+ case 1004:
123
+ return 'hex';
124
+ case 1040:
125
+ case 1041:
126
+ case 1042:
127
+ return 'real';
128
+ case 1070:
129
+ return 'integer';
130
+ case 1071:
131
+ return 'long';
132
+ case 1010:
133
+ case 1011:
134
+ case 1012:
135
+ case 1013:
136
+ return 'point';
137
+ default:
138
+ return '';
139
+ }
140
+ }
@@ -0,0 +1,22 @@
1
+ import type { Point3D } from '../../../types';
2
+
3
+ /*
4
+ https://help.autodesk.com/view/OARX/2023/ENU/?guid=GUID-A2A628B0-3699-4740-A215-C560E7242F63
5
+
6
+ 확장 데이터는 LISP 언어 형식으로 작성되는데, 대충 재귀적인 배열 구조라고 생각하면 된다.
7
+ 이 구조는 AutoCAD 혹은 서드파티가 알아서 정의하고 쓰므로 신경꺼도 좋다.
8
+ (ex: [1, 2, 'babo', [3], 3.14, [[]]])
9
+
10
+ 각 깊이는 1002번 코드의 {로 시작하여 }로 끝난다.
11
+ 이 값들은 DXF 일반 코드와 다르게 이름이 있기도 하고 없기도 하여, 아래와 같은 자료 구조로 저장한다.
12
+ */
13
+
14
+ export interface XData {
15
+ appName: string;
16
+ value: XDataEntry[];
17
+ }
18
+
19
+ export interface XDataEntry {
20
+ name?: string;
21
+ value: XDataEntry[] | number | string | Point3D;
22
+ }
@@ -0,0 +1,2 @@
1
+ export * from './types';
2
+ export * from './parser';
@@ -0,0 +1,49 @@
1
+ import {
2
+ createParser,
3
+ DXFParserSnippet,
4
+ Identity,
5
+ } from '../../shared/parserGenerator';
6
+ import { CommonTableEntryParserSnippets } from '../shared';
7
+
8
+ const BlockRecordTableParserSnippets: DXFParserSnippet[] = [
9
+ {
10
+ code: 310,
11
+ name: 'bmpPreview',
12
+ parser: Identity,
13
+ },
14
+ {
15
+ code: 281,
16
+ name: 'scalability',
17
+ parser: Identity,
18
+ },
19
+ {
20
+ code: 280,
21
+ name: 'explodability',
22
+ parser: Identity,
23
+ },
24
+ {
25
+ code: 70,
26
+ name: 'insertionUnits',
27
+ parser: Identity,
28
+ },
29
+ {
30
+ code: 340,
31
+ name: 'layoutObjects',
32
+ parser: Identity,
33
+ },
34
+ {
35
+ code: 2,
36
+ name: 'name',
37
+ parser: Identity,
38
+ },
39
+ {
40
+ code: 100,
41
+ name: 'subclassMarker',
42
+ parser: Identity,
43
+ },
44
+ ...CommonTableEntryParserSnippets,
45
+ ];
46
+
47
+ export const parseBlockRecordTable = createParser(
48
+ BlockRecordTableParserSnippets,
49
+ );
@@ -0,0 +1,11 @@
1
+ import type { CommonDxfTableEntry } from '../types';
2
+
3
+ export interface BlockRecordTableEntry extends CommonDxfTableEntry {
4
+ subclassMarker: 'AcDbBlockTableRecord';
5
+ name: string;
6
+ layoutObjects: string;
7
+ insertionUnits: number;
8
+ explodability: number;
9
+ scalability: number;
10
+ bmpPreview: string;
11
+ }