home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 1998 April / DPPCPRO0498.ISO / April / AutoCAD / ACLT / DXFIX.DOC < prev    next >
Encoding:
Text File  |  1997-10-16  |  72.1 KB  |  1,525 lines

  1.  
  2.                               D X F I X
  3.                               =========
  4.  
  5.   An open, programmable application permits translation of ASCII or
  6.   binary DXF files to input compatible with any release of AutoCAD.
  7.  
  8.                             by John Walker
  9.             Revision 2 by Duff Kurland -- February 18, 1991
  10.             R13->R12 conversion additions by Gary Scott -- March 9, 1995
  11.  
  12.  
  13.                Of one power  even God is deprived,  and
  14.                that is the power of making what is past
  15.                never to have been.
  16.                                  -- Aristotle, 340 B.C.
  17.  
  18.  
  19. Ever  since  the  first incremental update to AutoCAD(R), the issue of
  20. downward compatibility has been raised by users.  Unlike many software
  21. products, AutoCAD has always taken great pains to maintain 100% upward
  22. compatibility from  release  to  release--any  drawing  made  with  an
  23. earlier  release of AutoCAD can be edited with any subsequent release.
  24. The converse, however, is not the case.  Once a drawing is edited with
  25. a given release of AutoCAD it cannot be loaded by a prior release.  In
  26. fact, prior to Release 10, DXF(tm) files written by a later version of
  27. AutoCAD could not be loaded into an  earlier  version  without  manual
  28. modification.
  29.  
  30. In Release 10, we introduced code in DXFIN to ignore header variables,
  31. symbol tables, and entity fields not defined by the version of AutoCAD
  32. loading  the  DXF  file.   While  this  fixes  many  of  the  problems
  33. encountered  in  loading  DXF  written  by a later release of AutoCAD,
  34. experience has proven it inadequate; Release 10 still cannot read  DXF
  35. written by Release 11 without manual editing of the file.
  36.  
  37. This  shouldn't  be  surprising.   Solving  the  problem  of  downward
  38. compatibility in  a  general  way  is  extremely  difficult  since  it
  39. requires the developer, in essence, to anticipate the future direction
  40. of product  development.   Further,  the  need  to  maintain  downward
  41. compatibility  with  products  already  in the field may encourage bad
  42. design decisions in new product development, burdening those  products
  43. with  inefficiencies  and  unneeded  complexity.   While  it's easy to
  44. omit  entire  objects  that aren't recognized when loading a DXF file,
  45. coping with the subtler differences between releases of  AutoCAD  such
  46. as new bits denoting variants of Polylines, changes to text alignment,
  47. and the like cannot be reasonably done at the DXF input  level.   (The
  48. introduction  of  AUDIT  in  Release  11  will  go  a  long way toward
  49. detecting and discarding undefined  information  received  from  later
  50. releases  of  AutoCAD.   But  that,  of  course, doesn't help users of
  51. releases prior to 11.  Further, AUDIT will never be able to  translate
  52. entities  in subsequent releases into their equivalents in the release
  53. on which it's running.)
  54.  
  55. With the end approaching for support of various venerable AutoCAD host
  56. machines (e.g., the 8086 and 8088 in Release 11), the need  arises  to
  57. allow  users  of  those  machines  to  load,  albeit with some loss of
  58. information,  drawings  made  by  AutoCAD  Release  11  and,  ideally,
  59. releases   after   that.   The  fact  that  information  may  be  lost
  60. down-converting a drawing may not be as serious as it appears at first
  61. glance--the  user  of an obsolete machine is, in all likelihood, using
  62. it for pretty basic 2D drafting work.  Having the polyface meshes  and
  63. registered  application  name tables purged from a drawing is unlikely
  64. to bother such a user, particularly when the alternatives  are  either
  65. not  being  able  to  edit  the  drawing  at all or having to junk his
  66. computer.
  67.  
  68. The most straightforward way  to  provide  this  compatibility  is  by
  69. translating  a  DXF  file written by a new release of AutoCAD into one
  70. that can be  loaded  by  an  earlier  target  system.   Prior  to  the
  71. introduction  of  binary  DXF  in  Release 10, this was a very painful
  72. process since DXF files were huge, took forever to read and write, and
  73. forced a tradeoff between file size and accuracy of the numbers in the
  74. file.  With binary DXF, however, nothing  is  lost  in  exporting  and
  75. transferring  a  drawing via DXF, and the file sizes and I/O times are
  76. comparable to regular drawing (.dwg) files.
  77.  
  78. What we need, then, is a DXF converter  program--one  that  reads  DXF
  79. from  Release  11  and emits DXF compatible with Release 10.  Ideally,
  80. such a product should  be  configurable  so  changes  made  in  future
  81. releases  do  not require continual modification of the DXF converter.
  82. Indeed, the  converter  should  be  *programmable*,  so  that  it  can
  83. translate  DXF  from  ANY  release  of AutoCAD into that of any other.
  84. Best of all would be a converter that was open,  programmable  by  the
  85. user, one that  could  perform  any  transformation  on  a  DXF  file.
  86. DXFIX(tm)  (Drawing  eXchange  File  Inter Xlator) is precisely such a
  87. tool.   Incorporating  the  FORTH-based  Autodesk  Threaded   Language
  88. Application System Toolkit (ATLAST (tm)), DXFIX is an open system that
  89. can be used, without speed penalty, for the simple task of  converting
  90. DXF  from  Release  11  to  Release  10, or programmed by anybody with
  91. access to this documentation to perform arbitrary translation of  DXF.
  92.  
  93.  
  94. Running DXFIX
  95. -------------
  96.  
  97. NOTE: If you install AutoCAD for Win95, NT or Win3.1 you will get an
  98.       executable named DXFIXW95.EXE, not DXFIX.EXE. Use this new file
  99.       to perform DXF translation under Win95, NT, Win3.1 and DOS. The
  100.       original DXFIX (supplied with the DOS AutoCAD installation)
  101.       should be used, however, if running Norton Desktop under Win3.1.
  102.       In addition, DXFIX will still run under native DOS, but may not
  103.       run in a DOS box under Win95 or NT.
  104.                   
  105. To convert a Release 11 DXF file to Release 10, use the command:
  106.  
  107.     dxfix  [options]  infile  outfile
  108.  
  109. where  "infile"  is  the  input DXF file name (an extension of .dxf is
  110. assumed if no explicit extension  is  given),  and  "outfile"  is  the
  111. output  DXF file name (.dxf is also added to this name if no extension
  112. is present).  The input DXF file can be either binary or ASCII format;
  113. binary format is much faster to process and maintains full accuracy of
  114. drawing objects, but if you supply  an  ASCII  DXF  file,  DXFIX  will
  115. process  it  without difficulty.  DXFIX reads binary DXF files written
  116. in AutoCAD portable format regardless of the system  on  which  it  is
  117. running,  and  ASCII  DXF  with  any  of  the  end of line conventions
  118. recognized by AutoCAD.
  119.  
  120. The "outfile" is written, by default,  in  binary  DXF  format.   When
  121. transferring  data to AutoCAD Release 10, this format is preferable by
  122. far as it is much faster to write, generally  smaller,  and  preserves
  123. full  accuracy.  If you want ASCII DXF output instead (for example, if
  124. the DXF is intended for an AutoCAD  prior  to  Release  10  that  only
  125. supports  ASCII DXF, or is being sent to a non-Autodesk DXF processing
  126. program that requires ASCII), specify  the  "-Adigits"  option,  where
  127. "digits" is a number giving the precision, in decimal places, to which
  128. numbers should be edited in the ASCII DXF file.
  129.  
  130. For example, to convert a Release 11 DXF file named "house11.dxf" to a
  131. Release  10  DXF  file  named  "house10.dxf" (writing "house10.dxf" in
  132. binary format), use:
  133.  
  134.     dxfix  house11  house10
  135.  
  136. To perform the same translation, but generating an ASCII  output  file
  137. with six decimal places of precision, use:
  138.  
  139.     dxfix  -a6  house11  house10
  140.  
  141. The  actual  translation  relies  on  specifications given in the file
  142. "dxfix.dxt", which is assumed to  reside  in  the  current  directory.
  143. Alternatively,  you can use the "-Tname" option to specify a different
  144. location  or  name  for  the  translation  specifications  file.   For
  145. instance:
  146.  
  147.     dxfix  -a6  -t\dxfix\11_to_10  house11  house10
  148.  
  149. tells  DXFIX  to  find  its  translation  specifications  in  the file
  150. "\dxfix\11_to_10.dxt".  Note that the extension  .dxt  is  assumed  if
  151. none is supplied.
  152.  
  153.  
  154. Release 11 to 10 translations
  155. -----------------------------
  156.  
  157. The  following  Release 11 to Release 10 translations are specified by
  158. the standard "dxfix.dxt" file provided with  this  version  of  DXFIX.
  159.  
  160. Deleting new header variables
  161.   The  following drawing header variables, added since Release 10, are
  162.   deleted.  (The names in the DXF file are preceded by  dollar  signs;
  163.   we give the base names here, as they are more familiar.)
  164.  
  165.     DIMCLRD      Dimension line colour
  166.     DIMCLRE      Dimension extension line colour
  167.     DIMCLRT      Dimension text colour
  168.     DIMGAP       Dimension block gap
  169.     DIMSTYLE     Current dimension style
  170.     DIMTFAC      Dimension text vertical position
  171.     MAXACTVP     Maximum active viewports
  172.     PELEVATION   Paper elevation
  173.     PEXTMAX      Paper maximum extents
  174.     PEXTMIN      Paper minimum extents
  175.     PINSBASE     Paper insertion base
  176.     PLIMCHECK    Paper limit checking
  177.     PLIMMAX      Paper maximum limits
  178.     PLIMMIN      Paper minimum limits
  179.     PUCSNAME     Paper UCS name
  180.     PUCSORG      Paper UCS origin
  181.     PUCsXDIR     Paper UCS X direction
  182.     PUCSYDIR     Paper UCS Y direction
  183.     SHADEDGE     SHADE command edge rendering mode
  184.     SHADEDIF     Shading diffuse illumination factor
  185.     TILEMODE     Tiled viewports mode
  186.     UNITMODE     Drawing unit mode bits
  187.     VISRETAIN    Layer/viewport visibility retention
  188.  
  189. Flattening Z extents
  190.   The  drawing  extents,  output  as  the  $EXTMAX  and $EXTMIN header
  191.   variables, contain Z extents for  the  first  time  in  Release  11.
  192.   Earlier  releases  report an error when encountering an unexpected Z
  193.   coordinate, so the Z coordinates are removed from  these  variables.
  194.  
  195. Trapping zero $DIMSCALE
  196.   In Release 11, the DIMSCALE dimensioning variable can be set to zero
  197.   for paper space scaling.  If a zero is detected, it  is  changed  to
  198.   1.0.
  199.  
  200. Deleting new symbol tables
  201.   The  following new symbol tables were added in Release 11.  They are
  202.   deleted in their entirety from the TABLES section.
  203.  
  204.     APPID     - Registered application table
  205.     DIMSTYLE  - Dimension style table
  206.  
  207. Handling new LAYER table flag bits
  208.   The 70 (flags) group of the LAYER table entry has a  few  new  bits.
  209.   The  "frozen  by  default  in  new  viewports" bit has no meaning in
  210.   Release 10 and is zeroed.  If any of the "dependent symbol" bits are
  211.   set, the entire layer entry is discarded.
  212.  
  213. Deleting new entities
  214.   All VIEWPORT entities, used by the multiple view facility of Release
  215.   11, are deleted whenever  encountered  in  the  ENTITIES  or  BLOCKS
  216.   section.
  217.  
  218. Deleting new entity fields
  219.   The following fields, representing features added in Release 11, are
  220.   deleted from the entities in which they appear.
  221.  
  222.     BLOCK entity:
  223.       The 1 (Xref path name) and 3 (block name)  groups  are  deleted.
  224.       In  addition,  all Xref-related bits of the 70 (flags) group are
  225.       zeroed.  If the BLOCK was an Xref, it  becomes  a  dummy  BLOCK.
  226.  
  227.     DIMENSION entity:
  228.       The  3  (dimension  style),  52  (obliquing angle), and 53 (text
  229.       rotation angle) groups are deleted.
  230.  
  231. Deleting new common entity fields
  232.   The following fields, which can occur on any entity in the database,
  233.   are deleted wherever encountered.
  234.  
  235.     Extended entity data:
  236.       Extended  entity data (entity attributes) has group codes in the
  237.       1000 to 1100 range.  All  groups  in  that  range  are  deleted,
  238.       stripping all extended entity data from the drawing.
  239.  
  240.     Paper/model space indicator
  241.       A  new  common  property  of all entities, the paper/model space
  242.       indicator, is represented in DXF by a 67 group, where:
  243.  
  244.         0 = model space
  245.         1 = paper space
  246.  
  247.       All other values are reserved for future use.  Since versions of
  248.       AutoCAD  prior  to  Release  11 don't support paper space, DXFIX
  249.       deletes all entities whose 67 group is nonzero.  If the 67 group
  250.       is zero, just that group is deleted.
  251.  
  252. Adjusting text vertical alignment
  253.   In  Release  11,  general specification of the vertical alignment of
  254.   Text, Attribute Definition, and Attribute entities was  implemented.
  255.   Earlier  releases  provided  general  horizontal alignment, with one
  256.   special case providing both horizontal and vertical centering.   The
  257.   new-style   "MCenter"   specification   is   translated   into   the
  258.   near-equivalent "MID" form accepted by versions prior to Release 11.
  259.   All other instances of vertical alignment cause the text to be reset
  260.   to  left/baseline  justification.   In such cases, a warning message
  261.   informs the user of the  loss  of  alignment  information,  and  the
  262.   justification  point  (group  11)  is  deleted.   In  all cases, the
  263.   vertical alignment group (73 in a Text entity, 74 in an Attribute or
  264.   Attribute Definition) is deleted.
  265.  
  266. Exploding polyface meshes
  267.   In Release 11 a new variant of the  Polyline  entity,  the  polyface
  268.   mesh,  was introduced.  Consisting of a table of vertices and faces,
  269.   it is a far more compact representation of tiled surfaces  than  the
  270.   3Dface  entities  used  prior  to Release 11.  However, any polyface
  271.   mesh can be represented by a collection of 3Dface, Line,  and  Point
  272.   entities.   If  the  mesh is EXPLODEd prior to DXFOUT, the resulting
  273.   file can be loaded into Release 10 without difficulty.  To eliminate
  274.   this requirement (and to demonstrate by a flashy but convenient tour
  275.   de force the ATLAST-derived power of DXFIX), polyface meshes present
  276.   in  the  DXF  input  file  are  automatically  transformed  into the
  277.   equivalent collection of  individual  entities.   This  is  done  by
  278.   saving  the  vertices  in  a  temporary  file,  then  replacing each
  279.   polyface entity with the  corresponding  simple  entity.   Invisible
  280.   edge specifications are converted from the negative-vertex form used
  281.   in polyface meshes to the invisible edge bits used in 3Dfaces.   The
  282.   temporary  file,  "$pface.$ac",  is  deleted  at the end of DXF file
  283.   translation.
  284.  
  285.  
  286. Translation specifications
  287. --------------------------
  288.  
  289. Most customers who use DXFIX to convert Release 11 DXF to  Release  10
  290. need  know  nothing more about the program than the information above:
  291. how to run  it  and  what  information  is  lost  in  the  process  of
  292. converting  a  drawing.  DXFIX is, however, far more than a Release 11
  293. to Release 10 DXF translator.  In fact, it  knows  nothing  about  the
  294. contents of either Release 11 or Release 10 DXF.  DXFIX is actually an
  295. ATLAST-based, general purpose, open architecture DXF  translator.   As
  296. long  as  no  fundamentally  new  data types are added to DXF (and the
  297. extended entity group codes and binary chunks of Release 11  were  the
  298. first  additions  to the format in 5 years and 6 releases), DXFIX will
  299. be able, given suitable specifications,  to  translate  DXF  from  any
  300. AutoCAD  of  the future to any AutoCAD target system of Release 2.0 or
  301. later.  (Earlier versions of AutoCAD used a totally different form  of
  302. DXF,  and  while  DXFIX could even be made to generate that format, it
  303. would hardly be worth the bother.)
  304.  
  305. The transformation of a DXF file by DXFIX can be controlled at several
  306. different levels, provided  by  the  natural  layering  of  an  ATLAST
  307. application.  Each will be discussed in turn.
  308.  
  309.  
  310. Layer 0:  Translation file selection
  311. ------------------------------------
  312.  
  313. The transformations performed by DXFIX are defined in  a  "translation
  314. specification  file",  which  is actually an executable ATLAST program
  315. loaded by  DXFIX  to  perform  the  translation.   If  no  translation
  316. specification  file  is  named  on the DXFIX command line, the default
  317. file named "dxfix.dxt" is used.  The version of "dxfix.dxt"  furnished
  318. with  the  initial  version of DXFIX performs Release 11 to Release 10
  319. translation.  It is intended  that  when  DXFIX  is  shipped  with  an
  320. AutoCAD  release,  it  will normally be accompanied with a "dxfix.dxt"
  321. file that converts DXF from that release to the immediately prior one.
  322.  
  323. If  you  wish to use different translation specifications, specify the
  324. "-Tname" switch on  the  DXFIX  command  line,  where  "name"  is  the
  325. translation  specification  file  name.  If no extension is specified,
  326. ".dxt" is automatically appended.  For example,  if  you  had  a  file
  327. named  "r11_r9.dxt"  that  converts Release 11 DXF to input compatible
  328. with Release 9, you could translate a DXF  file  called  "chair11.dxf"
  329. with the command:
  330.  
  331.     dxfix  -tr11_r9  chair11  chair9
  332.  
  333. Since  Release  9  cannot read binary DXF, the "r11_r9.dxt" file would
  334. automatically  select  ASCII  output  format,  even  though  the  user
  335. specified  no "-Adigits" switch on the command line.  (We'll see later
  336. how the translation specifications can control  that  and  much,  much
  337. more.)
  338.  
  339.  
  340. Layer 1: Object processing specifications
  341. -----------------------------------------
  342.  
  343. Since much of the process of translating a DXF file consists of simply
  344. deleting material added in  later  releases,  much  of  a  translation
  345. specification  file  consists of statements that specify what is to be
  346. deleted, which bits should be turned off in mask fields, and the like.
  347. The  ability  to  define  new  data  types  and  methods  in ATLAST is
  348. exploited to  make  these  specifications  simple  and  readable.   To
  349. understand the bulk of the specifications in the "dxfix.dxt" file, you
  350. must first understand the hierarchy of a DXF file and the nomenclature
  351. DXFIX uses to designate different levels and objects in the structure.
  352.  
  353. The overall structure of a DXF file is as follows:
  354.  
  355.   Sections        Subsections      Objects      Groups
  356.   ---------       -----------      -------      ------
  357.   HEADER      
  358.                                    Variables
  359.                                                 Groups
  360.   TABLES
  361.                  LTYPE
  362.                                    Entries
  363.                                                 Groups
  364.                  LAYER
  365.                                    Entries
  366.                                                 Groups
  367.                  STYLE
  368.                                    Entries
  369.                                                 Groups
  370.                  ...
  371.   BLOCKS
  372.                                    Entities
  373.                                                 Groups
  374.   ENTITIES
  375.                                    Entities
  376.                                                 Groups
  377.   EOF
  378.  
  379. Processing  of  different  parts  of  this hierarchy is specified by a
  380. "structure name" that selects the portions(s) of the hierarchy  to  be
  381. processed.   Each  structure  name  begins  with the characters "DXF:"
  382. followed by the path through the hierarchy  with  wild-card  selection
  383. available by specifying the "*" character at various places.
  384.  
  385. To  illustrate  the  use of structure names, we'll use the most common
  386. declaration  in  a  translation  specification  file,   the   "remove"
  387. statement.   All objects that match the structure name are deleted, in
  388. their entirety, from the DXF file.  Here is  how  "dxfix.dxt"  deletes
  389. the paper space extents header variables from Release 11 DXF.
  390.  
  391.   remove dxf:header:$pextmax
  392.   remove dxf:header:$pextmin
  393.  
  394. The structure name "dxf:header:$pextmax" specifies the HEADER variable
  395. section, object $pextmax (recall that all header  variable  names  are
  396. prefixed  with a "$" in DXF files).  When this variable is encountered
  397. in the DXF file, its action, "remove", is executed,  thereby  deleting
  398. the  variable  from  the  output  file.   To  delete additional header
  399. variables, just add "remove" statements naming them.
  400.  
  401. To demonstrate the generality of this approach, let's examine how  the
  402. new  Release  11  DIMSTYLE  (Dimension  Style)  table is deleted.  The
  403. specification that accomplishes this is just:
  404.  
  405.   remove dxf:tables:dimstyle
  406.  
  407. Unlike the HEADER variables section, the TABLES  section  can  contain
  408. multiple  objects  in each table--in this case any number of dimension
  409. styles.  The structure name triggers, however, when it matches to  the
  410. end  of  the  name  specification,  so this "remove" statement will be
  411. executed for each entry in the DIMSTYLE table.  Since  each  execution
  412. has the effect of deleting the current item (and since the table start
  413. and table end items are also matched  as  part  of  the  table),  this
  414. single  statement deletes the entire dimension style symbol table from
  415. the output DXF.
  416.  
  417. As part of the multiple view plotting facility in Release  11,  a  new
  418. VIEWPORT entity was added to the database.  All of these entities must
  419. be removed when converting a DXF file for use with Release 10.   Since
  420. VIEWPORT  entities  can  appear  in either the ENTITIES section or, if
  421. part of a Block Definition, in the BLOCKS section, we can remove  them
  422. from both sections with the statements:
  423.  
  424.   remove dxf:blocks:viewport
  425.   remove dxf:entities:viewport
  426.  
  427. The  "remove"  declaration  isn't  the  only action we can take when a
  428. section name is matched.  The "ditchgroup" statement causes the  named
  429. group  (which must be specified to the group level) to be deleted from
  430. the current object.  For example, three new groups were added  to  the
  431. Dimension  entity  in  Release  11.   To  remove these, we can use the
  432. statements:
  433.  
  434.   ditchgroup dxf:*:dimension:3
  435.   ditchgroup dxf:*:dimension:52
  436.   ditchgroup dxf:*:dimension:53
  437.  
  438. The  first  statement  matches the 3 group of objects (entities) named
  439. DIMENSION appearing in any section of the DXF file  (effectively  just
  440. the  BLOCKS and ENTITIES sections, since DIMENSION objects appear only
  441. there).  The action of "ditchgroup" causes the 3 group to  be  deleted
  442. wherever  it  appears  within a Dimension entity.  The statements that
  443. follow similarly delete the 52 and 53 groups.
  444.  
  445. Extended  entity  data  (entity attributes) were introduced in Release
  446. 11.  These are written to DXF files with group codes between 1000  and
  447. 1100, and must be removed when translating DXF for earlier versions of
  448. AutoCAD.  We can remove all extended entity data, wherever present  in
  449. the DXF file, with the statement:
  450.  
  451.   ditchgroup dxf:*:*:1000-1100
  452.  
  453. In  this  case we're wild-carding both the section and the object type
  454. and taking advantage of the ability to specify a range of group  codes
  455. to  be selected.  If we wanted to select the polyface vertex fields in
  456. a Vertex entity, we could use "dxf:*:vertex:71-74".
  457.  
  458. If special processing  is  specified  at  more  than  one  level  (for
  459. example,   a   given  group  might  be  selected  by  a  global  group
  460. specification, as a group of an entity of that type, or as a member of
  461. an  object  of  that  type), processing is done with the most specific
  462. (group) first to the most general (item) last.
  463.  
  464.  
  465. Layer 2:  Translation programming
  466. ---------------------------------
  467.  
  468. What appears at first glance to be a  data  file  that  specifies  the
  469. changes to be made to a DXF  file  is,  in  actuality,  an  executable
  470. ATLAST  program.   The  program  has  access  to  all the usual ATLAST
  471. facilities and, in addition, a set of  primitives  provided  by  DXFIX
  472. that  allow  easy manipulation of objects in the DXF file.  The key to
  473. understanding how DXFIX and ATLAST work together is the structure name
  474. specifications  described  in  Layer  1  above.   Each  structure name
  475. specification   is   actually   an   executable   ATLAST    definition
  476. automatically  invoked  when  a  matching component of the DXF file is
  477. encountered.  The ability to potentially run  a  user-defined  program
  478. for  every  component  of  the file permits DXFIX to perform arbitrary
  479. transformations on the DXF files it  processes.   The  quickness  with
  480. which  DXFIX  can  determine  if special processing is requested for a
  481. component of the DXF file (by pre-scanning the ATLAST  dictionary  for
  482. the  "DXF:"  definitions and building a hierarchically-organized table
  483. of processing requests, it is just a  matter  of  a  few  pointer  and
  484. integer  comparisons), and the inherent speed of executing precompiled
  485. ATLAST code in an already-looked-up definition, result in DXFIX  being
  486. able to perform substantial user-specified processing while running at
  487. essentially the same speed  as  a  simple  DXF  copy  program  written
  488. entirely in C.
  489.  
  490. To  understand  how DXFIX and ATLAST are woven together into a unified
  491. general purpose translation tool, let's start with the DXF  processing
  492. primitives  added  to  ATLAST by DXFIX.  Many of these primitives will
  493. rarely be used in any but the most ambitious DXF translation  projects
  494. (far  more  complicated than converting Release 11 to Release 10), but
  495. they're available if you need them.  Key to  understanding  the  DXFIX
  496. primitives is the "current item".  DXFIX is always working on one item
  497. (structure delimiter, header variable, symbol table entry, or  entity)
  498. from  the  DXF  file  at  a  time.   This  current  item is implicitly
  499. referenced by all of the item and group manipulation primitives.
  500.  
  501.  
  502. Item primitives
  503. ---------------
  504.  
  505. The item primitives operate upon entire items (lists of groups forming
  506. the fundamental objects in the DXF file).
  507.  
  508.   CLEARITEM    All groups of the current item are deleted.  You'd only
  509.                use this if you intended  to  build  a  new  item  from
  510.                scratch using ADDGROUP.  The stack is not affected.
  511.  
  512.   ITEMPOS      The position at which the current item began in the DXF
  513.                file is placed on the stack.  This is the  line  number
  514.                of  the  first  group  of the item if the input file is
  515.                ASCII or its byte number if the input is binary.   Both
  516.                lines and bytes are numbered from zero.
  517.  
  518.   PRINTITEM    All  groups  of  the  current  item  are printed on the
  519.                output file specified by the top of the stack.  You can
  520.                use  the  predefined  and  automatically opened streams
  521.                STDOUT and STDERR to send  output  to  the  user.   For
  522.                example,   if   an  Arc  is  the  current  entity,  the
  523.                statement:
  524.  
  525.                  stdout printitem
  526.  
  527.                might generate the following output:
  528.  
  529.                   0:  "ARC"
  530.                   8:  "0"
  531.                  10:  (3, 2, 0)
  532.                  40:  1
  533.                  50:  0
  534.                  51:  90
  535.  
  536.   READITEM     The next item is read from the DXF file and becomes the
  537.                current  item.   If  the  item  is read normally, -1 is
  538.                placed on the stack; if end of file  or  a  read  error
  539.                occurs,  0  is  placed  on the stack.  When the item is
  540.                read, all  special  processing  declared  by  structure
  541.                names  that  match  the item and/or groups within it is
  542.                automatically  performed  BEFORE  the  item   is   made
  543.                available  to  the caller of READITEM.  If the previous
  544.                current item has not been written to  the  output  file
  545.                with  WRITEITEM  before  READITEM is called to read the
  546.                next, it will be lost--deleted from the output file.
  547.  
  548.   WRITEITEM    The  current item is written to the output file, unless
  549.                marked for deletion.  If the item is  written  normally
  550.                or  is  to  be  deleted, -1 is placed on the top of the
  551.                stack.  If an error occurs attempting to write the item
  552.                to the output file, 0 is returned on the stack top.  If
  553.                the DELITEM (delete item) shared variable  is  nonzero,
  554.                the  item  is  not  written to the output file, and the
  555.                DELITEM variable is cleared to zero.  If  the  DELCITEM
  556.                (delete  complex  item) shared variable is nonzero, the
  557.                item is not written to the output file and, if the item
  558.                is  a  Sequence  End  entity,  the DELCITEM variable is
  559.                cleared to zero.
  560.  
  561.   (Added for R13->R12 conversion)
  562.   SETUPSPLINE  This primitive was added to allow Spline entities to
  563.                be converted into more primitive entities. It is
  564.                used just prior to calling the EVALSPLINE
  565.                primitive below and again just after. The first
  566.                call before EVALSPLINE should pass the following
  567.                values on the stack:
  568.  
  569.                Top of stack -> true (integer)
  570.                                Order of spline (integer)
  571.                                Number of weights (integer)
  572.                                Weight_0 (floating point)
  573.                                ...
  574.                                Weight_M (floating point)
  575.                                Control point Z_0 (floating point)
  576.                                Control point Y_0 (floating point)
  577.                                Control point X_0 (floating point)
  578.                                ...
  579.                                Control point Z_M (floating point)
  580.                                Control point Y_M (floating point)
  581.                                Control point X_M (floating point)
  582.                                Number of knots (integer)
  583.                                Knot_0 (floating point)
  584.                                ...
  585.                                Knot_N (floating point)
  586.  
  587.  
  588.                Note that the number of weights is equal to the
  589.                number of control points.                 
  590.  
  591.                After EVALSPLINE is called, SETUPSPLINE should be
  592.                called again with only the value 'false' on
  593.                top of the stack. This frees up any memory
  594.                allocated during the initial call.
  595.  
  596.   (Added for R13->R12 conversion)
  597.   EVALSPLINE   This primitive was added to allow Spline entities to
  598.                be evaluated after setting up the parameters with
  599.                the SETUPSPLINE call above. It uses a Cox-de Boor
  600.                B-spline function to return a 3D point given a
  601.                certain parameter value. For example, the R13->R12
  602.                translator varies the parameter from the value of
  603.                the first knot to the last knot over an equaly
  604.                spaced interval.             
  605.                 
  606.                  -> 23.45 evalspline f. f. f.
  607.                  6.78 9.01 2.34
  608.  
  609.  
  610. Group primitives
  611. ----------------
  612.  
  613. The group primitives provide access to the individual data fields that
  614. make  up an item.  In the following descriptions of primitives, assume
  615. that the current item is a Line entity on layer  0,  from  coordinates
  616. (1,1,0)  to  (2,2,0).   This item would be displayed with the sequence
  617. "stdout printitem" as:
  618.  
  619.    0:  "LINE"
  620.    8:  "0"
  621.   10:  (1, 1, 0)
  622.   11:  (2, 2, 0)
  623.  
  624. Groups within an item can be identified either by  group  code  or  by
  625. their  position  within  the  item.   Regular  AutoCAD item fields are
  626. always unique and may be  identified  simply  by  their  group  codes.
  627. Extended entity data, however, uses the same group code for all fields
  628. of a given type,  so  group  codes  are  not  necessarily  unique.   A
  629. positive number used to designate a group chooses the first occurrence
  630. of that group code in the current item.  A negative number of the form
  631. -(10000 + n), where "n" specifies the position of the group within the
  632. item (with the first group numbered zero), selects the  nth  group  in
  633. the  chain  of  groups  composing the item and may be used to uniquely
  634. specify extended entity groups that appear more than once in an  item.
  635.  
  636.   PRINTGROUP   The group identified by the second item on the stack is
  637.                printed on the output stream specified by  the  top  of
  638.                stack.  For example:
  639.  
  640.                  -> 10 stdout printgroup
  641.                    10:  (1, 1, 0)
  642.                  -> -10001 stdout printgroup
  643.                     8:  "0"
  644.  
  645.   GROUPCOUNT   Places  the number of groups in the current item on the
  646.                top of the stack.
  647.  
  648.                  -> groupcount .
  649.                  4
  650.  
  651.   (Added for R13->R12 conversion)
  652.   GROUPCOUNT2  Places the number of a particular group in the current
  653.                item on the top of the stack. This is useful, for
  654.                example, in MText entities to find out how many 3
  655.                groups are in an item.
  656.  
  657.                  -> 10 groupcount2 .
  658.                  1
  659.  
  660.   (Added for R13->R12 conversion)
  661.   ITEMPOS2     The zero based index at which the specified group began
  662.                in the current item is placed on the stack. This
  663.                is useful, for example, in a Spline entity to
  664.                determine where to start requesting the control
  665.                point groups (10 groups) using the -(10000 + n)
  666.                technique mentioned above.
  667.  
  668.                  -> 10 itempos2 .
  669.                  2
  670.  
  671.   GROUP?       If the group with group code given by the  top  of  the
  672.                stack  is  present in the item, -1 is placed on the top
  673.                of the stack.  If the group  does  not  appear  in  the
  674.                item, 0 is returned.
  675.  
  676.                  -> 10 group? .
  677.                  -1
  678.                  -> 40 group? .
  679.                  0
  680.  
  681.   DELGROUP     The  group  on the top of the stack is deleted from the
  682.                item, if  present.   If  the  specified  group  is  not
  683.                present, DELGROUP is simply ignored.
  684.  
  685.                  -> stdout printitem
  686.                     0:  "LINE"
  687.                     8:  "0"
  688.                    10:  (1, 1, 0)
  689.                    11:  (2, 2, 0)
  690.                  -> 8 delgroup
  691.                  -> stdout printitem
  692.                     0:  "LINE"
  693.                    10:  (1, 1, 0)
  694.                    11:  (2, 2, 0)
  695.  
  696.   GROUP        The  value  of the specified group, in whatever form is
  697.                appropriate for it, is placed on the top of the  stack.
  698.                Integers are stored as single stack items; real numbers
  699.                and angles as pairs of stack items  representing  their
  700.                floating point values; coordinates as triples of pairs,
  701.                each giving a floating coordinate with Z at the top  of
  702.                the  stack,  Y next, and then X; strings as the address
  703.                of a temporary string buffer containing the  text;  and
  704.                binary  chunks as a length, in bytes, on the top of the
  705.                stack and the address of the chunk data,  stored  in  a
  706.                temporary string buffer, next on the stack.
  707.  
  708.                  -> 10 group f. f. f.
  709.                  0 1 1
  710.  
  711.   ADDGROUP     A  group with the type given by the top of the stack is
  712.                added to the end of the item.  The value field  of  the
  713.                group  is  cleared  to  zero,  and may be then set with
  714.                SETGROUP.
  715.  
  716.                  -> 62 addgroup
  717.                  -> stdout printitem
  718.                     0:  "LINE"
  719.                    10:  (1, 1, 0)
  720.                    11:  (2, 2, 0)
  721.                    62:  0
  722.  
  723.   SETGROUP     Sets the value of the group specified by the top of the
  724.                stack  to  the values below it (in the same form as the
  725.                results  returned  by  GROUP).    Removes   the   group
  726.                specification and the values from the stack.
  727.  
  728.                  -> 3 62 setgroup
  729.                  -> 3.0 4.0 5.0 10 setgroup
  730.                  -> stdout printitem
  731.                     0:  "LINE"
  732.                    10:  (3, 4, 5)
  733.                    11:  (2, 2, 0)
  734.                    62:  3
  735.  
  736.  
  737. Diagnostic primitives
  738. ---------------------
  739.  
  740.   DUMPSPECIAL  The hierarchy of the DXF file is printed, including all
  741.                items named by  structure  name  declarations  (whether
  742.                seen  in  the  DXF  file  or  not)  and  those actually
  743.                encountered in processing the input file so far.  Those
  744.                items  for  which  special  processing is requested are
  745.                identified with the legend "(Special)".  At the end  of
  746.                the listing, wild-card specifications are listed.  Here
  747.                is the output from  DUMPSPECIAL  after  the  first  few
  748.                header variables of a DXF file are processed when using
  749.                the standard  Release  11  to  Release  10  "dxfix.dxt"
  750.                specifications.
  751.  
  752.                  -> readitem readitem readitem readitem
  753.                  -> dumpspecial
  754.                  START (Special)
  755.                  HEADER
  756.                      $INSBASE
  757.                      $ACADVER
  758.                      $DIMCLRD (Special)
  759.                      $DIMCLRE (Special)
  760.                      $DIMCLRT (Special)
  761.                      $DIMGAP (Special)
  762.                      $DIMSTYLE (Special)
  763.                      $DIMTFAC (Special)
  764.                      $MAXACTVP (Special)
  765.                      $PELEVATION (Special)
  766.                      $PEXTMAX (Special)
  767.                      $PEXTMIN (Special)
  768.                      $PINSBASE (Special)
  769.                      $PLIMCHECK (Special)
  770.                      $PLIMMAX (Special)
  771.                      $PLIMMIN (Special)
  772.                      $PUCSNAME (Special)
  773.                      $PUCSORG (Special)
  774.                      $PUCSXDIR (Special)
  775.                      $PUCSYDIR (Special)
  776.                      $SHADEDGE (Special)
  777.                      $SHADEDIF (Special)
  778.                      $TILEMODE (Special)
  779.                      $UNITMODE (Special)
  780.                      $VISRETAIN (Special)
  781.                      $EXTMAX (Special)
  782.                      $EXTMIN (Special)
  783.                      $DIMSCALE (Special)
  784.                  TABLES
  785.                      APPID (Special)
  786.                      DIMSTYLE (Special)
  787.                      LAYER (Special)
  788.                  ENTITIES
  789.                      VIEWPORT (Special)
  790.                  BLOCKS
  791.                      VIEWPORT (Special)
  792.                      BLOCK (Special)
  793.                  END (Special)
  794.  
  795.                  Group range actions:
  796.                  DXF:*:DIMENSION:3
  797.                  DXF:*:DIMENSION:52
  798.                  DXF:*:DIMENSION:53
  799.                  DXF:*:*:1000-1100
  800.                  DXF:*:TEXT:73
  801.                  DXF:*:ATTDEF:74
  802.                  DXF:*:ATTRIB:74
  803.                  DXF:*:*:67
  804.                  DXF:*:POLYLINE:70
  805.                  DXF:*:SEQEND:*
  806.                  DXF:*:VERTEX:70
  807.  
  808.  
  809. Command line primitives
  810. -----------------------
  811.  
  812. The  following  primitives  provide access to the command line used to
  813. invoke DXFIX.  They can be used by advanced  translation  programs  to
  814. obtain  parameters  from  the  command  line.  The following primitive
  815. descriptions assume that DXFIX has been invoked with  a  command  line
  816. of:
  817.  
  818.     dxfix  -i  -v11  -y=NO  dxin  dxout
  819.  
  820.   OPTION       Tests whether a command line option letter, prefixed by
  821.                a minus sign,  is  present.   If  that  option  is  not
  822.                specified, 0 is placed on the top of the stack.  If the
  823.                option is present, a pointer to the text  that  follows
  824.                the  option  letter  is  placed on the top of the stack
  825.                (the pointer is guaranteed to be nonzero).   Note  that
  826.                if  no text follows the option letter, the pointer will
  827.                still be nonzero indicating the option  was  specified.
  828.                The  pointer will point to a null string, in that case.
  829.  
  830.                  -> "v" option type cr
  831.                  11
  832.                  -> "x" option . cr
  833.                  0
  834.                  -> "Y" option type cr
  835.                  =NO
  836.  
  837.   ARGCOUNT     Places the number of command line arguments,  including
  838.                the zeroth argument that gives the program name itself,
  839.                on the top of the stack.
  840.  
  841.                  -> argcount
  842.                  6
  843.  
  844.   ARGVALUE     Given a number from 0 to ARGCOUNT-1 on the top  of  the
  845.                stack,  returns  a pointer to a temporary string buffer
  846.                containing a copy of that command  line  argument.   If
  847.                the  number  is less than 0 or >= ARGCOUNT, 0 is placed
  848.                on the top of the stack.
  849.  
  850.                  -> 2 argvalue type cr
  851.                  -v11
  852.                  -> 6 argvalue . cr
  853.                  0
  854.                  -> : targs argcount 0 do i argvalue type
  855.                  :>  cr loop ;
  856.                  -> targs
  857.                  dxfix
  858.                  -i
  859.                  -v11
  860.                  -y=NO
  861.                  dxin
  862.                  dxout
  863.  
  864.  
  865. Shared variables
  866. ----------------
  867.  
  868. A number of shared variables serve  to  exchange  information  between
  869. DXFIX  and  the  ATLAST  translation  specification  program.    These
  870. variables are all integers (with the exception of OFILE and
  871. IFILE), and have the following meanings.
  872.  
  873.   DELITEM      DELITEM causes the current item to  be  deleted  rather
  874.                than   being  written  to  the  output  DXF  file  when
  875.                WRITEITEM is invoked.  You can  set  DELITEM  from  any
  876.                structure  name  definition  to  cause  the  item  that
  877.                invoked that definition to be deleted from  the  output
  878.                file.
  879.  
  880.   DELCITEM     DELCITEM  causes  the  current item, and all subsequent
  881.                items up to and including the next Sequence End  entity
  882.                to  be  deleted  from  the  output DXF file rather than
  883.                being written to it by  WRITEITEM.   A  structure  name
  884.                definition  may set DELCITEM when processing the header
  885.                of a complex entity (for example, a polygon mesh,  when
  886.                generating  DXF  for  a  version  of  AutoCAD  prior to
  887.                Release 10) which should be deleted  in  its  entirety.
  888.  
  889.   INBINARY     If the input file is binary, INBINARY has the value -1.
  890.                If the input file is ASCII, it's 0.
  891.  
  892.   OUTPREC      The OUTPREC variable specifies the mode of  the  output
  893.                file  and,  if  ASCII,  the precision of floating point
  894.                numbers written to it.  If the output file  is  binary,
  895.                OUTPREC  is  set  to  -1;  if  this  default  has  been
  896.                overridden with a "-Adigits" specification on the DXFIX
  897.                command  line, OUTPREC will be set to "digits".  If the
  898.                value of OUTPREC is set by a  DXF:START  definition  in
  899.                the  translation  program,  the  value  specified  will
  900.                override the default or  the  value  from  the  command
  901.                line.
  902.  
  903.   DUMPINPUT    If  DUMPINPUT is nonzero, each item read from the input
  904.                DXF file will be dumped to standard output.
  905.  
  906.   DUMPOUTPUT   If DUMPOUTPUT is nonzero,  each  item  written  to  the
  907.                output DXF file will be dumped to standard output.
  908.  
  909.   SPECIALDONE  When   an   item   matches   multiple   structure  name
  910.                definitions, each is normally executed in sequence.  If
  911.                a  structure name definition performs an action that by
  912.                its very nature completes the processing  of  the  item
  913.                (for  example,  setting  DELITEM  to delete it from the
  914.                output  file),  it  may  set  SPECIALDONE.   Once  this
  915.                variable is set nonzero by a structure name definition,
  916.                no other structure name  definition  triggered  by  the
  917.                item  will  be  processed.   This is particularly handy
  918.                when you wish processing  of  a  certain  group  of  an
  919.                entity to replace the default handling of entities with
  920.                that group missing.
  921.  
  922.   DXFTRACE     If the translation program sets DXFTRACE  nonzero,  all
  923.                invocations  of  structure name definitions are printed
  924.                on standard output.  Here is the  output  generated  by
  925.                translation  of a Release 11 DXF file with DXFTRACE set
  926.                to 1.
  927.  
  928.                  Invoking DXF:START
  929.                  Invoking DXF:HEADER:$EXTMIN
  930.                  Invoking DXF:HEADER:$EXTMAX
  931.                  Invoking DXF:HEADER:$DIMSCALE
  932.                  Invoking DXF:HEADER:$DIMSTYLE
  933.                  Invoking DXF:HEADER:$DIMCLRD
  934.                  Invoking DXF:HEADER:$DIMCLRE
  935.                  Invoking DXF:HEADER:$DIMCLRT
  936.                  Invoking DXF:HEADER:$DIMTFAC
  937.                  Invoking DXF:HEADER:$DIMGAP
  938.                  Invoking DXF:HEADER:$PELEVATION
  939.                  Invoking DXF:HEADER:$PUCSNAME
  940.                  Invoking DXF:HEADER:$PUCSORG
  941.                  Invoking DXF:HEADER:$PUCSXDIR
  942.                  Invoking DXF:HEADER:$PUCSYDIR
  943.                  Invoking DXF:HEADER:$SHADEDGE
  944.                  Invoking DXF:HEADER:$SHADEDIF
  945.                  Invoking DXF:HEADER:$TILEMODE
  946.                  Invoking DXF:HEADER:$MAXACTVP
  947.                  Invoking DXF:HEADER:$PINSBASE
  948.                  Invoking DXF:HEADER:$PLIMCHECK
  949.                  Invoking DXF:HEADER:$PEXTMIN
  950.                  Invoking DXF:HEADER:$PEXTMAX
  951.                  Invoking DXF:HEADER:$PLIMMIN
  952.                  Invoking DXF:HEADER:$PLIMMAX
  953.                  Invoking DXF:HEADER:$UNITMODE
  954.                  Invoking DXF:HEADER:$VISRETAIN
  955.                  Invoking DXF:TABLES:LAYER
  956.                  Invoking DXF:TABLES:LAYER
  957.                  Invoking DXF:TABLES:LAYER
  958.                  Invoking DXF:TABLES:APPID
  959.                  Invoking DXF:TABLES:APPID
  960.                  Invoking DXF:TABLES:APPID
  961.                  Invoking DXF:TABLES:DIMSTYLE
  962.                  Invoking DXF:TABLES:DIMSTYLE
  963.                  Invoking DXF:TABLES:DIMSTYLE
  964.                  Invoking DXF:BLOCKS:BLOCK
  965.                  Invoking DXF:BLOCKS:BLOCK
  966.                  Invoking DXF:*:SEQEND
  967.                  Invoking DXF:BLOCKS:BLOCK
  968.                  Invoking DXF:BLOCKS:BLOCK
  969.                  Invoking DXF:*:TEXT:73
  970.                  Invoking DXF:*:DIMENSION:3
  971.                  Invoking DXF:*:POLYLINE:70
  972.                  Invoking DXF:*:SEQEND
  973.                  Invoking DXF:*:SEQEND
  974.                  Invoking DXF:BLOCKS:BLOCK
  975.                  Invoking DXF:BLOCKS:BLOCK
  976.                  Invoking DXF:*:TEXT:73
  977.                  Invoking DXF:*:*:1000-1100
  978.                  Invoking DXF:*:*:1000-1100
  979.                  Invoking DXF:*:*:1000-1100
  980.                  Invoking DXF:*:*:1000-1100
  981.                  Invoking DXF:*:*:67
  982.                  Invoking DXF:ENTITIES:VIEWPORT
  983.                  Invoking DXF:END
  984.  
  985.   (Added for R13->R12 conversion)
  986.   REWIND       If the translation program sets REWIND  nonzero,
  987.                traslation will be rerun from the beginning after
  988.                the current translation is complete. This is used
  989.                to update the handle seed value when new entities
  990.                are added to the output dxf file (for example,
  991.                when an ellipse is decomposed into a polyline).
  992.  
  993.   (Added for R13->R12 conversion)
  994.   OFILE        This stream is made available to directly access
  995.                the output file. It is used in R13 conversion to
  996.                directly write new entities to the output file.
  997.  
  998.   (Added for R13->R12 conversion)
  999.   IFILE        This stream is made available to directly access
  1000.                the input file. It is not currently used in R13
  1001.                dxf conversion but is supplied here to complement
  1002.                the OFILE stream.
  1003.  
  1004. Missing Z coordinates
  1005. ---------------------
  1006.  
  1007. Some versions of DXF files contain two dimensional as  well  as  three
  1008. dimensional  points.   Unfortunately,  these objects are distinguished
  1009. only by the absence or presence, respectively, of a 3x  group  in  the
  1010. DXF  file.   They  cannot  be  told  apart  by  group  code alone once
  1011. assembled into composite structures with group codes from  10  to  19.
  1012. To  allow translation programs to determine whether a Z coordinate was
  1013. supplied in input and to control whether a  Z  coordinate  is  written
  1014. when  a point group is output, a special floating point variable named
  1015. MISSING_Z is defined.  The variable has a value of -1*(10^308),  which
  1016. should  never  occur in a valid AutoCAD database.  If the Z coordinate
  1017. of a point group tests equal to MISSING_Z, no Z coordinate was present
  1018. in  the  DXF input file.  If you set the Z coordinate of a point group
  1019. to MISSING_Z, only X and Y coordinates will be written for that  point
  1020. when it is output.  See the definition of DROP_Z in "dxfix.dxt" for an
  1021. example of MISSING_Z being used to discard an unwanted  Z  coordinate.
  1022.  
  1023.  
  1024. Structure name execution
  1025. ------------------------
  1026.  
  1027. As each item is read from the input DXF file, DXFIX matches it against
  1028. the  structure  words  (such  as  DXF:ENTITIES:LINE)  defined  in  the
  1029. translation   program.   When  a  match  occurs,  that  definition  is
  1030. executed, allowing it to perform whatever operations  it  wishes  upon
  1031. the current item.  Two kinds of structure names can be specified.  The
  1032. first contains no wild cards or group number and is  triggered  by  an
  1033. entire item in the input; it will be executed only once per item.  The
  1034. second form of structure name does contain wild cards and/or  a  group
  1035. number  or  range  of  group  numbers.  This form of structure name is
  1036. triggered at the individual group level; note that  a  structure  name
  1037. with  a  wild  card and no group range is triggered for EVERY group in
  1038. the item (if you don't want this to happen,  simply  specify  a  group
  1039. code  known  to  appear  only  once in the item, or set SPECIALDONE to
  1040. avert further processing of structure names for the  item).   The  two
  1041. forms  of structure names are executed in different ways as well.  The
  1042. following examples should make the distinctions clear.
  1043.  
  1044.  
  1045. Item level structure names
  1046. --------------------------
  1047.  
  1048. Examples  of  item  level  structure  names  are   DXF:HEADER:$EXTMIN,
  1049. DXF:TABLES:APPID,  and  DXF:ENTITIES:VERTEX.   Each of these denotes a
  1050. definition triggered when  an  object  with  that  sequence  of  names
  1051. appears  in  the  DXF hierarchy.  The test for the presence of an item
  1052. level structure name is extremely fast, as DXFIX knows  at  all  times
  1053. where  it  is  in  the hierarchy and does not need to search a list of
  1054. definitions.
  1055.  
  1056. When an item just read from the input file triggers a structure  name,
  1057. the  definition  for that name is run.  Nothing is placed on the stack
  1058. before executing the definition, and the definition  should  leave  no
  1059. result  on the stack.  Since the definition can examine and manipulate
  1060. the current item  with  the  primitives  provided  for  that  purpose,
  1061. there's no need to pass data on the stack.
  1062.  
  1063. Suppose  we  want to delete the UNITMODE header variable.  This can be
  1064. accomplished with the following definition:
  1065.  
  1066.   : dxf:header:$unitmode
  1067.       1 delitem !
  1068.   ;
  1069.  
  1070. Now when the $UNITMODE item is encountered in the HEADER section, this
  1071. definition will be run.  It stores 1 into the shared variable DELITEM,
  1072. which  causes  DXFIX  not  to  emit  the  item  to  the  output  file,
  1073. accomplishing the objective of the definition.
  1074.  
  1075. Another  example  of  an item level structure name is provided by this
  1076. definition that deletes the Xref information  from  Release  11  block
  1077. definitions:
  1078.  
  1079.   : dxf:blocks:block
  1080.       70 group? if
  1081.           70 group 3 and 70 setgroup
  1082.       then
  1083.       1 delgroup
  1084.       3 delgroup
  1085.   ;
  1086.  
  1087. When  triggered  by  each BLOCK entity in the BLOCKS section (the only
  1088. place they appear), this definition obtains its 70 group flags, clears
  1089. the Xref bits if set, and stores the revised flags using SETGROUP.  It
  1090. then uses DELGROUP twice to delete any 1 and 3 Xref groups present  in
  1091. the BLOCK entity.  Since DELGROUP does nothing if the group is absent,
  1092. the definition need not use  GROUP?   to  test  whether  those  groups
  1093. exist.
  1094.  
  1095.  
  1096. Group level structure names
  1097. ---------------------------
  1098.  
  1099. Group  level  structure  names contain wild card specifications, group
  1100. numbers or ranges, or both.  Group level structure names  are  matched
  1101. and  executed  at  the group level, and are passed the group code that
  1102. triggered them on the stack when invoked.   Examples  of  group  level
  1103. structure  names are DXF:*:*:1000-1100 which is triggered by any group
  1104. with a code between 1000 and 1100, wherever found in the  input  file;
  1105. DXF:TABLES:STYLE:70,  executed  for  the 70 group of each entry in the
  1106. STYLE table  of  the  TABLES  section;  and  DXF:*:TEXT:73,  activated
  1107. whenever a 73 group is encountered in a TEXT item anywhere in the file
  1108. (of course,  TEXT  items  appear  only  in  the  BLOCKS  and  ENTITIES
  1109. sections).
  1110.  
  1111. Checking  for  the  presence  of a group level structure definition is
  1112. somewhat less efficient than determining if an item  level  definition
  1113. exists.   You should use group level names only when you need the wild
  1114. card selection and group identification they provide.
  1115.  
  1116. In translating Release 11 DXF to Release 10, we want to delete all  52
  1117. groups  from  Dimension entities.  These entities can appear in either
  1118. the BLOCKS or the ENTITIES section.  We can accomplish this with:
  1119.  
  1120.   : dxf:*:dimension:52
  1121.       delgroup
  1122.   ;
  1123.  
  1124. Since this is a group level structure name definition, the group  code
  1125. that  invoked  it  (in this case 52) is placed on the top of the stack
  1126. before our definition is executed.  Knowing it's there, we  need  only
  1127. execute DELGROUP to remove the group from all DIMENSION items.
  1128.  
  1129. Actually,  we  want  to  get rid of both 52 and 53 groups in Dimension
  1130. entities.  This requires only our specifying the range of groups:
  1131.  
  1132.   : dxf:*:dimension:52-53
  1133.       delgroup
  1134.   ;
  1135.  
  1136. Again, since the group code  that  triggered  the  structure  name  is
  1137. placed on the stack, the definition does not need to "know" what group
  1138. caused it to be run.
  1139.  
  1140. An extreme example of a group range is provided by a  definition  that
  1141. removes all extended entity data from a DXF file.
  1142.  
  1143.   : dxf:*:*:1000-1100
  1144.       delgroup
  1145.   ;
  1146.  
  1147. Here  we delete all groups between 1000 and 1100 in any section of the
  1148. file.  (We should only find such groups in  the  BLOCKS  and  ENTITIES
  1149. section, but no harm is done by this more general specification.)
  1150.  
  1151. We can do anything we like with groups, not just delete them.  Suppose
  1152. we wished to guarantee that the 4 bit was never set in the 70 group of
  1153. a  Vertex  entity  (it's never supposed to be set anyway, but what the
  1154. heck).  The following definition will  clear  any  erroneously  set  4
  1155. bits.
  1156.  
  1157.   : dxf:*:VERTEX:70
  1158.       group 4 not and
  1159.       70 setgroup
  1160.   ;
  1161.  
  1162. When  this definition is activated, we use the group code on the stack
  1163. to obtain the current value of the field.  We then push the constant 4
  1164. for  the bit we wish to clear and use NOT to complement its bits.  AND
  1165. gives us the value with the 4 bit guaranteed to be off.  We then  push
  1166. the  group  code  of 70 (we could have copied the version on the stack
  1167. originally, but since this definition is only executed for 70  groups,
  1168. using  the  constant  is simpler and faster) and use SETGROUP to store
  1169. the masked value back into the group.
  1170.  
  1171. The only limits on the amount of processing you can do when  triggered
  1172. by a group are your ambition in writing code and your patience waiting
  1173. for it to execute.  Take a gander at the definition of DXF:*:VERTEX:70
  1174. actually  used in "dxfix.dxt" to translate polyface meshes into simple
  1175. entities for an idea of where the deep end begins.
  1176.  
  1177.  
  1178. Layer 3: Structure defining words
  1179. ---------------------------------
  1180.  
  1181. "But hey!", you say, "Those definitions you just showed me don't  look
  1182. anything  like  the  'remove'  and 'ditchgroup' statements you told me
  1183. about that are used in 'dxfix.dxt.'"
  1184.  
  1185. Right you are.  In "dxfix.dxt" we took advantage of one  of  the  most
  1186. powerful  aspects  of  ATLAST  to  make the translation specifications
  1187. compact,  readable,  and  efficient.   ATLAST  allows  you  to  create
  1188. "defining  words"  which  can subsequently be used to declare new data
  1189. types complete with method code to be executed when the data  type  is
  1190. referenced.   If the motive of ATLAST is "every product programmable",
  1191. its means are "every token executable".  When you say "2 3  +"  in  an
  1192. ATLAST  program, you're EXECUTING the literal 2 (in the implementation
  1193. as well as conceptually), which has the effect of  placing  2  on  the
  1194. stack.   You  next  EXECUTE  the literal 3, placing it on top of the 2
  1195. already there.  Finally, you EXECUTE the primitive "+", which adds the
  1196. two numbers and leaves their sum, 5, on the stack.
  1197.  
  1198. Not  only  can you add definitions which are executed just like system
  1199. primitives, you can also define new data types by creating definitions
  1200. called  "defining  words"  that  allocate  and  initialize storage and
  1201. specify a runtime method.  I took advantage of this facility to create
  1202. the REMOVE statement, defined as follows:
  1203.  
  1204.   : remove
  1205.       create
  1206.       does>
  1207.           drop
  1208.           1 delitem !
  1209.   ;
  1210.  
  1211. When you specify:
  1212.  
  1213.   remove dxf:entities:viewport
  1214.  
  1215. you  are actually EXECUTING the definition of REMOVE.  This definition
  1216. performs a CREATE, which causes the next token to be defined an a new,
  1217. executable  definition.   Following  the  CREATE  one can allocate and
  1218. initialize storage for  the  definition  (what  are  called  "instance
  1219. variables"  in  object-land).   This  definition  requires no data, so
  1220. CREATE is followed immediately by DOES>, which introduces  the  method
  1221. to be executed when the new definition is itself executed.  Whenever a
  1222. definition made with CREATE is executed, the address  of  its  storage
  1223. area  (instance  variables)  is passed to it on the stack--how can you
  1224. know what you need to do if you don't know who  you  are?   Since  our
  1225. definition  doesn't  need this address, we discard it with DROP.  That
  1226. taken care of, we need only set DELITEM to  1,  thereby  deleting  the
  1227. current  item,  and we're done.  Recall that REMOVE is declaring a new
  1228. EXECUTABLE word.  When we use it to  declare  a  DXF  structure  name,
  1229. we're  automatically  registering the processing defined by its method
  1230. to be done whenever that word is triggered.  Thus the user can  simply
  1231. write "remove statements", oblivious of the underlying mechanism.
  1232.  
  1233. We  can  exploit  instance  variables  to  create  more  sophisticated
  1234. defining words.  Here is a definition that allows us to AND  arbitrary
  1235. groups in a DXF file with any mask we wish:
  1236.  
  1237.   : maskfield
  1238.       create       (   Define Data Type:    )
  1239.       ,            ( Compile bitmask        )
  1240.       does>        (    Runtime Method:     )
  1241.           over     ( Duplicate group index  )
  1242.           group    ( Extract value of group )
  1243.           swap     ( Bitmask address to top )
  1244.           @        ( Get value of bitmask   )
  1245.           and      ( Mask value of field    )
  1246.           swap     ( Get group code on top  )
  1247.           setgroup ( Update group in item   )
  1248.   ;
  1249.  
  1250. We  can  use  this  definition to clear the 4 bits in Vertex entities,
  1251. rather than the less readable explicit definition we used before:
  1252.  
  1253.   4 not maskfield dxf:*:vertex:70
  1254.  
  1255. When this is executed we push 4 on the stack, invert its bits  to  get
  1256. our  AND  mask,  and  then execute MASKFIELD.  It performs a CREATE to
  1257. define the following token (in this case our structure name), and uses
  1258. the comma primitive to remove the value from the top of the stack (the
  1259. AND mask) and store it in the next instance variable field of the word
  1260. we're defining.
  1261.  
  1262. When DXFIX encounters a 70 group in a Vertex entity in the input file,
  1263. it will push the group code, 70, then  execute  DXF:*:VERTEX:70.   The
  1264. definition  pushes  its  instance variable address and runs the method
  1265. that follows the DOES> in the definition.  That method, in turn, grabs
  1266. the  group  index  from  the second item on the stack (OVER), gets its
  1267. current value (GROUP), moves the instance variable address, where  the
  1268. mask used by this word has been stored to the top of the stack (SWAP),
  1269. loads the mask from that location (@), logically ANDs  the  mask  with
  1270. the  value from the group, moves the group code to the top (SWAP), and
  1271. updates the group in the current item (SETGROUP).
  1272.  
  1273. Once a defining word like this has been created, the user can  use  it
  1274. to  simply  list  the  masks  and  field names to which they should be
  1275. applied without thinking about how it's all really working.
  1276.  
  1277. You can create defining words with  arbitrarily  complicated  methods.
  1278. An  example  is  the  definition  of  TEXTVADJ  in  "dxfix.dxt", which
  1279. declares the special processing of Release 11 text vertical  alignment
  1280. groups.   Since  these  groups  appear  in  three  different  kinds of
  1281. entities (Text,  Attributes,  and  Attribute  Definitions),  and  bear
  1282. different  group  codes in Text and the Attributes, this defining word
  1283. allows concise declaration of where the changes  are  to  be  applied.
  1284.  
  1285.  
  1286. Interposition processing (hooks)
  1287. --------------------------------
  1288.  
  1289. A  translation program can, by defining specified words, interpose its
  1290. own code before processing of the DXF  file  commences,  supplant  the
  1291. standard loop that processes items from the file, and perform closeout
  1292. actions after processing of the file is complete.
  1293.  
  1294.   DXF:START      If DXF:START is defined, it is  executed  before  the
  1295.                  first item is read from the input file.  The INBINARY
  1296.                  and OUTPREC shared variables are  set  based  on  the
  1297.                  properties  of  the  input  file and the command line
  1298.                  arguments.  The DXF:START definition can override the
  1299.                  OUTPREC  setting at this point to, for example, force
  1300.                  an ASCII output file for input  to  AutoCAD  versions
  1301.                  prior to Release 10.
  1302.  
  1303.   DXF:TRANSLATE  If DXF:TRANSLATE is defined, it is invoked instead of
  1304.                  the standard loop that reads  items  from  the  input
  1305.                  file   and   writes  them  to  the  output  file.   A
  1306.                  DXF:TRANSLATE definition that performs the same basic
  1307.                  functions as the standard loop is as follows:
  1308.  
  1309.                    : dxf:translate
  1310.                        begin
  1311.                            readitem while
  1312.                            writeitem drop
  1313.                        repeat
  1314.                    ;
  1315.  
  1316.   DXF:END        If  DXF:END  is defined, it is called after all items
  1317.                  in the DXF file have been processed, just before  the
  1318.                  input  and  output  DXF files are closed.  If the DXF
  1319.                  translation  program  has,   for   example,   created
  1320.                  temporary  files, this is an excellent opportunity to
  1321.                  close and delete them.
  1322.  
  1323.  
  1324. Interactive operation
  1325. ---------------------
  1326.  
  1327. To ease debugging of translation programs, you can  run  DXFIX  in  an
  1328. interactive  mode  where  you're  "talking"  directly  to  the  ATLAST
  1329. interpreter.  If you specify the "-I"  switch  on  the  DXFIX  command
  1330. line,  DXFIX  will pause and display the prompt "->" after opening the
  1331. input file, running the DXF:START definition (if any), and opening the
  1332. output  file.   At  this point you can enter any primitive provided by
  1333. ATLAST or DXFIX or invoke any definition in  the  translation  program
  1334. file.   When  you  enter  an end of file character (CTRL-Z followed by
  1335. RETURN on DOS, CTRL-D on Unix), DXFIX runs the DXF:END definition  (if
  1336. any), closes the input and output files, and exits.
  1337.  
  1338.  
  1339. Summary
  1340. -------
  1341.  
  1342. DXF  files have developed a well-deserved reputation for being easy to
  1343. read but difficult to process.   DXF  has  always  permitted  one,  in
  1344. theory,  to convert all mutually representable objects between any two
  1345. versions of AutoCAD, but the reality of the  process  was  often  much
  1346. more  difficult  and  time consuming than the easily-uttered, "You can
  1347. always edit the DXF..." would lead one to suspect.
  1348.  
  1349. DXFIX meets the immediate  need  for  converting  Release  11  DXF  so
  1350. Release 10 can load it.  With little or no additional development time
  1351. over that required to write a dedicated program for that  task,  DXFIX
  1352. can,  given  proper  specifications,  perform  any  DXF translation or
  1353. modification job that can reasonably be done in a serial scan  of  the
  1354. file.   Inheriting  most  of  its generality and flexibility merely by
  1355. including   ATLAST,  DXFIX  provides  a  textbook  case  of  how  open
  1356. architecture,  programmability,  and  data  driven  organization   can
  1357. expedite  the  development  and  reduce the life cycle costs of even a
  1358. small utility with a modest  charter.   The  implementation  of  DXFIX
  1359. provides  a  worked  example  of  how  ATLAST  can  be applied to more
  1360. ambitious products and projects.
  1361.  
  1362.  
  1363. DXFIX Primitives: Alphabetical Reference
  1364. ----------------------------------------
  1365.  
  1366. ADDGROUP    gcode --        Add group to item
  1367.                             Adds  a  new  group of type "gcode" to the
  1368.                             end of the current item.
  1369.  
  1370. ARGCOUNT          -- n      Command line argument count
  1371.                             Places  the   number   of   command   line
  1372.                             arguments,  including  the zeroth argument
  1373.                             giving the command name, on the stack.
  1374.  
  1375. ARGVALUE        n -- s      Command line argument string
  1376.                             Places the address of a  temporary  string
  1377.                             buffer  "s"  containing  a copy of command
  1378.                             line argument "n" on the stack.  If "n" is
  1379.                             less than zero or greater than ARGCOUNT-1,
  1380.                             0 is returned.
  1381.  
  1382. CLEARITEM         --        Clear current item
  1383.                             All  groups  of  the  current   item   are
  1384.                             deleted.
  1385.  
  1386. DELGROUP    group --        Delete group
  1387.                             The  group  selected by "group" is deleted
  1388.                             from the current item.
  1389.  
  1390. DUMPSPECIAL       --        Dump structure name table
  1391.                             The table of structure names selected  for
  1392.                             special   processing   and   DXF   objects
  1393.                             encountered so far in the file is  printed
  1394.                             on standard output.
  1395.  
  1396. GROUP       group -- value  Group value
  1397.                             The value of the group in the current item
  1398.                             selected by "group" is placed on  the  top
  1399.                             of  the  stack.  The value is stored as an
  1400.                             integer, a floating point value, a  triple
  1401.                             of  floating point values for coordinates,
  1402.                             the address of a temporary string  buffer,
  1403.                             or  the  address  of  a  temporary  string
  1404.                             buffer with a binary chunk length  on  the
  1405.                             top  of the stack depending on the group's
  1406.                             data type.
  1407.  
  1408. GROUP?      group -- flag   Test group present
  1409.                             If the designated "group"  is  present  in
  1410.                             the  current  item -1 is placed on the top
  1411.                             of the stack.  If no such group appears in
  1412.                             the current item, 0 is returned.
  1413.  
  1414. GROUPCOUNT        -- n      Number of groups in item
  1415.                             The  number  of groups in the current item
  1416.                             is placed on the top of the  stack.   This
  1417.                             number can be used in conjunction with the
  1418.                             -(10000 + n) group specification  to  scan
  1419.                             streams  of  extended  entity  data groups
  1420.                             with identical group codes.
  1421.  
  1422. (Added for R13->R12 conversion)
  1423. GROUPCOUNT2 group -- n      Number of particular groups in item
  1424.                             The  number  of particular groups  in  the
  1425.                             current item are placed on the top of  the
  1426.                             stack.
  1427.  
  1428. ITEMPOS           -- n      Current item position
  1429.                             The location in  the  input  DXF  file  at
  1430.                             which  the current item began is placed on
  1431.                             the top of the  stack.   This  is  a  byte
  1432.                             number  if  the  input file is binary or a
  1433.                             line number if it is  ASCII.   Both  bytes
  1434.                             and lines are numbered from zero.
  1435.  
  1436. (Added for R13->R12 conversion)
  1437. ITEMPOS2    group -- n      Current item index in group
  1438.                             The zero based index at which the specified group began
  1439.                             in the current item is placed on the stack. This
  1440.                             is useful, for example, in a Spline entity to
  1441.                             determine where to start requesting the control
  1442.                             point groups (10 groups) using the -(10000 + n)
  1443.                             technique.
  1444.  
  1445. OPTION         s1 -- s2     Command line option
  1446.                             If  a  command  line  specification of the
  1447.                             form "-xspec" is present, where "x" is the
  1448.                             same  as  the  first  character  of string
  1449.                             "s1", compared without  regard  to  letter
  1450.                             case,  "s2"  is returned as a pointer to a
  1451.                             temporary  string  buffer  containing  the
  1452.                             balance  of  the option specification.  If
  1453.                             nothing follows the  option  letter,  "s2"
  1454.                             will  be  a  pointer to a null string.  If
  1455.                             the  option  selected  by  "s1"   is   not
  1456.                             present, 0 is returned.
  1457.  
  1458. PRINTGROUP   group -- file  Print group
  1459.                             The  value of the specified "group" of the
  1460.                             current item is printed on "file".
  1461.  
  1462. PRINTITEM         -- file   Print current item
  1463.                             All groups of the current item are printed
  1464.                             on "file".
  1465.  
  1466. READITEM          -- flag   Read next item
  1467.                             The  next  item from the input DXF file is
  1468.                             read and becomes the current item and  all
  1469.                             processing  specified  by  structure  name
  1470.                             definitions is performed.  If the item was
  1471.                             read  normally, -1 is placed on the top of
  1472.                             the stack; if the end of file  is  reached
  1473.                             or  an  error  is  encountered reading the
  1474.                             item, 0 is returned.
  1475.  
  1476. SETGROUP   value group --   Set group value
  1477.                             The selected "group" is set to the "value"
  1478.                             that  precedes  it on the stack.  The form
  1479.                             of the "value" depends on the group's data
  1480.                             type; see the GROUP primitive for details.
  1481.  
  1482. WRITEITEM         -- flag   Write item
  1483.                             The current item is written to the  output
  1484.                             DXF file unless marked for deletion by the
  1485.                             setting of DELITEM  and/or  DELCITEM.   If
  1486.                             the   item  was  written  successfully  or
  1487.                             deleted, -1 is placed on the stack.  If an
  1488.                             error  occurred  writing  the  item,  0 is
  1489.                             returned.  DELITEM is cleared to zero, and
  1490.                             DELCITEM  is  cleared  if the current item
  1491.                             was a Sequence End.
  1492.  
  1493. (Added for R13->R12 conversion)
  1494. SETUPSPLINE                 Set up parameters for Spline
  1495.                             Called before EVALSPLINE with the
  1496.                             stack shown below. The top stack item
  1497.                             should be 'true'.
  1498.     Kn ... K0 #knots Xm Ym Zm ... X0 Y0 Z0 Wm ... W0 #Weights Order t/f --
  1499.                             Called again after the last call to
  1500.                             EVALSPLINE with one stack item,
  1501.                             'false' to free up memory allocated
  1502.                             during spline evaluation.
  1503.  
  1504. (Added for R13->R12 conversion)
  1505. EVALSPLINE      p -- x y z  Evaluate a Spline for given parameter
  1506.                             Called repeatedly with a floating
  1507.                             point parameter 'p' which usually
  1508.                             varies from the value of the first
  1509.                             knot to the last.
  1510.  
  1511. Known Problems
  1512. --------------
  1513. Under certain memory conditions, DXFIX may freeze while transforming a
  1514. drawing that contains a polyface mesh.  If you experience this problem,
  1515. EXPLODE the mesh before creating the DXF file.  Refer to the section
  1516. earlier in this document, "Exploding polyface meshes".
  1517.  
  1518. Running out of disk space will result in a zero-lenght output
  1519. file.
  1520.  
  1521.  
  1522. AutoCAD is a registered trademark of Autodesk, Inc.
  1523. DXF, DXFIX, and ATLAST are trademarks of Autodesk, Inc.
  1524. Win95, NT, Win3.1 and DOS are registered trademarks of Microsoft Inc.
  1525.