Make line placement retry if it places >= 50% of the characters upside down.
This commit is contained in:
parent
3d9024ddc4
commit
1d556b54fd
2 changed files with 43 additions and 3 deletions
|
@ -112,7 +112,10 @@ namespace mapnik
|
|||
//index: index of the node the current line ends on
|
||||
//distance: distance along the given index that the placement should start at, this includes the offset,
|
||||
// as such it may be > or < the length of the current line, so this must be checked for
|
||||
//orientation: 1/-1 depending which way up the string ends up being, set in get_placement_offset
|
||||
//orientation: if set to != 0 the placement will be attempted with the given orientation
|
||||
// otherwise it will autodetect the orientation.
|
||||
// If >= 50% of the characters end up upside down, it will be retried the other way.
|
||||
// RETURN: 1/-1 depending which way up the string ends up being.
|
||||
std::auto_ptr<placement_element> get_placement_offset(placement & p, const std::vector<vertex2d> & path_positions, const std::vector<double> & path_distances, int & orientation, unsigned index, double distance);
|
||||
|
||||
///Tests wether the given placement_element be placed without a collision
|
||||
|
|
|
@ -562,6 +562,10 @@ namespace mapnik
|
|||
if (index >= path_distances.size())
|
||||
return std::auto_ptr<placement_element>(NULL);
|
||||
|
||||
//Keep track of the initial index,distance incase we need to re-call get_placement_offset
|
||||
const unsigned initial_index = index;
|
||||
const double initial_distance = distance;
|
||||
|
||||
std::auto_ptr<placement_element> current_placement(new placement_element);
|
||||
|
||||
double string_height = p.info.get_dimensions().second;
|
||||
|
@ -578,10 +582,16 @@ namespace mapnik
|
|||
|
||||
current_placement->starting_x = old_x + dx*distance/segment_length;
|
||||
current_placement->starting_y = old_y + dy*distance/segment_length;
|
||||
|
||||
double angle = atan2(-dy, dx);
|
||||
orientation = (angle > 0.55*M_PI || angle < -0.45*M_PI) ? -1 : 1;
|
||||
|
||||
bool orientation_forced = (orientation != 0); //Wether the orientation was set by the caller
|
||||
if (!orientation_forced)
|
||||
orientation = (angle > 0.55*M_PI || angle < -0.45*M_PI) ? -1 : 1;
|
||||
|
||||
unsigned upside_down_char_count = 0; //Count of characters that are placed upside down.
|
||||
|
||||
std::clog << "Starting @ " << current_placement->starting_x << ", " << current_placement->starting_y << " @ " << angle << " OR: " << orientation << std::endl;
|
||||
|
||||
for (unsigned i = 0; i < p.info.num_characters(); ++i)
|
||||
{
|
||||
character_info ci;
|
||||
|
@ -679,6 +689,33 @@ namespace mapnik
|
|||
current_placement->add_node(c,render_x - current_placement->starting_x,
|
||||
-render_y + current_placement->starting_y,
|
||||
render_angle);
|
||||
|
||||
//Normalise to 0 <= angle < 2PI
|
||||
while (render_angle >= 2*M_PI)
|
||||
render_angle -= 2*M_PI;
|
||||
while (render_angle < 0)
|
||||
render_angle += 2*M_PI;
|
||||
|
||||
if (render_angle > M_PI/2 && render_angle < 1.5*M_PI)
|
||||
upside_down_char_count++;
|
||||
std::clog << "Rendering angle: " << render_angle << std::endl;
|
||||
}
|
||||
|
||||
//If we placed too many characters upside down
|
||||
if (upside_down_char_count >= p.info.num_characters()/2)
|
||||
{
|
||||
//if we auto-detected the orientation then retry with the opposite orientation
|
||||
if (!orientation_forced)
|
||||
{
|
||||
orientation = -orientation;
|
||||
current_placement = get_placement_offset(p, path_positions, path_distances, orientation, initial_index, initial_distance);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Otherwise we have failed to find a placement
|
||||
std::clog << "FAIL: Double upside-down!" << std::endl;
|
||||
return std::auto_ptr<placement_element>(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return current_placement;
|
||||
|
|
Loading…
Reference in a new issue