[mapserver-commits] r9317 - trunk/mapserver
svn at osgeo.org
svn at osgeo.org
Fri Sep 18 19:01:43 EDT 2009
Author: tbonfort
Date: 2009-09-18 19:01:42 -0400 (Fri, 18 Sep 2009)
New Revision: 9317
Modified:
trunk/mapserver/HISTORY.TXT
trunk/mapserver/mapchart.c
Log:
add vertical bar charts to dynamic charting (#3128)
Modified: trunk/mapserver/HISTORY.TXT
===================================================================
--- trunk/mapserver/HISTORY.TXT 2009-09-18 20:43:18 UTC (rev 9316)
+++ trunk/mapserver/HISTORY.TXT 2009-09-18 23:01:42 UTC (rev 9317)
@@ -13,6 +13,9 @@
Current Version (SVN trunk):
----------------------------
+
+- add vertical bar charts to dynamic charting (#3128)
+
- Get the intersection points and labels #3101
- Fixed shp2img not to cause a crash when the map couldn't be loaded
Modified: trunk/mapserver/mapchart.c
===================================================================
--- trunk/mapserver/mapchart.c 2009-09-18 20:43:18 UTC (rev 9316)
+++ trunk/mapserver/mapchart.c 2009-09-18 23:01:42 UTC (rev 9317)
@@ -34,6 +34,7 @@
#define MS_CHART_TYPE_PIE 1
#define MS_CHART_TYPE_BAR 2
+#define MS_CHART_TYPE_VBAR 3
/*
** check if an object of width w and height h placed at point x,y can fit in an image of width mw and height mh
@@ -138,47 +139,81 @@
}
}
-int msDrawBarChart(mapObj *map, layerObj *layer, shapeObj *shape, imageObj *image,
- int width, int height, float *maxVal, float *minVal, float barWidth)
+void drawRectangle(mapObj *map, imageObj *image, float mx, float my, float Mx, float My,
+ styleObj *style) {
+#ifdef USE_AGG
+ if(MS_RENDERER_AGG(map->outputformat)) {
+ msFilledRectangleAGG(image, style, mx, my, Mx, My);
+ }
+ else
+#endif
+ if(MS_RENDERER_GD(map->outputformat)) {
+ int color = gdImageColorResolve(image->img.gd,
+ style->color.red,
+ style->color.green,
+ style->color.blue);
+ int outlinecolor=-1;
+ if(MS_VALID_COLOR(style->outlinecolor)) {
+ outlinecolor = gdImageColorResolve(image->img.gd,
+ style->outlinecolor.red,
+ style->outlinecolor.green,
+ style->outlinecolor.blue);
+ }
+ if(outlinecolor==-1) {
+ gdImageFilledRectangle(image->img.gd,mx,my,Mx,My,color);
+ } else {
+ int outlinewidth = style->width;
+ gdImageFilledRectangle(image->img.gd, mx, my, Mx, My, outlinecolor);
+ gdImageFilledRectangle(image->img.gd, mx+outlinewidth, my+outlinewidth, Mx-outlinewidth , My-outlinewidth,color);
+ }
+ }
+}
+
+int msDrawVBarChart(mapObj *map, imageObj *image, pointObj *center,
+ float *values, styleObj **styles, int numvalues,
+ float barWidth)
{
- pointObj center;
+ int c;
+ float left,bottom,cur; /*shortcut to pixel boundaries of the chart*/
+ float height = 0;
+
+ for(c=0;c<numvalues;c++)
+ {
+ height += values[c];
+ }
+
+ cur = bottom = center->y+height/2.;
+ left = center->x-barWidth/2.;
+
+ for(c=0;c<numvalues;c++)
+ {
+ drawRectangle(map, image, left, cur, left+barWidth, cur+values[c], styles[c]);
+ cur += values[c];
+ }
+ return MS_SUCCESS;
+}
+
+
+int msDrawBarChart(mapObj *map, imageObj *image, pointObj *center,
+ float *values, styleObj **styles, int numvalues,
+ float width, float height, float *maxVal, float *minVal, float barWidth)
+{
+
float upperLimit,lowerLimit;
- float *values,shapeMaxVal,shapeMinVal,pixperval;
- int c,color,outlinecolor,outlinewidth;
+ float shapeMaxVal,shapeMinVal,pixperval;
+ int c;
float vertOrigin,vertOriginClipped,horizStart,y;
float left,top,bottom; /*shortcut to pixel boundaries of the chart*/
- msDrawStartShape(map, layer, image, shape);
-#ifdef USE_PROJ
- if(layer->project && msProjectionsDiffer(&(layer->projection), &(map->projection)))
- msProjectShape(&layer->projection, &map->projection, shape);
- else
- layer->project = MS_FALSE;
-#endif
- if(layer->transform == MS_TRUE) {
- if(findChartPoint(map, shape, width, height, ¢er)==MS_FAILURE)
- return MS_SUCCESS; /*next shape*/
- } else {
- /* why would this ever be used? */
- msOffsetPointRelativeTo(¢er, layer);
- }
- top=center.y-height/2.;
- bottom=center.y+height/2.;
- left=center.x-width/2.;
+ top=center->y-height/2.;
+ bottom=center->y+height/2.;
+ left=center->x-width/2.;
- if(msBindLayerToShape(layer, shape, MS_FALSE) != MS_SUCCESS)
- return MS_FAILURE; /* error message is set in msBindLayerToShape() */
-
- values=(float*)calloc(layer->numclasses,sizeof(float));
-
- shapeMaxVal=shapeMinVal=0;
- for(c=0;c<layer->numclasses;c++)
+ shapeMaxVal=shapeMinVal=values[0];
+ for(c=1;c<numvalues;c++)
{
- values[c]=(layer->class[c]->styles[0]->size);
if(maxVal==NULL || minVal==NULL) { /*compute bounds if not specified*/
- if(c==0)
- shapeMaxVal=shapeMinVal=values[0];
if(values[c]>shapeMaxVal)
shapeMaxVal=values[c];
if(values[c]<shapeMinVal)
@@ -202,200 +237,319 @@
color = gdImageColorAllocate(image->img.gd, 0,0,0);
gdImageRectangle(image->img.gd, left-1,top-1, center.x+width/2.+1,bottom+1,color);
*/
- for(c=0;c<layer->numclasses;c++)
+ for(c=0;c<numvalues;c++)
{
int barHeight=values[c]*pixperval;
/*clip bars*/
y=((vertOrigin-barHeight)<top) ? top :
- (vertOrigin-barHeight>bottom) ? bottom : vertOrigin-barHeight;
+ (vertOrigin-barHeight>bottom) ? bottom : vertOrigin-barHeight;
if(y!=vertOriginClipped) { /*don't draw bars of height == 0 (i.e. either values==0, or clipped)*/
- if( MS_RENDERER_GD(map->outputformat) ) {
- color = gdImageColorResolve(image->img.gd,
- layer->class[c]->styles[0]->color.red,
- layer->class[c]->styles[0]->color.green,
- layer->class[c]->styles[0]->color.blue);
- outlinecolor=-1;outlinewidth=1;
- if(MS_VALID_COLOR(layer->class[c]->styles[0]->outlinecolor)) {
- outlinecolor = gdImageColorResolve(image->img.gd,
- layer->class[c]->styles[0]->outlinecolor.red,
- layer->class[c]->styles[0]->outlinecolor.green,
- layer->class[c]->styles[0]->outlinecolor.blue);
- }
- if(layer->class[c]->styles[0]->width!=-1)
- outlinewidth=layer->class[c]->styles[0]->width;
- if(values[c]>0) {
- if(outlinecolor==-1) {
- gdImageFilledRectangle(image->img.gd, horizStart,y, horizStart+barWidth-1 , vertOriginClipped,color);
- } else {
- gdImageFilledRectangle(image->img.gd, horizStart,y, horizStart+barWidth-1 , vertOriginClipped,outlinecolor);
- gdImageFilledRectangle(image->img.gd, horizStart+outlinewidth,y+outlinewidth, horizStart+barWidth-1-outlinewidth , vertOriginClipped-outlinewidth,color);
- }
- }
- else {
- if(outlinecolor==-1) {
- gdImageFilledRectangle(image->img.gd, horizStart, vertOriginClipped, horizStart+barWidth-1 , y,color);
- } else {
- gdImageFilledRectangle(image->img.gd, horizStart, vertOriginClipped, horizStart+barWidth-1 , y,outlinecolor);
- gdImageFilledRectangle(image->img.gd, horizStart+outlinewidth, vertOriginClipped+outlinewidth, horizStart+barWidth-1-outlinewidth , y-outlinewidth,color);
- }
- }
-
- }
- #ifdef USE_AGG
- else if( MS_RENDERER_AGG(map->outputformat) ) {
- int outline=0;
- if(MS_VALID_COLOR(layer->class[c]->styles[0]->outlinecolor))
- outline=1; /*outlining is wierd if this isn't done*/
- msFilledRectangleAGG(image, layer->class[c]->styles[0], horizStart, y, horizStart+barWidth-outline , vertOriginClipped);
- }
- #endif
+ if(values[c]>0)
+ drawRectangle(map, image, horizStart, y, horizStart+barWidth-1, vertOriginClipped, styles[c]);
+ else
+ drawRectangle(map,image, horizStart, vertOriginClipped, horizStart+barWidth-1 , y, styles[c]);
}
horizStart+=barWidth;
}
- free(values);
-
return MS_SUCCESS;
}
-int msDrawPieChart(mapObj *map, layerObj *layer, shapeObj *shape,
- imageObj *image, int diameter,
- int range_class,
- float mindiameter,float maxdiameter,
- float minvalue,float maxvalue)
+int msDrawPieChart(mapObj *map, imageObj *image,
+ pointObj *center, float diameter,
+ float *values, styleObj **styles, int numvalues)
{
- int i,c,color,outlinecolor,outlinewidth;
- pointObj center;
- float *values;
+ int i,color,outlinecolor,outlinewidth;
float dTotal=0.,start=0,center_x,center_y;
- msDrawStartShape(map, layer, image, shape);
-#ifdef USE_PROJ
- if(layer->project && msProjectionsDiffer(&(layer->projection), &(map->projection)))
- msProjectShape(&layer->projection, &map->projection, shape);
- else
- layer->project = MS_FALSE;
-#endif
- if(msBindLayerToShape(layer, shape, MS_FALSE) != MS_SUCCESS)
- return MS_FAILURE; /* error message is set in msBindLayerToShape() */
-
- /*check if dynamic diameter was wanted*/
- if(range_class>=0) {
- diameter=layer->class[range_class]->styles[0]->size;
- /*check if the diameter should be scaled according to specified bounds*/
- if(mindiameter>=0) {
- if(diameter<=minvalue)
- diameter=mindiameter;
- else if(diameter>=maxvalue)
- diameter=maxdiameter;
- else {
- diameter=MS_NINT(
- mindiameter+
- ((diameter-minvalue)/(maxvalue-minvalue))*
- (maxdiameter-mindiameter)
- );
- }
- }
- }
-
- if(layer->transform == MS_TRUE) {
- if(findChartPoint(map, shape, diameter, diameter, ¢er)==MS_FAILURE)
- return MS_SUCCESS; /*next shape*/
- } else {
- /* why would this ever be used? */
- msOffsetPointRelativeTo(¢er, layer);
- }
- values=(float*)calloc(layer->numclasses,sizeof(float));
- for(c=0;c<layer->numclasses;c++)
+ for(i=0;i<numvalues;i++)
{
- if(c==range_class) continue; /*skip the class that gives the dynamic diameter*/
- values[c]=(layer->class[c]->styles[0]->size);
- if(values[c]<0.) {
+ if(values[i]<0.) {
msSetError(MS_MISCERR, "cannot draw pie charts for negative values", "msDrawPieChart()");
return MS_FAILURE;
}
- dTotal+=values[c];
+ dTotal+=values[i];
}
- for(i=0; i < layer->numclasses; i++)
+ for(i=0; i < numvalues; i++)
{
- if(i==range_class) continue; /*skip the class that gives the dynamic diameter*/
- if(values[i]==0) continue; /*no need to draw. causes artifacts with outlines*/
- values[i]*=360.0/dTotal;
+ float angle = values[i];
+ if(angle==0) continue; /*no need to draw. causes artifacts with outlines*/
+ angle*=360.0/dTotal;
if( MS_RENDERER_GD(map->outputformat) )
{
- color = gdImageColorResolve(image->img.gd, layer->class[i]->styles[0]->color.red,
- layer->class[i]->styles[0]->color.green,
- layer->class[i]->styles[0]->color.blue);
+ color = gdImageColorResolve(image->img.gd, styles[i]->color.red,
+ styles[i]->color.green,
+ styles[i]->color.blue);
outlinecolor=-1;outlinewidth=1;
- if(MS_VALID_COLOR(layer->class[i]->styles[0]->outlinecolor)) {
- outlinecolor = gdImageColorResolve(image->img.gd, layer->class[i]->styles[0]->outlinecolor.red,
- layer->class[i]->styles[0]->outlinecolor.green,
- layer->class[i]->styles[0]->outlinecolor.blue);
+ if(MS_VALID_COLOR(styles[i]->outlinecolor)) {
+ outlinecolor = gdImageColorResolve(image->img.gd,
+ styles[i]->outlinecolor.red,
+ styles[i]->outlinecolor.green,
+ styles[i]->outlinecolor.blue);
}
- if(layer->class[i]->styles[0]->width!=-1)
- outlinewidth=layer->class[i]->styles[0]->width;
+ if(styles[i]->width!=-1)
+ outlinewidth=styles[i]->width;
/*
* offset the center of the slice
* NOTE: angles are anti-trigonometric
*
*/
- if(layer->class[i]->styles[0]->offsetx>0) {
- center_x=center.x+layer->class[i]->styles[0]->offsetx*cos(((-start-values[i]/2)*MS_PI/180.));
- center_y=center.y-layer->class[i]->styles[0]->offsetx*sin(((-start-values[i]/2)*MS_PI/180.));
+ if(styles[i]->offsetx>0) {
+ center_x=center->x+styles[i]->offsetx*cos(((-start-angle/2)*MS_PI/180.));
+ center_y=center->y-styles[i]->offsetx*sin(((-start-angle/2)*MS_PI/180.));
} else {
- center_x=center.x;
- center_y=center.y;
+ center_x=center->x;
+ center_y=center->y;
}
if(outlinecolor==-1) {
- gdImageFilledArc(image->img.gd, center_x, center_y, diameter, diameter, (int)start, (int)(start+values[i]), color, gdPie);
+ gdImageFilledArc(image->img.gd, center_x, center_y, diameter, diameter, (int)start, (int)(start+angle), color, gdPie);
}
else {
- gdImageFilledArc(image->img.gd, center_x, center_y, diameter, diameter, (int)start, (int)(start+values[i]), color, gdPie);
+ gdImageFilledArc(image->img.gd, center_x, center_y, diameter, diameter, (int)start, (int)(start+angle), color, gdPie);
gdImageSetThickness(image->img.gd, outlinewidth);
- gdImageFilledArc(image->img.gd, center_x, center_y, diameter, diameter, (int)start, (int)(start+values[i]), outlinecolor,gdNoFill|gdEdged);
+ gdImageFilledArc(image->img.gd, center_x, center_y, diameter, diameter, (int)start, (int)(start+angle), outlinecolor,gdNoFill|gdEdged);
gdImageSetThickness(image->img.gd, 1);
}
}
#ifdef USE_AGG
else if( MS_RENDERER_AGG(map->outputformat) )
{
- msPieSliceAGG(image, layer->class[i]->styles[0], center.x, center.y, diameter/2., start, start+values[i]);
+ msPieSliceAGG(image, styles[i], center->x, center->y, diameter/2., start, start+angle);
}
#endif
- start+=values[i];
+ start+=angle;
}
- free(values);
return MS_SUCCESS;
}
-int msDrawPieChartLayer(mapObj *map, layerObj *layer, imageObj *image,
- int radius,
- int range_class,
- float mindiameter,float maxdiameter,
- float minvalue,float maxvalue)
+int getNextShape(mapObj *map, layerObj *layer, float *values, styleObj **styles, shapeObj *shape) {
+ int status;
+ int c;
+ status = msLayerNextShape(layer, shape);
+ if(status == MS_SUCCESS) {
+#ifdef USE_PROJ
+ if(layer->project && msProjectionsDiffer(&(layer->projection), &(map->projection)))
+ msProjectShape(&layer->projection, &map->projection, shape);
+ else
+ layer->project = MS_FALSE;
+#endif
+
+ if(msBindLayerToShape(layer, shape, MS_FALSE) != MS_SUCCESS)
+ return MS_FAILURE; /* error message is set in msBindLayerToShape() */
+
+ for(c=0;c<layer->numclasses;c++)
+ {
+ values[c]=(layer->class[c]->styles[0]->size);
+ styles[c]=layer->class[c]->styles[0];
+ }
+ }
+ return status;
+}
+
+/* eventually add a class to the layer to get the diameter from an attribute */
+int pieLayerProcessDynamicDiameter(layerObj *layer) {
+ const char *chartRangeProcessingKey=NULL;
+ char *attrib;
+ float mindiameter=-1, maxdiameter, minvalue, maxvalue;
+ const char *chartSizeProcessingKey=msLayerGetProcessingKey( layer,"CHART_SIZE" );
+ if(chartSizeProcessingKey != NULL)
+ return MS_FALSE;
+ chartRangeProcessingKey=msLayerGetProcessingKey( layer,"CHART_SIZE_RANGE" );
+ if(chartRangeProcessingKey==NULL)
+ return MS_FALSE;
+ classObj *newclass;
+ styleObj *newstyle;
+ attrib = malloc(strlen(chartRangeProcessingKey)+1);
+ switch(sscanf(chartRangeProcessingKey,"%s %f %f %f %f",attrib,
+ &mindiameter,&maxdiameter,&minvalue,&maxvalue))
+ {
+ case 1: /*we only have the attribute*/
+ case 5: /*we have the attribute and the four range values*/
+ break;
+ default:
+ free(attrib);
+ msSetError(MS_MISCERR, "Chart Layer format error for processing key \"CHART_RANGE\"", "msDrawChartLayer()");
+ return MS_FAILURE;
+ }
+ /*create a new class in the layer containing the wanted attribute
+ * as the SIZE of its first STYLE*/
+ newclass=msGrowLayerClasses(layer);
+ if(newclass==NULL) {
+ free(attrib);
+ return MS_FAILURE;
+ }
+ initClass(newclass);
+ layer->numclasses++;
+
+ /*create and attach a new styleObj to our temp class
+ * and bind the wanted attribute to its SIZE
+ */
+ newstyle=msGrowClassStyles(newclass);
+ if(newstyle==NULL) {
+ free(attrib);
+ return MS_FAILURE;
+ }
+ initStyle(newstyle);
+ newclass->numstyles++;
+ newclass->name=strdup("__MS_SIZE_ATTRIBUTE_");
+ newstyle->bindings[MS_STYLE_BINDING_SIZE].item=strdup(attrib);
+ newstyle->numbindings++;
+ free(attrib);
+
+ return MS_TRUE;
+
+}
+
+
+int msDrawPieChartLayer(mapObj *map, layerObj *layer, imageObj *image)
{
shapeObj shape;
int status=MS_SUCCESS;
+ const char *chartRangeProcessingKey=NULL;
+ const char *chartSizeProcessingKey=msLayerGetProcessingKey( layer,"CHART_SIZE" );
+ float diameter, mindiameter=-1, maxdiameter, minvalue, maxvalue;
+ float *values;
+ styleObj **styles;
+ pointObj center;
+ int numvalues = layer->numclasses; //the number of classes to represent in the graph
+ if(chartSizeProcessingKey==NULL)
+ {
+ chartRangeProcessingKey=msLayerGetProcessingKey( layer,"CHART_SIZE_RANGE" );
+ if(chartRangeProcessingKey==NULL)
+ diameter=20;
+ else {
+ sscanf(chartRangeProcessingKey,"%*s %f %f %f %f",
+ &mindiameter,&maxdiameter,&minvalue,&maxvalue);
+ }
+ }
+ else
+ {
+ if(sscanf(chartSizeProcessingKey ,"%f",&diameter)!=1) {
+ msSetError(MS_MISCERR, "msDrawChart format error for processing key \"CHART_SIZE\"", "msDrawChartLayer()");
+ return MS_FAILURE;
+ }
+ }
/* step through the target shapes */
msInitShape(&shape);
- while((status==MS_SUCCESS)&&(msLayerNextShape(layer, &shape)) == MS_SUCCESS) {
- status = msDrawPieChart(map, layer, &shape, image,radius,
- range_class,mindiameter,maxdiameter,minvalue,maxvalue);
+ values=(float*)calloc(numvalues,sizeof(float));
+ styles = (styleObj**)malloc((numvalues)*sizeof(styleObj*));
+ if(chartRangeProcessingKey!=NULL)
+ numvalues--;
+ while(MS_SUCCESS == getNextShape(map,layer,values,styles,&shape)) {
+ msDrawStartShape(map, layer, image, &shape);
+ if(chartRangeProcessingKey!=NULL) {
+ diameter = values[numvalues];
+ if(mindiameter>=0) {
+ if(diameter<=minvalue)
+ diameter=mindiameter;
+ else if(diameter>=maxvalue)
+ diameter=maxdiameter;
+ else {
+ diameter=MS_NINT(
+ mindiameter+
+ ((diameter-minvalue)/(maxvalue-minvalue))*
+ (maxdiameter-mindiameter)
+ );
+ }
+ }
+ }
+ if(findChartPoint(map, &shape, diameter, diameter, ¢er) == MS_SUCCESS) {
+ status = msDrawPieChart(map,image, ¢er, diameter,
+ values,styles,numvalues);
+ }
+ msDrawEndShape(map,layer,image,&shape);
msFreeShape(&shape);
}
+ free(values);
+ free(styles);
return status;
}
-int msDrawBarChartLayer(mapObj *map, layerObj *layer, imageObj *image,
- int width, int height)
+int msDrawVBarChartLayer(mapObj *map, layerObj *layer, imageObj *image)
{
shapeObj shape;
int status=MS_SUCCESS;
+ const char *chartSizeProcessingKey=msLayerGetProcessingKey( layer,"CHART_SIZE" );
+ const char *chartScaleProcessingKey=msLayerGetProcessingKey( layer,"CHART_SCALE" );
+ float barWidth,scale=1.0;
+ float *values;
+ styleObj **styles;
+ pointObj center;
+ int numvalues = layer->numclasses;
+ if(chartSizeProcessingKey==NULL)
+ {
+ barWidth=20;
+ }
+ else
+ {
+ if(sscanf(chartSizeProcessingKey ,"%f",&barWidth) != 1) {
+ msSetError(MS_MISCERR, "msDrawChart format error for processing key \"CHART_SIZE\"", "msDrawChartLayer()");
+ return MS_FAILURE;
+ }
+ }
+
+ if(chartScaleProcessingKey){
+ if(sscanf(chartScaleProcessingKey,"%f",&scale)!=1) {
+ msSetError(MS_MISCERR, "Error reading value for processing key \"CHART_SCALE\"", "msDrawBarChartLayerGD()");
+ return MS_FAILURE;
+ }
+ }
+ msInitShape(&shape);
+ values=(float*)calloc(numvalues,sizeof(float));
+ styles = (styleObj**)malloc(numvalues*sizeof(styleObj*));
+ while(MS_SUCCESS == getNextShape(map,layer,values,styles,&shape)) {
+ int i;
+ double h=0;
+ for(i=0;i<numvalues;i++) {
+ values[i]*=scale;
+ h += values[i];
+ }
+ msDrawStartShape(map, layer, image, &shape);
+ if(findChartPoint(map, &shape, barWidth,h, ¢er)==MS_SUCCESS) {
+ status = msDrawVBarChart(map,image,
+ ¢er,
+ values, styles, numvalues,
+ barWidth);
+ }
+ msDrawEndShape(map,layer,image,&shape);
+ msFreeShape(&shape);
+ }
+ return status;
+}
+
+
+int msDrawBarChartLayer(mapObj *map, layerObj *layer, imageObj *image)
+{
+ shapeObj shape;
+ int status=MS_SUCCESS;
+ const char *chartSizeProcessingKey=msLayerGetProcessingKey( layer,"CHART_SIZE" );
const char *barMax=msLayerGetProcessingKey( layer,"CHART_BAR_MAXVAL" );
const char *barMin=msLayerGetProcessingKey( layer,"CHART_BAR_MINVAL" );
+ float width,height;
float barWidth;
+ float *values;
+ styleObj **styles;
+ pointObj center;
+ int numvalues = layer->numclasses;
+ if(chartSizeProcessingKey==NULL)
+ {
+ width=height=20;
+ }
+ else
+ {
+ switch(sscanf(chartSizeProcessingKey ,"%f %f",&width,&height)) {
+ case 2:
+ break;
+ case 1:
+ height = width;
+ break;
+ default:
+ msSetError(MS_MISCERR, "msDrawChart format error for processing key \"CHART_SIZE\"", "msDrawChartLayer()");
+ return MS_FAILURE;
+ }
+ }
float barMaxVal,barMinVal;
if(barMax){
@@ -420,10 +574,22 @@
msSetError(MS_MISCERR, "Specified width of chart too small to fit given number of classes", "msDrawBarChartLayerGD()");
return MS_FAILURE;
}
- /* step through the target shapes */
+
msInitShape(&shape);
- while((status==MS_SUCCESS)&&(msLayerNextShape(layer, &shape)) == MS_SUCCESS) {
- status = msDrawBarChart(map, layer, &shape, image,width,height,(barMax!=NULL)?&barMaxVal:NULL,(barMin!=NULL)?&barMinVal:NULL,barWidth);
+ values=(float*)calloc(numvalues,sizeof(float));
+ styles = (styleObj**)malloc(numvalues*sizeof(styleObj*));
+ while(MS_SUCCESS == getNextShape(map,layer,values,styles,&shape)) {
+ msDrawStartShape(map, layer, image, &shape);
+ if(findChartPoint(map, &shape, width,height, ¢er)==MS_SUCCESS) {
+ status = msDrawBarChart(map,image,
+ ¢er,
+ values, styles, numvalues,
+ width,height,
+ (barMax!=NULL)?&barMaxVal:NULL,
+ (barMin!=NULL)?&barMinVal:NULL,
+ barWidth);
+ }
+ msDrawEndShape(map,layer,image,&shape);
msFreeShape(&shape);
}
return status;
@@ -435,15 +601,9 @@
int msDrawChartLayer(mapObj *map, layerObj *layer, imageObj *image)
{
- char annotate=MS_TRUE;
rectObj searchrect;
const char *chartTypeProcessingKey=msLayerGetProcessingKey( layer,"CHART_TYPE" );
- const char *chartSizeProcessingKey=msLayerGetProcessingKey( layer,"CHART_SIZE" );
- const char *chartRangeProcessingKey=msLayerGetProcessingKey( layer,"CHART_SIZE_RANGE" );
int chartType=MS_CHART_TYPE_PIE;
- int width,height;
- float mindiameter=-1.,maxdiameter=-1.,minvalue=-1.,maxvalue=-1.;
- int tmpclassindex=-1;
int status = MS_FAILURE;
if (image && map && layer)
@@ -465,87 +625,18 @@
else if( strcasecmp(chartTypeProcessingKey,"BAR") == 0 ) {
chartType=MS_CHART_TYPE_BAR;
}
+ else if( strcasecmp(chartTypeProcessingKey,"VBAR") == 0 ) {
+ chartType=MS_CHART_TYPE_VBAR;
+ }
else {
msSetError(MS_MISCERR,"unknown chart type for processing key \"CHART_TYPE\", must be one of \"PIE\" or \"BAR\"", "msDrawChartLayer()");
return MS_FAILURE;
}
}
-
- if(chartSizeProcessingKey==NULL)
- {
- width=height=20;
+ if(chartType == MS_CHART_TYPE_PIE) {
+ pieLayerProcessDynamicDiameter(layer);
}
- else
- {
- switch(sscanf(chartSizeProcessingKey ,"%d %d",&width,&height))
- {
- case 2:
- if(chartType==MS_CHART_TYPE_PIE) {
- msSetError(MS_MISCERR,"only one size (radius) supported for processing key \"CHART_SIZE\" for pie chart layers", "msDrawChartLayer()");
- return MS_FAILURE;
- }
- break;
- case 1: height=width;break;
- default:
- msSetError(MS_MISCERR, "msDrawChart format error for processing key \"CHART_SIZE\"", "msDrawChartLayer()");
- return MS_FAILURE;
- }
- }
-
- if(chartType==MS_CHART_TYPE_PIE && chartRangeProcessingKey) { /*if CHART_SIZE_RANGE was specified*/
- char *attrib;
- classObj *newclass;
- styleObj *newstyle;
- attrib = malloc(strlen(chartRangeProcessingKey)+1);
- switch(sscanf(chartRangeProcessingKey,"%s %f %f %f %f",attrib,
- &mindiameter,&maxdiameter,&minvalue,&maxvalue))
- {
- case 1: /*we only have the attribute*/
- case 5: /*we have the attribute and the four range values*/
- break;
- default:
- free(attrib);
- msSetError(MS_MISCERR, "Chart Layer format error for processing key \"CHART_RANGE\"", "msDrawChartLayer()");
- return MS_FAILURE;
- }
- /*create a new class in the layer containing the wanted attribute
- * as the SIZE of its first STYLE*/
- newclass=msGrowLayerClasses(layer);
- if(newclass==NULL) {
- free(attrib);
- return MS_FAILURE;
- }
- initClass(newclass);
- /*remember the new class's index so that:
- * - we can delete the class when we've finished processing the layer
- * - we can tell the pie rendering functions where it should read the size value
- */
- tmpclassindex=layer->numclasses;
- layer->numclasses++;
-
- /*create and attach a new styleObj to our temp class
- * and bind the wanted attribute to its SIZE
- */
- newstyle=msGrowClassStyles(newclass);
- if(newstyle==NULL) {
- free(attrib);
- return MS_FAILURE;
- }
- initStyle(newstyle);
- newclass->numstyles++;
- newclass->name=strdup("__MS_SIZE_ATTRIBUTE_");
- newstyle->bindings[MS_STYLE_BINDING_SIZE].item=strdup(attrib);
- newstyle->numbindings++;
- free(attrib);
- }
-
- annotate = msEvalContext(map, layer, layer->labelrequires);
- if(map->scaledenom > 0) {
- if((layer->labelmaxscaledenom != -1) && (map->scaledenom >= layer->labelmaxscaledenom)) annotate = MS_FALSE;
- if((layer->labelminscaledenom != -1) && (map->scaledenom < layer->labelminscaledenom)) annotate = MS_FALSE;
- }
-
/* open this layer */
status = msLayerOpen(layer);
if(status != MS_SUCCESS) return MS_FAILURE;
@@ -579,26 +670,19 @@
}
switch(chartType) {
case MS_CHART_TYPE_PIE:
- status = msDrawPieChartLayer(map, layer, image,width,
- tmpclassindex,mindiameter,maxdiameter,minvalue,maxvalue);
+ status = msDrawPieChartLayer(map, layer, image);
break;
case MS_CHART_TYPE_BAR:
- status = msDrawBarChartLayer(map, layer, image,width,height);
+ status = msDrawBarChartLayer(map, layer, image);
break;
+ case MS_CHART_TYPE_VBAR:
+ status = msDrawVBarChartLayer(map, layer, image);
+ break;
default:
return MS_FAILURE;/*shouldn't be here anyways*/
}
msLayerClose(layer);
}
- /*
- * if we're using a dynamic size for pie layers, free the temporary class we used
- * so it doesn't appear in legends, etc...
- */
- if(tmpclassindex>=0) {
- classObj *c=msRemoveClass(layer,tmpclassindex);
- freeClass(c);
- msFree(c);
- }
return status;
}
More information about the mapserver-commits
mailing list