diff --git a/demo/viewer/main.cpp b/demo/viewer/main.cpp index 905844720..c5cb4ad4c 100644 --- a/demo/viewer/main.cpp +++ b/demo/viewer/main.cpp @@ -36,52 +36,59 @@ int main( int argc, char **argv ) using mapnik::datasource_cache; using mapnik::freetype_engine; - QCoreApplication::setOrganizationName("Mapnik"); - QCoreApplication::setOrganizationDomain("mapnik.org"); - QCoreApplication::setApplicationName("Viewer"); - - QSettings settings("viewer.ini",QSettings::IniFormat); - - // register input plug-ins - QString plugins_dir = settings.value("mapnik/plugins_dir", - QVariant("/usr/local/lib/mapnik/input/")).toString(); - datasource_cache::instance()->register_datasources(plugins_dir.toStdString()); - // register fonts - int count = settings.beginReadArray("mapnik/fonts"); - for (int index=0; index < count; ++index) + try { - settings.setArrayIndex(index); - QString font_dir = settings.value("dir").toString(); - freetype_engine::register_fonts(font_dir.toStdString()); - } - settings.endArray(); + QCoreApplication::setOrganizationName("Mapnik"); + QCoreApplication::setOrganizationDomain("mapnik.org"); + QCoreApplication::setApplicationName("Viewer"); + QSettings settings("viewer.ini",QSettings::IniFormat); - QApplication app( argc, argv ); - MainWindow window; - window.show(); - if (argc > 1) window.open(argv[1]); - if (argc >= 3) - { - QStringList list = QString(argv[2]).split(","); - if (list.size()==4) + // register input plug-ins + QString plugins_dir = settings.value("mapnik/plugins_dir", + QVariant("/usr/local/lib/mapnik/input/")).toString(); + datasource_cache::instance()->register_datasources(plugins_dir.toStdString()); + // register fonts + int count = settings.beginReadArray("mapnik/fonts"); + for (int index=0; index < count; ++index) + { + settings.setArrayIndex(index); + QString font_dir = settings.value("dir").toString(); + freetype_engine::register_fonts(font_dir.toStdString()); + } + settings.endArray(); + + QApplication app( argc, argv ); + MainWindow window; + window.show(); + if (argc > 1) window.open(argv[1]); + if (argc >= 3) + { + QStringList list = QString(argv[2]).split(","); + if (list.size()==4) + { + bool ok; + double x0 = list[0].toDouble(&ok); + double y0 = list[1].toDouble(&ok); + double x1 = list[2].toDouble(&ok); + double y1 = list[3].toDouble(&ok); + if (ok) window.set_default_extent(x0,y0,x1,y1); + } + } + else + { + window.zoom_all(); + } + if (argc == 4) { bool ok; - double x0 = list[0].toDouble(&ok); - double y0 = list[1].toDouble(&ok); - double x1 = list[2].toDouble(&ok); - double y1 = list[3].toDouble(&ok); - if (ok) window.set_default_extent(x0,y0,x1,y1); + double scaling_factor = QString(argv[3]).toDouble(&ok); + if (ok) window.set_scaling_factor(scaling_factor); } + return app.exec(); } - else + catch (std::exception const& ex) { - window.zoom_all(); + std::cerr << "Could not start viewer: '" << ex.what() << "'\n"; + return 1; } - if (argc == 4) - { - bool ok; - double scaling_factor = QString(argv[3]).toDouble(&ok); - if (ok) window.set_scaling_factor(scaling_factor); - } - return app.exec(); } diff --git a/src/agg/process_building_symbolizer.cpp b/src/agg/process_building_symbolizer.cpp index 8f82ca2b8..4184bc42f 100644 --- a/src/agg/process_building_symbolizer.cpp +++ b/src/agg/process_building_symbolizer.cpp @@ -82,32 +82,31 @@ void agg_renderer::process(building_symbolizer const& sym, boost::scoped_ptr frame(new geometry_type(LineString)); boost::scoped_ptr roof(new geometry_type(Polygon)); std::deque face_segments; - double x0(0); - double y0(0); - + double x0 = 0; + double y0 = 0; + double x,y; geom.rewind(0); - unsigned cm = geom.vertex(&x0,&y0); - for (unsigned j=1;jmove_to(x,y); } - else if (cm == SEG_LINETO) + else if (cm == SEG_LINETO || cm == SEG_CLOSE) { frame->line_to(x,y); face_segments.push_back(segment_t(x0,y0,x,y)); } - x0 = x; y0 = y; } + std::sort(face_segments.begin(),face_segments.end(), y_order); std::deque::const_iterator itr=face_segments.begin(); - for (;itr!=face_segments.end();++itr) + std::deque::const_iterator end=face_segments.end(); + + for (; itr!=end; ++itr) { boost::scoped_ptr faces(new geometry_type(Polygon)); faces->move_to(itr->get<0>(),itr->get<1>()); @@ -120,22 +119,22 @@ void agg_renderer::process(building_symbolizer const& sym, ren.color(agg::rgba8(int(r*0.8), int(g*0.8), int(b*0.8), int(a * sym.get_opacity()))); agg::render_scanlines(*ras_ptr, sl, ren); ras_ptr->reset(); - + // frame->move_to(itr->get<0>(),itr->get<1>()); frame->line_to(itr->get<0>(),itr->get<1>()+height); + } geom.rewind(0); - for (unsigned j=0;jmove_to(x,y+height); roof->move_to(x,y+height); } - else if (cm == SEG_LINETO) + else if (cm == SEG_LINETO || cm == SEG_CLOSE) { frame->line_to(x,y+height); roof->line_to(x,y+height); @@ -153,6 +152,7 @@ void agg_renderer::process(building_symbolizer const& sym, ras_ptr->add_path(roof_path); ren.color(agg::rgba8(r, g, b, int(a * sym.get_opacity()))); agg::render_scanlines(*ras_ptr, sl, ren); + } } } diff --git a/src/agg/process_line_symbolizer.cpp b/src/agg/process_line_symbolizer.cpp index 1d5388aa3..ec75035b4 100644 --- a/src/agg/process_line_symbolizer.cpp +++ b/src/agg/process_line_symbolizer.cpp @@ -60,7 +60,7 @@ void agg_renderer::process(line_symbolizer const& sym, unsigned g=col.green(); unsigned b=col.blue(); unsigned a=col.alpha(); - + ras_ptr->reset(); set_gamma_method(stroke_, ras_ptr); @@ -76,7 +76,7 @@ void agg_renderer::process(line_symbolizer const& sym, pixfmt_comp_type pixf(buf); pixf.comp_op(static_cast(sym.comp_op())); renderer_base renb(pixf); - + agg::trans_affine tr; evaluate_transform(tr, feature, sym.get_transform()); @@ -94,12 +94,23 @@ void agg_renderer::process(line_symbolizer const& sym, rasterizer_type ras(ren); set_join_caps_aa(stroke_,ras); - typedef boost::mpl::vector conv_types; + typedef boost::mpl::vector conv_types; vertex_converter, rasterizer_type, line_symbolizer, CoordTransform, proj_transform, agg::trans_affine, conv_types> converter(ext,ras,sym,t_,prj_trans,tr,scaled); - if (sym.clip()) converter.set(); // optional clip (default: true) + if (sym.clip() && feature.paths().size() > 0) // optional clip (default: true) + { + eGeomType type = feature.paths()[0].type(); + if (type == Polygon) + converter.set(); + else if (type == LineString) + converter.set(); + // don't clip if type==Point + } + converter.set(); // always transform if (fabs(sym.offset()) > 0.0) converter.set(); // parallel offset converter.set(); // optional affine transform @@ -117,12 +128,23 @@ void agg_renderer::process(line_symbolizer const& sym, } else { - typedef boost::mpl::vector conv_types; + typedef boost::mpl::vector conv_types; + vertex_converter, rasterizer, line_symbolizer, CoordTransform, proj_transform, agg::trans_affine, conv_types> converter(ext,*ras_ptr,sym,t_,prj_trans,tr,scale_factor_); - if (sym.clip()) converter.set(); // optional clip (default: true) + if (sym.clip() && feature.paths().size() > 0) // optional clip (default: true) + { + eGeomType type = feature.paths()[0].type(); + if (type == Polygon) + converter.set(); + else if (type == LineString) + converter.set(); + // don't clip if type==Point + } + converter.set(); // always transform if (fabs(sym.offset()) > 0.0) converter.set(); // parallel offset converter.set(); // optional affine transform diff --git a/src/cairo_renderer.cpp b/src/cairo_renderer.cpp index 89fa90a9a..a3fae2a76 100644 --- a/src/cairo_renderer.cpp +++ b/src/cairo_renderer.cpp @@ -498,7 +498,6 @@ public: } else if (cm == SEG_CLOSE) { - line_to(x, y); close_path(); } } @@ -895,43 +894,32 @@ void cairo_renderer_base::process(building_symbolizer const& sym, boost::scoped_ptr frame(new geometry_type(LineString)); boost::scoped_ptr roof(new geometry_type(Polygon)); std::deque face_segments; - double x0(0); - double y0(0); - + double x0 = 0; + double y0 = 0; + double x, y; geom.rewind(0); - unsigned cm = geom.vertex(&x0, &y0); - - for (unsigned j = 1; j < geom.size(); ++j) + for (unsigned cm = geom.vertex(&x, &y); cm != SEG_END; + cm = geom.vertex(&x, &y)) { - double x=0; - double y=0; - - cm = geom.vertex(&x,&y); - if (cm == SEG_MOVETO) { frame->move_to(x,y); } - else if (cm == SEG_LINETO) + else if (cm == SEG_LINETO || cm == SEG_CLOSE) { frame->line_to(x,y); + face_segments.push_back(segment_t(x0,y0,x,y)); } - - if (j != 0) - { - face_segments.push_back(segment_t(x0, y0, x, y)); - } - x0 = x; y0 = y; } std::sort(face_segments.begin(), face_segments.end(), y_order); std::deque::const_iterator itr = face_segments.begin(); - for (; itr != face_segments.end(); ++itr) + std::deque::const_iterator end=face_segments.end(); + for (; itr != end; ++itr) { boost::scoped_ptr faces(new geometry_type(Polygon)); - faces->move_to(itr->get<0>(), itr->get<1>()); faces->line_to(itr->get<2>(), itr->get<3>()); faces->line_to(itr->get<2>(), itr->get<3>() + height); @@ -948,20 +936,18 @@ void cairo_renderer_base::process(building_symbolizer const& sym, } geom.rewind(0); - for (unsigned j = 0; j < geom.size(); ++j) + for (unsigned cm = geom.vertex(&x, &y); cm != SEG_END; + cm = geom.vertex(&x, &y)) { - double x, y; - unsigned cm = geom.vertex(&x, &y); - if (cm == SEG_MOVETO) { - frame->move_to(x, y + height); - roof->move_to(x, y + height); + frame->move_to(x,y+height); + roof->move_to(x,y+height); } - else if (cm == SEG_LINETO) + else if (cm == SEG_LINETO || cm == SEG_CLOSE) { - frame->line_to(x, y + height); - roof->line_to(x, y + height); + frame->line_to(x,y+height); + roof->line_to(x,y+height); } } @@ -1000,14 +986,21 @@ void cairo_renderer_base::process(line_symbolizer const& sym, evaluate_transform(tr, feature, sym.get_transform()); box2d ext = query_extent_ * 1.1; - typedef boost::mpl::vector conv_types; + typedef boost::mpl::vector conv_types; vertex_converter, cairo_context, line_symbolizer, CoordTransform, proj_transform, agg::trans_affine, conv_types> converter(ext,context,sym,t_,prj_trans,tr,scale_factor_); - if (sym.clip()) converter.set(); // optional clip (default: true) + if (sym.clip() && feature.paths().size() > 0) // optional clip (default: true) + { + eGeomType type = feature.paths()[0].type(); + if (type == Polygon) + converter.set(); + else if (type == LineString) + converter.set(); + // don't clip if type==Point + } converter.set(); // always transform - if (fabs(sym.offset()) > 0.0) converter.set(); // parallel offset converter.set(); // optional affine transform if (sym.smooth() > 0.0) converter.set(); // optional smooth converter diff --git a/src/save_map.cpp b/src/save_map.cpp index f572c8fc0..52d0482ec 100644 --- a/src/save_map.cpp +++ b/src/save_map.cpp @@ -78,6 +78,11 @@ public: { set_attr( sym_node, "placement", sym.get_point_placement() ); } + if (sym.get_image_transform()) + { + std::string tr_str = sym.get_image_transform_string(); + set_attr( sym_node, "transform", tr_str ); + } serialize_symbolizer_base(sym_node, sym); } @@ -218,6 +223,11 @@ public: { set_attr(sym_node, "shield-dy", displacement.second); } + if (sym.get_image_transform()) + { + std::string tr_str = sym.get_image_transform_string(); + set_attr( sym_node, "transform", tr_str ); + } serialize_symbolizer_base(sym_node, sym); } @@ -249,7 +259,6 @@ public: { set_attr( sym_node, "height", mapnik::to_expression_string(*sym.height()) ); } - serialize_symbolizer_base(sym_node, sym); } diff --git a/tests/python_tests/render_grid_test.py b/tests/python_tests/render_grid_test.py index f2ce75b3c..596480ab4 100644 --- a/tests/python_tests/render_grid_test.py +++ b/tests/python_tests/render_grid_test.py @@ -20,13 +20,13 @@ def setup(): grid_correct_old = {"keys": ["", "North West", "North East", "South West", "South East"], "data": {"South East": {"Name": "South East"}, "North East": {"Name": "North East"}, "North West": {"Name": "North West"}, "South West": {"Name": "South West"}}, "grid": [" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " !!! ### ", " !!!!! ##### ", " !!!!! ##### ", " !!! ### ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " $$$$ %%%% ", " $$$$$ %%%%% ", " $$$$$ %%%%% ", " $$$ %%% ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "]} # now using svg rendering -grid_correct_old2 = {"data": {"North East": {"Name": "North East"}, "North West": {"Name": "North West"}, "South East": {"Name": "South East"}, "South West": {"Name": "South West"}}, "grid": [" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " !!! ### ", " !!! ### ", " !!! ### ", " !!! ### ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " $$$ %%% ", " $$$ %%% ", " $$$ %%% ", " $ % ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "], "keys": ["", "North West", "North East", "South West", "South East"]} +grid_correct_old2 = {"data": {"North East": {"Name": "North East"}, "North West": {"Name": "North West"}, "South East": {"Name": "South East"}, "South West": {"Name": "South West"}}, "grid": [" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " !!! ### ", " !!! ### ", " !!! ### ", " !!! ### ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " $$$ %%% ", " $$$ %%% ", " $$$ %%% ", " $$$ %%% ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "], "keys": ["", "North West", "North East", "South West", "South East"]} # previous rendering using agg ellipse directly -grid_correct_new = {"keys": ["", "North West", "North East", "South West", "South East"], "data": {"South East": {"Name": "South East"}, "North East": {"Name": "North East"}, "North West": {"Name": "North West"}, "South West": {"Name": "South West"}}, "grid": [" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " !! ## ", " !!! ### ", " !! ## ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " $$$ %% ", " $$$ %%% ", " $$ %% ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "]} +grid_correct_new = {"data": {"North East": {"Name": "North East"}, "North West": {"Name": "North West"}, "South East": {"Name": "South East"}, "South West": {"Name": "South West"}}, "grid": [" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " !! ## ", " !!! ### ", " !! ## ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " $$ %% ", " $$$ %% ", " $$ %% ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "], "keys": ["", "North West", "North East", "South West", "South East"]} # newer rendering using svg -grid_correct_new2 = {"data": {"North East": {"Name": "North East"}, "North West": {"Name": "North West"}, "South East": {"Name": "South East"}, "South West": {"Name": "South West"}}, "grid": [" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " !! ## ", " !!! ## ", " !! ## ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " $$ %% ", " $$ %% ", " $ % ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "], "keys": ["", "North West", "North East", "South West", "South East"]} +grid_correct_new2 = {"data": {"North East": {"Name": "North East"}, "North West": {"Name": "North West"}, "South East": {"Name": "South East"}, "South West": {"Name": "South West"}}, "grid": [" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " !! ## ", " !!! ### ", " !! ## ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " $$ %% ", " $$$ %% ", " $$ %% ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "], "keys": ["", "North West", "North East", "South West", "South East"]} def resolve(grid,row,col): """ Resolve the attributes for a given pixel in a grid. @@ -164,7 +164,7 @@ def test_render_grid2(): grid_feat_id = {'keys': ['', '3', '4', '2', '1'], 'data': {'1': {'Name': 'South East'}, '3': {'Name': u'North West'}, '2': {'Name': 'South West'}, '4': {'Name': 'North East'}}, 'grid': [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' !! ## ', ' !!! ### ', ' !! ## ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' $$$ %% ', ' $$$ %%% ', ' $$ %% ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']} -grid_feat_id2 = {"data": {"1": {"Name": "South East"}, "2": {"Name": "South West"}, "3": {"Name": "North West"}, "4": {"Name": "North East"}}, "grid": [" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " !! ## ", " !!! ## ", " !! ## ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " $$ %% ", " $$ %% ", " $ % ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "], "keys": ["", "3", "4", "2", "1"]} +grid_feat_id2 = {"data": {"1": {"Name": "South East"}, "2": {"Name": "South West"}, "3": {"Name": "North West"}, "4": {"Name": "North East"}}, "grid": [" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " !! ## ", " !!! ### ", " !! ## ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " $$ %% ", " $$$ %% ", " $$ %% ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "], "keys": ["", "3", "4", "2", "1"]} def test_render_grid3(): """ test using feature id"""