32 #include <boost/unordered_map.hpp> 33 #include <boost/math/constants/constants.hpp> 34 #include <cairo-svg.h> 62 template<
typename IdType>
75 && first.getRaw() < second.getRaw());
78 const boost::unordered_map<IdType, Style*> &
styles;
82 template <
typename LabelType>
83 bool CompareLabels(
const shared_ptr<LabelType>& first,
const shared_ptr<LabelType>& second) {
84 return (first->style->font_size > second->style->font_size)
85 || (first->style->font_size == second->style->font_size
86 && first->box.minX < second->box.minX);
116 const shared_ptr<TileIdentifier>&
id)
const 120 cairo_set_font_size(cr, 10);
123 std::ostringstream labelstrm;
124 labelstrm <<
"X: " <<
id->getX() <<
" Y: " <<
id->getY();
125 labelstrm <<
" Zoom: " <<
id->getZoom();
126 labelstrm <<
" Style: " <<
id->getStylesheetPath();
128 cairo_text_path(cr, label.c_str());
130 cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0);
131 cairo_set_line_width(cr, 2.0);
132 cairo_stroke_preserve(cr);
133 cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
141 std::vector<NodeId>& nodes,
142 std::vector<WayId>& ways,
143 std::vector<RelId>& relations)
const 145 const boost::unordered_map<NodeId, Style*> &nodeMap = map.
getNodeMap();
146 const boost::unordered_map<WayId, Style*> &wayMap = map.
getWayMap();
147 const boost::unordered_map<RelId, Style*> &relationMap = map.
getRelationMap();
149 ways.reserve(wayMap.size());
150 for (
auto& pair : wayMap) {
151 ways.push_back(pair.first);
154 nodes.reserve(nodeMap.size());
155 for (
auto& pair : nodeMap) {
156 nodes.push_back(pair.first);
159 relations.reserve(relationMap.size());
160 for (
auto& pair : relationMap) {
161 relations.push_back(pair.first);
172 const cairo_matrix_t* transform,
173 std::vector<NodeId>& nodes,
174 std::vector<WayId>& ways,
175 std::vector<RelId>& relations,
176 std::list<shared_ptr<Label>>& labels,
177 std::list<shared_ptr<Shield>>& shields,
180 const boost::unordered_map<WayId, Style*> &wayStyles = map.
getWayMap();
181 const boost::unordered_map<NodeId, Style*> &nodeStyles = map.
getNodeMap();
182 const boost::unordered_map<RelId, Style*> &relationStyles = map.
getRelationMap();
187 if (ways.size() > 0) {
188 minZ = std::min(minZ, wayStyles.at(ways.front())->z_index);
189 maxZ = std::max(maxZ, wayStyles.at(ways.back())->z_index);
191 if (nodes.size() > 0) {
192 minZ = std::min(minZ, nodeStyles.at(nodes.front())->z_index);
193 maxZ = std::max(maxZ, nodeStyles.at(nodes.back())->z_index);
195 if (relations.size() > 0) {
196 minZ = std::min(minZ, relationStyles.at(relations.front())->z_index);
197 maxZ = std::max(maxZ, relationStyles.at(relations.back())->z_index);
200 auto rid = relations.begin();
201 auto wid = ways.begin();
202 auto nid = nodes.begin();
204 int layer = minZ / 100;
205 for (
int z = minZ; z <= maxZ; z = nextZ)
207 if (z/100 != layer) {
215 for (; rid != relations.end(); rid++)
217 const Style* s = relationStyles.at(*rid);
219 nextZ = std::min(nextZ, s->
z_index);
227 for (; wid != ways.end(); wid++)
229 const Style* s = wayStyles.at(*wid);
231 nextZ = std::min(nextZ, s->
z_index);
243 for (; nid != nodes.end(); nid++)
245 const Style* s = nodeStyles.at(*nid);
247 nextZ = std::min(nextZ, s->
z_index);
263 std::vector<shared_ptr<Shield> >& shields)
const 267 cairo_set_line_join(cr, CAIRO_LINE_JOIN_ROUND);
269 for (
auto& shield : shields)
271 const Style* s = shield->style;
273 double x0, y0, height, width;
275 x0 = shield->shield.minX + border;
276 y0 = shield->shield.minY + border;
277 width = shield->shield.getWidth() - 2*border;
278 height = shield->shield.getHeight() - 2*border;
284 cairo_arc(cr, x0 + height/2.0, y0 + height/2.0,
285 height/2.0, boost::math::constants::pi<double>()/2.0, 3.0*boost::math::constants::pi<double>()/2.0);
286 cairo_arc(cr, x0 + width - height/2.0, y0 + height/2.0,
287 height/2.0, 3.0*boost::math::constants::pi<double>()/2.0, boost::math::constants::pi<double>()/2.0);
288 cairo_close_path(cr);
290 cairo_rectangle(cr, x0, y0, width, height);
296 cairo_stroke_preserve(cr);
301 cairo_fill_preserve(cr);
312 template <
typename LabelType>
314 std::vector<shared_ptr<LabelType> >& labels,
319 cairo_set_line_join(cr, CAIRO_LINE_JOIN_ROUND);
321 for (
auto it = labels.rbegin(); it != labels.rend(); it++)
323 const shared_ptr<LabelType>& label = *it;
324 const Style* s = label->style;
328 cairo_move_to(cr, label->origin.x, label->origin.y);
330 cairo_select_font_face(cr,
336 cairo_text_path(cr, label->text.c_str());
342 cairo_stroke_preserve(cr);
355 bool tooLarge =
false;
356 for (
int i = 0; i < 8 && !tooLarge; i++)
363 std::vector<shared_ptr<Label> >& placed)
365 std::vector<shared_ptr<Label>> contained;
366 contained.reserve(labels.size());
369 for (
auto& l : labels) {
371 contained.push_back(l);
376 double intersect_max = 0.0;
377 for (
auto& other : placed)
378 intersect_max = std::max(intersect_max, other->box.getIntersection(l->box).getArea());
381 if (intersect_max < RENDERER_LABEL_OVERLAP * l->box.getArea())
386 for (
auto& l : contained) {
387 double width = l->box.getWidth();
388 double height = l->box.getHeight();
397 for (
int i = 0; i < 5; i++)
398 possible[i] = l->box.
translate(trans[i].
x, trans[i].
y);
401 double intersect_max[5] = {0.0, 0.0, 0.0, 0.0, 0.0};
402 for (
auto& other : placed) {
403 for (
int i = 0; i < 5; i++) {
405 intersect_max[i] = std::max(intersect_max[i], intersection.
getArea());
410 for (
int i = 1; i < 5; i++)
411 if (intersect_max[i] < intersect_max[min]
417 l->
translate(trans[min].x, trans[min].y);
425 std::vector<shared_ptr<Shield> >& placed)
427 std::vector<shared_ptr<Shield>> contained;
428 contained.reserve(10);
431 for (
auto& shield : shields) {
436 double intersect_max = 0.0;
437 for (
auto& other : placed) {
439 intersect_max = std::max(intersect_max, intersection.
getArea());
443 if (intersect_max < RENDERER_SHIELD_OVERLAP * shield->box.getArea())
444 placed.push_back(shield);
451 cairo_t* cr = layers[0].
cr;
456 cairo_surface_flush(layers[i].surface);
457 cairo_set_source_surface(cr, layers[i].surface, 0.0, 0.0);
470 cairo_surface_t* image = cairo_image_surface_create_from_png(bg.c_str());
471 cairo_pattern_t* pattern = cairo_pattern_create_for_surface(image);
472 cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
473 cairo_set_source(layer.
cr, pattern);
474 cairo_pattern_destroy(pattern);
475 cairo_surface_destroy(image);
476 cairo_paint(layer.
cr);
481 cairo_paint(layer.
cr);
486 const shared_ptr<RenderCanvas>& canvas,
487 const shared_ptr<Tile>& tile)
489 const shared_ptr<TileIdentifier>&
id = tile->getIdentifier();
507 tile->setImage(canvas->copySliceImage());
511 const shared_ptr<RenderCanvas>& canvas,
512 double width,
double height,
517 std::vector<NodeId> nodes;
518 std::vector<WayId> ways;
519 std::vector<RelId> relations;
523 cairo_matrix_t trans;
524 cairo_matrix_init_scale(&trans, width / (
double) area.
getWidth(),
526 cairo_matrix_translate(&trans, -area.
minX, -area.
minY);
528 CairoLayer* layers = canvas->getImageLayers();
532 std::list<shared_ptr<Label> > labels;
533 std::list<shared_ptr<Shield> > shields;
536 renderObjects(layers, map, &trans, nodes, ways, relations, labels, shields, cache);
539 std::vector<shared_ptr<Shield> > placedShields;
540 placedShields.reserve(10);
541 shields.sort(&CompareLabels<Shield>);
547 std::vector<shared_ptr<Label> > placedLabels;
548 placedLabels.reserve(labels.size());
549 labels.sort(&CompareLabels<Label>);
558 const shared_ptr<MetaIdentifier>& mid,
559 const shared_ptr<Tile>& tile)
const 561 int tx0 = mid->getX();
562 int ty0 = mid->getY();
564 CairoLayer* layers = canvas->getImageLayers();
567 cairo_surface_flush(layers[0].surface);
569 const shared_ptr<TileIdentifier>& tid = tile->getIdentifier();
570 int dx = (tid->getX() - tx0) *
TILE_SIZE;
571 int dy = (tid->getY() - ty0) *
TILE_SIZE;
573 cairo_set_source_surface(slice.
cr, layers[0].
surface, -dx, -dy);
574 cairo_paint(slice.
cr);
580 tile->setImage(canvas->copySliceImage());
586 int height =
id->getHeight() *
TILE_SIZE;
587 int zoom =
id->getZoom();
593 id->getY() +
id->getHeight(),
604 renderArea(area, canvas, width, height, map, cache);
void paintBackground(CairoLayer &layer, const Style *canvasStyle) const
void placeLabels(const std::list< shared_ptr< Label > > &labels, std::vector< shared_ptr< Label > > &placed)
Place labels with greedy algorithm.
#define TILE_SIZE
This file is part of alaCarte.
void icon(cairo_t *cr, AssetCache &cache)
void fill(cairo_t *cr, AssetCache &cache)
cairo_surface_t * surface
float shield_casing_width
void stroke(cairo_t *cr, AssetCache &cache)
const boost::unordered_map< IdType, Style * > & styles
TESTABLE const boost::unordered_map< WayId, Style * > & getWayMap() const
void fill(cairo_t *cr, AssetCache &cache)
A RenderAttributes object contains mappings from NodeIDs and WayIDs to Style objects which define how...
const string & str() const
Returns the internal string.
bool intersects(const basic_rect< T > &bounding) const
void sortObjects(RenderAttributes &map, std::vector< NodeId > &nodes, std::vector< WayId > &ways, std::vector< RelId > &relations) const
Sort objetcs into painting order.
void label(cairo_t *cr, std::list< shared_ptr< Label > > &labels, AssetCache &cache)
TESTABLE Style * getCanvasStyle()
MaybeCachedString fill_image
Format
Enumeration which contains all supported image formats.
MaybeCachedString font_family
bool contains(const basic_vector2< T > &p) const
TESTABLE const boost::unordered_map< RelId, Style * > & getRelationMap() const
TESTABLE const boost::unordered_map< NodeId, Style * > & getNodeMap() const
Color shield_casing_color
TESTABLE void sliceTile(const shared_ptr< RenderCanvas > &canvas, const shared_ptr< MetaIdentifier > &id, const shared_ptr< Tile > &tile) const
void label(cairo_t *cr, std::list< shared_ptr< Label > > &labels, AssetCache &cache)
void shield(cairo_t *cr, std::list< shared_ptr< Shield > > &shields, AssetCache &cache)
A Style stores the MapCSS properties for a single Node or Way, or a Relation of type multipolygon...
void renderArea(const FixedRect &area, const shared_ptr< RenderCanvas > &canvas, double width, double height, RenderAttributes &map, AssetCache &cache)
basic_rect< T > grow(T dx, T dy) const
#define RENDERER_LABEL_OVERLAP
bool CompareLabels(const shared_ptr< LabelType > &first, const shared_ptr< LabelType > &second)
Sort labels according to their area and minX (for determinism)
bool operator()(IdType first, IdType second)
void renderShields(cairo_t *cr, std::vector< shared_ptr< Shield > > &shields) const
Only renders the shield background, the text is rendered in renderLabels.
basic_rect< T > translate(T dx, T dy) const
void placeShields(const std::list< shared_ptr< Shield > > &shields, std::vector< shared_ptr< Shield > > &placed)
Place labels with greedy algorithm.
const shared_ptr< Geodata > data
stores the actual data
basic_vector2< double > FloatPoint
bool isCutOff(const FloatRect &box, const FloatRect &owner)
Checks if all neighbour tile know about the owner of the label.
void renderLabels(cairo_t *cr, std::vector< shared_ptr< LabelType > > &labels, AssetCache &cache) const
basic_rect< T > getIntersection(const basic_rect< T > &other) const
void renderObjects(CairoLayer *layers, RenderAttributes &map, const cairo_matrix_t *transform, std::vector< NodeId > &nodes, std::vector< WayId > &ways, std::vector< RelId > &relations, std::list< shared_ptr< Label >> &labels, std::list< shared_ptr< Shield >> &shields, AssetCache &cache) const
Renders a OSM layer onto the given cairo surface.
void compositeLayers(CairoLayer *layers) const
Composited all layers into the first layer.
This file is part of alaCarte.
const char * c_str() const
Returns the internal c string.
static boost::mutex renderLock
lock calls to cairo for old versions that are not thread-safe.
TESTABLE void renderEmptyTile(RenderAttributes &map, const shared_ptr< RenderCanvas > &canvas, const shared_ptr< Tile > &tile)
FloatRect neighbourRequests[8]
Sort objects according to osm-layer and z_index (and id for determinism)
void printTileId(cairo_t *cr, const shared_ptr< TileIdentifier > &id) const
Debug function that prints identifier on the tile.
void shield(cairo_t *cr, std::list< shared_ptr< Shield > > &shields, AssetCache &cache)
CompareObjects(const boost::unordered_map< IdType, Style * > &styles)
TESTABLE void renderMetaTile(RenderAttributes &map, const shared_ptr< RenderCanvas > &canvas, const shared_ptr< MetaIdentifier > &id)
Renderer(const shared_ptr< Geodata > &data)