add 'interior' placement option to text_symbolizr - patch from Toby Collet - closes #709
This commit is contained in:
parent
4b076272fe
commit
e803b1c2ec
7 changed files with 91 additions and 8 deletions
|
@ -165,6 +165,7 @@ void export_text_symbolizer()
|
|||
.value("LINE_PLACEMENT",LINE_PLACEMENT)
|
||||
.value("POINT_PLACEMENT",POINT_PLACEMENT)
|
||||
.value("VERTEX_PLACEMENT",VERTEX_PLACEMENT)
|
||||
.value("INTERIOR_PLACEMENT",INTERIOR_PLACEMENT)
|
||||
;
|
||||
enumeration_<vertical_alignment_e>("vertical_alignment")
|
||||
.value("TOP",TOP)
|
||||
|
|
|
@ -105,6 +105,75 @@ public:
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void label_interior_position(double *x, double *y) const
|
||||
{
|
||||
// start with the default label position
|
||||
label_position(x,y);
|
||||
unsigned size = cont_.size();
|
||||
// if we are not a polygon, or the default is within the polygon we are done
|
||||
if (size < 3 || hit_test(*x,*y,0))
|
||||
return;
|
||||
|
||||
// otherwise we find a horizontal line across the polygon and then return the
|
||||
// center of the widest intersection between the polygon and the line.
|
||||
|
||||
std::vector<double> intersections; // only need to store the X as we know the y
|
||||
|
||||
double x0, y0;
|
||||
rewind(0);
|
||||
unsigned command = vertex(&x0, &y0);
|
||||
double x1,y1;
|
||||
while (SEG_END != (command=vertex(&x1, &y1)))
|
||||
{
|
||||
if (command != SEG_MOVETO)
|
||||
{
|
||||
// if the segments overlap
|
||||
if (y0==y1)
|
||||
{
|
||||
if (y0==*y)
|
||||
{
|
||||
double xi = (x0+x1)/2.0;
|
||||
intersections.push_back(xi);
|
||||
}
|
||||
}
|
||||
// if the path segment crosses the bisector
|
||||
else if ((y0 <= *y && y1 >= *y) ||
|
||||
(y0 >= *y && y1 <= *y))
|
||||
{
|
||||
// then calculate the intersection
|
||||
double xi = x0;
|
||||
if (x0 != x1)
|
||||
{
|
||||
double m = (y1-y0)/(x1-x0);
|
||||
double c = y0 - m*x0;
|
||||
xi = (*y-c)/m;
|
||||
}
|
||||
|
||||
intersections.push_back(xi);
|
||||
}
|
||||
}
|
||||
x0 = x1;
|
||||
y0 = y1;
|
||||
}
|
||||
// no intersections we just return the default
|
||||
if (intersections.empty())
|
||||
return;
|
||||
x0=intersections[0];
|
||||
double max_width = 0;
|
||||
for (unsigned ii = 1; ii < intersections.size(); ++ii)
|
||||
{
|
||||
double x1=intersections[ii];
|
||||
double xc=(x0+x1)/2.0;
|
||||
double width = fabs(x1-x0);
|
||||
if (width > max_width && hit_test(xc,*y,0))
|
||||
{
|
||||
*x=xc;
|
||||
max_width = width;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void label_position(double *x, double *y) const
|
||||
{
|
||||
unsigned size = cont_.size();
|
||||
|
|
|
@ -45,6 +45,7 @@ enum label_placement_enum {
|
|||
POINT_PLACEMENT,
|
||||
LINE_PLACEMENT,
|
||||
VERTEX_PLACEMENT,
|
||||
INTERIOR_PLACEMENT,
|
||||
label_placement_enum_MAX
|
||||
};
|
||||
|
||||
|
|
|
@ -121,7 +121,7 @@ void agg_renderer<T>::process(shield_symbolizer const& sym,
|
|||
path_type path(t_,geom,prj_trans);
|
||||
|
||||
label_placement_enum how_placed = sym.get_label_placement();
|
||||
if (how_placed == POINT_PLACEMENT || how_placed == VERTEX_PLACEMENT)
|
||||
if (how_placed == POINT_PLACEMENT || how_placed == VERTEX_PLACEMENT || how_placed == INTERIOR_PLACEMENT)
|
||||
{
|
||||
// for every vertex, try and place a shield/text
|
||||
geom.rewind(0);
|
||||
|
@ -138,6 +138,8 @@ void agg_renderer<T>::process(shield_symbolizer const& sym,
|
|||
|
||||
if( how_placed == VERTEX_PLACEMENT )
|
||||
geom.vertex(&label_x,&label_y); // by vertex
|
||||
else if( how_placed == INTERIOR_PLACEMENT )
|
||||
geom.label_interior_position(&label_x,&label_y);
|
||||
else
|
||||
geom.label_position(&label_x, &label_y); // by middle of line or by point
|
||||
prj_trans.backward(label_x,label_y, z);
|
||||
|
|
|
@ -95,10 +95,14 @@ void agg_renderer<T>::process(text_symbolizer const& sym,
|
|||
{
|
||||
placement text_placement(info,sym,scale_factor_);
|
||||
text_placement.avoid_edges = sym.get_avoid_edges();
|
||||
if (sym.get_label_placement() == POINT_PLACEMENT)
|
||||
if (sym.get_label_placement() == POINT_PLACEMENT ||
|
||||
sym.get_label_placement() == INTERIOR_PLACEMENT)
|
||||
{
|
||||
double label_x, label_y, z=0.0;
|
||||
if (sym.get_label_placement() == POINT_PLACEMENT)
|
||||
geom.label_position(&label_x, &label_y);
|
||||
else
|
||||
geom.label_interior_position(&label_x, &label_y);
|
||||
prj_trans.backward(label_x,label_y, z);
|
||||
t_.forward(&label_x,&label_y);
|
||||
|
||||
|
|
|
@ -1141,7 +1141,7 @@ void cairo_renderer_base::process(shield_symbolizer const& sym,
|
|||
path_type path(t_, geom, prj_trans);
|
||||
|
||||
label_placement_enum how_placed = sym.get_label_placement();
|
||||
if (how_placed == POINT_PLACEMENT || how_placed == VERTEX_PLACEMENT)
|
||||
if (how_placed == POINT_PLACEMENT || how_placed == VERTEX_PLACEMENT || how_placed == INTERIOR_PLACEMENT)
|
||||
{
|
||||
// for every vertex, try and place a shield/text
|
||||
geom.rewind(0);
|
||||
|
@ -1158,6 +1158,8 @@ void cairo_renderer_base::process(shield_symbolizer const& sym,
|
|||
|
||||
if( how_placed == VERTEX_PLACEMENT )
|
||||
geom.vertex(&label_x,&label_y); // by vertex
|
||||
else if( how_placed == INTERIOR_PLACEMENT )
|
||||
geom.label_interior_position(&label_x,&label_y);
|
||||
else
|
||||
geom.label_position(&label_x, &label_y); // by middle of line or by point
|
||||
prj_trans.backward(label_x,label_y, z);
|
||||
|
@ -1550,11 +1552,14 @@ void cairo_renderer_base::process(text_symbolizer const& sym,
|
|||
path_type path(t_, geom, prj_trans);
|
||||
placement text_placement(info, sym, 1.0);
|
||||
|
||||
if (sym.get_label_placement() == POINT_PLACEMENT)
|
||||
if (sym.get_label_placement() == POINT_PLACEMENT ||
|
||||
sym.get_label_placement() == INTERIOR_PLACEMENT)
|
||||
{
|
||||
double label_x, label_y, z = 0.0;
|
||||
|
||||
double label_x, label_y, z=0.0;
|
||||
if (sym.get_label_placement() == POINT_PLACEMENT)
|
||||
geom.label_position(&label_x, &label_y);
|
||||
else
|
||||
geom.label_interior_position(&label_x, &label_y);
|
||||
prj_trans.backward(label_x, label_y, z);
|
||||
t_.forward(&label_x, &label_y);
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@ static const char * label_placement_strings[] = {
|
|||
"point",
|
||||
"line",
|
||||
"vertex",
|
||||
"interior",
|
||||
""
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue