MCPcopy Create free account
hub / github.com/MapServer/MapServer / OffsetPolygons

Function OffsetPolygons

renderers/agg/src/clipper.cpp:2322–2417  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

2320//------------------------------------------------------------------------------
2321
2322Polygons OffsetPolygons(const Polygons &pts, const float &delta)
2323{
2324 if (delta == 0) return pts;
2325
2326 double deltaSq = delta*delta;
2327 Polygons result(pts.size());
2328
2329 for (int j = 0; j < (int)pts.size(); ++j)
2330 {
2331 int highI = (int)pts[j].size() -1;
2332 //to minimize artefacts, strip out those polygons where
2333 //it's shrinking and where its area < Sqr(delta) ...
2334 double a1 = Area(pts[j]);
2335 if (delta < 0) { if (a1 > 0 && a1 < deltaSq) highI = 0;}
2336 else if (a1 < 0 && -a1 < deltaSq) highI = 0; //nb: a hole if area < 0
2337
2338 Polygon pg;
2339 pg.reserve(highI*2+2);
2340
2341 if (highI < 2)
2342 {
2343 result.push_back(pg);
2344 continue;
2345 }
2346
2347 std::vector < DoublePoint > normals(highI+1);
2348 normals[0] = GetUnitNormal(pts[j][highI], pts[j][0]);
2349 for (int i = 1; i <= highI; ++i)
2350 normals[i] = GetUnitNormal(pts[j][i-1], pts[j][i]);
2351
2352 for (int i = 0; i < highI; ++i)
2353 {
2354 pg.push_back(IntPoint(pts[j][i].X + Round(delta *normals[i].X),
2355 pts[j][i].Y + Round(delta *normals[i].Y)));
2356 pg.push_back(IntPoint(pts[j][i].X + Round(delta *normals[i+1].X),
2357 pts[j][i].Y + Round(delta *normals[i+1].Y)));
2358 }
2359 pg.push_back(IntPoint(pts[j][highI].X + Round(delta *normals[highI].X),
2360 pts[j][highI].Y + Round(delta *normals[highI].Y)));
2361 pg.push_back(IntPoint(pts[j][highI].X + Round(delta *normals[0].X),
2362 pts[j][highI].Y + Round(delta *normals[0].Y)));
2363
2364 //round off reflex angles (ie > 180 deg) unless it's almost flat (ie < 10deg angle) ...
2365 //cross product normals < 0 -> reflex angle; dot product normals == 1 -> no angle
2366 if ((normals[highI].X *normals[0].Y - normals[0].X *normals[highI].Y) *delta > 0 &&
2367 (normals[0].X *normals[highI].X + normals[0].Y *normals[highI].Y) < 0.985)
2368 {
2369 double a1 = std::atan2(normals[highI].Y, normals[highI].X);
2370 double a2 = std::atan2(normals[0].Y, normals[0].X);
2371 if (delta > 0 && a2 < a1) a2 = a2 + pi*2;
2372 else if (delta < 0 && a2 > a1) a2 = a2 - pi*2;
2373 Polygon arc = BuildArc(pts[j][highI], a1, a2, delta);
2374 Polygon::iterator it = pg.begin() +highI*2+1;
2375 pg.insert(it, arc.begin(), arc.end());
2376 }
2377 for (int i = highI; i > 0; --i)
2378 if ((normals[i-1].X*normals[i].Y - normals[i].X*normals[i-1].Y) *delta > 0 &&
2379 (normals[i].X*normals[i-1].X + normals[i].Y*normals[i-1].Y) < 0.985)

Callers

nothing calls this directly

Calls 14

AreaFunction · 0.85
GetUnitNormalFunction · 0.85
IntPointClass · 0.85
RoundFunction · 0.85
BuildArcFunction · 0.85
endMethod · 0.80
AddPolygonsMethod · 0.80
ExecuteMethod · 0.80
GetBoundsMethod · 0.80
AddPolygonMethod · 0.80
sizeMethod · 0.45
push_backMethod · 0.45

Tested by

no test coverage detected