天气与日历 切换到窄版

 找回密码
 立即注册
中国膜结构网
十大进口膜材评选 十大国产膜材评选 十大膜结构设计评选 十大膜结构公司评选
查看: 57|回复: 0

ObjectARX自定义实体

[复制链接]

该用户从未签到

主题

0

回帖

2912

积分

管理员

积分
2912
发表于 2024-6-22 09:46:18 | 显示全部楼层 |阅读模式
[code]说明: 此次绘制的CAD自定义实体是一个矩形,具有拉伸功能。因为初次接触自定义实体,在一次次制作的过程中遇到了很多困难,幸好有老大和同事的帮助,当然还有广大网友们的文章协助,才完成了这个自定义实体的绘制。我不敢说到目前还会有什么问题,但希望能帮助到别人。

一、需要重载的函数
    //绘制夹点
    virtual Acad::ErrorStatus getGripPoints(AcDbGripDataPtrArray& grips, const double curViewUnitSize, const int gripSize, const AcGeVector3d& curViewDir, const int bitflags) const;
        //移动夹点
        virtual Acad::ErrorStatus moveGripPointsAt(const AcDbVoidPtrArray& gripAppData,const AcGeVector3d& offset,const int bitflags);
        //加载数据
        virtual Acad::ErrorStatus dwgInFields(AcDbDwgFiler* pFiler);
        //保存数据
        virtual Acad::ErrorStatus dwgOutFields(AcDbDwgFiler* pFiler) const;
        //矩阵转换
        virtual Acad::ErrorStatus transformBy(const AcGeMatrix3d& xform);
        //分解(炸开)
        virtual Acad::ErrorStatus explode(ZcDbVoidPtrArray& entitySet) const;
        //夹点状态
        virtual void gripStatus(const AcDb::GripStat status);
        //实体绘制
        virtual Adesk::Boolean worldDraw(AcGiWorldDraw* pWd);
        //捕捉点
        virtual Acad::ErrorStatus getOsnapPoints(AcDb::OsnapMode osnapMode, Adesk::GsMarker gsSelectionMark, const AcGePoint3d& pickPoint, const AcGePoint3d& lastPoint,
                const AcGeMatrix3d& viewXform, AcGePoint3dArray& snapPoints, AcDbIntArray & geomIds) const;
        //外包矩形
        virtual Acad::ErrorStatus getGeomExtents(AcDbExtents& extents) const;
        //删除
        virtual        Acad::ErrorStatus erase(Adesk::Boolean erasing = true);

二、成员变量
因为这个自定义实体是矩形,所以是由四个直线组成,且由三个夹点。

        AcDbLine m_lineHori1;
        AcDbLine m_lineHori2;
        AcDbLine m_lineVert1;
        AcDbLine m_lineVert2;

        AcGePoint3d m_ptBase;               
        AcGePoint3d m_ptRight;       
        AcGePoint3d m_ptTop;

所以在写重载函数时,每个直线实体都要写一下。例如在worldDraw函数:

Adesk::Boolean CDiBanCsm::worldDraw(AcGiWorldDraw* pWd)
{
        assertReadEnabled();
        m_lineHori1.worldDraw(pWd);
        m_lineHori2.worldDraw(pWd);
        m_lineVert1.worldDraw(pWd);
        m_lineVert2.worldDraw(pWd);
        return Adesk::kTrue;
}

因为有夹点这个成员变量,所以,在dwgInFields函数、dwgOutFields函数、transformBy函数中也要将夹点添加进去:

Acad::ErrorStatus CDiBanCsm::dwgInFields(AcDbDwgFiler* pFiler)
{
        assertWriteEnabled();
        AcDbEntity::dwgInFields(pFiler);

        m_lineHori1.dwgInFields(pFiler);
        m_lineHori2.dwgInFields(pFiler);
        m_lineVert1.dwgInFields(pFiler);
        m_lineVert2.dwgInFields(pFiler);
       
        pFiler->readPoint3d(&m_ptBase);
        pFiler->readPoint3d(&m_ptRight);
        pFiler->readPoint3d(&m_ptTop);

        return pFiler->filerStatus();
}

三、夹点绘制
绘制夹点比较麻烦,如果你不是要绘制夹点的形状,可以重载

Acad::ErrorStatus getGripPoints(
    AcGePoint3dArray& gripPoints,
    AcDbIntArray & osnapModes,
    AcDbIntArray & geomIds
) const;

只需要在gripPoints参数中添加夹点坐标就可以,夹点为默认夹点。
这里,我们需要改变夹点的形状,所以这里我们需要绘制夹点。夹点用AcDbGripData类绘制,它是new出来的,所以我们需要将它delete。
我们需要重载gripStatus函数,在AcDb::kGripsDone状态下,将new的AcDbGripData指针delte。
我们要声明一个全局的map变量来存放AcDbGripData指针:

//键:自定义实体指针                值:AcDbGripData指针数组
static std::map<const AcDbEntity*, AcDbGripDataPtrArray> s_mapGripPtr;

直接上代码了:

