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
用于控制多个实体的显示,这个思路比较巧妙简单!如果后续有更加复杂的实体需要显示拖动效果,可能会用到关键字,可能需要鼠标点选,需要重复绘制,那就需要在多多把握一些细节了。
今天的文章关于Jig分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/67768.html