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