关于Jig

cad中的JIG

​ cad中经常会用到jig技术,主要是绘制某些定制实体的时候,有拖动效果,所见即所得,方便控制。在arx的二次开发中,一般是继承一个基类AcEdJig。

//关于这个AcEdJig
class	AcEdImpJig;
class	AcDbEntity;

class AcEdJig: public AcRxObject
{
public:
    ACRX_DECLARE_MEMBERS(AcEdJig);

    typedef enum UserInputControls {
        kGovernedByOrthoMode            = 0x000001,
        kNullResponseAccepted           = 0x000002,
        kDontEchoCancelForCtrlC         = 0x000004,
        kDontUpdateLastPoint            = 0x000008,
        kNoDwgLimitsChecking            = 0x000010,
        kNoZeroResponseAccepted         = 0x000020,
        kNoNegativeResponseAccepted     = 0x000040,
        kAccept3dCoordinates            = 0x000080,
        kAcceptMouseUpAsPoint           = 0x000100,
        kAnyBlankTerminatesInput        = 0x000200,
        kInitialBlankTerminatesInput    = 0x000400,
        kAcceptOtherInputString         = 0x000800,
        kGovernedByUCSDetect            = 0x001000,
        kNoZDirectionOrtho              = 0x002000,
        kImpliedFaceForUCSChange        = 0x004000,
        kUseBasePointElevation          = 0x008000,

        ///<summary> Disables direct distance input. When this flag is ON a
        ///distance input such as integer or real will not be accepted unless
        ///kAcceptOtherInputString is ON, in that case returned DragStatus is
        ///kOther. </summary>
        kDisableDirectDistanceInput     = 0x010000,
    };

    typedef enum DragStatus {
        kModeless       = -17,
        kNoChange       = -6,
        kCancel         = -4,//取消输入,esc键
        kOther          = -3,//其他,比如关键字字符串
        kNull           = -1,//用户按下回车键
        kNormal         = 0,//获取数据成功
        kKW1,//1~9表示对应的最多的九个关键字
        kKW2,
        kKW3,
        kKW4,
        kKW5,
        kKW6,
        kKW7,
        kKW8,
        kKW9
    };

    typedef enum CursorType {
        kNoSpecialCursor = -1,           // No Special Cursor Specified
        kCrosshair = 0,                  // Full Screen Cross Hair. 
        kRectCursor,                     // Rectangular cursor. 
        kRubberBand,                     // Rubber band line. 
        kNotRotated,                     // NotRotated Type. 
        kTargetBox,                      // Target Box Type. 
        kRotatedCrosshair,               // Rotated Crosshair w/ rubber band. 
        kCrosshairNoRotate,              // Crosshairs forced non-rotated. 
        kInvisible,                      // Invisible cursor. 
        kEntitySelect,                   // Entity selection target cursor. 
        kParallelogram,                  // Parallelogram cursor. 
        kEntitySelectNoPersp,            // Pickbox, suppressed in persp. 
        kPkfirstOrGrips,                 // Auto-select cursor. 
        kCrosshairDashed                 // 15 dashed style crosshair cursor

    };
    AcEdJig();
    virtual ~AcEdJig();

    DragStatus	drag();
    virtual DragStatus	sampler(); 
    virtual Adesk::Boolean  update();
    AcDbObjectId append();

    const ACHAR* keywordList();
    void        setKeywordList(const ACHAR*);

    const ACHAR* dispPrompt();
    void        setDispPrompt(const ACHAR*, ...);


    DragStatus acquireString(ACHAR *str);
    DragStatus acquireAngle(double &ang);
    DragStatus acquireAngle(double &ang, const AcGePoint3d& basePnt);
    DragStatus acquireDist(double &dist);
    DragStatus acquireDist(double &dist, const AcGePoint3d& basePnt);
    DragStatus acquirePoint(AcGePoint3d&);
    DragStatus acquirePoint(AcGePoint3d&, const AcGePoint3d&basePnt);

    AcEdJig::CursorType specialCursorType();
    void                setSpecialCursorType(CursorType);

    AcEdJig::UserInputControls userInputControls();
    void                       setUserInputControls(AcEdJig::UserInputControls);

    virtual AcDbEntity* entity() const;
    virtual AcDbDimDataPtrArray * dimData(const double dimScale);
    virtual Acad::ErrorStatus setDimValue(const AcDbDimData* dimData,
                                          const double dimValue); 

private:
    AcEdImpJig*  mpImpJig;
};

