图案填充类,实现实心颜色填充和各种图案填充效果
class McDbHatch : public McDbEntity;
McDbHatch.h
例如:mxdrawx.ocx中的图案填充代码
// .h class CDrawHatch { public: // 图案填充数据 struct stuFillLine { double dAngle; double dXOrigin; double dYOrigin; double dXDelta; double dYDelta; McGeDoubleArray aryDash; stuFillLine() { dAngle = 0; dXOrigin = 0; dYOrigin = 0; dXDelta = 0; dYDelta = 1; } }; typedef std::vector<stuFillLine> VecFillLineData; // 填充的闭合区端点数据 struct stuVertex { McGePoint2d pt; double dStartWidth; double dEndWidth; double dBulge; stuVertex() { dBulge = 0.0; dStartWidth = -1.0; dEndWidth = -1.0; } }; CDrawHatch(void); virtual ~CDrawHatch(void); // 增加一个填充定义 bool AddPatternDefinition(const CString& sName, const CString& sDefinitionData); McDbHatch* MakeHatch(CString sHatchName, double dScale, std::vector<stuVertex>& vecData, std::vector<std::pair<bool,std::vector<stuVertex>* > >& vecExcelude ); private: std::map<CString,VecFillLineData*> m_mapFillData; }; // .cpp #include "StdAfx.h" #include "DrawHatch.h" CDrawHatch::CDrawHatch(void) { } CDrawHatch::~CDrawHatch(void) { std::map<CString,VecFillLineData*>::iterator iter = m_mapFillData.begin(); for(;iter != m_mapFillData.end();++iter) { delete iter->second; } m_mapFillData.clear(); } McDbHatch* CDrawHatch::MakeHatch(CString sHatchName, double dScale, std::vector<stuVertex>& vecData, std::vector<std::pair<bool,std::vector<stuVertex>* > >& vecExcelude ) { if(vecData.size() < 3 && vecExcelude.empty() ) { return NULL; } if(dScale < 0.00001) dScale = 1.0; VecFillLineData* pFillLineData = NULL; std::map<CString,VecFillLineData*>::iterator iter = m_mapFillData.find(sHatchName); if(sHatchName.CompareNoCase(_T("SOLID")) != 0) { if(iter != m_mapFillData.end()) { pFillLineData = iter->second; } else { sHatchName = _T("SOLID"); } } McDbHatch* pH = new McDbHatch; pH->setHatchStyle(McDbHatch::kNormal); pH->setHatchObjectType(McDbHatch::kHatchObject); pH->setPatternScale(1.0); pH->setPattern(McDbHatch::kPreDefined,sHatchName); // 设置填充对象的Loop数据; if(vecData.size() > 2) { McGePoint2dArray vecVertices; McGeDoubleArray vecBulges; for(unsigned int i = 0; i < vecData.size();i++) { stuVertex& tmp = vecData[i]; vecVertices.append(tmp.pt); vecBulges.append(tmp.dBulge); } pH->appendLoop(McDbHatch::kPolyline,vecVertices,vecBulges); } for(unsigned int i = 0; i < vecExcelude.size();i++) { std::vector<stuVertex>* pVecData = vecExcelude[i].second; int iloopType = McDbHatch::kPolyline; if( vecExcelude[i].first) { iloopType = iloopType | McDbHatch::kOutermost; } McGePoint2dArray vecVertices; McGeDoubleArray vecBulges; for(unsigned int j = 0; j < pVecData->size();j++) { stuVertex& tmp = (*pVecData)[j]; vecVertices.append(tmp.pt); vecBulges.append(tmp.dBulge); } pH->appendLoop(iloopType,vecVertices,vecBulges); } // 设置填充线条数据。 if(pFillLineData != NULL) { // for(unsigned int i = 0; i < pFillLineData->size();i++) { stuFillLine& fillLine = (*pFillLineData)[i]; McGeDoubleArray aryDash; for(int j = 0; j < fillLine.aryDash.length();j++) { aryDash.append(fillLine.aryDash[j] * dScale); } // illLine.dXDelta,fillLine.dYDelta的值是相对于,坐标系旋转了fillLine.dAngle后 // 的坐标系的值。这里需要把它变成 没有旋转的坐标系的值。 McGePoint2d ptTmp; ptTmp.x = fillLine.dXDelta; ptTmp.y = fillLine.dYDelta; McGeMatrix2d tmpMat = McGeMatrix2d::rotation(fillLine.dAngle); ptTmp.transformBy(tmpMat); ptTmp.x *= dScale; ptTmp.y *= dScale; pH->addPatternDefinition(fillLine.dAngle, fillLine.dXOrigin * dScale, fillLine.dYOrigin * dScale, ptTmp.x,ptTmp.y , aryDash); } } return pH; } bool CDrawHatch::AddPatternDefinition(const CString& sName, const CString& sDefinitionData) { if(sName.IsEmpty() ) return false; std::map<CString,VecFillLineData*>::iterator iter = m_mapFillData.find(sName); if(iter != m_mapFillData.end()) { // 已经有这个图案定义. return false; } if(sDefinitionData.IsEmpty() ) return false; MxStrList lst(sDefinitionData); VecFillLineData* pFillLineData = new VecFillLineData; int iCount = lst.GetCount(); for(int i = 0; i < iCount;i++) { CString sItem = lst.GetStrAt(i); if(sItem.IsEmpty() ) continue; stuFillLine tmpFillLine; MxStrList lstItem(sItem); int iItemCount = lstItem.GetCount(); int j = 0; for(; j < iItemCount;j++) { double dV = lstItem.GetDoubleAt(j); if(j == 0) { // angle,把度变成弧度。 tmpFillLine.dAngle = dV * 3.14159265 / 180.0; } else if(j == 1) { // x-origin tmpFillLine.dXOrigin = dV; } else if(j == 2) { // y-origin tmpFillLine.dYOrigin = dV; } else if(j == 3) { // delta-x tmpFillLine.dXDelta = dV; } else if(j == 4) { // delta-y tmpFillLine.dYDelta = dV; } else { tmpFillLine.aryDash.append(dV); } } if(j < 5) { // 数据不够。 continue; } pFillLineData->push_back(tmpFillLine); } if(pFillLineData->empty() ) { delete pFillLineData; pFillLineData = NULL; } else { m_mapFillData.insert(std::make_pair(sName,pFillLineData)); } return true; } // 使用 #include "DrawHatch.h" void CTestCommands::DrawHatch() { { // SOLID CDrawHatch drawHatch; std::vector<CDrawHatch::stuVertex> vecData; std::vector<std::pair<bool,std::vector<CDrawHatch::stuVertex>* > > vecExcelude; CDrawHatch::stuVertex tmp; tmp.pt = McGePoint2d(0,0); vecData.push_back(tmp); tmp.pt = McGePoint2d(100,100); vecData.push_back(tmp); tmp.pt = McGePoint2d(100,0); vecData.push_back(tmp); tmp.pt = McGePoint2d(0,0); vecData.push_back(tmp); McDbHatch* pHatch = drawHatch.MakeHatch(_T("SOLID"),1.0,vecData,vecExcelude); MxDraw::SetEnityDrawOrder(pHatch,2); if(pHatch != NULL) { AddToModelSpace(pHatch,acdbCurDwg()); } } { // 图案填充 CDrawHatch drawHatch; std::vector<CDrawHatch::stuVertex> vecData; std::vector<std::pair<bool,std::vector<CDrawHatch::stuVertex>* > > vecExcelude; CDrawHatch::stuVertex tmp; tmp.pt = McGePoint2d(0,0); vecData.push_back(tmp); tmp.pt = McGePoint2d(100,200); vecData.push_back(tmp); tmp.pt = McGePoint2d(200,0); vecData.push_back(tmp); tmp.pt = McGePoint2d(0,0); vecData.push_back(tmp); //绘制一个有图案的填充 //angle, x-origin,y-origin, delta-x,delta-y,dash-1,dash-2, … //45 = angle 是图案线角度. //0 = x-origin 是第一个填充线经过的点位置X坐标 //0 = y-origin 是第一个填充线经过的点位置Y坐标 //0 = delta-x 是下一个填充线相对前一个线的X方向偏移 //0.125 = delta-y 是下一个填充线相对前一个线的Y方向偏移 drawHatch.AddPatternDefinition(_T("MyPattern"),_T("((45, 0,0, 0,0.125))")); //drawHatch.AddPatternDefinition(_T("MyPattern"),_T("((0,0,0,0,8)(90,0,0,8,8,8,-8))")); McDbHatch* pHatch = drawHatch.MakeHatch(_T("MyPattern"),4.0,vecData,vecExcelude); if(pHatch != NULL) { pHatch->setColorIndex(MrxDbgUtils::kRed); MxDraw::SetEnityDrawOrder(pHatch,1); AddToModelSpace(pHatch,acdbCurDwg()); } } return; }
例如: 演示图案填充代码2.
struct stuFillLine { double dAngle; double dXOrigin; double dYOrigin; double dXDelta; double dYDelta; McGeDoubleArray aryDash; stuFillLine() { dAngle = 0; dXOrigin = 0; dYOrigin = 0; dXDelta = 0; dYDelta = 1; } }; bool GetPatternDefinition( IN const CString& sDefinitionData, OUT std::vector<stuFillLine>& vecFillData ) { MxStrList lst(sDefinitionData); int iCount = lst.GetCount(); for(int i = 0; i < iCount;i++) { CString sItem = lst.GetStrAt(i); if(sItem.IsEmpty() ) continue; stuFillLine tmpFillLine; MxStrList lstItem(sItem); int iItemCount = lstItem.GetCount(); int j = 0; for(; j < iItemCount;j++) { double dV = lstItem.GetDoubleAt(j); if(j == 0) { // angle,把度变成弧度。 tmpFillLine.dAngle = dV * MxPI / 180.0; } else if(j == 1) { // x-origin tmpFillLine.dXOrigin = dV; } else if(j == 2) { // y-origin tmpFillLine.dYOrigin = dV; } else if(j == 3) { // delta-x tmpFillLine.dXDelta = dV; } else if(j == 4) { // delta-y tmpFillLine.dYDelta = dV; } else { tmpFillLine.aryDash.append(dV); } } if(j < 5) { // 数据不够。 continue; } vecFillData.push_back(tmpFillLine); } if(vecFillData.empty() ) { return false; } else { return true; } } void DrawHatch() { CString sPatternDefine = _T("((0, 0,0, 0,.275, .2,-.075) (90, 0,0, 0,.275, .2,-.075))"); std::vector<stuFillLine> vecFillData; if(!GetPatternDefinition( sPatternDefine, vecFillData ) ) { return; } double dPatternScale = 10.0; AcDbHatch* pHatch = new AcDbHatch(); AcGeVector3d normal(0.0, 0.0, 1.0); pHatch->setNormal(normal); pHatch->setElevation(0.0); pHatch->setPattern(AcDbHatch::kPreDefined, _T("ANGLE")); pHatch->setHatchStyle(AcDbHatch::kNormal); pHatch->setPatternScale(1); AcGePoint2dArray vertexPts; AcGeDoubleArray vertexBulges; vertexPts.setPhysicalLength(0).setLogicalLength(5); vertexPts[0].set(20.0, 20.0); vertexPts[1].set(80.0, 20.0); vertexPts[2].set(80.0, 80.0); vertexPts[3].set(20.0, 80.0); vertexPts[4].set(20.0, 20.0); vertexBulges.setPhysicalLength(0).setLogicalLength(5); for (int i = 0; i < 5; i++) vertexBulges[i] = 0.0; pHatch->appendLoop(AcDbHatch::kExternal, vertexPts, vertexBulges); AcDbPolyline* pLine = new AcDbPolyline(); for (int i = 0; i < 5; i++) { pLine->addVertexAt(i, vertexPts[i]); } for(unsigned int i = 0; i < vecFillData.size();i++) { stuFillLine& fillLine = vecFillData[i]; McGeDoubleArray aryDash; for(int j = 0; j < fillLine.aryDash.length();j++) { aryDash.append(fillLine.aryDash[j] * dPatternScale); } // illLine.dXDelta,fillLine.dYDelta的值是相对于,坐标系旋转了fillLine.dAngle后 // 的坐标系的值。这里需要把它变成 没有旋转的坐标系的值。 McGePoint2d ptTmp; ptTmp.x = fillLine.dXDelta; ptTmp.y = fillLine.dYDelta; McGeMatrix2d tmpMat = McGeMatrix2d::rotation(fillLine.dAngle); ptTmp.transformBy(tmpMat); ptTmp.x *= dPatternScale; ptTmp.y *= dPatternScale; pHatch->addPatternDefinition(fillLine.dAngle, fillLine.dXOrigin * dPatternScale, fillLine.dYOrigin * dPatternScale, ptTmp.x,ptTmp.y , aryDash); } AcDbObjectId newId; MrxDbgUtils::addToCurrentSpaceAndClose(pHatch, acdbCurDwg()); MrxDbgUtils::addToCurrentSpaceAndClose(pLine, acdbCurDwg()); Mx::ZoomE(); }