"Man's mind, once stretched by a new idea, never regains its original dimensions." Oliver Wendell Holmes
Geography Division
U. S. Census Bureau
Washington, D. C.
Map Image Metafile and MIM are Trademarks of the U.S. Department of Commerce, Bureau of the Census
Contents
Purpose and Applicability of Document
The purpose of this document is to provide a complete and concise description of the Map Image Metafile (MIM) language for describing in a device independent manner the components and relationships within a map image. The definitions, syntax, and structure of this language are used in most Census Bureau Geography division mapping projects requiring a standard, device independent means for creating, exchanging, and/or producing map images.
Change Overview
This version of the MIM language specification differs from the previous version in the following ways.
The maps allow the users of census data to visually relate the statistics to the geographic areas for which they were gathered. Other than for administrative type maps used during census operations, the maps that the public receive and use most are of two kinds, reference maps and statistical (thematic) maps. The former show the types, extent and spatial relationship of the political and statistical areas represented in the census while the latter generally depict one geographic level and one data variable such as percent of population graduating from high school. In general, the maps of use to people studying census data from a current or past census are the reference and statistical maps and not the operational maps.
The excellent quality of the printed map, both in image sharpness and paper stock, inexpensively provided the public with readily available and flexible research tools. Because of the high contrast and sharpness of the printed images, the maps were easy to duplicate either photographically or, in the past few decades, xerographically. The durability of the paper made them useful both as working bases and as archived documents for historical studies.
Present
The advent of the age of automated map production at the Census Bureau has changed things dramatically. The number of map sheets produced has increased ten-fold or more. Part of this has come about because of the change in the number of geographic units delimited for the country, e.g., block numbered maps are public products and now the whole country is block numbered and grouped into Census Tracts or Block Numbering Areas. Another reason is that more map types were produced as products than have been produced in previous censuses, e.g., metropolitan map series maps. In some instances, special maps were made for an operational task that in past censuses would have been handled by making another map do double duty. All this has added up to many maps , e.g., over 70,000 different sheets for just a single map type, and virtually every map was produced through automated means. For the 1990 Census of Population and Housing, over 2,000,000 maps were produced.
Plans were made to provide the public after 1990 with maps of types similar to those provided in the past. The shear volume, however, presented special problems to individuals, companies, other government agencies, academic institutions and libraries. They were not prepared to receive, store, and manage such a large number of map sheets, much less pay for them from limited budgets. Further complicating the situation was the fact that, except for less than 7,000 printed maps, all the maps were to be plotted at time of purchase. This could potentially restrict the flow volume to users. Finally, the somewhat lower quality of paper of the plotted maps verses printed maps affected wear and tear, marketability on the image, and archival quality. The contrast and sharpness of the plotted maps are difficult to reproduce by any means, even large format copying or re-plotting.
An early recommendation was to copy the plot tape and make these available to the public so they could make as many copies as desired. However, the plot files were produced in a format for a specific set of hardware. Therefore, in order for anyone to make as many copies of the maps as they wished, they had to pay for the cost of this type of plotter (over $25,000 in 1988) and the costs of the plot files on tape. Even providing the plot files on CD-ROM only reduced the volume of things to be handled, not the complexity of generating or viewing a map image. To overcome the limitation of having to have a specific type of plotter, some work was done by commercial firms to produce interpreter software so the plot tapes could be read and output to other display devices and plotters. Though promising, this still required a special step for each map plotted.
How to make the maps as readily available as in past censuses is only one of the problems caused by automated mapping. Another is that the programs that generate the map images (plot files) cannot account for all the variations and special conditions that occur in a map. Text placement, with or without overlap, position of a north- arrow within image area for different shapes of geography, removing or editing features that were erroneously coded in the TIGER/File are examples of tasks that cannot presently be economically and efficiently performed by batch (non-interactive) mapping programs. This type of task must be performed interactively. Therefore, some way had to be found to not only generate the map image, but to be able to edit and manipulate the image components.
Further compounding problems with the map generation process was an almost total lack of stability in the production environment. The main computer used for TIGER processing changed three times, thereby affecting the extraction of cartographic data from the TIGER/Files. The plot file generation software has had to be developed in four different environments. Finally, the programming, interactive editing, and plotting capabilities have continued to expand with concomitant needs for adjustments to the programs and procedures.
The situation begged for a simple and easy-to-implement solution. A solution that would allow a map image to be generated wherever and in whatever computer environment is available at the time, and then be edited, manipulated, and plotted wherever and in whatever hardware and software environment is available for those tasks. The answer was determined to be a simple image transfer format that would not suffer under hardware limitations such as how bits are stored by different machines and so forth. Some form of meta map image file was clearly needed. The map image metafile (MIM) was designed as the simplest and quickest way to provide the needed transfer format.
Future
Given that the map production environment in terms of hardware, software and operating procedures will continue to change, and that the MIM is a feasible solution to the problems caused by this change, there is yet another major problem: How to store map images for future reproduction and use.
As the years go by, two groups of people will need to be able to reproduce the census maps, the Census Bureau itself and the public. For a few years after creating the plot, the plot files can be used to re-plot maps as needed. However, aside from the very real possibility that the plot files may become unreadable, at some point in time, the plotters that read these tapes will have to be replaced. Storing the map images as hardware specific plot files and forcing an ever burdensome backwards compatibility on new plotters is neither desirable nor realistically possible in the long term.
One possible solution was the simple capture of the map image as a bit-image at the scale of map creation. While this was well within the technology of the day with all the image capture and manipulating systems available, this was unsatisfactory for several reasons. First, most of the maps were generated at a resolution of 200 dots per inch (dpi) and would require a plotter of that resolution to reproduce them. If a higher resolution plotter is used, either special software would have to translate the bit-image back to the original size or the plot would be changed proportionally. For example, a 200 dots per inch (dpi) census map reproduced without conversion on a 1,000 dpi plotter would make a map 1/5th the original size. Likewise, displaying the bit-image on the screen of a graphics terminal would severely limit the amount of the map visible since most screens today cannot display more than about 1,000 by 1,000 dots, if that much! This means that, at best, only about 5 inches of a map can be seen at a time of a map that may be 24 by 30 inches or larger. Further, a bit-image has no intelligence to allow for selected display of say boundaries without text, or county boundaries in red, all others in green though the map may be monochromatic. Finally, a decompressed bit-image file of a 24 by 30, 200 dpi map would take 28,800,000 million bits or 3,600,000 bytes. Compressing the file means that if the information on how to decompress becomes separated from the file or lost, the map could only be retrieved with great difficulty, if at all. Bit-images were discarded because they clearly were not a feasible solution.
Other storage forms were investigated, including, but not limited to the American National Standard computer graphics metafile (CGM) for the storage and transfer of picture description information. This is a powerful and clear standard in which many valuable ideas were found. However, the CGM standard, as well as the several other standards investigated, suffer from the same difficulty of use. They all produce a file that is very close to hardware levels of image data representation and their format and form require knowledge of some external facts to read the file. This was considered a serious shortcoming when viewed from a future position. Further, most of the storage forms limited the non-graphic information content of the file, thereby restricting flexibility. This is not to say that they could not have been forced to perform the task envisioned for census map image storage, retrieval, manipulation, and reproduction. Rather, desired was a simple, straight-forward file structure for the 1990 census maps; a structure that would serve census needs and the public (all other users) in the near future and for decades to come.
It is difficult, if not impossible to predict what will be the future uses of census maps. If the past is any indication, the users will need ready access to the maps and a relatively easy way for manipulating the images to show not only census data on them, but their data as well. Past maps were fully comprehensible, free standing documents of great use; digital files of map images should be no less.
The underlying MIM content and structure are based upon the map description concepts found in COOL. The map is considered to be an object that can be described in terms of other cartographic objects such as legends, north arrows, etc. These in turn can be described in terms of other cartographic objects or cartographic primitives such as text, lines, and areas; each with it's own attributes.
The two characteristics of a MIM, it's object nature and flat ASCII format, provide significant improvements over a regular plot file. The flat file format removes the need to interpret hardware codes while the object structure allows for showing relationships between graphic elements. This is very powerful because whole portions of a map image may be 1) readily identified within the file and 2) treated as a single unit when interactively manipulating the image. Neither of these are generally true of ordinary plot files.
Certainly such an object type capability could be incorporated into the map image generation software. This, however, would require that the whole map image be generated, manipulated for edit and/or design needs and output to a plot file in one step. The amount of computer resources (time, storage, communications, and so forth) needed to accomplish this in one step from the TIGER files is currently beyond the Bureau's capabilities, and likely to be for some time.
MIMs serve as the exchange format between the various operational steps. The production of a map is generally a multi-phased operation. This is particularly true of a publication map. As stated earlier, all the operations do not necessarily take place on one computer or even in one operating environment. MIMs were designed to be a simple but complete exchange format between the operations.
Finally, MIMs provide a simple means for archiving census map images in a digital form. Their form and content provides admirably for future reproduction of the original census map image. Regardless of the storage medium, tape, disk, CD-ROM, etc., a MIM can either contain the full description of a map image or when many images are grouped on a single medium, allow sharing of common file information. In either case, the full description of the map is stored, and stored in a "human" readable form.
A MIM is not a compact binary transfer format. Part of the value of a MIM comes not from the amount of data storage it uses, but from its almost universal flat, ASCII exchange format. In some very specific cases during internal operations, a binary version of a MIM has been used for exchange between programs.
A MIM is not intended to be used directly by mapping operations programs. Rather it almost always requires reading and loading into an internal structure; one that is efficient to the needs of a given hardware and software installation. The relative ease of reading a MIM is a strength that permits the use of many different types of hardware and software for display and processing.
MIMs are not designed to be randomly accessed. MIM information is communicated by command and data sequence, much as one reads a letter or novel. Rarely in a MIM is a map entity completely described by a single command. Since MIM information is presented in the file in sequence, when an attribute such as line width is set, it stays in force for all succeeding lines plotted. In this way file size is kept relatively low since redundant attributes do not have to be expressed for every instance of a map image command primitive. Even within a command, sequence is important. Arguments in the commands must appear in the specified sequence. If an optional argument is not included, the sequence of arguments is not changed; the optional one is merely not there. Therefore, knowing what conditions have been set earlier in the file is mandatory for proper display or manipulation of an entity.
MIM information is not stored in fixed field position or fixed record size. In most cases a data field is only wide enough to contain the value in it. A number 7863 would take up four positions in a record and a number 57 would take up only two, thus precipitating a shift left of two characters for all succeeding data in that record. Similarly, many arguments for the commands are optional, so the record size will vary according to the number of arguments actually used.
Finally, MIM commands are not designed to account for every possible special condition in every census map. Even if all the possible exceptions or special conditions could be enumerated and described, to do so would weight the system down with specialized commands. Different map symbols also are not pre-established in the MIM definitions. Rather, the philosophy of the MIM is to accommodate special conditions by utilizing the existing commands, of which one of the most important is the comment (*cmt) command.
Simplicity is maintained by defining the absolute minimum number of commands and providing for extensibility. This minimal number can be determined by only allowing commands if they 1) cannot be constructed efficiently and effectively out of existing meta-commands, 2) apply to most map images, and 3) are neither hardware, software, nor operation specific. Granted, some degree of common sense must apply when deciding on a new command, but in general, the fewer the better.
Suppleness is maintained providing for a way to accommodate special situations and changing conditions. This is achieved in MIMs by providing for extensibility to the image description commands. Suppleness implies a flexibility and moldability but not a change in the basic nature of the underlying structure. In mathematical terms, a piece of ceramic clay shaped like a torus can be molded into a coffee cup or an orange juicer dish with a handle, all without losing the underlying nature of the torus.
MIMs must be kept simple and supple.
MIMs are constructed from a series of primitive commands. Each primitive is discussed in terms of its category, use and file order. A detailed description of each command is given in Appendix B, Map Image Metafile Commands.
Meta-commands are divided into three categories, 1) required commands, 2) basic class and attribute commands, and 3) grouping and extending commands.
Required commands These commands must appear in all metafiles. There are only three commands in this category: *int, *cls, and *msz.
The *int and the *cls commands bracket a map image. Any command found outside these two are assumed to not be part of the image. The *int command must appear first before any other command necessary to that image. Likewise, the *cls must appear as the last command of all commands describing that image. This is not to say that commands such as comment commands cannot appear outside the *int-*cls bounding commands. In some cases, comments are added before the *int to specify that an operation or process has occurred on that file. These "external" commands are stripped off when no longer needed and are not part of the "real" image.
The *msz command defines the fundamental design parameters of the meta image. All map images have been designed to give a certain "look" to the map product. This means that they are designed for a certain size and to be produced on an output device with certain characteristics such as a given resolution. The *msz command sets the visual size and resolution parameters. Any parts of the image that fall outside the xy- values given in the *msz command are subject to be clipped at best and dropped at worse.
Basic object class, attribute, and helper commands These commands make up the bulk of the metafile commands. They define the look-and-feel of the map image.
There are three basic object class commands, *str, *pgX, and *vtx. The *str command defines a line in terms of its shape points. The *pgX command defines a polygon in terms of its shape points. The *vtx command defines a line of text to be plotted. While text can be considered to consist of lines and areas, for MIM purposes it is considered as a class itself. Therefore, these three commands are the fundamental cartographic entities of all maps images.
Because they are fundamental, the class commands can have an optional argument that identifies the state of the entity, i.e., active, deleted, changed, added (not created by original meta image generation software). This is useful when doing interactive work or displaying the file. The class commands also can have geocodes or similar alphanumeric codes that identify the geographic entity being represented. This has the advantage of allowing image display and/or interactive software to be able to work with the entities as say, county boundaries, tract boundaries, place name, and so forth without having to work with all strings or all text.
The way an entity appears in the final map depends upon the attributes of the entity. A line can have a width, a line type such as solid, dashed, and so forth, and other attributes. Text has fonts; polygons have pattern fill and other attributes. These are attributes to the entity. There is a category of commands that are used to set attribute conditions for succeeding entity processing. Each of the attribute setting commands must be proceeded by a defining command. For example, the *dpa command defines the characteristics of a pattern that is then referred to by the line or polygon fill pattern setting commands. Table I shows the relationships between the primitive cartographic entities, their attribute setting commands and the attribute defining commands.
Table I Strings Polygons Text Defined *str *pgX *vtx by Fill color *fcs *fcp *fcv *rgb Fill pattern n/a *fpp *fpv *dpa Line color *lcs *lcp *lcv *rgb Line pattern *lps *lpp *lpv *dpa Line type *lts *ltp *ltv *dlt Line weight *lws *lwp *lwv n/a Text font n/a n/a *sft n/a
Helper commands are there to make metafiles easier to build and understand. The two helper commands are *cmt and *inc. The *cmt command allows comments to be included anywhere in the file. They can be used to elaborate on the map image, identify "non-standard" things in the file such as a new scheme for geocoding, map projection, map scale, and so forth.
The other helper command is *inc. Meta commands, comments, definitions, etc. that are common to many maps do not have to reside in every metafile. A separate file of these meta commands can be produced and included in the map image file at the point that the content of the separate file is applicable. For example, a set of pattern descriptions that are common to the urbanized area page size maps can be put in a file. This file is then linked to an urbanized area map image file by the *inc command.
Combining and extending commands These commands provide a means for making more complex cartographic objects out of basic commands and for extending the number and type of commands. Basically they act like the *int and *cls command pair in that they define the beginning and end of a group of commands that produce either a given map element or a process.
The *bef and *enf commands denote the beginning and end of a collection of meta- commands that should be treated as a group or object. These can be used to define things like a legend, which is a group of text, lines, polygons, and even other *bef - *enf objects. Because the object components can be treated as a single object, it can be manipulated as needed. For example, during an interactive program, one may zoom in on a portion of a map and have a need to see the legend at the same time. Since the legend is positioned relative to the whole map image, it may not be visible in the zoom area. However, since the legend also can be an identifiable entity, a properly written program can translate the legend coordinates and display it in the visible area of the display.
To ease creation of "sets" of entities encapsulated within a *bef and relative to each other, the *rel is used to indicate that all coordinates within the *bef are relative to the map units (inches, centimeters, etc.) position given in the *rel command. Therefore, a symbol can be produced from a series of *str, *pgX and *vtx commands, each with coordinates relative to say the center of the symbol. By using a *rel command within the *bef, only the *rel coordinates need to be changed to move the symbol to a different position. The *rel command is only active within the *bef in which it appears, but does apply to subordinate *bef-commands.
The commands that provide extensibility to the map image meta basic set are the *dep and *enp commands. The *dep and *enp commands denote the beginning and end of a process to be performed on a set of meta commands. For example, the process may be to display a triangle in a specific location and at a given angle. The advantage is that a triangle symbol need only be defined once. Then encapsulating it between a *dep - *enp with arguments for x,y-position and angle creates a new command, say a *tri command (the * is not necessary), which will produce a triangle each time it is used. Now, the symbol can be produced as many times as needed on the map image, but without having to fully describe all the bounding coordinates, the fill pattern, and so forth at each instance of the triangle. Thus, the original meta commands have been extended within this map image.
Basically the difference between a *bef-object and a *dep-extension is that a *bef does not expect arguments to modify or control instantiation while the *dep does. Put another way, *bef's are singular expressions of the contents of the *bef while *dep is instantiated as many times as needed, i.e., a legend would be a *bef while a cemetery symbol would be a *dep. One occurs once; the other occurs as many times as needed.
Appendix H describes the commands, operations, and syntax for *dep commands.
The following shows the difference between using an object definition and not using one. The metafile containing a bar scale may look like the following:
*int "Test Map" *msz 10 15 inches 200 *lnw 0.005 *sft RPTrip.Hft *lnt 0 *vtx 2.90 1.20 0.10 0.0 "Bar_Scale" 10 Miles ... (denotes other commands) ... *str 4 2.0 1.10 2.0 1.00 3.0 1.00 3.0 1.10 ... *vtx 2.0 1.60 0.15 0.0 "Bar_Scale" Scale ... *vtx 1.95 1.20 0.10 0.0 "Bar_Scale" 0 *cls
Now an example of the metafile when the barscale is treated as an object:
*int "Test Map" *msz 10 15 inches 200 *lnw 0.005 *lnt 0 *sft RPTrip.Hft ... (denotes other commands) ... *bef "Bar_Scale" *str 4 2.0 1.10 2.0 1.00 3.0 1.00 3.0 1.10 *vtx 2.0 1.60 0.15 0.0 "Bar_Text" Scale *vtx 1.95 1.20 0.10 0.0 "Bar_Values" 0 *vtx 2.90 1.20 0.10 0.0 "Bar_Values" 10 Miles *enf ... *cls
Using the *bef keeps the parts of an object together in the file. Thus they can be more easily identified and manipulated.
Since no single set of primitive commands can efficiently describe higher levels of abstraction and complex actions, the command structure should provide for extensibility. This means that a new command, symbol, etc. can be defined within the map image file. That new element will then be able to be included on the final displayed or plotted map by merely including a reference to that element. This concept will be more fully developed as MIMs evolve.
While the descriptions are similar, there is a difference between an object and an extension to the MIM commands. The object is a description of a specific map element. It has no ability to reproduce itself elsewhere on the map, or change its characteristics. These must be done to it externally. A extension is an abstract map element that will act on itself or other map components to reproduce the image. Only the instantiation of the extension can be manipulated, not the extension itself.
A MIM is constructed much as one would write a verbal description of a map image. The rules for MIM construction are predicated upon the use of information in the sequence presented.
line weights 0.005 line types solid line patterns solid fill patterns solid font RPTrip.Sas
Note that there are only three exceptions to the rule that there are no defaults. Patterns 0 and 1 are already defined as all bits off and all bits on respectively, and the definitions are generally found throughout the industry. Also, line type 0 means a solid line.
5. *inc's must occur before their information is used. Includes can be placed anywhere in the MIM. The rule is that the included information must occur before any feature or attribute command references it.
6. Attribute values continue to apply. Once an attribute value has been set, it is applied to all subsequent commands as appropriate. It is the responsibility of the applications software to insure that the proper attribute value is in force at all times. The introduction of redundant attribute values, while not changing the image, take up file space and their occurrence is discouraged.
7. Use of optional entity geoID argument. Although the creator of a given map design is free to establish any geoID coding scheme desired, many map images have been generated using the ones listed in Appendix F. Whatever coding scheme is used, the codes and their meaning should be placed after the *msz command at the top of the file and within comment commands.
NOTE: geoID length should not be excessive. At the U.S. Bureau of the Census the geoIDs are limited to a character string of not more than 31 characters.
NOTE: Except for the use of double quotes in a quoted string, a geoID cannot start with a non-alphanumeric character.
A given map design may require a different set of geoID arguments. The principles underlying MIMs encourages appropriate use of any description in the argument. Two things need to be kept in mind. First, good form would be to specify the definitions at the top of the file through use of *cmt commands. Second, a geoID must be one and only one argument. The following are examples.
S76 Good Major_Road Good
"Green Briar Springs" Good, but poor form. Multiple words enclosed by quotes could cause difficulty Better to connect words by underscore
S76 C29 Bad Space makes two arguments Major Road Bad Space makes two arguments Green Briar Springs Bad No quotes, therefore three arguments -Hydro Bad Non-alphanumeric first character
Comments help provide information to users of the MIM about what codes are to be encountered and how they should be interpreted. It is the responsibility of the program developer of the map specific software to produce programs that read this map file and handle the geocodes appropriate to that map. There is no general procedure for handling geocode information, it is all map specific. For example, two useful comments,
*cmt "geoID MAJORWATER denotes a water body that must be kept" *cmt "geoID CFCC_nnn denotes a CFCC code"
Following these comments, the map specific programs can interpret any entities with these geoIDs as appropriate to the operation and needs of the program. Thus, if the program needed to display roads of a certain CFCC by a specific color, then the geoID with a CFCC as part of it would be further split by the program to determine what color to use. For example, say roads of class A1 are to be displayed in an interactive program in red and all other roads in green, then the first string below would be displayed green and the second in red.
*str 34 CFCC_1A20
. . . . . .
*str 18 CFCC_1A10
. . . . . .
NOTE: The manner in which a feature is displayed depends upon the display program, it's purpose, and the display hardware. In no way is the display on given hardware constrained by the color, line type, and so forth that are stated in the MIM. The MIM commands for color, line type, and so forth are followed, if and only if one wishes to faithfully reproduce the original map image.
8. Use of optional entity state argument. Five states in which an entity may exist in a MIM have been defined. However, other entity states may be defined by users for their own specific purposes, such as unique processing operations. While there is no absolute specification for the format, it is strongly recommended that new state arguments begin with -X and be three additional characters in length. This would differentiate the new ones from geoIDs since geoIDs cannot start with a non-alphanumeric character.
State Denoted by Active Absence of state argument Deleted Xdel argument Changed Xchg argument Added Xadd argument Reference Xref argument
These arguments are provided so that entities modified by an interactive program may be flagged. The value of these arguments depends upon the project. For example, suppose one were investigating how a human operator designs a map. After a computer program has produced it's version of the map image, a human operator may use an interactive program that allows modifications to be made to the image. The program flags each modified entity with one of the state flags. After a series of map images have been processed, the resulting MIMs can be examined to see what actions were taken by the operator. Comparing the human actions with the original image file may yield an understanding of what rules were followed and lead to these rules being incorporated into future mapping programs.
The Xref argument is used to denote a feature or entity that is included in the MIM as an aid to processing. It denotes a feature or entity that is not to be displayed as part of the image, but is to be used to aid in creating the image. This is valuable in such operations as splitting text for stacking when the original text string needs to be retained. Another example is when providing a coordinate string for automated positioning of text along it or a polygon within which text is to be constrained, but only using the coordinates for positional reference. Since these features or entities are not part of the image, they can and usually will be removed from the files for public release.
9. Portions of this documentation are in a MIM.doc file. This file is either included with every MIM or in the case of multiple MIMs on a single storage medium, it may appear just once. The file is not necessary to use the MIM for reproducing a map, but it helps. Therefore, this file is important only when preparing MIMs for public release or archival storage. If not included directly in a MIM, the documentation file should be referenced just after the *int and as shown below. Note that this will add considerable text to your image file and should be used with discretion.
*inc MIM.doc
The rules for reading a MIM are set forth here only for general guidance to those who must develop interpreters for specific operations and/or display devices. The design of a MIM interpreter becomes one of mapping the display device characteristics to the operations specified in the MIM.
The MIM command descriptions and rules for file generation fix the contents, syntax, and sequence of the file. This in no way forces or fixes the interpretation of the commands. If the commands can be followed faithfully, the original map image will be reproduced. This either may be unachievable or undesirable. In the former case, the interpreter may be for a device that lacks the functionality to correctly render the MIM commands in terms of line weight, fill patterns, and so forth. In the latter case, the interpreter may be part of an interactive editing system where deviations from the true representation enhance the ease of the edit operation, e.g., displaying certain map features in color when the original map is black and white.
Errors can be expected in spite of efforts to eliminate them. Some syntax errors may make it impossible to meaningfully parse the commands of a metafile. If a reasonable interpretation is possible, the error falls into the category of "do the best you can." If it is impossible to guess reasonably, then the interpreter must either skip the command or abort the run until the file is repaired.
There are several approaches to creating MIM interpreters. One is to only act on the information provided by the MIM and it's associated "include" files. This has the advantage of guaranteeing a reproduction that matches the file. The other approach is to assume some default values. The following are values that are frequently found in census maps:
Default attributes values Line type: solid Line width: 0.005 Line pattern: solid (all bits on) Line color: black Fill pattern: solid (all bits on) Text font : Roman Plain Simplex Hershey font
Since MIM records do not have fixed fields, the interpreter must have some means of parsing the MIM records. The difficulty of this operation is directly related to the programming language chosen by the user. Experience has shown that writing a parsing routine in FORTRAN is somewhat more difficult than writing one in C or one of the modern versions of BASIC.
Appendix E gives the code for a simple parser written in the C computer language.
Once the MIM record is parsed, the rules for interpretation of the arguments are more defined. The rules may be stated as follows:
Appendix F provides a MIM interpreter written in psuedocode. This is the simplest form of an interpreter and is not suitable for interactive work. To load the MIM into a program that will allow interaction or changes to the MIM, the basic procedure for reading the MIM is the same. However, as the information is read, each MIM entity (*str, *pgX, *vtx, etc.) must be stored with all associated attributes. Failure to store all the entities and attributes means that at best the program must reread the entire MIM every time some action is performed such as a zoom or pan of the displayed image. At worst the file cannot be changed and reconstituted after interaction.
Every map image consists of certain components such as legends, image area, graphics scale, and so forth. For purposes of describing these to a computer program, certain COOL conventions were adopted to use in a MIM. The following defines a minimum set of COOL definitions used in MIM development.
Frame line - this line defines size and shape of the area in which components of the maps itself are displayed. Folio information such as page numbers, map title, and so forth may appear outside this frame -- or may not, depending upon the map design. This defines the envelope, not the exact shape of the frame. The shape, if displayed, may be denoted by a geoID such as Frameline on the string and/or polygon of the area. Framelines are not mandatory.
Outer Image Line - this defines the maximum envelope of a map image. Generally no parts of a map image are expected to go beyond this. This defines the envelope, not the exact shape of the outer image area. The shape, if displayed, may be denoted by a geoID such as OuterImageLine on the string and/or polygon of the area.
Neatline (Map Image Area) - this defines the limits of the area within a map in which an image will be displayed. There may be multiple map image areas per map page. This defines the envelope, not the exact shape of the map image area. The shape, if displayed, may be denoted by a geoID such as Neatline on the string and/or polygon of the area.
Entity Latitude/Longitude Envelope - this is the maximum and minimum latitude/longitude of the entity being displayed. Usually it is required when an entity is free to float within an image area. These values relate to the entity maximum/minimum map inches envelope described below. This relationship allows the computation and positioning of latitude/longitude or other reference grid ticks. This is particularly valuable when moving the entity's position within the image area. Obviously, not all maps require this relationship.
Entity Map Inches Envelope - this is the maximum and minimum map inches of the entity being displayed. Usually it is required when and entity is free to float within an image area. These values relate to the entity maximum/ minimum latitude/longitude envelope. This relationship allows the computation and positioning of latitude/longitude or other reference grid ticks. This is particularly valuable when moving the entity's position within the image area. Obviously, not all maps require this relationship.
The following graphic describes the relationship of these components to each other.
Example in terms of MIM commands
Required commands
Example: *int "UAP346001"
for page number 1 an urbanized area map for UA number 3460.
Example: *int "Percent High School Graduated of Total Population (1990)"
2. *cls
Indicates end of map metafile.
Example: *cls
3. *msz x y units resolution
Gives the maximum physical size and the units of measure for all elements of the map sheet, including image offset, borders, and so forth. Since all map images are designed for reproduction on a specific device, the resolution of the device is given in terms of pixels (dots) per unit. This provides the necessary parameters for reproducing screen patterns and for providing the "true" texture to the map symbols, line, and so forth.
Example: *msz 22.5 17.0 inches 508
Optional commands
4. *aka original_text_string alias_text_string
Identifies an alias. After an aka command, every time the alias text string is encountered during processing, the original text string is substituted for it. If a text string consists of more than one word, the text must be enclosed within double quotes.
Example 1: *aka "draw_my_triangle" "*tri" Example 2: *aka "*rgb 255 0 127" myPurple Example 3: *aka "*draw_Square" "*dsq"
The *aka in example 1 indicates that anytime the text *tri appears in the metafile after this *aka, it is taken to mean draw_my_triangle. Likewise, anytime after the aka in example 2 that the text myPurple is encountered in the metafile, it is taken to mean the *rgb 255 0 127 text string., i.e., myPurple becomes another way of issuing that specific *rgb command. The double quotes should be considered as necessary.
5. *bef [feature_ID] [feature_status] . . . . . . . . . *enf [feature_ID]
Indicates the beginning and end of a feature. This is useful when multiple entities make up a single map image feature and one wishes to keep the entities together in the MIM. The optional feature ID is strongly suggested to separate *bef's and may be added for clarity at the *enf command when feature definitions are nested or complex.
Example: *bef North_Arrow_Symbol *cmt This is a north arrow symbol. *str 6 . . . . . . . . . . *enf North_Arrow_Symbol
6. *cmt [any string of characters]
Indicates a comment. This may be any string of characters. If the parts of the string are to be treated as one unit, the whole string must be enclosed within double quotes. This command is very useful when passing environmentally dependent information and file descriptor information.
Examples: *cmt "Page size county boundary map for Georgia" *cmt rotate image 90.0 degrees *cmt "PROJECTION: Albers Equal Area" *cmt " Lamda = center if geographic entity."
7. *dat data_set_ID . . . . . . . . . *end
Indicates the beginning and end of a data set that contains zero or more data elements. A data set can be referenced only from within a *dep-*enp command. The data_set_ID must always be present because there may be multiple data sets within the MIM. A data set cannot contain other MIM commands except *cmt. The *cmt is strongly recommended as a means of elaborating on the data set structure and meaning. The need for elaboration is more pressing when the data set consists of variable length elements and the start of each element needs to be readily identified to the user. A data set is part of the full description of a map . Therefore, a data set must be part of a MIM or included within a MIM by means of a *inc command before it is referenced by any other command.
Example 1:
*dat "CountyCornClasses"
*cmt "1994 United States Census of Agriculture " *cmt "Classed data for choropleth map of Corn Production by County" *cmt "First value is the FIPS state/county code; 2nd value is the county class" 01001 4
01003 3
01005 4
02001 4
. .
. .
. .
57001 2
57003 3
*endExample 2:
*dat "RPTrip.Sas"
*cmt "Roman Plain Triplex Stroke ASCII font file" *cmt "This file contains the vector descriptions of each character in the RPTRip.Sas" *cmt "font. This font is derived from the Hershey font sets placed in the public " *cmt "domain by the U.S. Government."
*cmt "The > character in the first position denotes beginning of a data element." >001 0 0 "Not used"
>002 5 3 "A"
2.34 4.56 2.65 2.11 2.88 1.01
>003 0 0 "Not used"
. . . . .
. . . . .
. . . . .
*end
Example 3:
*dat "MIM Documentation"
The meaning of each MIM command is based upon the premise that elements of a graphic image are being described; specifically, elements of a map image.
When the ....
*end
8. *dep procedure_ID [[arg] [arg] ... [arg]] . . . . . . . . . *enp [procedure_ID]
Indicates the beginning and end of a procedure definition. Useful for reducing the size of the metafile by being able to incorporate repetitive type command sequences into a single new command. The optional procedure ID may be added to the *enp for clarity when definitions are nested or complex.
Example: *dep *draw_Square $1 $2 $3 *cmt "$1 is size of the sides of the square" *cmt "$2 is the x-value of the center of the square" *cmt "$3 is the y-value of the center of the square" $2 $1 2.0 / - $4 =
$3 $1 2.0 / - $5 =
$2 $1 2.0 / + $6 =
$3 $1 2.0 / + $7 =
**str 5
$4 $5 $6 $5 $6 $7 $4 $7 $4 $5
*enp . . . . . . . . . . . . *draw_Square 0.25 24.001 13.345 15.0 . . . . . . . .
See section on *dep - *enp command for details about internal operators and use.
9. *dlt number_changes line_type_ID [-cap arg]
[-join arg]
Line types (styles) are defined as a sequence of pen ups and downs to be used when drawing the lines for these features. This command relates a pen up/down sequence to a line type ID. All values are given in terms of the decimal units of the map. Dash lengths are denoted by the minus values while the positive values denote the space between dashes. The optional arguments -cap and -join are provided to enhance the image quality. The -cap argument specifies the characteristics of the end of the line, while the -join argument specifies the characteristics of the point at which two lines join. Acceptable arguments for each are,
-cap butt round square -join beveled round mitered
The default is determined by the output device's default.
Example: *dlt 4 myDashDot -cap butt -join round -0.50 0.10 -0.01 0.20
10. *dpa matrix_side_size pattern_ID [pattern_Angle] Patterns are defined in terms of bits-on/bits-off in a matrix of 4 by 4, 8 by 8, 16 by 16, or 32 by 32. Matrix side size gives the size of the matrix. The pattern is known to all successive references to this pattern by the pattern ID. The angle argument is a decimal degree angle at which the pattern is to be plotted. This argument is optional and its absence causes a default to angle of 0.0. A *dpa command must occur somewhere before any references to the pattern ID.
Example: *dpa 4 pat_31 30.0
1 0 0 1
0 1 1 0
0 1 1 0
1 0 0 111. *fcp color_ID *fcs color_ID *fcv color_ID
Sets the pattern color for successive *pgX, *str and *vtx commands respectively. The color ID must have been defined earlier in the file.
Example: *fcs myPurple
12. *fpp pattern_ID -rule
*fpv pattern_ID -rule
Sets fill pattern for successive *pgX, and *vtx commands respectively. Each applies only to its respective feature type. This command defines the fill pattern to be used when drawing the lines for these features. Sets the fill pattern to the specified pattern ID. The pattern_ID is an alphanumeric identifies that is defined by a preceding *dpa- command. The application of the fill patter is governed by the optional application rule argument. If the argument is not given, the default rule is to use the transparent application rule. -tran denotes a transparent rule; -opaq denotes an opaque rule; and - eras denotes an erase rule. (Rules detailed in appendix.)
Example: *fpp 31 -OPAQ
13. *inc filename
Identifies a file whose contents are to be included at this point in the metafile being processed.
Examples: *inc "mysymbols.fil"
*inc "mypatterns.fil"
14. *lcs color_ID *lcp color_ID *lcv color_ID
Sets the line color for successive *str, *pgX, and *vtx commands respectively. The color ID must have been defined earlier in the file by a *rgb command.
Example: *lcs myPurple
15. *lps line_pattern_ID -rule *lpp line_pattern_ID -rule *lpv line_pattern_ID -rule
Sets line pattern for successive *str, *pgX, and *vtx commands respectively. Each applies to its respective feature type. This command defines the line pattern to be used when drawing the lines for these features. Each line pattern ID is an alphanumeric identifies that must have been previously defined by a *dlp command. The application rule argument is optional. See *fpp for discussion of rule argument.
Example: *lps 31
16. *lts line_type_ID (is an alphanumeric identifier) *ltp line_type_ID (is an alphanumeric identifier) *ltv line_type_ID (is an alphanumeric identifier)
Sets line type for successive *str, *pgX, and *vtx commands respectively. Each applies to its respective feature type. It is defined by a *dlt command.
Example: *lts myDashDot
17. *lws line_width *lwp line_width *lwv line_width
Sets line weight (width) for successive *str, *pgX, and *vtx commands respectively. Each applies to its respective feature type. This command defines the line weight to be used when drawing the lines for these features. Line width is given in decimal units of the map as provided in the *msz command.
Example: *lws 0.005
18 *pgX number_of_polygons points_in_first_polygon fill_boundary_flag [feature_ID] [feature_status] Defines a polygon. Acceptable values for the fill_boundary_flag are,
F Fill only, do not draw boundary.
O Only draw the boundary of the area, do not fill it.
B Fill the area and draw the boundary.
Example: *pgX 2 5 F Augusta Xchg 2.0 2.0 6.0 2.0 6.0 5.0 2.0 5.0 2.0 2.0 2 4 3.0 2.7 4.6 2.7 3.5 3.1 3.0 2.7
19. *rel map_units_X map_units_Y
Only has meaning when used within a *bef; it indicates that all succeeding coordinates within this *bef are given relative to this point and not to the map in total. The effect, i.e., scope of a *rel ends with the *enf of the *bef to which it refers.
Example: *rel 8.75 2.55
20. *rgb v1 v2 v3 color_ID
The *rgb is a defining command that sets the relationship between a color in RGB scheme and a color ID used within the MIM. All values are integer numbers ranging from zero to 255, i.e. 256 values per color. This gives a total of 16,777,216 colors.
Example: *rgb 255 0 127 myPurple
The color ID argument allows use of this name in subsequent color referencing commands.
Example: After defining, to set the line color, issue the command
*cvp myPurple
21. *sft font_type_name [[FOB] or [-fillFlag arg]] [-slopeFac arg] [- widthFac arg]
[-kernFlag OFF/ON] [-spaceFac arg]
Sets the font type to the font type name specified. The optional characteristics are things such as a flag that denotes to fill or not the interior of the character, letter spacing other than default, and so forth. NOTE: If the FOB single letter argument is used, then it must occur in the third position; if the -fillFlag plus single letter argument pair is used, then it can occur in any position after the second; but both the FOB single letter flag and the -fillFlag plus argument can not be used at the same time. All other argument pairs can occur in any sequence.
F Fill only, do not draw boundary.
O Only draw the boundary of the area, do not fill it.
B Fill the area and draw the boundary.
N If used, denotes that fill is not applicable to this font, equivalent to an OOO argument.
Example: *sft RPTriplex.Sas *sft RBHev.Oas B -slopeFac-20.0 *sft RBHev.Oas -spaceFac 0.8 -fillFlag F -slopeFac 30.0
22. *str number_of_points [string_ID] [string_status] Denotes a string of coordinates.
Example: *str 4 Triangle Xadd
3.0 2.7 4.6 2.7 3.5 3.1 3.0 2.7
23. *vtx x y h a [text_ID] [text_status] Indicates vector text. The start position of the text is given by x and y, while the text height and angle are h and a respectively.
Example: *vtx 3.2 1.7 0.5 30.0 M130095001
"Red River Road"
Inactive commands
This is a list of commands that may be found in the very oldest MIMs. They are no longer recognized.
*pgX number_of_polygons points_in_first_polygon [feature_ID] [feature_status] NOTE: This is the old form of the *pgX command. It does not contain the FOB argument.
*dpa matrix_side_size pattern_ID NOTE: This is the old form of the command. It does not contain the angle argument.
*lnt number_of_changes (1992) [see line type command] *lnp line_pattern_ID (1992) [see line pattern command] *lnw line_width (1992) [see line width command] *pat pattern_ID (1992) [see pattern command] *cir, *pdn, *pup, *pud, *rot, *txt, and *fnt (1990 commands.)
The cartographic font files are provided to aid in production of a MIM. Other fonts can be defined and used, but the ones listed here are the only ones used to date to produce census maps. Currently, they are implemented on three platforms: VAX (VMS operating system) in FORTRAN, Tektronix and Silicon Graphics (Unix operating system) in C and PC (DOS & Windows operating system) in MicroSoft Visual Basic.
Currently active font files.
RPTrip.Sas Roman Plain Triplex Stroke Hershey font RPSimp.Sas Roman Plain Simplex Stroke Hershey font RPSlim.Sas Roman Plain Slim (Simplex) Stroke Hershey font IPTrip.Sas Italic Plain Triplex Stroke Hershey font IPSimp.Sas Italic Plain Simplex Stroke Hershey font IPSlim.Sas Italic Plain Slim (Simplex) Stroke Hershey font RPHev.Oas Roman Plain Helvetica Outline mapping font RBHev.Oas Roman Bold Helvetica Outline mapping font IBHev.Oas Italic Bold Helvetica Outline mapping font IPHev.Oas Italic Plain Helvetica Outline mapping font
NOTE: Plans are to replace these with TrueType fonts in order to reduce the size of the output files when the Census unique files are used to make PostScript or HP plot files.
place includes here
main(argc, argv)
int argc;
chaö *argv[];
{
Set up variables and initialize them as required.
Check for input metafile and open it.
Open support files such as fonts.
Step thru meta file looking for *msz command and extract values when found. If not found, abort run.
Initial graphics system.
Rewind metafile
1. More records in metafile? If NO, end run. 2. Get record. These are expected to be command records. 3. Parse record. 4. Is it a - a. *str, then extract points and plot using current attributes. Go to 5. Example:
if ( (strcmp(tokenStrPtrs[0], "*str") == 0 )
{
k = atol(tokenStrPtrs[1]); /* Number of pts */ n = 0;
while(k > 0) { fptr = fgets(recBuf,130, metaFilePtr); numToks = parseTokens(recBuf); /* Pts this rec */ for (j = 0; j < numToks; j++) { fx = atof(tokenStrPtrs[j]) * scaleFac + offset; j++; fy = atof(tokenStrPtrs[j]) * scaleFac + offset; if(n == 0) { MOVE(fx,fy); n++; } else DRAW(fx,fy); } k = k - (numToks/2); }continue;
}
b. *pgX, then extract points and plot using current attributes. Go to 5. c. *vtx, then extract values and text record and plot using current attributes. Go to 5. d. *sft, if same as current, take no action. If not, then set the current font to this type. Go to 5. e. *lnw, if same as current, take no action. If not, then set the current line weight to this value. Go to 5.
Example: if ( (strcmp(tokenStrPtrs[0],"*lnw") == 0 ){
currentLineWeight = atof(tokenStrPtrs[1]); continue;
} f. So forth with all attribute commands. g. Not recognized command, go to 5. 5. Go to 1.
End program.
/* Utility function that successively parses the string passed to it in the function argument until all the tokens in the string have been extracted and stored in a global array of tokens. The function returns the number of tokens found. Pointers to the tokens are returned in another global array. See parseTokens.h for definition of global arrays. */ /* F. R. Broome ********************* 20 August 1990 */
#include <stdio.h>
#include <string.h> char tokenStrings[64][128]; /* Globals for passing tokens. */ char *tokenStrPtrs[64]; /*Include as externals in program*/ #define QUOTE 34 /* This is the double quote. */ #define COMMA 44 #define SPACE 32 #define CR 13 /* Carriage return */ #define LF 10 /* Line feed */ /* NULL already defined elsewhere. */long int parseTokens( inString )
char inString[]; /* Incoming text string. */
{ extern char tokenStrings[64][255]; extern char *tokenStrPtrs[64]; long int i, kount = 0, charCnt = 0, numTokens = 0, flag; char *inStrPtr = inString; /* Establish a pointer to inString */ char *tokenStart = NULL; /* Initialize to 0 */
/* Check to see if the incoming text string has any characters to process. */ charCnt = strlen(inString);
if( charCnt < 1 ) return(numTokens); /*No string passed. *//* --- Capture and store all tokens in this string. --- */ *(inStrPtr + charCnt ) = NULL; /* Force NULL to terminate the string. */
while(charCnt)
{
/* Check for end of string. */
if((*inStrPtr == NULL) || (*inStrPtr == CR) || (*inStrPtr == LF)) break; /* End of input string detected. */ /* Ignore spaces and commas in front of tokens. */ if((*inStrPtr == SPACE) || (*inStrPtr == COMMA)) {
inStrPtr++;
continue; /* Skip to bottom of while loop for and thence to next char */ }/* Have detected a possible token character. */ tokenStart = inStrPtr; /* Set pointer to head of potential token. */ kount = 0; /* Set token character count to zero. */ if(*inSt˜Ptr == QUOTE) /* Check for the special situation of Q˜OTE */ { tokenStart++; ˜ /* Set to next oossible char as token s˜art */ inStrPtr++; ˜ ¤ /* Set th˜s pointer to next character. */ while((*inStrPtr != QUOTE) /* Check for ending QUOTE. */ && (*inStrPtr != NULL) /* Check for other string ending chars */ && (*inStrPtr != CR) && (*inStrPtr != LF)) { kount++; /* Increment token character counter. */ inStrPtr++; /* Move token character pointer. */ } /* Falling through to here indicates that all characters of the */ /* quoted token have been found. NOTE: End of string is considered */ /* to be equal a double quote. */ } else /* token is not quoted. */
{
flag = 1;
while(flag) { switch (*inStrPtr) /* Use the character ASCII value for check. */ { case NULL: case CR: case LF: case SPACE: case QUOTE: case COMMA: flag = 0; /* End of token found. */ break; default: kount++; /* Increment token character counter. */ .. inSt˜Ptr++; /* Increment text˜string pointer. */ } /* End switch. */ }.. /* End flag while-loop */} } /* End else condition */
if(kount) /* If there i˜ one or more characters in token. */ . { . /* then move the token to the global array. */
for( i = 0; i < kount; i++) { tokenStrings[numTokens][i] = *(tokenStart + i); }
tokenStrings[numTokens][i] = NULL; /* Terminate with NULL */ /* Store the pointer to this token. */ tokenStrPtrs[numTokens] = &tokenStrings[numTokens][0]; numTokens++;
}
if(*inStrPtr == QUOTE) { inStrPtr++; /* Increment past any ending quote. */ }if(*inStrPtr == CR || *inStrPtr == LF || *inStrPtr == NULL) {
charCnt = 0; /* Set value to kick out of while-loop */ }
} /* End while-loop *//* Now have all tokens from this string. Return the count. */ return(numTokens);
}
The use of nnn sequences in the descriptions below denote a series of numbers. FIPS codes are used when possible.
GeoID Denoted by State Snn County Cnnnnn Minor civil division Mnnnnnnnnnn Census county division mnnnnnnnnnn Place Pnnnnnnn Census designed place pnnnnnnn AI/ANA (American Indian/Alaskan Native American) Reservation Innnnnn Tribal trust Tnnnnnn Individual trust Nnnnnnn Tribal designated statistical area dnnnnnn Tribal jurisdiction area knnnnnn Alaska native village statistical area Hnnnnnn Alaska native regional corporation Wnn Subbario Lnnnnnnn Urbanized area Unnnn Double line water shore SHORELINE
Some useful parameter comments [map design and processing dependent]:
Old font spacing flag Param_OLD_TEXT_SPACING Map scale Param_Scale (denominator of RF) Map type Param_MapType Map file number for multiple files Param_FileNum State code for grid reference Param_GeogridStateCode (FIPS) Map entity envelope Param_EntityMinLon Param_EntityMaxLon Param_EntityMinLat Param_EntityMaxLat Param_EntityMinX Param_EntityMaxX Param_EntityMinY Param_EntityMaxY Neatline Param_NeatlineMinX Param_NeatlineMaxX Param_NeatlineMinY Param_NeatlineMaxY Outer image envelope Param_OuterImageMinX Param_OuterImageMaxX Param_OuterImageMinY Param_OuterImageMaxY Frame line Param_FrameMinX Param_FrameMaxX Param_FrameMinY Param_FrameMaxY
Some useful geoIDs to denote special relationships between map image entities when placed within *bef-*enf structures. The {...} denotes optional part of geoID.
Areal feature with associated text AREF_{...} Linear feature with associated text LINF_{...} Areal text with associated arrows ARROW_TEXT{...} Parts of split text associated with original SPLIT_TEXT{...} Fishhooks between areas FISHHOOK
NOTE: geoID's are limited in Census Bureau software to a character string of not more than 31 characters.
Several pattern commands have an optional application rule. These rules tell the output device how the map designer intended the pattern to be applied to that class of entities. There are three rules, the transparent rule, the opaque rule, and the erase rule. While there is no operational reason why the rule names have to be denoted by a minus sign followed by a four letter lower case name, it is recommended that they be so designated.
-tran Transparent overlay. The ON-bits in the pattern definition are set to ON in the output image and the OFF-bits in the pattern have no effect.
Pattern bits 0011 Existing entity bits 0101 Resulting entity pattern 0111 -opaq Opaque overlay. The ON- and OFF-bits in the pattern definition determine the pattern in the output image, i.e., both ON- and OFF- bits have an effect. Pattern bits 0011 Existing entity bits 0101 Resulting entity pattern 0011 -eras Erase overlay. The ON-bits in the pattern definition are set to OFF in the output image and the OFF-bits in the pattern have no effect. Pattern bits 0011 Existing entity bits 0101 Resulting entity pattern 0100
These pattern application rules are provided to allow for description in the MIMs of several normal cartographic (map generation) operations.
The *dep command provides one means of extensibility to the map image meta basic set. The *dep and *enp commands denote the beginning and end of a process to be performed on a set of meta commands. This appendix describes the commands that are allowed within a *dep command.
Three categories of command/operations are defined for *dep commands. The first category is the MIM commands. Most MIM commands are allowed. Section one of this appendix lists the specific MIM commands allowed. There are two types of allowed MIM commands. Type 1 has the form of the standard defined command. The second type is MIM commands that use variables as arguments. The second category is for file handling/process non-MIM commands. Section two describes these. The third category is operation commands. Section three describes these.
All variables must be proceeded by a # symbol. Arrays of variables are indexed by the array name followed immediately by a + sign and a number of the array position. All arrays are numbered starting at zero, i.e., the first position in an array is zero. For example, to load 37 into the first position of array v,
integer #v[5]
#v+0 37 <-
All variables are set to zero upon initialization. Variables defined with a double ## sign are considered to be global and their values, after first initialization, will be available throughout the whole MIM to all other *deps. Variables defined with the leading designation of static will keep their value between references to that *dep command, but their values will only be known within the defining *dep. All other variables are reset to zero with each reference to a *dep.
Section 1: Allowable MIM commands
Most of the regular MIM commands are allowed within a *dep command. When used within a *dep command, the MIM commands have an added flexibility. Specifically, the regular MIM commands can have variablies as arguments. This powerful capability to use variables as arguments underlies the fundamental purpose of a *dep command, i.e., to allow development of new MIM commands that can be referenced to do specific and usually repetative map image creation tasks.
When a regular MIM command uses variables, this is noted by using a double star before the MIM command. The normal MIM command uses a single star. For example, a *str command used within a *dep would be acted upon as if all arguments are given in a normal fashion. If a **str command is used, then all arguments associated with the string are assumed to be variables unless they are numeric or quoted arguments which are treated as in a *str command.
The following regular MIM commands may be used in either a star or double star form in a *dep command.
*str *pgX *vtx *sft *rgb *fcs *fcp *fcv *fpp *fpv *lcs *lcp *lcv *lps *lpp *lpv *lts *ltp *ltv *lws *lwp
*lwv
A selected example of use:
*str 5 CityBoundary
2.3 4.7 2.4 4.7 2.8 4.6 2.9 4.9 3.2 5.3
**str 5 SquareSymbol
#x1 #y1 #x2 #y2 #x3 #y3 #x4 #y4 #x5 #y5
Section 2: Non-MIM commands (*dep unique)
integer Defines a 32-bit integer variable or array of integers. Example: To define two single 32-bit integer variables and an array of 12 32-bit values, integer #a #b #c[12]
float Defines a 32-bit decimal number or array of numbers. Example: To define two single 32-bit decimal variables and an array of 12 32-bit values, float #a #b #c[12]
char Defines a single character variable or a text string (array) of characters. Example: To define two single character variables and a string of 12 characters, char #a #b #c[12]
parse Directs the parsing of a text string variable. This operation stores the number of tokens resulting from the parsing as an integer value and pointers to each token at locations accessable by treating the parse command as an array. NOTE: Conversion from text token to numeric value is automatic and is based upon receiving variableOs data type. Example: To parse a text string, say #t, get the count of tokens, and store the third token in another text string variable, say #p,
integer #n
char #t[32] #p[16]
#t parse
#n #parse <-
#p #parse+3 <-
if
then
else
endif Defines a conditional execution operation. Each command brackets other operations and/or code that are to be evaluated or executed. NOTE: These must be by themselves on a line.
Example: To test the value of two numbers and add them if the first is greater than the second or subtract them if the second is equal to or greated than the first, and store the results in a variable #n,
integer #n #m
#m 5 <-
if
#m 19 >
then
#m 19 + #n ->
else
#m 19 - #n ->
endif
while
do
wend Defines a conditional execution looping operation. Each command brackets other operations/code that are to be evaluated or executed. NOTE: These must be by themselves on a line.
Example: To increment a counter variable, say #m, as long as the specified condition is true, say #n greater than zero,
integer #n #m
#n 5 <-
while
#n 0 >
do
#m 1 +
wend
break Causes a jump from that point to the first executable code beyond the current control loop.
continue Causes a jump from that point to the bottom of the current control loop.
getstate Gets the contents of a specified MIM state variable. The eighteen defined attribute references are,
Strings Polygons Text Fill color fcs fcp fcv Fill pattern fpp fpv Line color lcs lcp lcv Line pattern lps lpp lpv Line type lts ltp ltv Line weight lws lwp lwv Text font sft
NOTE: These three-character attribute reference acronyms are reserved words in MIMs and cannot be used as variable names.
Example: To get the currently active line color setting and store it in a variable, say #v,
integer #v
#v getstate lcs
setstate Sets the contents of a specified MIM state variable. The eighteen defined attribute references are,
Strings Polygons Text Fill color fcs fcp fcv Fill pattern fpp fpv Line color lcs lcp lcv Line pattern lps lpp lpv Line type lts ltp ltv Line weight lws lwp lwv Text font sft
NOTE: These three-character attribute reference acronyms are reserved words in MIMs and cannot be used as variable names.
Example: To set the currently active line color setting from the value in a given variable, say #v, integer #v
#v setstate lcs
dataop Performs the specified operation on an associated data set. The command has four arguments: 1) name of receiving text string (buffer), 2) data set identification, 3) the operation to be performed, and 4) the data set position indicator. Acceptable dataop operation commands are, TOP moves to first entry in data set, returns a one. NEXT moves to next entry in data set, returns the entry number or -1 if past end. PREV moves to the previous entry in data set, returns the entry number or -1 if below first record. END moves to the last entry in data set, returns the entry number. READ moves to the indicated record and reads the data, returns a zero if and error is encountered during the read or a -1 if an illegal position is requested.
The data set position indicator is a user defined variable that is loaded with the position in the data set from which reading is to begin, i.e., the record number. If the read is successful, then the value of the indicator remains the same; if and error occurs, the indicator is set to zero; and if the requested move sends the indicator below the first record or past the end of the file, the indicator is set to -1.
Example:
1. Into the user defined text buffer #b read the 23rd record in a data set, assuming it has been defined with a *dat command and the name stored in the user variable #dfile,
#p 23 <-
dataop #b #dfile READ #p
2. Move to a position and store the record number in the position argument and record at that position in #b, (note #p value is ignored for this command)
dataop #b #dfile END #p
NOTE: TOP works in a similar fashion.
dataop #b #dfile NEXT #p
NOTE: PREV works in a similar fashion.
Section 3: Operations
stackCount pushes the stack count on top of the stack. If this results in a full stack, the operation pushes a -1 on the stack.
stackTop points to the top value in the stack. Use example: Checking the value on the top of a stack.
if stackTop 1 > then 55 push endif
push pushes the proceeding argument onto the stack. Use example: Pushing a given value onto the stack.
if stackTop 1 > then 55 push endif
pull removes the top stack item from the stack and stores it in the proceeding agrument. Use example: Storing the top stack value in a specified variable.
integer #v
. . .
#v pull
pop removes the top stack item. Undefined if stack is empty. Use example: Removes the top stack value.
integer #v
23 push
pop
Results in 23 being removed from the stack and stack count being reduced by one.
exc exchanges the top two stack items. Use example: Exchanges the top two items on the stack. Undefined if stack has fewer than two items. Command Result 15 push stack top = 15 stack 2nd = empty 24 push stack top = 24 stack 2nd = 15 exc stack top = 15 stack 2nd = 24 + add the top two values on the stack and store results on stack. Results will be the same type as the top stack item. - subtract the top two values on the stack and store results on stack. Results will be the same type as the top stack item. * multiply the top two values on the stack and store results on stack. Results will be the same type as the top stack item. / divide the top two values on the stack and store results on stack. Results will be the same type as the top stack item. sqt take the square root of the top value on the stack and store results on stack. Results will be the same type as the top stack item. Undefined for negative values or empty stack. cos take the cosine(radians) of the top value on the stack and store results on stack. Result will be a float value. Undefined for negative values or empty stack. sin take the sine (radians) of the top value on the stack and store results on stack. Result will be a float value. Undefined for negative values or empty stack. tan take the tangent (radians) of the top value on the stack and store results on stack. Result will be a float value. Undefined for negative values or empty stack. atn take the arctangent (radians) of the top value on the stack and store results on stack. Result will be a float value. Undefined for negative values or empty stack. == test for equality that tests the top two values on the stack and pushes a 1 on the stack if equal, a 0 if unequal. It also pushes a -1 on the stack if there are less than two values on the stack or if a full-stack condition would result. != test for nonequality tests the top two values on the stack for equality, and pushes a 1 on the stack if unequal, a 0 if equal. Pushes a -1 on the stack if there are less than two values on the stack or if a full-stack condition would result. < test for less than tests the top two values on the stack for the top less than the below stack value and pushes a 1 on the stack if true, a 0 if not. Pushes a -1 on the stack if there are less than two values on the stack or if a full-stack condition would result. > test for greater than tests the top two values on the stack for the top greater than the below stack value and pushes a 1 on the stack if true, a 0 if not. Pushes a -1 on the stack if there are less than two values on the stack or if a full-stack condition would result. <= test for less than or equal tests the top two values on the stack for the top less than or equal the below stack value and pushes a 1 on the stack if true, a 0 if not. Pushes a -1 on the stack if there are less than two values on the stack or if a full-stack condition would result. >= test for greater than or equal tests the top two values on the stack for the top greater than or equal the below stack value and pushes a 1 on the stack if true, a 0 if not. Pushes a -1 on the stack if there are less than two values on the stack or if a full-stack condition would result. <- load the value of the 2nd argument into the location denoted by the value of the 1st argument. The load target must be a variable. -> load the value of the 1st argument into the location denoted by the value of the 2nd argument. The load target must be a variable.