在这个类中,有三个Enum

Enum用途
UserInputControls用户输入控制(比如单击鼠标右键,空格等)
DragStatus对用户当前的输入的结果的响应
CursorType在操作的时候,鼠标的形状

那么,继承后的类,一般需要重载下面三个函数

virtual DragStatus	sampler(); //获取一个几何值(表示发生了变化)
virtual Adesk::Boolean  update();//分析并保存获取的值,更新实体
virtual AcDbEntity* entity() const;//返回重构后,实体的指针
  • 首先,可以使用setDispPrompt,建立提示字符串,比如是否旋转,镜像等

  • 在调用drag()函数实现控制拖动循环,并在循环的过程中一次调用sampler(),update(),entity(),直到用户结束此次拖动

  • 在函数sample中做检测,如果使用关键字作为提示,那么就调用函数setKeywordList,如果想设置光标类型,就使用setSpecialCursorType,也可以调用函数setUserInputControls对拖动效果和返回值做限制

  • 根据sample中得到的集合数据,在update中对实体进行更改

  • 用一个指向需要更改重构的实体的指针作为参数调用的entity中,调用worldDraw重构实体

  • 最后根据drag函数的返回值决定状态并确认拖动过程中做出的修改,然后决定做出结果(添加实体还是直接删除)

下面是控制属性的含义:

控制属性含义
kAcceptOtherInputString接受不是关键字的字符串输入
kNullResponseAccepted禁止空输入
kDontEchoCancelForCtrlC设置取消操作时不显示"*cancel"
kDontUpdateLastPoint禁止更新最后一个点
kNoDwgLimitsChecking不检查图形界限
kNoZeroResponseAccepted禁止输入0值
kNoNegativeResponseAccepted禁止输入负值
kAccept3dCoordinates可以输入3d点
kAcceptMouseUpAsPoint设置鼠标按键松开为选点
kAnyBlankTerminatesInput输入字符串时,空格终止字符串
kInitialBlankTerminatesInput输入字符串时,开始的空格终止字符串

对AcEdJig大致了解后,开始尝试做一个简单的例子

//做一个绘制正方体的jig头文件

#ifndef __INCLUDE_DRAWSQUAREJIG_H__
#define __INCLUDE_DRAWSQUAREJIG_H__


class DrawSquareJig : public AcEdJig
{
public:
    DrawSquareJig(void);
    virtual ~DrawSquareJig(void);

    //外部调用,一般用于信息初始化
    bool Start(AcGePoint3d ptCenter, AcDbObjectId& resultId);

    virtual AcEdJig::DragStatus sampler();

    virtual Adesk::Boolean update();

    virtual AcDbEntity* entity() const;
private:
    AcDbPolyline* m_polyline;
    AcGePoint3d m_centerPnt;//鼠标点选的矩形中心点
    AcGePoint3d m_curPnt;//鼠标拖动过程中动态变化的实体
    
    AcGePoint2d Point3dTo2d(AcGePoint3d pnt);
};

#endif //__INCLUDE_DRAWSQUAREJIG_H__
//做一个绘制正方体的jig源文件
#include "StdAfx.h"
#include "drawsquarejig.h"


DrawSquareJig::DrawSquareJig(void) : m_polyline(NULL), m_centerPnt(AcGePoint3d::kOrigin), m_curPnt(AcGePoint3d::kOrigin)
{
}


DrawSquareJig::~DrawSquareJig(void)
{
    m_polyline = NULL;
}


//外部调用,一般用于信息初始化
bool DrawSquareJig::Start(AcGePoint3d ptCenter, AcDbObjectId& resultId)
{
    m_centerPnt = ptCenter;
    m_polyline = new AcDbPolyline;
    for (int i = 0; i < 4; i++)
    {
        m_polyline->addVertexAt(i, Point3dTo2d(m_centerPnt));
    }
    m_polyline->setClosed(Adesk::kTrue);
    CString prompt = _T("\n指定角点");
    setDispPrompt( prompt);
    AcEdJig::DragStatus status = drag();
    if (status == AcEdJig::kNormal)
    {
        resultId = append();
        return true;
    }
    else
    {
        delete m_polyline;
        return false;
    }
}

