Пример #1
0
//рисует центр прибора использу¤ цвет фона
void CAnalogMeter::DrawChord(const CRect& Bounds)
{
 if(!m_swGrid)
  return;

 CRect Circle = Bounds;
 CBrush*  pBrushOld = NULL;
 CPen* pPenOld = NULL;
 CBrush chord_brush;
 CPen   chord_pen;

 chord_brush.CreateSolidBrush((~m_colorBGround)&0xFFFFFF);
 chord_pen.CreatePen(PS_NULL,0,(~m_colorBGround)&0xFFFFFF);

 int r = m_nRadiusPix / 5;

 Circle.DeflateRect(r,r,r,r);

 CPoint ptStart(ROUND(m_nCXPix + m_nRadiusPix*sin(m_dLimitAngleRad)),
 ROUND(m_nCYPix - m_nRadiusPix*cos(m_dLimitAngleRad)));
 CPoint ptEnd(m_nLeftLimitXPix, m_nLeftLimitYPix);

 pBrushOld = m_dcGrid.SelectObject(&chord_brush);
 pPenOld = m_dcGrid.SelectObject(&chord_pen);
 m_dcGrid.Chord(Circle,ptStart,ptEnd);
 m_dcGrid.SelectObject(pPenOld);
 m_dcGrid.SelectObject(pBrushOld);
}
Пример #2
0
void MyGesture::removeRedundantEndPoints(vector<Vec4i> newDefects, MyInputImgStruct *m){
/***
 * DOC:
 */
	Vec4i Temp;
	int startidx, endidx, faridx, startidx2, endidx2;
	float Tolerance = bRect_Width/6;
	for(int i=0; i<newDefects.size(); i++)
	{
		for(int j=i; j<newDefects.size(); j++)
		{
			startidx = newDefects[i][0];
			Point ptStart(contours[cIdx][startidx]);
			endidx = newDefects[i][1];
			Point ptEnd(contours[cIdx][endidx]);
			startidx2 = newDefects[j][0];
			Point ptStart2(contours[cIdx][startidx2]);
			endidx2 = newDefects[j][1];
			Point ptEnd2(contours[cIdx][endidx2]);
			if(distanceP2P(ptStart, ptEnd2) < Tolerance)
			{
				contours[cIdx][startidx] = ptEnd2;
				break;
			}
			if(distanceP2P(ptEnd, ptStart2) < Tolerance)
			{
				contours[cIdx][startidx2] = ptEnd;
			}
		}
	}
}//ENDOF Method: removeRedundantEndPoints(newDefects, *m)
Пример #3
0
void MyGesture::getFingerTips(MyInputImgStruct *m){
/***
 *@DOC:  Gets which of the remaining Defect points are the finger tips
 * and returns it into the vector FingerTips
**/
	FingerTips.clear();
	int i = 0;
	vector<Vec4i>::iterator d = Defects[cIdx].begin();
	while(d != Defects[cIdx].end())
	{
		Vec4i& v = (*d);
		int startidx = v[0];
		Point ptStart(contours[cIdx][startidx]);
		int endidx = v[1];
		Point ptEnd(contours[cIdx][endidx]);
		int faridx = v[2];
		Point ptFar(contours[cIdx][faridx]);
		if(i==0){
			FingerTips.push_back(ptStart);
			i++;
		}
		FingerTips.push_back(ptEnd);
		d++;
		i++;
	}//ENDOF while()
	if(FingerTips.size() == 0)
	{
		checkForOneFinger(m);
	}
} //ENDOF Method: getFingerTips(MyInputImgStruct *m)
void condefects(vector<Vec4i>convexityDefectsSet, vector<Point> mycontour, Mat& drawing){
	for (int cDefIt = 0; cDefIt < convexityDefectsSet.size(); cDefIt++)
	{
		int startIdx = convexityDefectsSet[cDefIt].val[0]; Point ptStart(mycontour[startIdx]);
		int endIdx = convexityDefectsSet[cDefIt].val[1];	Point ptEnd(mycontour[endIdx]);
		int defectPtIdx = convexityDefectsSet[cDefIt].val[2]; Point ptFar(mycontour[defectPtIdx]);
		double depth = (double)convexityDefectsSet[cDefIt].val[3] / 256.0f;  // see documentation link below why this

		circle(drawing, ptStart, 5, CV_RGB(255, 0, 0), 2, 8);
		circle(drawing, ptEnd, 5, CV_RGB(255, 0, 0), 2, 8);
		circle(drawing, ptFar, 5, CV_RGB(255, 0, 0), 2, 8);
		// do something with *contour[defectPtIdx]*.. This is e.g. the defect point.

	}
}
CXTPChartDeviceCommand* CXTPChartRadarAxisXView::CreateConstantLinesDeviceCommand(CXTPChartDeviceContext* pDC, BOOL bBehind)
{
	CXTPChartAxisConstantLines* pConstantLines = m_pAxis->GetConstantLines();
	if (pConstantLines->GetCount() == 0)
		return NULL;

	CXTPChartDeviceCommand* pCommands = new CXTPChartDeviceCommand();

	for (int i = 0; i < pConstantLines->GetCount(); i++)
	{
		CXTPChartAxisConstantLine* pConstantLine = pConstantLines->GetAt(i);
		if (!pConstantLine->IsVisible())
			continue;

		if (pConstantLine->IsShowBehind() != bBehind)
			continue;

		double dMark = !pConstantLine->GetAxisValue().IsEmpty() ? m_pAxis->GetScaleTypeMap()->ValueToInternal(pConstantLine->GetAxisValue()) :
			pConstantLine->GetAxisValueInternal();

		double lineAngle = ValueToAngle(dMark);

		CXTPPoint3d ptEnd(m_ptCenter.X + cos(lineAngle) * m_nRadius, m_ptCenter.Y - sin(lineAngle) * m_nRadius);

		pCommands->AddChildCommand(pConstantLine->GetLineStyle()->CreateDeviceCommand(CXTPPoint3d(m_ptCenter),
			ptEnd, pConstantLine->GetActualColor()));

		CXTPChartString strText = pConstantLine->GetText();

		CPoint ptText(int(m_ptCenter.X + cos(lineAngle) * (m_nRadius - 5)), int(m_ptCenter.Y - sin(lineAngle) * (m_nRadius - 5)));

		CXTPChartRotatedTextPainterNearLine painter(pDC, strText, pConstantLine, ptText, xtpChartTextNearTop, -(float)CXTPChartMathUtils::Radian2Degree(lineAngle));
			pCommands->AddChildCommand(painter.CreateDeviceCommand(pDC, pConstantLine->GetActualTextColor()));

	}

	return pCommands;
}
Пример #6
0
void MyGesture::eleminateDefects(MyInputImgStruct *m){
/***
 * @DOC: Takes all the defect points into vector d. Loops through d and
 * measures the P2P distance between the Defect Points and decides whether
 * the Point will be dismissed or kept based on l>0.4lbb and Theta>85'
**/

	int tolerance = bRect_Height/5;
	float angleTol = 95;
	vector<Vec4i> newDefects;
	int startidx, endidx, faridx;
	vector<Vec4i>::iterator d = Defects[cIdx].begin();
	while(d != Defects[cIdx].end())
	{
		Vec4i& v = (*d);
		startidx = v[0];
		Point ptStart(contours[cIdx][startidx]);
		endidx = v[1];
		Point ptEnd(contours[cIdx][endidx]);
		faridx = v[2];
		Point ptFar(contours[cIdx][faridx]);

		if((distanceP2P(ptStart, ptFar) > tolerance) &&
				(distanceP2P(ptEnd, ptFar) > tolerance) &&
						(getAngle(ptStart, ptFar, ptEnd) < angleTol)){
			if(ptEnd.y > (bRect.y + bRect.height - bRect.height/4)) {/*Do Nothing*/}
			else if(ptStart.y > (bRect.y + bRect.height - bRect.height/4)) {/*Do Nothing*/}
			else {
				newDefects.push_back(v);
			}
		}
		d++;
	}//ENDOF While()
	numOfDefects = newDefects.size();
	Defects[cIdx].swap(newDefects);
	removeRedundantEndPoints(Defects[cIdx], m);
} //ENDOF Method: eleminateDefects(MyInputImgStruct *m)
void HandDetector::FindConvexityDefects(vector<Vec4i> ConvexityDefectSet, vector<Point> HandContour, Mat& LiveFrame, Point2f COM, int TiltAngle)
{
	vector<Point> FingerTips;
	
	Point2f HandCenter;
	float radius;
	int fingers=0;

	//minEnclosingCircle(HandContour,HandCenter,radius);
	//Rect contourRect = boundingRect(HandContour);
	//circle(LiveFrame,HandCenter,10,CV_RGB(0,0,255),2,8);
	//rectangle(LiveFrame, contourRect, Scalar(0,0,255), 3);
	//vector<Point> palmCircle;
	for (int i = 0; i < ConvexityDefectSet.size(); i++) 
	{

		int startId = ConvexityDefectSet[i].val[0];
		Point ptStart(HandContour[startId]);

		int endId = ConvexityDefectSet[i].val[1]; 
		Point ptEnd(HandContour[endId]);

		int farId = ConvexityDefectSet[i].val[2]; 
		Point ptFar(HandContour[farId]);

		double depth = (double)((ConvexityDefectSet[i].val[3]) / 256); //for getting real pixel values

		//cout << "depth" << depth << endl;
		//display start points
		//circle(original,ptStart,5,CV_RGB(255,0,0),2,8);
		//display all end points
		//circle(original, ptEnd, 5, CV_RGB(255, 255, 0), 2, 8);
		//display all far points
		//circle(LiveFrame,ptFar,5,CV_RGB(255,255,0),2,8);

		//circle(LiveFrame, HandCenter, radius, cv::Scalar(0,255,255),2);
		if (depth > 10 && ptStart.y < COM.y)//
		{
			circle(LiveFrame,ptStart,5,CV_RGB(255,0,0),2,8);
			//circle(LiveFrame, ptStart, 4, CV_RGB(255, 0,0), 4);
			FingerTips.push_back(ptStart);
			fingers++;
			//palmCircle.push_back(ptStart);
						
		}
	}
		
	if(mMouseControl)
	{
		InitMouseControl(LiveFrame,FingerTips,COM,TiltAngle);
	}
	if(mSwipeON)
	{
		Point tempCOM;
		tempCOM.x = COM.x;
		tempCOM.y = COM.y;
		mSwipeGesture.SwipeInit(tempCOM, LiveFrame);
	}

	//cout<<"Fingers = "<<fingers<<endl;
}
Пример #8
0
void CMyDlg::OnCreateLine() 
{	
	// TODO: Add your control notification handler code here
	acDocManager->lockDocument(curDoc());

	int i;
	int m, n;

	char *buf = (char*)malloc(20);
	
	AcDbObjectId LineId;
	AcDbLine *pLine = NULL;
	//块表
	AcDbBlockTable *pTb = NULL;
	//块表记录
	AcDbBlockTableRecord *pTbr = NULL;
	//层表
	AcDbLayerTable *pLyr = NULL;
	//层表记录
	AcDbLayerTableRecord* pLyrr = NULL;
	//图形数据库
	AcDbDatabase *pDb = acdbHostApplicationServices()->workingDatabase();
	
	Acad::ErrorStatus es;
	
	CListCtrl *pListCtr = (CListCtrl *)GetDlgItem( IDC_LIST1 );
	
	//设置随机数种子
	srand(time(NULL));
	
	//更新数据
	UpdateData(TRUE);

	m_VecSize += m_Edit5;
	m_xVec.resize(m_VecSize);
	m_yVec.resize(m_VecSize);

	//acutPrintf("%d\n", m_Edit1);
	
	es = pDb->getLayerTable(pLyr, AcDb::kForWrite);	//以写的方式打开层表
	es = pDb->getBlockTable(pTb, AcDb::kForRead);	//以读的方式打开块表
	es = pTb->getAt(ACDB_MODEL_SPACE, pTbr, AcDb::kForWrite);//以写的方式打开块表记录
	
	//创建图层GalLineTest
	if (!pLyr->has("GalLineTest"))
	{
		pLyrr = new AcDbLayerTableRecord;	//创建层记录
		pLyrr->setName("GalLineTest");		//设置名字
		//pLyrr->setColor(color);			//设置颜色
		//pLyrr->setLineWeight(lnWt);		//设置线宽
		
		if (Acad::eOk != pLyr->add(pLyrr))	//添加该层记录到层表
		{
			//添加失败
			delete pLyrr;		//释放内存
			pLyr->close();		//关闭层表
		}
		//关闭层表记录
		pLyrr->close();
	}
	//关闭层表
	pLyr->close();
	
	//生成点坐标
	for (i = 0; i < m_Edit5; ++i)
	{
		if ((m_Edit2 != 0) && (m_Edit4 != 0))
		{
			m_xVec[i] = rand() % m_Edit2 + m_Edit1;
			m_yVec[i] = rand() % m_Edit4 + m_Edit3;
		}
		else
		{
			m_xVec[i] = 0;
			m_yVec[i] = 0;
		}
	}
	
	//遍历点坐标
	for (m = 0; m < m_Edit5; ++m)
	{
		for (n = (m+1); n < m_Edit5; ++n)
		{
			if ((m_xVec[m] != m_xVec[n]) && (m_yVec[m] != m_yVec[n]))
			{
				AcGePoint3d ptStart(m_xVec[m], m_yVec[m], 0);
				AcGePoint3d ptEnd(m_xVec[n], m_yVec[n], 0);
				pLine = new AcDbLine(ptStart, ptEnd);
				//pLine->setColor();
				pLine->setLayer("GalLineTest");
				//创建线段
				es = pTbr->appendAcDbEntity(LineId, pLine);
				if (Acad::eOk == es)
				{
					++m_lLineCnt;
				}
				//acutPrintf("%d\n", LineId);
				sprintf(buf, "%d", LineId);			
				m_ListCtr.InsertItem(m_Row, buf);
				
				buf = itoa(pLine->colorIndex(), buf, 10);
				m_ListCtr.SetItemText(m_Row, 1, buf);
				
				buf = itoa(LineLength(m_xVec[m], m_yVec[m],
									m_xVec[n], m_yVec[n]), buf, 10);
				m_ListCtr.SetItemText(m_Row, 2, buf);
				
				++m_Row;
				pLine->close();	//关闭实体
			}
		}
	}
	pTbr->close();	//关闭块表记录
	pTb->close();	//关闭块表

	acDocManager->unlockDocument(curDoc());
	free(buf);
}
Mat CameraInteraction::Testmm(Mat frame){




            vector<vector<Point> > contours;


            //Update the current background model and get the foreground
            if(backgroundFrame>0)
            {bg.operator ()(frame,fore);backgroundFrame--;}
            else
            {bg.operator()(frame,fore,0);}

            //Get background image to display it
            bg.getBackgroundImage(back);


            //Enhance edges in the foreground by applying erosion and dilation
            erode(fore,fore,Mat());
            dilate(fore,fore,Mat());


            //Find the contours in the foreground
            findContours(fore,contours,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_NONE);
            for(int i=0;i<contours.size();i++)
                //Ignore all small insignificant areas
                if(contourArea(contours[i])>=5000)
                {
                    //Draw contour
                    vector<vector<Point> > tcontours;
                    tcontours.push_back(contours[i]);
                    drawContours(frame,tcontours,-1,cv::Scalar(0,0,255),2);

                    //Detect Hull in current contour
                    vector<vector<Point> > hulls(1);
                    vector<vector<int> > hullsI(1);
                    convexHull(Mat(tcontours[0]),hulls[0],false);
                    convexHull(Mat(tcontours[0]),hullsI[0],false);
                    drawContours(frame,hulls,-1,cv::Scalar(0,255,0),2);

                    //Find minimum area rectangle to enclose hand
                    RotatedRect rect=minAreaRect(Mat(tcontours[0]));

                    //Find Convex Defects
                    vector<Vec4i> defects;
                    if(hullsI[0].size()>0)
                    {
                        Point2f rect_points[4]; rect.points( rect_points );
                        for( int j = 0; j < 4; j++ )
                            line( frame, rect_points[j], rect_points[(j+1)%4], Scalar(255,0,0), 1, 8 );
                        Point rough_palm_center;
                        convexityDefects(tcontours[0], hullsI[0], defects);
                        if(defects.size()>=3)
                        {
                            vector<Point> palm_points;
                            for(int j=0;j<defects.size();j++)
                            {
                                int startidx=defects[j][0]; Point ptStart( tcontours[0][startidx] );
                                int endidx=defects[j][1]; Point ptEnd( tcontours[0][endidx] );
                                int faridx=defects[j][2]; Point ptFar( tcontours[0][faridx] );
                                //Sum up all the hull and defect points to compute average
                                rough_palm_center+=ptFar+ptStart+ptEnd;
                                palm_points.push_back(ptFar);
                                palm_points.push_back(ptStart);
                                palm_points.push_back(ptEnd);
                            }

                            //Get palm center by 1st getting the average of all defect points, this is the rough palm center,
                            //Then U chose the closest 3 points ang get the circle radius and center formed from them which is the palm center.
                            rough_palm_center.x/=defects.size()*3;
                            rough_palm_center.y/=defects.size()*3;
                            Point closest_pt=palm_points[0];
                            vector<pair<double,int> > distvec;
                            for(int i=0;i<palm_points.size();i++)
                                distvec.push_back(make_pair(dist(rough_palm_center,palm_points[i]),i));
                            sort(distvec.begin(),distvec.end());

                            //Keep choosing 3 points till you find a circle with a valid radius
                            //As there is a high chance that the closes points might be in a linear line or too close that it forms a very large circle
                            pair<Point,double> soln_circle;
                            for(int i=0;i+2<distvec.size();i++)
                            {
                                Point p1=palm_points[distvec[i+0].second];
                                Point p2=palm_points[distvec[i+1].second];
                                Point p3=palm_points[distvec[i+2].second];
                                soln_circle=circleFromPoints(p1,p2,p3);//Final palm center,radius
                                if(soln_circle.second!=0)
                                    break;
                            }

                            //Find avg palm centers for the last few frames to stabilize its centers, also find the avg radius
                            palm_centers.push_back(soln_circle);
                            if(palm_centers.size()>10)
                                palm_centers.erase(palm_centers.begin());

                            Point palm_center;
                            double radius=0;
                            for(int i=0;i<palm_centers.size();i++)
                            {
                                palm_center+=palm_centers[i].first;
                                radius+=palm_centers[i].second;
                            }
                            palm_center.x/=palm_centers.size();
                            palm_center.y/=palm_centers.size();
                            radius/=palm_centers.size();

                            //Draw the palm center and the palm circle
                            //The size of the palm gives the depth of the hand
                            circle(frame,palm_center,5,Scalar(144,144,255),3);
                            circle(frame,palm_center,radius,Scalar(144,144,255),2);

                            //Detect fingers by finding points that form an almost isosceles triangle with certain thesholds
                            int no_of_fingers=0;
                            for(int j=0;j<defects.size();j++)
                            {
                                int startidx=defects[j][0]; Point ptStart( tcontours[0][startidx] );
                                int endidx=defects[j][1]; Point ptEnd( tcontours[0][endidx] );
                                int faridx=defects[j][2]; Point ptFar( tcontours[0][faridx] );
                                //X o--------------------------o Y
                                double Xdist=sqrt(dist(palm_center,ptFar));
                                double Ydist=sqrt(dist(palm_center,ptStart));
                                double length=sqrt(dist(ptFar,ptStart));

                                double retLength=sqrt(dist(ptEnd,ptFar));
                                //Play with these thresholds to improve performance
                                if(length<=3*radius&&Ydist>=0.4*radius&&length>=10&&retLength>=10&&max(length,retLength)/min(length,retLength)>=0.8)
                                    if(min(Xdist,Ydist)/max(Xdist,Ydist)<=0.8)
                                    {
                                        if((Xdist>=0.1*radius&&Xdist<=1.3*radius&&Xdist<Ydist)||(Ydist>=0.1*radius&&Ydist<=1.3*radius&&Xdist>Ydist))
                                            line( frame, ptEnd, ptFar, Scalar(0,255,0), 1 ),no_of_fingers++;
                                    }


                            }

                            no_of_fingers=min(5,no_of_fingers);
                            qDebug()<<"NO OF FINGERS: "<<no_of_fingers;
                            //mouseTo(palm_center.x,palm_center.y);//Move the cursor corresponding to the palm
                            if(no_of_fingers<4)//If no of fingers is <4 , click , else release
//                                mouseClick();
                                qDebug()<<"Test";
                            else
//                                mouseRelease();
                                qDebug()<<"Hola";

                        }
                    }

                }
            if(backgroundFrame>0)
                putText(frame, "Recording Background", cvPoint(30,30), FONT_HERSHEY_COMPLEX_SMALL, 0.8, cvScalar(200,200,250), 1, CV_AA);
//            imshow("Framekj",frame);
//            imshow("Background",back);
return frame;

}
Пример #10
0
void MyGraph::DrawSeriesPie(CDC& dc) const
{
	VALIDATE;
	ASSERT_VALID(&dc);

	// Determine width of pie display area (pie and space).
	int nSeriesSpace(0);

	int seriesCount = GetNonZeroSeriesCount();
	int horizontalSpace(0);

	if (m_saLegendLabels.GetSize()) {
		// With legend box.

		horizontalSpace = m_nXAxisWidth - m_rcLegend.Width() - (GAP_PIXELS * 2);
		int nPieAndSpaceWidth(horizontalSpace / (seriesCount ? seriesCount : 1));

		// Height is limiting factor.
		if (nPieAndSpaceWidth > m_nYAxisHeight - (GAP_PIXELS * 2)) {
			nSeriesSpace = (m_nYAxisHeight - (GAP_PIXELS * 2));
		}
		else {
			// Width is limiting factor.
			nSeriesSpace = nPieAndSpaceWidth;
		}
	}
	else {
		// No legend box.

		horizontalSpace = m_nXAxisWidth;

		// Height is limiting factor.
		if (m_nXAxisWidth > m_nYAxisHeight * (seriesCount ? seriesCount : 1)) {
			nSeriesSpace = m_nYAxisHeight;
		}
		else {
			// Width is limiting factor.
			nSeriesSpace = m_nXAxisWidth / (seriesCount ? seriesCount : 1);
		}
	}

	// Make pies be centered horizontally
	int xOrigin = m_ptOrigin.x + GAP_PIXELS + (horizontalSpace - nSeriesSpace * seriesCount) / 2;

	// Create font for labels.
	CFont fontLabels;
	int pointFontHeight = max(m_rcGraph.Height() / Y_AXIS_LABEL_DIVISOR, MIN_FONT_SIZE);
	VERIFY(fontLabels.CreatePointFont(pointFontHeight, _T("Arial"), &dc));
	CFont* pFontOld = dc.SelectObject(&fontLabels);
	ASSERT_VALID(pFontOld);

	// Draw each pie.
	int nPie(0);
	int nRadius((int) (nSeriesSpace * INTERSERIES_PERCENT_USED / 2.0));
	POSITION pos(m_olMyGraphSeries.GetHeadPosition());

	while (pos) {

		MyGraphSeries* pSeries = m_olMyGraphSeries.GetNext(pos);
		ASSERT_VALID(pSeries);

		// Don't leave a space for empty pies.
		if (0 < pSeries->GetNonZeroElementCount()) {

			// Locate this pie.
			CPoint ptCenter;
			ptCenter.x = xOrigin + (nSeriesSpace * nPie) + nSeriesSpace / 2;
			ptCenter.y = m_ptOrigin.y - m_nYAxisHeight / 2;

			CRect rcPie;
			rcPie.left = ptCenter.x - nRadius;
			rcPie.right = ptCenter.x + nRadius;
			rcPie.top = ptCenter.y - nRadius;
			rcPie.bottom = ptCenter.y + nRadius;

			// Draw series label.
			CSize sizPieLabel(dc.GetTextExtent(pSeries->GetLabel()));

			VERIFY(dc.TextOut(ptCenter.x - (sizPieLabel.cx / 2),
			  ptCenter.y + nRadius + GAP_PIXELS, pSeries->GetLabel()));

			// How much do the wedges total to?
			double dPieTotal(pSeries->GetDataTotal());

			// Draw each wedge in this pie.
			CPoint ptStart(rcPie.left, ptCenter.y);
			double dRunningWedgeTotal(0.0);

			for (int nGroup = 0; nGroup < m_saLegendLabels.GetSize(); ++nGroup) {

				// Ignore empty wedges.
				if (0 < pSeries->GetData(nGroup)) {

					// Get the degrees of this wedge.
					dRunningWedgeTotal += pSeries->GetData(nGroup);
					double dPercent(dRunningWedgeTotal * 100.0 / dPieTotal);
					double degrees(360.0 * dPercent / 100.0);

					// Find the location of the wedge's endpoint.
					CPoint ptEnd(WedgeEndFromDegrees(degrees, ptCenter, nRadius));

					// Special case: a wedge that takes up the whole pie would
					// otherwise be confused with an empty wedge.
					bool drawEmptyWedges = false;
					if (1 == pSeries->GetNonZeroElementCount()) {
						_ASSERTE(360 == (int)degrees  &&  ptStart == ptEnd  &&  "This is the problem we're correcting");
						--ptEnd.y;
						drawEmptyWedges = true;
					}

					// If the wedge is zero size or very narrow, don't paint it.
					// If pie is small, and wedge data is small, we might get a wedges
					// where center and both endpoints lie on the same coordinate,
					// and endpoints differ only in one pixel. GDI draws such pie as whole pie,
					// so we just skip them instead.
					int distance = abs(ptStart.x-ptEnd.x) + abs(ptStart.y-ptEnd.y);
					if (drawEmptyWedges || distance > 1) {

						// Draw wedge.
						COLORREF crWedge(m_dwaColors.GetAt(nGroup));
						CBrush br(crWedge);
						CBrush* pBrushOld = dc.SelectObject(&br);
						ASSERT_VALID(pBrushOld);
						VERIFY(dc.Pie(rcPie, ptStart, ptEnd));

						// Create a region from the path we create.
						VERIFY(dc.BeginPath());
						VERIFY(dc.Pie(rcPie, ptStart, ptEnd));
						VERIFY(dc.EndPath());
						CRgn * prgnWedge = new CRgn;
						VERIFY(prgnWedge->CreateFromPath(&dc));
						pSeries->SetTipRegion(nGroup, prgnWedge);

						// Cleanup.
						dc.SelectObject(pBrushOld);
						br.DeleteObject();
						ptStart = ptEnd;
					}
				}
			}

			++nPie;
		}
	}

	// Draw X axis title
	CSize sizXLabel(dc.GetTextExtent(m_sXAxisLabel));
	VERIFY(dc.TextOut(xOrigin + (nSeriesSpace * nPie - sizXLabel.cx)/2,
		m_ptOrigin.y - m_nYAxisHeight/2 + nRadius + GAP_PIXELS*2 + sizXLabel.cy, m_sXAxisLabel));

	VERIFY(dc.SelectObject(pFontOld));
	fontLabels.DeleteObject();
}