www.mxdraw.com
内容索引主面
前一个向上下一个
McDbHatch 类

图案填充类,实现实心颜色填充和各种图案填充效果

C++
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();
    }
Copyright (c) 2010. All rights reserved.
你认为该帮助怎么样? 发送反馈信息!