Acad::ErrorStatus CDiBanCsm::getGripPoints(AcDbGripDataPtrArray& grips, const double curViewUnitSize,
        const int gripSize, const AcGeVector3d& curViewDir, const int bitflags) const
{
        assertReadEnabled();
        std::vector<CString>::const_iterator appIter = GetGripName();//这里appIter是一个字符串容器,存放的是夹点名称
        AcDbGripDataPtrArray tempGripArr;

        //BasePt
        AcDbGripData* pGripBase = new AcDbGripData();
        pGripBase->setAppData((void*)&(*appIter));//将夹点名称设置到数据中
        pGripBase->setGripPoint(m_ptBase);//设置夹点坐标
        grips.append(pGripBase);
        tempGripArr.append(pGripBase);
        appIter++;

        //RightPt
        AcDbGripData* pGripRight = new AcDbGripData();
        pGripRight->setAppData((void*)&(*appIter));
        pGripRight->setGripPoint(m_ptRight);
        pGripRight->setWorldDraw(DrawStretchGrip);
        grips.append(pGripRight);
        tempGripArr.append(pGripRight);
        appIter++;

        //TopPt
        AcDbGripData* pGripTop = new AcDbGripData();
        pGripTop->setAppData((void*)&(*appIter));
        pGripTop->setGripPoint(m_ptTop);
        pGripTop->setWorldDraw(DrawStretchGrip);
        grips.append(pGripTop);
        tempGripArr.append(pGripTop);
        appIter++;

        auto a = this;
        CCustomBase::s_mapGripPtr[this] = tempGripArr;//将new出来的AcDbGripData指针添加到s_mapGripPtr变量中
        return Acad::eOk;
}

bool CDiBanCsm::DrawStretchGrip(AcDbGripData *pThis, AcGiWorldDraw *pWd, const AcDbObjectId& entId, AcDbGripOperations::DrawType type, AcGePoint3d *cursor, double dGripSize)
{
        dGripSize *= CCustomBase::s_gripSize / 2;//夹点的大小 CCustomBase::s_gripSize == 2.8
        AcGePoint3d        pt = pThis->gripPoint();
        CString* pStr = (CString*)(pThis->appData());
        AcGeVector3d vec = AcGeVector3d::kXAxis;
        AcDbObjectPointer<CDiBanCsm> m_pDiBan(entId, AcDb::kForRead);
        if (m_pDiBan.openStatus() != Acad::eOk)
                return false;

        if (*pStr == _T("RightPt"))
                vec = m_pDiBan->GetHoriDirection().normal();//得到实体的水平向量,这个接口自己写,通过直线的两点坐标
        else if (*pStr == _T("TopPt"))
                vec = m_pDiBan->GetVertDirection().normal();//得到实体的垂直向量

        auto vecUp = AcGeVector3d::kZAxis.crossProduct(vec).normal();
        AcGePoint3d pts[3];
        pts[0] = pt + vec * dGripSize;
        pts[1] = pt - vec * dGripSize / 2 + vecUp * dGripSize * .7;
        pts[2] = pt - vec * dGripSize / 2 - vecUp * dGripSize * .7;

        pWd->subEntityTraits().setFillType(kAcGiFillAlways);
        pWd->geometry().polygon(3, pts);

        return true;
}


在重载的gripStatus函数中delete夹点指针

void CDiBanCsm::gripStatus(const AcDb::GripStat status)
{
        AcDbEntity::gripStatus(status);

        switch (status)
        {
        case AcDb::kGripsDone:
                CCustomBase::DeleteGrip(this);
                break;
        case AcDb::kGripsToBeDeleted:
               
                break;
        case AcDb::kDimDataToBeDeleted:

                break;
        }
}

bool CCustomBase::DeleteGrip(const AcDbEntity* pEnt)
{
        std::map<const AcDbEntity*, AcDbGripDataPtrArray>::iterator iter;
        for (iter = s_mapGripPtr.begin(); iter != s_mapGripPtr.end(); iter++)
        {
                if (pEnt == iter->first)
                {
                        AcDbGripDataPtrArray tempGripArr = iter->second;
                        for (int i = 0; i < tempGripArr.length(); ++i)
                        {
                                DEL(tempGripArr[i]);//这里delete 指针
                                tempGripArr[i] = NULL;
                        }
                }
        }
        int n = CCustomBase::s_mapGripPtr.erase(pEnt);//如果删除了会返回1,否则返回0  
        return n;
}


移动夹点就比较简单了,重写moveGripPointsAt函数就可以了

Acad::ErrorStatus CDiBanCsm::moveGripPointsAt(const AcDbVoidPtrArray& gripAppData,const AcGeVector3d& offset,
const int bitflags)
{
        assertWriteEnabled();
        CString* pStrTemp = NULL;
        for (int i = 0; i < gripAppData.length(); i++)
        {
                pStrTemp = static_cast<CString*>(gripAppData[i]);
                if (*pStrTemp == _T("BasePt"))//通过点的名称,判断移动的是哪个夹点
                {
                        //这里我是通过偏移向量,来移动直线的两点位置
                        SetLinePoint(m_lineHori1, 3, offset);
                        SetLinePoint(m_lineHori2, 3, offset);
                        SetLinePoint(m_lineVert1, 3, offset);
                        SetLinePoint(m_lineVert2, 3, offset);
                        m_ptBase = GetBaseGripPt();//重新定义夹点的位置
                        m_ptRight = GetRightGripPt();
                        m_ptTop = GetTopGripPt();
                }
                else if (*pStrTemp == _T("RightPt"))
                {
                        AcGePoint3d ptStart = m_lineHori2.startPoint();
                        AcGePoint3d ptEnd = m_lineHori2.endPoint();
                        AcGeVector3d vctHori = ptEnd - ptStart;
                        AcGeVector3d vctOffset = GetProjectVector(m_ptBase, offset, vctHori);
                        SetLinePoint(m_lineHori1,2,vctOffset);
                        SetLinePoint(m_lineHori2, 2, vctOffset);
                        SetLinePoint(m_lineVert2, 3, vctOffset);
                        m_ptBase = GetBaseGripPt();
                        m_ptRight = GetRightGripPt();
                        m_ptTop = GetTopGripPt();
                }
                else if (*pStrTemp == _T("TopPt"))
                {
                        AcGePoint3d ptStart = m_lineVert1.startPoint();
                        AcGePoint3d ptEnd = m_lineVert1.endPoint();
                        AcGeVector3d vctHori = ptEnd - ptStart;
                        AcGeVector3d vctOffset = GetProjectVector(m_ptBase, offset, vctHori);
                        SetLinePoint(m_lineVert1, 2, vctOffset);
                        SetLinePoint(m_lineVert2, 2, vctOffset);
                        SetLinePoint(m_lineHori1, 3, vctOffset);
                        m_ptBase = GetBaseGripPt();
                        m_ptRight = GetRightGripPt();
                        m_ptTop = GetTopGripPt();
                }
        }
        return Acad::eOk;
}

