2006-10-17 16:12:53 +02:00
|
|
|
/*****************************************************************************
|
Patch from David Eastcott :
1. Modified Text Symbolizer
a) corrected line fragment centering (for 2nd and subsequent lines, when line breaks occur).
b) adjusted vertical alignment calculation so that:
i) middle -> has the center of the text line(s) at the point origin
ii) bottom -> has the text line(s) below the point origin
iii) top -> has the text line(s) above the point origin
c) added new text_symbolizer attribute: 'wrap_before', value range: true/false, default == false
allows line breaks at first wrap_char before wrap_width as an alternative to the original
which was to create the line break at the first wrap_char after wrap_width
d) added new text_symbolizer attribute: 'horizontal_alignment', value range: left/middle/right, default == middle
i) left -> has all text line(s) to left of the point origin
ii) middle -> has all text line(s) centered on the the point origin
iii) right -> has all text line(s) to the right of the point origin
NOTE: dx, dy position adjustments are applied after alignments and before Justify.
e) added new text_symbolizer attribute: 'justify_alignment', value range: left/middle/right, default == middle
i) left -> after alignments, has all text line(s) are left justified (left to right reading)
ii) middle -> after alignments, has all text line(s) center justified
iii) right -> after alignments, has all text line(s) right justified (right to left reading)
f) added new text_symbolizer attribute: 'opacity', value range: 0.0 thru 1.0; 1.0 == fully opaque
g) modified positioning to compensate for both line_spacing and character_spacing, to ensure proper
centering of the text envelope. Also ensure that centering occurs correctly even if no wrapping
occurs. Line spacing is uniform and consistent and compensates for errors between text_size and
the actual size (ci.height is inconsistent, depending on case and character); fixes issue with
multi-line text where some lines have a slight gap and others are compressed together.
2. Modified shield_symbolizer
a) added the attributes:
i) allow_overlap
ii) vertical_alignment
iii) horizontal_alignment
iv) justify_alignment
v) wrap_width
vi) wrap_character
vii) wrap_before
viii) text_convert
ix) line_spacing
x) character_spacing
xi) opacity
b) added new shield_symbolizer attribute: 'unlock_image', value range: true/false, default == false
i) false == image and text placement behaviour same as before
ii) true == image placement independant of text, image is always centered at geometry point, text placed per attributes,
dx/dy only affect text.
Allows user to create point markers with text, but both the text and image rendering collision detection are done
as a pair (they come and go together - solves problem if using point_symbolizer and text_symbolizers where one or the
other are omitted due to overlaps, but not both)
c) extended choices for the attribute 'placement' to include vertex; effect is limited to the shield_symbolizer
Allows an attempted placement at every vertex available, gives additional shield placement volume when using line geometry
d) ensured that the text placement was not updating the detector unless a shield image was actually placed.
e) added new shield_symbolizer attribute: 'no_text', value range: true/false, default = false
When set true, the text for the feature is ignored ('space' subsituted) so that pure graphic symbols can be used
and no text is rendered over top of them.
2009-10-19 15:52:53 +02:00
|
|
|
*
|
2006-10-17 16:12:53 +02:00
|
|
|
* This file is part of Mapnik (c++ mapping toolkit)
|
|
|
|
*
|
2011-10-23 15:04:25 +02:00
|
|
|
* Copyright (C) 2011 Artem Pavlenko
|
2006-10-17 16:12:53 +02:00
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
*
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
//$Id$
|
|
|
|
|
2007-10-08 19:42:41 +02:00
|
|
|
//mapnik
|
|
|
|
#include <mapnik/placement_finder.hpp>
|
|
|
|
#include <mapnik/geometry.hpp>
|
|
|
|
#include <mapnik/text_path.hpp>
|
2012-01-22 18:41:04 +01:00
|
|
|
#include <mapnik/label_collision_detector.hpp>
|
2011-09-08 05:47:56 +02:00
|
|
|
#include <mapnik/fastmath.hpp>
|
2007-11-02 13:50:15 +01:00
|
|
|
|
|
|
|
// agg
|
|
|
|
#include "agg_path_length.h"
|
|
|
|
#include "agg_conv_clip_polyline.h"
|
2006-10-17 16:12:53 +02:00
|
|
|
|
|
|
|
// boost
|
|
|
|
#include <boost/shared_ptr.hpp>
|
|
|
|
#include <boost/utility.hpp>
|
|
|
|
#include <boost/ptr_container/ptr_vector.hpp>
|
2007-02-09 17:32:44 +01:00
|
|
|
#include <boost/tuple/tuple.hpp>
|
2011-10-12 02:02:28 +02:00
|
|
|
#include <boost/foreach.hpp>
|
2006-10-17 16:12:53 +02:00
|
|
|
|
2007-10-08 19:42:41 +02:00
|
|
|
//stl
|
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
2006-10-17 16:12:53 +02:00
|
|
|
|
2006-11-28 11:38:56 +01:00
|
|
|
#ifndef M_PI
|
|
|
|
#define M_PI 3.14159265358979323846
|
|
|
|
#endif
|
|
|
|
|
2006-10-17 16:12:53 +02:00
|
|
|
namespace mapnik
|
|
|
|
{
|
Patch from David Eastcott :
1. Modified Text Symbolizer
a) corrected line fragment centering (for 2nd and subsequent lines, when line breaks occur).
b) adjusted vertical alignment calculation so that:
i) middle -> has the center of the text line(s) at the point origin
ii) bottom -> has the text line(s) below the point origin
iii) top -> has the text line(s) above the point origin
c) added new text_symbolizer attribute: 'wrap_before', value range: true/false, default == false
allows line breaks at first wrap_char before wrap_width as an alternative to the original
which was to create the line break at the first wrap_char after wrap_width
d) added new text_symbolizer attribute: 'horizontal_alignment', value range: left/middle/right, default == middle
i) left -> has all text line(s) to left of the point origin
ii) middle -> has all text line(s) centered on the the point origin
iii) right -> has all text line(s) to the right of the point origin
NOTE: dx, dy position adjustments are applied after alignments and before Justify.
e) added new text_symbolizer attribute: 'justify_alignment', value range: left/middle/right, default == middle
i) left -> after alignments, has all text line(s) are left justified (left to right reading)
ii) middle -> after alignments, has all text line(s) center justified
iii) right -> after alignments, has all text line(s) right justified (right to left reading)
f) added new text_symbolizer attribute: 'opacity', value range: 0.0 thru 1.0; 1.0 == fully opaque
g) modified positioning to compensate for both line_spacing and character_spacing, to ensure proper
centering of the text envelope. Also ensure that centering occurs correctly even if no wrapping
occurs. Line spacing is uniform and consistent and compensates for errors between text_size and
the actual size (ci.height is inconsistent, depending on case and character); fixes issue with
multi-line text where some lines have a slight gap and others are compressed together.
2. Modified shield_symbolizer
a) added the attributes:
i) allow_overlap
ii) vertical_alignment
iii) horizontal_alignment
iv) justify_alignment
v) wrap_width
vi) wrap_character
vii) wrap_before
viii) text_convert
ix) line_spacing
x) character_spacing
xi) opacity
b) added new shield_symbolizer attribute: 'unlock_image', value range: true/false, default == false
i) false == image and text placement behaviour same as before
ii) true == image placement independant of text, image is always centered at geometry point, text placed per attributes,
dx/dy only affect text.
Allows user to create point markers with text, but both the text and image rendering collision detection are done
as a pair (they come and go together - solves problem if using point_symbolizer and text_symbolizers where one or the
other are omitted due to overlaps, but not both)
c) extended choices for the attribute 'placement' to include vertex; effect is limited to the shield_symbolizer
Allows an attempted placement at every vertex available, gives additional shield placement volume when using line geometry
d) ensured that the text placement was not updating the detector unless a shield image was actually placed.
e) added new shield_symbolizer attribute: 'no_text', value range: true/false, default = false
When set true, the text for the feature is ignored ('space' subsituted) so that pure graphic symbols can be used
and no text is rendered over top of them.
2009-10-19 15:52:53 +02:00
|
|
|
|
2010-05-27 12:19:47 +02:00
|
|
|
template<typename T>
|
|
|
|
std::pair<double, double> get_position_at_distance(double target_distance, T & shape_path)
|
|
|
|
{
|
|
|
|
double x1 = 0.0;
|
|
|
|
double y1 = 0.0;
|
|
|
|
double x2 = 0.0;
|
|
|
|
double y2 = 0.0;
|
|
|
|
double distance = 0.0;
|
|
|
|
bool first = true;
|
|
|
|
unsigned cmd;
|
|
|
|
double x = 0.0;
|
|
|
|
double y = 0.0;
|
|
|
|
shape_path.rewind(0);
|
|
|
|
while (!agg::is_stop(cmd = shape_path.vertex(&x2,&y2)))
|
|
|
|
{
|
2010-06-02 13:03:30 +02:00
|
|
|
if (first || agg::is_move_to(cmd))
|
|
|
|
{
|
2007-11-02 13:50:15 +01:00
|
|
|
first = false;
|
2010-06-02 13:03:30 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-11-02 13:50:15 +01:00
|
|
|
double dx = x2-x1;
|
|
|
|
double dy = y2-y1;
|
Patch from David Eastcott :
1. Modified Text Symbolizer
a) corrected line fragment centering (for 2nd and subsequent lines, when line breaks occur).
b) adjusted vertical alignment calculation so that:
i) middle -> has the center of the text line(s) at the point origin
ii) bottom -> has the text line(s) below the point origin
iii) top -> has the text line(s) above the point origin
c) added new text_symbolizer attribute: 'wrap_before', value range: true/false, default == false
allows line breaks at first wrap_char before wrap_width as an alternative to the original
which was to create the line break at the first wrap_char after wrap_width
d) added new text_symbolizer attribute: 'horizontal_alignment', value range: left/middle/right, default == middle
i) left -> has all text line(s) to left of the point origin
ii) middle -> has all text line(s) centered on the the point origin
iii) right -> has all text line(s) to the right of the point origin
NOTE: dx, dy position adjustments are applied after alignments and before Justify.
e) added new text_symbolizer attribute: 'justify_alignment', value range: left/middle/right, default == middle
i) left -> after alignments, has all text line(s) are left justified (left to right reading)
ii) middle -> after alignments, has all text line(s) center justified
iii) right -> after alignments, has all text line(s) right justified (right to left reading)
f) added new text_symbolizer attribute: 'opacity', value range: 0.0 thru 1.0; 1.0 == fully opaque
g) modified positioning to compensate for both line_spacing and character_spacing, to ensure proper
centering of the text envelope. Also ensure that centering occurs correctly even if no wrapping
occurs. Line spacing is uniform and consistent and compensates for errors between text_size and
the actual size (ci.height is inconsistent, depending on case and character); fixes issue with
multi-line text where some lines have a slight gap and others are compressed together.
2. Modified shield_symbolizer
a) added the attributes:
i) allow_overlap
ii) vertical_alignment
iii) horizontal_alignment
iv) justify_alignment
v) wrap_width
vi) wrap_character
vii) wrap_before
viii) text_convert
ix) line_spacing
x) character_spacing
xi) opacity
b) added new shield_symbolizer attribute: 'unlock_image', value range: true/false, default == false
i) false == image and text placement behaviour same as before
ii) true == image placement independant of text, image is always centered at geometry point, text placed per attributes,
dx/dy only affect text.
Allows user to create point markers with text, but both the text and image rendering collision detection are done
as a pair (they come and go together - solves problem if using point_symbolizer and text_symbolizers where one or the
other are omitted due to overlaps, but not both)
c) extended choices for the attribute 'placement' to include vertex; effect is limited to the shield_symbolizer
Allows an attempted placement at every vertex available, gives additional shield placement volume when using line geometry
d) ensured that the text placement was not updating the detector unless a shield image was actually placed.
e) added new shield_symbolizer attribute: 'no_text', value range: true/false, default = false
When set true, the text for the feature is ignored ('space' subsituted) so that pure graphic symbols can be used
and no text is rendered over top of them.
2009-10-19 15:52:53 +02:00
|
|
|
|
2009-06-03 07:26:46 +02:00
|
|
|
double segment_length = std::sqrt(dx*dx + dy*dy);
|
2007-11-02 13:50:15 +01:00
|
|
|
distance +=segment_length;
|
Patch from David Eastcott :
1. Modified Text Symbolizer
a) corrected line fragment centering (for 2nd and subsequent lines, when line breaks occur).
b) adjusted vertical alignment calculation so that:
i) middle -> has the center of the text line(s) at the point origin
ii) bottom -> has the text line(s) below the point origin
iii) top -> has the text line(s) above the point origin
c) added new text_symbolizer attribute: 'wrap_before', value range: true/false, default == false
allows line breaks at first wrap_char before wrap_width as an alternative to the original
which was to create the line break at the first wrap_char after wrap_width
d) added new text_symbolizer attribute: 'horizontal_alignment', value range: left/middle/right, default == middle
i) left -> has all text line(s) to left of the point origin
ii) middle -> has all text line(s) centered on the the point origin
iii) right -> has all text line(s) to the right of the point origin
NOTE: dx, dy position adjustments are applied after alignments and before Justify.
e) added new text_symbolizer attribute: 'justify_alignment', value range: left/middle/right, default == middle
i) left -> after alignments, has all text line(s) are left justified (left to right reading)
ii) middle -> after alignments, has all text line(s) center justified
iii) right -> after alignments, has all text line(s) right justified (right to left reading)
f) added new text_symbolizer attribute: 'opacity', value range: 0.0 thru 1.0; 1.0 == fully opaque
g) modified positioning to compensate for both line_spacing and character_spacing, to ensure proper
centering of the text envelope. Also ensure that centering occurs correctly even if no wrapping
occurs. Line spacing is uniform and consistent and compensates for errors between text_size and
the actual size (ci.height is inconsistent, depending on case and character); fixes issue with
multi-line text where some lines have a slight gap and others are compressed together.
2. Modified shield_symbolizer
a) added the attributes:
i) allow_overlap
ii) vertical_alignment
iii) horizontal_alignment
iv) justify_alignment
v) wrap_width
vi) wrap_character
vii) wrap_before
viii) text_convert
ix) line_spacing
x) character_spacing
xi) opacity
b) added new shield_symbolizer attribute: 'unlock_image', value range: true/false, default == false
i) false == image and text placement behaviour same as before
ii) true == image placement independant of text, image is always centered at geometry point, text placed per attributes,
dx/dy only affect text.
Allows user to create point markers with text, but both the text and image rendering collision detection are done
as a pair (they come and go together - solves problem if using point_symbolizer and text_symbolizers where one or the
other are omitted due to overlaps, but not both)
c) extended choices for the attribute 'placement' to include vertex; effect is limited to the shield_symbolizer
Allows an attempted placement at every vertex available, gives additional shield placement volume when using line geometry
d) ensured that the text placement was not updating the detector unless a shield image was actually placed.
e) added new shield_symbolizer attribute: 'no_text', value range: true/false, default = false
When set true, the text for the feature is ignored ('space' subsituted) so that pure graphic symbols can be used
and no text is rendered over top of them.
2009-10-19 15:52:53 +02:00
|
|
|
|
2007-11-02 13:50:15 +01:00
|
|
|
if (distance > target_distance)
|
|
|
|
{
|
2010-06-02 13:03:30 +02:00
|
|
|
x = x2 - dx * (distance - target_distance)/segment_length;
|
|
|
|
y = y2 - dy * (distance - target_distance)/segment_length;
|
|
|
|
break;
|
2007-11-02 13:50:15 +01:00
|
|
|
}
|
2010-06-02 13:03:30 +02:00
|
|
|
}
|
|
|
|
x1 = x2;
|
|
|
|
y1 = y2;
|
2010-05-27 12:19:47 +02:00
|
|
|
}
|
|
|
|
return std::pair<double, double>(x, y);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
double get_total_distance(T & shape_path)
|
|
|
|
{
|
|
|
|
return agg::path_length(shape_path);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename DetectorT>
|
2012-01-22 18:41:04 +01:00
|
|
|
placement_finder<DetectorT>::placement_finder(text_placement_info &placement_info, string_info &info, DetectorT & detector)
|
2010-05-27 12:19:47 +02:00
|
|
|
: detector_(detector),
|
2012-01-22 18:41:04 +01:00
|
|
|
dimensions_(detector_.extent()),
|
|
|
|
info_(info), p(placement_info.properties), pi(placement_info), string_width_(0), string_height_(0), first_line_space_(0), valign_(V_AUTO), halign_(H_AUTO), line_breaks_(), line_sizes_()
|
2010-05-27 12:19:47 +02:00
|
|
|
{
|
2012-01-29 04:49:02 +01:00
|
|
|
placement_info.placements.clear(); //Remove left overs
|
2010-05-27 12:19:47 +02:00
|
|
|
}
|
|
|
|
|
2010-11-22 12:25:36 +01:00
|
|
|
template <typename DetectorT>
|
2012-01-22 18:41:04 +01:00
|
|
|
placement_finder<DetectorT>::placement_finder(text_placement_info &placement_info, string_info &info, DetectorT & detector, box2d<double> const& extent)
|
2010-11-22 12:25:36 +01:00
|
|
|
: detector_(detector),
|
2012-01-22 18:41:04 +01:00
|
|
|
dimensions_(extent),
|
|
|
|
info_(info), p(placement_info.properties), pi(placement_info), string_width_(0), string_height_(0), first_line_space_(0), valign_(V_AUTO), halign_(H_AUTO), line_breaks_(), line_sizes_()
|
2010-11-22 12:25:36 +01:00
|
|
|
{
|
2012-01-29 04:49:02 +01:00
|
|
|
placement_info.placements.clear(); //Remove left overs
|
2010-11-22 12:25:36 +01:00
|
|
|
}
|
|
|
|
|
2010-05-27 12:19:47 +02:00
|
|
|
template <typename DetectorT>
|
|
|
|
template <typename T>
|
2012-01-22 18:41:04 +01:00
|
|
|
void placement_finder<DetectorT>::find_point_placements(T & shape_path)
|
2010-05-27 12:19:47 +02:00
|
|
|
{
|
|
|
|
unsigned cmd;
|
|
|
|
double new_x = 0.0;
|
|
|
|
double new_y = 0.0;
|
|
|
|
double old_x = 0.0;
|
|
|
|
double old_y = 0.0;
|
|
|
|
bool first = true;
|
|
|
|
|
|
|
|
double total_distance = get_total_distance<T>(shape_path);
|
|
|
|
shape_path.rewind(0);
|
|
|
|
|
|
|
|
if (distance == 0) //Point data, not a line
|
|
|
|
{
|
2010-06-02 13:03:30 +02:00
|
|
|
double x, y;
|
|
|
|
shape_path.vertex(&x,&y);
|
2012-01-22 18:41:04 +01:00
|
|
|
find_point_placement(x, y);
|
2010-06-02 13:03:30 +02:00
|
|
|
return;
|
2010-05-27 12:19:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
int num_labels = 1;
|
|
|
|
if (p.label_spacing > 0)
|
2012-01-22 18:41:04 +01:00
|
|
|
num_labels = static_cast<int> (floor(total_distance / pi.get_actual_label_spacing()));
|
2010-05-27 12:19:47 +02:00
|
|
|
|
2012-01-22 18:41:04 +01:00
|
|
|
if (p.force_odd_labels && num_labels % 2 == 0)
|
2010-06-02 13:03:30 +02:00
|
|
|
num_labels--;
|
2010-05-27 12:19:47 +02:00
|
|
|
if (num_labels <= 0)
|
2010-06-02 13:03:30 +02:00
|
|
|
num_labels = 1;
|
2010-05-27 12:19:47 +02:00
|
|
|
|
|
|
|
double distance = 0.0; // distance from last label
|
|
|
|
double spacing = total_distance / num_labels;
|
|
|
|
double target_distance = spacing / 2; // first label should be placed at half the spacing
|
|
|
|
|
|
|
|
while (!agg::is_stop(cmd = shape_path.vertex(&new_x,&new_y))) //For each node in the shape
|
|
|
|
{
|
|
|
|
|
2010-06-02 13:03:30 +02:00
|
|
|
if (first || agg::is_move_to(cmd)) //Don't do any processing if it is the first node
|
|
|
|
{
|
2008-01-24 02:16:14 +01:00
|
|
|
first = false;
|
2010-06-02 13:03:30 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-01-24 02:16:14 +01:00
|
|
|
//Add the length of this segment to the total we have saved up
|
2009-06-03 07:26:46 +02:00
|
|
|
double segment_length = std::sqrt(std::pow(old_x-new_x,2) + std::pow(old_y-new_y,2)); //Pythagoras
|
2008-01-24 02:16:14 +01:00
|
|
|
distance += segment_length;
|
Patch from David Eastcott :
1. Modified Text Symbolizer
a) corrected line fragment centering (for 2nd and subsequent lines, when line breaks occur).
b) adjusted vertical alignment calculation so that:
i) middle -> has the center of the text line(s) at the point origin
ii) bottom -> has the text line(s) below the point origin
iii) top -> has the text line(s) above the point origin
c) added new text_symbolizer attribute: 'wrap_before', value range: true/false, default == false
allows line breaks at first wrap_char before wrap_width as an alternative to the original
which was to create the line break at the first wrap_char after wrap_width
d) added new text_symbolizer attribute: 'horizontal_alignment', value range: left/middle/right, default == middle
i) left -> has all text line(s) to left of the point origin
ii) middle -> has all text line(s) centered on the the point origin
iii) right -> has all text line(s) to the right of the point origin
NOTE: dx, dy position adjustments are applied after alignments and before Justify.
e) added new text_symbolizer attribute: 'justify_alignment', value range: left/middle/right, default == middle
i) left -> after alignments, has all text line(s) are left justified (left to right reading)
ii) middle -> after alignments, has all text line(s) center justified
iii) right -> after alignments, has all text line(s) right justified (right to left reading)
f) added new text_symbolizer attribute: 'opacity', value range: 0.0 thru 1.0; 1.0 == fully opaque
g) modified positioning to compensate for both line_spacing and character_spacing, to ensure proper
centering of the text envelope. Also ensure that centering occurs correctly even if no wrapping
occurs. Line spacing is uniform and consistent and compensates for errors between text_size and
the actual size (ci.height is inconsistent, depending on case and character); fixes issue with
multi-line text where some lines have a slight gap and others are compressed together.
2. Modified shield_symbolizer
a) added the attributes:
i) allow_overlap
ii) vertical_alignment
iii) horizontal_alignment
iv) justify_alignment
v) wrap_width
vi) wrap_character
vii) wrap_before
viii) text_convert
ix) line_spacing
x) character_spacing
xi) opacity
b) added new shield_symbolizer attribute: 'unlock_image', value range: true/false, default == false
i) false == image and text placement behaviour same as before
ii) true == image placement independant of text, image is always centered at geometry point, text placed per attributes,
dx/dy only affect text.
Allows user to create point markers with text, but both the text and image rendering collision detection are done
as a pair (they come and go together - solves problem if using point_symbolizer and text_symbolizers where one or the
other are omitted due to overlaps, but not both)
c) extended choices for the attribute 'placement' to include vertex; effect is limited to the shield_symbolizer
Allows an attempted placement at every vertex available, gives additional shield placement volume when using line geometry
d) ensured that the text placement was not updating the detector unless a shield image was actually placed.
e) added new shield_symbolizer attribute: 'no_text', value range: true/false, default = false
When set true, the text for the feature is ignored ('space' subsituted) so that pure graphic symbols can be used
and no text is rendered over top of them.
2009-10-19 15:52:53 +02:00
|
|
|
|
2008-01-24 02:16:14 +01:00
|
|
|
//While we have enough distance to place text in
|
|
|
|
while (distance > target_distance)
|
|
|
|
{
|
2010-06-02 13:03:30 +02:00
|
|
|
//Try place at the specified place
|
|
|
|
double new_weight = (segment_length - (distance - target_distance))/segment_length;
|
2012-01-22 18:41:04 +01:00
|
|
|
find_point_placement(old_x + (new_x-old_x)*new_weight, old_y + (new_y-old_y)*new_weight);
|
Patch from David Eastcott :
1. Modified Text Symbolizer
a) corrected line fragment centering (for 2nd and subsequent lines, when line breaks occur).
b) adjusted vertical alignment calculation so that:
i) middle -> has the center of the text line(s) at the point origin
ii) bottom -> has the text line(s) below the point origin
iii) top -> has the text line(s) above the point origin
c) added new text_symbolizer attribute: 'wrap_before', value range: true/false, default == false
allows line breaks at first wrap_char before wrap_width as an alternative to the original
which was to create the line break at the first wrap_char after wrap_width
d) added new text_symbolizer attribute: 'horizontal_alignment', value range: left/middle/right, default == middle
i) left -> has all text line(s) to left of the point origin
ii) middle -> has all text line(s) centered on the the point origin
iii) right -> has all text line(s) to the right of the point origin
NOTE: dx, dy position adjustments are applied after alignments and before Justify.
e) added new text_symbolizer attribute: 'justify_alignment', value range: left/middle/right, default == middle
i) left -> after alignments, has all text line(s) are left justified (left to right reading)
ii) middle -> after alignments, has all text line(s) center justified
iii) right -> after alignments, has all text line(s) right justified (right to left reading)
f) added new text_symbolizer attribute: 'opacity', value range: 0.0 thru 1.0; 1.0 == fully opaque
g) modified positioning to compensate for both line_spacing and character_spacing, to ensure proper
centering of the text envelope. Also ensure that centering occurs correctly even if no wrapping
occurs. Line spacing is uniform and consistent and compensates for errors between text_size and
the actual size (ci.height is inconsistent, depending on case and character); fixes issue with
multi-line text where some lines have a slight gap and others are compressed together.
2. Modified shield_symbolizer
a) added the attributes:
i) allow_overlap
ii) vertical_alignment
iii) horizontal_alignment
iv) justify_alignment
v) wrap_width
vi) wrap_character
vii) wrap_before
viii) text_convert
ix) line_spacing
x) character_spacing
xi) opacity
b) added new shield_symbolizer attribute: 'unlock_image', value range: true/false, default == false
i) false == image and text placement behaviour same as before
ii) true == image placement independant of text, image is always centered at geometry point, text placed per attributes,
dx/dy only affect text.
Allows user to create point markers with text, but both the text and image rendering collision detection are done
as a pair (they come and go together - solves problem if using point_symbolizer and text_symbolizers where one or the
other are omitted due to overlaps, but not both)
c) extended choices for the attribute 'placement' to include vertex; effect is limited to the shield_symbolizer
Allows an attempted placement at every vertex available, gives additional shield placement volume when using line geometry
d) ensured that the text placement was not updating the detector unless a shield image was actually placed.
e) added new shield_symbolizer attribute: 'no_text', value range: true/false, default = false
When set true, the text for the feature is ignored ('space' subsituted) so that pure graphic symbols can be used
and no text is rendered over top of them.
2009-10-19 15:52:53 +02:00
|
|
|
|
2010-06-02 13:03:30 +02:00
|
|
|
distance -= target_distance; //Consume the spacing gap we have used up
|
|
|
|
target_distance = spacing; //Need to reset the target_distance as it is spacing/2 for the first label.
|
2008-01-24 02:16:14 +01:00
|
|
|
}
|
2010-06-02 13:03:30 +02:00
|
|
|
}
|
2010-05-27 12:19:47 +02:00
|
|
|
|
2010-06-02 13:03:30 +02:00
|
|
|
old_x = new_x;
|
|
|
|
old_y = new_y;
|
2010-05-27 12:19:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename DetectorT>
|
2012-01-22 18:41:04 +01:00
|
|
|
void placement_finder<DetectorT>::init_string_size()
|
2010-05-27 12:19:47 +02:00
|
|
|
{
|
2012-01-22 18:41:04 +01:00
|
|
|
// Get total string size
|
|
|
|
string_width_ = 0;
|
|
|
|
string_height_ = 0;
|
|
|
|
first_line_space_ = 0;
|
|
|
|
if (!info_.num_characters()) return; //At least one character is required
|
|
|
|
for (unsigned i = 0; i < info_.num_characters(); i++)
|
|
|
|
{
|
|
|
|
char_info const& ci = info_.at(i);
|
|
|
|
if (!ci.width || !ci.line_height) continue; //Skip empty chars (add no character_spacing for them)
|
|
|
|
string_width_ += ci.width + ci.format->character_spacing;
|
|
|
|
string_height_ = std::max(string_height_, ci.line_height+ci.format->line_spacing);
|
|
|
|
first_line_space_ = std::max(first_line_space_, ci.line_height-ci.avg_height);
|
|
|
|
}
|
|
|
|
string_width_ -= info_.at(info_.num_characters()-1).format->character_spacing; //Remove last space
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-05-27 12:19:47 +02:00
|
|
|
|
|
|
|
|
2012-01-22 18:41:04 +01:00
|
|
|
template <typename DetectorT>
|
|
|
|
void placement_finder<DetectorT>::find_line_breaks()
|
|
|
|
{
|
|
|
|
bool first_line = true;
|
|
|
|
line_breaks_.clear();
|
|
|
|
line_sizes_.clear();
|
2010-05-27 12:19:47 +02:00
|
|
|
// check if we need to wrap the string
|
2012-01-22 18:41:04 +01:00
|
|
|
double wrap_at = string_width_ + 1.0;
|
|
|
|
if (p.wrap_width && string_width_ > p.wrap_width)
|
2010-05-27 12:19:47 +02:00
|
|
|
{
|
2010-06-02 13:03:30 +02:00
|
|
|
if (p.text_ratio)
|
2012-01-22 18:41:04 +01:00
|
|
|
for (double i = 1.0; ((wrap_at = string_width_/i)/(string_height_*i)) > p.text_ratio && (string_width_/i) > p.wrap_width; i += 1.0) ;
|
2010-06-02 13:03:30 +02:00
|
|
|
else
|
2007-11-02 13:50:15 +01:00
|
|
|
wrap_at = p.wrap_width;
|
2010-05-27 12:19:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// work out where our line breaks need to be and the resultant width to the 'wrapped' string
|
2012-01-22 18:41:04 +01:00
|
|
|
if ((wrap_at < string_width_) || info_.has_line_breaks())
|
2010-05-27 12:19:47 +02:00
|
|
|
{
|
2012-01-22 18:41:04 +01:00
|
|
|
first_line_space_ = 0.0;
|
|
|
|
int last_wrap_char_pos = 0; //Position of last char where wrapping is possible
|
|
|
|
double last_char_spacing = 0.0;
|
|
|
|
double last_wrap_char_width = 0.0; //Include char_spacing before and after
|
|
|
|
string_width_ = 0.0;
|
|
|
|
string_height_ = 0.0;
|
2010-06-02 13:03:30 +02:00
|
|
|
double line_width = 0.0;
|
2012-01-22 18:41:04 +01:00
|
|
|
double line_height = 0.0; //Height of tallest char in line
|
|
|
|
double word_width = 0.0; //Current unfinished word width
|
|
|
|
double word_height = 0.0;
|
|
|
|
//line_width, word_width does include char width + spacing, but not the spacing after the last char
|
2010-06-02 13:03:30 +02:00
|
|
|
|
2012-01-22 18:41:04 +01:00
|
|
|
for (unsigned int ii = 0; ii < info_.num_characters(); ii++)
|
2010-06-02 13:03:30 +02:00
|
|
|
{
|
2012-01-22 18:41:04 +01:00
|
|
|
char_info const& ci = info_.at(ii);
|
2012-01-22 01:08:14 +01:00
|
|
|
unsigned c = ci.c;
|
Patch from David Eastcott :
1. Modified Text Symbolizer
a) corrected line fragment centering (for 2nd and subsequent lines, when line breaks occur).
b) adjusted vertical alignment calculation so that:
i) middle -> has the center of the text line(s) at the point origin
ii) bottom -> has the text line(s) below the point origin
iii) top -> has the text line(s) above the point origin
c) added new text_symbolizer attribute: 'wrap_before', value range: true/false, default == false
allows line breaks at first wrap_char before wrap_width as an alternative to the original
which was to create the line break at the first wrap_char after wrap_width
d) added new text_symbolizer attribute: 'horizontal_alignment', value range: left/middle/right, default == middle
i) left -> has all text line(s) to left of the point origin
ii) middle -> has all text line(s) centered on the the point origin
iii) right -> has all text line(s) to the right of the point origin
NOTE: dx, dy position adjustments are applied after alignments and before Justify.
e) added new text_symbolizer attribute: 'justify_alignment', value range: left/middle/right, default == middle
i) left -> after alignments, has all text line(s) are left justified (left to right reading)
ii) middle -> after alignments, has all text line(s) center justified
iii) right -> after alignments, has all text line(s) right justified (right to left reading)
f) added new text_symbolizer attribute: 'opacity', value range: 0.0 thru 1.0; 1.0 == fully opaque
g) modified positioning to compensate for both line_spacing and character_spacing, to ensure proper
centering of the text envelope. Also ensure that centering occurs correctly even if no wrapping
occurs. Line spacing is uniform and consistent and compensates for errors between text_size and
the actual size (ci.height is inconsistent, depending on case and character); fixes issue with
multi-line text where some lines have a slight gap and others are compressed together.
2. Modified shield_symbolizer
a) added the attributes:
i) allow_overlap
ii) vertical_alignment
iii) horizontal_alignment
iv) justify_alignment
v) wrap_width
vi) wrap_character
vii) wrap_before
viii) text_convert
ix) line_spacing
x) character_spacing
xi) opacity
b) added new shield_symbolizer attribute: 'unlock_image', value range: true/false, default == false
i) false == image and text placement behaviour same as before
ii) true == image placement independant of text, image is always centered at geometry point, text placed per attributes,
dx/dy only affect text.
Allows user to create point markers with text, but both the text and image rendering collision detection are done
as a pair (they come and go together - solves problem if using point_symbolizer and text_symbolizers where one or the
other are omitted due to overlaps, but not both)
c) extended choices for the attribute 'placement' to include vertex; effect is limited to the shield_symbolizer
Allows an attempted placement at every vertex available, gives additional shield placement volume when using line geometry
d) ensured that the text placement was not updating the detector unless a shield image was actually placed.
e) added new shield_symbolizer attribute: 'no_text', value range: true/false, default = false
When set true, the text for the feature is ignored ('space' subsituted) so that pure graphic symbols can be used
and no text is rendered over top of them.
2009-10-19 15:52:53 +02:00
|
|
|
|
2012-01-22 18:41:04 +01:00
|
|
|
if ((c == ci.format->wrap_char) || (c == '\n'))
|
2007-11-02 13:50:15 +01:00
|
|
|
{
|
2012-01-22 18:41:04 +01:00
|
|
|
last_wrap_char_pos = ii;
|
|
|
|
//No wrap at previous position
|
|
|
|
line_width += word_width + last_wrap_char_width;
|
|
|
|
line_height = std::max(line_height, word_height);
|
|
|
|
last_wrap_char_width = last_char_spacing + ci.width + ci.format->character_spacing;
|
|
|
|
last_char_spacing = 0.0;
|
2010-06-02 13:03:30 +02:00
|
|
|
word_width = 0.0;
|
2012-01-22 18:41:04 +01:00
|
|
|
word_height = 0.0;
|
|
|
|
} else {
|
|
|
|
//No wrap char
|
|
|
|
word_width += last_char_spacing + ci.width;
|
|
|
|
last_char_spacing = ci.format->character_spacing;
|
|
|
|
word_height = std::max(word_height, ci.line_height + ci.format->line_spacing);
|
|
|
|
if (first_line) first_line_space_ = std::max(first_line_space_, ci.line_height-ci.avg_height);
|
2007-11-02 13:50:15 +01:00
|
|
|
}
|
Patch from David Eastcott :
1. Modified Text Symbolizer
a) corrected line fragment centering (for 2nd and subsequent lines, when line breaks occur).
b) adjusted vertical alignment calculation so that:
i) middle -> has the center of the text line(s) at the point origin
ii) bottom -> has the text line(s) below the point origin
iii) top -> has the text line(s) above the point origin
c) added new text_symbolizer attribute: 'wrap_before', value range: true/false, default == false
allows line breaks at first wrap_char before wrap_width as an alternative to the original
which was to create the line break at the first wrap_char after wrap_width
d) added new text_symbolizer attribute: 'horizontal_alignment', value range: left/middle/right, default == middle
i) left -> has all text line(s) to left of the point origin
ii) middle -> has all text line(s) centered on the the point origin
iii) right -> has all text line(s) to the right of the point origin
NOTE: dx, dy position adjustments are applied after alignments and before Justify.
e) added new text_symbolizer attribute: 'justify_alignment', value range: left/middle/right, default == middle
i) left -> after alignments, has all text line(s) are left justified (left to right reading)
ii) middle -> after alignments, has all text line(s) center justified
iii) right -> after alignments, has all text line(s) right justified (right to left reading)
f) added new text_symbolizer attribute: 'opacity', value range: 0.0 thru 1.0; 1.0 == fully opaque
g) modified positioning to compensate for both line_spacing and character_spacing, to ensure proper
centering of the text envelope. Also ensure that centering occurs correctly even if no wrapping
occurs. Line spacing is uniform and consistent and compensates for errors between text_size and
the actual size (ci.height is inconsistent, depending on case and character); fixes issue with
multi-line text where some lines have a slight gap and others are compressed together.
2. Modified shield_symbolizer
a) added the attributes:
i) allow_overlap
ii) vertical_alignment
iii) horizontal_alignment
iv) justify_alignment
v) wrap_width
vi) wrap_character
vii) wrap_before
viii) text_convert
ix) line_spacing
x) character_spacing
xi) opacity
b) added new shield_symbolizer attribute: 'unlock_image', value range: true/false, default == false
i) false == image and text placement behaviour same as before
ii) true == image placement independant of text, image is always centered at geometry point, text placed per attributes,
dx/dy only affect text.
Allows user to create point markers with text, but both the text and image rendering collision detection are done
as a pair (they come and go together - solves problem if using point_symbolizer and text_symbolizers where one or the
other are omitted due to overlaps, but not both)
c) extended choices for the attribute 'placement' to include vertex; effect is limited to the shield_symbolizer
Allows an attempted placement at every vertex available, gives additional shield placement volume when using line geometry
d) ensured that the text placement was not updating the detector unless a shield image was actually placed.
e) added new shield_symbolizer attribute: 'no_text', value range: true/false, default = false
When set true, the text for the feature is ignored ('space' subsituted) so that pure graphic symbols can be used
and no text is rendered over top of them.
2009-10-19 15:52:53 +02:00
|
|
|
|
|
|
|
// wrap text at first wrap_char after (default) the wrap width or immediately before the current word
|
2010-12-09 09:48:46 +01:00
|
|
|
if ((c == '\n') ||
|
2012-01-22 18:41:04 +01:00
|
|
|
(line_width > 0 && ((line_width > wrap_at && !ci.format->wrap_before) ||
|
|
|
|
((line_width + last_wrap_char_width + word_width) > wrap_at && ci.format->wrap_before)) ))
|
2007-11-02 13:50:15 +01:00
|
|
|
{
|
2012-01-22 18:41:04 +01:00
|
|
|
string_width_ = std::max(string_width_, line_width); //Total width is the longest line
|
|
|
|
string_height_ += line_height;
|
|
|
|
line_breaks_.push_back(last_wrap_char_pos);
|
|
|
|
line_sizes_.push_back(std::make_pair(line_width, line_height));
|
2010-06-02 13:03:30 +02:00
|
|
|
line_width = 0.0;
|
2012-01-22 18:41:04 +01:00
|
|
|
line_height = 0.0;
|
|
|
|
last_wrap_char_width = 0; //Wrap char supressed
|
|
|
|
first_line = false;
|
2007-11-02 13:50:15 +01:00
|
|
|
}
|
2010-06-02 13:03:30 +02:00
|
|
|
}
|
2012-01-22 18:41:04 +01:00
|
|
|
line_width += last_wrap_char_width + word_width;
|
|
|
|
line_height = std::max(line_height, word_height);
|
|
|
|
string_width_ = std::max(string_width_, line_width);
|
|
|
|
string_height_ += line_height;
|
|
|
|
line_sizes_.push_back(std::make_pair(line_width, line_height));
|
|
|
|
} else {
|
|
|
|
//No linebreaks
|
|
|
|
line_sizes_.push_back(std::make_pair(string_width_, string_height_));
|
2010-05-27 12:19:47 +02:00
|
|
|
}
|
2012-01-22 18:41:04 +01:00
|
|
|
line_breaks_.push_back(info_.num_characters());
|
|
|
|
}
|
2010-05-27 12:19:47 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
2012-01-22 18:41:04 +01:00
|
|
|
template <typename DetectorT>
|
|
|
|
void placement_finder<DetectorT>::init_alignment()
|
|
|
|
{
|
|
|
|
valign_ = p.valign;
|
|
|
|
if (valign_ == V_AUTO) {
|
2012-01-29 17:33:43 +01:00
|
|
|
if (p.displacement.second > 0.0)
|
2012-01-22 18:41:04 +01:00
|
|
|
valign_ = V_BOTTOM;
|
2012-01-29 17:33:43 +01:00
|
|
|
else if (p.displacement.second < 0.0)
|
2012-01-22 18:41:04 +01:00
|
|
|
valign_ = V_TOP;
|
2011-02-28 14:17:46 +01:00
|
|
|
else
|
2012-01-22 18:41:04 +01:00
|
|
|
valign_ = V_MIDDLE;
|
2011-02-28 14:17:46 +01:00
|
|
|
}
|
|
|
|
|
2012-01-22 18:41:04 +01:00
|
|
|
halign_ = p.halign;
|
|
|
|
if (halign_ == H_AUTO) {
|
2012-01-29 17:33:43 +01:00
|
|
|
if (p.displacement.first > 0.0)
|
2012-01-22 18:41:04 +01:00
|
|
|
halign_ = H_RIGHT;
|
2012-01-29 17:33:43 +01:00
|
|
|
else if (p.displacement.first < 0.0)
|
2012-01-22 18:41:04 +01:00
|
|
|
halign_ = H_LEFT;
|
2011-02-28 14:17:46 +01:00
|
|
|
else
|
2012-01-22 18:41:04 +01:00
|
|
|
halign_ = H_MIDDLE;
|
2011-02-28 14:17:46 +01:00
|
|
|
}
|
2012-01-22 18:41:04 +01:00
|
|
|
}
|
2011-02-28 14:17:46 +01:00
|
|
|
|
2010-05-27 12:19:47 +02:00
|
|
|
|
2012-01-22 18:41:04 +01:00
|
|
|
template <typename DetectorT>
|
2012-01-28 00:09:58 +01:00
|
|
|
void placement_finder<DetectorT>::adjust_position(text_path *current_placement, double label_x, double label_y)
|
2012-01-22 18:41:04 +01:00
|
|
|
{
|
|
|
|
// if needed, adjust for desired vertical alignment
|
|
|
|
current_placement->starting_y = label_y; // no adjustment, default is MIDDLE
|
|
|
|
if (valign_ == V_TOP)
|
|
|
|
current_placement->starting_y -= 0.5 * string_height_; // move center up by 1/2 the total height
|
|
|
|
else if (valign_ == V_BOTTOM) {
|
|
|
|
current_placement->starting_y += 0.5 * string_height_; // move center down by the 1/2 the total height
|
|
|
|
current_placement->starting_y -= first_line_space_;
|
|
|
|
} else if (valign_ == V_MIDDLE) {
|
|
|
|
current_placement->starting_y -= first_line_space_/2.0;
|
|
|
|
}
|
2010-05-27 12:19:47 +02:00
|
|
|
|
|
|
|
// set horizontal position to middle of text
|
|
|
|
current_placement->starting_x = label_x; // no adjustment, default is MIDDLE
|
2012-01-22 18:41:04 +01:00
|
|
|
if (halign_ == H_LEFT)
|
|
|
|
current_placement->starting_x -= 0.5 * string_width_; // move center left by 1/2 the string width
|
|
|
|
else if (halign_ == H_RIGHT)
|
|
|
|
current_placement->starting_x += 0.5 * string_width_; // move center right by 1/2 the string width
|
|
|
|
|
|
|
|
// adjust text envelope position by user's x-y displacement (dx, dy)
|
2012-01-29 17:33:43 +01:00
|
|
|
current_placement->starting_x += pi.get_scale_factor() * p.displacement.first;
|
|
|
|
current_placement->starting_y += pi.get_scale_factor() * p.displacement.second;
|
2010-05-27 12:19:47 +02:00
|
|
|
|
2012-01-22 18:41:04 +01:00
|
|
|
}
|
2010-05-27 12:19:47 +02:00
|
|
|
|
2012-01-22 18:41:04 +01:00
|
|
|
template <typename DetectorT>
|
|
|
|
void placement_finder<DetectorT>::find_point_placement(double label_x, double label_y, double angle)
|
|
|
|
{
|
|
|
|
init_string_size();
|
|
|
|
find_line_breaks();
|
|
|
|
init_alignment();
|
2010-05-27 12:19:47 +02:00
|
|
|
|
2012-01-22 18:41:04 +01:00
|
|
|
double rad = M_PI * angle/180.0;
|
|
|
|
double cosa = std::cos(rad);
|
|
|
|
double sina = std::sin(rad);
|
|
|
|
|
|
|
|
double x, y;
|
2012-01-28 00:09:58 +01:00
|
|
|
std::auto_ptr<text_path> current_placement(new text_path);
|
2012-01-22 18:41:04 +01:00
|
|
|
|
|
|
|
adjust_position(current_placement.get(), label_x, label_y);
|
2010-05-27 12:19:47 +02:00
|
|
|
|
|
|
|
// presets for first line
|
|
|
|
unsigned int line_number = 0;
|
2012-01-22 18:41:04 +01:00
|
|
|
unsigned int index_to_wrap_at = line_breaks_[0];
|
|
|
|
double line_width = line_sizes_[0].first;
|
|
|
|
double line_height = line_sizes_[0].second;
|
2010-05-27 12:19:47 +02:00
|
|
|
|
2012-01-22 18:41:04 +01:00
|
|
|
//TODO: Understand and document this
|
2010-05-27 12:19:47 +02:00
|
|
|
// set for upper left corner of text envelope for the first line, bottom left of first character
|
2012-01-22 18:41:04 +01:00
|
|
|
y = (string_height_ / 2.0) - line_height;
|
|
|
|
|
|
|
|
// adjust for desired justification
|
|
|
|
//TODO: Understand and document this
|
|
|
|
if (p.jalign == J_LEFT)
|
|
|
|
x = -(string_width_ / 2.0);
|
|
|
|
else if (p.jalign == J_RIGHT)
|
|
|
|
x = (string_width_ / 2.0) - line_width;
|
2011-12-15 15:57:57 +01:00
|
|
|
else
|
2012-01-22 18:41:04 +01:00
|
|
|
x = -(line_width / 2.0);
|
2010-05-27 12:19:47 +02:00
|
|
|
|
|
|
|
// save each character rendering position and build envelope as go thru loop
|
|
|
|
std::queue< box2d<double> > c_envelopes;
|
|
|
|
|
2012-01-22 18:41:04 +01:00
|
|
|
for (unsigned i = 0; i < info_.num_characters(); i++)
|
2010-05-27 12:19:47 +02:00
|
|
|
{
|
2012-01-22 18:41:04 +01:00
|
|
|
char_info const& ci = info_.at(i);
|
2010-05-27 12:19:47 +02:00
|
|
|
|
2012-01-22 18:41:04 +01:00
|
|
|
double cwidth = ci.width + ci.format->character_spacing;
|
2010-05-27 12:19:47 +02:00
|
|
|
|
2012-01-22 01:08:14 +01:00
|
|
|
unsigned c = ci.c;
|
2010-06-02 13:03:30 +02:00
|
|
|
if (i == index_to_wrap_at)
|
|
|
|
{
|
2012-01-22 18:41:04 +01:00
|
|
|
index_to_wrap_at = line_breaks_[++line_number];
|
|
|
|
line_width = line_sizes_[line_number].first;
|
|
|
|
line_height= line_sizes_[line_number].second;
|
Patch from David Eastcott :
1. Modified Text Symbolizer
a) corrected line fragment centering (for 2nd and subsequent lines, when line breaks occur).
b) adjusted vertical alignment calculation so that:
i) middle -> has the center of the text line(s) at the point origin
ii) bottom -> has the text line(s) below the point origin
iii) top -> has the text line(s) above the point origin
c) added new text_symbolizer attribute: 'wrap_before', value range: true/false, default == false
allows line breaks at first wrap_char before wrap_width as an alternative to the original
which was to create the line break at the first wrap_char after wrap_width
d) added new text_symbolizer attribute: 'horizontal_alignment', value range: left/middle/right, default == middle
i) left -> has all text line(s) to left of the point origin
ii) middle -> has all text line(s) centered on the the point origin
iii) right -> has all text line(s) to the right of the point origin
NOTE: dx, dy position adjustments are applied after alignments and before Justify.
e) added new text_symbolizer attribute: 'justify_alignment', value range: left/middle/right, default == middle
i) left -> after alignments, has all text line(s) are left justified (left to right reading)
ii) middle -> after alignments, has all text line(s) center justified
iii) right -> after alignments, has all text line(s) right justified (right to left reading)
f) added new text_symbolizer attribute: 'opacity', value range: 0.0 thru 1.0; 1.0 == fully opaque
g) modified positioning to compensate for both line_spacing and character_spacing, to ensure proper
centering of the text envelope. Also ensure that centering occurs correctly even if no wrapping
occurs. Line spacing is uniform and consistent and compensates for errors between text_size and
the actual size (ci.height is inconsistent, depending on case and character); fixes issue with
multi-line text where some lines have a slight gap and others are compressed together.
2. Modified shield_symbolizer
a) added the attributes:
i) allow_overlap
ii) vertical_alignment
iii) horizontal_alignment
iv) justify_alignment
v) wrap_width
vi) wrap_character
vii) wrap_before
viii) text_convert
ix) line_spacing
x) character_spacing
xi) opacity
b) added new shield_symbolizer attribute: 'unlock_image', value range: true/false, default == false
i) false == image and text placement behaviour same as before
ii) true == image placement independant of text, image is always centered at geometry point, text placed per attributes,
dx/dy only affect text.
Allows user to create point markers with text, but both the text and image rendering collision detection are done
as a pair (they come and go together - solves problem if using point_symbolizer and text_symbolizers where one or the
other are omitted due to overlaps, but not both)
c) extended choices for the attribute 'placement' to include vertex; effect is limited to the shield_symbolizer
Allows an attempted placement at every vertex available, gives additional shield placement volume when using line geometry
d) ensured that the text placement was not updating the detector unless a shield image was actually placed.
e) added new shield_symbolizer attribute: 'no_text', value range: true/false, default = false
When set true, the text for the feature is ignored ('space' subsituted) so that pure graphic symbols can be used
and no text is rendered over top of them.
2009-10-19 15:52:53 +02:00
|
|
|
|
2012-01-22 18:41:04 +01:00
|
|
|
y -= line_height; // move position down to line start
|
Patch from David Eastcott :
1. Modified Text Symbolizer
a) corrected line fragment centering (for 2nd and subsequent lines, when line breaks occur).
b) adjusted vertical alignment calculation so that:
i) middle -> has the center of the text line(s) at the point origin
ii) bottom -> has the text line(s) below the point origin
iii) top -> has the text line(s) above the point origin
c) added new text_symbolizer attribute: 'wrap_before', value range: true/false, default == false
allows line breaks at first wrap_char before wrap_width as an alternative to the original
which was to create the line break at the first wrap_char after wrap_width
d) added new text_symbolizer attribute: 'horizontal_alignment', value range: left/middle/right, default == middle
i) left -> has all text line(s) to left of the point origin
ii) middle -> has all text line(s) centered on the the point origin
iii) right -> has all text line(s) to the right of the point origin
NOTE: dx, dy position adjustments are applied after alignments and before Justify.
e) added new text_symbolizer attribute: 'justify_alignment', value range: left/middle/right, default == middle
i) left -> after alignments, has all text line(s) are left justified (left to right reading)
ii) middle -> after alignments, has all text line(s) center justified
iii) right -> after alignments, has all text line(s) right justified (right to left reading)
f) added new text_symbolizer attribute: 'opacity', value range: 0.0 thru 1.0; 1.0 == fully opaque
g) modified positioning to compensate for both line_spacing and character_spacing, to ensure proper
centering of the text envelope. Also ensure that centering occurs correctly even if no wrapping
occurs. Line spacing is uniform and consistent and compensates for errors between text_size and
the actual size (ci.height is inconsistent, depending on case and character); fixes issue with
multi-line text where some lines have a slight gap and others are compressed together.
2. Modified shield_symbolizer
a) added the attributes:
i) allow_overlap
ii) vertical_alignment
iii) horizontal_alignment
iv) justify_alignment
v) wrap_width
vi) wrap_character
vii) wrap_before
viii) text_convert
ix) line_spacing
x) character_spacing
xi) opacity
b) added new shield_symbolizer attribute: 'unlock_image', value range: true/false, default == false
i) false == image and text placement behaviour same as before
ii) true == image placement independant of text, image is always centered at geometry point, text placed per attributes,
dx/dy only affect text.
Allows user to create point markers with text, but both the text and image rendering collision detection are done
as a pair (they come and go together - solves problem if using point_symbolizer and text_symbolizers where one or the
other are omitted due to overlaps, but not both)
c) extended choices for the attribute 'placement' to include vertex; effect is limited to the shield_symbolizer
Allows an attempted placement at every vertex available, gives additional shield placement volume when using line geometry
d) ensured that the text placement was not updating the detector unless a shield image was actually placed.
e) added new shield_symbolizer attribute: 'no_text', value range: true/false, default = false
When set true, the text for the feature is ignored ('space' subsituted) so that pure graphic symbols can be used
and no text is rendered over top of them.
2009-10-19 15:52:53 +02:00
|
|
|
|
|
|
|
// reset to begining of line position
|
2012-01-22 18:41:04 +01:00
|
|
|
if (p.jalign == J_LEFT)
|
|
|
|
x = -(string_width_ / 2.0);
|
|
|
|
else if (p.jalign == J_RIGHT)
|
|
|
|
x = (string_width_ / 2.0) - line_width;
|
|
|
|
else
|
|
|
|
x = -(line_width / 2.0);
|
2007-11-02 13:50:15 +01:00
|
|
|
continue;
|
2010-06-02 13:03:30 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
Patch from David Eastcott :
1. Modified Text Symbolizer
a) corrected line fragment centering (for 2nd and subsequent lines, when line breaks occur).
b) adjusted vertical alignment calculation so that:
i) middle -> has the center of the text line(s) at the point origin
ii) bottom -> has the text line(s) below the point origin
iii) top -> has the text line(s) above the point origin
c) added new text_symbolizer attribute: 'wrap_before', value range: true/false, default == false
allows line breaks at first wrap_char before wrap_width as an alternative to the original
which was to create the line break at the first wrap_char after wrap_width
d) added new text_symbolizer attribute: 'horizontal_alignment', value range: left/middle/right, default == middle
i) left -> has all text line(s) to left of the point origin
ii) middle -> has all text line(s) centered on the the point origin
iii) right -> has all text line(s) to the right of the point origin
NOTE: dx, dy position adjustments are applied after alignments and before Justify.
e) added new text_symbolizer attribute: 'justify_alignment', value range: left/middle/right, default == middle
i) left -> after alignments, has all text line(s) are left justified (left to right reading)
ii) middle -> after alignments, has all text line(s) center justified
iii) right -> after alignments, has all text line(s) right justified (right to left reading)
f) added new text_symbolizer attribute: 'opacity', value range: 0.0 thru 1.0; 1.0 == fully opaque
g) modified positioning to compensate for both line_spacing and character_spacing, to ensure proper
centering of the text envelope. Also ensure that centering occurs correctly even if no wrapping
occurs. Line spacing is uniform and consistent and compensates for errors between text_size and
the actual size (ci.height is inconsistent, depending on case and character); fixes issue with
multi-line text where some lines have a slight gap and others are compressed together.
2. Modified shield_symbolizer
a) added the attributes:
i) allow_overlap
ii) vertical_alignment
iii) horizontal_alignment
iv) justify_alignment
v) wrap_width
vi) wrap_character
vii) wrap_before
viii) text_convert
ix) line_spacing
x) character_spacing
xi) opacity
b) added new shield_symbolizer attribute: 'unlock_image', value range: true/false, default == false
i) false == image and text placement behaviour same as before
ii) true == image placement independant of text, image is always centered at geometry point, text placed per attributes,
dx/dy only affect text.
Allows user to create point markers with text, but both the text and image rendering collision detection are done
as a pair (they come and go together - solves problem if using point_symbolizer and text_symbolizers where one or the
other are omitted due to overlaps, but not both)
c) extended choices for the attribute 'placement' to include vertex; effect is limited to the shield_symbolizer
Allows an attempted placement at every vertex available, gives additional shield placement volume when using line geometry
d) ensured that the text placement was not updating the detector unless a shield image was actually placed.
e) added new shield_symbolizer attribute: 'no_text', value range: true/false, default = false
When set true, the text for the feature is ignored ('space' subsituted) so that pure graphic symbols can be used
and no text is rendered over top of them.
2009-10-19 15:52:53 +02:00
|
|
|
// place the character relative to the center of the string envelope
|
2010-06-02 13:03:30 +02:00
|
|
|
double dx = x * cosa - y*sina;
|
|
|
|
double dy = x * sina + y*cosa;
|
|
|
|
|
2012-01-22 01:08:14 +01:00
|
|
|
current_placement->add_node(c, dx, dy, rad, ci.format);
|
2010-06-02 13:03:30 +02:00
|
|
|
|
Patch from David Eastcott :
1. Modified Text Symbolizer
a) corrected line fragment centering (for 2nd and subsequent lines, when line breaks occur).
b) adjusted vertical alignment calculation so that:
i) middle -> has the center of the text line(s) at the point origin
ii) bottom -> has the text line(s) below the point origin
iii) top -> has the text line(s) above the point origin
c) added new text_symbolizer attribute: 'wrap_before', value range: true/false, default == false
allows line breaks at first wrap_char before wrap_width as an alternative to the original
which was to create the line break at the first wrap_char after wrap_width
d) added new text_symbolizer attribute: 'horizontal_alignment', value range: left/middle/right, default == middle
i) left -> has all text line(s) to left of the point origin
ii) middle -> has all text line(s) centered on the the point origin
iii) right -> has all text line(s) to the right of the point origin
NOTE: dx, dy position adjustments are applied after alignments and before Justify.
e) added new text_symbolizer attribute: 'justify_alignment', value range: left/middle/right, default == middle
i) left -> after alignments, has all text line(s) are left justified (left to right reading)
ii) middle -> after alignments, has all text line(s) center justified
iii) right -> after alignments, has all text line(s) right justified (right to left reading)
f) added new text_symbolizer attribute: 'opacity', value range: 0.0 thru 1.0; 1.0 == fully opaque
g) modified positioning to compensate for both line_spacing and character_spacing, to ensure proper
centering of the text envelope. Also ensure that centering occurs correctly even if no wrapping
occurs. Line spacing is uniform and consistent and compensates for errors between text_size and
the actual size (ci.height is inconsistent, depending on case and character); fixes issue with
multi-line text where some lines have a slight gap and others are compressed together.
2. Modified shield_symbolizer
a) added the attributes:
i) allow_overlap
ii) vertical_alignment
iii) horizontal_alignment
iv) justify_alignment
v) wrap_width
vi) wrap_character
vii) wrap_before
viii) text_convert
ix) line_spacing
x) character_spacing
xi) opacity
b) added new shield_symbolizer attribute: 'unlock_image', value range: true/false, default == false
i) false == image and text placement behaviour same as before
ii) true == image placement independant of text, image is always centered at geometry point, text placed per attributes,
dx/dy only affect text.
Allows user to create point markers with text, but both the text and image rendering collision detection are done
as a pair (they come and go together - solves problem if using point_symbolizer and text_symbolizers where one or the
other are omitted due to overlaps, but not both)
c) extended choices for the attribute 'placement' to include vertex; effect is limited to the shield_symbolizer
Allows an attempted placement at every vertex available, gives additional shield placement volume when using line geometry
d) ensured that the text placement was not updating the detector unless a shield image was actually placed.
e) added new shield_symbolizer attribute: 'no_text', value range: true/false, default = false
When set true, the text for the feature is ignored ('space' subsituted) so that pure graphic symbols can be used
and no text is rendered over top of them.
2009-10-19 15:52:53 +02:00
|
|
|
// compute the Bounding Box for each character and test for:
|
|
|
|
// overlap, minimum distance or edge avoidance - exit if condition occurs
|
2009-12-16 21:02:06 +01:00
|
|
|
box2d<double> e;
|
2012-01-22 18:41:04 +01:00
|
|
|
/*x axis: left to right, y axis: top to bottom (negative values higher)*/
|
|
|
|
if (pi.has_dimensions)
|
2007-11-02 13:50:15 +01:00
|
|
|
{
|
2012-01-22 18:41:04 +01:00
|
|
|
e.init(current_placement->starting_x - (pi.dimensions.first/2.0), // Top Left
|
|
|
|
current_placement->starting_y - (pi.dimensions.second/2.0),
|
Patch from David Eastcott :
1. Modified Text Symbolizer
a) corrected line fragment centering (for 2nd and subsequent lines, when line breaks occur).
b) adjusted vertical alignment calculation so that:
i) middle -> has the center of the text line(s) at the point origin
ii) bottom -> has the text line(s) below the point origin
iii) top -> has the text line(s) above the point origin
c) added new text_symbolizer attribute: 'wrap_before', value range: true/false, default == false
allows line breaks at first wrap_char before wrap_width as an alternative to the original
which was to create the line break at the first wrap_char after wrap_width
d) added new text_symbolizer attribute: 'horizontal_alignment', value range: left/middle/right, default == middle
i) left -> has all text line(s) to left of the point origin
ii) middle -> has all text line(s) centered on the the point origin
iii) right -> has all text line(s) to the right of the point origin
NOTE: dx, dy position adjustments are applied after alignments and before Justify.
e) added new text_symbolizer attribute: 'justify_alignment', value range: left/middle/right, default == middle
i) left -> after alignments, has all text line(s) are left justified (left to right reading)
ii) middle -> after alignments, has all text line(s) center justified
iii) right -> after alignments, has all text line(s) right justified (right to left reading)
f) added new text_symbolizer attribute: 'opacity', value range: 0.0 thru 1.0; 1.0 == fully opaque
g) modified positioning to compensate for both line_spacing and character_spacing, to ensure proper
centering of the text envelope. Also ensure that centering occurs correctly even if no wrapping
occurs. Line spacing is uniform and consistent and compensates for errors between text_size and
the actual size (ci.height is inconsistent, depending on case and character); fixes issue with
multi-line text where some lines have a slight gap and others are compressed together.
2. Modified shield_symbolizer
a) added the attributes:
i) allow_overlap
ii) vertical_alignment
iii) horizontal_alignment
iv) justify_alignment
v) wrap_width
vi) wrap_character
vii) wrap_before
viii) text_convert
ix) line_spacing
x) character_spacing
xi) opacity
b) added new shield_symbolizer attribute: 'unlock_image', value range: true/false, default == false
i) false == image and text placement behaviour same as before
ii) true == image placement independant of text, image is always centered at geometry point, text placed per attributes,
dx/dy only affect text.
Allows user to create point markers with text, but both the text and image rendering collision detection are done
as a pair (they come and go together - solves problem if using point_symbolizer and text_symbolizers where one or the
other are omitted due to overlaps, but not both)
c) extended choices for the attribute 'placement' to include vertex; effect is limited to the shield_symbolizer
Allows an attempted placement at every vertex available, gives additional shield placement volume when using line geometry
d) ensured that the text placement was not updating the detector unless a shield image was actually placed.
e) added new shield_symbolizer attribute: 'no_text', value range: true/false, default = false
When set true, the text for the feature is ignored ('space' subsituted) so that pure graphic symbols can be used
and no text is rendered over top of them.
2009-10-19 15:52:53 +02:00
|
|
|
|
2012-01-22 18:41:04 +01:00
|
|
|
current_placement->starting_x + (pi.dimensions.first/2.0), // Bottom Right
|
|
|
|
current_placement->starting_y + (pi.dimensions.second/2.0));
|
2007-11-02 13:50:15 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-06-02 13:03:30 +02:00
|
|
|
e.init(current_placement->starting_x + dx, // Bottom Left
|
2012-01-22 18:41:04 +01:00
|
|
|
current_placement->starting_y - dy - ci.ymin, /*ymin usually <0 */
|
Patch from David Eastcott :
1. Modified Text Symbolizer
a) corrected line fragment centering (for 2nd and subsequent lines, when line breaks occur).
b) adjusted vertical alignment calculation so that:
i) middle -> has the center of the text line(s) at the point origin
ii) bottom -> has the text line(s) below the point origin
iii) top -> has the text line(s) above the point origin
c) added new text_symbolizer attribute: 'wrap_before', value range: true/false, default == false
allows line breaks at first wrap_char before wrap_width as an alternative to the original
which was to create the line break at the first wrap_char after wrap_width
d) added new text_symbolizer attribute: 'horizontal_alignment', value range: left/middle/right, default == middle
i) left -> has all text line(s) to left of the point origin
ii) middle -> has all text line(s) centered on the the point origin
iii) right -> has all text line(s) to the right of the point origin
NOTE: dx, dy position adjustments are applied after alignments and before Justify.
e) added new text_symbolizer attribute: 'justify_alignment', value range: left/middle/right, default == middle
i) left -> after alignments, has all text line(s) are left justified (left to right reading)
ii) middle -> after alignments, has all text line(s) center justified
iii) right -> after alignments, has all text line(s) right justified (right to left reading)
f) added new text_symbolizer attribute: 'opacity', value range: 0.0 thru 1.0; 1.0 == fully opaque
g) modified positioning to compensate for both line_spacing and character_spacing, to ensure proper
centering of the text envelope. Also ensure that centering occurs correctly even if no wrapping
occurs. Line spacing is uniform and consistent and compensates for errors between text_size and
the actual size (ci.height is inconsistent, depending on case and character); fixes issue with
multi-line text where some lines have a slight gap and others are compressed together.
2. Modified shield_symbolizer
a) added the attributes:
i) allow_overlap
ii) vertical_alignment
iii) horizontal_alignment
iv) justify_alignment
v) wrap_width
vi) wrap_character
vii) wrap_before
viii) text_convert
ix) line_spacing
x) character_spacing
xi) opacity
b) added new shield_symbolizer attribute: 'unlock_image', value range: true/false, default == false
i) false == image and text placement behaviour same as before
ii) true == image placement independant of text, image is always centered at geometry point, text placed per attributes,
dx/dy only affect text.
Allows user to create point markers with text, but both the text and image rendering collision detection are done
as a pair (they come and go together - solves problem if using point_symbolizer and text_symbolizers where one or the
other are omitted due to overlaps, but not both)
c) extended choices for the attribute 'placement' to include vertex; effect is limited to the shield_symbolizer
Allows an attempted placement at every vertex available, gives additional shield placement volume when using line geometry
d) ensured that the text placement was not updating the detector unless a shield image was actually placed.
e) added new shield_symbolizer attribute: 'no_text', value range: true/false, default = false
When set true, the text for the feature is ignored ('space' subsituted) so that pure graphic symbols can be used
and no text is rendered over top of them.
2009-10-19 15:52:53 +02:00
|
|
|
|
2010-06-02 13:03:30 +02:00
|
|
|
current_placement->starting_x + dx + ci.width, // Top Right
|
2012-01-22 18:41:04 +01:00
|
|
|
current_placement->starting_y - dy - ci.ymax);
|
2007-11-02 13:50:15 +01:00
|
|
|
}
|
2010-06-02 13:03:30 +02:00
|
|
|
|
2009-12-14 00:30:36 +01:00
|
|
|
// if there is an overlap with existing envelopes, then exit - no placement
|
2012-01-22 18:41:04 +01:00
|
|
|
if (!detector_.extent().intersects(e) || (!p.allow_overlap && !detector_.has_point_placement(e, pi.get_actual_minimum_distance()))) {
|
2010-06-02 13:03:30 +02:00
|
|
|
return;
|
2012-01-22 18:41:04 +01:00
|
|
|
}
|
Patch from David Eastcott :
1. Modified Text Symbolizer
a) corrected line fragment centering (for 2nd and subsequent lines, when line breaks occur).
b) adjusted vertical alignment calculation so that:
i) middle -> has the center of the text line(s) at the point origin
ii) bottom -> has the text line(s) below the point origin
iii) top -> has the text line(s) above the point origin
c) added new text_symbolizer attribute: 'wrap_before', value range: true/false, default == false
allows line breaks at first wrap_char before wrap_width as an alternative to the original
which was to create the line break at the first wrap_char after wrap_width
d) added new text_symbolizer attribute: 'horizontal_alignment', value range: left/middle/right, default == middle
i) left -> has all text line(s) to left of the point origin
ii) middle -> has all text line(s) centered on the the point origin
iii) right -> has all text line(s) to the right of the point origin
NOTE: dx, dy position adjustments are applied after alignments and before Justify.
e) added new text_symbolizer attribute: 'justify_alignment', value range: left/middle/right, default == middle
i) left -> after alignments, has all text line(s) are left justified (left to right reading)
ii) middle -> after alignments, has all text line(s) center justified
iii) right -> after alignments, has all text line(s) right justified (right to left reading)
f) added new text_symbolizer attribute: 'opacity', value range: 0.0 thru 1.0; 1.0 == fully opaque
g) modified positioning to compensate for both line_spacing and character_spacing, to ensure proper
centering of the text envelope. Also ensure that centering occurs correctly even if no wrapping
occurs. Line spacing is uniform and consistent and compensates for errors between text_size and
the actual size (ci.height is inconsistent, depending on case and character); fixes issue with
multi-line text where some lines have a slight gap and others are compressed together.
2. Modified shield_symbolizer
a) added the attributes:
i) allow_overlap
ii) vertical_alignment
iii) horizontal_alignment
iv) justify_alignment
v) wrap_width
vi) wrap_character
vii) wrap_before
viii) text_convert
ix) line_spacing
x) character_spacing
xi) opacity
b) added new shield_symbolizer attribute: 'unlock_image', value range: true/false, default == false
i) false == image and text placement behaviour same as before
ii) true == image placement independant of text, image is always centered at geometry point, text placed per attributes,
dx/dy only affect text.
Allows user to create point markers with text, but both the text and image rendering collision detection are done
as a pair (they come and go together - solves problem if using point_symbolizer and text_symbolizers where one or the
other are omitted due to overlaps, but not both)
c) extended choices for the attribute 'placement' to include vertex; effect is limited to the shield_symbolizer
Allows an attempted placement at every vertex available, gives additional shield placement volume when using line geometry
d) ensured that the text placement was not updating the detector unless a shield image was actually placed.
e) added new shield_symbolizer attribute: 'no_text', value range: true/false, default = false
When set true, the text for the feature is ignored ('space' subsituted) so that pure graphic symbols can be used
and no text is rendered over top of them.
2009-10-19 15:52:53 +02:00
|
|
|
|
2010-11-22 12:25:36 +01:00
|
|
|
// if avoid_edges test dimensions contains e
|
2012-01-22 18:41:04 +01:00
|
|
|
if (p.avoid_edges && !dimensions_.contains(e)) {
|
2010-06-02 13:03:30 +02:00
|
|
|
return;
|
2012-01-22 18:41:04 +01:00
|
|
|
}
|
2010-11-22 12:25:36 +01:00
|
|
|
|
2012-01-22 18:41:04 +01:00
|
|
|
if (p.minimum_padding > 0)
|
2010-11-03 14:18:56 +01:00
|
|
|
{
|
2012-01-22 18:41:04 +01:00
|
|
|
double min_pad = pi.get_actual_minimum_padding();
|
|
|
|
box2d<double> epad(e.minx()-min_pad,
|
|
|
|
e.miny()-min_pad,
|
|
|
|
e.maxx()+min_pad,
|
|
|
|
e.maxy()+min_pad);
|
2010-11-03 14:18:56 +01:00
|
|
|
if (!dimensions_.contains(epad))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-12-14 00:30:36 +01:00
|
|
|
c_envelopes.push(e); // add character's envelope to temp storage
|
2010-06-02 13:03:30 +02:00
|
|
|
}
|
|
|
|
x += cwidth; // move position to next character
|
2010-05-27 12:19:47 +02:00
|
|
|
}
|
2009-12-14 00:30:36 +01:00
|
|
|
|
2011-10-12 02:02:28 +02:00
|
|
|
// check the placement of any additional envelopes
|
2012-01-29 20:28:32 +01:00
|
|
|
if (!p.allow_overlap && !pi.additional_boxes.empty())
|
2011-10-12 02:02:28 +02:00
|
|
|
{
|
2012-01-29 20:28:32 +01:00
|
|
|
BOOST_FOREACH(box2d<double> box, pi.additional_boxes)
|
2011-12-15 15:57:57 +01:00
|
|
|
{
|
|
|
|
box2d<double> pt(box.minx() + current_placement->starting_x,
|
|
|
|
box.miny() + current_placement->starting_y,
|
|
|
|
box.maxx() + current_placement->starting_x,
|
|
|
|
box.maxy() + current_placement->starting_y);
|
|
|
|
|
|
|
|
// abort the whole placement if the additional envelopes can't be placed.
|
|
|
|
if (!detector_.has_point_placement(pt, p.minimum_distance)) return;
|
|
|
|
|
|
|
|
c_envelopes.push(pt);
|
|
|
|
}
|
2011-10-12 02:02:28 +02:00
|
|
|
}
|
|
|
|
|
2010-05-27 12:19:47 +02:00
|
|
|
// since there was no early exit, add the character envelopes to the placements' envelopes
|
|
|
|
while( !c_envelopes.empty() )
|
|
|
|
{
|
2012-01-22 18:41:04 +01:00
|
|
|
pi.envelopes.push( c_envelopes.front() );
|
2009-12-14 00:30:36 +01:00
|
|
|
c_envelopes.pop();
|
2010-05-27 12:19:47 +02:00
|
|
|
}
|
|
|
|
|
2012-01-22 18:41:04 +01:00
|
|
|
pi.placements.push_back(current_placement.release());
|
2010-05-27 12:19:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <typename DetectorT>
|
|
|
|
template <typename PathT>
|
2012-01-22 18:41:04 +01:00
|
|
|
void placement_finder<DetectorT>::find_line_placements(PathT & shape_path)
|
2010-05-27 12:19:47 +02:00
|
|
|
{
|
2012-01-22 18:41:04 +01:00
|
|
|
init_string_size();
|
2010-05-27 12:19:47 +02:00
|
|
|
unsigned cmd;
|
|
|
|
double new_x = 0.0;
|
|
|
|
double new_y = 0.0;
|
|
|
|
double old_x = 0.0;
|
|
|
|
double old_y = 0.0;
|
|
|
|
bool first = true;
|
|
|
|
|
|
|
|
//Pre-Cache all the path_positions and path_distances
|
|
|
|
//This stops the PathT from having to do multiple re-projections if we need to reposition ourself
|
|
|
|
// and lets us know how many points are in the shape.
|
|
|
|
std::vector<vertex2d> path_positions;
|
|
|
|
std::vector<double> path_distances; // distance from node x-1 to node x
|
|
|
|
double total_distance = 0;
|
|
|
|
|
|
|
|
shape_path.rewind(0);
|
|
|
|
while (!agg::is_stop(cmd = shape_path.vertex(&new_x,&new_y))) //For each node in the shape
|
|
|
|
{
|
2010-06-02 13:03:30 +02:00
|
|
|
if (!first && agg::is_line_to(cmd))
|
|
|
|
{
|
2008-01-21 04:08:18 +01:00
|
|
|
double dx = old_x - new_x;
|
|
|
|
double dy = old_y - new_y;
|
2009-06-03 07:26:46 +02:00
|
|
|
double distance = std::sqrt(dx*dx + dy*dy);
|
2008-01-21 04:08:18 +01:00
|
|
|
total_distance += distance;
|
|
|
|
path_distances.push_back(distance);
|
2010-06-02 13:03:30 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-01-21 04:08:18 +01:00
|
|
|
path_distances.push_back(0);
|
2010-06-02 13:03:30 +02:00
|
|
|
}
|
|
|
|
first = false;
|
|
|
|
path_positions.push_back(vertex2d(new_x, new_y, cmd));
|
|
|
|
old_x = new_x;
|
|
|
|
old_y = new_y;
|
2010-05-27 12:19:47 +02:00
|
|
|
}
|
|
|
|
//Now path_positions is full and total_distance is correct
|
|
|
|
//shape_path shouldn't be used from here
|
Patch from David Eastcott :
1. Modified Text Symbolizer
a) corrected line fragment centering (for 2nd and subsequent lines, when line breaks occur).
b) adjusted vertical alignment calculation so that:
i) middle -> has the center of the text line(s) at the point origin
ii) bottom -> has the text line(s) below the point origin
iii) top -> has the text line(s) above the point origin
c) added new text_symbolizer attribute: 'wrap_before', value range: true/false, default == false
allows line breaks at first wrap_char before wrap_width as an alternative to the original
which was to create the line break at the first wrap_char after wrap_width
d) added new text_symbolizer attribute: 'horizontal_alignment', value range: left/middle/right, default == middle
i) left -> has all text line(s) to left of the point origin
ii) middle -> has all text line(s) centered on the the point origin
iii) right -> has all text line(s) to the right of the point origin
NOTE: dx, dy position adjustments are applied after alignments and before Justify.
e) added new text_symbolizer attribute: 'justify_alignment', value range: left/middle/right, default == middle
i) left -> after alignments, has all text line(s) are left justified (left to right reading)
ii) middle -> after alignments, has all text line(s) center justified
iii) right -> after alignments, has all text line(s) right justified (right to left reading)
f) added new text_symbolizer attribute: 'opacity', value range: 0.0 thru 1.0; 1.0 == fully opaque
g) modified positioning to compensate for both line_spacing and character_spacing, to ensure proper
centering of the text envelope. Also ensure that centering occurs correctly even if no wrapping
occurs. Line spacing is uniform and consistent and compensates for errors between text_size and
the actual size (ci.height is inconsistent, depending on case and character); fixes issue with
multi-line text where some lines have a slight gap and others are compressed together.
2. Modified shield_symbolizer
a) added the attributes:
i) allow_overlap
ii) vertical_alignment
iii) horizontal_alignment
iv) justify_alignment
v) wrap_width
vi) wrap_character
vii) wrap_before
viii) text_convert
ix) line_spacing
x) character_spacing
xi) opacity
b) added new shield_symbolizer attribute: 'unlock_image', value range: true/false, default == false
i) false == image and text placement behaviour same as before
ii) true == image placement independant of text, image is always centered at geometry point, text placed per attributes,
dx/dy only affect text.
Allows user to create point markers with text, but both the text and image rendering collision detection are done
as a pair (they come and go together - solves problem if using point_symbolizer and text_symbolizers where one or the
other are omitted due to overlaps, but not both)
c) extended choices for the attribute 'placement' to include vertex; effect is limited to the shield_symbolizer
Allows an attempted placement at every vertex available, gives additional shield placement volume when using line geometry
d) ensured that the text placement was not updating the detector unless a shield image was actually placed.
e) added new shield_symbolizer attribute: 'no_text', value range: true/false, default = false
When set true, the text for the feature is ignored ('space' subsituted) so that pure graphic symbols can be used
and no text is rendered over top of them.
2009-10-19 15:52:53 +02:00
|
|
|
|
2011-09-04 19:33:48 +02:00
|
|
|
// Ensure lines have a minimum length.
|
|
|
|
if (total_distance < p.minimum_path_length)
|
|
|
|
return;
|
|
|
|
|
2010-05-27 12:19:47 +02:00
|
|
|
double distance = 0.0;
|
Patch from David Eastcott :
1. Modified Text Symbolizer
a) corrected line fragment centering (for 2nd and subsequent lines, when line breaks occur).
b) adjusted vertical alignment calculation so that:
i) middle -> has the center of the text line(s) at the point origin
ii) bottom -> has the text line(s) below the point origin
iii) top -> has the text line(s) above the point origin
c) added new text_symbolizer attribute: 'wrap_before', value range: true/false, default == false
allows line breaks at first wrap_char before wrap_width as an alternative to the original
which was to create the line break at the first wrap_char after wrap_width
d) added new text_symbolizer attribute: 'horizontal_alignment', value range: left/middle/right, default == middle
i) left -> has all text line(s) to left of the point origin
ii) middle -> has all text line(s) centered on the the point origin
iii) right -> has all text line(s) to the right of the point origin
NOTE: dx, dy position adjustments are applied after alignments and before Justify.
e) added new text_symbolizer attribute: 'justify_alignment', value range: left/middle/right, default == middle
i) left -> after alignments, has all text line(s) are left justified (left to right reading)
ii) middle -> after alignments, has all text line(s) center justified
iii) right -> after alignments, has all text line(s) right justified (right to left reading)
f) added new text_symbolizer attribute: 'opacity', value range: 0.0 thru 1.0; 1.0 == fully opaque
g) modified positioning to compensate for both line_spacing and character_spacing, to ensure proper
centering of the text envelope. Also ensure that centering occurs correctly even if no wrapping
occurs. Line spacing is uniform and consistent and compensates for errors between text_size and
the actual size (ci.height is inconsistent, depending on case and character); fixes issue with
multi-line text where some lines have a slight gap and others are compressed together.
2. Modified shield_symbolizer
a) added the attributes:
i) allow_overlap
ii) vertical_alignment
iii) horizontal_alignment
iv) justify_alignment
v) wrap_width
vi) wrap_character
vii) wrap_before
viii) text_convert
ix) line_spacing
x) character_spacing
xi) opacity
b) added new shield_symbolizer attribute: 'unlock_image', value range: true/false, default == false
i) false == image and text placement behaviour same as before
ii) true == image placement independant of text, image is always centered at geometry point, text placed per attributes,
dx/dy only affect text.
Allows user to create point markers with text, but both the text and image rendering collision detection are done
as a pair (they come and go together - solves problem if using point_symbolizer and text_symbolizers where one or the
other are omitted due to overlaps, but not both)
c) extended choices for the attribute 'placement' to include vertex; effect is limited to the shield_symbolizer
Allows an attempted placement at every vertex available, gives additional shield placement volume when using line geometry
d) ensured that the text placement was not updating the detector unless a shield image was actually placed.
e) added new shield_symbolizer attribute: 'no_text', value range: true/false, default = false
When set true, the text for the feature is ignored ('space' subsituted) so that pure graphic symbols can be used
and no text is rendered over top of them.
2009-10-19 15:52:53 +02:00
|
|
|
|
2012-01-29 17:33:43 +01:00
|
|
|
double displacement = p.displacement.second; // displace by dy
|
Patch from David Eastcott :
1. Modified Text Symbolizer
a) corrected line fragment centering (for 2nd and subsequent lines, when line breaks occur).
b) adjusted vertical alignment calculation so that:
i) middle -> has the center of the text line(s) at the point origin
ii) bottom -> has the text line(s) below the point origin
iii) top -> has the text line(s) above the point origin
c) added new text_symbolizer attribute: 'wrap_before', value range: true/false, default == false
allows line breaks at first wrap_char before wrap_width as an alternative to the original
which was to create the line break at the first wrap_char after wrap_width
d) added new text_symbolizer attribute: 'horizontal_alignment', value range: left/middle/right, default == middle
i) left -> has all text line(s) to left of the point origin
ii) middle -> has all text line(s) centered on the the point origin
iii) right -> has all text line(s) to the right of the point origin
NOTE: dx, dy position adjustments are applied after alignments and before Justify.
e) added new text_symbolizer attribute: 'justify_alignment', value range: left/middle/right, default == middle
i) left -> after alignments, has all text line(s) are left justified (left to right reading)
ii) middle -> after alignments, has all text line(s) center justified
iii) right -> after alignments, has all text line(s) right justified (right to left reading)
f) added new text_symbolizer attribute: 'opacity', value range: 0.0 thru 1.0; 1.0 == fully opaque
g) modified positioning to compensate for both line_spacing and character_spacing, to ensure proper
centering of the text envelope. Also ensure that centering occurs correctly even if no wrapping
occurs. Line spacing is uniform and consistent and compensates for errors between text_size and
the actual size (ci.height is inconsistent, depending on case and character); fixes issue with
multi-line text where some lines have a slight gap and others are compressed together.
2. Modified shield_symbolizer
a) added the attributes:
i) allow_overlap
ii) vertical_alignment
iii) horizontal_alignment
iv) justify_alignment
v) wrap_width
vi) wrap_character
vii) wrap_before
viii) text_convert
ix) line_spacing
x) character_spacing
xi) opacity
b) added new shield_symbolizer attribute: 'unlock_image', value range: true/false, default == false
i) false == image and text placement behaviour same as before
ii) true == image placement independant of text, image is always centered at geometry point, text placed per attributes,
dx/dy only affect text.
Allows user to create point markers with text, but both the text and image rendering collision detection are done
as a pair (they come and go together - solves problem if using point_symbolizer and text_symbolizers where one or the
other are omitted due to overlaps, but not both)
c) extended choices for the attribute 'placement' to include vertex; effect is limited to the shield_symbolizer
Allows an attempted placement at every vertex available, gives additional shield placement volume when using line geometry
d) ensured that the text placement was not updating the detector unless a shield image was actually placed.
e) added new shield_symbolizer attribute: 'no_text', value range: true/false, default = false
When set true, the text for the feature is ignored ('space' subsituted) so that pure graphic symbols can be used
and no text is rendered over top of them.
2009-10-19 15:52:53 +02:00
|
|
|
|
2010-05-27 12:19:47 +02:00
|
|
|
//Calculate a target_distance that will place the labels centered evenly rather than offset from the start of the linestring
|
2012-01-22 18:41:04 +01:00
|
|
|
if (total_distance < string_width_) //Can't place any strings
|
2008-01-16 02:13:27 +01:00
|
|
|
return;
|
Patch from David Eastcott :
1. Modified Text Symbolizer
a) corrected line fragment centering (for 2nd and subsequent lines, when line breaks occur).
b) adjusted vertical alignment calculation so that:
i) middle -> has the center of the text line(s) at the point origin
ii) bottom -> has the text line(s) below the point origin
iii) top -> has the text line(s) above the point origin
c) added new text_symbolizer attribute: 'wrap_before', value range: true/false, default == false
allows line breaks at first wrap_char before wrap_width as an alternative to the original
which was to create the line break at the first wrap_char after wrap_width
d) added new text_symbolizer attribute: 'horizontal_alignment', value range: left/middle/right, default == middle
i) left -> has all text line(s) to left of the point origin
ii) middle -> has all text line(s) centered on the the point origin
iii) right -> has all text line(s) to the right of the point origin
NOTE: dx, dy position adjustments are applied after alignments and before Justify.
e) added new text_symbolizer attribute: 'justify_alignment', value range: left/middle/right, default == middle
i) left -> after alignments, has all text line(s) are left justified (left to right reading)
ii) middle -> after alignments, has all text line(s) center justified
iii) right -> after alignments, has all text line(s) right justified (right to left reading)
f) added new text_symbolizer attribute: 'opacity', value range: 0.0 thru 1.0; 1.0 == fully opaque
g) modified positioning to compensate for both line_spacing and character_spacing, to ensure proper
centering of the text envelope. Also ensure that centering occurs correctly even if no wrapping
occurs. Line spacing is uniform and consistent and compensates for errors between text_size and
the actual size (ci.height is inconsistent, depending on case and character); fixes issue with
multi-line text where some lines have a slight gap and others are compressed together.
2. Modified shield_symbolizer
a) added the attributes:
i) allow_overlap
ii) vertical_alignment
iii) horizontal_alignment
iv) justify_alignment
v) wrap_width
vi) wrap_character
vii) wrap_before
viii) text_convert
ix) line_spacing
x) character_spacing
xi) opacity
b) added new shield_symbolizer attribute: 'unlock_image', value range: true/false, default == false
i) false == image and text placement behaviour same as before
ii) true == image placement independant of text, image is always centered at geometry point, text placed per attributes,
dx/dy only affect text.
Allows user to create point markers with text, but both the text and image rendering collision detection are done
as a pair (they come and go together - solves problem if using point_symbolizer and text_symbolizers where one or the
other are omitted due to overlaps, but not both)
c) extended choices for the attribute 'placement' to include vertex; effect is limited to the shield_symbolizer
Allows an attempted placement at every vertex available, gives additional shield placement volume when using line geometry
d) ensured that the text placement was not updating the detector unless a shield image was actually placed.
e) added new shield_symbolizer attribute: 'no_text', value range: true/false, default = false
When set true, the text for the feature is ignored ('space' subsituted) so that pure graphic symbols can be used
and no text is rendered over top of them.
2009-10-19 15:52:53 +02:00
|
|
|
|
2010-05-27 12:19:47 +02:00
|
|
|
//If there is no spacing then just do one label, otherwise calculate how many there should be
|
|
|
|
int num_labels = 1;
|
|
|
|
if (p.label_spacing > 0)
|
2012-01-22 18:41:04 +01:00
|
|
|
num_labels = static_cast<int> (floor(total_distance / (pi.get_actual_label_spacing() + string_width_)));
|
2010-05-27 12:19:47 +02:00
|
|
|
|
2012-01-22 18:41:04 +01:00
|
|
|
if (p.force_odd_labels && (num_labels % 2 == 0))
|
2010-06-02 13:03:30 +02:00
|
|
|
num_labels--;
|
2010-05-27 12:19:47 +02:00
|
|
|
if (num_labels <= 0)
|
2010-06-02 13:03:30 +02:00
|
|
|
num_labels = 1;
|
2010-05-27 12:19:47 +02:00
|
|
|
|
|
|
|
//Now we know how many labels we are going to place, calculate the spacing so that they will get placed evenly
|
|
|
|
double spacing = total_distance / num_labels;
|
2012-01-22 18:41:04 +01:00
|
|
|
double target_distance = (spacing - string_width_) / 2; // first label should be placed at half the spacing
|
2010-05-27 12:19:47 +02:00
|
|
|
|
|
|
|
//Calculate or read out the tolerance
|
|
|
|
double tolerance_delta, tolerance;
|
|
|
|
if (p.label_position_tolerance > 0)
|
|
|
|
{
|
2010-06-02 13:03:30 +02:00
|
|
|
tolerance = p.label_position_tolerance;
|
|
|
|
tolerance_delta = std::max ( 1.0, p.label_position_tolerance/100.0 );
|
2010-05-27 12:19:47 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-06-02 13:03:30 +02:00
|
|
|
tolerance = spacing/2.0;
|
|
|
|
tolerance_delta = std::max ( 1.0, spacing/100.0 );
|
2010-05-27 12:19:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
first = true;
|
|
|
|
for (unsigned index = 0; index < path_positions.size(); index++) //For each node in the shape
|
|
|
|
{
|
2010-06-02 13:03:30 +02:00
|
|
|
cmd = path_positions[index].cmd;
|
|
|
|
new_x = path_positions[index].x;
|
|
|
|
new_y = path_positions[index].y;
|
2010-05-27 12:19:47 +02:00
|
|
|
|
2010-06-02 13:03:30 +02:00
|
|
|
if (first || agg::is_move_to(cmd)) //Don't do any processing if it is the first node
|
|
|
|
{
|
2007-11-02 13:50:15 +01:00
|
|
|
first = false;
|
2010-06-02 13:03:30 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-01-15 23:32:14 +01:00
|
|
|
//Add the length of this segment to the total we have saved up
|
2008-01-21 04:08:18 +01:00
|
|
|
double segment_length = path_distances[index];
|
2007-11-02 13:50:15 +01:00
|
|
|
distance += segment_length;
|
Patch from David Eastcott :
1. Modified Text Symbolizer
a) corrected line fragment centering (for 2nd and subsequent lines, when line breaks occur).
b) adjusted vertical alignment calculation so that:
i) middle -> has the center of the text line(s) at the point origin
ii) bottom -> has the text line(s) below the point origin
iii) top -> has the text line(s) above the point origin
c) added new text_symbolizer attribute: 'wrap_before', value range: true/false, default == false
allows line breaks at first wrap_char before wrap_width as an alternative to the original
which was to create the line break at the first wrap_char after wrap_width
d) added new text_symbolizer attribute: 'horizontal_alignment', value range: left/middle/right, default == middle
i) left -> has all text line(s) to left of the point origin
ii) middle -> has all text line(s) centered on the the point origin
iii) right -> has all text line(s) to the right of the point origin
NOTE: dx, dy position adjustments are applied after alignments and before Justify.
e) added new text_symbolizer attribute: 'justify_alignment', value range: left/middle/right, default == middle
i) left -> after alignments, has all text line(s) are left justified (left to right reading)
ii) middle -> after alignments, has all text line(s) center justified
iii) right -> after alignments, has all text line(s) right justified (right to left reading)
f) added new text_symbolizer attribute: 'opacity', value range: 0.0 thru 1.0; 1.0 == fully opaque
g) modified positioning to compensate for both line_spacing and character_spacing, to ensure proper
centering of the text envelope. Also ensure that centering occurs correctly even if no wrapping
occurs. Line spacing is uniform and consistent and compensates for errors between text_size and
the actual size (ci.height is inconsistent, depending on case and character); fixes issue with
multi-line text where some lines have a slight gap and others are compressed together.
2. Modified shield_symbolizer
a) added the attributes:
i) allow_overlap
ii) vertical_alignment
iii) horizontal_alignment
iv) justify_alignment
v) wrap_width
vi) wrap_character
vii) wrap_before
viii) text_convert
ix) line_spacing
x) character_spacing
xi) opacity
b) added new shield_symbolizer attribute: 'unlock_image', value range: true/false, default == false
i) false == image and text placement behaviour same as before
ii) true == image placement independant of text, image is always centered at geometry point, text placed per attributes,
dx/dy only affect text.
Allows user to create point markers with text, but both the text and image rendering collision detection are done
as a pair (they come and go together - solves problem if using point_symbolizer and text_symbolizers where one or the
other are omitted due to overlaps, but not both)
c) extended choices for the attribute 'placement' to include vertex; effect is limited to the shield_symbolizer
Allows an attempted placement at every vertex available, gives additional shield placement volume when using line geometry
d) ensured that the text placement was not updating the detector unless a shield image was actually placed.
e) added new shield_symbolizer attribute: 'no_text', value range: true/false, default = false
When set true, the text for the feature is ignored ('space' subsituted) so that pure graphic symbols can be used
and no text is rendered over top of them.
2009-10-19 15:52:53 +02:00
|
|
|
|
2008-01-15 23:32:14 +01:00
|
|
|
//While we have enough distance to place text in
|
2007-11-02 13:50:15 +01:00
|
|
|
while (distance > target_distance)
|
|
|
|
{
|
2010-06-02 13:03:30 +02:00
|
|
|
for (double diff = 0; diff < tolerance; diff += tolerance_delta)
|
|
|
|
{
|
|
|
|
for(int dir = -1; dir < 2; dir+=2) //-1, +1
|
|
|
|
{
|
|
|
|
//Record details for the start of the string placement
|
|
|
|
int orientation = 0;
|
2012-01-28 00:09:58 +01:00
|
|
|
std::auto_ptr<text_path> current_placement = get_placement_offset(path_positions, path_distances, orientation, index, segment_length - (distance - target_distance) + (diff*dir));
|
2010-06-02 13:03:30 +02:00
|
|
|
|
|
|
|
//We were unable to place here
|
|
|
|
if (current_placement.get() == NULL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
//Apply displacement
|
|
|
|
//NOTE: The text is centered on the line in get_placement_offset, so we are offsetting from there
|
|
|
|
if (displacement != 0)
|
|
|
|
{
|
|
|
|
//Average the angle of all characters and then offset them all by that angle
|
|
|
|
//NOTE: This probably calculates a bad angle due to going around the circle, test this!
|
|
|
|
double anglesum = 0;
|
|
|
|
for (unsigned i = 0; i < current_placement->nodes_.size(); i++)
|
|
|
|
{
|
|
|
|
anglesum += current_placement->nodes_[i].angle;
|
|
|
|
}
|
|
|
|
anglesum /= current_placement->nodes_.size(); //Now it is angle average
|
|
|
|
|
|
|
|
//Offset all the characters by this angle
|
|
|
|
for (unsigned i = 0; i < current_placement->nodes_.size(); i++)
|
|
|
|
{
|
2012-01-22 18:41:04 +01:00
|
|
|
current_placement->nodes_[i].x += pi.get_scale_factor() * displacement*cos(anglesum+M_PI/2);
|
|
|
|
current_placement->nodes_[i].y += pi.get_scale_factor() * displacement*sin(anglesum+M_PI/2);
|
2010-06-02 13:03:30 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-22 18:41:04 +01:00
|
|
|
bool status = test_placement(current_placement, orientation);
|
2010-06-02 13:03:30 +02:00
|
|
|
|
|
|
|
if (status) //We have successfully placed one
|
|
|
|
{
|
2012-01-22 18:41:04 +01:00
|
|
|
pi.placements.push_back(current_placement.release());
|
|
|
|
update_detector();
|
2010-06-02 13:03:30 +02:00
|
|
|
|
|
|
|
//Totally break out of the loops
|
|
|
|
diff = tolerance;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//If we've failed to place, remove all the envelopes we've added up
|
2012-01-22 18:41:04 +01:00
|
|
|
while (!pi.envelopes.empty())
|
|
|
|
pi.envelopes.pop();
|
2010-06-02 13:03:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//Don't need to loop twice when diff = 0
|
|
|
|
if (diff == 0)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
distance -= target_distance; //Consume the spacing gap we have used up
|
|
|
|
target_distance = spacing; //Need to reset the target_distance as it is spacing/2 for the first label.
|
2008-01-21 04:08:18 +01:00
|
|
|
}
|
2010-06-02 13:03:30 +02:00
|
|
|
}
|
2010-05-27 12:19:47 +02:00
|
|
|
|
2010-06-02 13:03:30 +02:00
|
|
|
old_x = new_x;
|
|
|
|
old_y = new_y;
|
2010-05-27 12:19:47 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename DetectorT>
|
2012-01-28 00:09:58 +01:00
|
|
|
std::auto_ptr<text_path> placement_finder<DetectorT>::get_placement_offset(const std::vector<vertex2d> &path_positions, const std::vector<double> &path_distances, int &orientation, unsigned index, double distance)
|
2010-05-27 12:19:47 +02:00
|
|
|
{
|
|
|
|
//Check that the given distance is on the given index and find the correct index and distance if not
|
|
|
|
while (distance < 0 && index > 1)
|
|
|
|
{
|
2010-06-02 13:03:30 +02:00
|
|
|
index--;
|
|
|
|
distance += path_distances[index];
|
2010-05-27 12:19:47 +02:00
|
|
|
}
|
|
|
|
if (index <= 1 && distance < 0) //We've gone off the start, fail out
|
2012-01-28 00:09:58 +01:00
|
|
|
return std::auto_ptr<text_path>(NULL);
|
2010-05-27 12:19:47 +02:00
|
|
|
|
|
|
|
//Same thing, checking if we go off the end
|
|
|
|
while (index < path_distances.size() && distance > path_distances[index])
|
|
|
|
{
|
2010-06-02 13:03:30 +02:00
|
|
|
distance -= path_distances[index];
|
|
|
|
index++;
|
2010-05-27 12:19:47 +02:00
|
|
|
}
|
|
|
|
if (index >= path_distances.size())
|
2012-01-28 00:09:58 +01:00
|
|
|
return std::auto_ptr<text_path>(NULL);
|
2010-05-27 12:19:47 +02:00
|
|
|
|
|
|
|
//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;
|
|
|
|
|
2012-01-28 00:09:58 +01:00
|
|
|
std::auto_ptr<text_path> current_placement(new text_path);
|
2010-05-27 12:19:47 +02:00
|
|
|
|
|
|
|
double old_x = path_positions[index-1].x;
|
|
|
|
double old_y = path_positions[index-1].y;
|
|
|
|
|
|
|
|
double new_x = path_positions[index].x;
|
|
|
|
double new_y = path_positions[index].y;
|
|
|
|
|
|
|
|
double dx = new_x - old_x;
|
|
|
|
double dy = new_y - old_y;
|
|
|
|
|
|
|
|
double segment_length = path_distances[index];
|
|
|
|
if (segment_length == 0) {
|
2010-06-02 13:03:30 +02:00
|
|
|
// Not allowed to place across on 0 length segments or discontinuities
|
2012-01-28 00:09:58 +01:00
|
|
|
return std::auto_ptr<text_path>(NULL);
|
2010-05-27 12:19:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
current_placement->starting_x = old_x + dx*distance/segment_length;
|
|
|
|
current_placement->starting_y = old_y + dy*distance/segment_length;
|
2012-01-22 18:41:04 +01:00
|
|
|
double angle = atan2(-dy, dx);
|
2010-05-27 12:19:47 +02:00
|
|
|
|
|
|
|
bool orientation_forced = (orientation != 0); //Wether the orientation was set by the caller
|
|
|
|
if (!orientation_forced)
|
2010-06-02 13:03:30 +02:00
|
|
|
orientation = (angle > 0.55*M_PI || angle < -0.45*M_PI) ? -1 : 1;
|
2010-05-27 12:19:47 +02:00
|
|
|
|
|
|
|
unsigned upside_down_char_count = 0; //Count of characters that are placed upside down.
|
|
|
|
|
2012-01-22 18:41:04 +01:00
|
|
|
for (unsigned i = 0; i < info_.num_characters(); ++i)
|
2010-05-27 12:19:47 +02:00
|
|
|
{
|
2012-01-22 18:41:04 +01:00
|
|
|
// grab the next character according to the orientation
|
|
|
|
char_info const &ci = orientation > 0 ? info_.at(i) : info_.at(info_.num_characters() - i - 1);
|
|
|
|
unsigned c = ci.c;
|
2010-05-27 12:19:47 +02:00
|
|
|
|
2010-06-02 13:03:30 +02:00
|
|
|
double last_character_angle = angle;
|
2010-05-27 12:19:47 +02:00
|
|
|
|
2010-06-02 13:03:30 +02:00
|
|
|
//Coordinates this character will start at
|
2008-03-29 21:02:16 +01:00
|
|
|
if (segment_length == 0) {
|
|
|
|
// Not allowed to place across on 0 length segments or discontinuities
|
2012-01-28 00:09:58 +01:00
|
|
|
return std::auto_ptr<text_path>(NULL);
|
2008-03-29 21:02:16 +01:00
|
|
|
}
|
2010-06-02 13:03:30 +02:00
|
|
|
double start_x = old_x + dx*distance/segment_length;
|
|
|
|
double start_y = old_y + dy*distance/segment_length;
|
|
|
|
//Coordinates this character ends at, calculated below
|
|
|
|
double end_x = 0;
|
|
|
|
double end_y = 0;
|
|
|
|
|
|
|
|
if (segment_length - distance >= ci.width)
|
|
|
|
{
|
2008-01-23 05:18:17 +01:00
|
|
|
//if the distance remaining in this segment is enough, we just go further along the segment
|
|
|
|
distance += ci.width;
|
Patch from David Eastcott :
1. Modified Text Symbolizer
a) corrected line fragment centering (for 2nd and subsequent lines, when line breaks occur).
b) adjusted vertical alignment calculation so that:
i) middle -> has the center of the text line(s) at the point origin
ii) bottom -> has the text line(s) below the point origin
iii) top -> has the text line(s) above the point origin
c) added new text_symbolizer attribute: 'wrap_before', value range: true/false, default == false
allows line breaks at first wrap_char before wrap_width as an alternative to the original
which was to create the line break at the first wrap_char after wrap_width
d) added new text_symbolizer attribute: 'horizontal_alignment', value range: left/middle/right, default == middle
i) left -> has all text line(s) to left of the point origin
ii) middle -> has all text line(s) centered on the the point origin
iii) right -> has all text line(s) to the right of the point origin
NOTE: dx, dy position adjustments are applied after alignments and before Justify.
e) added new text_symbolizer attribute: 'justify_alignment', value range: left/middle/right, default == middle
i) left -> after alignments, has all text line(s) are left justified (left to right reading)
ii) middle -> after alignments, has all text line(s) center justified
iii) right -> after alignments, has all text line(s) right justified (right to left reading)
f) added new text_symbolizer attribute: 'opacity', value range: 0.0 thru 1.0; 1.0 == fully opaque
g) modified positioning to compensate for both line_spacing and character_spacing, to ensure proper
centering of the text envelope. Also ensure that centering occurs correctly even if no wrapping
occurs. Line spacing is uniform and consistent and compensates for errors between text_size and
the actual size (ci.height is inconsistent, depending on case and character); fixes issue with
multi-line text where some lines have a slight gap and others are compressed together.
2. Modified shield_symbolizer
a) added the attributes:
i) allow_overlap
ii) vertical_alignment
iii) horizontal_alignment
iv) justify_alignment
v) wrap_width
vi) wrap_character
vii) wrap_before
viii) text_convert
ix) line_spacing
x) character_spacing
xi) opacity
b) added new shield_symbolizer attribute: 'unlock_image', value range: true/false, default == false
i) false == image and text placement behaviour same as before
ii) true == image placement independant of text, image is always centered at geometry point, text placed per attributes,
dx/dy only affect text.
Allows user to create point markers with text, but both the text and image rendering collision detection are done
as a pair (they come and go together - solves problem if using point_symbolizer and text_symbolizers where one or the
other are omitted due to overlaps, but not both)
c) extended choices for the attribute 'placement' to include vertex; effect is limited to the shield_symbolizer
Allows an attempted placement at every vertex available, gives additional shield placement volume when using line geometry
d) ensured that the text placement was not updating the detector unless a shield image was actually placed.
e) added new shield_symbolizer attribute: 'no_text', value range: true/false, default = false
When set true, the text for the feature is ignored ('space' subsituted) so that pure graphic symbols can be used
and no text is rendered over top of them.
2009-10-19 15:52:53 +02:00
|
|
|
|
2008-01-23 05:18:17 +01:00
|
|
|
end_x = old_x + dx*distance/segment_length;
|
|
|
|
end_y = old_y + dy*distance/segment_length;
|
2010-06-02 13:03:30 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-01-23 05:18:17 +01:00
|
|
|
//If there isn't enough distance left on this segment
|
2011-09-02 16:44:11 +02:00
|
|
|
// then we need to search until we find the line segment that ends further than ci.width away
|
2008-01-23 05:18:17 +01:00
|
|
|
do
|
2008-01-21 04:08:18 +01:00
|
|
|
{
|
2010-06-02 13:03:30 +02:00
|
|
|
old_x = new_x;
|
|
|
|
old_y = new_y;
|
|
|
|
index++;
|
|
|
|
if (index >= path_positions.size()) //Bail out if we run off the end of the shape
|
|
|
|
{
|
|
|
|
//std::clog << "FAIL: Out of space" << std::endl;
|
2012-01-28 00:09:58 +01:00
|
|
|
return std::auto_ptr<text_path>(NULL);
|
2010-06-02 13:03:30 +02:00
|
|
|
}
|
|
|
|
new_x = path_positions[index].x;
|
|
|
|
new_y = path_positions[index].y;
|
|
|
|
dx = new_x - old_x;
|
|
|
|
dy = new_y - old_y;
|
|
|
|
|
|
|
|
segment_length = path_distances[index];
|
2008-01-21 04:08:18 +01:00
|
|
|
}
|
2009-06-03 07:26:46 +02:00
|
|
|
while (std::sqrt(std::pow(start_x - new_x, 2) + std::pow(start_y - new_y, 2)) < ci.width); //Distance from start_ to new_
|
Patch from David Eastcott :
1. Modified Text Symbolizer
a) corrected line fragment centering (for 2nd and subsequent lines, when line breaks occur).
b) adjusted vertical alignment calculation so that:
i) middle -> has the center of the text line(s) at the point origin
ii) bottom -> has the text line(s) below the point origin
iii) top -> has the text line(s) above the point origin
c) added new text_symbolizer attribute: 'wrap_before', value range: true/false, default == false
allows line breaks at first wrap_char before wrap_width as an alternative to the original
which was to create the line break at the first wrap_char after wrap_width
d) added new text_symbolizer attribute: 'horizontal_alignment', value range: left/middle/right, default == middle
i) left -> has all text line(s) to left of the point origin
ii) middle -> has all text line(s) centered on the the point origin
iii) right -> has all text line(s) to the right of the point origin
NOTE: dx, dy position adjustments are applied after alignments and before Justify.
e) added new text_symbolizer attribute: 'justify_alignment', value range: left/middle/right, default == middle
i) left -> after alignments, has all text line(s) are left justified (left to right reading)
ii) middle -> after alignments, has all text line(s) center justified
iii) right -> after alignments, has all text line(s) right justified (right to left reading)
f) added new text_symbolizer attribute: 'opacity', value range: 0.0 thru 1.0; 1.0 == fully opaque
g) modified positioning to compensate for both line_spacing and character_spacing, to ensure proper
centering of the text envelope. Also ensure that centering occurs correctly even if no wrapping
occurs. Line spacing is uniform and consistent and compensates for errors between text_size and
the actual size (ci.height is inconsistent, depending on case and character); fixes issue with
multi-line text where some lines have a slight gap and others are compressed together.
2. Modified shield_symbolizer
a) added the attributes:
i) allow_overlap
ii) vertical_alignment
iii) horizontal_alignment
iv) justify_alignment
v) wrap_width
vi) wrap_character
vii) wrap_before
viii) text_convert
ix) line_spacing
x) character_spacing
xi) opacity
b) added new shield_symbolizer attribute: 'unlock_image', value range: true/false, default == false
i) false == image and text placement behaviour same as before
ii) true == image placement independant of text, image is always centered at geometry point, text placed per attributes,
dx/dy only affect text.
Allows user to create point markers with text, but both the text and image rendering collision detection are done
as a pair (they come and go together - solves problem if using point_symbolizer and text_symbolizers where one or the
other are omitted due to overlaps, but not both)
c) extended choices for the attribute 'placement' to include vertex; effect is limited to the shield_symbolizer
Allows an attempted placement at every vertex available, gives additional shield placement volume when using line geometry
d) ensured that the text placement was not updating the detector unless a shield image was actually placed.
e) added new shield_symbolizer attribute: 'no_text', value range: true/false, default = false
When set true, the text for the feature is ignored ('space' subsituted) so that pure graphic symbols can be used
and no text is rendered over top of them.
2009-10-19 15:52:53 +02:00
|
|
|
|
2008-01-23 05:18:17 +01:00
|
|
|
//Calculate the position to place the end of the character on
|
|
|
|
find_line_circle_intersection(
|
2010-06-02 13:03:30 +02:00
|
|
|
start_x, start_y, ci.width,
|
|
|
|
old_x, old_y, new_x, new_y,
|
|
|
|
end_x, end_y); //results are stored in end_x, end_y
|
2008-01-23 05:18:17 +01:00
|
|
|
|
|
|
|
//Need to calculate distance on the new segment
|
2009-06-03 07:26:46 +02:00
|
|
|
distance = std::sqrt(std::pow(old_x - end_x, 2) + std::pow(old_y - end_y, 2));
|
2010-06-02 13:03:30 +02:00
|
|
|
}
|
Patch from David Eastcott :
1. Modified Text Symbolizer
a) corrected line fragment centering (for 2nd and subsequent lines, when line breaks occur).
b) adjusted vertical alignment calculation so that:
i) middle -> has the center of the text line(s) at the point origin
ii) bottom -> has the text line(s) below the point origin
iii) top -> has the text line(s) above the point origin
c) added new text_symbolizer attribute: 'wrap_before', value range: true/false, default == false
allows line breaks at first wrap_char before wrap_width as an alternative to the original
which was to create the line break at the first wrap_char after wrap_width
d) added new text_symbolizer attribute: 'horizontal_alignment', value range: left/middle/right, default == middle
i) left -> has all text line(s) to left of the point origin
ii) middle -> has all text line(s) centered on the the point origin
iii) right -> has all text line(s) to the right of the point origin
NOTE: dx, dy position adjustments are applied after alignments and before Justify.
e) added new text_symbolizer attribute: 'justify_alignment', value range: left/middle/right, default == middle
i) left -> after alignments, has all text line(s) are left justified (left to right reading)
ii) middle -> after alignments, has all text line(s) center justified
iii) right -> after alignments, has all text line(s) right justified (right to left reading)
f) added new text_symbolizer attribute: 'opacity', value range: 0.0 thru 1.0; 1.0 == fully opaque
g) modified positioning to compensate for both line_spacing and character_spacing, to ensure proper
centering of the text envelope. Also ensure that centering occurs correctly even if no wrapping
occurs. Line spacing is uniform and consistent and compensates for errors between text_size and
the actual size (ci.height is inconsistent, depending on case and character); fixes issue with
multi-line text where some lines have a slight gap and others are compressed together.
2. Modified shield_symbolizer
a) added the attributes:
i) allow_overlap
ii) vertical_alignment
iii) horizontal_alignment
iv) justify_alignment
v) wrap_width
vi) wrap_character
vii) wrap_before
viii) text_convert
ix) line_spacing
x) character_spacing
xi) opacity
b) added new shield_symbolizer attribute: 'unlock_image', value range: true/false, default == false
i) false == image and text placement behaviour same as before
ii) true == image placement independant of text, image is always centered at geometry point, text placed per attributes,
dx/dy only affect text.
Allows user to create point markers with text, but both the text and image rendering collision detection are done
as a pair (they come and go together - solves problem if using point_symbolizer and text_symbolizers where one or the
other are omitted due to overlaps, but not both)
c) extended choices for the attribute 'placement' to include vertex; effect is limited to the shield_symbolizer
Allows an attempted placement at every vertex available, gives additional shield placement volume when using line geometry
d) ensured that the text placement was not updating the detector unless a shield image was actually placed.
e) added new shield_symbolizer attribute: 'no_text', value range: true/false, default = false
When set true, the text for the feature is ignored ('space' subsituted) so that pure graphic symbols can be used
and no text is rendered over top of them.
2009-10-19 15:52:53 +02:00
|
|
|
|
2010-06-02 13:03:30 +02:00
|
|
|
//Calculate angle from the start of the character to the end based on start_/end_ position
|
2011-09-08 05:47:56 +02:00
|
|
|
angle = fast_atan2(start_y-end_y, end_x-start_x);
|
Patch from David Eastcott :
1. Modified Text Symbolizer
a) corrected line fragment centering (for 2nd and subsequent lines, when line breaks occur).
b) adjusted vertical alignment calculation so that:
i) middle -> has the center of the text line(s) at the point origin
ii) bottom -> has the text line(s) below the point origin
iii) top -> has the text line(s) above the point origin
c) added new text_symbolizer attribute: 'wrap_before', value range: true/false, default == false
allows line breaks at first wrap_char before wrap_width as an alternative to the original
which was to create the line break at the first wrap_char after wrap_width
d) added new text_symbolizer attribute: 'horizontal_alignment', value range: left/middle/right, default == middle
i) left -> has all text line(s) to left of the point origin
ii) middle -> has all text line(s) centered on the the point origin
iii) right -> has all text line(s) to the right of the point origin
NOTE: dx, dy position adjustments are applied after alignments and before Justify.
e) added new text_symbolizer attribute: 'justify_alignment', value range: left/middle/right, default == middle
i) left -> after alignments, has all text line(s) are left justified (left to right reading)
ii) middle -> after alignments, has all text line(s) center justified
iii) right -> after alignments, has all text line(s) right justified (right to left reading)
f) added new text_symbolizer attribute: 'opacity', value range: 0.0 thru 1.0; 1.0 == fully opaque
g) modified positioning to compensate for both line_spacing and character_spacing, to ensure proper
centering of the text envelope. Also ensure that centering occurs correctly even if no wrapping
occurs. Line spacing is uniform and consistent and compensates for errors between text_size and
the actual size (ci.height is inconsistent, depending on case and character); fixes issue with
multi-line text where some lines have a slight gap and others are compressed together.
2. Modified shield_symbolizer
a) added the attributes:
i) allow_overlap
ii) vertical_alignment
iii) horizontal_alignment
iv) justify_alignment
v) wrap_width
vi) wrap_character
vii) wrap_before
viii) text_convert
ix) line_spacing
x) character_spacing
xi) opacity
b) added new shield_symbolizer attribute: 'unlock_image', value range: true/false, default == false
i) false == image and text placement behaviour same as before
ii) true == image placement independant of text, image is always centered at geometry point, text placed per attributes,
dx/dy only affect text.
Allows user to create point markers with text, but both the text and image rendering collision detection are done
as a pair (they come and go together - solves problem if using point_symbolizer and text_symbolizers where one or the
other are omitted due to overlaps, but not both)
c) extended choices for the attribute 'placement' to include vertex; effect is limited to the shield_symbolizer
Allows an attempted placement at every vertex available, gives additional shield placement volume when using line geometry
d) ensured that the text placement was not updating the detector unless a shield image was actually placed.
e) added new shield_symbolizer attribute: 'no_text', value range: true/false, default = false
When set true, the text for the feature is ignored ('space' subsituted) so that pure graphic symbols can be used
and no text is rendered over top of them.
2009-10-19 15:52:53 +02:00
|
|
|
|
2010-06-02 13:03:30 +02:00
|
|
|
//Test last_character_angle vs angle
|
|
|
|
// since our rendering angle has changed then check against our
|
|
|
|
// max allowable angle change.
|
|
|
|
double angle_delta = last_character_angle - angle;
|
|
|
|
// normalise between -180 and 180
|
|
|
|
while (angle_delta > M_PI)
|
2008-01-23 05:18:17 +01:00
|
|
|
angle_delta -= 2*M_PI;
|
2010-06-02 13:03:30 +02:00
|
|
|
while (angle_delta < -M_PI)
|
2008-01-23 05:18:17 +01:00
|
|
|
angle_delta += 2*M_PI;
|
2010-06-02 13:03:30 +02:00
|
|
|
if (p.max_char_angle_delta > 0 &&
|
2010-09-24 14:55:08 +02:00
|
|
|
fabs(angle_delta) > p.max_char_angle_delta)
|
2010-06-02 13:03:30 +02:00
|
|
|
{
|
2008-01-23 05:18:17 +01:00
|
|
|
//std::clog << "FAIL: Too Bendy!" << std::endl;
|
2012-01-28 00:09:58 +01:00
|
|
|
return std::auto_ptr<text_path>(NULL);
|
2010-06-02 13:03:30 +02:00
|
|
|
}
|
Patch from David Eastcott :
1. Modified Text Symbolizer
a) corrected line fragment centering (for 2nd and subsequent lines, when line breaks occur).
b) adjusted vertical alignment calculation so that:
i) middle -> has the center of the text line(s) at the point origin
ii) bottom -> has the text line(s) below the point origin
iii) top -> has the text line(s) above the point origin
c) added new text_symbolizer attribute: 'wrap_before', value range: true/false, default == false
allows line breaks at first wrap_char before wrap_width as an alternative to the original
which was to create the line break at the first wrap_char after wrap_width
d) added new text_symbolizer attribute: 'horizontal_alignment', value range: left/middle/right, default == middle
i) left -> has all text line(s) to left of the point origin
ii) middle -> has all text line(s) centered on the the point origin
iii) right -> has all text line(s) to the right of the point origin
NOTE: dx, dy position adjustments are applied after alignments and before Justify.
e) added new text_symbolizer attribute: 'justify_alignment', value range: left/middle/right, default == middle
i) left -> after alignments, has all text line(s) are left justified (left to right reading)
ii) middle -> after alignments, has all text line(s) center justified
iii) right -> after alignments, has all text line(s) right justified (right to left reading)
f) added new text_symbolizer attribute: 'opacity', value range: 0.0 thru 1.0; 1.0 == fully opaque
g) modified positioning to compensate for both line_spacing and character_spacing, to ensure proper
centering of the text envelope. Also ensure that centering occurs correctly even if no wrapping
occurs. Line spacing is uniform and consistent and compensates for errors between text_size and
the actual size (ci.height is inconsistent, depending on case and character); fixes issue with
multi-line text where some lines have a slight gap and others are compressed together.
2. Modified shield_symbolizer
a) added the attributes:
i) allow_overlap
ii) vertical_alignment
iii) horizontal_alignment
iv) justify_alignment
v) wrap_width
vi) wrap_character
vii) wrap_before
viii) text_convert
ix) line_spacing
x) character_spacing
xi) opacity
b) added new shield_symbolizer attribute: 'unlock_image', value range: true/false, default == false
i) false == image and text placement behaviour same as before
ii) true == image placement independant of text, image is always centered at geometry point, text placed per attributes,
dx/dy only affect text.
Allows user to create point markers with text, but both the text and image rendering collision detection are done
as a pair (they come and go together - solves problem if using point_symbolizer and text_symbolizers where one or the
other are omitted due to overlaps, but not both)
c) extended choices for the attribute 'placement' to include vertex; effect is limited to the shield_symbolizer
Allows an attempted placement at every vertex available, gives additional shield placement volume when using line geometry
d) ensured that the text placement was not updating the detector unless a shield image was actually placed.
e) added new shield_symbolizer attribute: 'no_text', value range: true/false, default = false
When set true, the text for the feature is ignored ('space' subsituted) so that pure graphic symbols can be used
and no text is rendered over top of them.
2009-10-19 15:52:53 +02:00
|
|
|
|
2010-06-02 13:03:30 +02:00
|
|
|
double render_angle = angle;
|
2012-01-31 19:01:19 +01:00
|
|
|
//double cosa = fast_cos(angle); TODO: do we need them?
|
|
|
|
//double sina = fast_sin(angle);
|
Patch from David Eastcott :
1. Modified Text Symbolizer
a) corrected line fragment centering (for 2nd and subsequent lines, when line breaks occur).
b) adjusted vertical alignment calculation so that:
i) middle -> has the center of the text line(s) at the point origin
ii) bottom -> has the text line(s) below the point origin
iii) top -> has the text line(s) above the point origin
c) added new text_symbolizer attribute: 'wrap_before', value range: true/false, default == false
allows line breaks at first wrap_char before wrap_width as an alternative to the original
which was to create the line break at the first wrap_char after wrap_width
d) added new text_symbolizer attribute: 'horizontal_alignment', value range: left/middle/right, default == middle
i) left -> has all text line(s) to left of the point origin
ii) middle -> has all text line(s) centered on the the point origin
iii) right -> has all text line(s) to the right of the point origin
NOTE: dx, dy position adjustments are applied after alignments and before Justify.
e) added new text_symbolizer attribute: 'justify_alignment', value range: left/middle/right, default == middle
i) left -> after alignments, has all text line(s) are left justified (left to right reading)
ii) middle -> after alignments, has all text line(s) center justified
iii) right -> after alignments, has all text line(s) right justified (right to left reading)
f) added new text_symbolizer attribute: 'opacity', value range: 0.0 thru 1.0; 1.0 == fully opaque
g) modified positioning to compensate for both line_spacing and character_spacing, to ensure proper
centering of the text envelope. Also ensure that centering occurs correctly even if no wrapping
occurs. Line spacing is uniform and consistent and compensates for errors between text_size and
the actual size (ci.height is inconsistent, depending on case and character); fixes issue with
multi-line text where some lines have a slight gap and others are compressed together.
2. Modified shield_symbolizer
a) added the attributes:
i) allow_overlap
ii) vertical_alignment
iii) horizontal_alignment
iv) justify_alignment
v) wrap_width
vi) wrap_character
vii) wrap_before
viii) text_convert
ix) line_spacing
x) character_spacing
xi) opacity
b) added new shield_symbolizer attribute: 'unlock_image', value range: true/false, default == false
i) false == image and text placement behaviour same as before
ii) true == image placement independant of text, image is always centered at geometry point, text placed per attributes,
dx/dy only affect text.
Allows user to create point markers with text, but both the text and image rendering collision detection are done
as a pair (they come and go together - solves problem if using point_symbolizer and text_symbolizers where one or the
other are omitted due to overlaps, but not both)
c) extended choices for the attribute 'placement' to include vertex; effect is limited to the shield_symbolizer
Allows an attempted placement at every vertex available, gives additional shield placement volume when using line geometry
d) ensured that the text placement was not updating the detector unless a shield image was actually placed.
e) added new shield_symbolizer attribute: 'no_text', value range: true/false, default = false
When set true, the text for the feature is ignored ('space' subsituted) so that pure graphic symbols can be used
and no text is rendered over top of them.
2009-10-19 15:52:53 +02:00
|
|
|
|
2010-06-02 13:03:30 +02:00
|
|
|
double render_x = start_x;
|
|
|
|
double render_y = start_y;
|
Patch from David Eastcott :
1. Modified Text Symbolizer
a) corrected line fragment centering (for 2nd and subsequent lines, when line breaks occur).
b) adjusted vertical alignment calculation so that:
i) middle -> has the center of the text line(s) at the point origin
ii) bottom -> has the text line(s) below the point origin
iii) top -> has the text line(s) above the point origin
c) added new text_symbolizer attribute: 'wrap_before', value range: true/false, default == false
allows line breaks at first wrap_char before wrap_width as an alternative to the original
which was to create the line break at the first wrap_char after wrap_width
d) added new text_symbolizer attribute: 'horizontal_alignment', value range: left/middle/right, default == middle
i) left -> has all text line(s) to left of the point origin
ii) middle -> has all text line(s) centered on the the point origin
iii) right -> has all text line(s) to the right of the point origin
NOTE: dx, dy position adjustments are applied after alignments and before Justify.
e) added new text_symbolizer attribute: 'justify_alignment', value range: left/middle/right, default == middle
i) left -> after alignments, has all text line(s) are left justified (left to right reading)
ii) middle -> after alignments, has all text line(s) center justified
iii) right -> after alignments, has all text line(s) right justified (right to left reading)
f) added new text_symbolizer attribute: 'opacity', value range: 0.0 thru 1.0; 1.0 == fully opaque
g) modified positioning to compensate for both line_spacing and character_spacing, to ensure proper
centering of the text envelope. Also ensure that centering occurs correctly even if no wrapping
occurs. Line spacing is uniform and consistent and compensates for errors between text_size and
the actual size (ci.height is inconsistent, depending on case and character); fixes issue with
multi-line text where some lines have a slight gap and others are compressed together.
2. Modified shield_symbolizer
a) added the attributes:
i) allow_overlap
ii) vertical_alignment
iii) horizontal_alignment
iv) justify_alignment
v) wrap_width
vi) wrap_character
vii) wrap_before
viii) text_convert
ix) line_spacing
x) character_spacing
xi) opacity
b) added new shield_symbolizer attribute: 'unlock_image', value range: true/false, default == false
i) false == image and text placement behaviour same as before
ii) true == image placement independant of text, image is always centered at geometry point, text placed per attributes,
dx/dy only affect text.
Allows user to create point markers with text, but both the text and image rendering collision detection are done
as a pair (they come and go together - solves problem if using point_symbolizer and text_symbolizers where one or the
other are omitted due to overlaps, but not both)
c) extended choices for the attribute 'placement' to include vertex; effect is limited to the shield_symbolizer
Allows an attempted placement at every vertex available, gives additional shield placement volume when using line geometry
d) ensured that the text placement was not updating the detector unless a shield image was actually placed.
e) added new shield_symbolizer attribute: 'no_text', value range: true/false, default = false
When set true, the text for the feature is ignored ('space' subsituted) so that pure graphic symbols can be used
and no text is rendered over top of them.
2009-10-19 15:52:53 +02:00
|
|
|
|
2010-06-02 13:03:30 +02:00
|
|
|
//Center the text on the line
|
2012-01-22 18:41:04 +01:00
|
|
|
double char_height = ci.avg_height;
|
|
|
|
render_x -= char_height/2.0*cos(render_angle+M_PI/2);
|
|
|
|
render_y += char_height/2.0*sin(render_angle+M_PI/2);
|
Patch from David Eastcott :
1. Modified Text Symbolizer
a) corrected line fragment centering (for 2nd and subsequent lines, when line breaks occur).
b) adjusted vertical alignment calculation so that:
i) middle -> has the center of the text line(s) at the point origin
ii) bottom -> has the text line(s) below the point origin
iii) top -> has the text line(s) above the point origin
c) added new text_symbolizer attribute: 'wrap_before', value range: true/false, default == false
allows line breaks at first wrap_char before wrap_width as an alternative to the original
which was to create the line break at the first wrap_char after wrap_width
d) added new text_symbolizer attribute: 'horizontal_alignment', value range: left/middle/right, default == middle
i) left -> has all text line(s) to left of the point origin
ii) middle -> has all text line(s) centered on the the point origin
iii) right -> has all text line(s) to the right of the point origin
NOTE: dx, dy position adjustments are applied after alignments and before Justify.
e) added new text_symbolizer attribute: 'justify_alignment', value range: left/middle/right, default == middle
i) left -> after alignments, has all text line(s) are left justified (left to right reading)
ii) middle -> after alignments, has all text line(s) center justified
iii) right -> after alignments, has all text line(s) right justified (right to left reading)
f) added new text_symbolizer attribute: 'opacity', value range: 0.0 thru 1.0; 1.0 == fully opaque
g) modified positioning to compensate for both line_spacing and character_spacing, to ensure proper
centering of the text envelope. Also ensure that centering occurs correctly even if no wrapping
occurs. Line spacing is uniform and consistent and compensates for errors between text_size and
the actual size (ci.height is inconsistent, depending on case and character); fixes issue with
multi-line text where some lines have a slight gap and others are compressed together.
2. Modified shield_symbolizer
a) added the attributes:
i) allow_overlap
ii) vertical_alignment
iii) horizontal_alignment
iv) justify_alignment
v) wrap_width
vi) wrap_character
vii) wrap_before
viii) text_convert
ix) line_spacing
x) character_spacing
xi) opacity
b) added new shield_symbolizer attribute: 'unlock_image', value range: true/false, default == false
i) false == image and text placement behaviour same as before
ii) true == image placement independant of text, image is always centered at geometry point, text placed per attributes,
dx/dy only affect text.
Allows user to create point markers with text, but both the text and image rendering collision detection are done
as a pair (they come and go together - solves problem if using point_symbolizer and text_symbolizers where one or the
other are omitted due to overlaps, but not both)
c) extended choices for the attribute 'placement' to include vertex; effect is limited to the shield_symbolizer
Allows an attempted placement at every vertex available, gives additional shield placement volume when using line geometry
d) ensured that the text placement was not updating the detector unless a shield image was actually placed.
e) added new shield_symbolizer attribute: 'no_text', value range: true/false, default = false
When set true, the text for the feature is ignored ('space' subsituted) so that pure graphic symbols can be used
and no text is rendered over top of them.
2009-10-19 15:52:53 +02:00
|
|
|
|
2010-06-02 13:03:30 +02:00
|
|
|
if (orientation < 0)
|
|
|
|
{
|
2008-01-21 04:08:18 +01:00
|
|
|
// rotate in place
|
2012-01-22 18:41:04 +01:00
|
|
|
render_x += ci.width*cos(render_angle) - (char_height-2)*sin(render_angle);
|
|
|
|
render_y -= ci.width*sin(render_angle) + (char_height-2)*cos(render_angle);
|
2008-01-21 04:08:18 +01:00
|
|
|
render_angle += M_PI;
|
2010-06-02 13:03:30 +02:00
|
|
|
}
|
|
|
|
current_placement->add_node(c,render_x - current_placement->starting_x,
|
|
|
|
-render_y + current_placement->starting_y,
|
2012-01-22 01:08:14 +01:00
|
|
|
render_angle, ci.format);
|
Patch from David Eastcott :
1. Modified Text Symbolizer
a) corrected line fragment centering (for 2nd and subsequent lines, when line breaks occur).
b) adjusted vertical alignment calculation so that:
i) middle -> has the center of the text line(s) at the point origin
ii) bottom -> has the text line(s) below the point origin
iii) top -> has the text line(s) above the point origin
c) added new text_symbolizer attribute: 'wrap_before', value range: true/false, default == false
allows line breaks at first wrap_char before wrap_width as an alternative to the original
which was to create the line break at the first wrap_char after wrap_width
d) added new text_symbolizer attribute: 'horizontal_alignment', value range: left/middle/right, default == middle
i) left -> has all text line(s) to left of the point origin
ii) middle -> has all text line(s) centered on the the point origin
iii) right -> has all text line(s) to the right of the point origin
NOTE: dx, dy position adjustments are applied after alignments and before Justify.
e) added new text_symbolizer attribute: 'justify_alignment', value range: left/middle/right, default == middle
i) left -> after alignments, has all text line(s) are left justified (left to right reading)
ii) middle -> after alignments, has all text line(s) center justified
iii) right -> after alignments, has all text line(s) right justified (right to left reading)
f) added new text_symbolizer attribute: 'opacity', value range: 0.0 thru 1.0; 1.0 == fully opaque
g) modified positioning to compensate for both line_spacing and character_spacing, to ensure proper
centering of the text envelope. Also ensure that centering occurs correctly even if no wrapping
occurs. Line spacing is uniform and consistent and compensates for errors between text_size and
the actual size (ci.height is inconsistent, depending on case and character); fixes issue with
multi-line text where some lines have a slight gap and others are compressed together.
2. Modified shield_symbolizer
a) added the attributes:
i) allow_overlap
ii) vertical_alignment
iii) horizontal_alignment
iv) justify_alignment
v) wrap_width
vi) wrap_character
vii) wrap_before
viii) text_convert
ix) line_spacing
x) character_spacing
xi) opacity
b) added new shield_symbolizer attribute: 'unlock_image', value range: true/false, default == false
i) false == image and text placement behaviour same as before
ii) true == image placement independant of text, image is always centered at geometry point, text placed per attributes,
dx/dy only affect text.
Allows user to create point markers with text, but both the text and image rendering collision detection are done
as a pair (they come and go together - solves problem if using point_symbolizer and text_symbolizers where one or the
other are omitted due to overlaps, but not both)
c) extended choices for the attribute 'placement' to include vertex; effect is limited to the shield_symbolizer
Allows an attempted placement at every vertex available, gives additional shield placement volume when using line geometry
d) ensured that the text placement was not updating the detector unless a shield image was actually placed.
e) added new shield_symbolizer attribute: 'no_text', value range: true/false, default = false
When set true, the text for the feature is ignored ('space' subsituted) so that pure graphic symbols can be used
and no text is rendered over top of them.
2009-10-19 15:52:53 +02:00
|
|
|
|
2010-06-02 13:03:30 +02:00
|
|
|
//Normalise to 0 <= angle < 2PI
|
|
|
|
while (render_angle >= 2*M_PI)
|
2008-01-23 22:38:48 +01:00
|
|
|
render_angle -= 2*M_PI;
|
2010-06-02 13:03:30 +02:00
|
|
|
while (render_angle < 0)
|
2008-01-23 22:38:48 +01:00
|
|
|
render_angle += 2*M_PI;
|
Patch from David Eastcott :
1. Modified Text Symbolizer
a) corrected line fragment centering (for 2nd and subsequent lines, when line breaks occur).
b) adjusted vertical alignment calculation so that:
i) middle -> has the center of the text line(s) at the point origin
ii) bottom -> has the text line(s) below the point origin
iii) top -> has the text line(s) above the point origin
c) added new text_symbolizer attribute: 'wrap_before', value range: true/false, default == false
allows line breaks at first wrap_char before wrap_width as an alternative to the original
which was to create the line break at the first wrap_char after wrap_width
d) added new text_symbolizer attribute: 'horizontal_alignment', value range: left/middle/right, default == middle
i) left -> has all text line(s) to left of the point origin
ii) middle -> has all text line(s) centered on the the point origin
iii) right -> has all text line(s) to the right of the point origin
NOTE: dx, dy position adjustments are applied after alignments and before Justify.
e) added new text_symbolizer attribute: 'justify_alignment', value range: left/middle/right, default == middle
i) left -> after alignments, has all text line(s) are left justified (left to right reading)
ii) middle -> after alignments, has all text line(s) center justified
iii) right -> after alignments, has all text line(s) right justified (right to left reading)
f) added new text_symbolizer attribute: 'opacity', value range: 0.0 thru 1.0; 1.0 == fully opaque
g) modified positioning to compensate for both line_spacing and character_spacing, to ensure proper
centering of the text envelope. Also ensure that centering occurs correctly even if no wrapping
occurs. Line spacing is uniform and consistent and compensates for errors between text_size and
the actual size (ci.height is inconsistent, depending on case and character); fixes issue with
multi-line text where some lines have a slight gap and others are compressed together.
2. Modified shield_symbolizer
a) added the attributes:
i) allow_overlap
ii) vertical_alignment
iii) horizontal_alignment
iv) justify_alignment
v) wrap_width
vi) wrap_character
vii) wrap_before
viii) text_convert
ix) line_spacing
x) character_spacing
xi) opacity
b) added new shield_symbolizer attribute: 'unlock_image', value range: true/false, default == false
i) false == image and text placement behaviour same as before
ii) true == image placement independant of text, image is always centered at geometry point, text placed per attributes,
dx/dy only affect text.
Allows user to create point markers with text, but both the text and image rendering collision detection are done
as a pair (they come and go together - solves problem if using point_symbolizer and text_symbolizers where one or the
other are omitted due to overlaps, but not both)
c) extended choices for the attribute 'placement' to include vertex; effect is limited to the shield_symbolizer
Allows an attempted placement at every vertex available, gives additional shield placement volume when using line geometry
d) ensured that the text placement was not updating the detector unless a shield image was actually placed.
e) added new shield_symbolizer attribute: 'no_text', value range: true/false, default = false
When set true, the text for the feature is ignored ('space' subsituted) so that pure graphic symbols can be used
and no text is rendered over top of them.
2009-10-19 15:52:53 +02:00
|
|
|
|
2010-06-02 13:03:30 +02:00
|
|
|
if (render_angle > M_PI/2 && render_angle < 1.5*M_PI)
|
2008-01-23 22:38:48 +01:00
|
|
|
upside_down_char_count++;
|
2010-05-27 12:19:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//If we placed too many characters upside down
|
2012-01-22 18:41:04 +01:00
|
|
|
if (upside_down_char_count >= info_.num_characters()/2.0)
|
2010-05-27 12:19:47 +02:00
|
|
|
{
|
2010-06-02 13:03:30 +02:00
|
|
|
//if we auto-detected the orientation then retry with the opposite orientation
|
|
|
|
if (!orientation_forced)
|
|
|
|
{
|
2008-01-23 22:38:48 +01:00
|
|
|
orientation = -orientation;
|
2012-01-22 18:41:04 +01:00
|
|
|
current_placement = get_placement_offset(path_positions, path_distances, orientation, initial_index, initial_distance);
|
2010-06-02 13:03:30 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-01-23 22:38:48 +01:00
|
|
|
//Otherwise we have failed to find a placement
|
2008-01-23 22:39:49 +01:00
|
|
|
//std::clog << "FAIL: Double upside-down!" << std::endl;
|
2012-01-28 00:09:58 +01:00
|
|
|
return std::auto_ptr<text_path>(NULL);
|
2010-06-02 13:03:30 +02:00
|
|
|
}
|
2010-05-27 12:19:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return current_placement;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename DetectorT>
|
2012-01-28 00:09:58 +01:00
|
|
|
bool placement_finder<DetectorT>::test_placement(const std::auto_ptr<text_path> & current_placement, const int & orientation)
|
2010-05-27 12:19:47 +02:00
|
|
|
{
|
|
|
|
//Create and test envelopes
|
|
|
|
bool status = true;
|
2012-01-22 18:41:04 +01:00
|
|
|
for (unsigned i = 0; i < info_.num_characters(); ++i)
|
2010-05-27 12:19:47 +02:00
|
|
|
{
|
2010-06-02 13:03:30 +02:00
|
|
|
// grab the next character according to the orientation
|
2012-01-22 18:41:04 +01:00
|
|
|
char_info const& ci = orientation > 0 ? info_.at(i) : info_.at(info_.num_characters() - i - 1);
|
2010-06-02 13:03:30 +02:00
|
|
|
int c;
|
|
|
|
double x, y, angle;
|
2012-01-22 18:41:04 +01:00
|
|
|
char_properties *properties;
|
|
|
|
current_placement->vertex(&c, &x, &y, &angle, &properties);
|
2010-06-02 13:03:30 +02:00
|
|
|
x = current_placement->starting_x + x;
|
|
|
|
y = current_placement->starting_y - y;
|
|
|
|
if (orientation < 0)
|
|
|
|
{
|
2008-01-21 04:08:18 +01:00
|
|
|
// rotate in place
|
2012-01-22 18:41:04 +01:00
|
|
|
/* TODO: What's the meaning of -2? */
|
|
|
|
x += ci.width*cos(angle) - (string_height_-2)*sin(angle);
|
|
|
|
y -= ci.width*sin(angle) + (string_height_-2)*cos(angle);
|
2008-01-21 04:08:18 +01:00
|
|
|
angle += M_PI;
|
2010-06-02 13:03:30 +02:00
|
|
|
}
|
2008-01-21 04:08:18 +01:00
|
|
|
|
2010-06-02 13:03:30 +02:00
|
|
|
box2d<double> e;
|
2012-01-22 18:41:04 +01:00
|
|
|
if (pi.has_dimensions)
|
2010-06-02 13:03:30 +02:00
|
|
|
{
|
2012-01-22 18:41:04 +01:00
|
|
|
e.init(x, y, x + pi.dimensions.first, y + pi.dimensions.second);
|
2010-06-02 13:03:30 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-01-21 04:08:18 +01:00
|
|
|
// put four corners of the letter into envelope
|
2012-01-22 18:41:04 +01:00
|
|
|
e.init(x, y, x + ci.width*cos(angle),
|
|
|
|
y - ci.width*sin(angle));
|
|
|
|
e.expand_to_include(x - ci.height()*sin(angle),
|
|
|
|
y - ci.height()*cos(angle));
|
|
|
|
e.expand_to_include(x + (ci.width*cos(angle) - ci.height()*sin(angle)),
|
|
|
|
y - (ci.width*sin(angle) + ci.height()*cos(angle)));
|
2010-06-02 13:03:30 +02:00
|
|
|
}
|
Patch from David Eastcott :
1. Modified Text Symbolizer
a) corrected line fragment centering (for 2nd and subsequent lines, when line breaks occur).
b) adjusted vertical alignment calculation so that:
i) middle -> has the center of the text line(s) at the point origin
ii) bottom -> has the text line(s) below the point origin
iii) top -> has the text line(s) above the point origin
c) added new text_symbolizer attribute: 'wrap_before', value range: true/false, default == false
allows line breaks at first wrap_char before wrap_width as an alternative to the original
which was to create the line break at the first wrap_char after wrap_width
d) added new text_symbolizer attribute: 'horizontal_alignment', value range: left/middle/right, default == middle
i) left -> has all text line(s) to left of the point origin
ii) middle -> has all text line(s) centered on the the point origin
iii) right -> has all text line(s) to the right of the point origin
NOTE: dx, dy position adjustments are applied after alignments and before Justify.
e) added new text_symbolizer attribute: 'justify_alignment', value range: left/middle/right, default == middle
i) left -> after alignments, has all text line(s) are left justified (left to right reading)
ii) middle -> after alignments, has all text line(s) center justified
iii) right -> after alignments, has all text line(s) right justified (right to left reading)
f) added new text_symbolizer attribute: 'opacity', value range: 0.0 thru 1.0; 1.0 == fully opaque
g) modified positioning to compensate for both line_spacing and character_spacing, to ensure proper
centering of the text envelope. Also ensure that centering occurs correctly even if no wrapping
occurs. Line spacing is uniform and consistent and compensates for errors between text_size and
the actual size (ci.height is inconsistent, depending on case and character); fixes issue with
multi-line text where some lines have a slight gap and others are compressed together.
2. Modified shield_symbolizer
a) added the attributes:
i) allow_overlap
ii) vertical_alignment
iii) horizontal_alignment
iv) justify_alignment
v) wrap_width
vi) wrap_character
vii) wrap_before
viii) text_convert
ix) line_spacing
x) character_spacing
xi) opacity
b) added new shield_symbolizer attribute: 'unlock_image', value range: true/false, default == false
i) false == image and text placement behaviour same as before
ii) true == image placement independant of text, image is always centered at geometry point, text placed per attributes,
dx/dy only affect text.
Allows user to create point markers with text, but both the text and image rendering collision detection are done
as a pair (they come and go together - solves problem if using point_symbolizer and text_symbolizers where one or the
other are omitted due to overlaps, but not both)
c) extended choices for the attribute 'placement' to include vertex; effect is limited to the shield_symbolizer
Allows an attempted placement at every vertex available, gives additional shield placement volume when using line geometry
d) ensured that the text placement was not updating the detector unless a shield image was actually placed.
e) added new shield_symbolizer attribute: 'no_text', value range: true/false, default = false
When set true, the text for the feature is ignored ('space' subsituted) so that pure graphic symbols can be used
and no text is rendered over top of them.
2009-10-19 15:52:53 +02:00
|
|
|
|
2010-11-22 12:25:36 +01:00
|
|
|
if (!detector_.extent().intersects(e) ||
|
2012-01-22 18:41:04 +01:00
|
|
|
!detector_.has_placement(e, info_.get_string(), pi.get_actual_minimum_distance()))
|
2010-06-02 13:03:30 +02:00
|
|
|
{
|
2008-01-21 04:08:18 +01:00
|
|
|
//std::clog << "No Intersects:" << !dimensions_.intersects(e) << ": " << e << " @ " << dimensions_ << std::endl;
|
2012-01-22 18:41:04 +01:00
|
|
|
//std::clog << "No Placements:" << !detector_.has_placement(e, info.get_string(), p.minimum_distance) << std::endl;
|
2008-01-21 04:08:18 +01:00
|
|
|
status = false;
|
|
|
|
break;
|
2010-06-02 13:03:30 +02:00
|
|
|
}
|
Patch from David Eastcott :
1. Modified Text Symbolizer
a) corrected line fragment centering (for 2nd and subsequent lines, when line breaks occur).
b) adjusted vertical alignment calculation so that:
i) middle -> has the center of the text line(s) at the point origin
ii) bottom -> has the text line(s) below the point origin
iii) top -> has the text line(s) above the point origin
c) added new text_symbolizer attribute: 'wrap_before', value range: true/false, default == false
allows line breaks at first wrap_char before wrap_width as an alternative to the original
which was to create the line break at the first wrap_char after wrap_width
d) added new text_symbolizer attribute: 'horizontal_alignment', value range: left/middle/right, default == middle
i) left -> has all text line(s) to left of the point origin
ii) middle -> has all text line(s) centered on the the point origin
iii) right -> has all text line(s) to the right of the point origin
NOTE: dx, dy position adjustments are applied after alignments and before Justify.
e) added new text_symbolizer attribute: 'justify_alignment', value range: left/middle/right, default == middle
i) left -> after alignments, has all text line(s) are left justified (left to right reading)
ii) middle -> after alignments, has all text line(s) center justified
iii) right -> after alignments, has all text line(s) right justified (right to left reading)
f) added new text_symbolizer attribute: 'opacity', value range: 0.0 thru 1.0; 1.0 == fully opaque
g) modified positioning to compensate for both line_spacing and character_spacing, to ensure proper
centering of the text envelope. Also ensure that centering occurs correctly even if no wrapping
occurs. Line spacing is uniform and consistent and compensates for errors between text_size and
the actual size (ci.height is inconsistent, depending on case and character); fixes issue with
multi-line text where some lines have a slight gap and others are compressed together.
2. Modified shield_symbolizer
a) added the attributes:
i) allow_overlap
ii) vertical_alignment
iii) horizontal_alignment
iv) justify_alignment
v) wrap_width
vi) wrap_character
vii) wrap_before
viii) text_convert
ix) line_spacing
x) character_spacing
xi) opacity
b) added new shield_symbolizer attribute: 'unlock_image', value range: true/false, default == false
i) false == image and text placement behaviour same as before
ii) true == image placement independant of text, image is always centered at geometry point, text placed per attributes,
dx/dy only affect text.
Allows user to create point markers with text, but both the text and image rendering collision detection are done
as a pair (they come and go together - solves problem if using point_symbolizer and text_symbolizers where one or the
other are omitted due to overlaps, but not both)
c) extended choices for the attribute 'placement' to include vertex; effect is limited to the shield_symbolizer
Allows an attempted placement at every vertex available, gives additional shield placement volume when using line geometry
d) ensured that the text placement was not updating the detector unless a shield image was actually placed.
e) added new shield_symbolizer attribute: 'no_text', value range: true/false, default = false
When set true, the text for the feature is ignored ('space' subsituted) so that pure graphic symbols can be used
and no text is rendered over top of them.
2009-10-19 15:52:53 +02:00
|
|
|
|
2010-06-02 13:03:30 +02:00
|
|
|
if (p.avoid_edges && !dimensions_.contains(e))
|
|
|
|
{
|
2008-01-21 04:08:18 +01:00
|
|
|
//std::clog << "Fail avoid edges" << std::endl;
|
|
|
|
status = false;
|
|
|
|
break;
|
2010-06-02 13:03:30 +02:00
|
|
|
}
|
2012-01-22 18:41:04 +01:00
|
|
|
if (p.minimum_padding > 0)
|
2010-11-03 14:18:56 +01:00
|
|
|
{
|
2012-01-22 18:41:04 +01:00
|
|
|
double min_pad = pi.get_actual_minimum_padding();
|
|
|
|
box2d<double> epad(e.minx()-min_pad,
|
|
|
|
e.miny()-min_pad,
|
|
|
|
e.maxx()+min_pad,
|
|
|
|
e.maxy()+min_pad);
|
2010-11-03 14:18:56 +01:00
|
|
|
if (!dimensions_.contains(epad))
|
|
|
|
{
|
|
|
|
status = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2012-01-22 18:41:04 +01:00
|
|
|
pi.envelopes.push(e);
|
2010-05-27 12:19:47 +02:00
|
|
|
}
|
2010-11-03 14:18:56 +01:00
|
|
|
|
2010-05-27 12:19:47 +02:00
|
|
|
current_placement->rewind();
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename DetectorT>
|
|
|
|
void placement_finder<DetectorT>::find_line_circle_intersection(
|
|
|
|
const double &cx, const double &cy, const double &radius,
|
|
|
|
const double &x1, const double &y1, const double &x2, const double &y2,
|
|
|
|
double &ix, double &iy)
|
|
|
|
{
|
|
|
|
double dx = x2 - x1;
|
|
|
|
double dy = y2 - y1;
|
|
|
|
|
|
|
|
double A = dx * dx + dy * dy;
|
|
|
|
double B = 2 * (dx * (x1 - cx) + dy * (y1 - cy));
|
|
|
|
double C = (x1 - cx) * (x1 - cx) + (y1 - cy) * (y1 - cy) - radius * radius;
|
|
|
|
|
|
|
|
double det = B * B - 4 * A * C;
|
|
|
|
if (A <= 0.0000001 || det < 0)
|
|
|
|
{
|
2010-06-02 13:03:30 +02:00
|
|
|
//Should never happen
|
|
|
|
//' No real solutions.
|
|
|
|
return;
|
2010-05-27 12:19:47 +02:00
|
|
|
}
|
|
|
|
else if (det == 0)
|
|
|
|
{
|
2010-06-02 13:03:30 +02:00
|
|
|
//Could potentially happen....
|
|
|
|
//One solution.
|
|
|
|
double t = -B / (2 * A);
|
|
|
|
ix = x1 + t * dx;
|
|
|
|
iy = y1 + t * dy;
|
|
|
|
return;
|
2010-05-27 12:19:47 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-06-02 13:03:30 +02:00
|
|
|
//Two solutions.
|
2010-05-27 12:19:47 +02:00
|
|
|
|
2010-06-02 13:03:30 +02:00
|
|
|
//Always use the 1st one
|
|
|
|
//We only really have one solution here, as we know the line segment will start in the circle and end outside
|
|
|
|
double t = (-B + std::sqrt(det)) / (2 * A);
|
|
|
|
ix = x1 + t * dx;
|
|
|
|
iy = y1 + t * dy;
|
2010-05-27 12:19:47 +02:00
|
|
|
|
2010-06-02 13:03:30 +02:00
|
|
|
//t = (-B - std::sqrt(det)) / (2 * A);
|
|
|
|
//ix = x1 + t * dx;
|
|
|
|
//iy = y1 + t * dy;
|
2010-05-27 12:19:47 +02:00
|
|
|
|
2010-06-02 13:03:30 +02:00
|
|
|
return;
|
2010-05-27 12:19:47 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename DetectorT>
|
2012-01-22 18:41:04 +01:00
|
|
|
void placement_finder<DetectorT>::update_detector()
|
2010-05-27 12:19:47 +02:00
|
|
|
{
|
2011-04-30 02:06:27 +02:00
|
|
|
bool first = true;
|
|
|
|
|
|
|
|
// add the bboxes to the detector and remove from the placement
|
2012-01-22 18:41:04 +01:00
|
|
|
while (!pi.envelopes.empty())
|
2010-05-27 12:19:47 +02:00
|
|
|
{
|
2012-01-22 18:41:04 +01:00
|
|
|
box2d<double> e = pi.envelopes.front();
|
|
|
|
detector_.insert(e, info_.get_string());
|
|
|
|
pi.envelopes.pop();
|
2011-04-30 02:06:27 +02:00
|
|
|
|
2012-01-22 18:41:04 +01:00
|
|
|
if (pi.collect_extents)
|
2011-04-30 02:06:27 +02:00
|
|
|
{
|
|
|
|
if(first)
|
|
|
|
{
|
|
|
|
first = false;
|
2012-01-22 18:41:04 +01:00
|
|
|
pi.extents = e;
|
2011-04-30 02:06:27 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-01-22 18:41:04 +01:00
|
|
|
pi.extents.expand_to_include(e);
|
2011-04-30 02:06:27 +02:00
|
|
|
}
|
|
|
|
}
|
2010-05-27 12:19:47 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename DetectorT>
|
|
|
|
void placement_finder<DetectorT>::clear()
|
|
|
|
{
|
|
|
|
detector_.clear();
|
|
|
|
}
|
|
|
|
|
2010-11-03 14:19:15 +01:00
|
|
|
typedef coord_transform2<CoordTransform,geometry_type> PathType;
|
2010-05-27 12:19:47 +02:00
|
|
|
typedef label_collision_detector4 DetectorType;
|
|
|
|
|
|
|
|
template class placement_finder<DetectorType>;
|
2012-01-22 18:41:04 +01:00
|
|
|
template void placement_finder<DetectorType>::find_point_placements<PathType>(PathType &);
|
|
|
|
template void placement_finder<DetectorType>::find_line_placements<PathType>(PathType &);
|
Patch from David Eastcott :
1. Modified Text Symbolizer
a) corrected line fragment centering (for 2nd and subsequent lines, when line breaks occur).
b) adjusted vertical alignment calculation so that:
i) middle -> has the center of the text line(s) at the point origin
ii) bottom -> has the text line(s) below the point origin
iii) top -> has the text line(s) above the point origin
c) added new text_symbolizer attribute: 'wrap_before', value range: true/false, default == false
allows line breaks at first wrap_char before wrap_width as an alternative to the original
which was to create the line break at the first wrap_char after wrap_width
d) added new text_symbolizer attribute: 'horizontal_alignment', value range: left/middle/right, default == middle
i) left -> has all text line(s) to left of the point origin
ii) middle -> has all text line(s) centered on the the point origin
iii) right -> has all text line(s) to the right of the point origin
NOTE: dx, dy position adjustments are applied after alignments and before Justify.
e) added new text_symbolizer attribute: 'justify_alignment', value range: left/middle/right, default == middle
i) left -> after alignments, has all text line(s) are left justified (left to right reading)
ii) middle -> after alignments, has all text line(s) center justified
iii) right -> after alignments, has all text line(s) right justified (right to left reading)
f) added new text_symbolizer attribute: 'opacity', value range: 0.0 thru 1.0; 1.0 == fully opaque
g) modified positioning to compensate for both line_spacing and character_spacing, to ensure proper
centering of the text envelope. Also ensure that centering occurs correctly even if no wrapping
occurs. Line spacing is uniform and consistent and compensates for errors between text_size and
the actual size (ci.height is inconsistent, depending on case and character); fixes issue with
multi-line text where some lines have a slight gap and others are compressed together.
2. Modified shield_symbolizer
a) added the attributes:
i) allow_overlap
ii) vertical_alignment
iii) horizontal_alignment
iv) justify_alignment
v) wrap_width
vi) wrap_character
vii) wrap_before
viii) text_convert
ix) line_spacing
x) character_spacing
xi) opacity
b) added new shield_symbolizer attribute: 'unlock_image', value range: true/false, default == false
i) false == image and text placement behaviour same as before
ii) true == image placement independant of text, image is always centered at geometry point, text placed per attributes,
dx/dy only affect text.
Allows user to create point markers with text, but both the text and image rendering collision detection are done
as a pair (they come and go together - solves problem if using point_symbolizer and text_symbolizers where one or the
other are omitted due to overlaps, but not both)
c) extended choices for the attribute 'placement' to include vertex; effect is limited to the shield_symbolizer
Allows an attempted placement at every vertex available, gives additional shield placement volume when using line geometry
d) ensured that the text placement was not updating the detector unless a shield image was actually placed.
e) added new shield_symbolizer attribute: 'no_text', value range: true/false, default = false
When set true, the text for the feature is ignored ('space' subsituted) so that pure graphic symbols can be used
and no text is rendered over top of them.
2009-10-19 15:52:53 +02:00
|
|
|
|
2007-11-02 13:50:15 +01:00
|
|
|
} // namespace
|