U.S. Census Bureau

Map Image Metafile ® (MIM ®) Language Manual

Version 6.0
27 April 1998

"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
  • Why MIM?
  • What Is MIM?
  • What MIM Is Not
  • KISS Principle (Keep It Simple and Supple)
  • Command Primitives
  • Objects and Command Extensibility
  • Rules for MIM Construction
  • Rules for Reading MIMs
  • Appendices
  • COOL Map Component Definitions
  • MIM Commands
  • Cartographic Fonts Files
  • Simple MIM Interpreter Psuedocode
  • Simple MIM Record Token Parser
  • U.S. Census Map GeoID and Parameter Examples
  • Pattern Application Rules
  • *dep Command Definitions and Syntax

    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.

  • Some typographical errors, spelling errors, and minor wording changes were made throughout the document.
  • All currently unimplemented commands have been moved to the active section since they are part of the MIM language specification. Implementation is considered a software/site issue, not a language specification issue.
  • The *dep section has been rewritten and much material moved to Appendix H

    Why MIM?

    Past
    Historically the U. S. Bureau of the Census has made available to the public the maps accompanying or associated with data products. Heretofore this has taken the form of having the maps printed and bound with the data volumes or issued separately. With the exception of a few map products, this has been the means of distribution for almost 100 years.

    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.

    What Is MIM?

    A Map Image Metafile is a flat file of ASCII characters that is a self-documenting, full-image description of a map. This means several things: The contents of a MIM file are readable without special software. In fully expanded form, no external documentation is needed to describe the data fields. Differences in the bit-structure of the real, integer, and character data types between computers and programming languages are of no consequence. And, most importantly, the information in the file can be used to faithfully reproduce a copy of the original census map.

    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.

    What MIM Is Not

    It is probably true to say that MIMs are not for the inflexible and weak-hearted!

    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.

    KISS Principle (Keep It Simple and Supple)

    The development and evolution of the file structure and content has been heavily influenced by the Keep It Simple Soldier (KISS) principle. While retaining the guiding principle of simplicity in form and content, the other need was for it to be supple. Indeed, one of the problems with defining strict structures and standards is that they tend to evolve into highly complex encoding schemes as technological and/or social changes occur and attempts are made to accommodate them. There is always the tendency, in the name of management ease, to enforce formalized structure in situations when it is at best inappropriate, and at worse, totally repressive to creativity and advancement. By keeping a MIM simple but flexible, hopefully some of these pitfalls may be avoided.

    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.

    Command Primitives

    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.

    Objects and Command Extensibility

    COOL considers a map as a collection of cartographic objects. Each object consists of one or more cartographic primitives and/or other objects. MIMs are constructed and should be processed from this same viewpoint. The advantage of objects is that they provide an easy means for manipulating multiple primitives as if they were one object. The use of objects also allows for the reuse of the same object between maps.

    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.

    Rules for MIM Construction

    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.

    1. A map image starts with an *int command. The inclusion of optional information in the *int command is strongly recommended. This information is useful when searching for a given MIM on a storage medium that may have many of them. For example, if the map ID is given, a simple search routine that checks the *int command in each MIM would be used to build an index of maps on a disk, CD-ROM or similar storage medium.
    2. A map image must close with a *cls command. This is the only way that a file of multiple images can separate one image from another.
    3. All map image files must contain one and only one *msz command. When placing the *msz command, it must be placed in the file ahead of any commands that include coordinates or patterns. All coordinates or other metric values that occur within that MIM are assumed to be in terms of the units argument in the *msz command, e.g., if the units are centimeters, then all coordinates are assumed to represent measurements in centimeters.
    4. Defaults cannot be assumed. Although some map series processing software have built in defaults, the MIM should always start by setting these values. A MIM must have these values set before any *str, *vtx, or *pgX command is encountered. The applications program can set any values desired. Some values that have served as reasonable initial values in the past are,

    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

    Rules for Reading MIMs

    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:

    1. Read the MIM until a *int command is encountered. Then and only then initiate the map image.
    2. Continue to read until a *msz command is encountered. Extract the map size and resolution. Set up processing factors such as display scale, initializing plot size, and so forth based upon these values. If a *msz is not found before a *cls is encountered, abort the run; this is a bad MIM.
    3. Return to the top of the MIM and process forward from the *int. This is done in case the *msz is not the first executable encountered - though it should be.
    4. Process each command in turn until a *cls is encountered. This signals the end of the file.

    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.

    Appendix A


    COOL Map Component Definitions

    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

    Appendix B


    Metafile Commands

    Required commands

    1. *int [alphanumeric map ID] Indicates beginning of map commands. This may or may not be followed by text elaborating on such things as the name of the map, project, etc. The comment command can be used for the same information.

    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
    *end

    Example 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 1

    11. *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.)
    

    Appendix C


    Cartographic Font Files

    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.

    Appendix D


    Simple MIM Interpreter Psuedocode

    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.

    Appendix E


    Simple MIM Record Token Parser
    
    

    /* 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);
    }

    Appendix F


    U.S. Census Map GeoID and Parameter Examples

    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.

    Appendix G


    Pattern Application Rules

    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.

    Appendix H


    *dep Command Definitions and Syntax

    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.

    1. Move to a position and store the record number in the position argument and record at that position in #b, (note #p value is automatically incremented from previous value),

    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.