Graph.cpp
资源名称:OSDemo [点击查看]
上传用户:tianjwyx
上传日期:2007-01-13
资源大小:813k
文件大小:288k
源码类别:
操作系统开发
开发平台:
Visual C++
- deltaY = radius * sin(degreeRadians2);
- newXLocation = (int)(centerShadowXPie - deltaX);
- newYLocation = (int)(centerShadowYPie - deltaY);
- newTopX = (int)(centerXPie - deltaX);
- newTopY = (int)(centerYPie - deltaY);
- break;
- case 4 : //straight line to left of center
- deltaX = radius;
- deltaY = 1;
- newXLocation = (int)(centerShadowXPie - deltaX);
- newYLocation = (int)(centerShadowYPie - deltaY);
- newTopX = (int)(centerXPie - deltaX);
- newTopY = (int)(centerYPie - deltaY);
- break;
- }
- if(s == 0)
- {
- lastYLocation -= 1;
- lastTopY -= 1;
- }
- COLORREF barColor;
- barColor = GetColor(s);
- int red, green, blue;
- red = GetRValue(barColor) - 35;
- green = GetGValue(barColor) - 35;
- blue = GetBValue(barColor) - 35;
- if(red < 0) red = 0;
- if(green < 0) green = 0;
- if(blue < 0) blue = 0;
- CPoint sp1 (lastXLocation, lastYLocation);
- CPoint sp2 (newXLocation, newYLocation);
- COLORREF shadowColor(RGB(red, green, blue));
- CPen shadowPen (PS_SOLID, 1, shadowColor);
- CBrush shadowBrush(shadowColor);
- pDC->SelectObject(&shadowPen);
- pDC->SelectObject(&shadowBrush);
- if((quadrant < 2) || (lastQuad < 2))
- {
- CPoint sidePolyArray[4];
- spa1.x = lastXLocation;
- spa1.y = lastYLocation;
- spa2.x = newXLocation;
- spa2.y = newYLocation;
- spa3.x = newTopX;
- spa3.y = newTopY;
- spa4.x = lastTopX;
- spa4.y = lastTopY;
- sidePolyArray[0] = spa1;
- sidePolyArray[1] = spa2;
- sidePolyArray[2] = spa3;
- sidePolyArray[3] = spa4;
- pDC->Polygon(sidePolyArray, 4);
- pDC->Pie(shadowRect, sp1, sp2);
- }
- else
- {
- CPoint sidePolyArray[3];
- spa1.x = newXLocation;
- spa1.y = newYLocation;
- spa2.x = newTopX;
- spa2.y = newTopY;
- spa3.x = lastTopX;
- spa3.y = lastTopY;
- sidePolyArray[0] = spa1;
- sidePolyArray[1] = spa2;
- sidePolyArray[2] = spa3;
- CPen oldShadowPen (PS_SOLID, 1, lastColor);
- pDC->SelectObject(&oldShadowPen);
- CBrush oldShadowBrush(lastColor);
- pDC->SelectObject(&oldShadowBrush);
- pDC->Pie(shadowRect, sp1, sp2);
- pDC->Polygon(sidePolyArray, 3);
- pDC->SelectObject(&shadowPen);
- pDC->SelectObject(&shadowBrush);
- }
- lastXLocation = newXLocation;
- lastYLocation = newYLocation;
- lastTopX = newTopX;
- lastTopY = newTopY;
- if((quadrant > 1) && (lastQuad < 2))
- {
- lastSidePolyArray[0] = spa1;
- lastSidePolyArray[1] = spa2;
- lastSidePolyArray[2] = spa3;
- lastSidePolyArray[3] = spa4;
- lastColor = shadowColor;
- }
- lastQuad = quadrant;
- pDC->SelectObject(pOldBrush);
- pDC->SelectObject(pOldPen);
- }
- }
- //draw normal pie
- lastXLocation = pieLeft;
- lastYLocation = centerYPie;
- dataSum = 0;
- for(s = 0; s < seriesSize; s++)
- {
- if(tmpSeries->GetData(s) > 0)
- {
- int seriesDataValue;
- seriesDataValue = tmpSeries->GetData(s);
- labelData = seriesDataValue / 2;
- dataSum += seriesDataValue;
- percent = (dataSum / totalSum) * 100;
- labelPercent = ((dataSum - labelData) / totalSum) * 100;
- degrees = (int)((360 * percent) / 100);
- labelDegrees = (int)((360 * labelPercent) / 100);
- //determine destination quadrant...
- //and set newXLocation and newYLocation values...
- //degress / 90 will never exceed 4.
- //this can tell us the quadrant of destination
- int quadrant = degrees / 90; //truncates decimal
- int labelQuadrant = labelDegrees / 90;
- //using the law of sines to determine the deltas :
- //deltaX = radius * sin(90 - degrees)
- //deltaY = radius * sin(degrees)
- //we convert degrees into radians so sin() function works right
- //note : in quad 1 and 3, we reverse the angle used to compute
- // the deltas, since the triangle plots reversed.
- switch(quadrant)
- {
- case 0 : //this is the base quadrant, so no manipulation needed
- degreeRadians = degrees * (3.14159 / 180);
- degreeRadians2 = (90 - degrees) * (3.14159 / 180);
- deltaX = radius * sin(degreeRadians2);
- deltaY = radius * sin(degreeRadians);
- newXLocation = (int)(centerXPie - deltaX);
- newYLocation = (int)(centerYPie + deltaY);
- break;
- case 1 : //bottom right quadrant, subtract 90 from angle
- degreeRadians = (degrees - 90) * (3.14159 / 180);
- degreeRadians2 = (90 - (degrees - 90)) * (3.14159 / 180);
- deltaX = radius * sin(degreeRadians);
- deltaY = radius * sin(degreeRadians2);
- newXLocation = (int)(centerXPie + deltaX);
- newYLocation = (int)(centerYPie + deltaY);
- break;
- case 2 : //top right quadrant, subtract 180 from angle
- degreeRadians = (degrees - 180) * (3.14159 / 180);
- degreeRadians2 = (90 - (degrees - 180)) * (3.14159 / 180);
- deltaX = radius * sin(degreeRadians2);
- deltaY = radius * sin(degreeRadians);
- newXLocation = (int)(centerXPie + deltaX);
- newYLocation = (int)(centerYPie - deltaY);
- break;
- case 3 : //upper left quadrant, subtract 270 from angle
- degreeRadians = (degrees - 270) * (3.14159 / 180);
- degreeRadians2 = (90 - (degrees - 270)) * (3.14159 / 180);
- deltaX = radius * sin(degreeRadians);
- deltaY = radius * sin(degreeRadians2);
- newXLocation = (int)(centerXPie - deltaX);
- newYLocation = (int)(centerYPie - deltaY);
- break;
- case 4 : //straight line to left of center
- deltaX = radius;
- deltaY = 1;
- newXLocation = (int)(centerXPie - deltaX);
- newYLocation = (int)(centerYPie - deltaY);
- break;
- }
- switch(labelQuadrant)
- {
- //after getting X & Y location for label, we take
- //1/2 the delta between x y locations and center pie
- case 0 :
- labelDegreeRadians = labelDegrees * (3.14159 / 180);
- labelDegreeRadians2 = (90 - labelDegrees) * (3.14159 / 180);
- labelDeltaX = radius * sin(labelDegreeRadians2);
- labelDeltaY = radius * sin(labelDegreeRadians);
- labelXLocation = (int)(centerXPie - labelDeltaX);
- labelYLocation = (int)(centerYPie + labelDeltaY);
- labelLineXStart = labelXLocation + ((centerXPie - labelXLocation) / 2);
- labelLineYStart = labelYLocation - ((labelYLocation - centerYPie) / 2);
- labelLineXEnd = labelXLocation - (radius / 2);
- labelLineYEnd = labelYLocation + (radius / 2);
- break;
- case 1 :
- labelDegreeRadians = (labelDegrees - 90) * (3.14159 / 180);
- labelDegreeRadians2 = (90 - (labelDegrees - 90)) * (3.14159 / 180);
- labelDeltaX = radius * sin(labelDegreeRadians);
- labelDeltaY = radius * sin(labelDegreeRadians2);
- labelXLocation = (int)(centerXPie + labelDeltaX);
- labelYLocation = (int)(centerYPie + labelDeltaY);
- labelLineXStart = labelXLocation - ((labelXLocation - centerXPie) / 2);
- labelLineYStart = labelYLocation - ((labelYLocation - centerYPie) / 2);
- labelLineXEnd = labelXLocation + (radius / 2);
- labelLineYEnd = labelYLocation + (radius / 2);
- break;
- case 2 :
- labelDegreeRadians = (labelDegrees - 180) * (3.14159 / 180);
- labelDegreeRadians2 = (90 - (labelDegrees - 180)) * (3.14159 / 180);
- labelDeltaX = radius * sin(labelDegreeRadians2);
- labelDeltaY = radius * sin(labelDegreeRadians);
- labelXLocation = (int)(centerXPie + labelDeltaX);
- labelYLocation = (int)(centerYPie - labelDeltaY);
- labelLineXStart = labelXLocation - ((labelXLocation - centerXPie) / 2);
- labelLineYStart = labelYLocation + ((centerYPie - labelYLocation) / 2);
- labelLineXEnd = labelXLocation + (radius / 2);
- labelLineYEnd = labelYLocation - (radius / 2);
- break;
- case 3 :
- labelDegreeRadians = (labelDegrees - 270) * (3.14159 / 180);
- labelDegreeRadians2 = (90 - (labelDegrees - 270)) * (3.14159 / 180);
- labelDeltaX = radius * sin(labelDegreeRadians);
- labelDeltaY = radius * sin(labelDegreeRadians2);
- labelXLocation = (int)(centerXPie - labelDeltaX);
- labelYLocation = (int)(centerYPie - labelDeltaY);
- labelLineXStart = labelXLocation + ((centerXPie - labelXLocation) / 2);
- labelLineYStart = labelYLocation + ((centerYPie - labelYLocation) / 2);
- labelLineXEnd = labelXLocation - (radius / 2);
- labelLineYEnd = labelYLocation - (radius / 2);
- break;
- //there should never be a half point ending on 4, so leave it out
- }
- pieLabel = new CGraphPieLabel();
- pieLabel->lineXStart = labelLineXStart;
- pieLabel->lineYStart = labelLineYStart;
- pieLabel->lineXEnd = labelLineXEnd;
- pieLabel->lineYEnd = labelLineYEnd;
- switch(labelQuadrant)
- {
- case 0 : //label to left of line
- pieLabel->topLeftX = labelLineXEnd - maxLabelWidth;
- pieLabel->topLeftY = labelLineYEnd;
- break;
- case 1 : //label to right of line
- pieLabel->topLeftX = labelLineXEnd + 5;
- pieLabel->topLeftY = labelLineYEnd;
- break;
- case 2 : //label to right of line
- pieLabel->topLeftX = labelLineXEnd + 5;
- pieLabel->topLeftY = labelLineYEnd - maxLabelHeight;
- break;
- case 3 : //label to left of line
- pieLabel->topLeftX = labelLineXEnd - maxLabelWidth;
- pieLabel->topLeftY = labelLineYEnd - maxLabelHeight;
- break;
- }
- pieLabel->labelQuadrant = labelQuadrant;
- int roundPercent;
- roundPercent = (int)((seriesDataValue * 100) / totalSum);
- pieLabel->pieLabel.Format("%d%%", roundPercent);
- pieLabels->AddTail(pieLabel);
- if(s == 0)
- lastYLocation -= 1;
- COLORREF barColor;
- barColor = GetColor(s);
- CPoint p1 (lastXLocation, lastYLocation);
- CPoint p2 (newXLocation, newYLocation);
- CBrush brush (barColor);
- CPen piePen (PS_SOLID, 1, barColor);
- pDC->SelectObject(&piePen);
- pDC->SelectObject(&brush);
- pDC->Pie(pieRect, p1, p2);
- lastXLocation = newXLocation;
- lastYLocation = newYLocation;
- }
- pDC->SelectObject(pOldBrush);
- pDC->SelectObject(pOldPen);
- }
- //draw lines and labels for pies slices
- POSITION labelPos;
- CBrush lineBrush (BLACK);
- CPen linePen (PS_SOLID, 1, BLACK);
- pDC->SelectObject(&lineBrush);
- pDC->SelectObject(&linePen);
- POSITION mainLinePos, checkLinePos;
- mainLinePos = pieLabels->GetHeadPosition();
- int numLinesDrawn = 0;
- CGraphPieLabel* currentLabel;
- CGraphPieLabel* tmpLabel;
- while(mainLinePos != NULL)
- {
- currentLabel = (CGraphPieLabel*)pieLabels->GetNext(mainLinePos);
- int r = 0;
- checkLinePos = pieLabels->GetHeadPosition();
- while(r < numLinesDrawn)
- {
- //check if any overlap in label areas
- tmpLabel = (CGraphPieLabel*)pieLabels->GetAt(checkLinePos);
- if((currentLabel->topLeftX > tmpLabel->topLeftX) &&
- (currentLabel->topLeftX < (tmpLabel->topLeftX + maxLabelWidth)) &&
- (currentLabel->topLeftY > tmpLabel->topLeftY) &&
- (currentLabel->topLeftY < (tmpLabel->topLeftY + maxLabelHeight)))
- {
- //OVERLAP !!!
- //move current label top left position up or down
- //depending on its quadrant
- if(currentLabel->labelQuadrant < 2)
- {
- //move label down to tmplabel topleft + height
- currentLabel->topLeftY = tmpLabel->topLeftY + maxLabelHeight;
- currentLabel->lineYEnd = tmpLabel->lineYEnd + maxLabelHeight;
- }
- else
- {
- //move label up to tmpLabel topleft - height
- currentLabel->topLeftY = tmpLabel->topLeftY - maxLabelHeight;
- currentLabel->lineYEnd = tmpLabel->lineYEnd - maxLabelHeight;
- }
- //reset r value to 0 so it starts over, just in
- //case we moved the label and it overlaps another
- r = 0;
- checkLinePos = pieLabels->GetHeadPosition();
- }
- else
- {
- r++;
- pieLabels->GetNext(checkLinePos);
- }
- }
- //draw the line and label
- pDC->MoveTo(currentLabel->lineXStart, currentLabel->lineYStart);
- pDC->LineTo(currentLabel->lineXEnd, currentLabel->lineYEnd);
- //write the label
- pDC->TextOut(currentLabel->topLeftX, currentLabel->topLeftY,
- currentLabel->pieLabel);
- numLinesDrawn++;
- }
- //now done, remove everything inside the label list
- labelPos = pieLabels->GetHeadPosition();
- while(labelPos != NULL)
- {
- pieLabel = (CGraphPieLabel*)pieLabels->GetNext(labelPos);
- delete pieLabel;
- }
- delete pieLabels;
- }
- pDC->SelectObject(pOldBrush);
- pDC->SelectObject(pOldPen);
- }
- void CGraph::Draw3DStackedBarSeries(CDC* pDC)
- {
- int barWidth;
- int barL, barT, barR, barB;
- int tickXLocation, tickYLocation;
- int seriesSpace;
- int barHeight;
- POSITION pos;
- CGraphSeries* tmpSeries;
- int blue;
- int red;
- int green;
- if(graphAlignment)
- {
- //determine width of barchart data blocks
- seriesSpace = xAxisWidth / graphSeries->GetCount();
- barWidth = (int)(seriesSpace * .8);
- pos = graphSeries->GetHeadPosition();
- double dataScale = 0.00;
- dataScale = (yAxisHeight * 1.00) / (maxTick - minTick);
- for(int x = 1; x <= graphSeries->GetCount(); x++)
- {
- tmpSeries = (CGraphSeries*)graphSeries->GetNext(pos);
- tickXLocation = xApexPoint + ((x * seriesSpace) - (seriesSpace / 2));
- barT = yApexPoint; //this is a running total;
- //it starts at yApexPoint so barB can
- //start there, then moves up by barHeight
- for(int s = 0; s < seriesSize; s++)
- {
- if(tmpSeries->GetData(s) > -1)
- {
- barHeight = (int)(((tmpSeries->GetData(s) - minTick) * 1.00) * dataScale);
- if(((tmpSeries->GetData(s) - minTick) > 0) && (barHeight < 1))
- barHeight = (int)dataScale;
- barB = barT;
- barL = tickXLocation - (barWidth / 2);
- if(barHeight > yAxisHeight)
- barT = barB - yAxisHeight;
- else
- barT = barB - barHeight;
- barR = barL + barWidth;
- COLORREF barColor;
- barColor = GetColor(s);
- CBrush brush (barColor);
- CPen rectPen (PS_SOLID, 1, barColor);
- CPen* pOldPen;
- pOldPen = pDC->SelectObject(&rectPen);
- CBrush* pOldBrush;
- pOldBrush = pDC->SelectObject(&brush);
- pDC->Rectangle(barL, barT, barR, barB);
- //now, we do the side
- //side is darker than front, so subtract
- //from color to make closer to black
- red = GetRValue(barColor);
- green = GetGValue(barColor);
- blue = GetBValue(barColor);
- int sideRed = red - 35;
- int sideGreen = green - 35;
- int sideBlue = blue - 35;
- if(sideRed < 0) sideRed = 0;
- if(sideGreen < 0) sideGreen = 0;
- if(sideBlue < 0) sideBlue = 0;
- COLORREF sideColor;
- sideColor = RGB(sideRed, sideGreen, sideBlue);
- CBrush sideBrush (sideColor);
- CPen sidePen (PS_SOLID, 1, sideColor);
- pDC->SelectObject(&sideBrush);
- pDC->SelectObject(&sidePen);
- CPoint sidePolyArray[4];
- CPoint sp1(barR, barT);
- CPoint sp2(barR, barB);
- CPoint sp3(barR + depth, barB - depth);
- CPoint sp4(barR + depth, barT - depth);
- sidePolyArray[0] = sp1;
- sidePolyArray[1] = sp2;
- sidePolyArray[2] = sp3;
- sidePolyArray[3] = sp4;
- pDC->Polygon(sidePolyArray, 4);
- //finally, the top
- int topRed = red + 35;
- int topGreen = green + 35;
- int topBlue = blue + 35;
- if(topRed > 255) topRed = 255;
- if(topGreen > 255) topGreen = 255;
- if(topBlue > 255) topBlue = 255;
- COLORREF topColor;
- topColor = RGB(topRed, topGreen, topBlue);
- CBrush topBrush (topColor);
- CPen topPen (PS_SOLID, 1, topColor);
- pDC->SelectObject(&topBrush);
- pDC->SelectObject(&topPen);
- CPoint topPolyArray[4];
- CPoint tp1(barL, barT);
- CPoint tp2(barR, barT);
- CPoint tp3(barR + depth, barT - depth);
- CPoint tp4(barL + depth, barT - depth);
- topPolyArray[0] = tp1;
- topPolyArray[1] = tp2;
- topPolyArray[2] = tp3;
- topPolyArray[3] = tp4;
- pDC->Polygon(topPolyArray, 4);
- pDC->SelectObject(pOldBrush);
- pDC->SelectObject(pOldPen);
- }
- }
- }
- }
- else
- {
- //determine width of barchart data blocks
- seriesSpace = yAxisHeight / graphSeries->GetCount();
- barHeight = (int)(seriesSpace * .8);
- pos = graphSeries->GetHeadPosition();
- double dataScale = 0.00;
- dataScale = ((xAxisWidth - 10) * 1.00) / (maxTick - minTick);
- for(int y = 1; y <= graphSeries->GetCount(); y++)
- {
- tmpSeries = (CGraphSeries*)graphSeries->GetNext(pos);
- tickYLocation = yApexPoint - ((y * seriesSpace) - (seriesSpace / 2));
- barR = xApexPoint; //this is a running total;
- //it starts at xApexPoint so barL can
- //start there, then moves right by barWidth
- for(int s = 0; s < seriesSize; s++)
- {
- if(tmpSeries->GetData(s) > -1)
- {
- barWidth = (int)(((tmpSeries->GetData(s) - minTick) * 1.00) * dataScale);
- if(((tmpSeries->GetData(s) - minTick) > 0) && (barWidth < 1))
- barWidth = (int)dataScale;
- barL = barR;
- barT = tickYLocation - (barHeight / 2);
- barB = barT + barHeight;
- if(barWidth > xAxisWidth)
- barR = barL + xAxisWidth;
- else
- barR = barL + barWidth;
- COLORREF barColor;
- barColor = GetColor(s);
- CBrush brush (barColor);
- CBrush* pOldBrush;
- pOldBrush = pDC->SelectObject(&brush);
- CPen rectPen (PS_SOLID, 1, barColor);
- CPen* pOldPen;
- pOldPen = pDC->SelectObject(&rectPen);
- pDC->Rectangle(barL, barT, barR, barB);
- //now, we do the side
- //side is darker than front, so subtract
- //from color to make closer to black
- red = GetRValue(barColor);
- green = GetGValue(barColor);
- blue = GetBValue(barColor);
- int sideRed = red - 35;
- int sideGreen = green - 35;
- int sideBlue = blue - 35;
- if(sideRed < 0) sideRed = 0;
- if(sideGreen < 0) sideGreen = 0;
- if(sideBlue < 0) sideBlue = 0;
- COLORREF sideColor;
- sideColor = RGB(sideRed, sideGreen, sideBlue);
- CBrush sideBrush (sideColor);
- CPen sidePen (PS_SOLID, 1, sideColor);
- pDC->SelectObject(&sideBrush);
- pDC->SelectObject(&sidePen);
- CPoint sidePolyArray[4];
- CPoint sp1(barL, barT);
- CPoint sp2(barR, barT);
- CPoint sp3(barR + depth, barT - depth);
- CPoint sp4(barL + depth, barT - depth);
- sidePolyArray[0] = sp1;
- sidePolyArray[1] = sp2;
- sidePolyArray[2] = sp3;
- sidePolyArray[3] = sp4;
- pDC->Polygon(sidePolyArray, 4);
- //finally, the top
- int topRed = red + 35;
- int topGreen = green + 35;
- int topBlue = blue + 35;
- if(topRed > 255) topRed = 255;
- if(topGreen > 255) topGreen = 255;
- if(topBlue > 255) topBlue = 255;
- COLORREF topColor;
- topColor = RGB(topRed, topGreen, topBlue);
- CBrush topBrush (topColor);
- CPen topPen (PS_SOLID, 1, topColor);
- pDC->SelectObject(&topBrush);
- pDC->SelectObject(&topPen);
- CPoint topPolyArray[4];
- CPoint tp1(barR, barT);
- CPoint tp2(barR, barB);
- CPoint tp3(barR + depth, barB - depth);
- CPoint tp4(barR + depth, barT - depth);
- topPolyArray[0] = tp1;
- topPolyArray[1] = tp2;
- topPolyArray[2] = tp3;
- topPolyArray[3] = tp4;
- pDC->Polygon(topPolyArray, 4);
- pDC->SelectObject(pOldBrush);
- pDC->SelectObject(pOldPen);
- }
- }
- }
- }
- }
- void CGraph::PrintBarSeries(CDC* pDC)
- {
- int barWidth;
- int dataPlotSize; //used to plot rects of data
- int barL, barT, barR, barB;
- int tickXLocation, tickYLocation;
- int seriesSpace;
- int barHeight; //for scalability
- POSITION pos;
- CGraphSeries* tmpSeries;
- if(graphAlignment)
- {
- //determine width of barchart data blocks
- seriesSpace = xAxisWidth / graphSeries->GetCount();
- barWidth = (int)((seriesSpace * .6) / seriesSize);
- dataPlotSize = seriesSize * barWidth;
- pos = graphSeries->GetHeadPosition();
- for(int x = 1; x <= graphSeries->GetCount(); x++)
- {
- tmpSeries = (CGraphSeries*)graphSeries->GetNext(pos);
- tickXLocation = xApexPoint + ((x * seriesSpace) - (seriesSpace / 2));
- for(int s = 0; s < seriesSize; s++)
- {
- if(tmpSeries->GetData(s) > -1)
- {
- double dataScale = 0.00;
- dataScale = ((yAxisHeight - 100) * 1.00) / (maxTick - minTick);
- barHeight = (int)(((tmpSeries->GetData(s) - minTick) * 1.00) * dataScale);
- if(((tmpSeries->GetData(s) - minTick) > 0) && (barHeight < 1))
- barHeight = (int)dataScale;
- barL = tickXLocation - (dataPlotSize / 2) + (s * barWidth);
- if(barHeight > yAxisHeight)
- barT = yApexPoint + yAxisHeight;
- else
- barT = yApexPoint + barHeight;
- barR = barL + barWidth;
- barB = yApexPoint;
- COLORREF barColor;
- barColor = GetColor(s);
- CBrush brush (barColor);
- CBrush* pOldBrush;
- pOldBrush = pDC->SelectObject(&brush);
- pDC->Rectangle(barL, barT, barR, barB);
- pDC->SelectObject(pOldBrush);
- }
- }
- }
- }
- else
- {
- //determine width of barchart data blocks
- seriesSpace = yAxisHeight / graphSeries->GetCount();
- barHeight = (int)((seriesSpace * .6) / seriesSize);
- dataPlotSize = seriesSize * barHeight;
- pos = graphSeries->GetHeadPosition();
- for(int y = 1; y <= graphSeries->GetCount(); y++)
- {
- tmpSeries = (CGraphSeries*)graphSeries->GetNext(pos);
- tickYLocation = yApexPoint + ((y * seriesSpace) - (seriesSpace / 2));
- for(int s = 0; s < seriesSize; s++)
- {
- if(tmpSeries->GetData(s) > -1)
- {
- double dataScale = 0.00;
- dataScale = ((xAxisWidth - 100) * 1.00) / (maxTick - minTick);
- barWidth = (int)(((tmpSeries->GetData(s) - minTick) * 1.00) * dataScale);
- if(((tmpSeries->GetData(s) - minTick) > 0) && (barWidth < 1))
- barWidth = (int)dataScale;
- barL = xApexPoint;
- barT = tickYLocation - (dataPlotSize / 2) + (s * barHeight);
- barB = barT + barHeight;
- if(barWidth > xAxisWidth)
- barR = xApexPoint + xAxisWidth;
- else
- barR = xApexPoint + barWidth;
- COLORREF barColor;
- barColor = GetColor(s);
- CBrush brush (barColor);
- CBrush* pOldBrush;
- pOldBrush = pDC->SelectObject(&brush);
- pDC->Rectangle(barL, barT, barR, barB);
- pDC->SelectObject(pOldBrush);
- }
- }
- }
- }
- }
- void CGraph::PrintLineSeries(CDC* pDC)
- {
- int barWidth;
- int dataPlotSize; //used to plot rects of data
- int tickXLocation, tickYLocation;
- int seriesSpace;
- int barHeight; //for scalability
- POSITION pos;
- CGraphSeries* tmpSeries;
- int lastXLoc, lastYLoc;
- if(graphAlignment)
- {
- for(int s = 0; s < seriesSize; s++)
- {
- //determine width of barchart data blocks
- seriesSpace = xAxisWidth / graphSeries->GetCount();
- barWidth = (int)((seriesSpace * .6) / seriesSize);
- dataPlotSize = seriesSize * barWidth;
- pos = graphSeries->GetHeadPosition();
- for(int x = 1; x <= graphSeries->GetCount(); x++)
- {
- tmpSeries = (CGraphSeries*)graphSeries->GetNext(pos);
- if(tmpSeries->GetData(s) > -1)
- {
- tickXLocation = xApexPoint + ((x * seriesSpace) - (seriesSpace / 2));
- barHeight = 0;
- double dataScale = 0.00;
- if((maxTick - minTick) != yAxisHeight)
- dataScale = ((yAxisHeight * 1.00) / ((maxTick - minTick) * 1.00)) * tickSpace;
- else dataScale = tickSpace * 15.00;
- int axisHeight = (int)(dataScale * numTicks);
- double barPercent = 0.00;
- barPercent = ((tmpSeries->GetData(s) - minTick) * 1.00) / maxTick;
- barHeight = (int)(barPercent * axisHeight);
- if(((tmpSeries->GetData(s) - minTick) > 0) && (barHeight < 1))
- barHeight = (int)dataScale;
- int yDataLocation = yApexPoint + barHeight;
- //now have x and y location of center of ellipse
- COLORREF barColor;
- barColor = GetColor(s);
- CBrush brush (barColor);
- CBrush* pOldBrush;
- pOldBrush = pDC->SelectObject(&brush);
- //draw line back to last data member
- if(x > 1)
- {
- CPen* pOldPen;
- CPen linePen (PS_SOLID, 20, barColor);
- pOldPen = pDC->SelectObject(&linePen);
- pDC->MoveTo(lastXLoc, lastYLoc);
- pDC->LineTo(tickXLocation, yDataLocation);
- pDC->SelectObject(pOldPen);
- }
- //now draw ellipse...
- pDC->Ellipse(tickXLocation + 60, yDataLocation + 60,
- tickXLocation - 60, yDataLocation - 60);
- lastXLoc = tickXLocation;
- lastYLoc = yDataLocation;
- pDC->SelectObject(pOldBrush);
- }
- }
- }
- }
- else
- {
- for(int s = 0; s < seriesSize; s++)
- {
- //determine width of barchart data blocks
- seriesSpace = yAxisHeight / graphSeries->GetCount();
- barHeight = (int)((seriesSpace * .6) / seriesSize);
- dataPlotSize = seriesSize * barHeight;
- pos = graphSeries->GetHeadPosition();
- for(int x = 1; x <= graphSeries->GetCount(); x++)
- {
- tmpSeries = (CGraphSeries*)graphSeries->GetNext(pos);
- if(tmpSeries->GetData(s) > -1)
- {
- tickYLocation = yApexPoint + ((x * seriesSpace) - (seriesSpace / 2));
- barWidth = 0;
- double dataScale = 0.00;
- dataScale = ((xAxisWidth - 100) * 1.00) / (maxTick - minTick);
- int axisWidth = (int)(dataScale * (maxTick - minTick));
- double barPercent = 0.00;
- barPercent = ((tmpSeries->GetData(s) - minTick) * 1.00) / ((maxTick - minTick) * 1.00);
- barWidth = (int)(barPercent * axisWidth);
- if(((tmpSeries->GetData(s) - minTick) > 0) && (barHeight < 1))
- barWidth = (int)dataScale;
- int xDataLocation = xApexPoint + barWidth;
- //now have x and y location of center of ellipse
- COLORREF barColor;
- barColor = GetColor(s);
- CBrush brush (barColor);
- CBrush* pOldBrush;
- pOldBrush = pDC->SelectObject(&brush);
- //draw line back to last data member
- if(x > 1)
- {
- CPen* pOldPen;
- CPen linePen (PS_SOLID, 20, barColor);
- pOldPen = pDC->SelectObject(&linePen);
- pDC->MoveTo(lastXLoc, lastYLoc);
- pDC->LineTo(xDataLocation, tickYLocation);
- pDC->SelectObject(pOldPen);
- }
- //now draw ellipse...
- pDC->Ellipse(xDataLocation + 60, tickYLocation + 60,
- xDataLocation - 60, tickYLocation - 60);
- lastYLoc = tickYLocation;
- lastXLoc = xDataLocation;
- pDC->SelectObject(pOldBrush);
- }
- }
- }
- }
- }
- void CGraph::PrintPieSeries(CDC* pDC)
- {
- int seriesSpace;
- POSITION pos;
- CGraphSeries* tmpSeries;
- double dataSum = 0.00; //for storing cumulative sum
- int lastXLocation, lastYLocation;
- int newXLocation, newYLocation;
- double percent = 0.00;
- int degrees;
- double totalSum = 0.00;
- int deltaXY;
- int radius;
- double labelData = 0.00;
- int labelXLocation, labelYLocation;
- double labelPercent = 0.00;
- int labelDegrees;
- int labelDeltaXY;
- int labelLineXStart, labelLineYStart;
- int labelLineXEnd, labelLineYEnd;
- int maxLabelWidth;
- int maxLabelHeight;
- TEXTMETRIC tm;
- lastXLocation = 0;
- lastYLocation = 0;
- pDC->GetTextMetrics(&tm);
- maxLabelWidth = tm.tmMaxCharWidth + 50;
- maxLabelHeight = tm.tmHeight + 30;
- //pie labels are stored in a list and drawn after entire pie
- //is completed.
- CObList *pieLabels;
- CGraphPieLabel *pieLabel;
- //determine width of pie display area
- if(xAxisWidth > yAxisHeight)
- seriesSpace = yAxisHeight / graphSeries->GetCount();
- else
- seriesSpace = xAxisWidth / graphSeries->GetCount();
- seriesSpace -= (3 * maxLabelWidth); //allows text like 25% (3 chars)
- //to plot a pie plus labels inside of series space, use the following :
- //(3 * radius) + (2 * label width) = series space
- //so, 3*radius = series space - (2 * label width)
- // 1 radius = (series space - (2 * label width)) / 3
- radius = seriesSpace / 3; //pie needs 2 radius, + 1 extra for line to labels = 3 for my divisor
- int centerYPie = pGraphT - (yAxisHeight / 2) - 500;
- pos = graphSeries->GetHeadPosition();
- for(int x = 1; x <= graphSeries->GetCount(); x++)
- {
- pieLabels = new CObList();
- tmpSeries = (CGraphSeries*)graphSeries->GetNext(pos);
- totalSum = 0;
- for(int s = 0; s < seriesSize; s++)
- totalSum += tmpSeries->GetData(s);
- int pieLeft, pieRight;
- if(graphSeries->GetCount() == 1)
- {
- pieLeft = xApexPoint + (xAxisWidth / 2) - radius;
- }
- else
- {
- pieLeft = xApexPoint + 15 + ((x * 2 - 1) * ((xAxisWidth / graphSeries->GetCount()) / 2)) - radius;
- }
- pieRight = pieLeft + (2 * radius);
- CRect pieRect (pieLeft,
- centerYPie + radius,
- pieRight,
- centerYPie - radius);
- int centerXPie = pieLeft + radius;
- CFont pieFont;
- pieFont.CreateFont(xTickFontSize * 20, 0, 0, 0, 700, FALSE, FALSE, 0,
- ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
- DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN,"Arial");
- CFont* pOldFont = (CFont*) pDC->SelectObject(&pieFont);
- //plot series label
- pDC->TextOut(centerXPie - ((tmpSeries->GetLabel().GetLength() / 2) * ((xTickFontSize / 2) * 20)),
- centerYPie - radius - maxLabelHeight - 600, tmpSeries->GetLabel());
- pDC->SelectObject(pOldFont);
- lastXLocation = pieLeft;
- lastYLocation = centerYPie;
- dataSum = 0;
- for(s = 0; s < seriesSize; s++)
- {
- if(tmpSeries->GetData(s) > 0)
- {
- int seriesDataValue;
- seriesDataValue = tmpSeries->GetData(s);
- dataSum += seriesDataValue;
- percent = (dataSum * 100) / totalSum;
- degrees = (int)((360 * percent) / 100);
- labelData = tmpSeries->GetData(s) / 2;
- labelPercent = ((dataSum - labelData) / totalSum) * 100;
- labelDegrees = (int)((360 * labelPercent) / 100);
- //degress / 90 will never exceed 4.
- //this can tell us the quadrant of destination
- deltaXY = (degrees * radius) / 90;
- labelDeltaXY = (labelDegrees * radius) / 90;
- //deltaXY is change from start point of pie 0
- //this value is total change. so if radius is 300
- //and degrees is 270, delta is 300. The change
- //would move both x and y 300 pixels. For x, 100
- //to right is center, another 100 to right edge,
- //100 back to center. For y, 100 to bottom, 100
- //back to center, 100 to top. thus gives 270 degree
- //rotation.
- //determine destination quadrant...
- //and set newXLocation and newYLocation values...
- int quadrant = degrees / 90; //truncates decimal
- int labelQuadrant = labelDegrees / 90;
- switch(quadrant)
- {
- //in the computations below, the remarked line is
- //the original computation. The line above it, for
- //actual use, is the simplified line, and gives the
- //exact same result
- case 0 : newXLocation = pieLeft + deltaXY;
- newYLocation = centerYPie - deltaXY;
- break;
- case 1 : newXLocation = pieLeft + deltaXY;
- newYLocation = centerYPie - (2 * radius) + deltaXY;
- break;
- case 2 : newXLocation = pieLeft + (4 * radius) - deltaXY;
- newYLocation = centerYPie - (2 * radius) + deltaXY;
- break;
- case 3 : newXLocation = pieLeft + (4 * radius) - deltaXY;
- newYLocation = centerYPie + (4 * radius) - deltaXY;
- break;
- case 4 : newXLocation = pieLeft;
- newYLocation = centerYPie + 1;
- break;
- }
- switch(labelQuadrant)
- {
- //after getting X & Y location for label, we take
- //1/2 the delta between x y locations and center pie
- case 0 : labelXLocation = pieLeft + labelDeltaXY;
- labelYLocation = centerYPie - labelDeltaXY;
- labelLineXStart = labelXLocation + ((centerXPie - labelXLocation) / 2);
- labelLineYStart = labelYLocation - ((labelYLocation - centerYPie) / 2);
- labelLineXEnd = labelXLocation - (radius / 2);
- labelLineYEnd = labelYLocation - (radius / 2);
- break;
- case 1 : labelXLocation = pieLeft + labelDeltaXY;
- labelYLocation = centerYPie - (2 * radius) + labelDeltaXY;
- labelLineXStart = labelXLocation - ((labelXLocation - centerXPie) / 2);
- labelLineYStart = labelYLocation - ((labelYLocation - centerYPie) / 2);
- labelLineXEnd = labelXLocation + (radius / 2);
- labelLineYEnd = labelYLocation - (radius / 2);
- break;
- case 2 : labelXLocation = pieLeft + (4 * radius) - labelDeltaXY;
- labelYLocation = centerYPie - (2 * radius) + labelDeltaXY;
- labelLineXStart = labelXLocation - ((labelXLocation - centerXPie) / 2);
- labelLineYStart = labelYLocation - ((labelYLocation - centerYPie) / 2);
- labelLineXEnd = labelXLocation + (radius / 2);
- labelLineYEnd = labelYLocation + (radius / 2);
- break;
- case 3 : labelXLocation = pieLeft + (4 * radius) - labelDeltaXY;
- labelYLocation = centerYPie + (4 * radius) - labelDeltaXY;
- labelLineXStart = labelXLocation + ((centerXPie - labelXLocation) / 2);
- labelLineYStart = labelYLocation - ((labelYLocation - centerYPie) / 2);
- labelLineXEnd = labelXLocation - (radius / 2);
- labelLineYEnd = labelYLocation + (radius / 2);
- break;
- //there should never be a half point ending on 4, so leave it out
- }
- pieLabel = new CGraphPieLabel();
- pieLabel->lineXStart = labelLineXStart;
- pieLabel->lineYStart = labelLineYStart;
- pieLabel->lineXEnd = labelLineXEnd;
- pieLabel->lineYEnd = labelLineYEnd;
- switch(labelQuadrant)
- {
- case 0 : //label to left of line
- pieLabel->topLeftX = labelLineXEnd - maxLabelWidth;
- pieLabel->topLeftY = labelLineYEnd;
- break;
- case 1 : //label to right of line
- pieLabel->topLeftX = labelLineXEnd + 50;
- pieLabel->topLeftY = labelLineYEnd;
- break;
- case 2 : //label to right of line
- pieLabel->topLeftX = labelLineXEnd + 50;
- pieLabel->topLeftY = labelLineYEnd + maxLabelHeight;
- break;
- case 3 : //label to left of line
- pieLabel->topLeftX = labelLineXEnd - maxLabelWidth;
- pieLabel->topLeftY = labelLineYEnd + maxLabelHeight;
- break;
- }
- pieLabel->labelQuadrant = labelQuadrant;
- int roundPercent;
- roundPercent = (int)((seriesDataValue * 100) / totalSum);
- pieLabel->pieLabel.Format("%d%%", roundPercent);
- pieLabels->AddTail(pieLabel);
- if(s == 0)
- lastYLocation -= 1;
- CPoint p1 (lastXLocation, lastYLocation);
- CPoint p2 (newXLocation, newYLocation);
- COLORREF barColor;
- barColor = GetColor(s);
- CBrush brush (barColor);
- CBrush* pOldBrush;
- CPen piePen(PS_SOLID, 1, barColor);
- CPen* pOldPen;
- pOldBrush = pDC->SelectObject(&brush);
- pOldPen = pDC->SelectObject(&piePen);
- pDC->Pie(pieRect, p1, p2);
- pDC->SelectObject(pOldBrush);
- pDC->SelectObject(pOldPen);
- lastXLocation = newXLocation;
- lastYLocation = newYLocation;
- }
- }
- //draw lines and labels for pies slices
- POSITION labelPos;
- CBrush lineBrush (BLACK);
- CBrush* pOldBrush;
- pOldBrush = pDC->SelectObject(&lineBrush);
- POSITION mainLinePos, checkLinePos;
- mainLinePos = pieLabels->GetHeadPosition();
- int numLinesDrawn = 0;
- CGraphPieLabel* currentLabel;
- CGraphPieLabel* tmpLabel;
- while(mainLinePos != NULL)
- {
- currentLabel = (CGraphPieLabel*)pieLabels->GetNext(mainLinePos);
- int r = 0;
- checkLinePos = pieLabels->GetHeadPosition();
- while(r < numLinesDrawn)
- {
- //check if any overlap in label areas
- tmpLabel = (CGraphPieLabel*)pieLabels->GetAt(checkLinePos);
- if((currentLabel->topLeftX > tmpLabel->topLeftX) &&
- (currentLabel->topLeftX < (tmpLabel->topLeftX + maxLabelWidth)) &&
- (currentLabel->topLeftY < tmpLabel->topLeftY) &&
- (currentLabel->topLeftY > (tmpLabel->topLeftY - maxLabelHeight)))
- {
- //OVERLAP !!!
- //move current label top left position up or down
- //depending on its quadrant
- if(currentLabel->labelQuadrant < 2)
- {
- //move label down to tmplabel topleft + height
- currentLabel->topLeftY = tmpLabel->topLeftY - maxLabelHeight;
- currentLabel->lineYEnd = tmpLabel->lineYEnd - maxLabelHeight;
- }
- else
- {
- //move label up to tmpLabel topleft - height
- currentLabel->topLeftY = tmpLabel->topLeftY + maxLabelHeight;
- currentLabel->lineYEnd = tmpLabel->lineYEnd + maxLabelHeight;
- }
- //reset r value to 0 so it starts over, just in
- //case we moved the label and it overlaps another
- r = 0;
- checkLinePos = pieLabels->GetHeadPosition();
- }
- else
- {
- r++;
- pieLabels->GetNext(checkLinePos);
- }
- }
- //draw the line and label
- pDC->MoveTo(currentLabel->lineXStart, currentLabel->lineYStart);
- pDC->LineTo(currentLabel->lineXEnd, currentLabel->lineYEnd);
- //write the label
- pDC->TextOut(currentLabel->topLeftX, currentLabel->topLeftY,
- currentLabel->pieLabel);
- numLinesDrawn++;
- }
- pDC->SelectObject(pOldBrush);
- //now done, remove everything inside the label list
- labelPos = pieLabels->GetHeadPosition();
- while(labelPos != NULL)
- {
- pieLabel = (CGraphPieLabel*)pieLabels->GetNext(labelPos);
- delete pieLabel;
- }
- delete pieLabels;
- }
- }
- void CGraph::PrintScatterSeries(CDC* pDC)
- {
- //rightXTick and topYTick contain the outer bounds of the axis ticks.
- //So, if maxTick is 100 on both axis lines, then 100, 100 would be top
- //right. We will use the bounds to see spacing from apex points and then
- //scale so any point can be plotted inside
- double yAxisScale, xAxisScale;
- int tickXLocation, tickYLocation;
- //multiply each value by 1.00 to force result into a double value, and therefore
- //make it more accurate in it's plot location.
- yAxisScale = ((p_topYTick - yApexPoint) / (maxTick * 1.00));
- xAxisScale = ((p_rightXTick - xApexPoint) / (maxTick * 1.00));
- //points will now plot as ((value * scale) + apex point)
- COLORREF barColor;
- barColor = BLACK;
- CBrush brush (barColor);
- CBrush* pOldBrush;
- pOldBrush = pDC->SelectObject(&brush);
- POSITION pos;
- CGraphSeries* tmpSeries;
- for(pos = graphSeries->GetHeadPosition(); pos != NULL; graphSeries->GetNext(pos))
- {
- tmpSeries = (CGraphSeries*)graphSeries->GetAt(pos);
- //multiply each value by 1.00 to force result into a double value, and therefore
- //make it more accurate in it's plot location.
- tickXLocation = (int)((tmpSeries->GetXDataValue() * 1.00) * xAxisScale) + xApexPoint;
- tickYLocation = yApexPoint + (int)((tmpSeries->GetYDataValue() * 1.00) * yAxisScale);
- //draw ellipse...
- pDC->Ellipse(tickXLocation - 60, tickYLocation - 60,
- tickXLocation + 60, tickYLocation + 60);
- }
- pDC->SelectObject(pOldBrush);
- }
- void CGraph::PrintBoxWhiskerSeries(CDC* pDC)
- {
- int upperQuartile;
- int lowerQuartile;
- int median;
- int highValue;
- int lowValue;
- COLORREF barColor;
- barColor = BLACK;
- CBrush brush (barColor);
- CBrush* pOldBrush;
- pOldBrush = pDC->SelectObject(&brush);
- int barWidth;
- int barL, barT, barR, barB;
- int tickXLocation, tickYLocation;
- int seriesSpace;
- int barHeight;
- POSITION pos;
- CGraphSeries* tmpSeries;
- pos = graphSeries->GetHeadPosition();
- CUIntArray dataArray;
- CUIntArray sortedArray;
- for(int x = 1; x <= graphSeries->GetCount(); x++)
- {
- dataArray.RemoveAll();
- sortedArray.RemoveAll();
- CObList *sortedData;
- sortedData = new CObList();
- tmpSeries = (CGraphSeries*)graphSeries->GetNext(pos);
- seriesSize = tmpSeries->GetDataCount();
- int dataValue;
- for(int s = 0; s < seriesSize; s++)
- {
- dataValue = 0;
- if(tmpSeries->GetData(s) > -1)
- dataValue = tmpSeries->GetData(s);
- dataArray.Add(dataValue);
- }
- //sort the array
- dataValue = dataArray.GetAt(0);
- sortedArray.Add(dataValue);
- for(int d = 1; d < dataArray.GetSize(); d++)
- {
- dataValue = dataArray.GetAt(d);
- BOOL placed = FALSE;
- for(int s = 0; s < sortedArray.GetSize(); s++)
- {
- int tmpI = sortedArray.GetAt(s);
- if(dataValue <= tmpI)
- {
- sortedArray.InsertAt(s, dataValue);
- placed = TRUE;
- break;
- }
- }
- if(!placed) //add at end
- sortedArray.Add(dataValue);
- }
- //sortedArray now contains the sorted list of all data in this
- //series. From here, we derive the other box-whisker data
- int medialElement;
- div_t div_result;
- div_result = div(sortedArray.GetSize(), 2);
- if(div_result.rem == 0) //even number of elements
- {
- //size is not 0 base, so below, I subtract 1 to 0 base it.
- medialElement = (sortedArray.GetSize() / 2) - 1;
- median = sortedArray.GetAt(medialElement) +
- ((sortedArray.GetAt(medialElement + 1) -
- sortedArray.GetAt(medialElement)) / 2);
- highValue = sortedArray.GetAt(sortedArray.GetSize() - 1);
- lowValue = sortedArray.GetAt(0);
- div_t div2Result;
- div2Result = div(medialElement + 1, 2);
- if(div2Result.rem == 0) //even again
- {
- upperQuartile = sortedArray.GetAt(medialElement + 1 + (medialElement / 2)) +
- (sortedArray.GetAt(medialElement + (medialElement / 2) + 2) -
- sortedArray.GetAt(medialElement + (medialElement / 2))) / 2;
- lowerQuartile = sortedArray.GetAt(medialElement / 2) +
- ((sortedArray.GetAt((medialElement / 2) + 1) -
- sortedArray.GetAt(medialElement / 2)) / 2);
- }
- else //odd
- {
- upperQuartile = sortedArray.GetAt(medialElement + 1 + (medialElement / 2));
- lowerQuartile = sortedArray.GetAt(medialElement / 2);
- }
- }
- else //odd number of elements
- {
- //size is not 0 base, so below, I subtract 1 to 0 base it.
- medialElement = sortedArray.GetSize() / 2;
- median = sortedArray.GetAt(medialElement);
- highValue = sortedArray.GetAt(sortedArray.GetSize() - 1);
- lowValue = sortedArray.GetAt(0);
- div_t div2Result;
- div2Result = div(medialElement, 2);
- if(div2Result.rem == 0) //even
- {
- upperQuartile = sortedArray.GetAt(medialElement + (medialElement / 2)) +
- (sortedArray.GetAt(medialElement + (medialElement / 2) + 1) -
- sortedArray.GetAt(medialElement + (medialElement / 2))) / 2;
- lowerQuartile = sortedArray.GetAt((medialElement - 1) / 2) +
- ((sortedArray.GetAt((medialElement + 1) / 2) -
- sortedArray.GetAt((medialElement - 1) / 2)) / 2);
- }
- else //odd
- {
- upperQuartile = sortedArray.GetAt(medialElement + 1 + (medialElement / 2));
- lowerQuartile = sortedArray.GetAt(medialElement / 2);
- }
- }
- //data has been computed for median, high, low, and interquartile range
- //now we can draw the series
- if(graphAlignment)
- {
- seriesSpace = xAxisWidth / graphSeries->GetCount();
- barWidth = (int)(seriesSpace * .8);
- double tickScale = 0.00;
- tickScale = (yAxisHeight - 100) / numTicks; //this must be consistent with PrintAxis()
- tickXLocation = xApexPoint + ((x * seriesSpace) - (seriesSpace / 2));
- barL = tickXLocation - (barWidth / 2);
- barR = barL + barWidth;
- double dataScale = 0.00;
- dataScale = ((yAxisHeight - 60) * 1.00) / (maxTick - minTick);
- //top cross bar (max value)
- barHeight = (int)((highValue * 1.00) * tickScale);
- barT = yApexPoint + barHeight;
- barB = barT - 60;
- pDC->Rectangle(barL, barT, barR, barB);
- //bottom cross bar (min value)
- barHeight = (int)((lowValue * 1.00) * tickScale);
- barT = yApexPoint + barHeight;
- barB = barT + 60;
- pDC->Rectangle(barL, barT, barR, barB);
- //vertical line (whisker)
- barHeight = (int)((highValue * 1.00) * tickScale);
- barT = yApexPoint + barHeight;
- pDC->Rectangle(tickXLocation - 40, barT, tickXLocation + 40, barB);
- //box (interquartile range, from upper quartile to lower quartile)
- barHeight = (int)(upperQuartile * tickScale);
- barT = yApexPoint + barHeight;
- barHeight = (int)(lowerQuartile * tickScale);
- barB = yApexPoint + barHeight;
- pDC->Rectangle(barL, barT, barR, barB);
- //draw median line (in RED)
- CPen* pOldPen;
- CPen linePen (PS_SOLID, 1, RED);
- pOldPen = pDC->SelectObject(&linePen);
- barHeight = (int)((median * 1.00) * tickScale);
- pDC->MoveTo(barL, yApexPoint + barHeight);
- pDC->LineTo(barR, yApexPoint + barHeight);
- pDC->SelectObject(pOldPen);
- }
- else
- {
- seriesSpace = yAxisHeight / graphSeries->GetCount();
- barHeight = (int)(seriesSpace * .8);
- double tickScale = 0.00;
- tickScale = (xAxisWidth - 200) / numTicks; //same as PrintAxis()
- tickYLocation = yApexPoint + ((x * seriesSpace) - (seriesSpace / 2));
- barT = tickYLocation + (barHeight / 2);
- barB = barT - barHeight;
- double dataScale = 0.00;
- dataScale = ((xAxisWidth - 60) * 1.00) / (maxTick - minTick);
- //top cross bar (max value)
- barWidth = (int)((highValue * 1.00) * tickScale);
- barR = xApexPoint + barWidth;
- barL = barR - 60;
- pDC->Rectangle(barL, barT, barR, barB);
- //bottom cross bar (min value)
- barWidth = (int)((lowValue * 1.00) * tickScale);
- barR = xApexPoint + barWidth;
- barL = barR + 60;
- pDC->Rectangle(barL, barT, barR, barB);
- //vertical line (whisker)
- barWidth = (int)((highValue * 1.00) * tickScale);
- barR = xApexPoint + barWidth;
- pDC->Rectangle(barL, tickYLocation + 40, barR, tickYLocation - 40);
- //box (interquartile range, from upper quartile to lower quartile)
- barWidth = (int)(upperQuartile * tickScale);
- barL = xApexPoint + barWidth;
- barWidth = (int)(lowerQuartile * tickScale);
- barR = xApexPoint + barWidth;
- pDC->Rectangle(barL, barT, barR, barB);
- //draw median line (in RED)
- CPen* pOldPen;
- CPen linePen (PS_SOLID, 1, RED);
- pOldPen = pDC->SelectObject(&linePen);
- barWidth = (int)((median * 1.00) * tickScale);
- pDC->MoveTo(xApexPoint + barWidth, barT);
- pDC->LineTo(xApexPoint + barWidth, barB);
- pDC->SelectObject(pOldPen);
- }
- }
- pDC->SelectObject(pOldBrush);
- }
- void CGraph::PrintStackedBarSeries(CDC* pDC)
- {
- int barWidth;
- int barL, barT, barR, barB;
- int tickXLocation, tickYLocation;
- int seriesSpace;
- int barHeight; //for scalability
- POSITION pos;
- CGraphSeries* tmpSeries;
- if(graphAlignment)
- {
- //determine width of barchart data blocks
- seriesSpace = xAxisWidth / graphSeries->GetCount();
- barWidth = (int)(seriesSpace * .6);
- pos = graphSeries->GetHeadPosition();
- double dataScale = 0.00;
- dataScale = ((yAxisHeight - 100) * 1.00) / (maxTick - minTick);
- for(int x = 1; x <= graphSeries->GetCount(); x++)
- {
- tmpSeries = (CGraphSeries*)graphSeries->GetNext(pos);
- tickXLocation = xApexPoint + ((x * seriesSpace) - (seriesSpace / 2));
- barT = yApexPoint; //this is a running total;
- //it starts at yApexPoint so barB can
- //start there, then moves up by barHeight
- for(int s = 0; s < seriesSize; s++)
- {
- if(tmpSeries->GetData(s) > -1)
- {
- barHeight = (int)(((tmpSeries->GetData(s) - minTick) * 1.00) * dataScale);
- if(((tmpSeries->GetData(s) - minTick) > 0) && (barHeight < 1))
- barHeight = (int)dataScale;
- barB = barT;
- barL = tickXLocation - (barWidth / 2);
- if(barHeight > yAxisHeight)
- barT = barB + yAxisHeight;
- else
- barT = barB + barHeight;
- barR = barL + barWidth;
- COLORREF barColor;
- barColor = GetColor(s);
- CBrush brush (barColor);
- CBrush* pOldBrush;
- pOldBrush = pDC->SelectObject(&brush);
- pDC->Rectangle(barL, barT, barR, barB);
- pDC->SelectObject(pOldBrush);
- }
- }
- }
- }
- else
- {
- //determine width of barchart data blocks
- seriesSpace = yAxisHeight / graphSeries->GetCount();
- barHeight = (int)(seriesSpace * .6);
- pos = graphSeries->GetHeadPosition();
- double dataScale = 0.00;
- dataScale = ((xAxisWidth - 100) * 1.00) / (maxTick - minTick);
- for(int y = 1; y <= graphSeries->GetCount(); y++)
- {
- tmpSeries = (CGraphSeries*)graphSeries->GetNext(pos);
- tickYLocation = yApexPoint + ((y * seriesSpace) - (seriesSpace / 2));
- barR = xApexPoint; //this is a running total;
- //it starts at xApexPoint so barL can
- //start there, then moves right by barWidth
- for(int s = 0; s < seriesSize; s++)
- {
- if(tmpSeries->GetData(s) > -1)
- {
- barWidth = (int)(((tmpSeries->GetData(s) - minTick) * 1.00) * dataScale);
- if(((tmpSeries->GetData(s) - minTick) > 0) && (barWidth < 1))
- barWidth = (int)dataScale;
- barL = barR;
- barT = tickYLocation + (barHeight / 2);
- barB = barT - barHeight;
- if(barWidth > xAxisWidth)
- barR = barL + xAxisWidth;
- else
- barR = barL + barWidth;
- COLORREF barColor;
- barColor = GetColor(s);
- CBrush brush (barColor);
- CBrush* pOldBrush;
- pOldBrush = pDC->SelectObject(&brush);
- pDC->Rectangle(barL, barT, barR, barB);
- pDC->SelectObject(pOldBrush);
- }
- }
- }
- }
- }
- void CGraph::PrintXYLineSeries(CDC* pDC)
- {
- //same as Line graph, but without dots at the values
- int barWidth;
- int dataPlotSize; //used to plot rects of data
- int tickXLocation, tickYLocation;
- int seriesSpace;
- int barHeight; //for scalability
- POSITION pos;
- CGraphSeries* tmpSeries;
- int lastXLoc, lastYLoc;
- if(graphAlignment)
- {
- for(int s = 0; s < seriesSize; s++)
- {
- //determine width of barchart data blocks
- seriesSpace = xAxisWidth / graphSeries->GetCount();
- barWidth = (int)((seriesSpace * .6) / seriesSize);
- dataPlotSize = seriesSize * barWidth;
- pos = graphSeries->GetHeadPosition();
- for(int x = 1; x <= graphSeries->GetCount(); x++)
- {
- tmpSeries = (CGraphSeries*)graphSeries->GetNext(pos);
- if(tmpSeries->GetData(s) > -1)
- {
- tickXLocation = xApexPoint + ((x * seriesSpace) - (seriesSpace / 2));
- barHeight = 0;
- double dataScale = 0.00;
- if((maxTick - minTick) != yAxisHeight)
- dataScale = ((yAxisHeight * 1.00) / ((maxTick - minTick) * 1.00)) * tickSpace;
- else dataScale = tickSpace * 15.00;
- int axisHeight = (int)(dataScale * numTicks);
- double barPercent = 0.00;
- barPercent = ((tmpSeries->GetData(s) - minTick) * 1.00) / maxTick;
- barHeight = (int)(barPercent * axisHeight);
- if(((tmpSeries->GetData(s) - minTick) > 0) && (barHeight < 1))
- barHeight = (int)dataScale;
- int yDataLocation = yApexPoint + barHeight;
- //now have x and y location of center of ellipse
- COLORREF barColor;
- barColor = GetColor(s);
- CBrush brush (barColor);
- CBrush* pOldBrush;
- pOldBrush = pDC->SelectObject(&brush);
- //draw line back to last data member
- if(x > 1)
- {
- CPen* pOldPen;
- CPen linePen (PS_SOLID, 40, barColor);
- pOldPen = pDC->SelectObject(&linePen);
- pDC->MoveTo(lastXLoc, lastYLoc);
- pDC->LineTo(tickXLocation, yDataLocation);
- pDC->SelectObject(pOldPen);
- }
- lastXLoc = tickXLocation;
- lastYLoc = yDataLocation;
- pDC->SelectObject(pOldBrush);
- }
- }
- }
- }
- else
- {
- for(int s = 0; s < seriesSize; s++)
- {
- //determine width of barchart data blocks
- seriesSpace = yAxisHeight / graphSeries->GetCount();
- barHeight = (int)((seriesSpace * .6) / seriesSize);
- dataPlotSize = seriesSize * barHeight;
- pos = graphSeries->GetHeadPosition();
- for(int x = 1; x <= graphSeries->GetCount(); x++)
- {
- tmpSeries = (CGraphSeries*)graphSeries->GetNext(pos);
- if(tmpSeries->GetData(s) > -1)
- {
- tickYLocation = yApexPoint + ((x * seriesSpace) - (seriesSpace / 2));
- barWidth = 0;
- double dataScale = 0.00;
- dataScale = ((xAxisWidth - 100) * 1.00) / (maxTick - minTick);
- int axisWidth = (int)(dataScale * (maxTick - minTick));
- double barPercent = 0.00;
- barPercent = ((tmpSeries->GetData(s) - minTick) * 1.00) / ((maxTick - minTick) * 1.00);
- barWidth = (int)(barPercent * axisWidth);
- if(((tmpSeries->GetData(s) - minTick) > 0) && (barHeight < 1))
- barWidth = (int)dataScale;
- int xDataLocation = xApexPoint + barWidth;
- //now have x and y location of center of ellipse
- COLORREF barColor;
- barColor = GetColor(s);
- CBrush brush (barColor);
- CBrush* pOldBrush;
- pOldBrush = pDC->SelectObject(&brush);
- //draw line back to last data member
- if(x > 1)
- {
- CPen* pOldPen;
- CPen linePen (PS_SOLID, 40, barColor);
- pOldPen = pDC->SelectObject(&linePen);
- pDC->MoveTo(lastXLoc, lastYLoc);
- pDC->LineTo(xDataLocation, tickYLocation);
- pDC->SelectObject(pOldPen);
- }
- //now draw ellipse...
- lastYLoc = tickYLocation;
- lastXLoc = xDataLocation;
- pDC->SelectObject(pOldBrush);
- }
- }
- }
- }
- }
- //void CGraph::PrintRadarSeries(CDC* pDC)
- //{
- //}
- void CGraph::Print3DBarSeries(CDC* pDC)
- {
- int barWidth;
- int dataPlotSize; //used to plot rects of data
- int barL, barT, barR, barB;
- int tickXLocation, tickYLocation;
- int seriesSpace;
- int barHeight;
- POSITION pos;
- CGraphSeries* tmpSeries;
- int blue;
- int red;
- int green;
- if(graphAlignment)
- {
- //determine width of barchart data blocks
- seriesSpace = (xAxisWidth - 100) / graphSeries->GetCount();
- barWidth = (int)((seriesSpace * .8) / seriesSize);
- dataPlotSize = seriesSize * barWidth;
- pos = graphSeries->GetHeadPosition();
- for(int x = 1; x <= graphSeries->GetCount(); x++)
- {
- tmpSeries = (CGraphSeries*)graphSeries->GetNext(pos);
- tickXLocation = xApexPoint + ((x * seriesSpace) - (seriesSpace / 2));
- for(int s = 0; s < seriesSize; s++)
- {
- if(tmpSeries->GetData(s) > -1)
- {
- double dataScale = 0.00;
- dataScale = (yAxisHeight * 1.00) / (maxTick - minTick);
- int dScale;
- dScale = (int)dataScale;
- barHeight = (int)(((tmpSeries->GetData(s) - minTick) * 1.00) * dScale);
- if(((tmpSeries->GetData(s) - minTick) > 0) && (barHeight < 1))
- barHeight = 1 * dScale;
- barL = tickXLocation - (dataPlotSize / 2) + (s * barWidth);
- if(barHeight > yAxisHeight)
- barT = yApexPoint + yAxisHeight;
- else
- barT = yApexPoint + barHeight;
- barR = barL + barWidth;
- barB = yApexPoint;
- COLORREF barColor;
- barColor = GetColor(s);
- CBrush brush (barColor);
- CPen rectPen (PS_SOLID, 1, barColor);
- CPen* pOldPen;
- pOldPen = pDC->SelectObject(&rectPen);
- CBrush* pOldBrush;
- pOldBrush = pDC->SelectObject(&brush);
- pDC->Rectangle(barL, barT, barR, barB);
- //now, we do the side
- //side is darker than front, so subtract
- //from color to make closer to black
- red = GetRValue(barColor);
- green = GetGValue(barColor);
- blue = GetBValue(barColor);
- int sideRed = red - 35;
- int sideGreen = green - 35;
- int sideBlue = blue - 35;
- if(sideRed < 0) sideRed = 0;
- if(sideGreen < 0) sideGreen = 0;
- if(sideBlue < 0) sideBlue = 0;
- COLORREF sideColor;
- sideColor = RGB(sideRed, sideGreen, sideBlue);
- CBrush sideBrush (sideColor);
- CPen sidePen (PS_SOLID, 1, sideColor);
- pDC->SelectObject(&sideBrush);
- pDC->SelectObject(&sidePen);
- CPoint sidePolyArray[4];
- CPoint sp1(barR, barT);
- CPoint sp2(barR, barB);
- CPoint sp3(barR + depth, barB + depth);
- CPoint sp4(barR + depth, barT + depth);
- sidePolyArray[0] = sp1;
- sidePolyArray[1] = sp2;
- sidePolyArray[2] = sp3;
- sidePolyArray[3] = sp4;
- pDC->Polygon(sidePolyArray, 4);
- //finally, the top
- int topRed = red + 35;
- int topGreen = green + 35;
- int topBlue = blue + 35;
- if(topRed > 255) topRed = 255;
- if(topGreen > 255) topGreen = 255;
- if(topBlue > 255) topBlue = 255;
- COLORREF topColor;
- topColor = RGB(topRed, topGreen, topBlue);
- CBrush topBrush (topColor);
- CPen topPen (PS_SOLID, 1, topColor);
- pDC->SelectObject(&topBrush);
- pDC->SelectObject(&topPen);
- CPoint topPolyArray[4];
- CPoint tp1(barL, barT);
- CPoint tp2(barR, barT);
- CPoint tp3(barR + depth, barT + depth);
- CPoint tp4(barL + depth, barT + depth);
- topPolyArray[0] = tp1;
- topPolyArray[1] = tp2;
- topPolyArray[2] = tp3;
- topPolyArray[3] = tp4;
- pDC->Polygon(topPolyArray, 4);
- pDC->SelectObject(pOldBrush);
- pDC->SelectObject(pOldPen);
- }
- }
- }
- }
- else
- {
- //determine width of barchart data blocks
- seriesSpace = yAxisHeight / graphSeries->GetCount();
- barHeight = (int)((seriesSpace * .8) / seriesSize);
- dataPlotSize = seriesSize * barHeight;
- pos = graphSeries->GetHeadPosition();
- for(int y = 1; y <= graphSeries->GetCount(); y++)
- {
- tmpSeries = (CGraphSeries*)graphSeries->GetNext(pos);
- tickYLocation = yApexPoint + ((y * seriesSpace) - (seriesSpace / 2));
- for(int s = 0; s < seriesSize; s++)
- {
- if(tmpSeries->GetData(s) > -1)
- {
- double dataScale = 0.00;
- dataScale = ((xAxisWidth - 200) * 1.00) / (maxTick - minTick);
- barWidth = (int)(((tmpSeries->GetData(s) - minTick) * 1.00) * dataScale);
- if(((tmpSeries->GetData(s) - minTick) > 0) && (barWidth < 1))
- barWidth = (int)dataScale;
- barL = xApexPoint;
- barB = tickYLocation - (dataPlotSize / 2) + (s * barHeight);
- barT = barB + barHeight;
- if(barWidth > xAxisWidth)
- barR = xApexPoint + xAxisWidth;
- else
- barR = xApexPoint + barWidth;
- COLORREF barColor;
- barColor = GetColor(s);
- CBrush brush (barColor);
- CBrush* pOldBrush;
- pOldBrush = pDC->SelectObject(&brush);
- CPen rectPen (PS_SOLID, 1, barColor);
- CPen* pOldPen;
- pOldPen = pDC->SelectObject(&rectPen);
- pDC->Rectangle(barL, barT, barR, barB);
- //now, we do the side
- //side is darker than front, so subtract
- //from color to make closer to black
- red = GetRValue(barColor);
- green = GetGValue(barColor);
- blue = GetBValue(barColor);
- int sideRed = red - 35;
- int sideGreen = green - 35;
- int sideBlue = blue - 35;
- if(sideRed < 0) sideRed = 0;
- if(sideGreen < 0) sideGreen = 0;
- if(sideBlue < 0) sideBlue = 0;
- COLORREF sideColor;
- sideColor = RGB(sideRed, sideGreen, sideBlue);
- CBrush sideBrush (sideColor);
- CPen sidePen (PS_SOLID, 1, sideColor);
- pDC->SelectObject(&sideBrush);
- pDC->SelectObject(&sidePen);
- CPoint sidePolyArray[4];
- CPoint sp1(barL, barT);
- CPoint sp2(barR, barT);
- //I'm subtracting below to shorten the width of the
- //bar, since it was showing farther right than actual value
- CPoint sp3(barR + depth - (seriesSize - s), barT + depth);
- CPoint sp4(barL + depth - (seriesSize - s), barT + depth);
- sidePolyArray[0] = sp1;
- sidePolyArray[1] = sp2;
- sidePolyArray[2] = sp3;
- sidePolyArray[3] = sp4;
- pDC->Polygon(sidePolyArray, 4);
- //finally, the top
- int topRed = red + 35;
- int topGreen = green + 35;
- int topBlue = blue + 35;
- if(topRed > 255) topRed = 255;
- if(topGreen > 255) topGreen = 255;
- if(topBlue > 255) topBlue = 255;
- COLORREF topColor;
- topColor = RGB(topRed, topGreen, topBlue);
- CBrush topBrush (topColor);
- CPen topPen (PS_SOLID, 1, topColor);
- pDC->SelectObject(&topBrush);
- pDC->SelectObject(&topPen);
- CPoint topPolyArray[4];
- CPoint tp1(barR, barT);
- CPoint tp2(barR, barB);
- //I'm subtracting below to shorten the width of the
- //bar, since it was showing farther right than actual value
- CPoint tp3(barR + depth - (seriesSize - s), barB + depth);
- CPoint tp4(barR + depth - (seriesSize - s), barT + depth);
- topPolyArray[0] = tp1;
- topPolyArray[1] = tp2;
- topPolyArray[2] = tp3;
- topPolyArray[3] = tp4;
- pDC->Polygon(topPolyArray, 4);
- pDC->SelectObject(pOldBrush);
- pDC->SelectObject(pOldPen);
- }
- }
- }
- }
- }
- void CGraph::Print3DLineSeries(CDC* pDC)
- {
- int barWidth;
- int dataPlotSize; //used to plot rects of data
- int tickXLocation, tickYLocation;
- int seriesSpace;
- int barHeight;
- POSITION pos;
- CGraphSeries* tmpSeries;
- int thick;
- int blue;
- int red;
- int green;
- CBrush* pOldBrush;
- CPen* pOldPen;
- thick = depth / 5;
- int lastXLoc, lastYLoc;
- if(graphAlignment)
- {
- for(int s = 0; s < seriesSize; s++)
- {
- //determine width of barchart data blocks
- seriesSpace = (xAxisWidth - 100) / graphSeries->GetCount();
- pos = graphSeries->GetHeadPosition();
- int yDataLocation;
- for(int x = 1; x <= graphSeries->GetCount(); x++)
- {
- tickXLocation = xApexPoint + ((x * seriesSpace) - (seriesSpace / 2));
- tmpSeries = (CGraphSeries*)graphSeries->GetNext(pos);
- if(tmpSeries->GetData(s) > -1)
- {
- double dataScale = 0.00;
- dataScale = (yAxisHeight * 1.00) / (maxTick - minTick);
- int dScale;
- dScale = (int)dataScale;
- barHeight = (int)(((tmpSeries->GetData(s) - minTick) * 1.00) * dScale);
- if(((tmpSeries->GetData(s) - minTick) > 0) && (barHeight < 1))
- barHeight = 1 * dScale;
- yDataLocation = yApexPoint + barHeight;
- //now have x and y location of center of ellipse
- COLORREF barColor;
- barColor = GetColor(s);
- red = GetRValue(barColor);
- green = GetGValue(barColor);
- blue = GetBValue(barColor);
- CBrush brush (barColor);
- pOldBrush = pDC->SelectObject(&brush);
- //draw line back to last data member
- if(x > 1)
- {
- CPen linePen (PS_SOLID, 1, barColor);
- pOldPen = pDC->SelectObject(&linePen);
- //front side of line
- CPoint sidePolyArray[4];
- CPoint sp1(lastXLoc, lastYLoc);
- CPoint sp2(lastXLoc, lastYLoc - thick);
- CPoint sp3(tickXLocation, yDataLocation - thick);
- CPoint sp4(tickXLocation, yDataLocation);
- sidePolyArray[0] = sp1;
- sidePolyArray[1] = sp2;
- sidePolyArray[2] = sp3;
- sidePolyArray[3] = sp4;
- pDC->Polygon(sidePolyArray, 4);
- //top part of line, lighter than front
- int topRed = red + 35;
- int topGreen = green + 35;
- int topBlue = blue + 35;
- if(topRed > 255) topRed = 255;
- if(topGreen > 255) topGreen = 255;
- if(topBlue > 255) topBlue = 255;
- COLORREF topColor;
- topColor = RGB(topRed, topGreen, topBlue);
- CPen topPen(PS_SOLID, 1, topColor);
- CBrush topBrush(topColor);
- pDC->SelectObject(&topPen);
- pDC->SelectObject(&topBrush);
- CPoint topPolyArray[4];
- CPoint tp1(lastXLoc, lastYLoc);
- CPoint tp2(lastXLoc + depth, lastYLoc + depth);
- CPoint tp3(tickXLocation + depth, yDataLocation + depth);
- CPoint tp4(tickXLocation, yDataLocation);
- topPolyArray[0] = tp1;
- topPolyArray[1] = tp2;
- topPolyArray[2] = tp3;
- topPolyArray[3] = tp4;
- pDC->Polygon(topPolyArray, 4);
- pDC->SelectObject(pOldBrush);
- pDC->SelectObject(pOldPen);
- }
- lastXLoc = tickXLocation;
- lastYLoc = yDataLocation;
- }
- }
- if(x > 1)
- {
- //end point of line
- int endRed = red - 35;
- int endGreen = green - 35;
- int endBlue = blue - 35;
- if(endRed < 0) endRed = 0;
- if(endGreen < 0) endGreen = 0;
- if(endBlue < 0) endBlue = 0;
- COLORREF endColor;
- endColor = RGB(endRed, endGreen, endBlue);
- CPen endPen(PS_SOLID, 1, endColor);
- CBrush endBrush(endColor);
- pDC->SelectObject(&endPen);
- pDC->SelectObject(&endBrush);
- CPoint endPolyArray[4];
- CPoint ep1(tickXLocation, yDataLocation);
- CPoint ep2(tickXLocation + depth, yDataLocation + depth);
- CPoint ep3(tickXLocation + depth, yDataLocation + depth - thick);
- CPoint ep4(tickXLocation, yDataLocation + thick);
- endPolyArray[0] = ep1;
- endPolyArray[1] = ep2;
- endPolyArray[2] = ep3;
- endPolyArray[3] = ep4;
- pDC->Polygon(endPolyArray, 4);
- pDC->SelectObject(pOldBrush);
- pDC->SelectObject(pOldPen);
- }
- }
- }
- else
- {
- for(int s = 0; s < seriesSize; s++)
- {
- //determine width of barchart data blocks
- seriesSpace = yAxisHeight / graphSeries->GetCount();
- barHeight = (int)((seriesSpace * .6) / seriesSize);
- dataPlotSize = seriesSize * barHeight;
- pos = graphSeries->GetHeadPosition();
- int xDataLocation;
- for(int x = 1; x <= graphSeries->GetCount(); x++)
- {
- tickYLocation = yApexPoint + ((x * seriesSpace) - (seriesSpace / 2));
- tmpSeries = (CGraphSeries*)graphSeries->GetNext(pos);
- if(tmpSeries->GetData(s) > -1)
- {
- double dataScale = 0.00;
- dataScale = ((xAxisWidth - 200) * 1.00) / (maxTick - minTick);
- barWidth = (int)(((tmpSeries->GetData(s) - minTick) * 1.00) * dataScale);
- if(((tmpSeries->GetData(s) - minTick) > 0) && (barWidth < 1))
- barWidth = (int)dataScale;
- xDataLocation = xApexPoint + barWidth;
- //now have x and y location of center of ellipse
- COLORREF barColor;
- barColor = GetColor(s);
- red = GetRValue(barColor);
- green = GetGValue(barColor);
- blue = GetBValue(barColor);
- CBrush brush (barColor);
- pOldBrush = pDC->SelectObject(&brush);
- //draw line back to last data member
- if(x > 1)
- {
- CPen linePen (PS_SOLID, 1, barColor);
- pOldPen = pDC->SelectObject(&linePen);
- //front side of line
- CPoint sidePolyArray[4];
- CPoint sp1(lastXLoc, lastYLoc);
- CPoint sp2(lastXLoc - thick, lastYLoc);
- CPoint sp3(xDataLocation - thick, tickYLocation);
- CPoint sp4(xDataLocation, tickYLocation);
- sidePolyArray[0] = sp1;
- sidePolyArray[1] = sp2;
- sidePolyArray[2] = sp3;
- sidePolyArray[3] = sp4;
- pDC->Polygon(sidePolyArray, 4);
- //top part of line, lighter than front
- int topRed = red + 35;
- int topGreen = green + 35;
- int topBlue = blue + 35;
- if(topRed > 255) topRed = 255;
- if(topGreen > 255) topGreen = 255;
- if(topBlue > 255) topBlue = 255;
- COLORREF topColor;
- topColor = RGB(topRed, topGreen, topBlue);
- CPen topPen(PS_SOLID, 1, topColor);
- CBrush topBrush(topColor);
- pDC->SelectObject(&topPen);
- pDC->SelectObject(&topBrush);
- CPoint topPolyArray[4];
- CPoint tp1(lastXLoc, lastYLoc);
- CPoint tp2(lastXLoc + depth, lastYLoc + thick);
- CPoint tp3(xDataLocation + depth, tickYLocation + thick);
- CPoint tp4(xDataLocation, tickYLocation);
- topPolyArray[0] = tp1;
- topPolyArray[1] = tp2;
- topPolyArray[2] = tp3;
- topPolyArray[3] = tp4;
- pDC->Polygon(topPolyArray, 4);
- pDC->SelectObject(pOldBrush);
- pDC->SelectObject(pOldPen);
- }
- lastYLoc = tickYLocation;
- lastXLoc = xDataLocation;
- }
- }
- if(x > 1)
- {
- //end point of line
- int endRed = red - 35;
- int endGreen = green - 35;
- int endBlue = blue - 35;
- if(endRed < 0) endRed = 0;
- if(endGreen < 0) endGreen = 0;
- if(endBlue < 0) endBlue = 0;
- COLORREF endColor;
- endColor = RGB(endRed, endGreen, endBlue);
- CPen endPen(PS_SOLID, 1, endColor);
- CBrush endBrush(endColor);
- pDC->SelectObject(&endPen);
- pDC->SelectObject(&endBrush);
- CPoint endPolyArray[4];
- CPoint ep1(xDataLocation, tickYLocation);
- CPoint ep2(xDataLocation + depth, tickYLocation + thick);
- CPoint ep3(xDataLocation + depth - thick, tickYLocation + thick);
- CPoint ep4(xDataLocation - thick, tickYLocation);
- endPolyArray[0] = ep1;
- endPolyArray[1] = ep2;
- endPolyArray[2] = ep3;
- endPolyArray[3] = ep4;
- pDC->Polygon(endPolyArray, 4);
- pDC->SelectObject(pOldBrush);
- pDC->SelectObject(pOldPen);
- }
- }
- }
- }
- void CGraph::Print3DPieSeries(CDC* pDC)
- {
- double dataSum = 0.00; //for storing cumulative sum
- double labelData = 0.00;
- int lastXLocation, lastYLocation;
- int newXLocation, newYLocation;
- int labelXLocation, labelYLocation;
- double percent = 0.00;
- double labelPercent = 0.00;
- int degrees;
- int labelDegrees;
- double totalSum = 0.00;
- int radius;
- POSITION pos;
- CGraphSeries* tmpSeries;
- int seriesSpace;
- int labelLineXStart, labelLineYStart;
- int labelLineXEnd, labelLineYEnd;
- int maxLabelWidth;
- int maxLabelHeight;
- TEXTMETRIC tm;
- CPen* pOldPen;
- CBrush* pOldBrush;
- CPen tmpPen(PS_SOLID, 1, BLACK);
- CBrush tmpBrush(WHITE);
- pOldPen = pDC->SelectObject(&tmpPen);
- pOldBrush = pDC->SelectObject(&tmpBrush);
- //deltaX and deltaY will be based on distance from x and y
- //axis for the new endpoint of the pie. These values can
- //then be used to find the true distance between starting
- //line and ending line of pie boundary.
- double deltaX, deltaY;
- double degreeRadians, degreeRadians2;
- double labelDeltaX, labelDeltaY;
- double labelDegreeRadians, labelDegreeRadians2;
- lastXLocation = 0;
- lastYLocation = 0;
- pDC->GetTextMetrics(&tm);
- maxLabelWidth = tm.tmMaxCharWidth + 10;
- maxLabelHeight = tm.tmHeight + 6;
- //pie labels will be stored in a list and drawn after entire pie
- //is completed.
- CObList *pieLabels;
- CGraphPieLabel *pieLabel;
- //determine width of pie display area
- if(xAxisWidth > yAxisHeight)
- seriesSpace = yAxisHeight / graphSeries->GetCount();
- else
- seriesSpace = xAxisWidth / graphSeries->GetCount();
- seriesSpace -= (3 * maxLabelWidth); //allows text like 25% (3 chars)
- //to plot a pie plus labels inside of series space, use the following :
- //(3 * radius) + (2 * label width) = series space
- //so, 3*radius = series space - (2 * label width)
- // 1 radius = (series space - (2 * label width)) / 3
- radius = seriesSpace / 3; //pie needs 2 radius, + 1 extra for line to labels = 3 for my divisor
- int depth = (int)(radius * depthRatio); //for shadow pie
- int centerYPie = pGraphT - (yAxisHeight / 2) - 500 - depth;
- pos = graphSeries->GetHeadPosition();
- for(int x = 1; x <= graphSeries->GetCount(); x++)
- {
- pDC->SelectObject(pOldBrush);
- pDC->SelectObject(pOldPen);
- pieLabels = new CObList();
- tmpSeries = (CGraphSeries*)graphSeries->GetNext(pos);
- totalSum = 0;
- for(int s = 0; s < seriesSize; s++)
- totalSum += tmpSeries->GetData(s);
- int pieLeft, pieRight;
- if(graphSeries->GetCount() == 1)
- {
- pieLeft = xApexPoint + (xAxisWidth / 2) - radius;
- }
- else
- {
- pieLeft = xApexPoint + 15 + ((x * 2 - 1) * ((xAxisWidth / graphSeries->GetCount()) / 2)) - radius;
- }
- pieRight = pieLeft + (2 * radius);
- CRect pieRect (pieLeft,
- centerYPie + radius,
- pieRight,
- centerYPie - radius);
- CRect shadowRect (pieLeft + depth,
- centerYPie + radius - depth,
- pieRight + depth,
- centerYPie - radius - depth);
- int centerXPie = pieLeft + radius;
- //plot series label
- pDC->TextOut(centerXPie - ((tmpSeries->GetLabel().GetLength() / 2) * ((xTickFontSize / 2) * 20)),
- centerYPie - radius - maxLabelHeight - 600 - depth, tmpSeries->GetLabel());
- int centerShadowXPie;
- int centerShadowYPie;
- //draw shadow pie first
- centerShadowYPie = centerYPie - depth;
- centerShadowXPie = centerXPie + depth;
- lastXLocation = centerShadowXPie - radius;
- lastYLocation = centerShadowYPie;
- int lastTopX = centerXPie - radius;
- int lastTopY = centerYPie;
- int newTopX, newTopY;
- dataSum = 0;
- int lastQuad = 0;
- CPoint lastSidePolyArray[4];
- COLORREF lastColor;
- CPoint spa1;
- CPoint spa2;
- CPoint spa3;
- CPoint spa4;
- for(s = 0; s < seriesSize; s++)
- {
- if(tmpSeries->GetData(s) > 0)
- {
- int seriesDataValue;
- seriesDataValue = tmpSeries->GetData(s);
- dataSum += seriesDataValue;
- percent = (dataSum / totalSum) * 100;
- degrees = (int)((360 * percent) / 100);
- //determine destination quadrant...
- //and set newXLocation and newYLocation values...
- //degrees / 90 will never exceed 4.
- //this can tell us the quadrant of destination
- int quadrant = degrees / 90; //truncates decimal
- //using the law of sines to determine the deltas :
- //deltaX = radius * sin(90 - degrees)
- //deltaY = radius * sin(degrees)
- //we convert degrees into radians so sin() function works right
- //note : in quad 1 and 3, we reverse the angle used to compute
- // the deltas, since the triangle plots reversed.
- switch(quadrant)
- {
- case 0 : //this is the base quadrant, so no manipulation needed
- degreeRadians = degrees * (3.14159 / 180);
- degreeRadians2 = (90 - degrees) * (3.14159 / 180);
- deltaX = radius * sin(degreeRadians2);
- deltaY = radius * sin(degreeRadians);
- newXLocation = (int)(centerShadowXPie - deltaX);
- newYLocation = (int)(centerShadowYPie - deltaY);
- newTopX = (int)(centerXPie - deltaX);
- newTopY = (int)(centerYPie - deltaY);
- break;
- case 1 : //bottom right quadrant, subtract 90 from angle
- degreeRadians = (degrees - 90) * (3.14159 / 180);
- degreeRadians2 = (90 - (degrees - 90)) * (3.14159 / 180);
- deltaX = radius * sin(degreeRadians);
- deltaY = radius * sin(degreeRadians2);
- newXLocation = (int)(centerShadowXPie + deltaX);
- newYLocation = (int)(centerShadowYPie - deltaY);
- newTopX = (int)(centerXPie + deltaX);
- newTopY = (int)(centerYPie - deltaY);
- break;
- case 2 : //top right quadrant, subtract 180 from angle
- degreeRadians = (degrees - 180) * (3.14159 / 180);
- degreeRadians2 = (90 - (degrees - 180)) * (3.14159 / 180);
- deltaX = radius * sin(degreeRadians2);
- deltaY = radius * sin(degreeRadians);
- newXLocation = (int)(centerShadowXPie + deltaX);
- newYLocation = (int)(centerShadowYPie + deltaY);
- newTopX = (int)(centerXPie + deltaX);
- newTopY = (int)(centerYPie + deltaY);
- break;
- case 3 : //upper left quadrant, subtract 270 from angle
- degreeRadians = (degrees - 270) * (3.14159 / 180);
- degreeRadians2 = (90 - (degrees - 270)) * (3.14159 / 180);
- deltaX = radius * sin(degreeRadians);
- deltaY = radius * sin(degreeRadians2);
- newXLocation = (int)(centerShadowXPie - deltaX);
- newYLocation = (int)(centerShadowYPie + deltaY);
- newTopX = (int)(centerXPie - deltaX);
- newTopY = (int)(centerYPie + deltaY);
- break;
- case 4 : //straight line to left of center
- deltaX = radius;
- deltaY = 1;
- newXLocation = (int)(centerShadowXPie - deltaX);
- newYLocation = (int)(centerShadowYPie + deltaY);
- newTopX = (int)(centerXPie - deltaX);
- newTopY = (int)(centerYPie + deltaY);
- break;
- }
- if(s == 0)
- {
- lastYLocation += 1;
- lastTopY += 1;
- }
- COLORREF barColor;
- barColor = GetColor(s);
- int red, green, blue;
- red = GetRValue(barColor) - 35;
- green = GetGValue(barColor) - 35;
- blue = GetBValue(barColor) - 35;
- if(red < 0) red = 0;
- if(green < 0) green = 0;
- if(blue < 0) blue = 0;
- CPoint sp1 (lastXLocation, lastYLocation);
- CPoint sp2 (newXLocation, newYLocation);
- COLORREF shadowColor(RGB(red, green, blue));
- CPen shadowPen (PS_SOLID, 1, shadowColor);
- CBrush shadowBrush(shadowColor);
- pDC->SelectObject(&shadowPen);
- pDC->SelectObject(&shadowBrush);
- if((quadrant < 2) || (lastQuad < 2))
- {
- CPoint sidePolyArray[4];
- spa1.x = lastXLocation;
- spa1.y = lastYLocation;
- spa2.x = newXLocation;
- spa2.y = newYLocation;
- spa3.x = newTopX;
- spa3.y = newTopY;
- spa4.x = lastTopX;
- spa4.y = lastTopY;
- sidePolyArray[0] = spa1;
- sidePolyArray[1] = spa2;
- sidePolyArray[2] = spa3;
- sidePolyArray[3] = spa4;
- pDC->Polygon(sidePolyArray, 4);
- pDC->Pie(shadowRect, sp1, sp2);
- }
- else
- {
- CPoint sidePolyArray[3];
- spa1.x = newXLocation;
- spa1.y = newYLocation;
- spa2.x = newTopX;
- spa2.y = newTopY;
- spa3.x = lastTopX;
- spa3.y = lastTopY;
- sidePolyArray[0] = spa1;
- sidePolyArray[1] = spa2;
- sidePolyArray[2] = spa3;
- CPen oldShadowPen (PS_SOLID, 1, lastColor);
- pDC->SelectObject(&oldShadowPen);
- CBrush oldShadowBrush(lastColor);
- pDC->SelectObject(&oldShadowBrush);
- pDC->Pie(shadowRect, sp1, sp2);
- pDC->Polygon(sidePolyArray, 3);
- pDC->SelectObject(&shadowPen);
- pDC->SelectObject(&shadowBrush);
- }
- lastXLocation = newXLocation;
- lastYLocation = newYLocation;
- lastTopX = newTopX;
- lastTopY = newTopY;
- if((quadrant > 1) && (lastQuad < 2))
- {
- lastSidePolyArray[0] = spa1;
- lastSidePolyArray[1] = spa2;
- lastSidePolyArray[2] = spa3;
- lastSidePolyArray[3] = spa4;
- lastColor = shadowColor;
- }
- lastQuad = quadrant;
- pDC->SelectObject(pOldBrush);
- pDC->SelectObject(pOldPen);
- }
- }
- //draw normal pie
- lastXLocation = pieLeft;
- lastYLocation = centerYPie;
- dataSum = 0;
- for(s = 0; s < seriesSize; s++)
- {
- if(tmpSeries->GetData(s) > 0)
- {
- int seriesDataValue;
- seriesDataValue = tmpSeries->GetData(s);
- labelData = seriesDataValue / 2;
- dataSum += seriesDataValue;
- percent = (dataSum / totalSum) * 100;
- labelPercent = ((dataSum - labelData) / totalSum) * 100;
- degrees = (int)((360 * percent) / 100);
- labelDegrees = (int)((360 * labelPercent) / 100);
- //determine destination quadrant...
- //and set newXLocation and newYLocation values...
- //degress / 90 will never exceed 4.
- //this can tell us the quadrant of destination
- int quadrant = degrees / 90; //truncates decimal
- int labelQuadrant = labelDegrees / 90;
- //using the law of sines to determine the deltas :
- //deltaX = radius * sin(90 - degrees)
- //deltaY = radius * sin(degrees)
- //we convert degrees into radians so sin() function works right
- //note : in quad 1 and 3, we reverse the angle used to compute
- // the deltas, since the triangle plots reversed.
- switch(quadrant)
- {
- case 0 : //this is the base quadrant, so no manipulation needed
- degreeRadians = degrees * (3.14159 / 180);
- degreeRadians2 = (90 - degrees) * (3.14159 / 180);
- deltaX = radius * sin(degreeRadians2);
- deltaY = radius * sin(degreeRadians);
- newXLocation = (int)(centerXPie - deltaX);
- newYLocation = (int)(centerYPie - deltaY);
- break;
- case 1 : //bottom right quadrant, subtract 90 from angle
- degreeRadians = (degrees - 90) * (3.14159 / 180);
- degreeRadians2 = (90 - (degrees - 90)) * (3.14159 / 180);
- deltaX = radius * sin(degreeRadians);
- deltaY = radius * sin(degreeRadians2);
- newXLocation = (int)(centerXPie + deltaX);
- newYLocation = (int)(centerYPie - deltaY);
- break;
- case 2 : //top right quadrant, subtract 180 from angle
- degreeRadians = (degrees - 180) * (3.14159 / 180);
- degreeRadians2 = (90 - (degrees - 180)) * (3.14159 / 180);
- deltaX = radius * sin(degreeRadians2);
- deltaY = radius * sin(degreeRadians);
- newXLocation = (int)(centerXPie + deltaX);
- newYLocation = (int)(centerYPie + deltaY);
- break;
- case 3 : //upper left quadrant, subtract 270 from angle
- degreeRadians = (degrees - 270) * (3.14159 / 180);
- degreeRadians2 = (90 - (degrees - 270)) * (3.14159 / 180);
- deltaX = radius * sin(degreeRadians);
- deltaY = radius * sin(degreeRadians2);
- newXLocation = (int)(centerXPie - deltaX);
- newYLocation = (int)(centerYPie + deltaY);
- break;
- case 4 : //straight line to left of center
- deltaX = radius;
- deltaY = 1;
- newXLocation = (int)(centerXPie - deltaX);
- newYLocation = (int)(centerYPie + deltaY);
- break;
- }
- switch(labelQuadrant)
- {
- //after getting X & Y location for label, we take
- //1/2 the delta between x y locations and center pie
- case 0 :
- labelDegreeRadians = labelDegrees * (3.14159 / 180);
- labelDegreeRadians2 = (90 - labelDegrees) * (3.14159 / 180);
- labelDeltaX = radius * sin(labelDegreeRadians2);
- labelDeltaY = radius * sin(labelDegreeRadians);
- labelXLocation = (int)(centerXPie - labelDeltaX);
- labelYLocation = (int)(centerYPie - labelDeltaY);
- labelLineXStart = labelXLocation + ((centerXPie - labelXLocation) / 2);
- labelLineYStart = labelYLocation - ((labelYLocation - centerYPie) / 2);
- labelLineXEnd = labelXLocation - (radius / 2);
- labelLineYEnd = labelYLocation - (radius / 2);
- break;
- case 1 :
- labelDegreeRadians = (labelDegrees - 90) * (3.14159 / 180);
- labelDegreeRadians2 = (90 - (labelDegrees - 90)) * (3.14159 / 180);
- labelDeltaX = radius * sin(labelDegreeRadians);
- labelDeltaY = radius * sin(labelDegreeRadians2);
- labelXLocation = (int)(centerXPie + labelDeltaX);
- labelYLocation = (int)(centerYPie - labelDeltaY);
- labelLineXStart = labelXLocation - ((labelXLocation - centerXPie) / 2);
- labelLineYStart = labelYLocation - ((labelYLocation - centerYPie) / 2);
- labelLineXEnd = labelXLocation + (radius / 2);
- labelLineYEnd = labelYLocation - (radius / 2);
- break;
- case 2 :
- labelDegreeRadians = (labelDegrees - 180) * (3.14159 / 180);
- labelDegreeRadians2 = (90 - (labelDegrees - 180)) * (3.14159 / 180);
- labelDeltaX = radius * sin(labelDegreeRadians2);
- labelDeltaY = radius * sin(labelDegreeRadians);
- labelXLocation = (int)(centerXPie + labelDeltaX);
- labelYLocation = (int)(centerYPie + labelDeltaY);
- labelLineXStart = labelXLocation - ((labelXLocation - centerXPie) / 2);
- labelLineYStart = labelYLocation - ((labelYLocation - centerYPie) / 2);
- labelLineXEnd = labelXLocation + (radius / 2);
- labelLineYEnd = labelYLocation + (radius / 2);
- break;
- case 3 :
- labelDegreeRadians = (labelDegrees - 270) * (3.14159 / 180);
- labelDegreeRadians2 = (90 - (labelDegrees - 270)) * (3.14159 / 180);
- labelDeltaX = radius * sin(labelDegreeRadians);
- labelDeltaY = radius * sin(labelDegreeRadians2);
- labelXLocation = (int)(centerXPie - labelDeltaX);
- labelYLocation = (int)(centerYPie + labelDeltaY);
- labelLineXStart = labelXLocation + ((centerXPie - labelXLocation) / 2);
- labelLineYStart = labelYLocation - ((labelYLocation - centerYPie) / 2);
- labelLineXEnd = labelXLocation - (radius / 2);
- labelLineYEnd = labelYLocation + (radius / 2);
- break;
- //there should never be a half point ending on 4, so leave it out
- }
- pieLabel = new CGraphPieLabel();
- pieLabel->lineXStart = labelLineXStart;
- pieLabel->lineYStart = labelLineYStart;
- pieLabel->lineXEnd = labelLineXEnd;
- pieLabel->lineYEnd = labelLineYEnd;
- switch(labelQuadrant)
- {
- case 0 : //label to left of line
- pieLabel->topLeftX = labelLineXEnd - maxLabelWidth;
- pieLabel->topLeftY = labelLineYEnd;
- break;
- case 1 : //label to right of line
- pieLabel->topLeftX = labelLineXEnd + 50;
- pieLabel->topLeftY = labelLineYEnd;
- break;
- case 2 : //label to right of line
- pieLabel->topLeftX = labelLineXEnd + 50;
- pieLabel->topLeftY = labelLineYEnd + maxLabelHeight;
- break;
- case 3 : //label to left of line
- pieLabel->topLeftX = labelLineXEnd - maxLabelWidth;
- pieLabel->topLeftY = labelLineYEnd + maxLabelHeight;
- break;
- }
- pieLabel->labelQuadrant = labelQuadrant;
- int roundPercent;
- roundPercent = (int)((seriesDataValue * 100) / totalSum);
- pieLabel->pieLabel.Format("%d%%", roundPercent);
- pieLabels->AddTail(pieLabel);
- if(s == 0)
- lastYLocation += 1;
- COLORREF barColor;
- barColor = GetColor(s);
- CPoint p1 (lastXLocation, lastYLocation);
- CPoint p2 (newXLocation, newYLocation);
- CBrush brush (barColor);
- CPen piePen (PS_SOLID, 1, barColor);
- pDC->SelectObject(&piePen);
- pDC->SelectObject(&brush);
- pDC->Pie(pieRect, p1, p2);
- lastXLocation = newXLocation;
- lastYLocation = newYLocation;
- }
- pDC->SelectObject(pOldBrush);
- pDC->SelectObject(pOldPen);
- }
- //draw lines and labels for pies slices
- POSITION labelPos;
- CBrush lineBrush (BLACK);
- CPen linePen (PS_SOLID, 1, BLACK);
- pDC->SelectObject(&lineBrush);
- pDC->SelectObject(&linePen);
- POSITION mainLinePos, checkLinePos;
- mainLinePos = pieLabels->GetHeadPosition();
- int numLinesDrawn = 0;
- CGraphPieLabel* currentLabel;
- CGraphPieLabel* tmpLabel;
- while(mainLinePos != NULL)
- {
- currentLabel = (CGraphPieLabel*)pieLabels->GetNext(mainLinePos);
- int r = 0;
- checkLinePos = pieLabels->GetHeadPosition();
- while(r < numLinesDrawn)
- {
- //check if any overlap in label areas
- tmpLabel = (CGraphPieLabel*)pieLabels->GetAt(checkLinePos);
- if((currentLabel->topLeftX > tmpLabel->topLeftX) &&
- (currentLabel->topLeftX < (tmpLabel->topLeftX - maxLabelWidth)) &&
- (currentLabel->topLeftY > tmpLabel->topLeftY) &&
- (currentLabel->topLeftY < (tmpLabel->topLeftY - maxLabelHeight)))
- {
- //OVERLAP !!!
- //move current label top left position up or down
- //depending on its quadrant
- if(currentLabel->labelQuadrant < 2)
- {
- //move label down to tmplabel topleft + height
- currentLabel->topLeftY = tmpLabel->topLeftY - maxLabelHeight;
- currentLabel->lineYEnd = tmpLabel->lineYEnd - maxLabelHeight;
- }
- else
- {
- //move label up to tmpLabel topleft - height
- currentLabel->topLeftY = tmpLabel->topLeftY + maxLabelHeight;
- currentLabel->lineYEnd = tmpLabel->lineYEnd + maxLabelHeight;
- }
- //reset r value to 0 so it starts over, just in
- //case we moved the label and it overlaps another
- r = 0;
- checkLinePos = pieLabels->GetHeadPosition();
- }
- else
- {
- r++;
- pieLabels->GetNext(checkLinePos);
- }
- }
- //draw the line and label
- pDC->MoveTo(currentLabel->lineXStart, currentLabel->lineYStart);
- pDC->LineTo(currentLabel->lineXEnd, currentLabel->lineYEnd);
- //write the label
- pDC->TextOut(currentLabel->topLeftX, currentLabel->topLeftY,
- currentLabel->pieLabel);
- numLinesDrawn++;
- }
- //now done, remove everything inside the label list
- labelPos = pieLabels->GetHeadPosition();
- while(labelPos != NULL)
- {
- pieLabel = (CGraphPieLabel*)pieLabels->GetNext(labelPos);
- delete pieLabel;
- }
- delete pieLabels;
- }
- pDC->SelectObject(pOldBrush);
- pDC->SelectObject(pOldPen);
- }
- void CGraph::Print3DStackedBarSeries(CDC* pDC)
- {
- int barWidth;
- int barL, barT, barR, barB;
- int tickXLocation, tickYLocation;
- int seriesSpace;
- int barHeight;
- POSITION pos;
- CGraphSeries* tmpSeries;
- int blue;
- int red;
- int green;
- if(graphAlignment)
- {
- //determine width of barchart data blocks
- seriesSpace = xAxisWidth / graphSeries->GetCount();
- barWidth = (int)(seriesSpace * .8);
- pos = graphSeries->GetHeadPosition();
- double dataScale = 0.00;
- dataScale = (yAxisHeight * 1.00) / (maxTick - minTick);
- for(int x = 1; x <= graphSeries->GetCount(); x++)
- {
- tmpSeries = (CGraphSeries*)graphSeries->GetNext(pos);
- tickXLocation = xApexPoint + ((x * seriesSpace) - (seriesSpace / 2));
- barT = yApexPoint; //this is a running total;
- //it starts at yApexPoint so barB can
- //start there, then moves up by barHeight
- for(int s = 0; s < seriesSize; s++)
- {
- if(tmpSeries->GetData(s) > -1)
- {
- barHeight = (int)(((tmpSeries->GetData(s) - minTick) * 1.00) * dataScale);
- if(((tmpSeries->GetData(s) - minTick) > 0) && (barHeight < 1))
- barHeight = (int)dataScale;
- barB = barT;
- barL = tickXLocation - (barWidth / 2);
- if(barHeight > yAxisHeight)
- barT = barB + yAxisHeight;
- else
- barT = barB + barHeight;
- barR = barL + barWidth;
- COLORREF barColor;
- barColor = GetColor(s);
- CBrush brush (barColor);
- CPen rectPen (PS_SOLID, 1, barColor);
- CPen* pOldPen;
- pOldPen = pDC->SelectObject(&rectPen);
- CBrush* pOldBrush;
- pOldBrush = pDC->SelectObject(&brush);
- pDC->Rectangle(barL, barT, barR, barB);
- //now, we do the side
- //side is darker than front, so subtract
- //from color to make closer to black
- red = GetRValue(barColor);
- green = GetGValue(barColor);
- blue = GetBValue(barColor);
- int sideRed = red - 35;
- int sideGreen = green - 35;
- int sideBlue = blue - 35;
- if(sideRed < 0) sideRed = 0;
- if(sideGreen < 0) sideGreen = 0;
- if(sideBlue < 0) sideBlue = 0;
- COLORREF sideColor;
- sideColor = RGB(sideRed, sideGreen, sideBlue);
- CBrush sideBrush (sideColor);
- CPen sidePen (PS_SOLID, 1, sideColor);
- pDC->SelectObject(&sideBrush);
- pDC->SelectObject(&sidePen);
- CPoint sidePolyArray[4];
- CPoint sp1(barR, barT);
- CPoint sp2(barR, barB);
- CPoint sp3(barR + depth, barB + depth);
- CPoint sp4(barR + depth, barT + depth);
- sidePolyArray[0] = sp1;
- sidePolyArray[1] = sp2;
- sidePolyArray[2] = sp3;
- sidePolyArray[3] = sp4;
- pDC->Polygon(sidePolyArray, 4);
- //finally, the top
- int topRed = red + 35;
- int topGreen = green + 35;
- int topBlue = blue + 35;
- if(topRed > 255) topRed = 255;
- if(topGreen > 255) topGreen = 255;
- if(topBlue > 255) topBlue = 255;
- COLORREF topColor;
- topColor = RGB(topRed, topGreen, topBlue);
- CBrush topBrush (topColor);
- CPen topPen (PS_SOLID, 1, topColor);
- pDC->SelectObject(&topBrush);
- pDC->SelectObject(&topPen);
- CPoint topPolyArray[4];
- CPoint tp1(barL, barT);
- CPoint tp2(barR, barT);
- CPoint tp3(barR + depth, barT + depth);
- CPoint tp4(barL + depth, barT + depth);
- topPolyArray[0] = tp1;
- topPolyArray[1] = tp2;
- topPolyArray[2] = tp3;
- topPolyArray[3] = tp4;
- pDC->Polygon(topPolyArray, 4);
- pDC->SelectObject(pOldBrush);
- pDC->SelectObject(pOldPen);
- }
- }
- }
- }
- else
- {
- //determine width of barchart data blocks
- seriesSpace = yAxisHeight / graphSeries->GetCount();
- barHeight = (int)(seriesSpace * .8);
- pos = graphSeries->GetHeadPosition();
- double dataScale = 0.00;
- dataScale = ((xAxisWidth - 10) * 1.00) / (maxTick - minTick);
- for(int y = 1; y <= graphSeries->GetCount(); y++)
- {
- tmpSeries = (CGraphSeries*)graphSeries->GetNext(pos);
- tickYLocation = yApexPoint + ((y * seriesSpace) - (seriesSpace / 2));
- barR = xApexPoint; //this is a running total;
- //it starts at xApexPoint so barL can
- //start there, then moves right by barWidth
- for(int s = 0; s < seriesSize; s++)
- {
- if(tmpSeries->GetData(s) > -1)
- {
- barWidth = (int)(((tmpSeries->GetData(s) - minTick) * 1.00) * dataScale);
- if(((tmpSeries->GetData(s) - minTick) > 0) && (barWidth < 1))
- barWidth = (int)dataScale;
- barL = barR;
- barT = tickYLocation + (barHeight / 2);
- barB = barT - barHeight;
- if(barWidth > xAxisWidth)
- barR = barL + xAxisWidth;
- else
- barR = barL + barWidth;
- COLORREF barColor;
- barColor = GetColor(s);
- CBrush brush (barColor);
- CBrush* pOldBrush;
- pOldBrush = pDC->SelectObject(&brush);
- CPen rectPen (PS_SOLID, 1, barColor);
- CPen* pOldPen;
- pOldPen = pDC->SelectObject(&rectPen);
- pDC->Rectangle(barL, barT, barR, barB);
- //now, we do the side
- //side is darker than front, so subtract
- //from color to make closer to black
- red = GetRValue(barColor);
- green = GetGValue(barColor);
- blue = GetBValue(barColor);
- int sideRed = red - 35;
- int sideGreen = green - 35;
- int sideBlue = blue - 35;
- if(sideRed < 0) sideRed = 0;
- if(sideGreen < 0) sideGreen = 0;
- if(sideBlue < 0) sideBlue = 0;
- COLORREF sideColor;
- sideColor = RGB(sideRed, sideGreen, sideBlue);
- CBrush sideBrush (sideColor);
- CPen sidePen (PS_SOLID, 1, sideColor);
- pDC->SelectObject(&sideBrush);
- pDC->SelectObject(&sidePen);
- CPoint sidePolyArray[4];
- CPoint sp1(barL, barT);
- CPoint sp2(barR, barT);
- CPoint sp3(barR + depth, barT + depth);
- CPoint sp4(barL + depth, barT + depth);
- sidePolyArray[0] = sp1;
- sidePolyArray[1] = sp2;
- sidePolyArray[2] = sp3;
- sidePolyArray[3] = sp4;
- pDC->Polygon(sidePolyArray, 4);
- //finally, the top
- int topRed = red + 35;
- int topGreen = green + 35;
- int topBlue = blue + 35;
- if(topRed > 255) topRed = 255;
- if(topGreen > 255) topGreen = 255;
- if(topBlue > 255) topBlue = 255;
- COLORREF topColor;
- topColor = RGB(topRed, topGreen, topBlue);
- CBrush topBrush (topColor);
- CPen topPen (PS_SOLID, 1, topColor);
- pDC->SelectObject(&topBrush);
- pDC->SelectObject(&topPen);
- CPoint topPolyArray[4];
- CPoint tp1(barR, barT);
- CPoint tp2(barR, barB);
- CPoint tp3(barR + depth, barB + depth);
- CPoint tp4(barR + depth, barT + depth);
- topPolyArray[0] = tp1;
- topPolyArray[1] = tp2;
- topPolyArray[2] = tp3;
- topPolyArray[3] = tp4;
- pDC->Polygon(topPolyArray, 4);
- pDC->SelectObject(pOldBrush);
- pDC->SelectObject(pOldPen);
- }
- }
- }
- }
- }
- void CGraph::RemoveSeries(CString label)
- {
- POSITION pos;
- CGraphSeries* pSeries;
- pos = graphSeries->GetHeadPosition();
- while(pos != NULL)
- {
- pSeries = (CGraphSeries*)graphSeries->GetAt(pos);
- if(pSeries->GetLabel().Compare(label) == 0)
- {
- graphSeries->RemoveAt(pos);
- delete pSeries;
- break;
- }
- graphSeries->GetNext(pos);
- }
- }
- void CGraph::RemoveColor(int dataGroup)
- {
- POSITION pos;
- CGraphDataColor* dataColor;
- pos = colorList->GetHeadPosition();
- for(int i = 0; i < dataGroup; i++)
- {
- dataColor = (CGraphDataColor*)colorList->GetNext(pos);
- }
- colorList->RemoveAt(pos);
- delete dataColor;
- }
- void CGraph::RemoveLegend(int dataGroup)
- {
- graphLegend.Remove(dataGroup);
- }
- void CGraph::RemoveAllSeries()
- {
- POSITION pos;
- CGraphSeries* pSeries;
- pos = graphSeries->GetHeadPosition();
- while(pos != NULL)
- {
- pSeries = (CGraphSeries*) graphSeries->GetAt( pos );
- graphSeries->RemoveAt(pos);
- delete pSeries;
- }
- graphSeries->RemoveAll();
- }
- void CGraph::RemoveAllColors()
- {
- POSITION pos;
- CGraphDataColor* dataColor;
- pos = colorList->GetHeadPosition();
- while(pos != NULL)
- {
- dataColor = (CGraphDataColor*) colorList->GetAt( pos );
- colorList->RemoveAt(pos);
- delete dataColor;
- }
- colorList->RemoveAll();
- }
- void CGraph::RemoveAllLegends()
- {
- graphLegend.RemoveAll();
- }
- void CGraph::RemoveAllData()
- {
- RemoveAllSeries();
- RemoveAllLegends();
- RemoveAllColors();
- }
- void CGraph::Set3DDepthRatio(double ratio)
- {
- depthRatio = ratio;
- }
- void CGraph::SetGraphQuadType(int quads)
- {
- if(graphType == BAR_GRAPH)
- {
- if((quads < 1) || (quads > 4))
- graphQuadType = 1;
- else
- {
- graphQuadType = quads;
- quadSetManually = TRUE;
- }
- }
- }
- void CGraph::Set3DLineBase(int x, int y)
- {
- line3DXBase = x;
- line3DYBase = y;
- }