Osmarender/Rules

From OpenStreetMap

Jump to: navigation, search

Contents

Developing Osma Styles

If you plan to create a new style for rendering, have a look at Osmarender Styleguide where we try to collect some guidelines.

Rule file grammar

The rule file is an xml file that specifies the drawing rules. The basic structure is a list of selection rules containing rendering instructions that are processed sequentially. Items drawn later will be on top of items drawn earlier. For example:

  <rule e="way" k="highway" v="primary">
     ...
  </rule>
  <rule e="way" k="highway" v="motorway">
     ...
  </rule>

Each rule specifies what elements to select based on a matching key/value pair (for example, e="way" k="highway" v="motorway" will select all ways that have a highway tag with a value of motorway). It then specifies what to do with these nodes or segments or ways. The current instruction set allows lines, circles, symbols and text to be drawn.

Rules may be nested. This enables a rendering instruction to be based on a combination of key values. For example the following rule will select only anglican places of worship:

 <rule e="node" k="amenity" v="place_of_worship">
   <rule e="node" k="denomination" v="anglican">
     ...
   </rule>
 </rule>
  

Rules

<rule>

 <rule e="elementList" k="keyList" v="valueList" 
   [s="selector"] 
   [layer="layer"] 
   [horizontalProximity="degrees" verticalProximity="degrees"]
   [notConnectedSameTag="key"]
   [minSize="number"]>
    ...
 </rule>
  • elementList is a | separated list of one or more of the following elements that will be matched by this rule:
    • node
    • segment
    • waysegment (a segment that is part of a way)
    • way
  • selector is an optional attribute that specifies which element to use for selection. For example, all nodes can be selected that are on ways that have a highway tag, by using e="node" s="way" k="highway" v="*".
  • keyList is a | separated list of keys that will be matched by this rule
  • valueList is a | separated list of values that will be matched for the keys selected by this rule
  • A value of "*" will match any element, key or value.
  • A value of "~" for keyList will match any element that does not have any keys.
  • A value of "~" for valueList will match any element that does not have the specified key.
  • layer forces elements to be selected a the specified layer. This overrides any layer tag that there may be on the actual element itself.
  • horizontalProximity and verticalProximity provide a crude method of preventing collisions between place names by specifying the minimum distance between nodes that match the current rule. See example of collision detection for more details.
  • notConnectedSameTag is meant to inhibit the rendering of text on features that should only be labeled when some key has a different value on the feature than it has on all connected elements. For example it is used to only display names for highway areas and roundabouts when they have a name that's different from all the connected ways.
  • minSize makes it possible to filter on the approximate size of an object. See [[1]] for details.

<else>

 <else>
    ...
 </else>

The <else> rule selects all elements that were not selected by the preceding <rule>.

Due to a limitation in the implementation horizontalProximity/verticalProximity, notConnectedSameTag and minSize (which are implemented as filters) don't work in the expected way with <else>, they get applied in the same way to both <rule> and <else>.

Rendering Instructions

The following instructions tell Osmarender what to do with the elements selected by a rule:

  • <line> draws a line. It applies to <segment> and <way> elements.
  • <circle> draws a circle. It applies to <node> elements.
  • <text> draws text at a node or along the path of a way. It applies to <node>, <segment> and <way> elements.
    • The text to be used is specified by the k attribute of the text instruction (eg <text k="name"/>) or the data content of the <text> element.
  • <areaText> draws text in the middle of a way that describes an area.
  • <symbol> draws a symbol or image. It applies to <node> elements.
  • <areaSymbol> draws a symbol or image in the middle of a way that describes an area.
  • <wayMarker> draws a marker on a node perpendicular to any way that passes through the node. Applies to <node> elements.

Each rendering instruction can contain SVG styling attributes or it can reference a class that is defined in an embedded CSS stylesheet so the full power of SVG and CSS can be used to control the look and feel of the output.

Simple Example

This is a simple example of a rule file that selects primary roads (all ways with a key of highway and a value of primary) and draws them first in black with a 4px wide line and then in green with a 2px line (this results in a green road with a black border or casing).

<?xml version='1.0' encoding='UTF-8'?>
<?xml-stylesheet type="text/xsl" href="osmarender.xsl"?>

<rules 
  data="data.xml"
  scale="1"
  minimumMapWidth="4"
  minimumMapHeight="3"
  showScale="yes"
  showGrid="yes"
  showBorder="yes"
  showAttribution="yes"
  showLicense="yes"
  showZoomControls="yes"
  javaScript="yes">

  <rule e="way" k="highway" v="primary">
      <line style="stroke-width: 4px; stroke-linecap: round; stroke: #000000;"/>
  </rule>

  <rule e="way" k="highway" v="primary">
      <line style="stroke-width: 2px; stroke-linecap: round; stroke: #7FC97F;"/>
  </rule>

</rules>

Example of drawing nodes

Nodes can be drawn either as circles or as captions or both. This example draws towns as captions, churches as black circles with the name of the church as a caption, and hotels as uncaptioned green circles.

When a circle and a caption are both drawn for a node the caption can be offset from the circle by using the SVG attributes dx and dy.

<?xml version='1.0' encoding='UTF-8'?>
<?xml-stylesheet type="text/xsl" href="osmarender.xsl"?>