AcGeVector3d CCustomBase::GetProjectVector(const AcGePoint3d& ptBase, const AcGeVector3d& vctOffset, const AcGeVector3d& vctDirection)
{//得到某一向量在指定向量上的投影向量
        AcGePoint3d ptOffset = ptBase + vctOffset;
        AcGeLine3d geLine(ptBase, vctDirection);
        AcGePoint3d ptTarget = geLine.closestPointTo(ptOffset);
        return ptTarget - ptBase;
}



四、实体分解
需要重写explode函数,这里有两个知识要说,一个是如果自定义实体可以分解,需要添加克隆的直线指针

Acad::ErrorStatus CDiBanCsm::explode(ZcDbVoidPtrArray& entitySet) const
{
        assertReadEnabled();
        entitySet.append(m_lineHori1.clone());
        entitySet.append(m_lineHori2.clone());
        entitySet.append(m_lineVert1.clone());
        entitySet.append(m_lineVert2.clone());
        return Acad::eOk;
}

如果你想让自定义实体不能分解,返回值返回:Acad::eCannotExplodeEntity即可。

五、总结
其实原本的代码比这个多很多,这里我只是截取了重要部分展示。这是目前绘制的自定义实体,某些地方还需要改进。

六、源码展示
这篇文章本来是已经删掉的,因为我觉得自己写的这个自定义实体比较垃圾,但是删掉后发现别人还是能看,也能收到评论,就感觉许多人都有这个自定义实体这个需求的,今天准备把源码贴出来。在这里我要简单说明一下,这篇文章是当初学习ObjectArx自定义实体时写的,例子也是当时写的。主要功能实现是做了一个矩形自定义实体,这个实体选中后会显示三个夹点,实体位置夹点、向上拉伸夹点、向右拉伸夹点,且具有移动和拉伸功能。当时测试过,应该是没什么问题的,如果有问题的话也不要@我了。总共2个类,4个文件。

CCustomBase.h

#pragma once

/*
//自定义实体初始化
CDiBanCsm::rxInit();
acrxBuildClassHierarchy();
//自定义实体删除
deleteAcRxClass(CDiBanCsm::desc());
*/

//自定义实体基类
class CCustomBase :public AcDbEntity
{
public:
        CCustomBase();
        ~CCustomBase();

        virtual Adesk::Boolean worldDraw(AcGiWorldDraw* pWd);
        virtual Acad::ErrorStatus dwgInFields(AcDbDwgFiler* pFiler);
        virtual Acad::ErrorStatus dwgOutFields(AcDbDwgFiler* pFiler) const;
        virtual Acad::ErrorStatus dxfInFields(AcDbDxfFiler* pFiler);
        virtual Acad::ErrorStatus dxfOutFields(AcDbDxfFiler* pFiler) const;
        virtual Acad::ErrorStatus getOsnapPoints(AcDb::OsnapMode osnapMode, Adesk::GsMarker gsSelectionMark, const AcGePoint3d& pickPoint, const AcGePoint3d& lastPoint,
                const AcGeMatrix3d& viewXform, AcGePoint3dArray& snapPoints, AcDbIntArray & geomIds) const;
        virtual Acad::ErrorStatus getGeomExtents(AcDbExtents& extents) const;
        virtual Acad::ErrorStatus transformBy(const AcGeMatrix3d& xform);
        virtual Acad::ErrorStatus getTransformedCopy(const AcGeMatrix3d& xform, AcDbEntity*& ent) const;
        virtual        Acad::ErrorStatus erase(Adesk::Boolean erasing = true);

protected:
#pragma region 辅助函数
        std::vector<CString>::const_iterator GetGripName() const;//记录夹点的名称

        //************************************
        // Summary:         得到X轴或Y轴偏移点后的点坐标
        // Parameters:        
        //    ptBase                -         输入要偏移的点坐标
        //    dX                -         输入X轴偏移距离
        //    dY                -         输入Y轴偏移距离
        // Returns:          
        //************************************
        AcGePoint3d GetOffsetPt(const AcGePoint3d& ptBase, double dX, double dY);

        //************************************
        // Summary:         得到某一向量在指定向量上的投影向量
        // Parameters:        
        //    ptBase                -         输入两个向量的交点
        //    vctOffset                -         输入某一向量
        //    vctDirection                -         输入指定向量
        // Returns:          
        //************************************
        AcGeVector3d GetProjectVector(const AcGePoint3d& ptBase, const AcGeVector3d& vctOffset, const AcGeVector3d& vctDirection);
       
        //************************************
        // Summary:         通过偏移向量移动直线的点坐标
        // Parameters:        
        //    pLine                -         输入直线指针
        //    nType                -         输入类型(1:移动起点,2:移动终点,3:都移动)
        //    vctOffset                -         输入偏移向量
        // Returns:          
        //************************************
        void SetLinePoint(AcDbLine& line, int nType, const AcGeVector3d& vctOffset);//设置直线偏移点
       
#pragma endregion 辅助函数

#pragma region 夹点
public:
        static double s_gripSize;        //夹点的大小
        static std::map<const AcDbEntity*, AcDbGripDataPtrArray> s_mapGripPtr;

        //delete夹点
        static bool DeleteGrip(const AcDbEntity* pEnt);
#pragma endregion 夹点

protected:
        AcArray<AcDbEntity*> m_arrEntPtr;
        std::vector<CString> m_vecGripName;
};



CCustomBase.cpp

