1
+ import { Colors , DLine , DxfWriter , point3d , SplineArgs_t , SplineFlags , Units , vec3_t } from '@tarikjabiri/dxf' ;
2
+ import { Arc } from './shapes/arc' ;
3
+ import { BezierCurve } from './shapes/bezier-curve' ;
4
+ import { Circle } from './shapes/circle' ;
5
+ import { AngleBetweenDimension , DiameterDimension , HDimension , LinearDimension , VDimension } from './shapes/dim' ;
6
+ import { Ellipse } from './shapes/ellipse' ;
7
+ import { Label } from './shapes/label' ;
8
+ import { EndPoint } from './shapes/point' ;
9
+ import { Segment } from './shapes/segment' ;
10
+ import { SketchObject } from './shapes/sketch-object' ;
11
+ import { Layer } from './viewer2d' ;
12
+
13
+ function deg2rad ( a : number ) {
14
+ return ( a * Math . PI ) / 180 ;
15
+ }
16
+
17
+ export class DxfWriterAdapter {
18
+ writer : DxfWriter ;
19
+
20
+ constructor ( ) {
21
+ this . writer = new DxfWriter ( ) ;
22
+ this . writer . setUnits ( Units . Millimeters ) ;
23
+
24
+ // Dimensions customization
25
+ // I hard coded these values but I am not sure about them
26
+ this . writer . setVariable ( '$DIMTXT' , { 40 : 10 } ) ; // The text height
27
+ this . writer . setVariable ( '$DIMASZ' , { 40 : 10 } ) ; // Dimensioning arrow size
28
+
29
+ // Theses for preserving the look like jsketcher
30
+ this . writer . setVariable ( '$DIMDEC' , { 70 : 2 } ) ; // Number of precision places displayed
31
+ this . writer . setVariable ( '$DIMTIH' , { 70 : 0 } ) ; // Text inside horizontal if nonzero
32
+ this . writer . setVariable ( '$DIMTOH' , { 70 : 0 } ) ; // Text outside horizontal if nonzero
33
+ // Do not force text inside extensions
34
+ this . writer . setVariable ( '$DIMTIX' , { 70 : 0 } ) ; // Force text inside extensions if nonzero
35
+ this . writer . setVariable ( '$DIMATFIT' , { 70 : 0 } ) ; // Controls dimension text and arrow placement
36
+
37
+ // For more customization
38
+ // this.writer.setVariable('$DIMEXE', { 40: 10 }); // Extension line extension
39
+ // this.writer.setVariable('$DIMCLRD', { 70: Colors.Yellow }); // Dimension line color
40
+ // this.writer.setVariable('$DIMCLRE', { 70: Colors.Red }); // Dimension extension line color
41
+ // this.writer.setVariable('$DIMCLRT', { 70: Colors.Green }); // Dimension text color
42
+ // this.writer.setVariable('$DIMTIX', { 70: 1 }); // Force text inside extensions if nonzero
43
+ }
44
+
45
+ private _point ( shape : EndPoint ) {
46
+ this . writer . addPoint ( shape . x , shape . y , 0 ) ;
47
+ }
48
+
49
+ private _segment ( shape : Segment ) {
50
+ this . writer . addLine ( point3d ( shape . a . x , shape . a . y ) , point3d ( shape . b . x , shape . b . y ) ) ;
51
+ }
52
+
53
+ private _arc ( shape : Arc ) {
54
+ this . writer . addArc (
55
+ point3d ( shape . c . x , shape . c . y ) ,
56
+ shape . r . get ( ) ,
57
+ deg2rad ( shape . getStartAngle ( ) ) ,
58
+ deg2rad ( shape . getEndAngle ( ) )
59
+ ) ;
60
+ }
61
+
62
+ private _circle ( shape : Circle ) {
63
+ this . writer . addCircle ( point3d ( shape . c . x , shape . c . y ) , shape . r . get ( ) ) ;
64
+ }
65
+
66
+ private _ellipse ( shape : Ellipse ) {
67
+ const majorX = Math . cos ( shape . rotation ) * shape . radiusX ;
68
+ const majorY = Math . sin ( shape . rotation ) * shape . radiusX ;
69
+ this . writer . addEllipse (
70
+ point3d ( shape . centerX , shape . centerY ) ,
71
+ point3d ( majorX , majorY ) ,
72
+ shape . radiusY / shape . radiusX ,
73
+ 0 ,
74
+ 2 * Math . PI
75
+ ) ;
76
+ }
77
+
78
+ private _bezier ( shape : BezierCurve ) {
79
+ const controlPoints : vec3_t [ ] = [
80
+ point3d ( shape . p0 . x , shape . p0 . y ) ,
81
+ point3d ( shape . p1 . x , shape . p1 . y ) ,
82
+ point3d ( shape . p2 . x , shape . p2 . y ) ,
83
+ point3d ( shape . p3 . x , shape . p3 . y ) ,
84
+ ] ;
85
+ const splineArgs : SplineArgs_t = {
86
+ controlPoints,
87
+ flags : SplineFlags . Periodic ,
88
+ } ;
89
+ this . writer . addSpline ( splineArgs ) ;
90
+ }
91
+
92
+ private _label ( shape : Label ) {
93
+ const m = shape . assignedObject . labelCenter ;
94
+ if ( ! m ) return ;
95
+ const height = shape . textHelper . fontSize ;
96
+ const h = shape . textHelper . textMetrics . width / 2 ;
97
+ const lx = m . x - h + shape . offsetX ;
98
+ const ly = m . y + shape . marginOffset + shape . offsetY ;
99
+ this . writer . addText ( point3d ( lx , ly ) , height , shape . text ) ;
100
+ }
101
+
102
+ private _vdim ( shape : VDimension ) {
103
+ this . writer . addLinearDim ( point3d ( shape . a . x , shape . a . y ) , point3d ( shape . b . x , shape . b . y ) , {
104
+ angle : 90 , // Make it vertical
105
+ offset : - shape . offset ,
106
+ } ) ;
107
+ }
108
+
109
+ private _hdim ( shape : HDimension ) {
110
+ this . writer . addLinearDim ( point3d ( shape . a . x , shape . a . y ) , point3d ( shape . b . x , shape . b . y ) , { offset : - shape . offset } ) ;
111
+ }
112
+
113
+ private _linearDim ( shape : LinearDimension ) {
114
+ this . writer . addAlignedDim ( point3d ( shape . a . x , shape . a . y ) , point3d ( shape . b . x , shape . b . y ) , { offset : shape . offset } ) ;
115
+ }
116
+
117
+ private _ddim ( shape : DiameterDimension ) {
118
+ // I remarked that the DiameterDimension looks like Radius dimension so I used RadialDim
119
+ const radius = shape . obj . distanceA ? shape . obj . distanceA ( ) : shape . obj . r . get ( ) ;
120
+ const x = shape . obj . c . x + radius * Math . cos ( shape . angle ) ;
121
+ const y = shape . obj . c . y + radius * Math . sin ( shape . angle ) ;
122
+ this . writer . addRadialDim ( point3d ( x , y ) , point3d ( shape . obj . c . x , shape . obj . c . y ) ) ;
123
+ }
124
+
125
+ private _bwdim ( shape : AngleBetweenDimension ) {
126
+ // This is not working as expected.
127
+ const s : DLine = {
128
+ start : point3d ( shape . a . a . x , shape . a . a . y ) ,
129
+ end : point3d ( shape . a . b . x , shape . a . b . y ) ,
130
+ } ;
131
+ const f : DLine = {
132
+ start : point3d ( shape . b . a . x , shape . b . a . y ) ,
133
+ end : point3d ( shape . b . b . x , shape . b . b . y ) ,
134
+ } ;
135
+ const c = point3d ( shape . a . a . x , shape . a . a . y ) ;
136
+ const offset = shape . offset ;
137
+ const dyf = f . end . y - c . y ;
138
+ const dys = s . end . y - c . y ;
139
+ const df = Math . sqrt ( Math . pow ( f . end . x - c . x , 2 ) + Math . pow ( f . end . y - c . y , 2 ) ) ;
140
+ const ds = Math . sqrt ( Math . pow ( s . end . x - c . x , 2 ) + Math . pow ( s . end . y - c . y , 2 ) ) ;
141
+ const alphaf = Math . acos ( dyf / df ) ;
142
+ const alphas = Math . acos ( dys / ds ) ;
143
+ const alpham = Math . abs ( alphaf - alphas ) / 2 + ( alphaf > alphas ? alphas : alphaf ) ;
144
+ const xm = c . x + offset * Math . cos ( alpham )
145
+ const ym = c . y + offset * Math . sin ( alpham )
146
+ this . writer . addAngularLinesDim ( f , s , point3d ( xm , ym ) ) ;
147
+ }
148
+
149
+ export ( layers : Layer < SketchObject > [ ] ) {
150
+ layers . forEach ( layer => {
151
+ // this will prevent addLayer from throwing.
152
+ if ( ! this . writer . tables . layerTable . exist ( layer . name ) )
153
+ this . writer . addLayer ( layer . name , Colors . Black , 'Continuous' ) ;
154
+ this . writer . setCurrentLayerName ( layer . name ) ;
155
+
156
+ layer . objects . forEach ( shape => {
157
+ if ( shape instanceof EndPoint ) this . _point ( shape ) ;
158
+ else if ( shape instanceof Segment ) this . _segment ( shape ) ;
159
+ else if ( shape instanceof Arc ) this . _arc ( shape ) ;
160
+ else if ( shape instanceof Circle ) this . _circle ( shape ) ;
161
+ else if ( shape instanceof Ellipse ) this . _ellipse ( shape ) ;
162
+ else if ( shape instanceof BezierCurve ) this . _bezier ( shape ) ;
163
+ else if ( shape instanceof Label ) this . _label ( shape ) ;
164
+ else if ( shape instanceof VDimension ) this . _vdim ( shape ) ;
165
+ else if ( shape instanceof HDimension ) this . _hdim ( shape ) ;
166
+ else if ( shape instanceof LinearDimension ) this . _linearDim ( shape ) ;
167
+ else if ( shape instanceof DiameterDimension ) this . _ddim ( shape ) ;
168
+ else if ( shape instanceof AngleBetweenDimension ) this . _bwdim ( shape ) ;
169
+ } ) ;
170
+ } ) ;
171
+ }
172
+
173
+ stringify ( ) : string {
174
+ // reset the current layer to 0, because its preserved in the dxf.
175
+ this . writer . setCurrentLayerName ( '0' ) ;
176
+ return this . writer . stringify ( ) ;
177
+ }
178
+ }
0 commit comments