AcEdJig::DragStatus DrawSquareJig::sampler()
{
    setUserInputControls((UserInputControls)(AcEdJig::kAccept3dCoordinates
                         | AcEdJig::kNoNegativeResponseAccepted
                         | AcEdJig::kNullResponseAccepted));
    static AcGePoint3d pointTemp;
    DragStatus stat = acquirePoint(m_curPnt);
    if (pointTemp != m_curPnt)
    {
        pointTemp = m_curPnt;
    }
    else if (stat == AcEdJig::kNormal)
    {
        return AcEdJig::kNoChange;
    }
    return stat;
}

Adesk::Boolean DrawSquareJig::update()
{
    double dist = Point3dTo2d(m_curPnt).distanceTo(Point3dTo2d(m_centerPnt));
    AcGeVector2d vec = Point3dTo2d(m_curPnt) - Point3dTo2d(m_centerPnt);
    AcGePoint2d pt1, pt2, pt3, pt4;
    pt1 = Point3dTo2d(m_curPnt);
    pt3 = pt1 - 2 * vec;
    vec.rotateBy(PI*0.5);
    pt2 = Point3dTo2d(m_centerPnt) + vec;
    pt4 = pt2 - 2 *vec;
    m_polyline->setPointAt(0, pt1);
    m_polyline->setPointAt(1, pt2);
    m_polyline->setPointAt(2, pt3);
    m_polyline->setPointAt(3, pt4);
    return Adesk::kTrue;
}

AcDbEntity* DrawSquareJig::entity() const
{
    return m_polyline;
}

AcGePoint2d DrawSquareJig::Point3dTo2d(AcGePoint3d pnt)
{
    return AcGePoint2d(pnt.x, pnt.y);
}
void Func()
{
    ads_point pnt;
    if (RTNORM != ads_getpoint(NULL, _T("选取矩形插入点"), pnt))
        return;
    AcGePoint3d pnt3d = asPnt3d(pnt);
    DrawSquareJig jig;
    AcDbObjectId id;
    jig.Start(pnt3d, id);
}

这是一个单个实体发生变化的例子,如果当有多个实体的时候,如何写?

#ifndef __INCLUDE_MULTIPLE_ENTITY_JIG_H__
#define __INCLUDE_MULTIPLE_ENTITY_JIG_H__

class MultipleEntityJig : public AcEdJig
{
public:
    MultipleEntityJig();
    virtual ~MultipleEntityJig();

    bool Start(AcGePoint3d ptCenter, AcDbObjectIdArray& idArray);

    virtual AcEdJig::DragStatus sampler();
    virtual Adesk::Boolean update();
    virtual AcDbEntity* entity() const;

private:
    //创建的实体
    AcDbVoidPtrArray CreateEntitys();

    AcGePoint2d Point3dTo2d(AcGePoint3d pnt);


    class MEntity : public AcDbEntity
    {
    public:
        AcDbVoidPtrArray m_aryPtr;
#if _MSC_VER >= 1500
        virtual Adesk::Boolean subWorldDraw(AcGiWorldDraw* pWd);
#else
        virtual Adesk::Boolean worldDraw(AcGiWorldDraw* pWd);
#endif
    };

    MEntity* m_pEnt;
    AcGePoint3d m_centerPnt;
    AcGePoint3d m_curPnt;
};

#endif //__INCLUDE_MULTIPLE_ENTITY_JIG_H__
#include "stdafx.h"
#include "multipleentityjig.h"

MultipleEntityJig::MultipleEntityJig()
{
    m_pEnt = NULL;
}

MultipleEntityJig::~MultipleEntityJig()
{
    if (m_pEnt)
    {
        delete m_pEnt;
    }
    m_pEnt = NULL;
}

bool MultipleEntityJig::Start(AcGePoint3d ptCenter, AcDbObjectIdArray& idArray)
{
    m_centerPnt = ptCenter;
    m_curPnt = ptCenter;
    m_pEnt = new MEntity;
    CString prompt = _T("\n指定角点");
    setDispPrompt(prompt);
    AcEdJig::DragStatus stat = drag();
    if (stat == AcEdJig::kNormal)
    {
        AddMEntity();
        return true;
    }
    else
    {
        return false;
    }
}

AcEdJig::DragStatus MultipleEntityJig::sampler()
{
    setUserInputControls((UserInputControls)(AcEdJig::kAccept3dCoordinates
                         | AcEdJig::kNoNegativeResponseAccepted
                         | AcEdJig::kNullResponseAccepted));
    static AcGePoint3d pointTemp;
    DragStatus stat = acquirePoint(m_curPnt);
    if (pointTemp != m_curPnt)
    {
        pointTemp = m_curPnt;
    }
    else if (stat == AcEdJig::kNormal)
    {
        return AcEdJig::kNoChange;
    }
    return stat;
}

