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("LINE_PLACEMENT",LINE_PLACEMENT)
|
||||||
.value("POINT_PLACEMENT",POINT_PLACEMENT)
|
.value("POINT_PLACEMENT",POINT_PLACEMENT)
|
||||||
.value("VERTEX_PLACEMENT",VERTEX_PLACEMENT)
|
.value("VERTEX_PLACEMENT",VERTEX_PLACEMENT)
|
||||||
|
.value("INTERIOR_PLACEMENT",INTERIOR_PLACEMENT)
|
||||||
;
|
;
|
||||||
enumeration_<vertical_alignment_e>("vertical_alignment")
|
enumeration_<vertical_alignment_e>("vertical_alignment")
|
||||||
.value("TOP",TOP)
|
.value("TOP",TOP)
|
||||||
|
|
|
@ -105,6 +105,75 @@ public:
|
||||||
}
|
}
|
||||||
return result;
|
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
|
void label_position(double *x, double *y) const
|
||||||
{
|
{
|
||||||
unsigned size = cont_.size();
|
unsigned size = cont_.size();
|
||||||
|
|
|
@ -45,6 +45,7 @@ enum label_placement_enum {
|
||||||
POINT_PLACEMENT,
|
POINT_PLACEMENT,
|
||||||
LINE_PLACEMENT,
|
LINE_PLACEMENT,
|
||||||
VERTEX_PLACEMENT,
|
VERTEX_PLACEMENT,
|
||||||
|
INTERIOR_PLACEMENT,
|
||||||
label_placement_enum_MAX
|
label_placement_enum_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -121,7 +121,7 @@ void agg_renderer<T>::process(shield_symbolizer const& sym,
|
||||||
path_type path(t_,geom,prj_trans);
|
path_type path(t_,geom,prj_trans);
|
||||||
|
|
||||||
label_placement_enum how_placed = sym.get_label_placement();
|
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
|
// for every vertex, try and place a shield/text
|
||||||
geom.rewind(0);
|
geom.rewind(0);
|
||||||
|
@ -138,6 +138,8 @@ void agg_renderer<T>::process(shield_symbolizer const& sym,
|
||||||
|
|
||||||
if( how_placed == VERTEX_PLACEMENT )
|
if( how_placed == VERTEX_PLACEMENT )
|
||||||
geom.vertex(&label_x,&label_y); // by vertex
|
geom.vertex(&label_x,&label_y); // by vertex
|
||||||
|
else if( how_placed == INTERIOR_PLACEMENT )
|
||||||
|
geom.label_interior_position(&label_x,&label_y);
|
||||||
else
|
else
|
||||||
geom.label_position(&label_x, &label_y); // by middle of line or by point
|
geom.label_position(&label_x, &label_y); // by middle of line or by point
|
||||||
prj_trans.backward(label_x,label_y, z);
|
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_);
|
placement text_placement(info,sym,scale_factor_);
|
||||||
text_placement.avoid_edges = sym.get_avoid_edges();
|
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;
|
double label_x, label_y, z=0.0;
|
||||||
geom.label_position(&label_x, &label_y);
|
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);
|
prj_trans.backward(label_x,label_y, z);
|
||||||
t_.forward(&label_x,&label_y);
|
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);
|
path_type path(t_, geom, prj_trans);
|
||||||
|
|
||||||
label_placement_enum how_placed = sym.get_label_placement();
|
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
|
// for every vertex, try and place a shield/text
|
||||||
geom.rewind(0);
|
geom.rewind(0);
|
||||||
|
@ -1158,6 +1158,8 @@ void cairo_renderer_base::process(shield_symbolizer const& sym,
|
||||||
|
|
||||||
if( how_placed == VERTEX_PLACEMENT )
|
if( how_placed == VERTEX_PLACEMENT )
|
||||||
geom.vertex(&label_x,&label_y); // by vertex
|
geom.vertex(&label_x,&label_y); // by vertex
|
||||||
|
else if( how_placed == INTERIOR_PLACEMENT )
|
||||||
|
geom.label_interior_position(&label_x,&label_y);
|
||||||
else
|
else
|
||||||
geom.label_position(&label_x, &label_y); // by middle of line or by point
|
geom.label_position(&label_x, &label_y); // by middle of line or by point
|
||||||
prj_trans.backward(label_x,label_y, z);
|
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);
|
path_type path(t_, geom, prj_trans);
|
||||||
placement text_placement(info, sym, 1.0);
|
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);
|
geom.label_position(&label_x, &label_y);
|
||||||
|
else
|
||||||
|
geom.label_interior_position(&label_x, &label_y);
|
||||||
prj_trans.backward(label_x, label_y, z);
|
prj_trans.backward(label_x, label_y, z);
|
||||||
t_.forward(&label_x, &label_y);
|
t_.forward(&label_x, &label_y);
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@ static const char * label_placement_strings[] = {
|
||||||
"point",
|
"point",
|
||||||
"line",
|
"line",
|
||||||
"vertex",
|
"vertex",
|
||||||
|
"interior",
|
||||||
""
|
""
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue