Table of Contents
MapTools
TerraLib provides a basic set of tools for dealing with maps. You can extend this basic framework in order to have your own way of rendering and representing the concept of a map.
In this module you will find some useful concepts:
- Canvas: a canvas is an abstraction of a drawing area.
- Layer: a base class designed to support applications that handle information as layers. A layer is just a reference to the data (not the data itself) and can be used to logically organize it. The information about a layer can be stored in different medias (a XML file or a DBMS table) depending on the type of persistence choosed.
- Renderer: a set of classes for rendering layers, geographical objects and other stuffs.
- Project: an auxiliary class that can be used to split a set of layers… <color red>(não deve ser mais necessário)</color>
- DataGrid: a base class representing the data table associated to a dataset.
- MapDisplay: A helper class to control the display of a set of layers.
The data structures in this module are not bounded to a specific GUI nor a given data model. There are complementary modules that can be used to take advantage of thi module:
- TerraLib Symbology Encoding Module
- TerraLib Qt Widgets
- TerraLib XML Persistence module
- TerraLib DB Persistence module
Design Rationale
Examples
Canvas
Layer
Rendering
How to Extend MapTools
Remarks
Análise e ideias
- Definição da classe
AbstractRenderer
- Inicialmente… método
draw()
:
AbstractRenderer::draw(AbstractLayer* l, Canvas* c, Envelope& bbox, int srid);
- Qual o papel de um Renderer?
Básico:
- Capaz de obter as geometrias do layer;
- Intepretação das regras (
Rules
) definidas no estilo. Inclui a decodificação das expressões de restrição<Filters>
; - Interpretação dos
Symbolizers
e ajuste dos parâmetros visuais no Canvas; - Transformação de coordenadas / projeção?
- (2) e (3): Utilização do padrão Visitor?
// Something like that... LayerRenderer::draw(Layer* layer, Canvas* canvas, const te::gm::Envelope& bbox, int srid) { // Gets the associated data source te::da::DataSource* ds = layer->getDataSource(); // Gets a transactor! te::da::DataSourceTransactor* t = ds->getTransactor(); // What is the data set? std::string dsname = layer->getDataSetName(); // or size_t idx = layer->getDataSet(); // Gets the style and rules Style* style = layer->getStyle(); std::vector<Rule*> rules = style->getRules(); for(unsigned int i = 0; i < rules.size(); i++) // for each rule { Rule* r = rules[i]; /* Gets the objects that obey the rule's restriction. Case there isn't restriction, gets all objects! */ /* Here should be called the transactor query() method. It is necessary interprets the <Rule> elements included on Style. For now, gets the data set using only box restriction. */ te::da::DataSet* dataset = t->getDataSet(dsname, &bbox, te::gm::SpatialRelation::INTERSECTS); // Gets the symbolizers std::vector<Symbolizer*> symbs = r->getSymbolizers(); for(unsigned int i = 0; i < symbs.size(); i++) // for each symbolizer { /* Sets the graphics parameters on canvas and for each geometry, let´s draw! */ /* For while, Default Geometry. How can we get anothers or a specified, for example? And others data sets (dataset->getDataSet())? Uses <Geometry> element? */ te::gm::Geometry* g = dataset->getGeometry(); // Verifies the SRID. Case different, converts coordinates... canvas->draw(g); delete g; } } delete t; }
- A especificação SE permite que atributos de visual (ex.: a expessura da linha, tamanho de uma imagem, etc.) sejam definidos com base em atributos dos objetos. Mais ainda, podem ser definidos a partir de uma expressão. Por exemplo, no desenho de um dado Rodovias, é possível definir a expessura de cada linha a partir do atributo
numero_de_pistas
. Como esta questão pode ser tratada? - Revisar a interface
AbstractLayer
, métodos e atributos; - Atualmente, um layer possui um
Style
. É interessante a criação de um novo nível chamadoStyledLayer
para associar um estilo + layer? Ou então, definição de um métodoAbstractLayer::draw(Style* s)
? Implica em…
AbstractRenderer::draw(AbstractLayer* l, Style* s, Canvas* c, Envelope& bbox, int srid);
Basicamente, permite sobreescrever um estilo pré-determinado…
- Pensando no caso mais simples, o
DataSetLayer
:
- Aponta um
DataSource
, ok? QualDataSet
o layer referencia? Carregar o nome (std::string) resolve. Ou ainda, o index associado (+ rápido)… - É necessário a utilização de um
Filter
separado das restrições que podem ser definidas nasRules
? - Sendo possível sub-layers, quem é responsável pelo desenho deles? O próprio layer?
- É interessante (é possível), neste nível, fornecer métodos utilizados geralmente para análise? Por exemplo: interseção, diferença, união, etc. entre dois layers. Temos no
Geometry
:
Geometry* result = g1->intersection(g2); // ...... AbstractLayer* result = l1->intersection(l2); // ?
- Discutir e definir a classe base
MapDisplay
. Alguns pontos:
- Possui um conjunto de layers e;
- um conjunto de canvas?
- Qual o melhor modo de trabalhar com estas duas classes?
- Define a ordem de exibição das camadas?
- Responsável pelo desenho dos sub-layers?
- Construção de uma classe base
AbstractMapDisplay
sem atributos e com a definição de alguns métodos para controle e configuração; - Podemos fornecer uma classe concreta básica que implementa uma estratégia, ou seja, um modo de trabalhar com as questões apontadas acima.
- É o melhor? Se não, o 'insatisfeito' pode estender direto o Abstract…
- Urgente! É necessário implementar a tradução de um objeto <Filter> para o nosso
Query
. Só assim, será possível fazer ojoin
das restrições e repassar ao Transactor. Desse modo, eliminamos oQueryLayer
do modo que está implementado…