OpenSeaMap/smfilter

From OpenStreetMap Wiki
Jump to navigation Jump to search

smfilter

smfilter is a tool which is part of the OpenSeaMap rendering process. It is a preprocessor run before the actual task of rendering. smfilter reads an OSM file from stdin, processes sectored lights, and outputs the result in OSM format to stdout again. The output contains all the input data plus additional nodes, ways and tags which are generated for the sectors of lights. This simplifies the rendering process and reduces data within the OSM database.

Sectors of lights are defined by several tags as found at OpenSeaMap/Lights_Data_Model#Sectors. Start and end of sectors are defined by seamark:light:#:sector_start=* and seamark:light:#:sector_end=*. The values are given in degrees from 0° to 360°. Please note that these are bearings from observer to the light which means that they are rotated by 180 degrees. This definition is common to mariners. smfilter reads and parses this sector data and adds two radial ways and the sector arc in form of OSM nodes and ways to the OSM file. This can then be simply rendered by the renderer through applying style sheets to these ways.

The radial ways and arcs are tagged with information required by the renderer to complete the process. Note that these ways and their tags form private, virtual data and are not used within the OSM database. They only have a transient existence, between the output of smfilter and the input of Osmarender.

Radius Extension

seamark:light:#:radius=* (see Rendering Sector Arcs) is an optional tag for influencing the behavior of smfilter. It defines the radius of the sector and other information to change rendering on the map. Please note that this does not have any relevance for navigation.

The value of seamark:light:#:radius=* is defined as follows:

seamark:light:#:radius = <arcdef>[;<arcdef>][;...]

<arcdef>  ::= [<radius>][:<secdef>]
<secdef>  ::= <segment>[:<style>] | <style>[:<segment>]
<radius>  ::= Radius in nautical miles.
<segment> ::= Angle of the arc segment in degrees relative to sector_start.
<style>   ::= 'solid' | 'dashed' | 'suppress'

<segment> may also be given as a negative number. In that case it is measured backwards starting at sector_end. This is only valid if it is used in the last <arcdef>. If just a single <arcdef> is defined, a virtual solid arc segment is inserted before (see sector 3 of example below).

<radius> and <segment> must be any sole fractional number without units (they would simply be ignored). Negative values of <radius> would result in a default value being used.

If the sum of angles of all segments is not equal to the range of the sector, smfilter will squeeze or enlarge them to fit the actual range of the sector (see sector 2 of example below). There is always is a mapping error and will probably result in a rendering which was not desired by the mapper. In case of using a negative value for <segment> in the last <arcdef>, smfilter will stretch the previous <arcdef> appropriately, if it does not have a <segment> defined (see sectors 1 and 5 of example below).

Special Cases

Currently, two special case with different behavior as described above exist: First, unsectored lights with a seamark:light:radius = x. An annular arc way will be generated with the specified radius and no radial ways. Second, lights with seamark:light:[#:]category = directional and seamark:light:[#:]orientation = x which is correct tagging for directional lights. A small arc (of about 4 degress) is drawn having one radial way in the center of the arc. This radial way corresponds to the value of the orientation tag.


Example

The following light shows some examples of how to use the radius tag. It has 5 different sectors and additional there is a leading sector defined be seamark:light:orientation=* (such a light would probably not exist in reality).

<?xml version='1.0' encoding='UTF-8'?>
<osm version='0.6' generator='Bernhard R. Fischer'>
  <node id='1' version='1' visible='true' timestamp='2008-07-25T11:12:13Z' lat='38.3' lon='25.1'>
     <tag k='seamark:name' v='smfilter test object' />
     <tag k='seamark:type' v='light_minor' />
     <tag k='seamark:light:character' v='Fl' />
     <tag k='seamark:light:period' v='8' />
     <tag k='seamark:light:category' v='directional' />
     <tag k='seamark:light:orientation' v='230' />
     <tag k='seamark:light:radius' v='1.2' />
     <tag k='seamark:light:1:sector_start' v='40'/>
     <tag k='seamark:light:1:sector_end' v='70'/>
     <tag k='seamark:light:1:colour' v='white'/>
     <tag k='seamark:light:1:radius' v='1:10;:dashed;:solid:-10'/>
     <tag k='seamark:light:2:sector_start' v='120'/>
     <tag k='seamark:light:2:sector_end' v='190'/>
     <tag k='seamark:light:2:colour' v='red'/>
     <tag k='seamark:light:2:radius' v='.5:20;:10:suppress;:10:dashed;:10:solid'/>
     <tag k='seamark:light:3:sector_start' v='300'/>
     <tag k='seamark:light:3:sector_end' v='20'/>
     <tag k='seamark:light:3:colour' v='green'/>
     <tag k='seamark:light:3:radius' v='.3:-25:suppress'/>
     <tag k='seamark:light:4:sector_start' v='25'/>
     <tag k='seamark:light:4:sector_end' v='35'/>
     <tag k='seamark:light:4:colour' v='red'/>
     <tag k='seamark:light:4:radius' v='1.5'/>
     <tag k='seamark:light:5:sector_start' v='250'/>
     <tag k='seamark:light:5:sector_end' v='300'/>
     <tag k='seamark:light:5:colour' v='red;green'/>
     <tag k='seamark:light:5:radius' v='1'/>
  </node>
</osm>

Source Code

smfilter is based on [libhpxml]. This is a high performance XML stream parser library which was developed to be able to parse the planet file in a reasonable amount of time.

Smfilter is released under GPLv3 and can be found at [1]. Please note that the development of Smfilter is discontinued in favor of Smrender. Smrender contains the full improved code of Smfilter.