#include "StdAfx.h"
#include "CCustomBase.h"
#include <strsafe.h>

double CCustomBase::s_gripSize = 2.8;
std::map<const AcDbEntity*, AcDbGripDataPtrArray> CCustomBase::s_mapGripPtr;

CCustomBase::CCustomBase()
{
}


CCustomBase::~CCustomBase()
{
}

Adesk::Boolean CCustomBase::worldDraw(AcGiWorldDraw* pWd)
{
        assertReadEnabled();
        for (int i = 0; i < m_arrEntPtr.length(); ++i)
        {
                m_arrEntPtr[i]->worldDraw(pWd);
        }
        return Adesk::kTrue;
}

Acad::ErrorStatus CCustomBase::dwgInFields(AcDbDwgFiler* pFiler)
{
        //读取数据
        assertWriteEnabled();
        AcDbEntity::dwgInFields(pFiler);
        for (int i = 0; i < m_arrEntPtr.length(); ++i)
        {
                m_arrEntPtr[i]->dwgInFields(pFiler);
        }
        return pFiler->filerStatus();
}

Acad::ErrorStatus CCustomBase::dwgOutFields(AcDbDwgFiler* pFiler) const
{
        //存入数据
        assertReadEnabled();
        AcDbEntity::dwgOutFields(pFiler);
        for (int i = 0; i < m_arrEntPtr.length(); ++i)
        {
                m_arrEntPtr[i]->dwgOutFields(pFiler);
        }
        return pFiler->filerStatus();
}

Acad::ErrorStatus CCustomBase::dxfInFields(AcDbDxfFiler* pFiler)
{
        return Acad::eNotImplementedYet;
}

Acad::ErrorStatus CCustomBase::dxfOutFields(AcDbDxfFiler* pFiler) const
{
        return Acad::eNotImplementedYet;
}

Acad::ErrorStatus CCustomBase::getOsnapPoints(AcDb::OsnapMode osnapMode, Adesk::GsMarker gsSelectionMark, const AcGePoint3d& pickPoint, const AcGePoint3d& lastPoint, const AcGeMatrix3d& viewXform, AcGePoint3dArray& snapPoints, AcDbIntArray & geomIds) const
{
        assertReadEnabled();
        for (int i = 0; i < m_arrEntPtr.length(); ++i)
        {
                m_arrEntPtr[i]->getOsnapPoints(osnapMode, gsSelectionMark, pickPoint, lastPoint, viewXform, snapPoints, geomIds);
        }
        return Acad::eOk;
}

Acad::ErrorStatus CCustomBase::getGeomExtents(AcDbExtents& extents) const
{
        assertReadEnabled();
        for (int i = 0; i < m_arrEntPtr.length(); ++i)
        {
                AcDbExtents ext;
                m_arrEntPtr[i]->getGeomExtents(ext);
                extents.addExt(ext);
        }
        return Acad::eOk;
}

Acad::ErrorStatus CCustomBase::transformBy(const AcGeMatrix3d& xform)
{
        assertWriteEnabled();
       
        for (int i = 0; i < m_arrEntPtr.length(); ++i)
        {
                m_arrEntPtr[i]->transformBy(xform);
        }
        return AcDbEntity::transformBy(xform);
}

Acad::ErrorStatus CCustomBase::getTransformedCopy(const AcGeMatrix3d& xform, AcDbEntity*& ent) const
{
        assertReadEnabled();
        for (int i = 0; i < m_arrEntPtr.length(); ++i)
        {
                m_arrEntPtr[i]->getTransformedCopy(xform, ent);
        }
        return AcDbEntity::getTransformedCopy(xform, ent);
}

Acad::ErrorStatus CCustomBase::erase(Adesk::Boolean erasing /*= true*/)
{
        assertWriteEnabled();
        for (int i = 0; i < m_arrEntPtr.length(); ++i)
        {
                m_arrEntPtr[i]->erase(erasing);
        }
        return Acad::eOk;
}

std::vector<CString>::const_iterator CCustomBase::GetGripName() const
{
        return m_vecGripName.begin();
}

AcGePoint3d CCustomBase::GetOffsetPt(const AcGePoint3d& ptBase, double dX, double dY)
{
        AcGePoint3d ptTemp = ptBase;
        ptTemp.x += dX;
        ptTemp.y += dY;
        return ptTemp;
}

AcGeVector3d CCustomBase::GetProjectVector(const AcGePoint3d& ptBase, const AcGeVector3d& vctOffset, const AcGeVector3d& vctDirection)
{
        AcGePoint3d ptOffset = ptBase + vctOffset;
        AcGeLine3d geLine(ptBase, vctDirection);
        AcGePoint3d ptTarget = geLine.closestPointTo(ptOffset);
        return ptTarget - ptBase;
}

void CCustomBase::SetLinePoint(AcDbLine& line, int nType, const AcGeVector3d& vctOffset)
{
        AcGePoint3d ptStart = line.startPoint();
        AcGePoint3d ptEnd = line.endPoint();
        switch (nType)
        {
        case 1://移动起点
                ptStart += vctOffset;
                line.setStartPoint(ptStart);
                break;
        case 2://移动终点
                ptEnd += vctOffset;
                line.setEndPoint(ptEnd);
                break;
        case 3://移动起点和终点
                ptStart += vctOffset;
                line.setStartPoint(ptStart);
                ptEnd += vctOffset;
                line.setEndPoint(ptEnd);
                break;
        default:
                break;
        }
}

