Un-ignored: the dev drive is the ground truth the restoration and emulator work constantly reference (DPL3/LIBDPL + VRENDER i860 renderer source, BT/RP live+dev game trees, VGL_LABS pod boot, scene/audio content). Kept in-repo for the pod-owner community. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1392 lines
66 KiB
Plaintext
1392 lines
66 KiB
Plaintext
|
|
D X F I X
|
|
=========
|
|
|
|
An open, programmable application permits translation of ASCII or
|
|
binary DXF files to input compatible with any release of AutoCAD.
|
|
|
|
by John Walker
|
|
Revision 2 by Duff Kurland -- February 18, 1991
|
|
|
|
|
|
Of one power even God is deprived, and
|
|
that is the power of making what is past
|
|
never to have been.
|
|
-- Aristotle, 340 B.C.
|
|
|
|
|
|
Ever since the first incremental update to AutoCAD(R), the issue of
|
|
downward compatibility has been raised by users. Unlike many software
|
|
products, AutoCAD has always taken great pains to maintain 100% upward
|
|
compatibility from release to release--any drawing made with an
|
|
earlier release of AutoCAD can be edited with any subsequent release.
|
|
The converse, however, is not the case. Once a drawing is edited with
|
|
a given release of AutoCAD it cannot be loaded by a prior release. In
|
|
fact, prior to Release 10, DXF(tm) files written by a later version of
|
|
AutoCAD could not be loaded into an earlier version without manual
|
|
modification.
|
|
|
|
In Release 10, we introduced code in DXFIN to ignore header variables,
|
|
symbol tables, and entity fields not defined by the version of AutoCAD
|
|
loading the DXF file. While this fixes many of the problems
|
|
encountered in loading DXF written by a later release of AutoCAD,
|
|
experience has proven it inadequate; Release 10 still cannot read DXF
|
|
written by Release 11 without manual editing of the file.
|
|
|
|
This shouldn't be surprising. Solving the problem of downward
|
|
compatibility in a general way is extremely difficult since it
|
|
requires the developer, in essence, to anticipate the future direction
|
|
of product development. Further, the need to maintain downward
|
|
compatibility with products already in the field may encourage bad
|
|
design decisions in new product development, burdening those products
|
|
with inefficiencies and unneeded complexity. While it's easy to
|
|
omit entire objects that aren't recognized when loading a DXF file,
|
|
coping with the subtler differences between releases of AutoCAD such
|
|
as new bits denoting variants of Polylines, changes to text alignment,
|
|
and the like cannot be reasonably done at the DXF input level. (The
|
|
introduction of AUDIT in Release 11 will go a long way toward
|
|
detecting and discarding undefined information received from later
|
|
releases of AutoCAD. But that, of course, doesn't help users of
|
|
releases prior to 11. Further, AUDIT will never be able to translate
|
|
entities in subsequent releases into their equivalents in the release
|
|
on which it's running.)
|
|
|
|
With the end approaching for support of various venerable AutoCAD host
|
|
machines (e.g., the 8086 and 8088 in Release 11), the need arises to
|
|
allow users of those machines to load, albeit with some loss of
|
|
information, drawings made by AutoCAD Release 11 and, ideally,
|
|
releases after that. The fact that information may be lost
|
|
down-converting a drawing may not be as serious as it appears at first
|
|
glance--the user of an obsolete machine is, in all likelihood, using
|
|
it for pretty basic 2D drafting work. Having the polyface meshes and
|
|
registered application name tables purged from a drawing is unlikely
|
|
to bother such a user, particularly when the alternatives are either
|
|
not being able to edit the drawing at all or having to junk his
|
|
computer.
|
|
|
|
The most straightforward way to provide this compatibility is by
|
|
translating a DXF file written by a new release of AutoCAD into one
|
|
that can be loaded by an earlier target system. Prior to the
|
|
introduction of binary DXF in Release 10, this was a very painful
|
|
process since DXF files were huge, took forever to read and write, and
|
|
forced a tradeoff between file size and accuracy of the numbers in the
|
|
file. With binary DXF, however, nothing is lost in exporting and
|
|
transferring a drawing via DXF, and the file sizes and I/O times are
|
|
comparable to regular drawing (.dwg) files.
|
|
|
|
What we need, then, is a DXF converter program--one that reads DXF
|
|
from Release 11 and emits DXF compatible with Release 10. Ideally,
|
|
such a product should be configurable so changes made in future
|
|
releases do not require continual modification of the DXF converter.
|
|
Indeed, the converter should be *programmable*, so that it can
|
|
translate DXF from ANY release of AutoCAD into that of any other.
|
|
Best of all would be a converter that was open, programmable by the
|
|
user, one that could perform any transformation on a DXF file.
|
|
DXFIX(tm) (Drawing eXchange File Inter Xlator) is precisely such a
|
|
tool. Incorporating the FORTH-based Autodesk Threaded Language
|
|
Application System Toolkit (ATLAST (tm)), DXFIX is an open system that
|
|
can be used, without speed penalty, for the simple task of converting
|
|
DXF from Release 11 to Release 10, or programmed by anybody with
|
|
access to this documentation to perform arbitrary translation of DXF.
|
|
|
|
|
|
Running DXFIX
|
|
-------------
|
|
|
|
To convert a Release 11 DXF file to Release 10, use the command:
|
|
|
|
dxfix [options] infile outfile
|
|
|
|
where "infile" is the input DXF file name (an extension of .dxf is
|
|
assumed if no explicit extension is given), and "outfile" is the
|
|
output DXF file name (.dxf is also added to this name if no extension
|
|
is present). The input DXF file can be either binary or ASCII format;
|
|
binary format is much faster to process and maintains full accuracy of
|
|
drawing objects, but if you supply an ASCII DXF file, DXFIX will
|
|
process it without difficulty. DXFIX reads binary DXF files written
|
|
in AutoCAD portable format regardless of the system on which it is
|
|
running, and ASCII DXF with any of the end of line conventions
|
|
recognized by AutoCAD.
|
|
|
|
The "outfile" is written, by default, in binary DXF format. When
|
|
transferring data to AutoCAD Release 10, this format is preferable by
|
|
far as it is much faster to write, generally smaller, and preserves
|
|
full accuracy. If you want ASCII DXF output instead (for example, if
|
|
the DXF is intended for an AutoCAD prior to Release 10 that only
|
|
supports ASCII DXF, or is being sent to a non-Autodesk DXF processing
|
|
program that requires ASCII), specify the "-Adigits" option, where
|
|
"digits" is a number giving the precision, in decimal places, to which
|
|
numbers should be edited in the ASCII DXF file.
|
|
|
|
For example, to convert a Release 11 DXF file named "house11.dxf" to a
|
|
Release 10 DXF file named "house10.dxf" (writing "house10.dxf" in
|
|
binary format), use:
|
|
|
|
dxfix house11 house10
|
|
|
|
To perform the same translation, but generating an ASCII output file
|
|
with six decimal places of precision, use:
|
|
|
|
dxfix -a6 house11 house10
|
|
|
|
The actual translation relies on specifications given in the file
|
|
"dxfix.dxt", which is assumed to reside in the current directory.
|
|
Alternatively, you can use the "-Tname" option to specify a different
|
|
location or name for the translation specifications file. For
|
|
instance:
|
|
|
|
dxfix -a6 -t\dxfix\11_to_10 house11 house10
|
|
|
|
tells DXFIX to find its translation specifications in the file
|
|
"\dxfix\11_to_10.dxt". Note that the extension .dxt is assumed if
|
|
none is supplied.
|
|
|
|
|
|
Release 11 to 10 translations
|
|
-----------------------------
|
|
|
|
The following Release 11 to Release 10 translations are specified by
|
|
the standard "dxfix.dxt" file provided with this version of DXFIX.
|
|
|
|
Deleting new header variables
|
|
The following drawing header variables, added since Release 10, are
|
|
deleted. (The names in the DXF file are preceded by dollar signs;
|
|
we give the base names here, as they are more familiar.)
|
|
|
|
DIMCLRD Dimension line colour
|
|
DIMCLRE Dimension extension line colour
|
|
DIMCLRT Dimension text colour
|
|
DIMGAP Dimension block gap
|
|
DIMSTYLE Current dimension style
|
|
DIMTFAC Dimension text vertical position
|
|
MAXACTVP Maximum active viewports
|
|
PELEVATION Paper elevation
|
|
PEXTMAX Paper maximum extents
|
|
PEXTMIN Paper minimum extents
|
|
PINSBASE Paper insertion base
|
|
PLIMCHECK Paper limit checking
|
|
PLIMMAX Paper maximum limits
|
|
PLIMMIN Paper minimum limits
|
|
PUCSNAME Paper UCS name
|
|
PUCSORG Paper UCS origin
|
|
PUCsXDIR Paper UCS X direction
|
|
PUCSYDIR Paper UCS Y direction
|
|
SHADEDGE SHADE command edge rendering mode
|
|
SHADEDIF Shading diffuse illumination factor
|
|
TILEMODE Tiled viewports mode
|
|
UNITMODE Drawing unit mode bits
|
|
VISRETAIN Layer/viewport visibility retention
|
|
|
|
Flattening Z extents
|
|
The drawing extents, output as the $EXTMAX and $EXTMIN header
|
|
variables, contain Z extents for the first time in Release 11.
|
|
Earlier releases report an error when encountering an unexpected Z
|
|
coordinate, so the Z coordinates are removed from these variables.
|
|
|
|
Trapping zero $DIMSCALE
|
|
In Release 11, the DIMSCALE dimensioning variable can be set to zero
|
|
for paper space scaling. If a zero is detected, it is changed to
|
|
1.0.
|
|
|
|
Deleting new symbol tables
|
|
The following new symbol tables were added in Release 11. They are
|
|
deleted in their entirety from the TABLES section.
|
|
|
|
APPID - Registered application table
|
|
DIMSTYLE - Dimension style table
|
|
|
|
Handling new LAYER table flag bits
|
|
The 70 (flags) group of the LAYER table entry has a few new bits.
|
|
The "frozen by default in new viewports" bit has no meaning in
|
|
Release 10 and is zeroed. If any of the "dependent symbol" bits are
|
|
set, the entire layer entry is discarded.
|
|
|
|
Deleting new entities
|
|
All VIEWPORT entities, used by the multiple view facility of Release
|
|
11, are deleted whenever encountered in the ENTITIES or BLOCKS
|
|
section.
|
|
|
|
Deleting new entity fields
|
|
The following fields, representing features added in Release 11, are
|
|
deleted from the entities in which they appear.
|
|
|
|
BLOCK entity:
|
|
The 1 (Xref path name) and 3 (block name) groups are deleted.
|
|
In addition, all Xref-related bits of the 70 (flags) group are
|
|
zeroed. If the BLOCK was an Xref, it becomes a dummy BLOCK.
|
|
|
|
DIMENSION entity:
|
|
The 3 (dimension style), 52 (obliquing angle), and 53 (text
|
|
rotation angle) groups are deleted.
|
|
|
|
Deleting new common entity fields
|
|
The following fields, which can occur on any entity in the database,
|
|
are deleted wherever encountered.
|
|
|
|
Extended entity data:
|
|
Extended entity data (entity attributes) has group codes in the
|
|
1000 to 1100 range. All groups in that range are deleted,
|
|
stripping all extended entity data from the drawing.
|
|
|
|
Paper/model space indicator
|
|
A new common property of all entities, the paper/model space
|
|
indicator, is represented in DXF by a 67 group, where:
|
|
|
|
0 = model space
|
|
1 = paper space
|
|
|
|
All other values are reserved for future use. Since versions of
|
|
AutoCAD prior to Release 11 don't support paper space, DXFIX
|
|
deletes all entities whose 67 group is nonzero. If the 67 group
|
|
is zero, just that group is deleted.
|
|
|
|
Adjusting text vertical alignment
|
|
In Release 11, general specification of the vertical alignment of
|
|
Text, Attribute Definition, and Attribute entities was implemented.
|
|
Earlier releases provided general horizontal alignment, with one
|
|
special case providing both horizontal and vertical centering. The
|
|
new-style "MCenter" specification is translated into the
|
|
near-equivalent "MID" form accepted by versions prior to Release 11.
|
|
All other instances of vertical alignment cause the text to be reset
|
|
to left/baseline justification. In such cases, a warning message
|
|
informs the user of the loss of alignment information, and the
|
|
justification point (group 11) is deleted. In all cases, the
|
|
vertical alignment group (73 in a Text entity, 74 in an Attribute or
|
|
Attribute Definition) is deleted.
|
|
|
|
Exploding polyface meshes
|
|
In Release 11 a new variant of the Polyline entity, the polyface
|
|
mesh, was introduced. Consisting of a table of vertices and faces,
|
|
it is a far more compact representation of tiled surfaces than the
|
|
3Dface entities used prior to Release 11. However, any polyface
|
|
mesh can be represented by a collection of 3Dface, Line, and Point
|
|
entities. If the mesh is EXPLODEd prior to DXFOUT, the resulting
|
|
file can be loaded into Release 10 without difficulty. To eliminate
|
|
this requirement (and to demonstrate by a flashy but convenient tour
|
|
de force the ATLAST-derived power of DXFIX), polyface meshes present
|
|
in the DXF input file are automatically transformed into the
|
|
equivalent collection of individual entities. This is done by
|
|
saving the vertices in a temporary file, then replacing each
|
|
polyface entity with the corresponding simple entity. Invisible
|
|
edge specifications are converted from the negative-vertex form used
|
|
in polyface meshes to the invisible edge bits used in 3Dfaces. The
|
|
temporary file, "$pface.$ac", is deleted at the end of DXF file
|
|
translation.
|
|
|
|
|
|
Translation specifications
|
|
--------------------------
|
|
|
|
Most customers who use DXFIX to convert Release 11 DXF to Release 10
|
|
need know nothing more about the program than the information above:
|
|
how to run it and what information is lost in the process of
|
|
converting a drawing. DXFIX is, however, far more than a Release 11
|
|
to Release 10 DXF translator. In fact, it knows nothing about the
|
|
contents of either Release 11 or Release 10 DXF. DXFIX is actually an
|
|
ATLAST-based, general purpose, open architecture DXF translator. As
|
|
long as no fundamentally new data types are added to DXF (and the
|
|
extended entity group codes and binary chunks of Release 11 were the
|
|
first additions to the format in 5 years and 6 releases), DXFIX will
|
|
be able, given suitable specifications, to translate DXF from any
|
|
AutoCAD of the future to any AutoCAD target system of Release 2.0 or
|
|
later. (Earlier versions of AutoCAD used a totally different form of
|
|
DXF, and while DXFIX could even be made to generate that format, it
|
|
would hardly be worth the bother.)
|
|
|
|
The transformation of a DXF file by DXFIX can be controlled at several
|
|
different levels, provided by the natural layering of an ATLAST
|
|
application. Each will be discussed in turn.
|
|
|
|
|
|
Layer 0: Translation file selection
|
|
------------------------------------
|
|
|
|
The transformations performed by DXFIX are defined in a "translation
|
|
specification file", which is actually an executable ATLAST program
|
|
loaded by DXFIX to perform the translation. If no translation
|
|
specification file is named on the DXFIX command line, the default
|
|
file named "dxfix.dxt" is used. The version of "dxfix.dxt" furnished
|
|
with the initial version of DXFIX performs Release 11 to Release 10
|
|
translation. It is intended that when DXFIX is shipped with an
|
|
AutoCAD release, it will normally be accompanied with a "dxfix.dxt"
|
|
file that converts DXF from that release to the immediately prior one.
|
|
|
|
If you wish to use different translation specifications, specify the
|
|
"-Tname" switch on the DXFIX command line, where "name" is the
|
|
translation specification file name. If no extension is specified,
|
|
".dxt" is automatically appended. For example, if you had a file
|
|
named "r11_r9.dxt" that converts Release 11 DXF to input compatible
|
|
with Release 9, you could translate a DXF file called "chair11.dxf"
|
|
with the command:
|
|
|
|
dxfix -tr11_r9 chair11 chair9
|
|
|
|
Since Release 9 cannot read binary DXF, the "r11_r9.dxt" file would
|
|
automatically select ASCII output format, even though the user
|
|
specified no "-Adigits" switch on the command line. (We'll see later
|
|
how the translation specifications can control that and much, much
|
|
more.)
|
|
|
|
|
|
Layer 1: Object processing specifications
|
|
-----------------------------------------
|
|
|
|
Since much of the process of translating a DXF file consists of simply
|
|
deleting material added in later releases, much of a translation
|
|
specification file consists of statements that specify what is to be
|
|
deleted, which bits should be turned off in mask fields, and the like.
|
|
The ability to define new data types and methods in ATLAST is
|
|
exploited to make these specifications simple and readable. To
|
|
understand the bulk of the specifications in the "dxfix.dxt" file, you
|
|
must first understand the hierarchy of a DXF file and the nomenclature
|
|
DXFIX uses to designate different levels and objects in the structure.
|
|
|
|
The overall structure of a DXF file is as follows:
|
|
|
|
Sections Subsections Objects Groups
|
|
--------- ----------- ------- ------
|
|
HEADER
|
|
Variables
|
|
Groups
|
|
TABLES
|
|
LTYPE
|
|
Entries
|
|
Groups
|
|
LAYER
|
|
Entries
|
|
Groups
|
|
STYLE
|
|
Entries
|
|
Groups
|
|
...
|
|
BLOCKS
|
|
Entities
|
|
Groups
|
|
ENTITIES
|
|
Entities
|
|
Groups
|
|
EOF
|
|
|
|
Processing of different parts of this hierarchy is specified by a
|
|
"structure name" that selects the portions(s) of the hierarchy to be
|
|
processed. Each structure name begins with the characters "DXF:"
|
|
followed by the path through the hierarchy with wild-card selection
|
|
available by specifying the "*" character at various places.
|
|
|
|
To illustrate the use of structure names, we'll use the most common
|
|
declaration in a translation specification file, the "remove"
|
|
statement. All objects that match the structure name are deleted, in
|
|
their entirety, from the DXF file. Here is how "dxfix.dxt" deletes
|
|
the paper space extents header variables from Release 11 DXF.
|
|
|
|
remove dxf:header:$pextmax
|
|
remove dxf:header:$pextmin
|
|
|
|
The structure name "dxf:header:$pextmax" specifies the HEADER variable
|
|
section, object $pextmax (recall that all header variable names are
|
|
prefixed with a "$" in DXF files). When this variable is encountered
|
|
in the DXF file, its action, "remove", is executed, thereby deleting
|
|
the variable from the output file. To delete additional header
|
|
variables, just add "remove" statements naming them.
|
|
|
|
To demonstrate the generality of this approach, let's examine how the
|
|
new Release 11 DIMSTYLE (Dimension Style) table is deleted. The
|
|
specification that accomplishes this is just:
|
|
|
|
remove dxf:tables:dimstyle
|
|
|
|
Unlike the HEADER variables section, the TABLES section can contain
|
|
multiple objects in each table--in this case any number of dimension
|
|
styles. The structure name triggers, however, when it matches to the
|
|
end of the name specification, so this "remove" statement will be
|
|
executed for each entry in the DIMSTYLE table. Since each execution
|
|
has the effect of deleting the current item (and since the table start
|
|
and table end items are also matched as part of the table), this
|
|
single statement deletes the entire dimension style symbol table from
|
|
the output DXF.
|
|
|
|
As part of the multiple view plotting facility in Release 11, a new
|
|
VIEWPORT entity was added to the database. All of these entities must
|
|
be removed when converting a DXF file for use with Release 10. Since
|
|
VIEWPORT entities can appear in either the ENTITIES section or, if
|
|
part of a Block Definition, in the BLOCKS section, we can remove them
|
|
from both sections with the statements:
|
|
|
|
remove dxf:blocks:viewport
|
|
remove dxf:entities:viewport
|
|
|
|
The "remove" declaration isn't the only action we can take when a
|
|
section name is matched. The "ditchgroup" statement causes the named
|
|
group (which must be specified to the group level) to be deleted from
|
|
the current object. For example, three new groups were added to the
|
|
Dimension entity in Release 11. To remove these, we can use the
|
|
statements:
|
|
|
|
ditchgroup dxf:*:dimension:3
|
|
ditchgroup dxf:*:dimension:52
|
|
ditchgroup dxf:*:dimension:53
|
|
|
|
The first statement matches the 3 group of objects (entities) named
|
|
DIMENSION appearing in any section of the DXF file (effectively just
|
|
the BLOCKS and ENTITIES sections, since DIMENSION objects appear only
|
|
there). The action of "ditchgroup" causes the 3 group to be deleted
|
|
wherever it appears within a Dimension entity. The statements that
|
|
follow similarly delete the 52 and 53 groups.
|
|
|
|
Extended entity data (entity attributes) were introduced in Release
|
|
11. These are written to DXF files with group codes between 1000 and
|
|
1100, and must be removed when translating DXF for earlier versions of
|
|
AutoCAD. We can remove all extended entity data, wherever present in
|
|
the DXF file, with the statement:
|
|
|
|
ditchgroup dxf:*:*:1000-1100
|
|
|
|
In this case we're wild-carding both the section and the object type
|
|
and taking advantage of the ability to specify a range of group codes
|
|
to be selected. If we wanted to select the polyface vertex fields in
|
|
a Vertex entity, we could use "dxf:*:vertex:71-74".
|
|
|
|
If special processing is specified at more than one level (for
|
|
example, a given group might be selected by a global group
|
|
specification, as a group of an entity of that type, or as a member of
|
|
an object of that type), processing is done with the most specific
|
|
(group) first to the most general (item) last.
|
|
|
|
|
|
Layer 2: Translation programming
|
|
---------------------------------
|
|
|
|
What appears at first glance to be a data file that specifies the
|
|
changes to be made to a DXF file is, in actuality, an executable
|
|
ATLAST program. The program has access to all the usual ATLAST
|
|
facilities and, in addition, a set of primitives provided by DXFIX
|
|
that allow easy manipulation of objects in the DXF file. The key to
|
|
understanding how DXFIX and ATLAST work together is the structure name
|
|
specifications described in Layer 1 above. Each structure name
|
|
specification is actually an executable ATLAST definition
|
|
automatically invoked when a matching component of the DXF file is
|
|
encountered. The ability to potentially run a user-defined program
|
|
for every component of the file permits DXFIX to perform arbitrary
|
|
transformations on the DXF files it processes. The quickness with
|
|
which DXFIX can determine if special processing is requested for a
|
|
component of the DXF file (by pre-scanning the ATLAST dictionary for
|
|
the "DXF:" definitions and building a hierarchically-organized table
|
|
of processing requests, it is just a matter of a few pointer and
|
|
integer comparisons), and the inherent speed of executing precompiled
|
|
ATLAST code in an already-looked-up definition, result in DXFIX being
|
|
able to perform substantial user-specified processing while running at
|
|
essentially the same speed as a simple DXF copy program written
|
|
entirely in C.
|
|
|
|
To understand how DXFIX and ATLAST are woven together into a unified
|
|
general purpose translation tool, let's start with the DXF processing
|
|
primitives added to ATLAST by DXFIX. Many of these primitives will
|
|
rarely be used in any but the most ambitious DXF translation projects
|
|
(far more complicated than converting Release 11 to Release 10), but
|
|
they're available if you need them. Key to understanding the DXFIX
|
|
primitives is the "current item". DXFIX is always working on one item
|
|
(structure delimiter, header variable, symbol table entry, or entity)
|
|
from the DXF file at a time. This current item is implicitly
|
|
referenced by all of the item and group manipulation primitives.
|
|
|
|
|
|
Item primitives
|
|
---------------
|
|
|
|
The item primitives operate upon entire items (lists of groups forming
|
|
the fundamental objects in the DXF file).
|
|
|
|
CLEARITEM All groups of the current item are deleted. You'd only
|
|
use this if you intended to build a new item from
|
|
scratch using ADDGROUP. The stack is not affected.
|
|
|
|
ITEMPOS The position at which the current item began in the DXF
|
|
file is placed on the stack. This is the line number
|
|
of the first group of the item if the input file is
|
|
ASCII or its byte number if the input is binary. Both
|
|
lines and bytes are numbered from zero.
|
|
|
|
PRINTITEM All groups of the current item are printed on the
|
|
output file specified by the top of the stack. You can
|
|
use the predefined and automatically opened streams
|
|
STDOUT and STDERR to send output to the user. For
|
|
example, if an Arc is the current entity, the
|
|
statement:
|
|
|
|
stdout printitem
|
|
|
|
might generate the following output:
|
|
|
|
0: "ARC"
|
|
8: "0"
|
|
10: (3, 2, 0)
|
|
40: 1
|
|
50: 0
|
|
51: 90
|
|
|
|
READITEM The next item is read from the DXF file and becomes the
|
|
current item. If the item is read normally, -1 is
|
|
placed on the stack; if end of file or a read error
|
|
occurs, 0 is placed on the stack. When the item is
|
|
read, all special processing declared by structure
|
|
names that match the item and/or groups within it is
|
|
automatically performed BEFORE the item is made
|
|
available to the caller of READITEM. If the previous
|
|
current item has not been written to the output file
|
|
with WRITEITEM before READITEM is called to read the
|
|
next, it will be lost--deleted from the output file.
|
|
|
|
WRITEITEM The current item is written to the output file, unless
|
|
marked for deletion. If the item is written normally
|
|
or is to be deleted, -1 is placed on the top of the
|
|
stack. If an error occurs attempting to write the item
|
|
to the output file, 0 is returned on the stack top. If
|
|
the DELITEM (delete item) shared variable is nonzero,
|
|
the item is not written to the output file, and the
|
|
DELITEM variable is cleared to zero. If the DELCITEM
|
|
(delete complex item) shared variable is nonzero, the
|
|
item is not written to the output file and, if the item
|
|
is a Sequence End entity, the DELCITEM variable is
|
|
cleared to zero.
|
|
|
|
|
|
Group primitives
|
|
----------------
|
|
|
|
The group primitives provide access to the individual data fields that
|
|
make up an item. In the following descriptions of primitives, assume
|
|
that the current item is a Line entity on layer 0, from coordinates
|
|
(1,1,0) to (2,2,0). This item would be displayed with the sequence
|
|
"stdout printitem" as:
|
|
|
|
0: "LINE"
|
|
8: "0"
|
|
10: (1, 1, 0)
|
|
11: (2, 2, 0)
|
|
|
|
Groups within an item can be identified either by group code or by
|
|
their position within the item. Regular AutoCAD item fields are
|
|
always unique and may be identified simply by their group codes.
|
|
Extended entity data, however, uses the same group code for all fields
|
|
of a given type, so group codes are not necessarily unique. A
|
|
positive number used to designate a group chooses the first occurrence
|
|
of that group code in the current item. A negative number of the form
|
|
-(10000 + n), where "n" specifies the position of the group within the
|
|
item (with the first group numbered zero), selects the nth group in
|
|
the chain of groups composing the item and may be used to uniquely
|
|
specify extended entity groups that appear more than once in an item.
|
|
|
|
PRINTGROUP The group identified by the second item on the stack is
|
|
printed on the output stream specified by the top of
|
|
stack. For example:
|
|
|
|
-> 10 stdout printgroup
|
|
10: (1, 1, 0)
|
|
-> -10001 stdout printgroup
|
|
8: "0"
|
|
|
|
GROUPCOUNT Places the number of groups in the current item on the
|
|
top of the stack.
|
|
|
|
-> groupcount .
|
|
4
|
|
|
|
GROUP? If the group with group code given by the top of the
|
|
stack is present in the item, -1 is placed on the top
|
|
of the stack. If the group does not appear in the
|
|
item, 0 is returned.
|
|
|
|
-> 10 group? .
|
|
-1
|
|
-> 40 group? .
|
|
0
|
|
|
|
DELGROUP The group on the top of the stack is deleted from the
|
|
item, if present. If the specified group is not
|
|
present, DELGROUP is simply ignored.
|
|
|
|
-> stdout printitem
|
|
0: "LINE"
|
|
8: "0"
|
|
10: (1, 1, 0)
|
|
11: (2, 2, 0)
|
|
-> 8 delgroup
|
|
-> stdout printitem
|
|
0: "LINE"
|
|
10: (1, 1, 0)
|
|
11: (2, 2, 0)
|
|
|
|
GROUP The value of the specified group, in whatever form is
|
|
appropriate for it, is placed on the top of the stack.
|
|
Integers are stored as single stack items; real numbers
|
|
and angles as pairs of stack items representing their
|
|
floating point values; coordinates as triples of pairs,
|
|
each giving a floating coordinate with Z at the top of
|
|
the stack, Y next, and then X; strings as the address
|
|
of a temporary string buffer containing the text; and
|
|
binary chunks as a length, in bytes, on the top of the
|
|
stack and the address of the chunk data, stored in a
|
|
temporary string buffer, next on the stack.
|
|
|
|
-> 10 group f. f. f.
|
|
0 1 1
|
|
|
|
ADDGROUP A group with the type given by the top of the stack is
|
|
added to the end of the item. The value field of the
|
|
group is cleared to zero, and may be then set with
|
|
SETGROUP.
|
|
|
|
-> 62 addgroup
|
|
-> stdout printitem
|
|
0: "LINE"
|
|
10: (1, 1, 0)
|
|
11: (2, 2, 0)
|
|
62: 0
|
|
|
|
SETGROUP Sets the value of the group specified by the top of the
|
|
stack to the values below it (in the same form as the
|
|
results returned by GROUP). Removes the group
|
|
specification and the values from the stack.
|
|
|
|
-> 3 62 setgroup
|
|
-> 3.0 4.0 5.0 10 setgroup
|
|
-> stdout printitem
|
|
0: "LINE"
|
|
10: (3, 4, 5)
|
|
11: (2, 2, 0)
|
|
62: 3
|
|
|
|
|
|
Diagnostic primitives
|
|
---------------------
|
|
|
|
DUMPSPECIAL The hierarchy of the DXF file is printed, including all
|
|
items named by structure name declarations (whether
|
|
seen in the DXF file or not) and those actually
|
|
encountered in processing the input file so far. Those
|
|
items for which special processing is requested are
|
|
identified with the legend "(Special)". At the end of
|
|
the listing, wild-card specifications are listed. Here
|
|
is the output from DUMPSPECIAL after the first few
|
|
header variables of a DXF file are processed when using
|
|
the standard Release 11 to Release 10 "dxfix.dxt"
|
|
specifications.
|
|
|
|
-> readitem readitem readitem readitem
|
|
-> dumpspecial
|
|
START (Special)
|
|
HEADER
|
|
$INSBASE
|
|
$ACADVER
|
|
$DIMCLRD (Special)
|
|
$DIMCLRE (Special)
|
|
$DIMCLRT (Special)
|
|
$DIMGAP (Special)
|
|
$DIMSTYLE (Special)
|
|
$DIMTFAC (Special)
|
|
$MAXACTVP (Special)
|
|
$PELEVATION (Special)
|
|
$PEXTMAX (Special)
|
|
$PEXTMIN (Special)
|
|
$PINSBASE (Special)
|
|
$PLIMCHECK (Special)
|
|
$PLIMMAX (Special)
|
|
$PLIMMIN (Special)
|
|
$PUCSNAME (Special)
|
|
$PUCSORG (Special)
|
|
$PUCSXDIR (Special)
|
|
$PUCSYDIR (Special)
|
|
$SHADEDGE (Special)
|
|
$SHADEDIF (Special)
|
|
$TILEMODE (Special)
|
|
$UNITMODE (Special)
|
|
$VISRETAIN (Special)
|
|
$EXTMAX (Special)
|
|
$EXTMIN (Special)
|
|
$DIMSCALE (Special)
|
|
TABLES
|
|
APPID (Special)
|
|
DIMSTYLE (Special)
|
|
LAYER (Special)
|
|
ENTITIES
|
|
VIEWPORT (Special)
|
|
BLOCKS
|
|
VIEWPORT (Special)
|
|
BLOCK (Special)
|
|
END (Special)
|
|
|
|
Group range actions:
|
|
DXF:*:DIMENSION:3
|
|
DXF:*:DIMENSION:52
|
|
DXF:*:DIMENSION:53
|
|
DXF:*:*:1000-1100
|
|
DXF:*:TEXT:73
|
|
DXF:*:ATTDEF:74
|
|
DXF:*:ATTRIB:74
|
|
DXF:*:*:67
|
|
DXF:*:POLYLINE:70
|
|
DXF:*:SEQEND:*
|
|
DXF:*:VERTEX:70
|
|
|
|
|
|
Command line primitives
|
|
-----------------------
|
|
|
|
The following primitives provide access to the command line used to
|
|
invoke DXFIX. They can be used by advanced translation programs to
|
|
obtain parameters from the command line. The following primitive
|
|
descriptions assume that DXFIX has been invoked with a command line
|
|
of:
|
|
|
|
dxfix -i -v11 -y=NO dxin dxout
|
|
|
|
OPTION Tests whether a command line option letter, prefixed by
|
|
a minus sign, is present. If that option is not
|
|
specified, 0 is placed on the top of the stack. If the
|
|
option is present, a pointer to the text that follows
|
|
the option letter is placed on the top of the stack
|
|
(the pointer is guaranteed to be nonzero). Note that
|
|
if no text follows the option letter, the pointer will
|
|
still be nonzero indicating the option was specified.
|
|
The pointer will point to a null string, in that case.
|
|
|
|
-> "v" option type cr
|
|
11
|
|
-> "x" option . cr
|
|
0
|
|
-> "Y" option type cr
|
|
=NO
|
|
|
|
ARGCOUNT Places the number of command line arguments, including
|
|
the zeroth argument that gives the program name itself,
|
|
on the top of the stack.
|
|
|
|
-> argcount
|
|
6
|
|
|
|
ARGVALUE Given a number from 0 to ARGCOUNT-1 on the top of the
|
|
stack, returns a pointer to a temporary string buffer
|
|
containing a copy of that command line argument. If
|
|
the number is less than 0 or >= ARGCOUNT, 0 is placed
|
|
on the top of the stack.
|
|
|
|
-> 2 argvalue type cr
|
|
-v11
|
|
-> 6 argvalue . cr
|
|
0
|
|
-> : targs argcount 0 do i argvalue type
|
|
:> cr loop ;
|
|
-> targs
|
|
dxfix
|
|
-i
|
|
-v11
|
|
-y=NO
|
|
dxin
|
|
dxout
|
|
|
|
|
|
Shared variables
|
|
----------------
|
|
|
|
A number of shared variables serve to exchange information between
|
|
DXFIX and the ATLAST translation specification program. These
|
|
variables are all integers, and have the following meanings.
|
|
|
|
DELITEM DELITEM causes the current item to be deleted rather
|
|
than being written to the output DXF file when
|
|
WRITEITEM is invoked. You can set DELITEM from any
|
|
structure name definition to cause the item that
|
|
invoked that definition to be deleted from the output
|
|
file.
|
|
|
|
DELCITEM DELCITEM causes the current item, and all subsequent
|
|
items up to and including the next Sequence End entity
|
|
to be deleted from the output DXF file rather than
|
|
being written to it by WRITEITEM. A structure name
|
|
definition may set DELCITEM when processing the header
|
|
of a complex entity (for example, a polygon mesh, when
|
|
generating DXF for a version of AutoCAD prior to
|
|
Release 10) which should be deleted in its entirety.
|
|
|
|
INBINARY If the input file is binary, INBINARY has the value -1.
|
|
If the input file is ASCII, it's 0.
|
|
|
|
OUTPREC The OUTPREC variable specifies the mode of the output
|
|
file and, if ASCII, the precision of floating point
|
|
numbers written to it. If the output file is binary,
|
|
OUTPREC is set to -1; if this default has been
|
|
overridden with a "-Adigits" specification on the DXFIX
|
|
command line, OUTPREC will be set to "digits". If the
|
|
value of OUTPREC is set by a DXF:START definition in
|
|
the translation program, the value specified will
|
|
override the default or the value from the command
|
|
line.
|
|
|
|
DUMPINPUT If DUMPINPUT is nonzero, each item read from the input
|
|
DXF file will be dumped to standard output.
|
|
|
|
DUMPOUTPUT If DUMPOUTPUT is nonzero, each item written to the
|
|
output DXF file will be dumped to standard output.
|
|
|
|
SPECIALDONE When an item matches multiple structure name
|
|
definitions, each is normally executed in sequence. If
|
|
a structure name definition performs an action that by
|
|
its very nature completes the processing of the item
|
|
(for example, setting DELITEM to delete it from the
|
|
output file), it may set SPECIALDONE. Once this
|
|
variable is set nonzero by a structure name definition,
|
|
no other structure name definition triggered by the
|
|
item will be processed. This is particularly handy
|
|
when you wish processing of a certain group of an
|
|
entity to replace the default handling of entities with
|
|
that group missing.
|
|
|
|
DXFTRACE If the translation program sets DXFTRACE nonzero, all
|
|
invocations of structure name definitions are printed
|
|
on standard output. Here is the output generated by
|
|
translation of a Release 11 DXF file with DXFTRACE set
|
|
to 1.
|
|
|
|
Invoking DXF:START
|
|
Invoking DXF:HEADER:$EXTMIN
|
|
Invoking DXF:HEADER:$EXTMAX
|
|
Invoking DXF:HEADER:$DIMSCALE
|
|
Invoking DXF:HEADER:$DIMSTYLE
|
|
Invoking DXF:HEADER:$DIMCLRD
|
|
Invoking DXF:HEADER:$DIMCLRE
|
|
Invoking DXF:HEADER:$DIMCLRT
|
|
Invoking DXF:HEADER:$DIMTFAC
|
|
Invoking DXF:HEADER:$DIMGAP
|
|
Invoking DXF:HEADER:$PELEVATION
|
|
Invoking DXF:HEADER:$PUCSNAME
|
|
Invoking DXF:HEADER:$PUCSORG
|
|
Invoking DXF:HEADER:$PUCSXDIR
|
|
Invoking DXF:HEADER:$PUCSYDIR
|
|
Invoking DXF:HEADER:$SHADEDGE
|
|
Invoking DXF:HEADER:$SHADEDIF
|
|
Invoking DXF:HEADER:$TILEMODE
|
|
Invoking DXF:HEADER:$MAXACTVP
|
|
Invoking DXF:HEADER:$PINSBASE
|
|
Invoking DXF:HEADER:$PLIMCHECK
|
|
Invoking DXF:HEADER:$PEXTMIN
|
|
Invoking DXF:HEADER:$PEXTMAX
|
|
Invoking DXF:HEADER:$PLIMMIN
|
|
Invoking DXF:HEADER:$PLIMMAX
|
|
Invoking DXF:HEADER:$UNITMODE
|
|
Invoking DXF:HEADER:$VISRETAIN
|
|
Invoking DXF:TABLES:LAYER
|
|
Invoking DXF:TABLES:LAYER
|
|
Invoking DXF:TABLES:LAYER
|
|
Invoking DXF:TABLES:APPID
|
|
Invoking DXF:TABLES:APPID
|
|
Invoking DXF:TABLES:APPID
|
|
Invoking DXF:TABLES:DIMSTYLE
|
|
Invoking DXF:TABLES:DIMSTYLE
|
|
Invoking DXF:TABLES:DIMSTYLE
|
|
Invoking DXF:BLOCKS:BLOCK
|
|
Invoking DXF:BLOCKS:BLOCK
|
|
Invoking DXF:*:SEQEND
|
|
Invoking DXF:BLOCKS:BLOCK
|
|
Invoking DXF:BLOCKS:BLOCK
|
|
Invoking DXF:*:TEXT:73
|
|
Invoking DXF:*:DIMENSION:3
|
|
Invoking DXF:*:POLYLINE:70
|
|
Invoking DXF:*:SEQEND
|
|
Invoking DXF:*:SEQEND
|
|
Invoking DXF:BLOCKS:BLOCK
|
|
Invoking DXF:BLOCKS:BLOCK
|
|
Invoking DXF:*:TEXT:73
|
|
Invoking DXF:*:*:1000-1100
|
|
Invoking DXF:*:*:1000-1100
|
|
Invoking DXF:*:*:1000-1100
|
|
Invoking DXF:*:*:1000-1100
|
|
Invoking DXF:*:*:67
|
|
Invoking DXF:ENTITIES:VIEWPORT
|
|
Invoking DXF:END
|
|
|
|
|
|
Missing Z coordinates
|
|
---------------------
|
|
|
|
Some versions of DXF files contain two dimensional as well as three
|
|
dimensional points. Unfortunately, these objects are distinguished
|
|
only by the absence or presence, respectively, of a 3x group in the
|
|
DXF file. They cannot be told apart by group code alone once
|
|
assembled into composite structures with group codes from 10 to 19.
|
|
To allow translation programs to determine whether a Z coordinate was
|
|
supplied in input and to control whether a Z coordinate is written
|
|
when a point group is output, a special floating point variable named
|
|
MISSING_Z is defined. The variable has a value of -1*(10^308), which
|
|
should never occur in a valid AutoCAD database. If the Z coordinate
|
|
of a point group tests equal to MISSING_Z, no Z coordinate was present
|
|
in the DXF input file. If you set the Z coordinate of a point group
|
|
to MISSING_Z, only X and Y coordinates will be written for that point
|
|
when it is output. See the definition of DROP_Z in "dxfix.dxt" for an
|
|
example of MISSING_Z being used to discard an unwanted Z coordinate.
|
|
|
|
|
|
Structure name execution
|
|
------------------------
|
|
|
|
As each item is read from the input DXF file, DXFIX matches it against
|
|
the structure words (such as DXF:ENTITIES:LINE) defined in the
|
|
translation program. When a match occurs, that definition is
|
|
executed, allowing it to perform whatever operations it wishes upon
|
|
the current item. Two kinds of structure names can be specified. The
|
|
first contains no wild cards or group number and is triggered by an
|
|
entire item in the input; it will be executed only once per item. The
|
|
second form of structure name does contain wild cards and/or a group
|
|
number or range of group numbers. This form of structure name is
|
|
triggered at the individual group level; note that a structure name
|
|
with a wild card and no group range is triggered for EVERY group in
|
|
the item (if you don't want this to happen, simply specify a group
|
|
code known to appear only once in the item, or set SPECIALDONE to
|
|
avert further processing of structure names for the item). The two
|
|
forms of structure names are executed in different ways as well. The
|
|
following examples should make the distinctions clear.
|
|
|
|
|
|
Item level structure names
|
|
--------------------------
|
|
|
|
Examples of item level structure names are DXF:HEADER:$EXTMIN,
|
|
DXF:TABLES:APPID, and DXF:ENTITIES:VERTEX. Each of these denotes a
|
|
definition triggered when an object with that sequence of names
|
|
appears in the DXF hierarchy. The test for the presence of an item
|
|
level structure name is extremely fast, as DXFIX knows at all times
|
|
where it is in the hierarchy and does not need to search a list of
|
|
definitions.
|
|
|
|
When an item just read from the input file triggers a structure name,
|
|
the definition for that name is run. Nothing is placed on the stack
|
|
before executing the definition, and the definition should leave no
|
|
result on the stack. Since the definition can examine and manipulate
|
|
the current item with the primitives provided for that purpose,
|
|
there's no need to pass data on the stack.
|
|
|
|
Suppose we want to delete the UNITMODE header variable. This can be
|
|
accomplished with the following definition:
|
|
|
|
: dxf:header:$unitmode
|
|
1 delitem !
|
|
;
|
|
|
|
Now when the $UNITMODE item is encountered in the HEADER section, this
|
|
definition will be run. It stores 1 into the shared variable DELITEM,
|
|
which causes DXFIX not to emit the item to the output file,
|
|
accomplishing the objective of the definition.
|
|
|
|
Another example of an item level structure name is provided by this
|
|
definition that deletes the Xref information from Release 11 block
|
|
definitions:
|
|
|
|
: dxf:blocks:block
|
|
70 group? if
|
|
70 group 3 and 70 setgroup
|
|
then
|
|
1 delgroup
|
|
3 delgroup
|
|
;
|
|
|
|
When triggered by each BLOCK entity in the BLOCKS section (the only
|
|
place they appear), this definition obtains its 70 group flags, clears
|
|
the Xref bits if set, and stores the revised flags using SETGROUP. It
|
|
then uses DELGROUP twice to delete any 1 and 3 Xref groups present in
|
|
the BLOCK entity. Since DELGROUP does nothing if the group is absent,
|
|
the definition need not use GROUP? to test whether those groups
|
|
exist.
|
|
|
|
|
|
Group level structure names
|
|
---------------------------
|
|
|
|
Group level structure names contain wild card specifications, group
|
|
numbers or ranges, or both. Group level structure names are matched
|
|
and executed at the group level, and are passed the group code that
|
|
triggered them on the stack when invoked. Examples of group level
|
|
structure names are DXF:*:*:1000-1100 which is triggered by any group
|
|
with a code between 1000 and 1100, wherever found in the input file;
|
|
DXF:TABLES:STYLE:70, executed for the 70 group of each entry in the
|
|
STYLE table of the TABLES section; and DXF:*:TEXT:73, activated
|
|
whenever a 73 group is encountered in a TEXT item anywhere in the file
|
|
(of course, TEXT items appear only in the BLOCKS and ENTITIES
|
|
sections).
|
|
|
|
Checking for the presence of a group level structure definition is
|
|
somewhat less efficient than determining if an item level definition
|
|
exists. You should use group level names only when you need the wild
|
|
card selection and group identification they provide.
|
|
|
|
In translating Release 11 DXF to Release 10, we want to delete all 52
|
|
groups from Dimension entities. These entities can appear in either
|
|
the BLOCKS or the ENTITIES section. We can accomplish this with:
|
|
|
|
: dxf:*:dimension:52
|
|
delgroup
|
|
;
|
|
|
|
Since this is a group level structure name definition, the group code
|
|
that invoked it (in this case 52) is placed on the top of the stack
|
|
before our definition is executed. Knowing it's there, we need only
|
|
execute DELGROUP to remove the group from all DIMENSION items.
|
|
|
|
Actually, we want to get rid of both 52 and 53 groups in Dimension
|
|
entities. This requires only our specifying the range of groups:
|
|
|
|
: dxf:*:dimension:52-53
|
|
delgroup
|
|
;
|
|
|
|
Again, since the group code that triggered the structure name is
|
|
placed on the stack, the definition does not need to "know" what group
|
|
caused it to be run.
|
|
|
|
An extreme example of a group range is provided by a definition that
|
|
removes all extended entity data from a DXF file.
|
|
|
|
: dxf:*:*:1000-1100
|
|
delgroup
|
|
;
|
|
|
|
Here we delete all groups between 1000 and 1100 in any section of the
|
|
file. (We should only find such groups in the BLOCKS and ENTITIES
|
|
section, but no harm is done by this more general specification.)
|
|
|
|
We can do anything we like with groups, not just delete them. Suppose
|
|
we wished to guarantee that the 4 bit was never set in the 70 group of
|
|
a Vertex entity (it's never supposed to be set anyway, but what the
|
|
heck). The following definition will clear any erroneously set 4
|
|
bits.
|
|
|
|
: dxf:*:VERTEX:70
|
|
group 4 not and
|
|
70 setgroup
|
|
;
|
|
|
|
When this definition is activated, we use the group code on the stack
|
|
to obtain the current value of the field. We then push the constant 4
|
|
for the bit we wish to clear and use NOT to complement its bits. AND
|
|
gives us the value with the 4 bit guaranteed to be off. We then push
|
|
the group code of 70 (we could have copied the version on the stack
|
|
originally, but since this definition is only executed for 70 groups,
|
|
using the constant is simpler and faster) and use SETGROUP to store
|
|
the masked value back into the group.
|
|
|
|
The only limits on the amount of processing you can do when triggered
|
|
by a group are your ambition in writing code and your patience waiting
|
|
for it to execute. Take a gander at the definition of DXF:*:VERTEX:70
|
|
actually used in "dxfix.dxt" to translate polyface meshes into simple
|
|
entities for an idea of where the deep end begins.
|
|
|
|
|
|
Layer 3: Structure defining words
|
|
---------------------------------
|
|
|
|
"But hey!", you say, "Those definitions you just showed me don't look
|
|
anything like the 'remove' and 'ditchgroup' statements you told me
|
|
about that are used in 'dxfix.dxt.'"
|
|
|
|
Right you are. In "dxfix.dxt" we took advantage of one of the most
|
|
powerful aspects of ATLAST to make the translation specifications
|
|
compact, readable, and efficient. ATLAST allows you to create
|
|
"defining words" which can subsequently be used to declare new data
|
|
types complete with method code to be executed when the data type is
|
|
referenced. If the motive of ATLAST is "every product programmable",
|
|
its means are "every token executable". When you say "2 3 +" in an
|
|
ATLAST program, you're EXECUTING the literal 2 (in the implementation
|
|
as well as conceptually), which has the effect of placing 2 on the
|
|
stack. You next EXECUTE the literal 3, placing it on top of the 2
|
|
already there. Finally, you EXECUTE the primitive "+", which adds the
|
|
two numbers and leaves their sum, 5, on the stack.
|
|
|
|
Not only can you add definitions which are executed just like system
|
|
primitives, you can also define new data types by creating definitions
|
|
called "defining words" that allocate and initialize storage and
|
|
specify a runtime method. I took advantage of this facility to create
|
|
the REMOVE statement, defined as follows:
|
|
|
|
: remove
|
|
create
|
|
does>
|
|
drop
|
|
1 delitem !
|
|
;
|
|
|
|
When you specify:
|
|
|
|
remove dxf:entities:viewport
|
|
|
|
you are actually EXECUTING the definition of REMOVE. This definition
|
|
performs a CREATE, which causes the next token to be defined an a new,
|
|
executable definition. Following the CREATE one can allocate and
|
|
initialize storage for the definition (what are called "instance
|
|
variables" in object-land). This definition requires no data, so
|
|
CREATE is followed immediately by DOES>, which introduces the method
|
|
to be executed when the new definition is itself executed. Whenever a
|
|
definition made with CREATE is executed, the address of its storage
|
|
area (instance variables) is passed to it on the stack--how can you
|
|
know what you need to do if you don't know who you are? Since our
|
|
definition doesn't need this address, we discard it with DROP. That
|
|
taken care of, we need only set DELITEM to 1, thereby deleting the
|
|
current item, and we're done. Recall that REMOVE is declaring a new
|
|
EXECUTABLE word. When we use it to declare a DXF structure name,
|
|
we're automatically registering the processing defined by its method
|
|
to be done whenever that word is triggered. Thus the user can simply
|
|
write "remove statements", oblivious of the underlying mechanism.
|
|
|
|
We can exploit instance variables to create more sophisticated
|
|
defining words. Here is a definition that allows us to AND arbitrary
|
|
groups in a DXF file with any mask we wish:
|
|
|
|
: maskfield
|
|
create ( Define Data Type: )
|
|
, ( Compile bitmask )
|
|
does> ( Runtime Method: )
|
|
over ( Duplicate group index )
|
|
group ( Extract value of group )
|
|
swap ( Bitmask address to top )
|
|
@ ( Get value of bitmask )
|
|
and ( Mask value of field )
|
|
swap ( Get group code on top )
|
|
setgroup ( Update group in item )
|
|
;
|
|
|
|
We can use this definition to clear the 4 bits in Vertex entities,
|
|
rather than the less readable explicit definition we used before:
|
|
|
|
4 not maskfield dxf:*:vertex:70
|
|
|
|
When this is executed we push 4 on the stack, invert its bits to get
|
|
our AND mask, and then execute MASKFIELD. It performs a CREATE to
|
|
define the following token (in this case our structure name), and uses
|
|
the comma primitive to remove the value from the top of the stack (the
|
|
AND mask) and store it in the next instance variable field of the word
|
|
we're defining.
|
|
|
|
When DXFIX encounters a 70 group in a Vertex entity in the input file,
|
|
it will push the group code, 70, then execute DXF:*:VERTEX:70. The
|
|
definition pushes its instance variable address and runs the method
|
|
that follows the DOES> in the definition. That method, in turn, grabs
|
|
the group index from the second item on the stack (OVER), gets its
|
|
current value (GROUP), moves the instance variable address, where the
|
|
mask used by this word has been stored to the top of the stack (SWAP),
|
|
loads the mask from that location (@), logically ANDs the mask with
|
|
the value from the group, moves the group code to the top (SWAP), and
|
|
updates the group in the current item (SETGROUP).
|
|
|
|
Once a defining word like this has been created, the user can use it
|
|
to simply list the masks and field names to which they should be
|
|
applied without thinking about how it's all really working.
|
|
|
|
You can create defining words with arbitrarily complicated methods.
|
|
An example is the definition of TEXTVADJ in "dxfix.dxt", which
|
|
declares the special processing of Release 11 text vertical alignment
|
|
groups. Since these groups appear in three different kinds of
|
|
entities (Text, Attributes, and Attribute Definitions), and bear
|
|
different group codes in Text and the Attributes, this defining word
|
|
allows concise declaration of where the changes are to be applied.
|
|
|
|
|
|
Interposition processing (hooks)
|
|
--------------------------------
|
|
|
|
A translation program can, by defining specified words, interpose its
|
|
own code before processing of the DXF file commences, supplant the
|
|
standard loop that processes items from the file, and perform closeout
|
|
actions after processing of the file is complete.
|
|
|
|
DXF:START If DXF:START is defined, it is executed before the
|
|
first item is read from the input file. The INBINARY
|
|
and OUTPREC shared variables are set based on the
|
|
properties of the input file and the command line
|
|
arguments. The DXF:START definition can override the
|
|
OUTPREC setting at this point to, for example, force
|
|
an ASCII output file for input to AutoCAD versions
|
|
prior to Release 10.
|
|
|
|
DXF:TRANSLATE If DXF:TRANSLATE is defined, it is invoked instead of
|
|
the standard loop that reads items from the input
|
|
file and writes them to the output file. A
|
|
DXF:TRANSLATE definition that performs the same basic
|
|
functions as the standard loop is as follows:
|
|
|
|
: dxf:translate
|
|
begin
|
|
readitem while
|
|
writeitem drop
|
|
repeat
|
|
;
|
|
|
|
DXF:END If DXF:END is defined, it is called after all items
|
|
in the DXF file have been processed, just before the
|
|
input and output DXF files are closed. If the DXF
|
|
translation program has, for example, created
|
|
temporary files, this is an excellent opportunity to
|
|
close and delete them.
|
|
|
|
|
|
Interactive operation
|
|
---------------------
|
|
|
|
To ease debugging of translation programs, you can run DXFIX in an
|
|
interactive mode where you're "talking" directly to the ATLAST
|
|
interpreter. If you specify the "-I" switch on the DXFIX command
|
|
line, DXFIX will pause and display the prompt "->" after opening the
|
|
input file, running the DXF:START definition (if any), and opening the
|
|
output file. At this point you can enter any primitive provided by
|
|
ATLAST or DXFIX or invoke any definition in the translation program
|
|
file. When you enter an end of file character (CTRL-Z followed by
|
|
RETURN on DOS, CTRL-D on Unix), DXFIX runs the DXF:END definition (if
|
|
any), closes the input and output files, and exits.
|
|
|
|
|
|
Summary
|
|
-------
|
|
|
|
DXF files have developed a well-deserved reputation for being easy to
|
|
read but difficult to process. DXF has always permitted one, in
|
|
theory, to convert all mutually representable objects between any two
|
|
versions of AutoCAD, but the reality of the process was often much
|
|
more difficult and time consuming than the easily-uttered, "You can
|
|
always edit the DXF..." would lead one to suspect.
|
|
|
|
DXFIX meets the immediate need for converting Release 11 DXF so
|
|
Release 10 can load it. With little or no additional development time
|
|
over that required to write a dedicated program for that task, DXFIX
|
|
can, given proper specifications, perform any DXF translation or
|
|
modification job that can reasonably be done in a serial scan of the
|
|
file. Inheriting most of its generality and flexibility merely by
|
|
including ATLAST, DXFIX provides a textbook case of how open
|
|
architecture, programmability, and data driven organization can
|
|
expedite the development and reduce the life cycle costs of even a
|
|
small utility with a modest charter. The implementation of DXFIX
|
|
provides a worked example of how ATLAST can be applied to more
|
|
ambitious products and projects.
|
|
|
|
|
|
DXFIX Primitives: Alphabetical Reference
|
|
----------------------------------------
|
|
|
|
ADDGROUP gcode -- Add group to item
|
|
Adds a new group of type "gcode" to the
|
|
end of the current item.
|
|
|
|
ARGCOUNT -- n Command line argument count
|
|
Places the number of command line
|
|
arguments, including the zeroth argument
|
|
giving the command name, on the stack.
|
|
|
|
ARGVALUE n -- s Command line argument string
|
|
Places the address of a temporary string
|
|
buffer "s" containing a copy of command
|
|
line argument "n" on the stack. If "n" is
|
|
less than zero or greater than ARGCOUNT-1,
|
|
0 is returned.
|
|
|
|
CLEARITEM -- Clear current item
|
|
All groups of the current item are
|
|
deleted.
|
|
|
|
DELGROUP group -- Delete group
|
|
The group selected by "group" is deleted
|
|
from the current item.
|
|
|
|
DUMPSPECIAL -- Dump structure name table
|
|
The table of structure names selected for
|
|
special processing and DXF objects
|
|
encountered so far in the file is printed
|
|
on standard output.
|
|
|
|
GROUP group -- value Group value
|
|
The value of the group in the current item
|
|
selected by "group" is placed on the top
|
|
of the stack. The value is stored as an
|
|
integer, a floating point value, a triple
|
|
of floating point values for coordinates,
|
|
the address of a temporary string buffer,
|
|
or the address of a temporary string
|
|
buffer with a binary chunk length on the
|
|
top of the stack depending on the group's
|
|
data type.
|
|
|
|
GROUP? group -- flag Test group present
|
|
If the designated "group" is present in
|
|
the current item -1 is placed on the top
|
|
of the stack. If no such group appears in
|
|
the current item, 0 is returned.
|
|
|
|
GROUPCOUNT -- n Number of groups in item
|
|
The number of groups in the current item
|
|
is placed on the top of the stack. This
|
|
number can be used in conjunction with the
|
|
-(10000 + n) group specification to scan
|
|
streams of extended entity data groups
|
|
with identical group codes.
|
|
|
|
ITEMPOS -- n Current item position
|
|
The location in the input DXF file at
|
|
which the current item began is placed on
|
|
the top of the stack. This is a byte
|
|
number if the input file is binary or a
|
|
line number if it is ASCII. Both bytes
|
|
and lines are numbered from zero.
|
|
|
|
OPTION s1 -- s2 Command line option
|
|
If a command line specification of the
|
|
form "-xspec" is present, where "x" is the
|
|
same as the first character of string
|
|
"s1", compared without regard to letter
|
|
case, "s2" is returned as a pointer to a
|
|
temporary string buffer containing the
|
|
balance of the option specification. If
|
|
nothing follows the option letter, "s2"
|
|
will be a pointer to a null string. If
|
|
the option selected by "s1" is not
|
|
present, 0 is returned.
|
|
|
|
PRINTGROUP group -- file Print group
|
|
The value of the specified "group" of the
|
|
current item is printed on "file".
|
|
|
|
PRINTITEM -- file Print current item
|
|
All groups of the current item are printed
|
|
on "file".
|
|
|
|
READITEM -- flag Read next item
|
|
The next item from the input DXF file is
|
|
read and becomes the current item and all
|
|
processing specified by structure name
|
|
definitions is performed. If the item was
|
|
read normally, -1 is placed on the top of
|
|
the stack; if the end of file is reached
|
|
or an error is encountered reading the
|
|
item, 0 is returned.
|
|
|
|
SETGROUP value group -- Set group value
|
|
The selected "group" is set to the "value"
|
|
that precedes it on the stack. The form
|
|
of the "value" depends on the group's data
|
|
type; see the GROUP primitive for details.
|
|
|
|
WRITEITEM -- flag Write item
|
|
The current item is written to the output
|
|
DXF file unless marked for deletion by the
|
|
setting of DELITEM and/or DELCITEM. If
|
|
the item was written successfully or
|
|
deleted, -1 is placed on the stack. If an
|
|
error occurred writing the item, 0 is
|
|
returned. DELITEM is cleared to zero, and
|
|
DELCITEM is cleared if the current item
|
|
was a Sequence End.
|
|
|
|
Known Problems
|
|
--------------
|
|
Under certain memory conditions, DXFIX may freeze while transforming a
|
|
drawing that contains a polyface mesh. If you experience this problem,
|
|
EXPLODE the mesh before creating the DXF file. Refer to the section
|
|
earlier in this document, "Exploding polyface meshes".
|
|
|
|
|
|
AutoCAD is a registered trademark of Autodesk, Inc.
|
|
DXF, DXFIX, and ATLAST are trademarks of Autodesk, Inc.
|