Request for comment 3: Symbology (new generation)¶
|Date||24 January 2009|
|Contact||wonder.sk at gmail dot com|
This RFC describes design and implementation of new generation symbology for rendering of vector layers in QGIS. The RFC consists of a brief description of vector rendering capabilities (at time of v1.0), its design, its shortcomings and finally a proposed solution.
Current capabilities¶In 1.0 version, users are able to apply the following properties for different feature types:
- lines - set line width, pen style and color
- polygons - set fill color and pattern
- points - use hardcoded symbols (+ set line and fill settings) or svg symbols, set size and/or angle
- single symbol - one symbol is used for rendering of all features
- graduated symbol - given a set of ranges of some numerical attribute, objects are rendered with symbol based on the attribute value
- continuous color - based on numerical attribute object gets drawn with a symbol with color interpolated between two colors. Actually a special case of graduated symbol
- unique symbol - given a set of categories from attribute's unique values, objects are rendererd with symbol based on the attribute value
- fetch feature
- transform from layer coordinates to screen coordinates
- renderer sets painter's pen and brush (resp. returns an image when drawing points)
- the feature is drawn
Current limitations¶This section summarizes limitations of current implementation for production of high-quality maps that need bigger amount of customization, including examples:
- impossible to combine basic symbols and form complex symbols from them
- point symbol "star in a circle"
- line symbol made by thicker and thinner line with different colors
- impossible to draw lines with a decoration
- line with an arrow (at the end of line)
- line made by repeating a marker along it
- impossible to develop custom rendering styles
- polygon with numbered vertices
- point rendered as a combination of icons based on attributes
- rendered doesn't have full control of drawing, it just sets painter, the drawing itself is done in vector layer
- symbols can't contain more layers
This section summarizes key concepts of the new symbology implementation.
Symbols and symbol layers
There are three types of symbols: marker symbols (for points), line symbols, fill symbols (for polygons).
Symbols consist of one or more symbol layers.
When rendering a symbol, an appropriate render*() method is called to draw it. Before the first call to render method, symbol has to be initialized by calling startRender() method. Finally, stopRender() method has to be called when rendering is done. All these calls are delegated to symbol layers contained in the symbol.
It is possible to set color of a symbol - this color is set to all symbol layers. Some layers might have the color locked - for them the color is not altered. This is useful when setting color of a multilayer symbol. Similarly, it's possible to set width for line symbols, size and angle for marker symbolsThe actual rendering is implemented in symbol layers - classes derived from Qgs***SymbolLayer. These layer types will be available:
- simple marker - rendering with one of hardcoded markers
- simple line - usual rendering of a line (with specified width, color and pen style)
- simple fill - usual rendering of a polygon (with defined fill color, fill pattern and outline)
- svg marker - rendering with a SVG picture
- marker line - a line rendered by repeating a marker symbol
Symbol layers are stored in symbol layer registry. More symbol layers can be added in future.
Symbol layers are usually implemented with a function returning a widget (derived from QWidget) for setting symbol layer properties. Symbol layers that won't implement it won't be customizable from GUI.
Symbol layer properties (e.g. color, pen width) are specified as key-value pairs of strings. The properties are used when creating and saving symbol layers.
Color ramps are used for defining a range of colors that can be used during creation of renderers - symbol's color will be set from the color ramp.There are two types of color ramps:
- gradient - linear gradient from one color to some other
- random - randomly generated colors from a specified area of color space
Style groups a set of various symbols and color ramps (in future more items can be added, e.g. font setting).
User can define his own prefered / frequently used symbols, then he will be able to use them without having to recreate them everytime.
Style items (symbols and color ramps) have always a name by which they can be queried from the style.
There will be one default style in QGIS (modifiable), user will have the possibility to add new styles.
Styles are stored in an XML file with well-defined structure. This is an example of line symbol composed from two layers:
<symbol type="line" name="bigway"> <layer class="SimpleLine" locked="1"> <prop k="color" v="0,0,0" /> <prop k="width" v="3" /> <prop k="penstyle" v="solid" /> </layer> <layer class="SimpleLine" locked="0"> <prop k="color" v="255,0,0" /> <prop k="width" v="1" /> <prop k="penstyle" v="solid" /> </layer> </symbol>
RenderersRenderer is responsible for drawing a feature with correct symbol. There are three types:
- single symbol
- categorized (called unique color before)
There is no continuous color renderer because it is in fact only a special case of graduated renderer.
Categorized and graduated renderer can be created by specifying a symbol and color ramp - they will set colors for symbols appropriately.
Proposed user interface¶
Renderer settings dialog (will be embedded in vector layer properties, in symbology tab)
Symbol selector dialog - shown in case that user wants to change symbol. It shows symbols available in style and allows user to change symbol's properties.
Symbol properties dialog - allows to add and delete symbol layers, change their layer types and properties.
Color ramp dialogs - gradient and random colors
Style manager - overview of symbols and color ramps available in a style, allows to add and remove items
The described proposal has been implemented as a python plugin, you can get it from my repository:
Because of backward compatibility in 1.x series it's not possible to replace original classes with new ones with different interfaces and semantics. New implementation will exist side by side with original implementation. New classes will have a suffix (or prefix) added for better distinction, e.g. QgsSymbolV2. In version 2.0 old classes can be removed completely and the new ones will be renamed.The work can be divided into three phases:
- implementation of core classes and connection with QGIS infrastructure:
- * QgsVectorLayer - new methods drawV2(), rendererV2() and setRendererV2() will be added
- * QgsMapRenderer - new method setRenderingVersion() will be added - it will
- implementation of dialogs
- migration of QGIS application from original to new implementation
- Tim Sutton: I think one important addition will be the ability to use true type font based markers as used by other GIS applications. As mentioned in the mailing lists, it would also be good to try to keep the way open for setting styles from OGC Styled Layer Descriptor documents, and exporting styles to SLD docs (although its not necessary to implement this from the beginning). Some other things that would be good to consider: transparency per style layer, allowing different offsets per style layer so that e.g. a polygon can be rendered with an outline and then a broader outline that falls only inside the polygon (often used when creating maps with politcal boundaries for example). It would also be nice to be able to specify a blur factor for style layers so that 'soft' lines can be created and effects such as drop shadows. BR I noticed that rendering in the python prototype is quite slow which I guess is a factor of a) using an interpreted lang for the renderers and b) the extra work that needs to be done when e.g. drawing symbol lines. I assume the C++ implementation will remediate this somewhat, but it may also be a good idea to implement this in tandem with the composition engine that we have oft discussed.
SLD import/export might be good addition later (although personally I don't see much use for it now). The design allows relatively simple addition of more options you mention - like transparency or offsets. The prototype is slow indeed, there's quite some overhead with Python-C++ conversions and some optimizations like caching of markers are missing. Composition engine can be done completely separately because it would operate with whole rendered layers. --Martin
|Your Name||Vote||Comments (optional)|
|John C. Tull||+1|