bool CCustomBase::DeleteGrip(const AcDbEntity* pEnt)
{
        std::map<const AcDbEntity*, AcDbGripDataPtrArray>::iterator iter;
        for (iter = s_mapGripPtr.begin(); iter != s_mapGripPtr.end(); iter++)
        {
                if (pEnt == iter->first)
                {
                        AcDbGripDataPtrArray tempGripArr = iter->second;
                        for (int i = 0; i < tempGripArr.length(); ++i)
                        {
                                AcDbGripData* pGrip = tempGripArr[i];
                                DEL(tempGripArr[i]);
                                tempGripArr[i] = NULL;
                        }
                }
        }
        int n = CCustomBase::s_mapGripPtr.erase(pEnt);//如果删除了会返回1,否则返回0  
        return n;
}


CDiBanCsm.h

#pragma once
#include "CCustomBase.h"

//底板
class CDiBanCsm :public CCustomBase
{
public:
        ACRX_DECLARE_MEMBERS(CDiBanCsm);

        CDiBanCsm();
        CDiBanCsm(const AcGePoint3d& ptBase,double dLength,double dWidth);
        CDiBanCsm(const CDiBanCsm& obj);//拷贝构造函数
        ~CDiBanCsm();

#pragma region 重载函数
        virtual Acad::ErrorStatus getGripPoints(AcDbGripDataPtrArray& grips, const double curViewUnitSize, const int gripSize, const AcGeVector3d& curViewDir, const int bitflags) const;
        virtual Acad::ErrorStatus moveGripPointsAt(const AcDbVoidPtrArray& gripAppData,const AcGeVector3d& offset,const int bitflags);
        virtual Acad::ErrorStatus dwgInFields(AcDbDwgFiler* pFiler);//加载
        virtual Acad::ErrorStatus dwgOutFields(AcDbDwgFiler* pFiler) const;//保存
        virtual Acad::ErrorStatus transformBy(const AcGeMatrix3d& xform);
        virtual Acad::ErrorStatus explode(ZcDbVoidPtrArray& entitySet) const;
        virtual void gripStatus(const AcDb::GripStat status);

        virtual Adesk::Boolean worldDraw(AcGiWorldDraw* pWd);//绘制
        virtual Acad::ErrorStatus dxfInFields(AcDbDxfFiler* pFiler);
        virtual Acad::ErrorStatus dxfOutFields(AcDbDxfFiler* pFiler) const;
        virtual Acad::ErrorStatus getOsnapPoints(AcDb::OsnapMode osnapMode, Adesk::GsMarker gsSelectionMark, const AcGePoint3d& pickPoint, const AcGePoint3d& lastPoint,
                const AcGeMatrix3d& viewXform, AcGePoint3dArray& snapPoints, AcDbIntArray & geomIds) const;
        virtual Acad::ErrorStatus getGeomExtents(AcDbExtents& extents) const;
        virtual Acad::ErrorStatus getTransformedCopy(const AcGeMatrix3d& xform, AcDbEntity*& ent) const;
        virtual        Acad::ErrorStatus erase(Adesk::Boolean erasing = true);
       
#pragma endregion 重载函数

#pragma region 接口
        bool SetPosition(const AcGePoint3d& pt);//设置基点位置
        bool SetRotation(double dAngle);//设置旋转角度
        AcGeVector3d GetHoriDirection() const;//得到水平向量
        AcGeVector3d GetVertDirection() const;//得到垂直向量
#pragma endregion 接口

#pragma region 辅助函数
protected:
        //得到夹点坐标
        AcGePoint3d GetBaseGripPt() const;
        AcGePoint3d GetRightGripPt() const;
        AcGePoint3d GetTopGripPt() const;
#pragma endregion 辅助函数

#pragma region 夹点
public:
        //拉伸夹点
        static bool DrawStretchGrip(AcDbGripData *pThis, AcGiWorldDraw *pWd, const AcDbObjectId& entId, AcDbGripOperations::DrawType type, AcGePoint3d *cursor, double dGripSize);
        //转换夹点
        static bool DrawSwitchGrip(AcDbGripData *pThis, AcGiWorldDraw *pWd, const AcDbObjectId& entId, AcDbGripOperations::DrawType type, AcGePoint3d *cursor, double dGripSize);
        //枚举夹点
        static bool DrawEnumGrip(AcDbGripData *pThis, AcGiWorldDraw *pWd, const AcDbObjectId& entId, AcDbGripOperations::DrawType type, AcGePoint3d *cursor, double dGripSize);
#pragma endregion 夹点

protected:
        AcDbLine m_lineHori1;
        AcDbLine m_lineHori2;
        AcDbLine m_lineVert1;
        AcDbLine m_lineVert2;

        AcGePoint3d m_ptBase;       
        AcGePoint3d m_ptRight;       
        AcGePoint3d m_ptTop;
        double m_dLength;
        double m_dWidth;

};




CDiBanCsm.cpp

#include "StdAfx.h"
#include "CDiBanCsm.h"


ACRX_DXF_DEFINE_MEMBERS(CDiBanCsm, AcDbEntity, AcDb::kDHL_CURRENT, AcDb::kMReleaseCurrent,
        AcDbProxyEntity::kNoOperation, CDiBanCsm, ZwCad);


CDiBanCsm::CDiBanCsm()
{
        m_arrEntPtr.append(&m_lineHori1);
        m_arrEntPtr.append(&m_lineHori2);
        m_arrEntPtr.append(&m_lineVert1);
        m_arrEntPtr.append(&m_lineVert2);

        m_vecGripName.clear();
        m_vecGripName.push_back(_T("BasePt"));
        m_vecGripName.push_back(_T("RightPt"));
        m_vecGripName.push_back(_T("TopPt"));
}


