[mapserver-commits] r7578 - trunk/mapserver
svn at osgeo.org
svn at osgeo.org
Mon May 12 13:13:24 EDT 2008
Author: tbonfort
Date: 2008-05-12 13:13:24 -0400 (Mon, 12 May 2008)
New Revision: 7578
Modified:
trunk/mapserver/HISTORY.TXT
trunk/mapserver/mapagg.cpp
trunk/mapserver/mapagg.h
trunk/mapserver/mapserver.h
trunk/mapserver/maputil.c
Log:
AGG: enable offset lines of type x -99 (#2588)
Modified: trunk/mapserver/HISTORY.TXT
===================================================================
--- trunk/mapserver/HISTORY.TXT 2008-05-12 16:32:27 UTC (rev 7577)
+++ trunk/mapserver/HISTORY.TXT 2008-05-12 17:13:24 UTC (rev 7578)
@@ -12,6 +12,8 @@
Current Version (5.1-dev, SVN trunk):
-------------------------------------
+- AGG: enable offset lines of type x -99 (#2588)
+
- AGG: use an agg specific label size calculation function where possible (#2357)
- mapogcsld.c: fetch TextSymbolizer/Label/ogc:PropertyName correctly (#2611)
Modified: trunk/mapserver/mapagg.cpp
===================================================================
--- trunk/mapserver/mapagg.cpp 2008-05-12 16:32:27 UTC (rev 7577)
+++ trunk/mapserver/mapagg.cpp 2008-05-12 17:13:24 UTC (rev 7578)
@@ -1527,7 +1527,8 @@
double nwidth, size;
symbolObj *symbol;
AGGMapserverRenderer* ren = getAGGRenderer(image);
-
+ shapeObj *offsetLine = NULL;
+
if(style->symbol >= symbolset->numsymbols || style->symbol < 0) return; /* no such symbol, 0 is OK */
symbol = symbolset->symbol[style->symbol];
@@ -1559,8 +1560,21 @@
}
//transform the shapeobj to something AGG understands
- line_adaptor lines(p,style->offsetx,style->offsety);
+ line_adaptor *lines;
+ if(style->offsety==-99) {
+ offsetLine = msOffsetPolyline(p,style->offsetx,style->offsety);
+ }
+ if(offsetLine!=NULL) {
+ lines=new line_adaptor(offsetLine);
+ } else {
+ if(style->offsetx!=0 || style->offsety!=0) {
+ lines=new offset_line_adaptor(p,style->offsetx,style->offsety);
+ } else {
+ lines=new line_adaptor(p);
+ }
+ }
+
// treat the easy case
// NOTE/TODO: symbols of type ELLIPSE are included here, as using those with a SIZE param was
// standard practice for drawing thick lines. This should probably be removed some day
@@ -1600,7 +1614,7 @@
break;
}
}
- ren->renderPolyline(lines,*color,nwidth,symbol->patternlength,symbol->pattern,lc,lj);
+ ren->renderPolyline(*lines,*color,nwidth,symbol->patternlength,symbol->pattern,lc,lj);
}
else if(symbol->type==MS_SYMBOL_TRUETYPE) {
//specific function that treats truetype symbols
@@ -1614,7 +1628,7 @@
switch(symbol->type) {
case MS_SYMBOL_PIXMAP: {
GDpixfmt img_pixf = loadSymbolPixmap(symbol);
- ren->renderPathPixmapBGRA(lines,img_pixf);
+ ren->renderPathPixmapBGRA(*lines,img_pixf);
}
break;
case MS_SYMBOL_VECTOR: {
@@ -1631,8 +1645,8 @@
if((pw <= 1) && (ph <= 1)) { // No sense using a tile, just draw a simple line
- ren->renderPolyline(lines,*color,size,0,NULL);
- return;
+ ren->renderPolyline(*lines,*color,size,0,NULL);
+ break;
}
agg::path_storage path = imageVectorSymbolAGG(symbol,d);
@@ -1645,14 +1659,14 @@
if(symbol->filled) {
//brush with a filled vector symbol, with an optional background
- ren->renderPolylineVectorSymbol(lines,path,pw,ph,*color,agg_bcolor);
+ ren->renderPolylineVectorSymbol(*lines,path,pw,ph,*color,agg_bcolor);
} else {
//brush with a stroked vector symbol (to get width),
//with an optional background
agg::conv_stroke <agg::path_storage > stroke(path);
stroke.width(style->width);
strokeFromSymbol(stroke,symbol);
- ren->renderPolylineVectorSymbol(lines,stroke,pw,ph,*color,agg_bcolor);
+ ren->renderPolylineVectorSymbol(*lines,stroke,pw,ph,*color,agg_bcolor);
}
if(bRotated) { /* free the rotated symbol */
msFreeSymbol(symbol);
@@ -1662,12 +1676,16 @@
break;
case MS_SYMBOL_CARTOLINE:
msSetError(MS_AGGERR, "Cartoline drawing is deprecated with AGG", "msDrawLineSymbolAGG()");
- return;
default:
//we don't treat hatches on lines
break;
}
}
+ if(offsetLine!=NULL) {
+ msFreeShape(offsetLine);
+ free(offsetLine);
+ }
+ delete lines;
return;
}
@@ -1678,7 +1696,7 @@
{
if(style->symbol >= symbolset->numsymbols || style->symbol < 0) return; // no such symbol, 0 is OK
if(p->numlines==0) return;
-
+
symbolObj *symbol = symbolset->symbol[style->symbol];;
if(!MS_VALID_COLOR(style->color) &&
MS_VALID_COLOR(style->outlinecolor) &&
@@ -1689,6 +1707,7 @@
}
double ox,oy,size, angle_radians,width;
+ shapeObj *offsetPolygon=NULL;
if(!p) return;
if(p->numlines <= 0) return;
@@ -1715,7 +1734,19 @@
if(size < 1) return; // size too small
AGGMapserverRenderer* ren = getAGGRenderer(image);
- polygon_adaptor polygons(p,style->offsetx,style->offsety);
+ polygon_adaptor *polygons;
+ if(style->offsety==-99) {
+ offsetPolygon = msOffsetPolyline(p,style->offsetx,style->offsety);
+ }
+ if(offsetPolygon!=NULL) {
+ polygons=new polygon_adaptor(offsetPolygon);
+ } else {
+ if(style->offsetx!=0 || style->offsety!=0) {
+ polygons = new offset_polygon_adaptor(p,style->offsetx,style->offsety);
+ } else {
+ polygons = new polygon_adaptor(p);
+ }
+ }
agg::rgba8 agg_color,agg_ocolor,agg_bcolor;
agg_color=getAGGColor(&style->color,style->opacity);
agg_ocolor=getAGGColor(&style->outlinecolor,style->opacity);
@@ -1724,11 +1755,11 @@
if(style->symbol == 0 || symbol->type==MS_SYMBOL_SIMPLE) {
// simply draw a solid fill and outline of the specified colors
if(MS_VALID_COLOR(style->outlinecolor))
- ren->renderPathSolid(polygons,agg_color,agg_ocolor,style->width);
+ ren->renderPathSolid(*polygons,agg_color,agg_ocolor,style->width);
//use outline width without scalefactor applied
else
//draw a one pixel outline of the same color as the fill to avoid a faint outline
- ren->renderPathSolid(polygons,agg_color,agg_color,1);
+ ren->renderPathSolid(*polygons,agg_color,agg_color,1);
}
else {
switch(symbol->type) {
@@ -1740,7 +1771,7 @@
agg::path_storage hatch;
//optional backgroundcolor before drawing the symbol
- ren->renderPathSolid(polygons,agg_bcolor,AGG_NO_COLOR,1);
+ ren->renderPathSolid(*polygons,agg_bcolor,AGG_NO_COLOR,1);
//create a rectangular hatch of size pw,ph starting at 0,0
//the created hatch is of the size of the shape's bounding box
@@ -1753,11 +1784,10 @@
stroke.width(style->width);
//render the hatch clipped by the shape
- ren->renderPathSolidClipped(stroke,polygons,agg_color);
+ ren->renderPathSolidClipped(stroke,*polygons,agg_color);
//render the optional outline
- ren->renderPathSolid(polygons,AGG_NO_COLOR,agg_ocolor,1);
- return;
+ ren->renderPathSolid(*polygons,AGG_NO_COLOR,agg_ocolor,1);
}
break;
case(MS_SYMBOL_VECTOR): {
@@ -1773,12 +1803,12 @@
if((pw <= 1) && (ph <= 1)) {
//use a solid fill if the symbol is too small
if(MS_VALID_COLOR(style->outlinecolor))
- ren->renderPathSolid(polygons,agg_color,agg_ocolor,width);
+ ren->renderPathSolid(*polygons,agg_color,agg_ocolor,width);
else
//render a one pixel outline of the same color as the fill to prevent a
//faint due to antialiasing with contiguous polygons
- ren->renderPathSolid(polygons,agg_color,agg_color,1);
- return;
+ ren->renderPathSolid(*polygons,agg_color,agg_color,1);
+ break;
}
agg::path_storage path = imageVectorSymbolAGG(symbol,d);
if(symbol->gap>0) {
@@ -1790,13 +1820,13 @@
path.transform(agg::trans_affine_translation(gap/2.,gap/2.));
}
if(symbol->filled) {
- ren->renderPathTiled(polygons,path,pw,ph,agg_color,agg_bcolor);
+ ren->renderPathTiled(*polygons,path,pw,ph,agg_color,agg_bcolor);
} else {
agg::conv_stroke <agg::path_storage > stroke(path);
stroke.width(style->width);
//apply symbol caps and joins
strokeFromSymbol(stroke,symbol);
- ren->renderPathTiled(polygons,stroke,pw,ph,agg_color,agg_bcolor);
+ ren->renderPathTiled(*polygons,stroke,pw,ph,agg_color,agg_bcolor);
}
//draw an outline on the shape
@@ -1807,7 +1837,7 @@
else if(agg_bcolor.a)
oc=&agg_bcolor; /*avoid faint outline*/
if(oc!=NULL)
- ren->renderPathSolid(polygons,AGG_NO_COLOR,*oc,1);
+ ren->renderPathSolid(*polygons,AGG_NO_COLOR,*oc,1);
if(bRotated) { // free the rotated symbol
msFreeSymbol(symbol);
@@ -1818,9 +1848,9 @@
case MS_SYMBOL_PIXMAP: {
//TODO: rotate and scale image before tiling
GDpixfmt img_pixf = loadSymbolPixmap(symbol);
- ren->renderPathSolid(polygons,agg_bcolor,agg_bcolor,1);
- ren->renderPathTiledPixmapBGRA(polygons,img_pixf);
- ren->renderPathSolid(polygons,AGG_NO_COLOR,agg_ocolor,style->width);
+ ren->renderPathSolid(*polygons,agg_bcolor,agg_bcolor,1);
+ ren->renderPathTiledPixmapBGRA(*polygons,img_pixf);
+ ren->renderPathSolid(*polygons,AGG_NO_COLOR,agg_ocolor,style->width);
}
break;
case MS_SYMBOL_ELLIPSE: {
@@ -1829,9 +1859,9 @@
int ph = MS_NINT(symbol->sizey*d);
if((ph <= 1) && (pw <= 1)) { /* No sense using a tile, just fill solid */
if(MS_VALID_COLOR(style->outlinecolor))
- ren->renderPathSolid(polygons,agg_color,agg_ocolor,style->width);
+ ren->renderPathSolid(*polygons,agg_color,agg_ocolor,style->width);
else
- ren->renderPathSolid(polygons,agg_color,agg_color,1);
+ ren->renderPathSolid(*polygons,agg_color,agg_color,1);
}
else {
agg::path_storage path;
@@ -1846,7 +1876,7 @@
ph+=MS_NINT(gap);
path.transform(agg::trans_affine_translation(gap/2.,gap/2.));
}
- ren->renderPathTiled(polygons,ellipse,pw,ph,
+ ren->renderPathTiled(*polygons,ellipse,pw,ph,
agg_color,agg_bcolor);
//draw an outline on the shape
@@ -1857,29 +1887,35 @@
else if(agg_bcolor.a)
oc=&agg_bcolor;
if(oc!=NULL)
- ren->renderPathSolid(polygons,AGG_NO_COLOR,*oc,1);
+ ren->renderPathSolid(*polygons,AGG_NO_COLOR,*oc,1);
}
}
break;
case MS_SYMBOL_TRUETYPE: {
char *font = msLookupHashTable(&(symbolset->fontset->fonts), symbol->font);
if(!font)
- return;
+ break;
double gap=(symbol->gap>0)?symbol->gap*size:0;
- ren->renderPathTruetypeTiled(polygons,font,(unsigned int)((unsigned char)symbol->character[0]),size,
+ ren->renderPathTruetypeTiled(*polygons,font,(unsigned int)((unsigned char)symbol->character[0]),size,
gap,agg_color,agg_bcolor,agg_ocolor);
//if a background was specified, draw an outline of the color
//to avoid faint outlines in contiguous polygons
- ren->renderPathSolid(polygons,AGG_NO_COLOR,agg_bcolor,1);
+ ren->renderPathSolid(*polygons,AGG_NO_COLOR,agg_bcolor,1);
}
break;
case MS_SYMBOL_CARTOLINE:
msSetError(MS_AGGERR, "Cartoline drawing is deprecated with AGG", "msDrawShadeSymbolAGG()");
- return;
+ break;
default:
break;
}
}
+ if(offsetPolygon!=NULL) {
+ msFreeShape(offsetPolygon);
+ free(offsetPolygon);
+ }
+ delete polygons;
+
return;
}
Modified: trunk/mapserver/mapagg.h
===================================================================
--- trunk/mapserver/mapagg.h 2008-05-12 16:32:27 UTC (rev 7577)
+++ trunk/mapserver/mapagg.h 2008-05-12 17:13:24 UTC (rev 7578)
@@ -153,7 +153,7 @@
*/
class line_adaptor {
public:
- line_adaptor(shapeObj *shape, double ox, double oy):s(shape),ox(ox),oy(oy)
+ line_adaptor(shapeObj *shape):s(shape)
{
m_line=s->line; /*first line*/
m_point=m_line->point; /*current vertex is first vertex of first line*/
@@ -167,14 +167,14 @@
m_pend=&(m_line->point[m_line->numpoints]); /*pointer to after last vertex of first line*/
}
- unsigned vertex(double* x, double* y)
+ virtual unsigned vertex(double* x, double* y)
{
if(m_point < m_pend)
{
/*here we treat the case where a real vertex is returned*/
bool first = m_point == m_line->point; /*is this the first vertex of a line*/
- *x = m_point->x+ox;
- *y = m_point->y+oy;
+ *x = m_point->x;
+ *y = m_point->y;
m_point++;
return first ? agg::path_cmd_move_to : agg::path_cmd_line_to;
}
@@ -194,16 +194,34 @@
}
private:
shapeObj *s;
- double ox,oy;
lineObj *m_line, /*current line pointer*/
*m_lend; /*points to after the last line*/
pointObj *m_point, /*current point*/
*m_pend; /*points to after last point of current line*/
};
+class offset_line_adaptor: public line_adaptor {
+public:
+ offset_line_adaptor(shapeObj *shape, double ox, double oy):line_adaptor(shape),ox(ox),oy(oy)
+ {
+ }
+
+ unsigned vertex(double* x, double* y)
+ {
+ unsigned ret = line_adaptor::vertex(x,y);
+ *x+=ox;
+ *y+=oy;
+ return ret;
+ }
+private:
+ double ox,oy;
+};
+
+
+
class polygon_adaptor {
public:
- polygon_adaptor(shapeObj *shape, double ox, double oy):s(shape),ox(ox),oy(oy),m_stop(false)
+ polygon_adaptor(shapeObj *shape):s(shape),m_stop(false)
{
m_line=s->line; /*first lines*/
m_point=m_line->point; /*first vertex of first line*/
@@ -219,14 +237,14 @@
m_pend=&(m_line->point[m_line->numpoints]);
}
- unsigned vertex(double* x, double* y)
+ virtual unsigned vertex(double* x, double* y)
{
if(m_point < m_pend)
{
/*if here, we have a real vertex*/
bool first = m_point == m_line->point;
- *x = m_point->x+ox;
- *y = m_point->y+oy;
+ *x = m_point->x;
+ *y = m_point->y;
m_point++;
return first ? agg::path_cmd_move_to : agg::path_cmd_line_to;
}
@@ -263,5 +281,24 @@
bool m_stop; /*should next call return stop command*/
};
+class offset_polygon_adaptor: public polygon_adaptor {
+public:
+ offset_polygon_adaptor(shapeObj *shape, double ox, double oy):polygon_adaptor(shape),ox(ox),oy(oy)
+ {
+ }
+
+ unsigned vertex(double* x, double* y)
+ {
+ unsigned ret = polygon_adaptor::vertex(x,y);
+ *x+=ox;
+ *y+=oy;
+ return ret;
+ }
+private:
+ double ox,oy;
+};
+
+
+
Modified: trunk/mapserver/mapserver.h
===================================================================
--- trunk/mapserver/mapserver.h 2008-05-12 16:32:27 UTC (rev 7577)
+++ trunk/mapserver/mapserver.h 2008-05-12 17:13:24 UTC (rev 7578)
@@ -1986,7 +1986,7 @@
MS_DLL_EXPORT int msConstrainExtent(rectObj *bounds, rectObj *rect, double overlay);
MS_DLL_EXPORT int *msGetLayersIndexByGroup(mapObj *map, char *groupname, int *nCount);
MS_DLL_EXPORT unsigned char *msSaveImageBuffer(imageObj* image, int *size_ptr, outputFormatObj *format);
-
+MS_DLL_EXPORT shapeObj* msOffsetPolyline(shapeObj* shape, int offsetx, int offsety);
/* Functions to chnage the drawing order of the layers. */
/* Defined in mapobject.c */
MS_DLL_EXPORT int msMoveLayerUp(mapObj *map, int nLayerIndex);
Modified: trunk/mapserver/maputil.c
===================================================================
--- trunk/mapserver/maputil.c 2008-05-12 16:32:27 UTC (rev 7577)
+++ trunk/mapserver/maputil.c 2008-05-12 17:13:24 UTC (rev 7578)
@@ -1,5 +1,5 @@
/******************************************************************************
- * $Id:$
+ * $Id$
*
* Project: MapServer
* Purpose: Various utility functions ... a real hodgepodge.
@@ -1443,6 +1443,105 @@
msTransformShapeToPixel(shape, extent, cellsize);
}
+shapeObj* msOffsetPolyline(shapeObj *p, int offsetx, int offsety) {
+ int i, j, first,idx;
+ int ox=0, oy=0, limit;
+ double dx,dy,dx0=0, dy0=0,x, y, x0=0.0, y0=0.0, k=0.0, k0=0.0, q=0.0, q0=0.0;
+ float par=(float)0.71;
+ shapeObj *ret = (shapeObj*)malloc(sizeof(shapeObj));
+ msInitShape(ret);
+ ret->numlines = p->numlines;
+ ret->line=(lineObj*)malloc(sizeof(lineObj)*ret->numlines);
+ for(i=0;i<ret->numlines;i++) {
+ ret->line[i].numpoints=p->line[i].numpoints;
+ ret->line[i].point=(pointObj*)malloc(sizeof(pointObj)*ret->line[i].numpoints);
+ }
+ if(offsety == -99) {
+ limit = offsetx*offsetx/4;
+ for (i = 0; i < p->numlines; i++) {
+ idx=0;
+ first = 1;
+ for(j=1; j<p->line[i].numpoints; j++) {
+ ox=0; oy=0;
+ dx = (p->line[i].point[j].x - p->line[i].point[j-1].x);
+ dy = (p->line[i].point[j].y - p->line[i].point[j-1].y);
+
+ /* offset setting - quick approximation, may be changed with goniometric functions */
+ if(dx==0) { /* vertical line */
+ if(dy==0) {
+ continue; /* checking unique points */
+ }
+ ox=(dy>0) ? -offsetx : offsetx;
+ } else {
+ k = (double)dy/(double)dx;
+ if(MS_ABS(k)<0.5) {
+ oy = (dx>0) ? offsetx : -offsetx;
+ } else {
+ if (MS_ABS(k)<2.1) {
+ oy = (int) ((dx>0) ? offsetx*par : -offsetx*par);
+ ox = (int) ((dy>0) ? -offsetx*par : offsetx*par);
+ } else
+ ox = (int)((dy>0) ? -offsetx : offsetx);
+ }
+ q = p->line[i].point[j-1].y+oy - k*(p->line[i].point[j-1].x+ox);
+ }
+
+ /* offset line points computation */
+ if(first==1) { /* first point */
+ first = 0;
+ ret->line[i].point[idx].x = p->line[i].point[j-1].x+ox;
+ ret->line[i].point[idx].y = p->line[i].point[j-1].y+oy;
+ idx++;
+ } else { /* middle points */
+ if((dx*dx+dy*dy)>limit){ /* if the points are too close */
+ if(dx0==0) { /* checking verticals */
+ if(dx==0) {
+ continue;
+ }
+ x = x0;
+ y = k*x + q;
+ } else {
+ if(dx==0) {
+ x = p->line[i].point[j-1].x+ox;
+ y = k0*x + q0;
+ } else {
+ if(k==k0) continue; /* checking equal direction */
+ x = (q-q0)/(k0-k);
+ y = k*x+q;
+ }
+ }
+ }else{/* need to be refined */
+ x = p->line[i].point[j-1].x+ox;
+ y = p->line[i].point[j-1].y+oy;
+ }
+ ret->line[i].point[idx].x=x;
+ ret->line[i].point[idx].y=y;
+ idx++;
+ }
+ dx0 = dx; dy0 = dy; x0 = x, y0 = y; k0 = k; q0=q;
+ }
+ /* last point */
+ if(first==0) {
+ ret->line[i].point[idx].x=p->line[i].point[p->line[i].numpoints-1].x+ox;
+ ret->line[i].point[idx].y=p->line[i].point[p->line[i].numpoints-1].y+oy;
+ idx++;
+ }
+ if(idx!=p->line[i].numpoints) {
+ /*printf("shouldn't happen :(\n");*/
+ ret->line[i].numpoints=idx;
+ ret->line=realloc(ret->line,ret->line[i].numpoints*sizeof(pointObj));
+ }
+ }
+ } else { /* normal offset (eg. drop shadow) */
+ for (i = 0; i < p->numlines; i++)
+ for(j=1; j<p->line[i].numpoints; j++) {
+ ret->line[i].point[j-1].x=p->line[i].point[j-1].x+offsetx;
+ ret->line[i].point[j-1].y=p->line[i].point[j-1].y+offsety;
+ }
+ }
+ return ret;
+}
+
/*
-------------------------------------------------------------------------------
msSetup()
More information about the mapserver-commits
mailing list