Merge pull request #3160 from mapycz/FIX-offseting

Fix offsetting
This commit is contained in:
Artem Pavlenko 2015-11-04 15:29:55 +00:00
commit c3c7513c7f

View file

@ -35,6 +35,7 @@
#include <cmath>
#include <vector>
#include <cstddef>
#include <algorithm>
namespace mapnik
{
@ -261,7 +262,15 @@ private:
v.cmd = u.cmd;
}
void displace2(vertex2d & v, double a, double b) const
int point_line_position(vertex2d const& a, vertex2d const& b, vertex2d const& point) const
{
double position = (b.x - a.x) * (point.y - a.y) - (b.y - a.y) * (point.x - a.x);
if (position > 1e-6) return 1;
if (position < -1e-6) return -1;
return 0;
}
void displace2(vertex2d & v1, vertex2d const& v0, vertex2d const& v2, double a, double b) const
{
double sa = offset_ * std::sin(a);
double ca = offset_ * std::cos(a);
@ -269,26 +278,60 @@ private:
double hsa = h * sa;
double hca = h * ca;
double abs_offset = std::abs(offset_);
if (hsa > 1.0 * abs_offset)
double hsaca = ca-hsa;
double hcasa = -sa-hca;
double abs_hsaca = std::abs(hsaca);
double abs_hcasa = std::abs(hcasa);
double abs_hsa = std::abs(hsa);
double abs_hca = std::abs(hca);
vertex2d v_tmp(vertex2d::no_init);
v_tmp.x = v1.x - sa - hca;
v_tmp.y = v1.y + ca - hsa;
v_tmp.cmd = v1.cmd;
int same = point_line_position(v0, v2, v_tmp)*point_line_position(v0, v2, v1);
if (same >= 0 && std::abs(h) < 10)
{
hsa = 1.0 * abs_offset;
v1.x = v_tmp.x;
v1.y = v_tmp.y;
}
else if (hsa < -1.0 * abs_offset)
else if ((v0.x-v1.x)*(v0.x-v1.x) + (v0.y-v1.y)*(v0.y-v1.y) +
(v0.x-v2.x)*(v0.x-v2.x) + (v0.y-v2.y)*(v0.y-v2.y) > offset_*offset_)
{
hsa = -1.0 * abs_offset;
if (abs_hsa > abs_offset || abs_hca > abs_offset)
{
double scale = std::max(abs_hsa,abs_hca);
scale = scale < 1e-6 ? 1. : abs_offset / scale;
// interpolate hsa, hca to <0,abs_offset>
hsa = hsa * scale;
sa = sa * scale;
hca = hca * scale;
ca = ca * scale;
}
v1.x = v1.x - sa - hca;
v1.y = v1.y + ca - hsa;
}
if (hca > 1.0 * abs_offset)
else
{
hca = 1.0 * abs_offset;
if (abs_hsaca*abs_hsaca + abs_hcasa*abs_hcasa > abs_offset*abs_offset)
{
double d = (abs_hsaca*abs_hsaca + abs_hcasa*abs_hcasa);
d = d < 1e-6 ? 1. : d;
double scale = (abs_offset*abs_offset)/d;
v1.x = v1.x + hcasa*scale;
v1.y = v1.y + hsaca*scale;
}
else
{
v1.x = v1.x + hcasa;
v1.y = v1.y + hsaca;
}
}
else if (hca < -1.0 * abs_offset)
{
hca = -1.0 * abs_offset;
}
v.x = v.x - sa - hca;
v.y = v.y + ca - hsa;
}
status init_vertices()
{
if (status_ != initial) // already initialized
@ -412,7 +455,7 @@ private:
if (bulge_steps == 0)
{
displace2(v1, angle_a, angle_b);
displace2(v1, v0, v2, angle_a, angle_b);
push_vertex(v1);
}
else
@ -440,6 +483,8 @@ private:
start_v2.x = v2.x;
start_v2.y = v2.y;
bool continue_loop = true;
vertex2d tmp_prev(vertex2d::no_init);
while (i < points.size())
{
v1 = v2;
@ -530,11 +575,15 @@ private:
<< " degrees ((< with " << bulge_steps << " segments";
}
#endif
tmp_prev.cmd = v1.cmd;
tmp_prev.x = v1.x;
tmp_prev.y = v1.y;
if (v1.cmd == SEG_MOVETO)
{
if (bulge_steps == 0)
{
displace2(v1, angle_a, angle_b);
displace2(v1, v0, v2, angle_a, angle_b);
push_vertex(v1);
}
else
@ -547,7 +596,7 @@ private:
{
if (bulge_steps == 0)
{
displace2(v1, angle_a, angle_b);
displace2(v1, v0, v2, angle_a, angle_b);
push_vertex(v1);
}
else
@ -565,6 +614,9 @@ private:
push_vertex(v1);
}
}
v0.cmd = tmp_prev.cmd;
v0.x = tmp_prev.x;
v0.y = tmp_prev.y;
}
// last vertex