CDiBanCsm::CDiBanCsm(const AcGePoint3d& ptBase, double dLength, double dWidth)
        :m_ptBase(ptBase),m_dLength(dLength),m_dWidth(dWidth)
{
        //实体初始化
        m_ptRight = GetOffsetPt(m_ptBase, m_dLength, m_dWidth / 2);
        m_ptTop = GetOffsetPt(m_ptBase, m_dLength / 2, m_dWidth);

        m_lineHori1.setStartPoint(GetOffsetPt(m_ptBase,0, m_dWidth));
        m_lineHori1.setEndPoint(GetOffsetPt(m_ptBase, m_dLength, m_dWidth));

        m_lineHori2.setStartPoint(m_ptBase);
        m_lineHori2.setEndPoint(GetOffsetPt(m_ptBase, m_dLength, 0));

        m_lineVert1.setStartPoint(m_ptBase);
        m_lineVert1.setEndPoint(GetOffsetPt(m_ptBase, 0, m_dWidth));

        m_lineVert2.setStartPoint(GetOffsetPt(m_ptBase, m_dLength, 0));
        m_lineVert2.setEndPoint(GetOffsetPt(m_ptBase, m_dLength, m_dWidth));
        //添加实体指针,用于调用基类
        m_arrEntPtr.append(&m_lineHori1);
        m_arrEntPtr.append(&m_lineHori2);
        m_arrEntPtr.append(&m_lineVert1);
        m_arrEntPtr.append(&m_lineVert2);
       
        //添加夹点类型
        m_vecGripName.clear();
        m_vecGripName.push_back(_T("BasePt"));
        m_vecGripName.push_back(_T("RightPt"));
        m_vecGripName.push_back(_T("TopPt"));
}

CDiBanCsm::CDiBanCsm(const CDiBanCsm& obj)
{
        m_lineHori1.setStartPoint(obj.m_lineHori1.startPoint());
        m_lineHori1.setEndPoint(obj.m_lineHori1.endPoint());

        m_lineHori2.setStartPoint(obj.m_lineHori2.startPoint());
        m_lineHori2.setEndPoint(obj.m_lineHori2.endPoint());

        m_lineVert1.setStartPoint(obj.m_lineVert1.startPoint());
        m_lineVert1.setEndPoint(obj.m_lineVert1.endPoint());

        m_lineVert2.setStartPoint(obj.m_lineVert2.startPoint());
        m_lineVert2.setEndPoint(obj.m_lineVert2.endPoint());

        m_ptBase = obj.m_ptBase;
        m_ptRight = obj.m_ptRight;
        m_ptTop = obj.m_ptTop;
        m_dLength = obj.m_dLength;
        m_dWidth = obj.m_dWidth;

        //添加实体指针,用于调用基类
        m_arrEntPtr.append(&m_lineHori1);
        m_arrEntPtr.append(&m_lineHori2);
        m_arrEntPtr.append(&m_lineVert1);
        m_arrEntPtr.append(&m_lineVert2);
        //添加夹点类型
        m_vecGripName.clear();
        m_vecGripName.push_back(_T("BasePt"));
        m_vecGripName.push_back(_T("RightPt"));
        m_vecGripName.push_back(_T("TopPt"));
}

CDiBanCsm::~CDiBanCsm()
{
}

Adesk::Boolean CDiBanCsm::worldDraw(AcGiWorldDraw* pWd)
{
        assertReadEnabled();
        return CCustomBase::worldDraw(pWd);
}

Acad::ErrorStatus CDiBanCsm::dwgInFields(AcDbDwgFiler* pFiler)
{//读取数据
        assertWriteEnabled();
        CCustomBase::dwgInFields(pFiler);
        pFiler->readPoint3d(&m_ptBase);
        pFiler->readPoint3d(&m_ptRight);
        pFiler->readPoint3d(&m_ptTop);

        return pFiler->filerStatus();
}

Acad::ErrorStatus CDiBanCsm::dwgOutFields(AcDbDwgFiler* pFiler) const
{//存入数据
        assertReadEnabled();
        CCustomBase::dwgOutFields(pFiler);
        pFiler->writePoint3d(m_ptBase);
        pFiler->writePoint3d(m_ptRight);
        pFiler->writePoint3d(m_ptTop);

        return pFiler->filerStatus();
}

Acad::ErrorStatus CDiBanCsm::dxfInFields(AcDbDxfFiler* pFiler)
{
        return Acad::eNotImplementedYet;
}

Acad::ErrorStatus CDiBanCsm::dxfOutFields(AcDbDxfFiler* pFiler) const
{
        return Acad::eNotImplementedYet;
}

Acad::ErrorStatus CDiBanCsm::getGripPoints(AcDbGripDataPtrArray& grips, const double curViewUnitSize,
        const int gripSize, const AcGeVector3d& curViewDir, const int bitflags) const
{
        assertReadEnabled();
        std::vector<CString>::const_iterator appIter = GetGripName();
        AcDbGripDataPtrArray tempGripArr;

        //BasePt
        AcDbGripData* pGripBase = new AcDbGripData();
        pGripBase->setAppData((void*)&(*appIter));
        pGripBase->setGripPoint(m_ptBase);
        grips.append(pGripBase);
        tempGripArr.append(pGripBase);
        appIter++;

        //RightPt
        AcDbGripData* pGripRight = new AcDbGripData();
        pGripRight->setAppData((void*)&(*appIter));
        pGripRight->setGripPoint(m_ptRight);
        pGripRight->setWorldDraw(DrawStretchGrip);
        grips.append(pGripRight);
        tempGripArr.append(pGripRight);
        appIter++;

        //TopPt
        AcDbGripData* pGripTop = new AcDbGripData();
        pGripTop->setAppData((void*)&(*appIter));
        pGripTop->setGripPoint(m_ptTop);
        pGripTop->setWorldDraw(DrawStretchGrip);
        grips.append(pGripTop);
        tempGripArr.append(pGripTop);
        appIter++;

        auto a = this;
        CCustomBase::s_mapGripPtr[this] = tempGripArr;
        return Acad::eOk;
}

