1. patch from Toby that allows repeated labels to be placed on a line
geometry (such as roads) 2. restored text labels for point geometry. 3. process 'spacing' attribute in load_map.cpp
This commit is contained in:
parent
51906ed2f8
commit
e924b597f4
10 changed files with 228 additions and 188 deletions
|
@ -49,6 +49,9 @@ void export_text_symbolizer()
|
||||||
.add_property("text_ratio",
|
.add_property("text_ratio",
|
||||||
&text_symbolizer::get_text_ratio,
|
&text_symbolizer::get_text_ratio,
|
||||||
&text_symbolizer::set_text_ratio)
|
&text_symbolizer::set_text_ratio)
|
||||||
|
.add_property("label_spacing",
|
||||||
|
&text_symbolizer::get_label_spacing,
|
||||||
|
&text_symbolizer::set_label_spacing)
|
||||||
.add_property("halo_radius",
|
.add_property("halo_radius",
|
||||||
&text_symbolizer::get_halo_radius,
|
&text_symbolizer::get_halo_radius,
|
||||||
&text_symbolizer::set_halo_radius)
|
&text_symbolizer::set_halo_radius)
|
||||||
|
|
|
@ -280,11 +280,13 @@ popplaces_rule = Rule()
|
||||||
# The first parameter is the name of the attribute to use as the source of the
|
# The first parameter is the name of the attribute to use as the source of the
|
||||||
# text to label with. Then there is font size in points (I think?), and colour.
|
# text to label with. Then there is font size in points (I think?), and colour.
|
||||||
|
|
||||||
popplaces_text_symbolizer = TextSymbolizer('GEONAME', 10, Color('black'))
|
popplaces_text_symbolizer = TextSymbolizer('GEONAME',
|
||||||
|
'Bitstream Vera Sans Roman',
|
||||||
|
10, Color('black'))
|
||||||
|
|
||||||
# We set a "halo" around the text, which looks like an outline if thin enough,
|
# We set a "halo" around the text, which looks like an outline if thin enough,
|
||||||
# or an outright background if large enough.
|
# or an outright background if large enough.
|
||||||
|
popplaces_text_symbolizer.set_label_placement=label_placement.POINT_PLACEMENT
|
||||||
popplaces_text_symbolizer.halo_fill = Color('white')
|
popplaces_text_symbolizer.halo_fill = Color('white')
|
||||||
popplaces_text_symbolizer.halo_radius = 1
|
popplaces_text_symbolizer.halo_radius = 1
|
||||||
popplaces_rule.symbols.append(popplaces_text_symbolizer)
|
popplaces_rule.symbols.append(popplaces_text_symbolizer)
|
||||||
|
|
|
@ -36,6 +36,15 @@
|
||||||
|
|
||||||
namespace mapnik
|
namespace mapnik
|
||||||
{
|
{
|
||||||
|
|
||||||
|
struct placement_element
|
||||||
|
{
|
||||||
|
double starting_x;
|
||||||
|
double starting_y;
|
||||||
|
|
||||||
|
text_path path;
|
||||||
|
};
|
||||||
|
|
||||||
struct placement
|
struct placement
|
||||||
{
|
{
|
||||||
typedef coord_transform2<CoordTransform,geometry_type> path_type;
|
typedef coord_transform2<CoordTransform,geometry_type> path_type;
|
||||||
|
@ -48,6 +57,7 @@ namespace mapnik
|
||||||
|
|
||||||
~placement();
|
~placement();
|
||||||
|
|
||||||
|
unsigned path_size() const;
|
||||||
string_info *info;
|
string_info *info;
|
||||||
|
|
||||||
CoordTransform *ctrans;
|
CoordTransform *ctrans;
|
||||||
|
@ -63,11 +73,10 @@ namespace mapnik
|
||||||
std::queue< Envelope<double> > envelopes;
|
std::queue< Envelope<double> > envelopes;
|
||||||
|
|
||||||
//output
|
//output
|
||||||
double starting_x;
|
std::vector<placement_element> placements;
|
||||||
double starting_y;
|
|
||||||
|
|
||||||
text_path path;
|
|
||||||
|
|
||||||
|
// caching output
|
||||||
|
placement_element current_placement;
|
||||||
|
|
||||||
//helpers
|
//helpers
|
||||||
std::pair<double, double> get_position_at_distance(double target_distance);
|
std::pair<double, double> get_position_at_distance(double target_distance);
|
||||||
|
@ -78,14 +87,18 @@ namespace mapnik
|
||||||
|
|
||||||
int wrap_width;
|
int wrap_width;
|
||||||
int text_ratio;
|
int text_ratio;
|
||||||
|
|
||||||
|
int label_spacing; // distance between repeated labels on a single geometry
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class placement_finder : boost::noncopyable
|
class placement_finder : boost::noncopyable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
placement_finder(Envelope<double> e);
|
placement_finder(Envelope<double> e);
|
||||||
|
|
||||||
bool find_placement(placement *placement);
|
bool find_placements(placement *p);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool find_placement_follow(placement *p);
|
bool find_placement_follow(placement *p);
|
||||||
|
|
|
@ -93,9 +93,9 @@ namespace mapnik
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct text_path : private boost::noncopyable
|
struct text_path
|
||||||
{
|
{
|
||||||
struct character_node : boost::noncopyable
|
struct character_node
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
double x, y, angle;
|
double x, y, angle;
|
||||||
|
@ -112,7 +112,7 @@ namespace mapnik
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef boost::ptr_vector<character_node> character_nodes_t;
|
typedef std::vector<character_node> character_nodes_t;
|
||||||
|
|
||||||
character_nodes_t nodes_;
|
character_nodes_t nodes_;
|
||||||
int itr_;
|
int itr_;
|
||||||
|
@ -120,11 +120,17 @@ namespace mapnik
|
||||||
std::pair<unsigned,unsigned> string_dimensions;
|
std::pair<unsigned,unsigned> string_dimensions;
|
||||||
|
|
||||||
text_path() : itr_(0) {}
|
text_path() : itr_(0) {}
|
||||||
|
text_path(const text_path & other) : itr_(0)
|
||||||
|
{
|
||||||
|
nodes_ = other.nodes_;
|
||||||
|
string_dimensions = other.string_dimensions;
|
||||||
|
}
|
||||||
|
|
||||||
~text_path() {}
|
~text_path() {}
|
||||||
|
|
||||||
void add_node(int c, double x, double y, double angle)
|
void add_node(int c, double x, double y, double angle)
|
||||||
{
|
{
|
||||||
nodes_.push_back(new character_node(c, x, y, angle));
|
nodes_.push_back(character_node(c, x, y, angle));
|
||||||
}
|
}
|
||||||
|
|
||||||
void vertex(int *c, double *x, double *y, double *angle)
|
void vertex(int *c, double *x, double *y, double *angle)
|
||||||
|
|
|
@ -45,8 +45,10 @@ namespace mapnik
|
||||||
std::string const& get_name() const;
|
std::string const& get_name() const;
|
||||||
unsigned get_text_ratio() const; // target ratio for text bounding box in pixels
|
unsigned get_text_ratio() const; // target ratio for text bounding box in pixels
|
||||||
void set_text_ratio(unsigned ratio);
|
void set_text_ratio(unsigned ratio);
|
||||||
unsigned get_wrap_width() const; // target ratio for text bounding box in pixels
|
unsigned get_wrap_width() const; // width to wrap text at, or trigger ratio
|
||||||
void set_wrap_width(unsigned ratio);
|
void set_wrap_width(unsigned ratio);
|
||||||
|
unsigned get_label_spacing() const; // spacing between repeated labels on lines
|
||||||
|
void set_label_spacing(unsigned spacing);
|
||||||
unsigned get_text_size() const;
|
unsigned get_text_size() const;
|
||||||
std::string const& get_face_name() const;
|
std::string const& get_face_name() const;
|
||||||
Color const& get_fill() const;
|
Color const& get_fill() const;
|
||||||
|
@ -66,6 +68,7 @@ namespace mapnik
|
||||||
unsigned size_;
|
unsigned size_;
|
||||||
unsigned text_ratio_;
|
unsigned text_ratio_;
|
||||||
unsigned wrap_width_;
|
unsigned wrap_width_;
|
||||||
|
unsigned label_spacing_;
|
||||||
Color fill_;
|
Color fill_;
|
||||||
Color halo_fill_;
|
Color halo_fill_;
|
||||||
unsigned halo_radius_;
|
unsigned halo_radius_;
|
||||||
|
|
|
@ -346,28 +346,30 @@ namespace mapnik
|
||||||
|
|
||||||
placement text_placement(&info, &t_, &prj_trans, geom, std::pair<double, double>(w, h) );
|
placement text_placement(&info, &t_, &prj_trans, geom, std::pair<double, double>(w, h) );
|
||||||
|
|
||||||
bool found = finder_.find_placement(&text_placement);
|
bool found = finder_.find_placements(&text_placement);
|
||||||
if (!found) {
|
if (!found) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
double x = text_placement.starting_x;
|
|
||||||
double y = text_placement.starting_y;
|
for (unsigned int ii = 0; ii < text_placement.placements.size(); ++ ii)
|
||||||
|
{
|
||||||
|
double x = text_placement.placements[ii].starting_x;
|
||||||
|
double y = text_placement.placements[ii].starting_y;
|
||||||
|
|
||||||
int px=int(floor(x - 0.5 * w));
|
int px=int(floor(x - 0.5 * w));
|
||||||
int py=int(floor(y - 0.5 * h));
|
int py=int(floor(y - 0.5 * h));
|
||||||
|
|
||||||
pixmap_.set_rectangle_alpha(px,py,*data);
|
pixmap_.set_rectangle_alpha(px,py,*data);
|
||||||
|
|
||||||
Envelope<double> dim = ren.prepare_glyphs(&text_placement.path);
|
Envelope<double> dim = ren.prepare_glyphs(&text_placement.placements[ii].path);
|
||||||
|
|
||||||
//If has_placement
|
|
||||||
|
|
||||||
ren.render(x,y);
|
ren.render(x,y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void agg_renderer<T>::process(line_pattern_symbolizer const& sym,
|
void agg_renderer<T>::process(line_pattern_symbolizer const& sym,
|
||||||
|
@ -504,16 +506,19 @@ namespace mapnik
|
||||||
placement text_placement(&info, &t_, &prj_trans, geom, sym.get_label_placement());
|
placement text_placement(&info, &t_, &prj_trans, geom, sym.get_label_placement());
|
||||||
text_placement.text_ratio = sym.get_text_ratio();
|
text_placement.text_ratio = sym.get_text_ratio();
|
||||||
text_placement.wrap_width = sym.get_wrap_width();
|
text_placement.wrap_width = sym.get_wrap_width();
|
||||||
|
text_placement.label_spacing = sym.get_label_spacing();
|
||||||
|
|
||||||
bool found = finder_.find_placement(&text_placement);
|
bool found = finder_.find_placements(&text_placement);
|
||||||
if (!found) {
|
if (!found) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
double x = text_placement.starting_x;
|
for (unsigned int ii = 0; ii < text_placement.placements.size(); ++ ii)
|
||||||
double y = text_placement.starting_y;
|
{
|
||||||
|
double x = text_placement.placements[ii].starting_x;
|
||||||
|
double y = text_placement.placements[ii].starting_y;
|
||||||
|
|
||||||
Envelope<double> dim = ren.prepare_glyphs(&text_placement.path);
|
Envelope<double> dim = ren.prepare_glyphs(&text_placement.placements[ii].path);
|
||||||
|
|
||||||
Envelope<double> text_box(x + dim.minx() ,y - dim.maxy(), x + dim.maxx(),y - dim.miny());
|
Envelope<double> text_box(x + dim.minx() ,y - dim.maxy(), x + dim.maxx(),y - dim.miny());
|
||||||
|
|
||||||
|
@ -527,6 +532,7 @@ namespace mapnik
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template class agg_renderer<Image32>;
|
template class agg_renderer<Image32>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,7 +126,16 @@ namespace mapnik
|
||||||
|
|
||||||
if ( sym.first == "PointSymbolizer")
|
if ( sym.first == "PointSymbolizer")
|
||||||
{
|
{
|
||||||
std::cout << sym.first << "\n";
|
std::string file =
|
||||||
|
sym.second.get<std::string>("<xmlattr>.file");
|
||||||
|
std::string type =
|
||||||
|
sym.second.get<std::string>("<xmlattr>.type");
|
||||||
|
unsigned width =
|
||||||
|
sym.second.get<unsigned>("<xmlattr>.width");
|
||||||
|
unsigned height =
|
||||||
|
sym.second.get<unsigned>("<xmlattr>.height");
|
||||||
|
|
||||||
|
rule.append(point_symbolizer(file,type,width,height));
|
||||||
}
|
}
|
||||||
else if ( sym.first == "LinePatternSymbolizer")
|
else if ( sym.first == "LinePatternSymbolizer")
|
||||||
{
|
{
|
||||||
|
@ -163,6 +172,7 @@ namespace mapnik
|
||||||
{
|
{
|
||||||
text_symbol.set_label_placement(line_placement);
|
text_symbol.set_label_placement(line_placement);
|
||||||
}
|
}
|
||||||
|
|
||||||
// halo fill and radius
|
// halo fill and radius
|
||||||
boost::optional<std::string> halo_fill =
|
boost::optional<std::string> halo_fill =
|
||||||
sym.second.get_optional<std::string>("<xmlattr>.halo_fill");
|
sym.second.get_optional<std::string>("<xmlattr>.halo_fill");
|
||||||
|
@ -195,6 +205,13 @@ namespace mapnik
|
||||||
text_symbol.set_wrap_width(*wrap_width);
|
text_symbol.set_wrap_width(*wrap_width);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// spacing between repeated labels on lines
|
||||||
|
boost::optional<unsigned> spacing =
|
||||||
|
sym.second.get_optional<unsigned>("<xmlattr>.spacing");
|
||||||
|
if (spacing)
|
||||||
|
{
|
||||||
|
text_symbol.set_label_spacing(*spacing);
|
||||||
|
}
|
||||||
rule.append(text_symbol);
|
rule.append(text_symbol);
|
||||||
}
|
}
|
||||||
else if ( sym.first == "ShieldSymbolizer")
|
else if ( sym.first == "ShieldSymbolizer")
|
||||||
|
|
|
@ -41,13 +41,13 @@
|
||||||
namespace mapnik
|
namespace mapnik
|
||||||
{
|
{
|
||||||
placement::placement(string_info *info_, CoordTransform *ctrans_, const proj_transform *proj_trans_, geometry_ptr geom_, std::pair<double, double> dimensions_)
|
placement::placement(string_info *info_, CoordTransform *ctrans_, const proj_transform *proj_trans_, geometry_ptr geom_, std::pair<double, double> dimensions_)
|
||||||
: info(info_), ctrans(ctrans_), proj_trans(proj_trans_), geom(geom_), label_placement(point_placement), dimensions(dimensions_), has_dimensions(true), shape_path(*ctrans_, *geom_, *proj_trans_), total_distance_(-1.0), wrap_width(0), text_ratio(0)
|
: info(info_), ctrans(ctrans_), proj_trans(proj_trans_), geom(geom_), label_placement(point_placement), dimensions(dimensions_), has_dimensions(true), shape_path(*ctrans_, *geom_, *proj_trans_), total_distance_(-1.0), wrap_width(0), text_ratio(0), label_spacing(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
//For text
|
//For text
|
||||||
placement::placement(string_info *info_, CoordTransform *ctrans_, const proj_transform *proj_trans_, geometry_ptr geom_, label_placement_e placement_)
|
placement::placement(string_info *info_, CoordTransform *ctrans_, const proj_transform *proj_trans_, geometry_ptr geom_, label_placement_e placement_)
|
||||||
: info(info_), ctrans(ctrans_), proj_trans(proj_trans_), geom(geom_), label_placement(placement_), has_dimensions(false), shape_path(*ctrans_, *geom_, *proj_trans_), total_distance_(-1.0), wrap_width(0), text_ratio(0)
|
: info(info_), ctrans(ctrans_), proj_trans(proj_trans_), geom(geom_), label_placement(placement_), has_dimensions(false), shape_path(*ctrans_, *geom_, *proj_trans_), total_distance_(-1.0), wrap_width(0), text_ratio(0), label_spacing(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,6 +55,11 @@ namespace mapnik
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned placement::path_size() const
|
||||||
|
{
|
||||||
|
return geom->num_points();
|
||||||
|
}
|
||||||
|
|
||||||
std::pair<double, double> placement::get_position_at_distance(double target_distance)
|
std::pair<double, double> placement::get_position_at_distance(double target_distance)
|
||||||
{
|
{
|
||||||
double old_x, old_y, new_x, new_y;
|
double old_x, old_y, new_x, new_y;
|
||||||
|
@ -136,7 +141,8 @@ namespace mapnik
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool placement_finder::find_placement(placement *p)
|
|
||||||
|
bool placement_finder::find_placements(placement *p)
|
||||||
{
|
{
|
||||||
if (p->label_placement == point_placement)
|
if (p->label_placement == point_placement)
|
||||||
{
|
{
|
||||||
|
@ -156,36 +162,75 @@ namespace mapnik
|
||||||
double string_width = string_dimensions.first;
|
double string_width = string_dimensions.first;
|
||||||
// double string_height = string_dimensions.second;
|
// double string_height = string_dimensions.second;
|
||||||
|
|
||||||
|
|
||||||
|
std::clog << "trying to place string: ";
|
||||||
|
for (unsigned int ii = 0; ii < p->info->num_characters(); ++ii)
|
||||||
|
std::clog << static_cast<char> (p->info->at(ii).character);
|
||||||
|
std::clog << std::endl;
|
||||||
|
|
||||||
double distance = p->get_total_distance();
|
double distance = p->get_total_distance();
|
||||||
|
|
||||||
//~ double delta = string_width/distance;
|
if (string_width > distance)
|
||||||
double delta = distance/100.0;
|
{
|
||||||
|
std::clog << "String longer than segment, bailing" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
for (double i = 0; i < (distance - string_width)/2.0; i += delta)
|
|
||||||
|
int num_labels = 0;
|
||||||
|
if (p->label_spacing)
|
||||||
|
num_labels = static_cast<int> (floor(distance / (p->label_spacing + string_width)));
|
||||||
|
if (num_labels == 0)
|
||||||
|
num_labels = 1;
|
||||||
|
|
||||||
|
double ideal_spacing = distance/num_labels;
|
||||||
|
std::vector<double> ideal_label_distances;
|
||||||
|
for (double label_pos = ideal_spacing/2; label_pos < distance; label_pos += ideal_spacing)
|
||||||
|
ideal_label_distances.push_back(label_pos);
|
||||||
|
|
||||||
|
double delta = distance/100.0;
|
||||||
|
bool FoundPlacement = false;
|
||||||
|
for (std::vector<double>::const_iterator itr = ideal_label_distances.begin(); itr < ideal_label_distances.end(); ++itr)
|
||||||
|
{
|
||||||
|
std::clog << "Trying to find txt placement at distance: " << *itr << std::endl;
|
||||||
|
for (double i = 0; i < ideal_spacing; i += delta)
|
||||||
{
|
{
|
||||||
p->clear_envelopes();
|
p->clear_envelopes();
|
||||||
|
|
||||||
if ( build_path_follow(p, (distance - string_width)/2.0 + i) ) {
|
// check position +- delta for valid placement
|
||||||
|
if ( build_path_follow(p, *itr - string_width/2 + i)) {
|
||||||
update_detector(p);
|
update_detector(p);
|
||||||
return true;
|
FoundPlacement = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
p->clear_envelopes();
|
p->clear_envelopes();
|
||||||
|
if (build_path_follow(p, *itr - string_width/2 - i) ) {
|
||||||
if ( build_path_follow(p, (distance - string_width)/2.0 - i) ) {
|
|
||||||
update_detector(p);
|
update_detector(p);
|
||||||
return true;
|
FoundPlacement = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p->starting_x = 0;
|
if (FoundPlacement)
|
||||||
p->starting_y = 0;
|
std::clog << "Found Placement" << string_width << " " << distance << std::endl;
|
||||||
|
|
||||||
return false;
|
return FoundPlacement;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool placement_finder::find_placement_horizontal(placement *p)
|
bool placement_finder::find_placement_horizontal(placement *p)
|
||||||
{
|
{
|
||||||
|
if (p->path_size() == 1) // point geometry
|
||||||
|
{
|
||||||
|
if ( build_path_horizontal(p, 0) )
|
||||||
|
{
|
||||||
|
update_detector(p);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
double distance = p->get_total_distance();
|
double distance = p->get_total_distance();
|
||||||
//~ double delta = string_width/distance;
|
//~ double delta = string_width/distance;
|
||||||
double delta = distance/100.0;
|
double delta = distance/100.0;
|
||||||
|
@ -206,10 +251,6 @@ namespace mapnik
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p->starting_x = 0;
|
|
||||||
p->starting_y = 0;
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,7 +274,7 @@ namespace mapnik
|
||||||
double angle = 0.0;
|
double angle = 0.0;
|
||||||
int orientation = 0;
|
int orientation = 0;
|
||||||
|
|
||||||
p->path.clear();
|
p->current_placement.path.clear();
|
||||||
|
|
||||||
double x, y;
|
double x, y;
|
||||||
x = y = 0.0;
|
x = y = 0.0;
|
||||||
|
@ -265,8 +306,8 @@ namespace mapnik
|
||||||
distance += segment_length;
|
distance += segment_length;
|
||||||
if (distance > target_distance)
|
if (distance > target_distance)
|
||||||
{
|
{
|
||||||
p->starting_x = new_x - dx*(distance - target_distance)/segment_length;
|
p->current_placement.starting_x = new_x - dx*(distance - target_distance)/segment_length;
|
||||||
p->starting_y = new_y - dy*(distance - target_distance)/segment_length;
|
p->current_placement.starting_y = new_y - dy*(distance - target_distance)/segment_length;
|
||||||
|
|
||||||
angle = atan2(-dy, dx);
|
angle = atan2(-dy, dx);
|
||||||
|
|
||||||
|
@ -288,7 +329,8 @@ namespace mapnik
|
||||||
character_info ci;
|
character_info ci;
|
||||||
unsigned c;
|
unsigned c;
|
||||||
|
|
||||||
while (distance <= 0) {
|
while (distance <= 0)
|
||||||
|
{
|
||||||
double dx, dy;
|
double dx, dy;
|
||||||
|
|
||||||
cur_node++;
|
cur_node++;
|
||||||
|
@ -364,82 +406,21 @@ namespace mapnik
|
||||||
|
|
||||||
p->envelopes.push(e);
|
p->envelopes.push(e);
|
||||||
|
|
||||||
p->path.add_node(c, x - p->starting_x, -y + p->starting_y, (orientation == -1 ? angle + M_PI : angle));
|
p->current_placement.path.add_node(c, x - p->current_placement.starting_x, -y + p->current_placement.starting_y, (orientation == -1 ? angle + M_PI : angle));
|
||||||
|
|
||||||
distance -= ci.width;
|
distance -= ci.width;
|
||||||
}
|
}
|
||||||
|
p->placements.push_back(p->current_placement);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
bool placement_finder::build_path_horizontal(placement *p, double target_distance)
|
bool placement_finder::build_path_horizontal(placement *p, double target_distance)
|
||||||
{
|
{
|
||||||
double x, y;
|
double x, y;
|
||||||
|
|
||||||
p->path.clear();
|
p->current_placement.path.clear();
|
||||||
|
|
||||||
std::pair<double, double> string_dimensions = p->info->get_dimensions();
|
|
||||||
double string_width = string_dimensions.first;
|
|
||||||
double string_height = string_dimensions.second;
|
|
||||||
|
|
||||||
x = -string_width/2.0;
|
|
||||||
y = -string_height/2.0 + 1.0;
|
|
||||||
|
|
||||||
if (p->geom->type() == LineString)
|
|
||||||
{
|
|
||||||
std::pair<double, double> starting_pos = p->get_position_at_distance(target_distance);
|
|
||||||
|
|
||||||
p->starting_x = starting_pos.first;
|
|
||||||
p->starting_y = starting_pos.second;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
p->geom->label_position(&p->starting_x, &p->starting_y);
|
|
||||||
// TODO:
|
|
||||||
// We would only want label position in final 'paper' coords.
|
|
||||||
// Move view and proj transforms to e.g. label_position(x,y,proj_trans,ctrans)?
|
|
||||||
double z=0;
|
|
||||||
p->proj_trans->backward(p->starting_x, p->starting_y, z);
|
|
||||||
p->ctrans->forward(&p->starting_x, &p->starting_y);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (unsigned i = 0; i < p->info->num_characters(); i++)
|
|
||||||
{
|
|
||||||
character_info ci;;
|
|
||||||
ci = p->info->at(i);
|
|
||||||
|
|
||||||
unsigned c = ci.character;
|
|
||||||
|
|
||||||
p->path.add_node(c, x, y, 0.0);
|
|
||||||
|
|
||||||
Envelope<double> e;
|
|
||||||
if (p->has_dimensions)
|
|
||||||
{
|
|
||||||
e.init(p->starting_x - (p->dimensions.first/2.0), p->starting_y - (p->dimensions.second/2.0), p->starting_x + (p->dimensions.first/2.0), p->starting_y + (p->dimensions.second/2.0));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
e.init(p->starting_x + x, p->starting_y - y, p->starting_x + x + ci.width, p->starting_y - y - ci.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!detector_.has_placement(e))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
p->envelopes.push(e);
|
|
||||||
|
|
||||||
x += ci.width;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
bool placement_finder::build_path_horizontal(placement *p, double target_distance)
|
|
||||||
{
|
|
||||||
|
|
||||||
p->path.clear();
|
|
||||||
|
|
||||||
std::pair<double, double> string_dimensions = p->info->get_dimensions();
|
std::pair<double, double> string_dimensions = p->info->get_dimensions();
|
||||||
double string_width = string_dimensions.first;
|
double string_width = string_dimensions.first;
|
||||||
|
@ -471,7 +452,7 @@ namespace mapnik
|
||||||
double word_height = 0;
|
double word_height = 0;
|
||||||
for (unsigned int ii = 0; ii < p->info->num_characters(); ii++)
|
for (unsigned int ii = 0; ii < p->info->num_characters(); ii++)
|
||||||
{
|
{
|
||||||
character_info ci;
|
character_info ci;;
|
||||||
ci = p->info->at(ii);
|
ci = p->info->at(ii);
|
||||||
|
|
||||||
unsigned c = ci.character;
|
unsigned c = ci.character;
|
||||||
|
@ -518,18 +499,18 @@ namespace mapnik
|
||||||
{
|
{
|
||||||
std::pair<double, double> starting_pos = p->get_position_at_distance(target_distance);
|
std::pair<double, double> starting_pos = p->get_position_at_distance(target_distance);
|
||||||
|
|
||||||
p->starting_x = starting_pos.first;
|
p->current_placement.starting_x = starting_pos.first;
|
||||||
p->starting_y = starting_pos.second;
|
p->current_placement.starting_y = starting_pos.second;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
p->geom->label_position(&p->starting_x, &p->starting_y);
|
p->geom->label_position(&p->current_placement.starting_x, &p->current_placement.starting_y);
|
||||||
// TODO:
|
// TODO:
|
||||||
// We would only want label position in final 'paper' coords.
|
// We would only want label position in final 'paper' coords.
|
||||||
// Move view and proj transforms to e.g. label_position(x,y,proj_trans,ctrans)?
|
// Move view and proj transforms to e.g. label_position(x,y,proj_trans,ctrans)?
|
||||||
double z=0;
|
double z=0;
|
||||||
p->proj_trans->backward(p->starting_x, p->starting_y, z);
|
p->proj_trans->backward(p->current_placement.starting_x, p->current_placement.starting_y, z);
|
||||||
p->ctrans->forward(&p->starting_x, &p->starting_y);
|
p->ctrans->forward(&p->current_placement.starting_x, &p->current_placement.starting_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
double line_height = 0;
|
double line_height = 0;
|
||||||
|
@ -537,12 +518,12 @@ namespace mapnik
|
||||||
unsigned int index_to_wrap_at = line_breaks[line_number];
|
unsigned int index_to_wrap_at = line_breaks[line_number];
|
||||||
double line_width = line_widths[line_number];
|
double line_width = line_widths[line_number];
|
||||||
|
|
||||||
double x = -line_width/2.0;
|
x = -line_width/2.0;
|
||||||
double y = -string_height/2.0 + 1.0;
|
y = string_height/2.0;
|
||||||
|
|
||||||
for (unsigned i = 0; i < p->info->num_characters(); i++)
|
for (unsigned i = 0; i < p->info->num_characters(); i++)
|
||||||
{
|
{
|
||||||
character_info ci;
|
character_info ci;;
|
||||||
ci = p->info->at(i);
|
ci = p->info->at(i);
|
||||||
|
|
||||||
unsigned c = ci.character;
|
unsigned c = ci.character;
|
||||||
|
@ -558,22 +539,16 @@ namespace mapnik
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
p->path.add_node(c, x, y, 0.0);
|
p->current_placement.path.add_node(c, x, y, 0.0);
|
||||||
|
|
||||||
Envelope<double> e;
|
Envelope<double> e;
|
||||||
if (p->has_dimensions)
|
if (p->has_dimensions)
|
||||||
{
|
{
|
||||||
e.init(p->starting_x - (p->dimensions.first/2.0),
|
e.init(p->current_placement.starting_x - (p->dimensions.first/2.0), p->current_placement.starting_y - (p->dimensions.second/2.0), p->current_placement.starting_x + (p->dimensions.first/2.0), p->current_placement.starting_y + (p->dimensions.second/2.0));
|
||||||
p->starting_y - (p->dimensions.second/2.0),
|
|
||||||
p->starting_x + (p->dimensions.first/2.0),
|
|
||||||
p->starting_y + (p->dimensions.second/2.0));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
e.init(p->starting_x + x,
|
e.init(p->current_placement.starting_x + x, p->current_placement.starting_y - y, p->current_placement.starting_x + x + ci.width, p->current_placement.starting_y - y - ci.height);
|
||||||
p->starting_y - y,
|
|
||||||
p->starting_x + x + ci.width,
|
|
||||||
p->starting_y - y - ci.height);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!detector_.has_placement(e))
|
if (!detector_.has_placement(e))
|
||||||
|
@ -586,7 +561,9 @@ namespace mapnik
|
||||||
x += ci.width;
|
x += ci.width;
|
||||||
line_height = line_height > ci.height ? line_height : ci.height;
|
line_height = line_height > ci.height ? line_height : ci.height;
|
||||||
}
|
}
|
||||||
|
p->placements.push_back(p->current_placement);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
|
@ -35,6 +35,7 @@ namespace mapnik
|
||||||
size_(size),
|
size_(size),
|
||||||
text_ratio_(0),
|
text_ratio_(0),
|
||||||
wrap_width_(0),
|
wrap_width_(0),
|
||||||
|
label_spacing_(0),
|
||||||
fill_(fill),
|
fill_(fill),
|
||||||
halo_fill_(Color(255,255,255)),
|
halo_fill_(Color(255,255,255)),
|
||||||
halo_radius_(0),
|
halo_radius_(0),
|
||||||
|
@ -48,6 +49,7 @@ namespace mapnik
|
||||||
size_(rhs.size_),
|
size_(rhs.size_),
|
||||||
text_ratio_(rhs.text_ratio_),
|
text_ratio_(rhs.text_ratio_),
|
||||||
wrap_width_(rhs.wrap_width_),
|
wrap_width_(rhs.wrap_width_),
|
||||||
|
label_spacing_(rhs.label_spacing_),
|
||||||
fill_(rhs.fill_),
|
fill_(rhs.fill_),
|
||||||
halo_fill_(rhs.halo_fill_),
|
halo_fill_(rhs.halo_fill_),
|
||||||
halo_radius_(rhs.halo_radius_),
|
halo_radius_(rhs.halo_radius_),
|
||||||
|
@ -64,6 +66,7 @@ namespace mapnik
|
||||||
size_ = other.size_;
|
size_ = other.size_;
|
||||||
text_ratio_ = other.text_ratio_;
|
text_ratio_ = other.text_ratio_;
|
||||||
wrap_width_ = other.wrap_width_;
|
wrap_width_ = other.wrap_width_;
|
||||||
|
label_spacing_ = other.label_spacing_;
|
||||||
fill_ = other.fill_;
|
fill_ = other.fill_;
|
||||||
halo_fill_ = other.halo_fill_;
|
halo_fill_ = other.halo_fill_;
|
||||||
halo_radius_ = other.halo_radius_;
|
halo_radius_ = other.halo_radius_;
|
||||||
|
@ -103,6 +106,16 @@ namespace mapnik
|
||||||
wrap_width_ = width;
|
wrap_width_ = width;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned text_symbolizer::get_label_spacing() const
|
||||||
|
{
|
||||||
|
return label_spacing_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void text_symbolizer::set_label_spacing(unsigned spacing)
|
||||||
|
{
|
||||||
|
label_spacing_ = spacing;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned text_symbolizer::get_text_size() const
|
unsigned text_symbolizer::get_text_size() const
|
||||||
{
|
{
|
||||||
return size_;
|
return size_;
|
||||||
|
|
Loading…
Reference in a new issue