alaCarte Maps
Renderer for OpenStreetMap tiles
relation_renderer.cpp
Go to the documentation of this file.
1 
23 #include <boost/unordered_map.hpp>
24 
25 #include "general/geodata.hpp"
26 #include "general/way.hpp"
27 #include "general/node.hpp"
28 #include "general/relation.hpp"
29 
30 #include "server/style.hpp"
31 
34 #include "relation_renderer.hpp"
35 
36 
37 RelationRenderer::RelationRenderer(const shared_ptr<Geodata>& data,
38  RelId rid,
39  const Style* s,
40  const cairo_matrix_t* transform)
41  : ObjectRenderer(data, s, transform)
42  , relation(data->getRelation(rid))
43 {
44 }
45 
53 void RelationRenderer::addRingPath(cairo_t* cr, const std::vector<WayId>& ids, int& idx, bool* used)
54 {
55  NodeId startNode;
56  NodeId lastNode;
57  int i = idx;
58  bool closed = false;
59  do {
60  if (used[i]) {
61  // skip entrys the next time we search for unused ones
62  if (i == idx)
63  idx++;
64  continue;
65  }
66  const std::vector<NodeId>& nodeIDs = data->getWay(ids[i])->getNodeIDs();
67 
68  bool reverse;
69  if (i == idx || nodeIDs.front() == lastNode)
70  reverse = false;
71  else if (nodeIDs.back() == lastNode)
72  reverse = true;
73  else
74  continue;
75 
76  paintLine(cr, nodeIDs, reverse, i != idx);
77  used[i] = true;
78  if (i == idx)
79  startNode = nodeIDs.front();
80 
81  if (reverse)
82  lastNode = nodeIDs.front();
83  else
84  lastNode = nodeIDs.back();
85 
86  closed = (startNode == lastNode);
87  // begin search from start
88  i = idx;
89  } while (++i < ids.size() && !closed);
90 
91  cairo_close_path(cr);
92 }
93 
94 void RelationRenderer::fill(cairo_t* cr, AssetCache& cache)
95 {
96  cairo_new_path(cr);
97 
98  const std::vector<WayId>& ids = relation->getWayIDs();
99  int n = ids.size();
100  if (n == 0)
101  return;
102 
103  // default false array
104  bool* used = new bool[n]();
105  // check if any way is part of a ring
106  for (int i = 0; i < n; i++)
107  if (!used[i]) {
108  addRingPath(cr, ids, i, used);
109  cairo_new_sub_path(cr);
110  }
111 
112  delete[] used;
113 
114  cairo_push_group(cr);
115 
116  cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
117  const string& bg = s->fill_image.str();
118  if (!bg.empty()) {
119  cairo_pattern_t* pattern = cairo_pattern_create_for_surface(cache.getImage(bg));
120  cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
121  cairo_set_source(cr, pattern);
122  cairo_fill(cr);
123  cairo_pattern_destroy(pattern);
124  } else {
125  cairo_set_source_rgba(cr, COLOR2RGBA(s->fill_color));
126  cairo_fill(cr);
127  }
128 
129  cairo_pop_group_to_source(cr);
130  cairo_paint(cr);
131 }
132 
void fill(cairo_t *cr, AssetCache &cache)
const string & str() const
Returns the internal string.
MaybeCachedString fill_image
Definition: style.hpp:82
#define COLOR2RGBA(_X)
const shared_ptr< Geodata > & data
TESTABLE const std::vector< WayId > & getWayIDs() const
Definition: relation.cpp:39
A Style stores the MapCSS properties for a single Node or Way, or a Relation of type multipolygon...
Definition: style.hpp:35
void addRingPath(cairo_t *cr, const std::vector< WayId > &ids, int &idx, bool *used)
tries to paint a ring starting at ids[idx].
void paintLine(cairo_t *cr, const std::vector< NodeId > &nodeIDs, bool reverse=false, bool connect=false) const
This file is part of alaCarte.
Color fill_color
Definition: style.hpp:79
cairo_surface_t * getImage(string path)
RelationRenderer(const shared_ptr< Geodata > &data, RelId rid, const Style *s, const cairo_matrix_t *transform)
This file is part of alaCarte.
const Style * s