# Microstation DGN Feature Representation

This document addresses how DGN features should be drawn to match the behaviour of Microstation as closely as possible. It is written for users of the dgnlib reader code, but the information should be applicable to anyone working with DGN.

The information is based on the ISFF.TXT document, supposition, and review of display effects in various viewers. It is incomplete, and at times likely incorrect. I would appreciate feedback at warmerdam@pobox.com.

## General Symbology Information

All graphical elements contain a set of common information, represented by the following fields in DGNElemCore.

1. int color
2. int weight
3. int style
4. int properties

### Color

The color field of the DGNElemCore is a color index number (0-255), referencing a color from the appropriate color table. This is normally translated into an RGB color for use using DGNLookupColor(). The returned color should be considered the foreground color for drawing the element.

NOTE: There can be more than one color table in a DGN file, and currently on the first is utilized. In theory the screen or view value from the colormap should be used to establish which is to be used but this doesn't seem to be an issue in any sample data I have encountered.

### Weight

This is a value between 0 and 31 which is supposed to establish the weight, or thickness of lines for this element. It is unclear how this should be utilized. Geographic Explorer treats it as a line width in pixels.

### Style

The style field has one of the following values, with 0 (Solid) being the default. Presumably this only affects drawing of line segments. There is no information on appropriate sizing information for dashes or dots, or relative guidelines implicit in the names.

- DGNS_SOLID (0)
- DGNS_DOTTED (1)
- DGNS_MEDIUM_DASH (2)
- DGNS_LONG_DASH (3)
- DGNS_DOT_DASH (4)
- DGNS_SHORT_DASH (5)
- DGNS_DASH_DOUBLE_DOT (6)
- DGNS_LONG_DASH_SHORT_DASH (7)

### Properties

The properties bitfield in DGNElemCore contains various possible values, but only a few affect drawing.

The DGNPF_ORIENTATION flag is set an element is to be oriented relative to the screen, instead of relative to the design plane. It isn't clear what all properties this affects, perhaps the orientation of text in a viewer that can rotate the view of the file as a whole. No examples of this being used have been found.

If used with a line element, the DBNPF_HOLE flag indicates that the line should be treated as infinite, while it is otherwise just a segment between the two provided points. If used with a closed element (shape, complex shape, ellipse, ...) it indicates that shape is a hole (unfilled) while by default such elements are filled.

## Element Types

### DGNT_LINE

Single line segment. Use color, weight and line style.

### DGNT_LINESTRING

Polyline. Use color, weight, and line style.

### DGNT_SHAPE

Polygon. Use color for edge color. If the polygon is supposed to be filled the 0x0041 fill information attribute linkage will also be included. The fill color may differ from the element color in which case the element should be filled with the fill color, and then the boundary drawn in the element (outline) color.

If the DGNPF_HOLE flag is set the shape is really a hole within another element and should be "cleared". The exact semantics are unclear. The first and last vertices of a shape are always the same.

### DGNT_CURVE

The curve (type 11) element is a 2D or 3D parametric spline curve completely defined by a set of n points. The first two and last two points define endpoint derivatives and do not display. The interpolated curve passes through all other points.

A curve with n points defines n-1 line segments; interpolation occurs over the middle n-5 segments. Each segment has its own parametric cubic interpolation polynomial for the x and y (and z in 3D) dimensions. The parameter for each of these polynomials is the length along the line segment. Thus, for a segment k, the interpolated points P are expressed as a function of the distance d along the segment as follows:

           Pk(d) = {Fk,x(d), Fk,y(d), Fk,z(d)} with 0 <= d <= Dk

Fk,x, Fk,y, and Fk,z are cubic polynomials and Dk is the length of segment k. In addition, the polynomial coefficients are functions of the segment length and the endpoint derivatives of Fk,x, Fk,y, and Fk,z. The subscript k is merely a reminder that these functions depend on the segment.

The cubic polynomials are defined as follows:

        Fk,x = axd3 + bxd2 + cxd + Xk
        cx = tk
        bx = [3(Xk+1-Xk)/Dk - 2tk,x - tk+1,x] / Dk
        ax = [tk,x + tk+1,x - 2(xk+1-xk)/Dk] / Dk2

The m variable is analogous to the slope of the segment.

     If (|mk+1,x-mk,x| + |mk-1,x-mk-2,x|) <> 0, then:
        tk,x = (mk-1,x|mk+1,x-mk,x| + mk,x|mk-1,x-mk-2,x|)/(|mk+1,x-mk,x| +
        |mk-1,x-mk-2,x|)
     else:
        tk,x = (mk+1,x+mk,x) / 2
        mk,x = (Xk+1 - Xk) / Dk

Fk,y(d) and Fk,z(d) are defined analogously.

### DGNT_BSPLINE

Fill in later.

### DGNT_ELLIPSE

Ellipse. See DGNT_ARC for details of geometry. The DGNPF_HOLE and fill color information are applied to ellipses in the same manner as they are applied to the Shape.

### DGNT_ARC

Arc (portion of ellipse). Draw line with color, line style and weight.

The DGNElemArc (also used for ellipses) looks like this:

    typedef struct {
      DGNElemCore 	core;
      DGNPoint	origin;
      double	primary_axis;
      double        secondary_axis;
      double	rotation;
      long          quat[4];
      double	startang;
      double	sweepang;
    } DGNElemArc;

The origin is the center of rotation for the ellipse or arc.

The primary_axis and secondary_axis define the distance from the origin to the ellipse edge on the primary (horizontal) and secondary (vertical) axis.

The rotation indicates the counterclockwise (or clockwise if negative) rotation in degrees of the defined ellipse around the origin.

The startang indicates the start angle (degrees, counterclockwise) of the arc. For ellipses this is always 0.

The sweepang indicates the angle through which the arc sweeps (counterclockwise in degrees, clockwise if negative). For ellipses this is always 360.

The DGNStrokeArc() function can be used to approximate arcs and ellipses as a polyline.

### DGNT_TEXT

Text. Should be drawn using color. The text structure looks like:

    typedef struct {
        DGNElemCore core;

        int		font_id;
        int		justification;
        long        length_mult;
        long        height_mult;
        double	rotation;
        DGNPoint	origin;
        char	string[1];
    } DGNElemText;

The font_id is a value from 0-255 for the to use. It is unclear to me at this time how this can be related to a non-microstation specific font.

The justification is generally ignored, since the provided origin is always at the bottom left of the text to be placed. The justification relates to how the user originally placed the text.

The rotation indicates the rotation in degrees counterclockwise of the text (zero is horizontal, left to right).

The origin is position where the bottom left corner of the text is placed.

The height_mult field gives the height of the text in master coordinates. This appears to be the height of a line, measuring distance from the baseline of one line to the next, and is usually a bit more than the height of the text itself.

If length_mult is different than height_mult, it means the aspect ratio of the text has been adjusted from the default.

## Level Symbology

Fill in later.