Acad::ErrorStatus CDiBanCsm::moveGripPointsAt(const AcDbVoidPtrArray& gripAppData,const AcGeVector3d& offset,
const int bitflags)
{
        assertWriteEnabled();
        CString* pStrTemp = NULL;
        for (int i = 0; i < gripAppData.length(); i++)
        {
                pStrTemp = static_cast<CString*>(gripAppData[i]);
                if (*pStrTemp == _T("BasePt"))
                {
                        SetLinePoint(m_lineHori1, 3, offset);
                        SetLinePoint(m_lineHori2, 3, offset);
                        SetLinePoint(m_lineVert1, 3, offset);
                        SetLinePoint(m_lineVert2, 3, offset);
                        m_ptBase = GetBaseGripPt();
                        m_ptRight = GetRightGripPt();
                        m_ptTop = GetTopGripPt();
                }
                else if (*pStrTemp == _T("RightPt"))
                {
                        AcGePoint3d ptStart = m_lineHori2.startPoint();
                        AcGePoint3d ptEnd = m_lineHori2.endPoint();
                        AcGeVector3d vctHori = ptEnd - ptStart;
                        AcGeVector3d vctOffset = GetProjectVector(m_ptBase, offset, vctHori);
                        SetLinePoint(m_lineHori1,2,vctOffset);
                        SetLinePoint(m_lineHori2, 2, vctOffset);
                        SetLinePoint(m_lineVert2, 3, vctOffset);
                        m_ptBase = GetBaseGripPt();
                        m_ptRight = GetRightGripPt();
                        m_ptTop = GetTopGripPt();
                }
                else if (*pStrTemp == _T("TopPt"))
                {
                        AcGePoint3d ptStart = m_lineVert1.startPoint();
                        AcGePoint3d ptEnd = m_lineVert1.endPoint();
                        AcGeVector3d vctHori = ptEnd - ptStart;
                        AcGeVector3d vctOffset = GetProjectVector(m_ptBase, offset, vctHori);
                        SetLinePoint(m_lineVert1, 2, vctOffset);
                        SetLinePoint(m_lineVert2, 2, vctOffset);
                        SetLinePoint(m_lineHori1, 3, vctOffset);
                        m_ptBase = GetBaseGripPt();
                        m_ptRight = GetRightGripPt();
                        m_ptTop = GetTopGripPt();
                }
        }
        return Acad::eOk;
}

Acad::ErrorStatus CDiBanCsm::getOsnapPoints(AcDb::OsnapMode osnapMode, Adesk::GsMarker gsSelectionMark,
        const AcGePoint3d& pickPoint, const AcGePoint3d& lastPoint, const AcGeMatrix3d& viewXform,
        AcGePoint3dArray& snapPoints, AcDbIntArray & geomIds) const
{
        assertReadEnabled();
        return CCustomBase::getOsnapPoints(osnapMode, gsSelectionMark, pickPoint, lastPoint, viewXform,
                snapPoints, geomIds);
}

Acad::ErrorStatus CDiBanCsm::getGeomExtents(AcDbExtents& extents) const
{
        assertReadEnabled();
        return CCustomBase::getGeomExtents(extents);
}

Acad::ErrorStatus CDiBanCsm::transformBy(const AcGeMatrix3d& xform)
{
        assertWriteEnabled();
        m_ptBase.transformBy(xform);
        m_ptRight.transformBy(xform);
        m_ptTop.transformBy(xform);

        return CCustomBase::transformBy(xform);
}

Acad::ErrorStatus CDiBanCsm::getTransformedCopy(const AcGeMatrix3d& xform, AcDbEntity*& ent) const
{
        assertReadEnabled();
        return CCustomBase::getTransformedCopy(xform, ent);
}

Acad::ErrorStatus CDiBanCsm::explode(ZcDbVoidPtrArray& entitySet) const
{
        assertReadEnabled();
//         entitySet.append(m_lineHori1.clone());
//         entitySet.append(m_lineHori2.clone());
//         entitySet.append(m_lineVert1.clone());
//         entitySet.append(m_lineVert2.clone());
        return Acad::eCannotExplodeEntity;
}

Acad::ErrorStatus CDiBanCsm::erase(Adesk::Boolean erasing /*= true*/)
{
        assertWriteEnabled();
        return CCustomBase::erase(erasing);
}

bool CDiBanCsm::SetPosition(const AcGePoint3d& pt)
{
        assertWriteEnabled();
        AcGeVector3d offset = pt - m_ptBase;
        SetLinePoint(m_lineHori1, 3, offset);
        SetLinePoint(m_lineHori2, 3, offset);
        SetLinePoint(m_lineVert1, 3, offset);
        SetLinePoint(m_lineVert2, 3, offset);
        m_ptBase = GetBaseGripPt();
        m_ptRight = GetRightGripPt();
        m_ptTop = GetTopGripPt();
        return true;
}

bool CDiBanCsm::SetRotation(double dAngle)
{
        assertWriteEnabled();
        m_lineHori1.setStartPoint(GetOffsetPt(m_ptBase, 0, m_dWidth).rotateBy(dAngle,AcGeVector3d::kZAxis,m_ptBase));
        m_lineHori1.setEndPoint(GetOffsetPt(m_ptBase, m_dLength, m_dWidth).rotateBy(dAngle, AcGeVector3d::kZAxis, m_ptBase));
        m_lineHori2.setEndPoint(GetOffsetPt(m_ptBase, m_dLength, 0).rotateBy(dAngle, AcGeVector3d::kZAxis, m_ptBase));
        m_lineVert1.setEndPoint(GetOffsetPt(m_ptBase, 0, m_dWidth).rotateBy(dAngle, AcGeVector3d::kZAxis, m_ptBase));
        m_lineVert2.setStartPoint(GetOffsetPt(m_ptBase, m_dLength, 0).rotateBy(dAngle, AcGeVector3d::kZAxis, m_ptBase));
        m_lineVert2.setEndPoint(GetOffsetPt(m_ptBase, m_dLength, m_dWidth).rotateBy(dAngle, AcGeVector3d::kZAxis, m_ptBase));
        m_ptBase = GetBaseGripPt();
        m_ptRight = GetRightGripPt();
        m_ptTop = GetTopGripPt();
        return true;
}

