home *** CD-ROM | disk | FTP | other *** search
/ Computer Discount - Smash Disk / SmashDisk.bin / Cdc / Autodesk / ITALIANO / ACLT / ATLAST.DXT < prev    next >
Text File  |  1997-11-27  |  90KB  |  2,667 lines

  1.  
  2. \ Notes, bugs and problems:
  3. \  2. The anonymous blocks *MODEL_SPACE and *PAPER_SPACE in R13 are changed
  4. \     to the named blocks $MODEL_SPACE and $PAPER_SPACE in the R12 dxf file.
  5. \  3. A RAY or XLINE without any entities will result in an exceedingly
  6. \     small line due to the small drawing extents. Putting a non-infinite
  7. \     entity in the drawing will remedy this problem.
  8. \  4. *STACK 10000  - This doesn't seem to work since dictionary entries
  9. \                     have already been made.
  10. \  5. The stack notation: ( ... n n ) , used in the defining words below,
  11. \     assumes that the stack grows from left to right with the right most
  12. \     term being on top.
  13. \  6. Make sure you have enough disk space for the output file, otherwise
  14. \     you will get no output.
  15. \
  16. \ =======================================================================
  17. \ README information April 1997:
  18. \   Header variables DWGCODEPAGE, TREEDEPTH and PINSBASE
  19. \
  20. \   in order to comply with R12 DXF file standards as formulated in the
  21. \   EQM (European Quality Manual) the above header variables are removed
  22. \   for R12 DXF files. In case they are needed, this translation file can 
  23. \   be edited and the corresponding statements remove dxf:header:... can 
  24. \   get commented out.
  25. \
  26. \   Fonts with Full Path Names :
  27. \
  28. \   in accordance with the behaviour of R13 writing out R12 drawing files,
  29. \   all *.ttf and *.pfa based text styles are set to txt. If you don't want 
  30. \   the font file path removed by dxfix, comment the statement following the
  31. \   line 'replace all *.ttf and *.pfa text styles with txt' out.
  32. \   OCTREE 6 Error:
  33. \     Some DXF files, created in Release 12, or created after using
  34. \     the DXF translator, result in this error while being read in.
  35. \     To "repair" the DXF file so that it can be read in, change the
  36. \     value of TREEDEPTH Group 70 to 3020.  If desired, this value
  37. \     can then be reset to 0 from inside of AutoCAD, after the
  38. \     drawing has been read in.
  39. \ =======================================================================
  40. \   Rules for translating AutoCAD Release 13 DXF files to Release 12
  41. \     Command line options: -x => Delete RAYs and XLINEs, otherwise if this
  42. \                                 option is not present they will be replaced
  43. \                                 by finite lines that approximate the drawing
  44. \                                 extents.
  45. \
  46. \
  47. \   Changes made by this program to go from R13 to R12 DXF:
  48. \   1. $ACADVER changed from AC1012 to AC1009
  49. \     The following HEADER section variables were deleted:
  50. \   2. $CELTSCALE
  51. \   3. $DELOBJ
  52. \   4. $DISPSILH
  53. \   5. $DIMJUST
  54. \   6. $DIMSD1
  55. \   7. $DIMSD2
  56. \   8. $DIMTOLJ
  57. \   9. $DIMTZIN
  58. \  10. $DIMALTZ
  59. \  11. $DIMALTTZ
  60. \  12. $DIMFIT
  61. \  13. $DIMUPT
  62. \  14. $DIMUNIT
  63. \  15. $DIMDEC
  64. \  16. $DIMTDEC
  65. \  17. $DIMALTU
  66. \  18. $DIMALTTD
  67. \  19. $DIMTXSTY
  68. \  20. $DIMAUNIT
  69. \  21. $CHAMFERC
  70. \  22. $CHAMFERD
  71. \  23. $PICKSTYLE
  72. \  24. $CMLSTYLE
  73. \  25. $CMLJUST
  74. \  26. $CMLSCALE
  75. \  27. $SAVEIMAGES
  76. \  see remarks above: $DWGCODEPAGE, $TREEDEPTH, $PINSBASE
  77. \
  78. \  28. CLASSES section deleted
  79. \  29. OBJECTS section deleted
  80. \  30. Delete 300-369 groups - arbitrary strings, chunks and handles
  81. \  31. Delete 100 groups - AcDb... groups (eg. AcDbSymbolTable, AcDbLinetypeTableRecord, etc)
  82. \
  83. \     The following ENTITIES section objects were changed:
  84. \  32. RAY changed into a long, but finite, line.
  85. \  33. ELLIPSE decomposed into polyline vertex segments.
  86. \  34. BODY deleted.
  87. \  35. OLEFRAME deleted.
  88. \  36. 3DSOLID deleted.
  89. \  37. DIMENSION removed -3 group.
  90. \  38. INSERT removed -3 group.
  91. \  39. VIEWPORT removed -3 group.
  92. \  40. LEADER decomposed into polyline vertex segments.
  93. \  41. MLINE deleted.
  94. \  42. TOLERANCE deleted.
  95. \  43. REGION deleted.
  96. \  44. XLINE changed into a long, but finite, line.
  97. \  45. MTEXT changed to TEXT.
  98. \  46. SEQEND removed the -2 group.
  99. \  47. SPLINE decomposed into polyline vertex segments.
  100. \  48. ZOMBIE_ENTITY deleted.
  101.  
  102. \ 'bignum' used to make RAYs and XLINEs long, finite lines.
  103. 1.0E99 2constant bignum
  104. 1.0E-3 2constant bignumerror
  105. 50 constant iterator
  106. 7 constant unicount
  107. 1.0 atan 4.0 f* 2constant pi
  108. 2.7182818 2constant e
  109. 180.0 pi f/ 2constant radToDeg
  110. pi 180.0 f/ 2constant degToRad
  111. 0 constant false
  112. -1 constant true
  113.  
  114. 241 constant tolerSymbol
  115.  
  116. \ DOS produces this one ...
  117. 248 constant degreeSymbol
  118. \ ... and Windows produces this one.
  119. 176 constant altDegreeSymbol
  120.  
  121. 123 constant leftBrace
  122. 125 constant rightBrace
  123. 92  constant backSlash
  124. 94  constant separator
  125. 47  constant forwardSlash
  126. 59  constant semicolon
  127. 37  constant percent
  128. 32  constant space
  129. 48  constant ascii0
  130. 49  constant ascii1
  131. 50  constant ascii2
  132. 51  constant ascii3
  133. 52  constant ascii4
  134. 53  constant ascii5
  135. 54  constant ascii6
  136. 55  constant ascii7
  137. 56  constant ascii8
  138. 57  constant ascii9
  139. 100 constant littleD
  140. 108 constant littleL
  141. 111 constant littleO
  142. 117 constant littleU
  143. 65  constant bigA
  144. 67  constant bigC
  145. 70  constant bigF
  146. 72  constant bigH
  147. 76  constant bigL
  148. 79  constant bigO
  149. 80  constant bigP
  150. 81  constant bigQ
  151. 83  constant bigS
  152. 84  constant bigT
  153. 85  constant bigU
  154. 87  constant bigW
  155. -1  constant EOF
  156. 0   constant EOS
  157.  
  158. 4 constant cell
  159. : cells cell * ;
  160. : cell+ cell + ;
  161.  
  162. 2variable bignumhi
  163. 2variable bignumlo
  164.  
  165. 2variable xmax
  166. 2variable ymax
  167. 2variable zmax
  168. variable maxset
  169.  
  170. 2variable xmin
  171. 2variable ymin
  172. 2variable zmin
  173. variable minset
  174.  
  175. variable handlesOn
  176. variable nextHandle
  177. variable needToRewind
  178.  
  179. variable layer
  180.  
  181. variable icount
  182. variable jcount
  183. variable loopCount
  184. variable maxi
  185. variable maxj
  186. 2variable ftmp
  187.  
  188. variable delEndBlock
  189.  
  190. \ MText variables
  191. variable fixedMtextGroups
  192. variable countChar
  193. variable thisChar
  194. variable nextChar
  195. variable group72
  196. 2variable textHeight
  197. 2variable textRotationPrimary
  198. 2variable textRotation
  199. variable color
  200. variable 62group
  201. 80 string mtextStyle
  202. variable 7group
  203. 5 string unicodeStr
  204. 5 string diameter
  205. 5 string toler
  206. 5 string degree
  207. 0.3 2constant mtextFudge
  208. \ R12 will not accept more than 256 characters in a DXF text entity.
  209. \ Oddly, you can 'saveasr12' in R13 with more than 256 characters in an
  210. \ MText entity and import the drawing into R12. However, doing a DXFOUT
  211. \ followed by DXFIN on that same drawing in R12 will result in an error.
  212. 256 constant mtextMaxLength
  213. file mtextFileA
  214.  
  215. \ Ellipse variables
  216. 2variable ellipsea
  217. 2variable ellipseb
  218. 2variable ellipsestartangle
  219. 2variable ellipseendangle
  220. 2variable ellipseangleincr
  221.  
  222. \ Spline variables
  223. 32 constant splineConstant
  224. variable splineIterator
  225. 2variable firstKnot
  226. 2variable knotInterval
  227.  
  228. \ Number of segments used to approximate an ellipse.
  229. 128 constant ellipseSteps
  230. 1.0E-3 2constant ellipseanglefuzz
  231.  
  232. \ Create a matrix of doubles
  233. : matrix
  234.     create 2dup , , * 8 * allot
  235. ;
  236.  
  237. \                                    Stack on entering:           Stack on leaving:
  238. : element                            ( ... r c addr1 )            ( ... addr1+x )
  239.     dup >r                           ( ... r c addr1 )
  240.     @                                ( ... r c columns )
  241.     rot                              ( ... c columns r )
  242.     * +                              ( ... columns*r+c )
  243.     \ Since the array consists of doubles, multiply by 8.
  244.     8 *
  245.     \ Offset from the columns and rows stored at the head of this array.
  246.     8 +
  247.     r> +                             ( ... addr1+x )
  248. ;
  249.  
  250. 1 3 matrix extentsMinSave
  251. 1 3 matrix extentsMaxSave
  252. 1 3 matrix vector
  253. 1 3 matrix result
  254. 1 3 matrix offset
  255. 1 3 matrix extrusion
  256. 3 3 matrix rotationMatrix
  257.  
  258. \                                    Stack on entering:           Stack on leaving:
  259. : 3x3print                           ( ... addr )                 ( ... )
  260.     cr ." "Row Column Value" cr
  261.     0 icount !
  262.     begin
  263.     0 jcount !
  264.     icount @ 3 <
  265.     while
  266.         begin
  267.         jcount @ 3 <
  268.         while
  269.             icount @ dup .           ( ... addr icount )
  270.             jcount @ dup .           ( ... addr icount jcount )
  271.             2 pick                   ( ... addr icount jcount addr )
  272.             element 2@ f. cr         ( ... addr )
  273.             1 jcount +!
  274.         repeat
  275.         1 icount +!
  276.     repeat
  277.     drop                             ( ... )
  278. ;
  279.  
  280. \                                    Stack on entering:           Stack on leaving:
  281. : matrixprint                        ( ... row col addr )         ( ... )
  282.     cr ." "Row Column Value" cr
  283.     swap                             ( ... row addr col )
  284.     maxj !                           ( ... row addr )
  285.     swap                             ( ... addr row )
  286.     maxi !                           ( ... addr )
  287.     0 icount !
  288.     begin
  289.     0 jcount !
  290.     icount @ maxi @ <
  291.     while
  292.         begin
  293.         jcount @ maxj @ <
  294.         while
  295.             icount @ dup .           ( ... addr icount )
  296.             jcount @ dup .           ( ... addr icount jcount )
  297.             2 pick                   ( ... addr icount jcount addr )
  298.             element 2@ f. cr         ( ... addr )
  299.             1 jcount +!
  300.         repeat
  301.         1 icount +!
  302.     repeat
  303.     drop                             ( ... )
  304. ;
  305.  
  306. \                                    Stack on entering:           Stack on leaving:
  307. : matrixclear                        ( ... row col addr )         ( ... )
  308.     swap                             ( ... row addr col )
  309.     maxj !                           ( ... row addr )
  310.     swap                             ( ... addr row )
  311.     maxi !                           ( ... addr )
  312.     0 icount !
  313.     begin
  314.     0 jcount !
  315.     icount @ maxi @ <
  316.     while
  317.         begin
  318.         jcount @ maxj @ <
  319.         while
  320.             0.0                      ( ... addr 0.0 0.0 )
  321.             icount @                 ( ... addr 0.0 0.0 icount )
  322.             jcount @                 ( ... addr 0.0 0.0 icount jcount )
  323.             4 pick                   ( ... addr 0.0 0.0 icount jcount addr )
  324.             element 2!               ( ... addr )
  325.             1 jcount +!
  326.         repeat
  327.         1 icount +!
  328.     repeat
  329.     drop                             ( ... )
  330. ;
  331.  
  332. \                                    Stack on entering:           Stack on leaving:
  333. : 1x33x3multiply                     ( ... addrv addrt )          ( ... )
  334.     0 icount !
  335.     begin
  336.     0 jcount !
  337.     0.0 ftmp 2!
  338.     icount @ 3 <
  339.     while
  340.         begin
  341.         jcount @ 3 <
  342.         while
  343.             jcount @                 ( ... addrv addrt jcount )
  344.             icount @                 ( ... addrv addrt jcount icount )
  345.             2 pick                   ( ... addrv addrt jcount icount addrt )
  346.             \ Get the i,j element from the 3x3 matrix.
  347.             element 2@               ( ... addrv addrt f1 f1 )
  348.             0 jcount @               ( ... addrv addrt f1 f1 0 jcount )
  349.             5 pick                   ( ... addrv addrt f1 f1 0 jcount addrv )
  350.             element 2@               ( ... addrv addrt f1 f1 f2 f2 )
  351.             f* ftmp 2@ f+            ( ... addrv addrt f3 f3 )
  352.             ftmp 2!                  ( ... addrv addrt )
  353.  
  354.             1 jcount +!
  355.         repeat
  356.         ftmp 2@                      ( ... addrv addrt f4 f4 )
  357.         0 icount @                   ( ... addrv addrt f4 f4 0 icount )
  358.         result element 2!            ( ... addrv addrt )
  359.  
  360.         1 icount +!
  361.     repeat
  362.     drop drop                        ( ... )
  363. ;
  364.  
  365.  
  366. \ ************ START DEBUG-ONLY STUFF ***************
  367.  
  368. \   Initialization routine
  369.  
  370. : dxf:start
  371. \   -1 dumpinput !                    \ Un-comment to dump input items
  372. \   -1 dumpoutput !                   \ Un-comment to dump output items
  373. \    6 outprec !                      \ Un-comment to force ASCII output
  374. \   -1 mbchar !                       \ Un-comment to force multibyte char interp
  375. \    dumpspecial
  376.     false maxset !
  377.     false minset !
  378.     false handleson !
  379.     false needToRewind !              \ Only redo the translation if necessary.
  380.     false delEndBlock !
  381. \   true trace                        \ Un-comment for debugging.
  382. ;
  383.  
  384.  
  385. \   Manual translation program (equivalent to the standard loop, so it's
  386. \                               commented out).
  387.  
  388. \ : dxf:translate
  389. \    begin
  390. \        readitem while
  391. \        writeitem drop
  392. \    repeat
  393. \ ;
  394.  
  395. \   Print point on stack
  396.  
  397. 80 string edbuf
  398. 512 string longString
  399. : point.                              \ x y z --
  400.     2rot
  401.     "(%g," edbuf fstrform edbuf type
  402.     2swap
  403.     "%g" edbuf fstrform edbuf type
  404.     2dup missing_z 2@ f= if
  405.         ")"
  406.     else
  407.         ",%g)" edbuf fstrform edbuf
  408.     then
  409.     type
  410. ;
  411.  
  412. \ ************* END DEBUG-ONLY STUFF **************
  413.  
  414. \   Defining words to make common translation operations easier
  415. \   and more expressive to specify.
  416.  
  417. \   REMOVE DXF:bilge:rat  --  Causes all instances of item RAT in section
  418. \                             BILGE to be removed.  (An explicit section
  419. \                             name is expected; "*" is not valid here)
  420.  
  421. : remove
  422.     create
  423.     does>
  424.         drop
  425.         1 delitem !
  426. ;
  427.  
  428. \  DROP_Z DXF:header:$zilch  --  The Z co-ordinate will be deleted from
  429. \                                header variable ZILCH.
  430.  
  431. : drop_z
  432.     create
  433.     does>
  434.         drop
  435.         10 group 2drop missing_z 2@ 10 setgroup
  436. ;
  437.  
  438. \   bitmask MASKFIELD DXF:*:*:<field>  --  AND a field with a bitmask
  439.  
  440. : maskfield
  441.     create
  442.     ,                                 \ Compile bitmask
  443.     does>
  444.     over                              \ Duplicate group index
  445.     group                             \ Extract value of group
  446.     swap                              \ Move bitmask address to the top
  447.     @                                 \ Get value of bitmask
  448.     and                               \ Mask the value of the field
  449.     swap                              \ Get group code on top
  450.     setgroup                          \ Update group in item
  451. \   stdout printitem
  452. ;
  453.  
  454. \   DITCHGROUP DXF:*:<type>:<group>
  455.  
  456. : ditchgroup
  457.     create
  458.     does>
  459.     drop                              \ Get rid of word's address
  460.     delgroup                          \ Delete this group from item
  461. ;
  462.  
  463. \   ERRAT  --  End an error message by editing the location in the
  464. \              file that the error occurred.
  465.  
  466. : errat
  467.     ." " at "
  468.     itempos
  469.     inbinary @ if
  470.         "byte 0x%lX"
  471.     else
  472.         1+ "line %ld"
  473.     then
  474.     edbuf strform edbuf type
  475.     ." " of input file.\n"
  476. ;
  477.  
  478. \                                    Stack on entering:           Stack on leaving:
  479. : cmove                              ( ... from to n )            ( ... )
  480.     0 do                             ( ... from to )
  481.         2dup swap                    ( ... from to to from )
  482.         i + c@                       ( ... from to to cfrom+i )
  483.         swap i +                     ( ... from to cfrom+i to+i )
  484.         c!                           ( ... from to )
  485.     loop
  486.     drop drop                        ( ... )
  487. ;
  488.  
  489. \                                    Stack on entering:           Stack on leaving:
  490. \ : strncmp                            ( ... str1 str2 n )          ( ... t/f )
  491. \    \ Temporarily truncate the strings to n characters.
  492. \    dup                              ( ... str1 str2 n n )
  493. \    2 pick + dup                     ( ... str1 str2 n str2+n str2+n )
  494. \    c@                               ( ... str1 str2 n str2+n cstr2+n )
  495. \    swap                             ( ... str1 str2 n cstr2+n str2+n )
  496. \    0 swap                           ( ... str1 str2 n cstr2+n 0 str2+n )
  497. \    c!                               ( ... str1 str2 n cstr2+n )
  498. \    swap dup                         ( ... str1 str2 cstr2+n n n )
  499. \    4 pick + dup                     ( ... str1 str2 cstr2+n n str1+n str1+n )
  500. \    c@                               ( ... str1 str2 cstr2+n n str1+n cstr1+n )
  501. \    swap                             ( ... str1 str2 cstr2+n n cstr1+n str1+n )
  502. \    0 swap                           ( ... str1 str2 cstr2+n n cstr1+n 0 str1+n )
  503. \    c!                               ( ... str1 str2 cstr2+n n cstr1+n )
  504. \    swap                             ( ... str1 str2 cstr2+n cstr1+n n )
  505. \    4 pick                           ( ... str1 str2 cstr2+n cstr1+n n str1 )
  506. \    4 pick                           ( ... str1 str2 cstr2+n cstr1+n n str1 str2 )
  507. \    strcmp                           ( ... str1 str2 cstr2+n cstr1+n n t/f )
  508. \
  509. \    \ Put the strings back the way they were.
  510. \    3 roll                           ( ... str1 str2 cstr1+n n t/f cstr2+n )
  511. \    4 roll                           ( ... str1 cstr1+n n t/f cstr2+n str2 )
  512. \    3 pick +                         ( ... str1 cstr1+n n t/f cstr2+n str2+n )
  513. \    c!                               ( ... str1 cstr1+n n t/f )
  514. \    2 roll                           ( ... str1 n t/f cstr1+n )
  515. \    3 roll                           ( ... n t/f cstr1+n str1 )
  516. \    3 roll +                         ( ... t/f cstr1+n str1+n )
  517. \    c!                               ( ... t/f )
  518. \ ;
  519.  
  520. \ Equivalent to ROLL only used on doubles.
  521. \ The stack trace shown below uses 1 as an example.
  522. \ Doubles are represented as 2 words (eg. z1 z2).
  523. \                                    Stack on entering:           Stack on leaving:
  524. : 2roll                              ( ... z1 z2 x1 x2 y1 y2 1 )  ( ... z1 z2 y1 y2 x1 x2 )
  525.     dup                              ( ... z1 z2 x1 x2 y1 y2 1 1 )
  526.     1+ 2*                            ( ... z1 z2 x1 x2 y1 y2 1 4 )
  527.     roll                             ( ... z1 z2 x2 y1 y2 1 x1 )
  528.     swap                             ( ... z1 z2 x2 y1 y2 x1 1 )
  529.     2* 1+                            ( ... z1 z2 x2 y1 y2 x1 3 )
  530.     roll                             ( ... z1 z2 y1 y2 x1 x2 )
  531. ;
  532.  
  533. \                                    Stack on entering:           Stack on leaving:
  534. : 2pick                              ( ... z1 z2 x1 x2 y1 y2 1 )  ( ... z1 z2 x1 x2 y1 y2 x1 x2 )
  535.     dup                              ( ... z1 z2 x1 x2 y1 y2 1 1 )
  536.     1+ 2*                            ( ... z1 z2 x1 x2 y1 y2 1 4 )
  537.     pick                             ( ... z1 z2 x1 x2 y1 y2 1 x1 )
  538.     swap                             ( ... z1 z2 x1 x2 y1 y2 x1 1 )
  539.     2* 1+                            ( ... z1 z2 x1 x2 y1 y2 x1 3 )
  540.     pick                             ( ... z1 z2 x1 x2 y1 y2 x1 x2 )
  541. ;
  542.  
  543.  
  544. \ Add 2 3Dpoints (composed of doubles).
  545. \                                    Stack on entering:           Stack on leaving:
  546. : 2pointadd                          ( ... x1 y1 z1 x2 y2 z2 )    ( ... x3 y3 z3 )
  547.     3 2roll                          ( ... x1 y1 x2 y2 z2 z1 )
  548.     f+                               ( ... x1 y1 x2 y2 z3 )
  549.     1 2roll                          ( ... x1 y1 x2 z3 y2 )
  550.     3 2roll                          ( ... x1 x2 z3 y2 y1 )
  551.     f+                               ( ... x1 x2 z3 y3 )
  552.     3 2roll                          ( ... x2 z3 y3 x1 )
  553.     3 2roll                          ( ... z3 y3 x1 x2 )
  554.     f+                               ( ... z3 y3 x3 )
  555.     1 2roll                          ( ... z2 x3 y3 )
  556.     2 2roll                          ( ... x3 y3 z3 )
  557. ;
  558.  
  559. \ Multiply all components of a point (composed of doubles) by a double scalar.
  560. \                                    Stack on entering:           Stack on leaving:
  561. : 2scalarMult                        ( ... x1 y1 z1 n )           ( ... x2 y2 z2 )
  562.     2dup                             ( ... x1 y1 z1 n n )
  563.     4 2roll                          ( ... y1 z1 n n x1 )
  564.     f*                               ( ... y1 z1 n x2 )
  565.     2swap 2dup                       ( ... y1 z1 x2 n n )
  566.     4 2roll                          ( ... z1 x2 n n y1 )
  567.     f*                               ( ... z1 x2 n y2 )
  568.     2swap                            ( ... z1 x2 y2 n )
  569.     3 2roll                          ( ... x2 y2 n z1 )
  570.     f*                               ( ... x2 y2 z2 )
  571. ;
  572.  
  573. \ Divide all components of a point (composed of doubles) by a double scalar.
  574. \                                    Stack on entering:           Stack on leaving:
  575. : 2scalarDiv                         ( ... x1 y1 z1 n )           ( ... x2 y2 z2 )
  576.     2dup                             ( ... x1 y1 z1 n n )
  577.     4 2roll                          ( ... y1 z1 n n x1 )
  578.     2swap                            ( ... y1 z1 n x1 n )
  579.     f/                               ( ... y1 z1 n x2 )
  580.     2swap 2dup                       ( ... y1 z1 x2 n n )
  581.     4 2roll                          ( ... z1 x2 n n y1 )
  582.     2swap                            ( ... z1 x2 n y1 n )
  583.     f/                               ( ... z1 x2 n y2 )
  584.     2swap                            ( ... z1 x2 y2 n )
  585.     3 2roll                          ( ... x2 y2 n z1 )
  586.     2swap                            ( ... x2 y2 z1 n )
  587.     f/                               ( ... x2 y2 z2 )
  588. ;
  589.  
  590. \                                    Stack on entering:           Stack on leaving:
  591. : 2pointprint                        ( ... x1 y1 z1 )             ( ... x1 y1 z1 )
  592.     2 2roll 2dup                     ( ... y1 z1 x1 x1 )
  593.     ." "X=" f.                       ( ... y1 z1 x1 )
  594.     2 2roll 2dup                     ( ... z1 x1 y1 y1 )
  595.     ." "Y=" f.                       ( ... z1 x1 y1 )
  596.     2 2roll 2dup                     ( ... x1 y1 z1 z1 )
  597.     ." "Z=" f. cr                    ( ... x1 y1 z1 )
  598. ;
  599.  
  600. \ Is xmax >= x1 >= xmin?
  601. \                                    Stack on entering:           Stack on leaving:
  602. : inside                             ( ... x1 xmax xmin )         ( ... t/f )
  603.     2 2roll 2dup                     ( ... xmax xmin x1 x1 )
  604.     3 2roll                          ( ... xmin x1 x1 xmax )
  605.     f<= if                           ( ... xmin x1 )
  606.         \ x1 is less than or equal to xmax
  607.         f<= if                       ( ... )
  608.             \ xmin is less than or equal to x1
  609.             true                     ( ... true )
  610.         else
  611.             false                    ( ... false )
  612.         then
  613.     else                             ( ... xmin x1 )
  614.         2drop 2drop false            ( ... false )
  615.     then
  616. ;
  617.  
  618. \                                    Stack on entering:           Stack on leaving:
  619. : extentsok                          ( ... )                      ( ... t/f )
  620.     maxset @ minset @ and if         ( ... )
  621.         \ Extents are there.
  622.         true                         ( ... true )
  623.     else
  624.         \ Extents are missing.
  625.         false                        ( ... false )
  626.     then
  627. ;
  628.  
  629. \ Is the 3D point contained withing the drawing extents?
  630. \                                    Stack on entering:           Stack on leaving:
  631. : insideextents                      ( ... x1 y1 z1 )             ( ... t/f )
  632.     extentsok not if                 ( ... x1 y1 z1 )
  633.         \ If the extents are missing or malformed then exit.
  634.         2drop 2drop 2drop true exit
  635.     then
  636.  
  637.     zmax 2@ zmin 2@                  ( ... x1 y1 z1 zmax zmin )
  638.     inside if                        ( ... x1 y1 )
  639.         ymax 2@ ymin 2@              ( ... x1 y1 ymax ymin )
  640.         inside if                    ( ... x1 )
  641.             xmax 2@ xmin 2@          ( ... x1 xmax xmin )
  642.             inside if                ( ... )
  643.                 true                 ( ... true )
  644.             else                     ( ... )
  645.                 false                ( ... false )
  646.             then
  647.         else                         ( ... x1 )
  648.             2drop false              ( ... false )
  649.         then
  650.     else                             ( ... x1 y1 )
  651.         2drop 2drop false            ( ... false )
  652.     then
  653. ;
  654.  
  655. \ Initialize the high and low values for point * scalar multiplication
  656. \                                    Stack on entering:           Stack on leaving:
  657. : initbignumrange                    ( ... )                      ( ... )
  658.     bignum bignumhi 2!
  659.     1.0 bignum f/ bignumlo 2!
  660. ;
  661.  
  662. \ Find a logarithmic mean between bignumhi and bignumlo
  663. \                                    Stack on entering:           Stack on leaving:
  664. : bignummean                         ( ... )                      ( ... f )
  665.     bignumhi 2@ log
  666.     bignumlo 2@ log
  667.     f+ 2.0 f/
  668.     e 2swap pow
  669. ;
  670.  
  671. \                                    Stack on entering:           Stack on leaving:
  672. : goodenough                         ( ... )                      ( ... t/f )
  673.     bignumlo 2@ bignumhi 2@ f- fabs bignumerror f<
  674. ;
  675.  
  676. (   Process command line options and set special operating modes   )
  677.  
  678. : modeset
  679.     "d" option if                     \ If -D option is set, turn on trace
  680.         1 dxftrace !
  681.     then
  682. ;
  683.  
  684. \   End of defining words.  Let the fun begin!
  685.  
  686. modeset                               \ Process command line options
  687.  
  688. (   Header variables to delete or modify   )
  689.  
  690. : dxf:header:$acadver                 \ $ACADVER needs special processing
  691.     "AC1009" 1 setgroup               \ Substitute R12's version code
  692. ;
  693.  
  694. \ : dxf:header:$dimscale                \ $DIMSCALE needs special processing
  695. \    40 group 0.0 f= if                \ If it's zero (for paper space)...
  696. \        1.0 40 setgroup               \ ...substitute 1.0
  697. \    then
  698. \ ;
  699.  
  700.  
  701. (   Symbol tables to delete or modify   )
  702.  
  703. remove dxf:header:$celtscale
  704. remove dxf:header:$delobj
  705. remove dxf:header:$dispsilh
  706. remove dxf:header:$dimjust
  707. remove dxf:header:$dimsd1
  708. remove dxf:header:$dimsd2
  709. remove dxf:header:$dimtolj
  710. remove dxf:header:$dimtzin
  711. remove dxf:header:$dimaltz
  712. remove dxf:header:$dimalttz
  713. remove dxf:header:$dimfit
  714. remove dxf:header:$dimupt
  715. remove dxf:header:$dimunit
  716. remove dxf:header:$dimdec
  717. remove dxf:header:$dimtdec
  718. remove dxf:header:$dimaltu
  719. remove dxf:header:$dimalttd
  720. remove dxf:header:$dimtxsty
  721. remove dxf:header:$dimaunit
  722. remove dxf:header:$chamferc
  723. remove dxf:header:$chamferd
  724. remove dxf:header:$pickstyle
  725. remove dxf:header:$cmlstyle
  726. remove dxf:header:$cmljust
  727. remove dxf:header:$cmlscale
  728. remove dxf:header:$saveimages
  729.  
  730. \ comment the following statements out if you need the variabels
  731. remove dxf:header:$dwgcodepage
  732. remove dxf:header:$treedepth
  733. remove dxf:header:$pinsbase
  734.  
  735. : dxf:header:$extmax
  736.     true maxset !
  737.     10 group
  738.     zmax 2!
  739.     ymax 2!
  740.     xmax 2!
  741. ;
  742.  
  743. \ Return the base-10 equivalent of a hexadecimal string.
  744. \ e.g. String "10" is converted to number 16.
  745. \                                    Stack on entering:           Stack on leaving:
  746. : strhexint                          ( ... addr1 )                ( ... n )
  747.     "0x" edbuf strcpy                ( ... addr1 )
  748.     edbuf                            ( ... addr1 edbuf )
  749.     strcat                           ( ... )
  750.     edbuf strint swap drop           ( ... n )
  751. ;
  752.  
  753. : dxf:header:$handseed
  754.     handleson @ if
  755.         rewind @ if
  756.             \ Second pass.
  757.             5 group strhexint         ( ... oldnexthandle )
  758.             \ Handles are in hex.
  759.             nexthandle @ "%lX" edbuf strform
  760.             edbuf 5 setgroup
  761.             \ Now load the 'nexthandle' with the original 'oldnexthandle'.
  762.             nexthandle !              ( ... )
  763.         else
  764.             \ First pass.
  765.             5 group strhexint nexthandle !
  766.         then
  767.     else
  768.         ." "Warning. Handle seed value present, but handles not enabled."
  769.     then
  770. ;
  771.  
  772. : dxf:header:$handling
  773.     70 group
  774.     0= if
  775.         false handleson !
  776.     else
  777.         true handleson !
  778.     then
  779. ;
  780.  
  781. remove dxf:classes
  782. remove dxf:objects
  783.  
  784.  
  785. (   Entities to delete   )
  786.  
  787.     \ Since apps can now create their own entities, we don't know what
  788.     \ entities should be deleted - only which ones to keep ...
  789.  
  790. : removeUnknownEnts
  791.     0 group "SECTION"   strcmp 0= if exit then
  792.     0 group "ENDSEC"    strcmp 0= if exit then
  793.     0 group "3DFACE"    strcmp 0= if exit then
  794.     0 group "ATTDEF"    strcmp 0= if exit then
  795.     0 group "ATTRIB"    strcmp 0= if exit then
  796.     0 group "ARC"       strcmp 0= if exit then
  797.     0 group "CIRCLE"    strcmp 0= if exit then
  798.     0 group "DIMENSION" strcmp 0= if exit then
  799.     0 group "INSERT"    strcmp 0= if exit then
  800.     0 group "LINE"      strcmp 0= if exit then
  801.     0 group "POINT"     strcmp 0= if exit then
  802.     0 group "POLYLINE"  strcmp 0= if exit then
  803.     0 group "SEQEND"    strcmp 0= if exit then
  804.     0 group "SHAPE"     strcmp 0= if exit then
  805.     0 group "SOLID"     strcmp 0= if exit then
  806.     0 group "TEXT"      strcmp 0= if exit then
  807.     0 group "TRACE"     strcmp 0= if exit then
  808.     0 group "VERTEX"    strcmp 0= if exit then
  809.     0 group "VIEWPORT"  strcmp 0= if exit then
  810.     0 group "BLOCK"     strcmp 0= if exit then
  811.     0 group "ENDBLK"    strcmp 0= if exit then
  812.     1 delitem !
  813.     1 specialdone !
  814. ;
  815.  
  816.  
  817. (   Block definition transformations   )
  818.  
  819.  
  820.  
  821. (   Dimension entity transformations   )
  822. 32 not maskfield dxf:*:DIMENSION:70        \ remove 32 bit flag of group 70
  823.  
  824. (   Delete specific group data   )
  825.  
  826. ditchgroup dxf:*:*:300-369            \ Drop all arbitrary strings, chunks and handles
  827. ditchgroup dxf:*:*:100                \ Drop all AcDb... groups (eg. AcDbSymbolTable, AcDbLinetypeTableRecord, etc)
  828. ditchgroup dxf:*:*:60                 \ Ignor Invisibility flag
  829. ditchgroup dxf:*:*:102                \ drop arbitrary strings in 102 groups
  830. ditchgroup dxf:*:VPORT:5
  831. ditchgroup dxf:*:LTYPE:5
  832. ditchgroup dxf:*:LTYPE:74-75
  833. ditchgroup dxf:*:LTYPE:44-46
  834. ditchgroup dxf:*:LTYPE:50
  835. ditchgroup dxf:*:LAYER:5
  836. ditchgroup dxf:*:STYLE:5
  837. ditchgroup dxf:*:VIEW:5
  838. ditchgroup dxf:*:UCS:5
  839. ditchgroup dxf:*:APPID:5
  840. ditchgroup dxf:*:APPID:71
  841. ditchgroup dxf:*:MTEXT:1000-1100
  842. ditchgroup dxf:*:BLOCK:5
  843.  
  844. : printobject
  845.     ." "Object printout:" cr
  846.     stdout printitem cr
  847. ;
  848.  
  849. : dxf:tables:block_record
  850.     5 group? if
  851.         1 delitem !
  852.     then
  853. ;
  854.  
  855. : removeXdata
  856.     1101 1000 do
  857.         i dup loopCount !             ( ... i )
  858.         groupcount2 dup if            ( ... count )
  859.             0 do                      ( ... )
  860.                 loopCount @ delgroup
  861.             loop
  862.         else                          ( ... count )
  863.             drop                      ( ... )
  864.         then
  865.     loop
  866. ;
  867.  
  868. \ Remove all XREF data from the TABLES section.
  869. : dxf:tables:vport
  870.     removeXdata
  871. ;
  872. : dxf:tables:ltype
  873.     removeXdata
  874.     9 delgroup
  875.     74 delgroup
  876.     2 group? if
  877.         2 group "BYBLOCK" strcmp 0= if
  878.             1 delitem !
  879.         then
  880.         2 group "BYLAYER" strcmp 0= if
  881.             1 delitem !
  882.         then
  883.     then
  884. ;
  885.  
  886. \ replace all .ttf and .pfa text styles with txt
  887. : dxf:tables:style
  888.     removeXdata
  889.     3 group? if
  890.         3 group ".ttf" strstr 0= if
  891.             "txt" 3 setgroup  
  892.         then
  893.         3 group ".pfa" strstr 0= if
  894.             "txt" 3 setgroup  
  895.         then
  896.     then
  897. ;
  898.  
  899. : dxf:tables:layer
  900.     removeXdata
  901. ;
  902.  
  903. : dxf:tables:view
  904.     removeXdata
  905. ;
  906. : dxf:tables:ucs
  907.     removeXdata
  908. ;
  909. : dxf:tables:appid
  910.     removeXdata
  911. ;
  912.  
  913. : dxf:tables:dimstyle
  914.     groupcount 1 = if
  915.         0 group? if
  916.             1 delitem !
  917.         then
  918.     then
  919.  
  920.     groupcount 4 = if
  921.         5 delgroup
  922.     then
  923.  
  924.     105 delgroup
  925.     100 delgroup
  926.     270 delgroup
  927.     271 delgroup
  928.     272 delgroup
  929.     273 delgroup
  930.     274 delgroup
  931.     275 delgroup
  932.     280 delgroup
  933.     281 delgroup
  934.     282 delgroup
  935.     283 delgroup
  936.     284 delgroup
  937.     285 delgroup
  938.     286 delgroup
  939.     287 delgroup
  940.     288 delgroup
  941.     removeXdata
  942. ;
  943.  
  944. : starmodel                           ( ... n )
  945.     dup dup                           ( ... n n n )
  946.     group? if                         ( ... n n )
  947.         group                         ( ... n addr1 )
  948.         "*MODEL_SPACE"                ( ... n addr1 addr2 )
  949.         strcmp                        ( ... n flag )
  950.         0= if                         ( ... n )
  951.             "$MODEL_SPACE"            ( ... n addr3 )
  952.             swap                      ( ... addr3 n )
  953.             setgroup                  ( ... )
  954.         else                          ( ... n )
  955.             drop                      ( ... )
  956.         then
  957.     else                              ( ... n n )
  958.         drop drop                     ( ... )
  959.     then
  960. ;
  961.  
  962. \ Remove any existing "$MODEL_SPACE" blocks. These can occur in the following
  963. \  scenario: 1. DXFIX an R13 drawing.
  964. \            2. Read in the R12 dxf file.
  965. \            3. DXFOUT the new R13 drawing which now contains both $MODEL_SPACE
  966. \                and *MODEL_SPACE.
  967. \            4. DXFIX this new R13 drawing and the old $MODEL_SPACE will be removed.
  968. : delmodel                            ( ... n )
  969.     dup                               ( ... n n )
  970.     group? if                         ( ... n )
  971.         group                         ( ... addr1 )
  972.         "$MODEL_SPACE"                ( ... addr1 addr2 )
  973.         strcmp                        ( ... flag )
  974.         0= if                         ( ... )
  975.             true delEndBlock !
  976.             clearitem writeitem drop
  977.         then
  978.     else                              ( ... n )
  979.         drop
  980.     then
  981.  
  982. ;
  983.  
  984. : delpaper                            ( ... n )
  985.     dup                               ( ... n n )
  986.     group? if                         ( ... n )
  987.         group                         ( ... addr1 )
  988.         "$PAPER_SPACE"                ( ... addr1 addr2 )
  989.         strcmp                        ( ... flag )
  990.         0= if                         ( ... )
  991.             true delEndBlock !
  992.             clearitem writeitem drop
  993.         then
  994.     else                              ( ... n )
  995.         drop
  996.     then
  997.  
  998. ;
  999.  
  1000. : starpaper                           ( ... n )
  1001.     dup dup                           ( ... n n n )
  1002.     group? if                         ( ... n n )
  1003.         group                         ( ... n addr1 )
  1004.         "*PAPER_SPACE"                ( ... n addr1 addr2 )
  1005.         strcmp                        ( ... n flag )
  1006.         0= if                         ( ... n )
  1007.             "$PAPER_SPACE"            ( ... n addr3 )
  1008.             swap                      ( ... addr3 n )
  1009.             setgroup                  ( ... )
  1010.         else                          ( ... n )
  1011.             drop                      ( ... )
  1012.         then
  1013.     else                              ( ... n n )
  1014.         drop drop                     ( ... )
  1015.     then
  1016. ;
  1017.  
  1018. : dxf:blocks:block
  1019.     2 delmodel
  1020.     3 delmodel
  1021.     2 delpaper
  1022.     3 delpaper
  1023.     2 starmodel                       \ Change *MODEL_SPACE and *PAPER_SPACE
  1024.     2 starpaper                       \ to $MODEL_SPACE and $PAPER_SPACE in
  1025.     3 starpaper                       \ the 2 and 3 groups.
  1026.     3 starmodel
  1027. ;
  1028.  
  1029. \ Note, don't want to delete the 48 group from the TABLES section.
  1030. : dxf:blocks
  1031.     0 group? if
  1032.         removeUnknownEnts
  1033.         0 group                       ( ... addr1 )
  1034.         "ENDBLK"                      ( ... addr1 addr2 )
  1035.         strcmp                        ( ... flag )
  1036.         0= delEndBlock @ and if       ( ... )
  1037.             \ Delete the ENDBLK that corresponds to the PAPER/MODEL_SPACE
  1038.             \  block just deleted.
  1039.             false delEndBlock !
  1040.             clearitem writeitem drop
  1041.         then
  1042.  
  1043.     then
  1044.     48 delgroup
  1045. ;
  1046. : dxf:entities
  1047.     0 group? if
  1048.         removeUnknownEnts
  1049.     then
  1050.     48 delgroup
  1051. ;
  1052.  
  1053. : setHiLoRange
  1054.     insideextents if
  1055.         bignummean bignumlo 2!
  1056.     else
  1057.         bignummean bignumhi 2!
  1058.     then
  1059. ;
  1060.  
  1061. \ Add the offset from the origin.
  1062. : addOffset
  1063.     10 group
  1064.     2pointadd
  1065. ;
  1066.  
  1067. \                                    Stack on entering:           Stack on leaving:
  1068. : setExtents                         ( ... )                      ( ... )
  1069.     xMin 2@ 0 0 extentsMinSave element 2!
  1070.     yMin 2@ 0 1 extentsMinSave element 2!
  1071.     zMin 2@ 0 2 extentsMinSave element 2!
  1072.     xMax 2@ 0 0 extentsMaxSave element 2!
  1073.     yMax 2@ 0 1 extentsMaxSave element 2!
  1074.     zMax 2@ 0 2 extentsMaxSave element 2!
  1075.  
  1076.     10 group                         ( ... x y z )
  1077.     \ Temporarily move the extents to include the origin of the RAY or XLINE.
  1078.     2dup                             ( ... x y z z )
  1079.     zMax 2@                          ( ... x y z z zMax )
  1080.     f> if                            ( ... x y z )
  1081.         zMax 2!                      ( ... x y )
  1082.     else                             ( ... x y z )
  1083.         2dup                         ( ... x y z z )
  1084.         zMin 2@                      ( ... x y z z zMin )
  1085.         f< if                        ( ... x y z )
  1086.             zMin 2!                  ( ... x y )
  1087.         else                         ( ... x y z )
  1088.             2drop                    ( ... x y )
  1089.         then
  1090.     then
  1091.  
  1092.     2dup                             ( ... x y y )
  1093.     yMax 2@                          ( ... x y y yMax )
  1094.     f> if                            ( ... x y )
  1095.         yMax 2!                      ( ... x )
  1096.     else                             ( ... x y )
  1097.         2dup                         ( ... x y y )
  1098.         yMin 2@                      ( ... x y y yMin )
  1099.         f< if                        ( ... x y )
  1100.             yMin 2!                  ( ... x )
  1101.         else                         ( ... x y )
  1102.             2drop                    ( ... x )
  1103.         then
  1104.     then
  1105.  
  1106.     2dup                             ( ... x x )
  1107.     xMax 2@                          ( ... x x xMax )
  1108.     f> if                            ( ... x )
  1109.         xMax 2!                      ( ... )
  1110.     else                             ( ... x )
  1111.         2dup                         ( ... x x )
  1112.         xMin 2@                      ( ... x x xMin )
  1113.         f< if                        ( ... x )
  1114.             xMin 2!                  ( ... )
  1115.         else                         ( ... x )
  1116.             2drop                    ( ... )
  1117.         then
  1118.     then
  1119. ;
  1120.  
  1121. \                                    Stack on entering:           Stack on leaving:
  1122. : resetExtents                       ( ... )                      ( ... )
  1123.     0 0 extentsMinSave element 2@ xMin 2!
  1124.     0 1 extentsMinSave element 2@ yMin 2!
  1125.     0 2 extentsMinSave element 2@ zMin 2!
  1126.     0 0 extentsMaxSave element 2@ xMax 2!
  1127.     0 1 extentsMaxSave element 2@ yMax 2!
  1128.     0 2 extentsMaxSave element 2@ zMax 2!
  1129. ;
  1130.  
  1131. : dxf:*:ray
  1132.     "x" option if
  1133.         1 delitem !
  1134.     else
  1135.         \ Bug in the interpreter makes multiple calls on one ray entity.
  1136.         \ The following code stops that.
  1137.         0 group "LINE" strcmp 0= if
  1138.             exit
  1139.         then
  1140.         setExtents
  1141.         initbignumrange
  1142.         "LINE" 0 setgroup             \ Turn a RAY into a line
  1143.         iterator 0 do
  1144.             11 group                  \ Get the X,Y,Z components of the unit direction vector
  1145.             bignummean 2scalarmult
  1146.             addOffset
  1147.             setHiLoRange
  1148.             goodenough if
  1149.                 leave
  1150.             then
  1151.         loop
  1152.         11 group
  1153.         bignummean 2scalarmult
  1154.         addOffset
  1155.         11 setgroup
  1156.         resetExtents
  1157.     then
  1158. ;
  1159.  
  1160. : dxf:*:xline
  1161.     "x" option if
  1162.         1 delitem !
  1163.     else
  1164.         setExtents
  1165.         initbignumrange
  1166.         "LINE" 0 setgroup             \ Turn an XLINE into a line
  1167.         iterator 0 do
  1168.             11 group                  \ Get the X,Y,Z components of the unit direction vector
  1169.             bignummean fnegate 2scalarmult
  1170.             addOffset
  1171.             setHiLoRange
  1172.             goodenough if
  1173.                 leave
  1174.             then
  1175.         loop
  1176.         11 group
  1177.         bignummean fnegate 2scalarmult
  1178.         addOffset
  1179.         \ Hold the results in the stack for later ...
  1180.  
  1181.         initbignumrange
  1182.         iterator 0 do
  1183.             11 group                  \ Get the X,Y,Z components of the unit direction vector
  1184.             bignummean 2scalarmult
  1185.             addOffset
  1186.             setHiLoRange
  1187.             goodenough if
  1188.                 leave
  1189.             then
  1190.         loop
  1191.         11 group
  1192.         bignummean 2scalarmult
  1193.         addOffset
  1194.         11 setgroup                   \ Set the end point
  1195.  
  1196.         \ ... OK, we can now set the 10 group
  1197.         10 setgroup                   \ Set the start point
  1198.         resetExtents
  1199.     then
  1200. ;
  1201.  
  1202. \ Compute the length of a 3D vector which has one endpoint at 0,0,0.
  1203. \                                    Stack on entering:           Stack on leaving:
  1204. : vectorLength                       ( ... x y z )                ( ... len )
  1205.     2.0 pow                          ( ... x y z**2 )
  1206.     2swap 2.0 pow                    ( ... x z**2 y**2 )
  1207.     f+                               ( ... x z**2+y**2 )
  1208.     2swap 2.0 pow                    ( ... z**2+y**2 x**2 )
  1209.     f+                               ( ... z**2+y**2+x**2 )
  1210.     sqrt                             ( ... len )
  1211. ;
  1212.  
  1213. \ angle = atan2(sin(p) * radiusRatio, cos(p))
  1214. \                                    Stack on entering:           Stack on leaving:
  1215. : ellipseparamtoangle                ( ... p )                    ( ... a )
  1216.     2dup                             ( ... p p )
  1217.     sin                              ( ... p sin[p] )
  1218.     40 group f*                      ( ... p r*sin[p] )
  1219.     2swap                            ( ... r*sin[p] p )
  1220.     cos                              ( ... r*sin[p] cos[p] )
  1221.     atan2                            ( ... a )
  1222. ;
  1223.  
  1224. \                                    Stack on entering:           Stack on leaving:
  1225. : vector2dup                         ( ... x y z )                ( ... x y z x y z )
  1226.     2 2pick                          ( ... x y z x )
  1227.     2 2pick                          ( ... x y z x y )
  1228.     2 2pick                          ( ... x y z x y z )
  1229. ;
  1230.  
  1231. \                                    Stack on entering:           Stack on leaving:
  1232. : vector2swap                        ( ... x1 y1 z1 x2 y2 z2 )    ( ... x2 y2 z2 x1 y1 z1 )
  1233.     5 2roll                          ( ... y1 z1 x2 y2 z2 x1 )
  1234.     5 2roll                          ( ... z1 x2 y2 z2 x1 y1 )
  1235.     5 2roll                          ( ... x2 y2 z2 x1 y1 z1 )
  1236. ;
  1237.  
  1238. \ Dot product of u and v: u . v
  1239. \                                    Stack on entering:           Stack on leaving:
  1240. : dotProduct                         ( ... x1 y1 z1 x2 y2 z2 )    ( ... x1x2+y1y2+z1z2 )
  1241.     2 2roll                          ( ... x1 y1 z1 y2 z2 x2 )
  1242.     5 2roll f*                       ( ... y1 z1 y2 z2 x2x1 )
  1243.     2 2roll                          ( ... y1 z1 z2 x2x1 y2 )
  1244.     4 2roll f* f+                    ( ... z1 z2 x2x1+y2y1 )
  1245.     2swap                            ( ... z1 x2x1+y2y1 z2 )
  1246.     2 2roll f* f+                    ( ... x2x1+y2y1+z2z1 )
  1247. ;
  1248.  
  1249. \ Cross product of u and v: u x v
  1250. \                                    Stack on entering:           Stack on leaving:
  1251. : crossProduct                       ( ... u1 u2 u3 v1 v2 v3 )    ( ... u2v3-u3v2 u3v1-u1v3 u1v2-u2v1 )
  1252.     4 2pick                          ( ... u1 u2 u3 v1 v2 v3 u2 )
  1253.     1 2pick f*                       ( ... u1 u2 u3 v1 v2 v3 u2v3 )
  1254.     4 2pick                          ( ... u1 u2 u3 v1 v2 v3 u2v3 u3 )
  1255.     3 2pick f* f-                    ( ... u1 u2 u3 v1 v2 v3 u2v3-u3v2 )
  1256.  
  1257.     4 2roll                          ( ... u1 u2 v1 v2 v3 u2v3-u3v2 u3 )
  1258.     4 2pick f*                       ( ... u1 u2 v1 v2 v3 u2v3-u3v2 u3v1 )
  1259.     6 2pick                          ( ... u1 u2 v1 v2 v3 u2v3-u3v2 u3v1 u1 )
  1260.     3 2roll f* f-                    ( ... u1 u2 v1 v2 u2v3-u3v2 u3v1-u1v3 )
  1261.  
  1262.     5 2roll                          ( ... u2 v1 v2 u2v3-u3v2 u3v1-u1v3 u1 )
  1263.     3 2roll f*                       ( ... u2 v1 u2v3-u3v2 u3v1-u1v3 u1v2 )
  1264.     4 2roll                          ( ... v1 u2v3-u3v2 u3v1-u1v3 u1v2 u2 )
  1265.     4 2roll f* f-                    ( ... u2v3-u3v2 u3v1-u1v3 u1v2-u2v1 )
  1266. ;
  1267.  
  1268. \ Given a vector, scale its components to make it a unit vector.
  1269. \                                    Stack on entering:           Stack on leaving:
  1270. : makeUnitVector                     ( ... x y z )                ( ... x1 y1 z1 )
  1271.     vector2dup                       ( ... x y z x y z )
  1272.     vectorLength                     ( ... x y z len )
  1273.     2scalarDiv                       ( ... x1 y1 z1 )
  1274. ;
  1275.  
  1276. \ Angle between 2 vectors, where both vectors have one endpoint at 0,0,0
  1277. \ Use the dot product of these 2 vectors to calculate the angle between them.
  1278. \   u.v = ||u|| ||v|| cos(theta)
  1279. \                                    Stack on entering:                   Stack on leaving:
  1280. : vectorangle                        ( ... ux uy uz vx vy vz )            ( ... theta )
  1281.     vector2dup                       ( ... ux uy uz vx vy vz vx vy vz )
  1282.     8 2pick                          ( ... ux uy uz vx vy vz vx vy vz ux )
  1283.     8 2pick                          ( ... ux uy uz vx vy vz vx vy vz ux uy )
  1284.     8 2pick                          ( ... ux uy uz vx vy vz vx vy vz ux uy uz )
  1285.     vector2swap                      ( ... ux uy uz vx vy vz ux uy uz vx vy vz )
  1286.     dotProduct                       ( ... ux uy uz vx vy vz u.v )
  1287.  
  1288.     6 2roll                          ( ... uy uz vx vy vz u.v ux )
  1289.     6 2roll                          ( ... uz vx vy vz u.v ux uy )
  1290.     6 2roll                          ( ... vx vy vz u.v ux uy uz )
  1291.     vectorLength                     ( ... vx vy vz u.v ulen )
  1292.  
  1293.     4 2roll                          ( ... vy vz u.v ulen vx )
  1294.     4 2roll                          ( ... vz u.v ulen vx vy )
  1295.     4 2roll                          ( ... u.v ulen vx vy vz )
  1296.     vectorLength f* f/               ( ... u.v / ulen*vlen )
  1297.  
  1298.     acos                             ( ... theta )
  1299. ;
  1300.  
  1301. \ Is this 3D point 0,0,0 ?
  1302. \                                    Stack on entering:           Stack on leaving:
  1303. : isZeroVector                       ( ... x y z )                ( ... x y z t/f )
  1304.     2dup                             ( ... x y z z )
  1305.     0.0 f= if                        ( ... x y z )
  1306.         1 2pick                      ( ... x y z y )
  1307.         0.0 f= if                    ( ... x y z )
  1308.            2 2pick                   ( ... x y z x )
  1309.            0.0 f= if                 ( ... x y z )
  1310.                true                  ( ... x y z t )
  1311.            else                      ( ... x y z )
  1312.                false                 ( ... x y z f )
  1313.            then
  1314.         else                         ( ... x y z )
  1315.             false                    ( ... x y z f )
  1316.         then
  1317.     else                             ( ... x y z )
  1318.         false                        ( ... x y z f )
  1319.     then
  1320. ;
  1321.  
  1322. : 2pi
  1323.     2.0 pi f*
  1324. ;
  1325.  
  1326. \                                     Stack on entering:           Stack on leaving:
  1327. : normalizeEllipseAngle                  ( ... a1 )                   ( ... a2 )
  1328.     2dup 0.0 f< if                       ( ... a1 )
  1329.         \ If angle is less than 0 add 2pi radians to make it positive.
  1330.         2pi f+                           ( ... a2 )
  1331.     then
  1332.  
  1333.     2dup                                 ( ... a1 a1 )
  1334.     2pi f>= if                           ( ... a1 )
  1335.         \ If angle is greater than or equal to 2pi, subtract 2pi.
  1336.         2pi f-
  1337.     then
  1338. ;
  1339.  
  1340.  
  1341. \                                     Stack on entering:           Stack on leaving:
  1342. : ellipseStepToPoint                  ( ... i )                    ( ... x y z )
  1343.     float ellipseangleincr 2@ f*      ( ... angle )
  1344.     ellipseStartAngle 2@ f+
  1345.     normalizeEllipseAngle
  1346.     2dup                              ( ... angle angle )
  1347.     cos ellipsea 2@ f*                ( ... angle x )
  1348.     2swap                             ( ... x angle )
  1349.     sin ellipseb 2@ f* 0.0            ( ... x y 0.0 )
  1350. ;
  1351.  
  1352. \                                     Stack on entering:           Stack on leaving:
  1353. : resulttovector                      ( ... )                      ( ... )
  1354.     0 0 result element 2@
  1355.     0 0 vector element 2!
  1356.     0 1 result element 2@
  1357.     0 1 vector element 2!
  1358.     0 2 result element 2@
  1359.     0 2 vector element 2!
  1360. ;
  1361.  
  1362. \                                     Stack on entering:           Stack on leaving:
  1363. : ellipseApplyTransform               ( ... x y z )                ( ... x y z )
  1364.     0 2 vector element 2!             ( ... x y )
  1365.     0 1 vector element 2!             ( ... x )
  1366.     0 0 vector element 2!             ( ... )
  1367.     vector rotationMatrix 1x33x3multiply
  1368.  
  1369.     \ Apply offset
  1370.     0 0 result element 2@             ( ... x )
  1371.     0 1 result element 2@             ( ... x y )
  1372.     0 2 result element 2@             ( ... x y z )
  1373.  
  1374.     0 0 offset element 2@             ( ... x y z x )
  1375.     0 1 offset element 2@             ( ... x y z x y )
  1376.     0 2 offset element 2@             ( ... x y z x y z )
  1377.     2pointadd                         ( ... x2 y2 z2 )
  1378. ;
  1379.  
  1380. \ Put a 16-bit short in file.
  1381. \ Not to be confused with FPUTS which operates on a string, not a short.
  1382. \                                     Stack on entering:           Stack on leaving:
  1383. : fputshort                           ( ... s file )               ( ... stat )
  1384.     \ First byte
  1385.     over                              ( ... s file s )
  1386.     over                              ( ... s file s file )
  1387.     fputc drop                        ( ... s file )
  1388.  
  1389.     \ Second byte
  1390.     swap                              ( ... file s )
  1391.     \ Shift right
  1392.     -8 shift                          ( ... file s2 )
  1393.     swap                              ( ... s2 file )
  1394.     fputc                             ( ... stat )
  1395. ;
  1396.  
  1397. \ Put a 32-bit word in file.
  1398. \                                     Stack on entering:           Stack on leaving:
  1399. : fputw                               ( ... l file )               ( ... stat )
  1400.     over                              ( ... l file l )
  1401.     over                              ( ... l file l file )
  1402.     fputshort drop                    ( ... l file )
  1403.  
  1404.     swap                              ( ... file l )
  1405.     \ Shift right
  1406.     -16 shift                         ( ... file l1 )
  1407.     swap                              ( ... l1 file )
  1408.     fputshort                         ( ... stat )
  1409. ;
  1410.  
  1411. \ Put a 64-bit double word in file.
  1412. \                                     Stack on entering:           Stack on leaving:
  1413. : fputd                               ( ... w2 w1 file )           ( ... stat )
  1414.     rot                               ( ... w1 file w2 )
  1415.     over                              ( ... w1 file w2 file )
  1416.     fputw drop                        ( ... w1 file )
  1417.     fputw                             ( ... stat )
  1418. ;
  1419.  
  1420. \ Leave 'nexthandle' with the next valid handle to use.
  1421. \                                     Stack on entering:           Stack on leaving:
  1422. : addHandle                           ( ... )                      ( ... )
  1423.     handleson @ if
  1424.         \ Handles are in hex.
  1425.         nexthandle @ "%lX" edbuf strform
  1426.         inbinary @ if
  1427.             5 ofile fputc drop
  1428.             edbuf strlen 1+
  1429.             edbuf ofile fwrite drop
  1430.         else
  1431.             "  5" ofile fputs drop
  1432.             edbuf ofile fputs drop
  1433.         then
  1434.         1 nexthandle +!
  1435.         true needToRewind !
  1436.     then
  1437. ;
  1438.  
  1439. \                                     Stack on entering:           Stack on leaving:
  1440. : saveLayer                           ( ... )                      ( ... )
  1441.     8 group? if                       ( ... )
  1442.         8 group                       ( ... addr )
  1443.         strint swap drop              ( ... n )
  1444.     else                              ( ... )
  1445.         0                             ( ... 0 )
  1446.     then
  1447.     layer !                           ( ... )
  1448. ;
  1449.  
  1450. \                                     Stack on entering:           Stack on leaving:
  1451. : saveColor
  1452.     62 group? if
  1453.         62 group
  1454.         color !
  1455.         true
  1456.     else
  1457.         false
  1458.     then
  1459.     62group !
  1460. ;
  1461.  
  1462. \                                     Stack on entering:           Stack on leaving:
  1463. : addLayer                            ( ... )                      ( ... )
  1464.     layer @ "%ld" edbuf strform
  1465.     inbinary @ if
  1466.         8 ofile fputc drop
  1467.         edbuf strlen 1+
  1468.         edbuf ofile fwrite drop
  1469.     else
  1470.         "  8" ofile fputs drop
  1471.         edbuf ofile fputs drop
  1472.     then
  1473. ;
  1474.  
  1475. \                                     Stack on entering:           Stack on leaving:
  1476. : addVertexHeader                     ( ... )                      ( ... )
  1477.     \ Add a new vertex.
  1478.     "VERTEX" edbuf strcpy
  1479.     inbinary @ if
  1480.         0 ofile fputc drop
  1481.         edbuf strlen 1+
  1482.         edbuf ofile fwrite drop
  1483.     else
  1484.         "  0" ofile fputs drop
  1485.         edbuf ofile fputs drop
  1486.     then
  1487.     addLayer
  1488.     addHandle
  1489. ;
  1490.  
  1491. \                                     Stack on entering:           Stack on leaving:
  1492. : addVertexTrailer                    ( ... )                      ( ... )
  1493.     inbinary @ if
  1494.         70 ofile fputc drop
  1495.         32 ofile fputshort drop
  1496.     else
  1497.         "  70" ofile fputs drop
  1498.         "    32" ofile fputs drop
  1499.     then
  1500. ;
  1501.  
  1502. \                                     Stack on entering:           Stack on leaving:
  1503. : addSequend                          ( ... )                      ( ... )
  1504.     "SEQEND" edbuf strcpy
  1505.     inbinary @ if
  1506.         0 ofile fputc drop
  1507.         edbuf strlen 1+
  1508.         edbuf ofile fwrite drop
  1509.     else
  1510.         "  0" ofile fputs drop
  1511.         edbuf ofile fputs drop
  1512.     then
  1513.  
  1514.     addLayer
  1515.     addHandle
  1516. ;
  1517.  
  1518. \                                     Stack on entering:           Stack on leaving:
  1519. : add10Group                          ( ... x y z )                ( ... )
  1520.     inbinary @ if
  1521.         10 ofile fputc drop
  1522.         2 2roll                       ( ... y z x )
  1523.         ofile fputd drop              ( ... y z )
  1524.         20 ofile fputc drop
  1525.         2swap                         ( ... z y )
  1526.         ofile fputd drop              ( ... z )
  1527.         30 ofile fputc drop
  1528.         ofile fputd drop              ( ... )
  1529.     else
  1530.         " 10" ofile fputs drop
  1531.         2 2roll                       ( ... y z x )
  1532.         "%#g" edbuf fstrform          ( ... y z )
  1533.         edbuf ofile fputs drop
  1534.         " 20" ofile fputs drop
  1535.         2swap                         ( ... z y )
  1536.         "%#g" edbuf fstrform          ( ... z )
  1537.         edbuf ofile fputs drop
  1538.         " 30" ofile fputs drop
  1539.         "%#g" edbuf fstrform          ( ... )
  1540.         edbuf ofile fputs drop
  1541.     then
  1542. ;
  1543.  
  1544. : dxf:header:$extmin
  1545.     true minset !
  1546.     10 group                          ( ... x y z )
  1547.     zmin 2!
  1548.     ymin 2!
  1549.     xmin 2!
  1550. ;
  1551.  
  1552. \                                     Stack on entering:           Stack on leaving:
  1553. : addColor
  1554.     62group @ if
  1555.         inbinary @ if
  1556.             62 ofile fputc drop
  1557.             color @ ofile fputshort drop
  1558.          else
  1559.             "  62" ofile fputs drop
  1560.             color @ "%ld" edbuf strform
  1561.             edbuf ofile fputs drop
  1562.          then
  1563.     then
  1564. ;
  1565.  
  1566. \                                     Stack on entering:           Stack on leaving:
  1567. : addPolylineHeader                   ( ... )                      ( ... )
  1568.     "POLYLINE" edbuf strcpy
  1569.     inbinary @ if
  1570.         0 ofile fputc drop
  1571.         edbuf strlen 1+
  1572.         edbuf ofile fwrite drop
  1573.     else
  1574.         "  0" ofile fputs drop
  1575.         edbuf ofile fputs drop
  1576.     then
  1577.  
  1578.     addLayer
  1579.     addHandle
  1580.     addColor
  1581.  
  1582.     inbinary @ if
  1583.         66 ofile fputc drop
  1584.         1 ofile fputshort drop
  1585.     else
  1586.         "  66" ofile fputs drop
  1587.         "     1" ofile fputs drop
  1588.     then
  1589.  
  1590.     add10Group
  1591. ;
  1592.  
  1593. : add3dPolylineHeader                   ( ... )                      ( ... )
  1594.     inbinary @ if
  1595.         70 ofile fputc drop
  1596.         8 ofile fputshort drop
  1597.     else
  1598.         "  70" ofile fputs drop
  1599.         "     8" ofile fputs drop
  1600.     then
  1601. ;
  1602.  
  1603. : addVertex
  1604.     addVertexHeader
  1605.     add10Group
  1606. ;
  1607.  
  1608. \                                     Stack on entering:           Stack on leaving:
  1609. : saveOffset                          ( ... )                      ( ... )
  1610.     10 group                          ( ... x y z )
  1611.     0 2 offset element 2!
  1612.     0 1 offset element 2!
  1613.     0 0 offset element 2!
  1614. ;
  1615.  
  1616. : dxf:*:ellipse
  1617.     saveLayer
  1618.     saveOffset
  1619.  
  1620.     removeXdata
  1621.     11 group                          ( ... x y z )
  1622.     \ Calculate the parameter 'a' for the ellipse equation: x = a cos(theta), y = b sin(theta)
  1623.     vectorLength 2dup ellipsea 2!     ( ... len )
  1624.  
  1625.     \ Calculate the parameter 'b'.
  1626.     40 group                          ( ... len p )
  1627.     f* ellipseb 2!                    ( ... )
  1628.  
  1629.     \ Calculate the start angle.
  1630.     41 group                          ( ... a1 )
  1631.     ellipseparamtoangle               ( ... a2 )
  1632.     normalizeEllipseAngle
  1633.     ellipseStartAngle 2!              ( ... )
  1634.  
  1635.     \ Calculate the end angle.
  1636.     42 group                          ( ... a1 )
  1637.     ellipseparamtoangle               ( ... a2 )
  1638.     normalizeEllipseAngle
  1639.     2dup ellipseEndAngle 2!           ( ... endangle )
  1640.  
  1641.     ellipseStartAngle 2@              ( ... endangle startangle )
  1642.     f- fabs                           ( ... deltaangle )
  1643.     ellipseanglefuzz f> if
  1644.         \ An elliptical arc.
  1645.         ellipseStartAngle 2@          ( ... s )
  1646.         ellipseEndAngle 2@            ( ... s e )
  1647.         f> if
  1648.             \ Start angle greater than end angle.
  1649.             2pi ellipseStartAngle 2@ f-
  1650.             ellipseEndAngle 2@ f+
  1651.         else
  1652.             ellipseEndAngle 2@        ( ... e )
  1653.             ellipseStartAngle 2@      ( ... s )
  1654.             f-                        ( ... arcangle )
  1655.         then
  1656.     else
  1657.         \ A full ellipse, not an elliptical arc.
  1658.         2pi                           ( ... 2pi )
  1659.     then
  1660.     ellipseSteps float f/
  1661.     ellipseangleincr 2!
  1662.  
  1663.     \ Set up the rotation matrix.
  1664.     210 group                         ( ... x3 y3 z3 )
  1665.     vector2dup                        ( ... x3 y3 z3 x3 y3 z3 )
  1666.     2 2 rotationMatrix element 2!     ( ... x3 y3 z3 x3 y3 )
  1667.     2 1 rotationMatrix element 2!     ( ... x3 y3 z3 x3 )
  1668.     2 0 rotationMatrix element 2!     ( ... x3 y3 z3 )
  1669.  
  1670.     11 group                          ( ... x3 y3 z3 x y z )
  1671.     makeUnitVector                    ( ... x3 y3 z3 x1 y1 z1 )
  1672.     vector2dup                        ( ... x3 y3 z3 x1 y1 z1 x1 y1 z1 )
  1673.     0 2 rotationMatrix element 2!     ( ... x3 y3 z3 x1 y1 z1 x1 y1 )
  1674.     0 1 rotationMatrix element 2!     ( ... x3 y3 z3 x1 y1 z1 x1 )
  1675.     0 0 rotationMatrix element 2!     ( ... x3 y3 z3 x1 y1 z1 )
  1676.  
  1677.     crossProduct                      ( ... x4 y4 z4 )
  1678.     1 2 rotationMatrix element 2!     ( ... x4 y4 )
  1679.     1 1 rotationMatrix element 2!     ( ... x4 )
  1680.     1 0 rotationMatrix element 2!     ( ... )
  1681.  
  1682.     "POLYLINE" 0 setgroup             \ Turn an ELLIPSE into a POLYLINE
  1683.     \ Need to set point from the 0th VERTEX here.
  1684.     11 delgroup
  1685.     40 delgroup
  1686.     41 delgroup
  1687.     42 delgroup
  1688.     48 delgroup
  1689.     66 group? not if
  1690.         66 addgroup
  1691.     then
  1692.     1 66 setgroup
  1693.     70 group? not if
  1694.         70 addgroup
  1695.     then
  1696.     8 70 setgroup
  1697.     210 delgroup
  1698.  
  1699.     0 ellipseStepToPoint              ( ... x y z )
  1700.     ellipseApplyTransform
  1701.     10 setgroup                       ( ... )
  1702.  
  1703.     \ Need to force a write of this item in order to append explicit VERTEX items.
  1704.     writeitem drop
  1705.  
  1706.     \ Calculate points on the ellipse.
  1707.     ellipseSteps 1+ 0 do
  1708.         i ellipseStepToPoint          ( ... x y z )
  1709.         ellipseApplyTransform
  1710. \       2pointprint
  1711.         addVertex
  1712.         addVertexTrailer
  1713.     loop
  1714.     addSequend
  1715. ;
  1716.  
  1717. : dxf:entities:dimension
  1718. \    -3 delgroup
  1719.     3 delgroup
  1720. ;
  1721.  
  1722. \ : dxf:entities:insert
  1723. \    -3 delgroup
  1724. \ ;
  1725.  
  1726. \ : dxf:entities:viewport
  1727. \    -3 delgroup
  1728. \ ;
  1729.  
  1730. : dxf:entities:seqend
  1731.     -2 delgroup
  1732. ;
  1733.  
  1734. : addRotationAngle                    ( ... )                      ( ... )
  1735.     textRotation 2@ 0.0 f= not if
  1736.         inbinary @ if
  1737.             50 ofile fputc drop
  1738.         else
  1739.             "  50" ofile fputs drop   ( ... x y z )
  1740.         then
  1741.         textRotation 2@
  1742.         inbinary @ if
  1743.             ofile fputd drop
  1744.         else
  1745.             "%#g" edbuf fstrform
  1746.             edbuf ofile fputs drop
  1747.         then
  1748.     then
  1749. ;
  1750.  
  1751. \                                     Stack on entering:           Stack on leaving:
  1752. : getArbitraryXAxis                   ( ... x y z )                ( ... x3 y3 z3 )
  1753.     \ See pg. 272 of the AutoCAD R12 Customization Manual.
  1754.     2 2pick                           ( ... x y z x )
  1755.     \ 0.015625 = 1/64
  1756.     0.015625 f< if                    ( ... x y z )
  1757.         1 2pick                       ( ... x y z y )
  1758.         0.015625 f< if                ( ... x y z )
  1759.             0.0 1.0 0.0               ( ... x y z 0.0 1.0 0.0 )
  1760.         else                          ( ... x y z )
  1761.             0.0 0.0 1.0               ( ... x y z 0.0 0.0 1.0 )
  1762.         then
  1763.     else                              ( ... x y z )
  1764.         0.0 0.0 1.0                   ( ... x y z 0.0 0.0 1.0 )
  1765.     then
  1766.     vector2swap                       ( ... 0.0 0.0 1.0 x y z )
  1767.     crossProduct                      ( ... x2 y2 z2 )
  1768.     makeUnitVector                    ( ... x3 y3 z3 )
  1769. ;
  1770.  
  1771. \                                     Stack on entering:           Stack on leaving:
  1772. : saveExtrusion                       ( ... )                      ( ... )
  1773.     0.0 2dup                          ( ... ang ang )
  1774.     textRotation 2!                   ( ... ang )
  1775.     textRotationPrimary 2!            ( ... )
  1776.     210 group? if
  1777.         210 group                     ( ... Zx Zy Zz )
  1778.         vector2dup                    ( ... Zx Zy Zz Zx Zy Zz )
  1779.         \ Set up the rotation matrix Z
  1780.         2 2 rotationMatrix element 2!
  1781.         1 2 rotationMatrix element 2!
  1782.         0 2 rotationMatrix element 2! ( ... Zx Zy Zz )
  1783.         vector2dup                    ( ... Zx Zy Zz Zx Zy Zz )
  1784.         getArbitraryXAxis             ( ... Zx Zy Zz Xx Xy Xz )
  1785.         vector2dup                    ( ... Zx Zy Zz Xx Xy Xz Xx Xy Xz )
  1786.         \ Set up the rotation matrix X
  1787.         2 0 rotationMatrix element 2!
  1788.         1 0 rotationMatrix element 2!
  1789.         0 0 rotationMatrix element 2! ( ... Zx Zy Zz Xx Xy Xz )
  1790.         vector2dup                    ( ... Zx Zy Zz Xx Xy Xz Xx Xy Xz )
  1791.         8 2pick                       ( ... Zx Zy Zz Xx Xy Xz Xx Xy Xz Zx )
  1792.         8 2pick                       ( ... Zx Zy Zz Xx Xy Xz Xx Xy Xz Zx Zy )
  1793.         8 2pick                       ( ... Zx Zy Zz Xx Xy Xz Xx Xy Xz Zx Zy Zz )
  1794.         vector2swap                   ( ... Zx Zy Zz Xx Xy Xz Zx Zy Zz Xx Xy Xz )
  1795.         crossProduct                  ( ... Zx Zy Zz Xx Xy Xz Yx Yy Yz )
  1796.         makeUnitVector
  1797.         \ Set up the rotation matrix Y
  1798.         2 1 rotationMatrix element 2!
  1799.         1 1 rotationMatrix element 2!
  1800.         0 1 rotationMatrix element 2! ( ... Zx Zy Zz Xx Xy Xz )
  1801.         \ Now transform the offset from World Coordinate System to Local CS.
  1802.         offset rotationMatrix 1x33x3multiply
  1803.         0 0 result element 2@         ( ... Zx Zy Zz Xx Xy Xz Xlcs )
  1804.         0 1 result element 2@         ( ... Zx Zy Zz Xx Xy Xz Xlcs Ylcs )
  1805.         0 2 result element 2@         ( ... Zx Zy Zz Xx Xy Xz Xlcs Ylcs Zlcs )
  1806.  
  1807.         0 2 offset element 2!
  1808.         0 1 offset element 2!
  1809.         0 0 offset element 2!         ( ... Zx Zy Zz Xx Xy Xz )
  1810.  
  1811.         2drop 2swap                   ( ... Zx Zy Zz Xy Xx )
  1812.         atan2                         ( ... Zx Zy Zz rad )
  1813.         2.0 pi f* 2swap f-            ( ... Zx Zy Zz 2pi-rad )
  1814.         radToDeg f*                   ( ... Zx Zy Zz arbAxisAng )
  1815.  
  1816.         \ Get angle between WCS X-axis and LCS X-axis
  1817.         11 group? if                   ( ... Zx Zy Zz arbAxisAng )
  1818.             11 group                   ( ... Zx Zy Zz arbAxisAng x y z )
  1819.             0 2 vector element 2!
  1820.             0 1 vector element 2!
  1821.             0 0 vector element 2!
  1822.             vector rotationMatrix 1x33x3multiply
  1823.  
  1824.             0 1 result element 2@      ( ... Zx Zy Zz arbAxisAng y )
  1825.             0 0 result element 2@      ( ... Zx Zy Zz arbAxisAng y x )
  1826.             atan2 radToDeg f*          ( ... Zx Zy Zz arbAxisAng LCSang )
  1827.  
  1828.             1.0 0.0 0.0                ( ... Zx Zy Zz arbAxisAng LCSang 1.0 0.0 0.0 )
  1829.             2 0 rotationMatrix element 2@
  1830.             1 0 rotationMatrix element 2@
  1831.             0 0 rotationMatrix element 2@ ( ... Zx Zy Zz arbAxisAng LCSang 1.0 0.0 0.0 x y z )
  1832.             vectorangle radToDeg f*    ( ... Zx Zy Zz arbAxisAng LCSang theta )
  1833.             f+                         ( ... Zx Zy Zz arbAxisAng rotationAng )
  1834.             2dup                       ( ... Zx Zy Zz arbAxisAng rotationAng rotationAng )
  1835.             textRotationPrimary 2!     ( ... Zx Zy Zz arbAxisAng roationAng )
  1836.             f+                         ( ... Zx Zy Zz arbAxisAng2 )
  1837.             textRotation 2!            ( ... Zx Zy Zz )
  1838.         then
  1839.     else
  1840.         \ Indicates no 210 group was present.
  1841.         0.0 0.0 0.0
  1842.     then
  1843.     0 2 extrusion element 2!
  1844.     0 1 extrusion element 2!
  1845.     0 0 extrusion element 2!
  1846. ;
  1847.  
  1848. \                                     Stack on entering:           Stack on leaving:
  1849. : save72Group                         ( ... )                      ( ... )
  1850.     72 group? if
  1851.         72 group group72 !
  1852.     else
  1853.         ." "Warning. No 72 group in MText entity." cr
  1854.     then
  1855. ;
  1856.  
  1857. \                                     Stack on entering:           Stack on leaving:
  1858. : saveHeight                          ( ... )                      ( ... )
  1859.     40 group
  1860.     textHeight 2!
  1861. ;
  1862.  
  1863. \                                     Stack on entering:           Stack on leaving:
  1864. : addExtrusion                        ( ... )                      ( ... )
  1865.     0 2 extrusion element 2@          ( ... z )
  1866.     0 1 extrusion element 2@          ( ... z y )
  1867.     0 0 extrusion element 2@          ( ... z y x )
  1868.     isZeroVector not if
  1869.         inbinary @ if
  1870.             210 ofile fputc drop
  1871.             ofile fputd drop          ( ... z y )
  1872.             220 ofile fputc drop
  1873.             ofile fputd drop          ( ... z )
  1874.             230 ofile fputc drop
  1875.             ofile fputd drop          ( ... )
  1876.         else
  1877.             "210" ofile fputs drop
  1878.             "%#g" edbuf fstrform      ( ... z y )
  1879.             edbuf ofile fputs drop
  1880.             "220" ofile fputs drop
  1881.             "%#g" edbuf fstrform      ( ... z )
  1882.             edbuf ofile fputs drop
  1883.             "230" ofile fputs drop
  1884.             "%#g" edbuf fstrform      ( ... )
  1885.             edbuf ofile fputs drop
  1886.         then
  1887.     else
  1888.         2drop 2drop 2drop
  1889.     then
  1890. ;
  1891.  
  1892. \                                     Stack on entering:           Stack on leaving:
  1893. : add72Group                          ( ... )                      ( ... )
  1894.     \ Transform 72 into 71 group.
  1895.     inbinary @ if
  1896.         72 ofile fputc drop
  1897.         0 ofile fputshort drop
  1898.     else
  1899.         "  72" ofile fputs drop
  1900.         "0" ofile fputs drop
  1901.     then
  1902.  
  1903.     group72 @ dup                     ( ... n n )
  1904.     1 = if                            ( ... n )
  1905.         drop                          ( ... )
  1906.         inbinary @ if
  1907.             71 ofile fputc drop
  1908.             0 ofile fputshort drop
  1909.         else
  1910.             "  71" ofile fputs drop
  1911.             "0" ofile fputs drop
  1912.         then
  1913.     else
  1914.         3 = if
  1915.             inbinary @ if
  1916.                 71 ofile fputc drop
  1917.                 0 ofile fputshort drop
  1918.             else
  1919.                 "  71" ofile fputs drop
  1920.                 "0" ofile fputs drop
  1921.             then
  1922.         then
  1923.     then
  1924. ;
  1925.  
  1926. \                                     Stack on entering:           Stack on leaving:
  1927. : addTextHeader                       ( ... )                      ( ... )
  1928.     \ Add a new TEXT entity.
  1929.     "TEXT" edbuf strcpy
  1930.     inbinary @ if
  1931.         0 ofile fputc drop
  1932.         edbuf strlen 1+
  1933.         edbuf ofile fwrite drop
  1934.         addLayer
  1935.         40 ofile fputc drop
  1936.         textHeight 2@
  1937.         ofile fputd drop
  1938.     else
  1939.         "  0" ofile fputs drop
  1940.         edbuf ofile fputs drop
  1941.         addLayer
  1942.         "  40" ofile fputs drop
  1943.         textHeight 2@                 ( ... addr )
  1944.         "%g" edbuf fstrform           ( ... )
  1945.         edbuf ofile fputs drop
  1946.     then
  1947.     addHandle
  1948.     addColor
  1949.     addRotationAngle
  1950.     add72group
  1951.     addExtrusion
  1952. ;
  1953.  
  1954. \                                     Stack on entering:           Stack on leaving:
  1955. : addTextStyle
  1956.     7group @ if
  1957.         inbinary @ if
  1958.             7 ofile fputc drop
  1959.             mtextStyle strlen 1+
  1960.             mtextStyle ofile fwrite drop
  1961.         else
  1962.             "  7" ofile fputs drop
  1963.             mtextStyle ofile fputs drop
  1964.         then
  1965.     then
  1966. ;
  1967.  
  1968. \                                     Stack on entering:           Stack on leaving:
  1969. : addTextPosition                     ( ... )                      ( ... )
  1970.     0 0 offset element 2@             ( ... x )
  1971.     0 1 offset element 2@             ( ... x y )
  1972.     0 2 offset element 2@             ( ... x y z )
  1973.     add10Group
  1974. ;
  1975.  
  1976. \                                     Stack on entering:           Stack on leaving:
  1977. : setNewTextPosition                  ( ... )                      ( ... )
  1978.     0 2 extrusion element 2@          ( ... z )
  1979.     0 1 extrusion element 2@          ( ... z y )
  1980.     0 0 extrusion element 2@          ( ... z y x )
  1981.     isZeroVector if
  1982.         textHeight 2@ 2dup            ( ... height height )
  1983.         mtextFudge f* f+ 2dup         ( ... newheight newheight )
  1984.         \ X component
  1985.         textRotationPrimary 2@ sin f* ( ... newheight sin*newheight )
  1986.         0 0 offset element 2@ f+
  1987.         0 0 offset element 2!         ( ... newheight )
  1988.  
  1989.         \ Y component
  1990.         textRotationPrimary 2@ cos f* ( ... cos*newheight )
  1991.         0 1 offset element 2@ 2swap f-
  1992.         0 1 offset element 2!         ( ... )
  1993.     else
  1994.         textHeight 2@ 2dup            ( ... height height )
  1995.         mtextFudge f* f+ 2dup         ( ... newheight newheight )
  1996.         \ X component
  1997.  
  1998.         textRotationPrimary 2@ degToRad f*
  1999.         sin f*                        ( ... newheight sin*newheight )
  2000.         0 0 vector element 2!         ( ... newheight )
  2001.  
  2002.         \ Y component
  2003.         textRotationPrimary 2@ degToRad f*
  2004.         cos f* -1.0 f*                ( ... cos*newheight )
  2005.         0 1 vector element 2!         ( ... )
  2006.         0.0 0 2 vector element 2!
  2007.  
  2008.         \ Transform this offset into the new coordinate system
  2009.         vector rotationMatrix 1x33x3multiply
  2010.         0 0 result element 2@         ( ... x )
  2011.         0 1 result element 2@         ( ... x y )
  2012.         0 2 result element 2@         ( ... x y z )
  2013.  
  2014. \       ." "vector after" cr
  2015. \       2pointprint
  2016.  
  2017.         0 0 offset element 2@         ( ... x y z x1 )
  2018.         0 1 offset element 2@         ( ... x y z x1 y1 )
  2019.         0 2 offset element 2@         ( ... x y z x1 y1 z1 )
  2020.         2pointadd                     ( ... x2 y2 z2 )
  2021.         0 2 offset element 2!
  2022.         0 1 offset element 2!
  2023.         0 0 offset element 2!
  2024.     then
  2025.     2drop 2drop 2drop
  2026. ;
  2027.  
  2028. \                                     Stack on entering:           Stack on leaving:
  2029. : mtextReadChar                       ( ... )                      ( ... )
  2030.     mtextFileA ftell                  ( ... p )
  2031.     dup 0 mtextFileA fseek            ( ... p )
  2032.     mtextFileA fgetc                  ( ... p c1 )
  2033.     dup                               ( ... p c1 c1 )
  2034.     EOF = if                          ( ... p c1 )
  2035.         dup                           ( ... p c1 c1 )
  2036.         thisChar !                    ( ... p c1 )
  2037.         nextChar !                    ( ... p )
  2038.         drop
  2039.     else                              ( ... p c1 )
  2040.         thisChar !                    ( ... p )
  2041.         1+ dup 0 mtextFileA fseek     ( ... p2 )
  2042.         mtextFileA fgetc              ( ... p2 c2 )
  2043.         nextChar !                    ( ... p2 )
  2044.         0 mtextFileA fseek            ( ... )
  2045.     then
  2046. ;
  2047.  
  2048. \                                     Stack on entering:           Stack on leaving:
  2049. : mtextWriteChar                      ( ... )                      ( ... )
  2050.     thisChar @                        ( ... c )
  2051.     longString countChar @ + c!
  2052.     1 countChar +!
  2053. ;
  2054.  
  2055. \                                     Stack on entering:           Stack on leaving:
  2056. : addLongString                       ( ... )                      ( ... )
  2057.     \ Save the character ...
  2058.     thisChar @                        ( ... c )
  2059.     EOS thisChar !
  2060.     mtextWriteChar
  2061.     \ ... now restore it.
  2062.     thisChar !
  2063.     inbinary @ if
  2064.         1 ofile fputc drop
  2065.         longString strlen 1+
  2066.         longString ofile fwrite drop
  2067.     else
  2068.         "  1" ofile fputs drop
  2069.         longString ofile fputs drop
  2070.     then
  2071.     0 countChar !
  2072. ;
  2073.  
  2074. \                                     Stack on entering:           Stack on leaving:
  2075. : equalToThisChar                     ( ... c1 )                   ( ... )
  2076.     thisChar @ =                      ( ... t/f )
  2077. ;
  2078.  
  2079. \                                     Stack on entering:           Stack on leaving:
  2080. : equalToNextChar                     ( ... c1 )                   ( ... )
  2081.     nextChar @ =                      ( ... t/f )
  2082. ;
  2083.  
  2084. \                                     Stack on entering:           Stack on leaving:
  2085. : deleteSemicolon
  2086.     iterator 0 do
  2087.         mtextReadChar
  2088.         semicolon equalToThisChar if
  2089.             leave
  2090.         then
  2091.     loop
  2092. ;
  2093.  
  2094. : mtextActionUnicode
  2095.     "2205" diameter strcpy
  2096.     "00B1" toler strcpy
  2097.     "00B0" degree strcpy
  2098.     diameter
  2099.     unicodeStr
  2100.     strcmp
  2101.     0= if
  2102.         percent thisChar !
  2103.         mtextWriteChar
  2104.         percent thisChar !
  2105.         mtextWriteChar
  2106.         "c"
  2107.         thisChar
  2108.         strcpy
  2109.         mtextWriteChar
  2110.     else
  2111.         toler
  2112.         unicodeStr
  2113.         strcmp
  2114.         0= if
  2115.             percent thisChar !
  2116.             mtextWriteChar
  2117.             percent thisChar !
  2118.             mtextWriteChar
  2119.             "p"
  2120.             thisChar
  2121.             strcpy
  2122.             mtextWriteChar
  2123.         else
  2124.             degree
  2125.             unicodeStr
  2126.             strcmp
  2127.             0= if
  2128.                 percent thisChar !
  2129.                 mtextWriteChar
  2130.                 mtextWriteChar
  2131.                 "d"
  2132.                 thisChar
  2133.                 strcpy
  2134.                 mtextWriteChar
  2135.              else
  2136.                 "?" thisChar strcpy
  2137.                  mtextWriteChar
  2138.              then
  2139.         then
  2140.     then
  2141. ;
  2142. \ A backslash has already been encountered. The next character dictates the action.
  2143. \                                     Stack on entering:           Stack on leaving:
  2144. : mtextActionBackslash                ( ... )                      ( ... n )
  2145.     \ '\'
  2146.     backSlash equalToNextChar if
  2147.         mtextReadChar mtextWriteChar
  2148.         exit
  2149.     then
  2150.  
  2151.     \ '{'
  2152.     leftBrace equalToNextChar if
  2153.         mtextReadChar
  2154.         mtextWriteChar
  2155.         exit
  2156.     then
  2157.  
  2158.     \ '}'
  2159.     rightBrace equalToNextChar if
  2160.         mtextReadChar
  2161.         mtextWriteChar
  2162.         exit
  2163.     then
  2164.  
  2165.     \ 'O'
  2166.     bigO equalToNextChar if
  2167.         mtextReadChar
  2168.         percent thisChar !
  2169.         mtextWriteChar
  2170.         mtextWriteChar
  2171.         bigO thisChar !
  2172.         mtextWriteChar
  2173.         exit
  2174.     then
  2175.  
  2176.     \ 'C'
  2177.     bigC equalToNextChar if
  2178.         deleteSemicolon
  2179.         exit
  2180.     then
  2181.  
  2182.     \ 'F'
  2183.     bigF equalToNextChar if
  2184.         deleteSemicolon
  2185.         exit
  2186.     then
  2187.  
  2188.     \ 'H'
  2189.     bigH equalToNextChar if
  2190.         deleteSemicolon
  2191.         exit
  2192.     then
  2193.  
  2194.     \ 'A'
  2195.     bigA equalToNextChar if
  2196.         mtextReadChar
  2197.         mtextReadChar
  2198.         thisChar @ ascii0 - dup       ( ... n n )
  2199.         \ Valid realignment values: 0 1 2
  2200.         0 = if                        ( ... n )
  2201.             drop                      ( ... )
  2202.             \ Offset = (1 1/3)*Height
  2203.             textHeight 2@             ( ... height )
  2204.             1.33 f* 2dup              ( ... 1.33height 1.33height )
  2205.             \ Y-value
  2206.             0 1 offset element 2@     ( ... 1.33height 1.33height y )
  2207.             2swap f-                  ( ... 1.33height y-1.33height
  2208.             0 1 offset element 2!     ( ... 1.33height )
  2209.             \ X-value
  2210.             0 0 offset element 2@     ( ... 1.33height x )
  2211.             2swap f-                  ( ... x-1.33height
  2212.             0 0 offset element 2!     ( ... )
  2213.         else                          ( ... n )
  2214.             1 = if                    ( ... )
  2215.                 \ Offset = (2/3)*Height
  2216.                 textHeight 2@         ( ... height )
  2217.                 0.47 f*               ( ... Cheight )
  2218.                 \ Y-value
  2219.                 0 1 offset element 2@ ( ... Cheight y )
  2220.                 2swap f-              ( ... y-Cheight )
  2221.                 0 1 offset element 2! ( ... )
  2222.                 \ X-value
  2223.                 textHeight 2@         ( ... height )
  2224.                 2.0 f*                ( ... Cheight )
  2225.                 0 0 offset element 2@ ( ... Cheight x )
  2226.                 2swap f-              ( ... x-Cheight )
  2227.                 0 0 offset element 2! ( ... )
  2228.             then
  2229.         then
  2230.         \ Delete the semicolon.
  2231.         mtextReadChar
  2232.         exit
  2233.     then
  2234.  
  2235.     \ 'U'
  2236.     bigU equalToNextChar if
  2237.         2 0 do
  2238.             mtextReadChar
  2239.         loop
  2240.         4 0 do
  2241.             mtextReadChar
  2242.             thisChar @
  2243.             unicodeStr i + c!
  2244.         loop
  2245.         mtextActionUnicode
  2246.         exit
  2247.     then
  2248.  
  2249.     \ 'S'
  2250.     bigS equalToNextChar if
  2251.          mtextReadChar
  2252.          space thisChar !
  2253.          mtextWriteChar
  2254.          iterator 0 do
  2255.              mtextReadChar
  2256.              separator equalToThisChar if
  2257.                  forwardSlash thisChar !
  2258.              then
  2259.              mtextWriteChar
  2260.              semicolon equalToNextChar if
  2261.                  mtextReadChar
  2262.                  leave
  2263.              then
  2264.          loop
  2265.          exit
  2266.     then
  2267.  
  2268.     \ 'o'
  2269.     littleO equalToNextChar if
  2270.         mtextReadChar
  2271.         percent thisChar !
  2272.         mtextWriteChar
  2273.         mtextWriteChar
  2274.         littleO thisChar !
  2275.         mtextWriteChar
  2276.         exit
  2277.     then
  2278.  
  2279.     \ 'L'
  2280.     bigL equalToNextChar if
  2281.         mtextReadChar
  2282.         percent thisChar !
  2283.         mtextWriteChar
  2284.         mtextWriteChar
  2285.         bigU thisChar !
  2286.         mtextWriteChar
  2287.         exit
  2288.     then
  2289.  
  2290.     \ 'l'
  2291.     littleL equalToNextChar if
  2292.         mtextReadChar
  2293.         percent thisChar !
  2294.         mtextWriteChar
  2295.         mtextWriteChar
  2296.         littleU thisChar !
  2297.         mtextWriteChar
  2298.         exit
  2299.     then
  2300.  
  2301.     \ 'P'
  2302.     bigP equalToNextChar if
  2303.         mtextReadChar
  2304.         addTextHeader
  2305.         addTextPosition
  2306.         setNewTextPosition
  2307.         addLongString
  2308.         addTextStyle
  2309.         exit
  2310.     then
  2311.  
  2312.     \ 'Q'
  2313.     bigQ equalToNextChar if
  2314.         deleteSemicolon
  2315.         exit
  2316.     then
  2317.  
  2318.     \ The default action.
  2319.     mtextWriteChar
  2320. ;
  2321.  
  2322. \                                     Stack on entering:           Stack on leaving:
  2323. : mtextAction                         ( ... )                      ( ... n )
  2324.     \ '{'
  2325.     leftBrace equalToThisChar if
  2326.         \ No action
  2327.         exit
  2328.     then
  2329.  
  2330.     \ '}'
  2331.     rightBrace equalToThisChar if
  2332.         \ No action
  2333.         exit
  2334.     then
  2335.  
  2336.     \ '\'
  2337.     backSlash equalToThisChar if
  2338.         \ Need to check the next character.
  2339.         mtextActionBackslash
  2340.         exit
  2341.     then
  2342.  
  2343.     \ o
  2344.     degreeSymbol equalToThisChar if
  2345.         percent thisChar !
  2346.         mtextWriteChar
  2347.         mtextWriteChar
  2348.         littleD thisChar !
  2349.         mtextWriteChar
  2350.         exit
  2351.     else
  2352.         altDegreeSymbol equalToThisChar if
  2353.             percent thisChar !
  2354.             mtextWriteChar
  2355.             mtextWriteChar
  2356.             littleD thisChar !
  2357.             mtextWriteChar
  2358.             exit
  2359.         then
  2360.     then
  2361.  
  2362.     \ plus/minus symbol
  2363.     tolerSymbol equalToThisChar if
  2364.         percent thisChar !
  2365.         mtextWriteChar
  2366.         mtextWriteChar
  2367.         "p" thisChar strcpy
  2368.         mtextWriteChar
  2369.         exit
  2370.     then
  2371.  
  2372.     \ percent
  2373.     percent equalToThisChar if
  2374.         percent thisChar !
  2375.         mtextWriteChar
  2376.         mtextWriteChar
  2377.         mtextWriteChar
  2378.         exit
  2379.     then
  2380.  
  2381.     \ The default action.
  2382.     mtextWriteChar
  2383. ;
  2384.  
  2385. : dxf:*:mtext
  2386.     "$mtexta.$ac" 11 mtextFileA fopen if
  2387.         saveHeight
  2388.         saveOffset
  2389.         saveLayer
  2390.         saveColor
  2391.         save72group
  2392.         saveExtrusion
  2393.         0
  2394.         3 group? if
  2395.             drop
  2396.             3 groupcount2
  2397.         then
  2398.         1 group? if
  2399.             1+
  2400.         then
  2401.         dup
  2402.         groupcount swap -
  2403.         11 group? if
  2404.             1-
  2405.         then
  2406.         210 group? if
  2407.             1-
  2408.         then
  2409.         7 group? if
  2410.             1-
  2411.             7 group
  2412.             mtextStyle
  2413.             strcpy
  2414.             true
  2415.         else
  2416.             false
  2417.         then
  2418.         7group !
  2419.         fixedMtextGroups !
  2420.         \ Top stack item 'p' contains the number of text groups which could
  2421.         \ be multiple 3 and one 1 group, or just multiple 3 groups.
  2422. \       dup                           ( ... p p )
  2423. \       ." "Number of 3 and/or 1 groups in this entity = " . cr ( ... p )
  2424.         0 do                          ( ... )
  2425.             i fixedMtextGroups @ +    ( ... n )
  2426.             -10000 swap -             ( ... -10000-n )
  2427.             dup                       ( ... -10000-n -10000-n )
  2428.             group strlen              ( ... -10000-n m )
  2429.             swap                      ( ... m -10000-n )
  2430.             group                     ( ... m addr )
  2431.             mtextFileA                ( ... m addr file )
  2432.             fwrite drop               ( ... )
  2433.         loop
  2434.  
  2435.         \ OK, all text is now written to 'mtextFileA'.
  2436.         \ Now delete everything.
  2437.         clearitem
  2438.         writeitem drop
  2439.  
  2440.         \ Now start reading the text from the temporary file taking the
  2441.         \  appropriate actions on control characters.
  2442.  
  2443.         \ Rewind the file.
  2444.         0 0 mtextFileA fseek
  2445.         0 countChar !
  2446.  
  2447.         setNewTextPosition
  2448.         mtextReadChar
  2449.         begin
  2450.         EOF equalToThisChar not
  2451.         while
  2452.             mtextAction
  2453.             mtextReadChar
  2454.             countChar @ mtextMaxLength >= if
  2455.                 addTextHeader
  2456.                 addTextPosition
  2457.                 setNewTextPosition
  2458.                 addLongString
  2459.                 addTextStyle
  2460.             then
  2461.         repeat
  2462.  
  2463.         \ Flush out the last Text entity.
  2464.         countChar @ if
  2465.             addTextHeader
  2466.             addTextPosition
  2467.             addLongString
  2468.             addTextStyle
  2469.         then
  2470.         mtextFileA fclose
  2471.         "$mtexta.$ac" fdelete drop
  2472.     else
  2473.         ." "Cannot open MText temporary file.\n"
  2474.     then
  2475. ;
  2476.  
  2477. \                                     Stack on entering:           Stack on leaving:
  2478. : getSplineItem                       ( ... #k p )                 ( ... #k p K )
  2479.     dup                               ( ... #k p p )
  2480.     -10000                            ( ... #k p p -10000 )
  2481.     swap -                            ( ... #k p -10000-p )
  2482.     2 pick - 1+                       ( ... #k p -10000-p-#k+1 )
  2483. ;
  2484.  
  2485. : dxf:*:spline
  2486.     saveLayer
  2487.     saveColor
  2488.     \ The spline iterator is proportional to the number of control points.
  2489.     73 group                          ( ... n )
  2490.     splineConstant *                  ( ... m )
  2491.     splineIterator !                  ( ... )
  2492.  
  2493.     \ Knots
  2494.     72 group dup                      ( ... #k #k )
  2495.     40 itempos2                       ( ... #k #k p )
  2496.  
  2497.     \ Store value of first knot value.
  2498.     dup                               ( ... #k #k p p )
  2499.     -10000 swap -                     ( ... #k #k p -10000-p )
  2500.     group                             ( ... #k #k p K0 )
  2501.     firstKnot 2!                      ( ... #k #k p )
  2502.     2dup                              ( ... #k #k p #k p )
  2503.     -10000 swap -                     ( ... #k #k p #k -10000-p )
  2504.     swap - 1+                         ( ... #k #k p -10000-p-#k+1 )
  2505.     \ Make sure we're within the domain range.
  2506.     group 1.0E-11 f-                  ( ... #k #k p Kn )
  2507.     firstKnot 2@ f- fabs              ( ... #k #k p abs[Kn-K0] )
  2508.     splineIterator @ 1 - float f/
  2509.     knotInterval 2!                   ( ... #k #k p )
  2510.  
  2511.     swap                              ( ... #k p #k )
  2512.     0 do                              ( ... #k p )
  2513.         getSplineItem
  2514.         i +                           ( ... #k p -10000-p-#k+1+i )
  2515.         group                         ( ... #k p K )
  2516.         2swap                         ( ... K #k p )
  2517.     loop
  2518.     drop                              ( ... Kn...K0 #k )
  2519.  
  2520.     \ Control points
  2521.     73 group dup                      ( .... #c #c )
  2522.     10 itempos2                       ( .... #c #c p )
  2523.     swap                              ( .... #c p #c )
  2524.     41 group? if
  2525.         \ Group sequence: 10-20-30-41-10-20-30-41 ...
  2526.         \ Position: -10000 - (p+2(#c-i-1))
  2527.         0 do                          ( .... #c p )
  2528.             dup                       ( .... #c p p )
  2529.             2 pick                    ( .... #c p p #c )
  2530.             i - 1-                    ( .... #c p p #c-i-1 )
  2531.             2*                        ( .... #c p p 2[#c-i-1] )
  2532.             +                         ( .... #c p p+2[#c-i-1] )
  2533.             -10000 swap -             ( .... #c p -10000-[p+2[#c-i-1] )
  2534.             group                     ( .... #c p Cx Cy Cz )
  2535.             3 2roll                   ( .... Cx Cy Cz #c p )
  2536.         loop
  2537.     else
  2538.         \ Group sequence: 10-20-30-10-20-30...
  2539.         \ Position: -10000-p-#c+1+i
  2540.         0 do                          ( .... #c p )
  2541.             getSplineItem
  2542.             i +                       ( .... #c p -10000-p-#c+1+i )
  2543.             group                     ( .... #c p Cx Cy Cz )
  2544.             3 2roll                   ( .... Cx Cy Cz #c p )
  2545.         loop
  2546.     then
  2547.     drop                              ( ... Kn...K0 #k CxmCymCzm...Cx0Cy0Cz0 #c )
  2548.  
  2549.     \ Weights
  2550.     41 group? not if
  2551.         \ Same number of weights as control points.
  2552.         dup                           ( .... #c #c )
  2553.         0 do                          ( .... #c )
  2554.             dup                       ( .... #c #c )
  2555.             1.0                       ( .... #c #c 1.0 )
  2556.             2swap                     ( .... 1.0 #c #c )
  2557.             drop                      ( .... 1.0 #c )
  2558.         loop
  2559.     else
  2560.         \ Same number of weights as control points.
  2561.         dup                           ( .... #c #c )
  2562.         41 itempos2                   ( .... #c #c p )
  2563.         swap                          ( .... #c p #c )
  2564.         0 do                          ( .... #c p )
  2565.             dup                       ( .... #c p p )
  2566.             2 pick                    ( .... #c p p #c )
  2567.             i - 1-                    ( .... #c p p #c-i-1 )
  2568.             2*                        ( .... #c p p 2[#c-i-1] )
  2569.             +                         ( .... #c p p+2[#c-i-1] )
  2570.             -10000 swap -             ( .... #c p -10000-[p+2[#c-i-1] )
  2571.             group                     ( .... #c p W )
  2572.             2swap                     ( .... W #c p )
  2573.         loop
  2574.         drop
  2575.     then                              ( ... Kn...K0 #k CxmCymCzm...Cx0Cy0Cz0 Wm...W0 #c )
  2576.  
  2577.     \ Order
  2578.     71 group 1+                       ( ... Kn...K0 #k CxmCymCzm...Cx0Cy0Cz0 Wm...W0 #c order )
  2579.  
  2580.     \ Set up flag to begin (true) or end (false).
  2581.     true
  2582.     setupspline
  2583.  
  2584.     clearitem writeitem drop
  2585.  
  2586.     \ Now vary the parameter from the value of the first to the last knot.
  2587.     0.0 0.0 0.0
  2588.     addPolylineHeader
  2589.     add3dPolylineHeader
  2590.  
  2591.     splineIterator @ 0 do
  2592.         i float knotInterval 2@ f*
  2593.         firstKnot 2@ f+
  2594.         evalSpline
  2595.         addVertex
  2596.         addVertexTrailer
  2597.     loop
  2598.     addSequend
  2599.  
  2600.     \ Clean up any memory allocated by the interpreter.
  2601.     false
  2602.     setupspline
  2603. ;
  2604.  
  2605. : doLeader
  2606.         \ Decompose into polyline segments.
  2607.         saveLayer
  2608.         saveColor
  2609.         10 itempos2                   ( ... n )
  2610.         76 group 1- +                 ( ... n+[x-1] )
  2611.         dup dup                       ( ... m m m )
  2612.  
  2613.         76 group 0 do                 ( ... m m m )
  2614.             -10000 swap -             ( ... m m -10000-m )
  2615.             i +                       ( ... m m -10000-m+i )
  2616.             group                     ( ... m m xx yy zz )
  2617.             3 2roll                   ( ... xx yy zz m m )
  2618.             dup                       ( ... xx yy zz m m m )
  2619.         loop
  2620.         drop drop drop
  2621.  
  2622.         76 group                      ( .... xx yy zz xx yy zz p )
  2623.         clearitem writeitem drop
  2624.         0.0 0.0 0.0 addPolylineHeader
  2625.         add3dPolylineHeader
  2626.  
  2627.         0 do                          ( .... xx yy zz xx yy zz )
  2628.             addVertex                 ( .... xx yy zz )
  2629.             addVertexTrailer
  2630.         loop
  2631.         addSequend
  2632. ;
  2633.  
  2634. : dxf:entities:leader
  2635.     doLeader
  2636. ;
  2637.  
  2638. : dxf:blocks:leader
  2639.     doLeader
  2640. ;
  2641.  
  2642. \   Termination processing
  2643. : dxf:end
  2644.     handleson @ if
  2645.         \ No need to run a second pass if no new entities were added.
  2646.         needToRewind @ if
  2647.             \ Run 2 passes on the input file.
  2648.             \ This is done to increment the handle seed value back in the header.
  2649.             rewind @ if
  2650.                 false rewind !
  2651.                 "End translation.\n" type
  2652.             else
  2653.                 true rewind !
  2654.                 "End first pass, now updating handle values.\n" type
  2655.             then
  2656.         then
  2657.     then
  2658.     depth if
  2659.         .s cr
  2660.     then
  2661. ;
  2662.