MCPcopy Index your code
hub / github.com/MapServer/MapServer / msOffsetPolyline

Function msOffsetPolyline

maputil.c:1697–1778  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

1695#define CURVE_SIN_LIMIT 0.3
1696
1697shapeObj *msOffsetPolyline(shapeObj *p, double offsetx, double offsety) {
1698 int i, j, first,idx;
1699
1700 shapeObj *ret = (shapeObj*)msSmallMalloc(sizeof(shapeObj));
1701 msInitShape(ret);
1702 ret->numlines = p->numlines;
1703 ret->line=(lineObj*)msSmallMalloc(sizeof(lineObj)*ret->numlines);
1704 for(i=0;i<ret->numlines;i++) {
1705 ret->line[i].numpoints=p->line[i].numpoints;
1706 ret->line[i].point=(pointObj*)msSmallMalloc(sizeof(pointObj)*ret->line[i].numpoints);
1707 }
1708
1709 if(offsety == -99) { /* complex calculations */
1710 for (i = 0; i < p->numlines; i++) {
1711 pointObj old_pt, old_diffdir, old_offdir;
1712 /* initialize old_offdir and old_diffdir, as gcc isn't smart enough to see that it
1713 * is not an error to do so, and prints a warning */
1714 old_offdir.x=old_offdir.y=old_diffdir.x=old_diffdir.y = 0;
1715
1716 idx=0;
1717 first = 1;
1718
1719 /* saved metrics of the last processed point */
1720 if (p->line[i].numpoints>0)
1721 old_pt=p->line[i].point[0];
1722 for(j=1; j<p->line[i].numpoints; j++) {
1723 const pointObj pt = p->line[i].point[j]; /* place of the point */
1724 const pointObj diffdir = point_norm(point_diff(pt,old_pt)); /* direction of the line */
1725 const pointObj offdir = point_rotz90(diffdir); /* direction where the distance between the line and the offset is measured */
1726 pointObj offpt; /* this will be the corner point of the offset line */
1727
1728 /* offset line points computation */
1729 if(first == 1) { /* first point */
1730 first = 0;
1731 offpt = point_sum(old_pt,point_mul(offdir,offsetx));
1732 } else { /* middle points */
1733 /* curve is the angle of the last and the current line's direction (supplementary angle of the shape's inner angle) */
1734 double sin_curve = point_cross(diffdir,old_diffdir);
1735 double cos_curve = point_cross(old_offdir,diffdir);
1736 if ((-1.0)*CURVE_SIN_LIMIT < sin_curve && sin_curve < CURVE_SIN_LIMIT) {
1737 /* do not calculate 1/sin, instead use a corner point approximation: average of the last and current offset direction and length */
1738
1739 /*
1740 ** TODO: fair for obtuse inner angles, however, positive and negative
1741 ** acute inner angles would need special handling - similar to LINECAP
1742 ** to avoid drawing of long spikes
1743 */
1744 offpt = point_sum(old_pt, point_mul(point_sum(offdir, old_offdir),0.5*offsetx));
1745 } else {
1746 double base_shift = -1.0*(1.0+cos_curve)/sin_curve;
1747 offpt = point_sum(old_pt, point_mul(point_sum(point_mul(diffdir,base_shift),offdir), offsetx));
1748 }
1749 }
1750 ret->line[i].point[idx]=offpt;
1751 idx++;
1752 old_pt=pt; old_diffdir=diffdir; old_offdir=offdir;
1753 }
1754

Callers 2

msDrawLineSymbolFunction · 0.85
msDrawShadeSymbolFunction · 0.85

Calls 9

msSmallMallocFunction · 0.85
msInitShapeFunction · 0.85
point_normFunction · 0.85
point_diffFunction · 0.85
point_rotz90Function · 0.85
point_sumFunction · 0.85
point_mulFunction · 0.85
point_crossFunction · 0.85
msSmallReallocFunction · 0.85

Tested by

no test coverage detected