AcGeVector3d CDiBanCsm::GetHoriDirection() const
{
        AcGePoint3d ptStart = m_lineHori2.startPoint();
        AcGePoint3d ptEnd = m_lineHori2.endPoint();
        return ptEnd - ptStart;
}

AcGeVector3d CDiBanCsm::GetVertDirection() const
{
        AcGePoint3d ptStart = m_lineVert1.startPoint();
        AcGePoint3d ptEnd = m_lineVert1.endPoint();
        return ptEnd - ptStart;
}

void CDiBanCsm::gripStatus(const AcDb::GripStat status)
{
        AcDbEntity::gripStatus(status);

        switch (status)
        {
        case AcDb::kGripsDone:
                CCustomBase::DeleteGrip(this);
                break;
        case AcDb::kGripsToBeDeleted:
               
                break;
        case AcDb::kDimDataToBeDeleted:

                break;
        }
}

AcGePoint3d CDiBanCsm::GetBaseGripPt() const
{
        return m_lineHori2.startPoint();
}

AcGePoint3d CDiBanCsm::GetRightGripPt() const
{
        AcGePoint3d ptStart = m_lineVert2.startPoint();
        AcGePoint3d ptEnd = m_lineVert2.endPoint();
        return AcGePoint3d((ptStart.x + ptEnd.x)/2,(ptStart.y + ptEnd.y)/2,(ptStart.z + ptEnd.z)/2);
}

AcGePoint3d CDiBanCsm::GetTopGripPt() const
{
        AcGePoint3d ptStart = m_lineHori1.startPoint();
        AcGePoint3d ptEnd = m_lineHori1.endPoint();
        return AcGePoint3d((ptStart.x + ptEnd.x) / 2, (ptStart.y + ptEnd.y) / 2, (ptStart.z + ptEnd.z) / 2);
}

bool CDiBanCsm::DrawStretchGrip(AcDbGripData *pThis, AcGiWorldDraw *pWd, const AcDbObjectId& entId, AcDbGripOperations::DrawType type, AcGePoint3d *cursor, double dGripSize)
{
        dGripSize *= CCustomBase::s_gripSize / 2;
        AcGePoint3d        pt = pThis->gripPoint();
        CString* pStr = (CString*)(pThis->appData());
        AcGeVector3d vec = AcGeVector3d::kXAxis;
        AcDbObjectPointer<CDiBanCsm> m_pDiBan(entId, AcDb::kForRead);
        if (m_pDiBan.openStatus() != Acad::eOk)
                return false;

        if (*pStr == _T("RightPt"))
                vec = m_pDiBan->GetHoriDirection().normal();
        else if (*pStr == _T("TopPt"))
                vec = m_pDiBan->GetVertDirection().normal();

        auto vecUp = AcGeVector3d::kZAxis.crossProduct(vec).normal();
        AcGePoint3d pts[3];
        pts[0] = pt + vec * dGripSize;
        pts[1] = pt - vec * dGripSize / 2 + vecUp * dGripSize * .7;
        pts[2] = pt - vec * dGripSize / 2 - vecUp * dGripSize * .7;

        pWd->subEntityTraits().setFillType(kAcGiFillAlways);
        pWd->geometry().polygon(3, pts);

        return true;
}

bool CDiBanCsm::DrawSwitchGrip(AcDbGripData *pThis, AcGiWorldDraw *pWd, const AcDbObjectId& entId, AcDbGripOperations::DrawType type, AcGePoint3d *cursor, double dGripSize)
{
        dGripSize *= CCustomBase::s_gripSize / 2;
        AcGePoint3d        pt = pThis->gripPoint();
        AcGeVector3d vec = AcGeVector3d::kXAxis;

        auto vecUp = AcGeVector3d::kZAxis.crossProduct(vec).normal();
        AcGePoint3d ptsRec[4];
        ptsRec[0] = pt + vecUp * dGripSize;
        ptsRec[1] = pt + vecUp * dGripSize - vec * dGripSize;
        ptsRec[2] = pt - vecUp * dGripSize - vec * dGripSize;
        ptsRec[3] = pt - vecUp * dGripSize;

        AcGePoint3d ptsArr[3];
        ptsArr[0] = pt + vec * dGripSize * 2.4;
        ptsArr[1] = pt + vec * dGripSize + vecUp * dGripSize;
        ptsArr[2] = pt + vec * dGripSize - vecUp * dGripSize;

        pWd->subEntityTraits().setFillType(kAcGiFillAlways);

        pWd->geometry().polygon(4, ptsRec);
        pWd->geometry().polygon(3, ptsArr);
        return true;
}

bool CDiBanCsm::DrawEnumGrip(AcDbGripData *pThis, AcGiWorldDraw *pWd, const AcDbObjectId& entId, AcDbGripOperations::DrawType type, AcGePoint3d *cursor, double dGripSize)
{
        dGripSize *= CCustomBase::s_gripSize / 2;
        AcGePoint3d        pt = pThis->gripPoint();

        // 中心圆
        pWd->subEntityTraits().setFillType(kAcGiFillAlways);
        pWd->geometry().circle(pt, dGripSize, AcGeVector3d::kZAxis);

        return true;
}
[/code]

 

 

 

 

ObjectARX自定义实体
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|中国膜结构网|中国膜结构协会|进口膜材|国产膜材|ETFE|PVDF|PTFE|设计|施工|安装|车棚|看台|污水池|中国膜结构网_中国空间膜结构协会

GMT+8, 2024-11-1 10:28 , Processed in 0.139574 second(s), 27 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表