Adesk::Boolean MultipleEntityJig::update()
{
    //删除旧指针
    for (int i = 0; i < m_pEnt->m_aryPtr.length(); i++)
    {
        AcDbEntity* pEnt = (AcDbEntity*)m_pEnt->m_aryPtr.at(i);
        delete pEnt;
        pEnt = NULL;
    }
    //创建新实体
    m_pEnt->m_aryPtr = CreateEntitys();

    return Adesk::kTrue;
}

AcDbEntity* MultipleEntityJig::entity() const
{
    return m_pEnt;
}

AcDbVoidPtrArray MultipleEntityJig::CreateEntitys()
{
    AcDbVoidPtrArray aryEnts;
    //创建实体
    double dist = Point3dTo2d(m_curPnt).distanceTo(Point3dTo2d(m_centerPnt));
    AcGeVector2d vec = Point3dTo2d(m_curPnt) - Point3dTo2d(m_centerPnt);
    AcGePoint2d pt1, pt2, pt3, pt4;
    pt1 = Point3dTo2d(m_curPnt);
    pt3 = pt1 - 2 * vec;
    vec.rotateBy(PI*0.5);
    pt2 = Point3dTo2d(m_centerPnt) + vec;
    pt4 = pt2 - 2 * vec;
    AcDbPolyline* poly = new AcDbPolyline;
    poly->addVertexAt(0, pt1);
    poly->addVertexAt(1, pt2);
    poly->addVertexAt(2, pt3);
    poly->addVertexAt(3, pt4);
    poly->setClosed(Adesk::kTrue);
    poly->setColorIndex(1);
    aryEnts.append(static_cast<void*>(poly));
    AcDbCircle *circle = new AcDbCircle(m_centerPnt, AcGeVector3d::kZAxis, pt1.distanceTo(pt2) * 0.5);
    circle->setColorIndex(3);
    aryEnts.append(static_cast<void*>(circle));
    return aryEnts;
}

AcGePoint2d MultipleEntityJig::Point3dTo2d(AcGePoint3d pnt)
{
    return AcGePoint2d(pnt.x, pnt.y);
}

AcDbObjectIdArray MultipleEntityJig::AddMEntity()
{
    AcDbObjectIdArray idArray;
    AcDbDatabase*  pBase = acdbCurDwg();
    //获取块表指针
    AcDbBlockTable* pTable = NULL;
    Acad::ErrorStatus es = pBase->getBlockTable(pTable, AcDb::kForRead);
    //获取指向特定块表记录的指针(模型空间)
    AcDbBlockTableRecord* pTableRecord = NULL;
    es = pTable->getAt(ACDB_MODEL_SPACE, pTableRecord, AcDb::kForWrite);
    pTable->close();
    //添加实体
    for (int i = 0; i < m_pEnt->m_aryPtr.length(); i++)
    {
        AcDbEntity* pEnt = (AcDbEntity*)m_pEnt->m_aryPtr.at(i);
        AcDbObjectId id = AcDbObjectId::kNull;
        pTableRecord->appendAcDbEntity(id, pEnt);
        pEnt->close();
        pEnt = NULL;
        idArray.append(id);
    }
    pTableRecord->close();
    m_pEnt = nullptr;
    return idArray;
}

#if (_MSC_VER>=1500)
Adesk::Boolean MultipleEntityJig::MEntity::subWorldDraw(AcGiWorldDraw* mode)
#else
Adesk::Boolean MultipleEntityJig::MEntity::worldDraw(AcGiWorldDraw* mode)
#endif
{
    for (int i = 0; i < m_aryPtr.length(); i++)
    {
        AcDbEntity* pEnt = (AcDbEntity*)m_aryPtr.at(i);
        mode->subEntityTraits().setColor(pEnt->colorIndex());
        mode->subEntityTraits().setLayer(pEnt->layerId());
        pEnt->worldDraw(mode);
    }

    return Adesk::kTrue;
}

绘制完后的效果显示:

在这里插入图片描述

用一个指向需要更改重构的实体的指针作为参数调用的entity中,调用worldDraw重构实体,我们重载AcDbEntity,重写worldDraw
用于控制多个实体的显示,这个思路比较巧妙简单!如果后续有更加复杂的实体需要显示拖动效果,可能会用到关键字,可能需要鼠标点选,需要重复绘制,那就需要在多多把握一些细节了。

  • 7
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值