<rules 
  data="data.xml"
  scale="1"
  minimumMapWidth="4"
  minimumMapHeight="3"
  showScale="yes"
  showGrid="yes"
  showBorder="yes"
  showAttribution="yes"
  showLicense="yes"
  showZoomControls="yes"
  javaScript="yes">

  <rule e="node" k="class" v="town">
    <text k="name" font-family='Verdana' font-size='14px' font-style='bold' fill='black'/>
  </rule>

  <rule e="node" k="class" v="church">
    <circle r='3px' fill='black' stroke='black' stroke-width='1px'/>
    <text k="name" font-family='Verdana' font-size='10px' fill='black' dx='4px' dy='4px'/>
  </rule>

  <rule e="node" k="class" v="hotel">
    <circle r='3px' fill='green' stroke='black' stroke-width='1px'/>
  </rule>

</rules>

Example of using embedded CSS styles

CSS styles can be used to define the appearance of drawing elements using a style element embedded in the rules file. This is done by referencing the style using the class attribute. The following example shows minor and unclassified roads drawn using the same style.

<?xml version='1.0' encoding='UTF-8'?>
<?xml-stylesheet type="text/xsl" href="osmarender.xsl"?>

<rules 
  data="data.xml"
  scale="1"
  minimumMapWidth="4"
  minimumMapHeight="3"
  showScale="yes"
  showGrid="yes"
  showBorder="yes"
  showAttribution="yes"
  showLicense="yes"
  showZoomControls="yes"
  javaScript="yes">

  <rule e="way" k="highway" v="unclassified">
      <line class='unclassified-casing'/>
  </rule>

  <rule e="way" k="highway" v="minor">
      <line class='unclassified-casing'/>
  </rule>

  <rule e="way" k="highway" v="unclassified">
      <line class='unclassified-core'/>
  </rule>

  <rule e="way" k="highway" v="minor">
      <line class='unclassified-core'/>
  </rule>

  <defs>
    <style type="text/css" xmlns="http://www.w3.org/2000/svg">
      .unclassified-casing {
        stroke-width: 3px;
        stroke-linecap: round;
        stroke: #000000;
        }
      
      .unclassified-core {
        stroke-width: 2px; 
        stroke-linecap: round; 
        stroke: #E6E6E6;
        }
    </style>
  </defs>

</rules>

Example of route number captions

This example shows how to display route captions near a road. The text follows the path of the road but is offset to one side.

<?xml version='1.0' encoding='UTF-8'?>
<?xml-stylesheet type="text/xsl" href="osmarender.xsl"?>

<rules 
  data="data.xml"
  scale="1"
  minimumMapWidth="4"
  minimumMapHeight="3"
  showScale="yes"
  showGrid="yes"
  showBorder="yes"
  showAttribution="yes"
  showLicense="yes"
  showZoomControls="yes"
  javaScript="yes">

  <rule e="way" k="highway" v="primary">
      <line style="stroke-width: 4px; stroke-linecap: round; stroke: #000000;"/>
  </rule>

  <rule e="way" k="highway" v="primary">
      <line style="stroke-width: 2px; stroke-linecap: round; stroke: #7FC97F;"/>
      <text k="ref" font-family='Verdana' font-size='10px' fill='black' dx='2.5px' dy='-2.5px'/>
  </rule>

</rules>

Example of text on ways

This example shows how to render text along the the path of a way using the <text> instruction. The k="name" attribute specifies that the value of the name key should be used as the text value. The startOffset='50%' and text-anchor='middle' attributes specify that the text should centered halfway along the line of the path. The baseline-shift attribute offsets the baseline of the text from the center-line of the way.

Caveats:

  • Text that extends beyond the end of the way will get truncated.
  • Not all SVG viewers are able to display textPaths. Adobe ASV3 and Inkscape can, Firefox 1.5 and GIMP cannot. Inkscape does not interpret the baseline-shift attribute.
<?xml version='1.0' encoding='UTF-8'?>
<?xml-stylesheet type="text/xsl" href="osmarender.xsl"?>

<rules 
  data="data.osm"
  scale="1"
  minimumMapWidth="4"
  minimumMapHeight="3"
  showScale="yes"
  showGrid="yes"
  showBorder="yes"
  showAttribution="yes"
  showLicense="yes"
  showZoomControls="yes"
  javaScript="yes">

  <rule e="way" k="highway" v="primary">
      <line style="stroke-width: 4px; stroke-linecap: round; stroke: #000000;"/>
  </rule>

  <rule e="way" k="highway" v="primary">
      <line style="stroke-width: 2px; stroke-linecap: round; stroke: #7FC97F;"/>
      <text k="name" baseline-shift='-35%' text-anchor='middle' startOffset='50%' font-family='Verdana' font-size='4px' fill='black'/>
  </rule>

</rules>

Example of collision detection

This example shows how to filter nodes to reduce the chance of collisions when captions are rendered. Normally, if two items, such as place names, are very close together then when they are rendered one will overlap the other.

A <rule> can filter nodes based on the distance to the next similar node by using the horizontalProximity and verticalProximity attributes. The two attributes describe a rectangle around a node. If there is another node of the same kind within this rectangle then the first node will be filtered out.

For example:

 <rule e="node" k="place" v="town" horizontalProximity="0.8" verticalProximity="0.2">
   <rule e="node" k="place" v="town">
   	<text k="name" class='caption-casing town-caption-casing'/>
   	<text k="name" class='caption-core town-caption' />
   </rule>
 </rule>

This rule will select all nodes tagged with place=town, but will filter out any nodes that are close to another node within 0.8 degrees horizontally or 0.2 degrees vertically.

Links

Personal tools
recent changes