Files
envi-code/SourceCode/Code2026/AdsXRx/entity.cpp
T
2026-09-28 15:28:50 +08:00

1571 lines
27 KiB
C++

//-------------------------------------------------------------------------------------------------------+
// Copyright (C), 1998-2007, SH Software Co. Ltd.
// = FileName : Entity 类
// = Version : ver2.0
// = Author : zjq
// = CreateDate : 2002-09-09
// = Description: Entity 定义
// = Maintainers:
//
//-------------------------------------------------------------------------------------------------------+
#include "StdAfx.h"
#include "Entity.h"
#include "XArc.h"
#include "XAString.h"
#include "PickSet.h"
#include "DragPickEntSet.h"
#include "XPoly2D.h"
#include "XDbObject.h"
#include "X3DFace.h"
#include "XPushVar.h"
#include "SymbolTable.h"
#include "DragPickEntSet.h"
#include "XBlockTable.h"
#include "XGlobalFunc.h"
#include "XPrivateGlobalFunc.h"
static const TCHAR *sMsgPrompt[] =
{
/*MSG0*/ _T("\n选择无效, 重新选择!"),
/*MSG1*/ _T("\n请重新选择!"),
/*MSG2*/ _T("\n发现不可变形的对象: "),
/*MSG3*/ _T("\n图块内有延伸方向不同于Z轴的对象,不能打散!"),
/*MSG4*/ _T("\n是否为该对象"),
};
const TCHAR* Entity::ApplicationName=_T("_ASH");
Entity::~Entity()
{
}
int Entity::MatchEx(int tag, const Groups *data)
{
if (!groups)
{
GetGroups();
}
if (!groupsEx || !data)
{
return 0;
}
Groups *rbData = SearchDataByTag(tag);
if (!rbData)
{
return 0;
}
return (*rbData) == (*data);
}
int Entity::MatchEx(int tag, int data)
{
if (!groups)
{
GetGroups();
}
if (!groupsEx)
{
return 0;
}
Groups *rbData = SearchDataByTag(tag);
if (!rbData || rbData->code != XD_SHORT)
{
return 0;
}
return (rbData->shortInt == data);
}
int Entity::MatchEx(int tag, const TCHAR *data)
{
if (!groups)
{
GetGroups();
}
if (!groupsEx || !data)
{
return 0;
}
Groups *rbData = SearchDataByTag(tag);
if (!rbData || rbData->code != XD_STR || !rbData->string)
{
return 0;
}
return !_tcscmp(rbData->string, data);
}
int Entity::MatchEx(int tag, ads_real data)
{
if (!groups)
{
GetGroups();
}
if (!groupsEx)
{
return 0;
}
Groups *rbData = SearchDataByTag(tag);
if (!rbData || rbData->code != XD_REAL)
{
return 0;
}
return rbData->real == data;
}
int Entity::MatchEx(const Groups *tag, const Groups *data)
{
if (!tag || tag->code != XD_SHORT)
{
return 0;
}
return MatchEx(tag->shortInt, data);
}
int Entity::MatchBase(const Groups &rb)
{
if (rb.code == 1001)
{
OPENOBJ_BEGIN(*this, AcDb::kForRead, AcDbEntity, pEnt);
if (pEnt)
{
resbuf *xData = pEnt->xData(rb.string);
if (xData)
{
ads_relrb(xData);
return 1;
}
else
{
return 0;
}
}
else
{
return 0;
}
OPENOBJ_END();
}
if (!groups)
{
GetGroups(0);
}
Groups *pg = SearchNode(rb.code);
if (!pg)
{
return 0;
}
if (TypeOfCode(rb.code) == RTSTR)
{
XString s1, s2;
s1 = pg->string;
s2 = rb.string;
_tcsupr(s1);
_tcsupr(s2);
return (ads_wcmatch(s1, s2) == RTNORM);
}
return *pg == rb;
}
int Entity::SetData(int code,...)
{
if (!groups) _GetGroups();
#ifdef _WIN64
va_list args;
va_start(args, code);
int rc = _SetData(code, args);
va_end(args);
return rc;
#else
void *buf=(char *)&code+sizeof(int);
return _SetData(code,buf);
#endif
/*if (!groups)
{
_GetGroups();
}
void *buf = (TCHAR *)&code + sizeof(int);
return _SetData(code,buf);*/
}
// 两个Resubf 节点成对的Match方可以
int Entity::Match(const RBList &exlist)
{
if (!groups)
{
GetGroups();
}
Groups *exList = exlist.groups;
if (!groupsEx || !exList || !exList->next)
{
return 0;
}
Groups *rb1 = exList, *rb2 = exList->next;
while(MatchEx(rb1, rb2))
{
rb1 = rb2->next;
if (!rb1)
{
return 1;
}
rb2 = rb1->next;
if (!rb2)
{
ads_fail(_T("\nBad Extend data list!"));
return 0;
}
if (ads_usrbrk())
{
return 0;
}
}
return 0;
}
int Entity::_GetGroups()
{
if (groups)
{
Release(groups);
groups = groupsEx = NULL;
}
// else groupsEx set to NULL ??
groups = (PGroups)ads_entget(name);
return (groups ? RTNORM : RTERROR);
}
int Entity::FilterSelect(const TCHAR *prompt, const RBList &mask)
{
const TCHAR *szPrompts[2] = { prompt, _T("") };
PickSet ss(SS_FREE);
int nRet = ss.Get(_T(":S:$"), szPrompts, NULL, mask);
if (nRet == RTNORM)
{
long lCount = ss.Length();
if (lCount == 1)
{
*this = ss[0L];
}
else
{
for (long i = 0; i < lCount; i++)
{
Entity ent = ss[i];
ent.Redraw(3);
int rc = YesNoQuestion(sMsgPrompt[4], Q_YES);
ent.Redraw(4);
if (rc == RTCAN)
{
return rc;
}
else if (rc == Q_YES)
{
*this = ent;
return RTNORM;
}
}
return RTNONE;
}
}
return nRet;
}
int Entity::FilterSelect(const TCHAR *prompt, const RBList &mask, ads_point res)
{
do
{
Entity ent;
int rc = res ? ent.UserSelect(prompt, res) : ent.UserSelect(prompt);
if (rc != RTNORM)
{
return rc;
}
if (ent.MatchBase(mask))
{
*this = ent;
return RTNORM;
}
XGeLib::adsout << sMsgPrompt[0];
} while(1);
}
int Entity::FilterSelect1(ads_real distPrec, const TCHAR *prompt, const RBList &mask, ads_point res)
{
XPushVar<int> osmode(_T("OSMODE"), 512);
do
{
XPoint pickPt;
int rc = ads_getpoint(NULL, prompt, pickPt);
if (rc != RTNORM)
{
return rc;
}
XPoint lowCorner = pickPt - XPoint(distPrec, distPrec);
XPoint upCorner = pickPt + XPoint(distPrec, distPrec);
PickSet ss(SS_FREE);
if (ss.Get(_T("C"), &lowCorner, upCorner, mask) != RTNORM)
{
XGeLib::adsout << sMsgPrompt[0];
continue;
}
if (ss.Length() == 1)
{
*this = ss[0L];
if (res)
{
pickPt > res;
}
return RTNORM;
}
long len = ss.Length();
for (long i = 0; i < len; i++)
{
Entity ent = ss[i];
ent.Redraw(3);
rc = YesNoQuestion(sMsgPrompt[4]);
ent.Redraw(4);
if (rc == RTCAN)
{
return rc;
}
else if (rc == Q_YES)
{
*this = ent;
if (res)
{
pickPt > res;
}
return RTNORM;
}
}
XGeLib::adsout << sMsgPrompt[1];
} while(1);
}
int Entity::RedrawAll(int mode) const
{
int nTileMode = 0;
xg_getvar(_T("TILEMODE"), &nTileMode);
resbuf * rbViewports = NULL;
VERIFY(ads_vports(&rbViewports) == RTNORM && rbViewports);
int nCurVp = rbViewports->rbnext->resval.rint;
resbuf *rbNext = rbViewports->rbnext->rbnext->rbnext->rbnext->rbnext;
while(rbNext && !(nTileMode == 0 && nCurVp == 1))
{
ASSERT(rbNext->restype == RTLB && rbNext->rbnext->restype == RTSHORT);
if (xg_setvar(_T("CVPORT"), rbNext->rbnext->resval.rint) == RTNORM)
{
Redraw(mode);
}
rbNext = rbNext->rbnext->rbnext->rbnext->rbnext->rbnext;
}
ads_relrb(rbViewports);
xg_setvar(_T("CVPORT"), nCurVp);
int nRet = Redraw(mode);
return nRet;
}
int Entity::Move(const XPoint & basept, XPoint & res) const
{
if (!name[0] && !name[1])
{
return RTERROR;
}
DragPickEntSet picks(basept);
picks += *this;
return picks.Move(basept, res);
}
int Entity::Rotate(const XPoint & basept, ads_real *res) const
{
if (!name[0] && !name[1])
{
return RTERROR;
}
DragPickEntSet picks(basept);
picks += *this;
return picks.Rotate(basept, res);
}
int Entity::Scale(const XPoint & basept, ads_real *res) const
{
if (!name[0] && !name[1])
{
return RTERROR;
}
DragPickEntSet picks(basept);
picks += *this;
return picks.Scale(basept, res);
}
int Entity::AssignAppName(const TCHAR *s)
{
if (s && s[0])
{
ApplicationName = s;
XSymbolTable appId(_T("APPID"), ApplicationName);
if (!appId)
{
return ads_regapp(ApplicationName);
}
return RTNORM;
}
ApplicationError(_T("Bad Application Name\n"));
return RTERROR;
}
// 创建扩充实体数据
void Entity::_MakeExGroups()
{
if (groups)
{
groupsEx = groups;
while (groupsEx->next && (groupsEx->code != -3))
{
groupsEx = groupsEx->next;
}
if (groupsEx->next)
{ // I got it; code = -3
groupsEx = groupsEx->next;
}
else
{ // make a -3 head
groupsEx->next = (PGroups)ads_buildlist(-3,1001,ApplicationName,0);
if (!groupsEx->next)
{
ApplicationError(_T("Error in Ex::GetGroups\n"));
return;
}
groupsEx = (groupsEx->next)->next;
}
}
}
int Entity::GetGroups(int getEx)
{
if (groups)
{
Release(groups);
groups = groupsEx = 0;
}
if (getEx && ApplicationName)
{
PGroups agroup = (PGroups)ads_newrb(RTSTR);
if (!agroup)
{
return RTERROR;
}
agroup->string = _tcsdup(ApplicationName);
groups = (PGroups)ads_entgetx(name,(struct resbuf*)agroup);
ads_relrb((resbuf *)agroup);
if (!groups)
{
return RTERROR;
}
else
{
_MakeExGroups();
}
return RTNORM;
}
return _GetGroups();
}
int Entity::GetGroups(const TCHAR *appname)
{
const TCHAR *oldApp = ApplicationName;
ApplicationName = appname;
int rc = GetGroups();
ApplicationName = oldApp;
if (!groupsEx)
{
rc = RTERROR;
}
return rc;
}
PGroups Entity::SearchByTagCode(int tagCode)
{
PGroups group;
group = groupsEx;
while (group)
{
if (group->code == 1070 && group->shortInt == tagCode)
{
return group;
}
group = group->next;
}
return NULL;
}
int Entity::RemoveXData()
{
GetGroups(0);
_MakeExGroups();
Modify();
return RTNORM;
}
int Entity::Erase() const
{
XDbObject dbObj(name, AcDb::kForWrite);
if (!dbObj)
{
;
}
else
{
AcDbEntity &dbEnt = dbObj;
if (dbEnt.erase() == Acad::eOk)
{
return RTNORM;
}
}
return RTERROR;
}
int Entity::DeleteTag(int tagCode)
{
PGroups g = groupsEx,g1,g2,g3;
if (!g)
{
return RTERROR;
}
g1 = g;
while (g)
{
if (g->code == 1070 && g->shortInt == tagCode)
{
break;
}
g1 = g;
g = g->next;
}
if (!g)
{
return RTERROR;
}
g2 = g->next;
if (!g2)
{
return RTERROR;
}
if (g2->code == 1002 && g2->string[0] == _T('{'))
{
while (g2)
{
if (g2->code == 1002 && g2->string[0] == _T('}'))
{
break;
}
g2 = g2->next;
}
if (!g2)
{
return RTERROR;
}
}
g3 = g2->next;
g2->next = 0;
g1->next = g3;
Release(g);
return RTNORM;
}
int Entity::CreateTag(void *buf,int tagCode,int type)
{
PGroups list = groupsEx;
if (!list)
{
ApplicationError(_T("Error in ::CreateTag"));
return RTERROR;
}
while (list->next)
{
list = list->next;
}
list->next = (PGroups)ads_newrb(1070);
if (!list->next)
{
ApplicationError(_T("Error in ::CreateTag"));
return RTERROR;
}
list = list->next;
list->shortInt = tagCode;
list->next = (PGroups)ads_newrb(0);
if (!list->next)
{
ApplicationError(_T("Error in ::CreateTag"));
return RTERROR;
}
list = list->next;
list->next = NULL;
if (type == RTSTR)
{
list->code = XD_STR;
list->string = _tcsdup(*(TCHAR **)buf);
}
else if (type == RTREAL)
{ // real
list->code = XD_REAL;
list->real = *((ads_real *)buf);
}
else
{ // int
list->code = XD_SHORT;
list->shortInt = *((short *)buf);
}
return RTNORM;
}
int Entity::SetExData(int tagCode,...)
{
if (!groups || !groupsEx)
{
GetGroups();
}
int type = TypeOfCode(tagCode);
void *buf = (int *)&tagCode + 1;
if (type != RTSTR && type != RTREAL && type != RTSHORT)
{
ApplicationError(_T("This tag code %d is not support by the::SetExdata.\n"),tagCode);
return RTERROR;
}
PGroups group = SearchByTagCode(tagCode);
if (!group)
{ // add on the whole thing
CreateTag(buf,tagCode,type);
}
else
{ // replace it
PGroups list = group->next;
int t1 = TypeOfCode(list->code);
if (t1 != type)
{
ApplicationError(_T("Tag Code type does not match the group code type.::SetExData\n"));
return RTERROR;
}
if (type == RTSTR)
{
free(list->string);
list->string = _tcsdup(*(TCHAR **)buf);
}
else if (type == RTREAL)
{ // real
list->real = *((ads_real *)buf);
}
else
{ //int
list->shortInt = *((short *)buf);
}
}
return RTNORM;
}
int Entity::GetExData(int tagCode,void *buf)
{
if (!groups || !groupsEx)
{
GetGroups();
}
int type = TypeOfCode(tagCode);
if (type != RTSTR && type != RTREAL && type != RTSHORT)
{
ApplicationError(_T("This tag code %d is not support by the::GetExdata.\n"),tagCode);
return RTERROR;
}
PGroups group = SearchByTagCode(tagCode);
if (group)
{ // replace it
PGroups list = group->next;
int t1 = TypeOfCode(list->code);
if (t1 != type)
{
ApplicationError(_T("Tag Code type does not match the group code type.::SetExData\n"));
return RTERROR;
}
if (type == RTSTR)
{
_tcscpy((TCHAR *)buf,list->string);
}
else if (type == RTREAL)
{ // real
*((ads_real *)buf) = list->real;
}
else
{ //int
*((short *)buf) = list->shortInt;
}
return RTNORM;
}
return RTERROR;
}
// Get 系列都没有检查类型的匹配 ------------------------------------!!!
int Entity::GetInt(int tag_code,int &buf)
{
if (!groups || !groupsEx)
{
GetGroups();
}
Groups *list;
if ((list = (PGroups)XPrivate::get_xdata_tag_item((resbuf *)groupsEx, tag_code, NULL)) == NULL)
{
return RTERROR;
}
list = list->next;
buf = list->shortInt;
return RTNORM;
}
int Entity::GetReal(int tag_code,ads_real &buf)
{
if (!groups || !groupsEx)
{
GetGroups();
}
Groups *list;
if ((list = (PGroups)XPrivate::get_xdata_tag_item((resbuf *)groupsEx, tag_code, NULL)) == NULL)
{
return RTERROR;
}
list = list->next;
buf = list->real;
return RTNORM;
}
// don't free buf
int Entity::GetRBinary(int tag_code, short &nBufLen, const char * &buf)
{
if (!groups || !groupsEx)
{
GetGroups();
}
Groups *list;
if ((list = (PGroups)XPrivate::get_xdata_tag_item((resbuf *)groupsEx, tag_code, NULL)) == NULL)
{
return RTERROR;
}
list = list->next;
nBufLen = list->binary.length;
buf = list->binary.buffer;
return RTNORM;
}
// NOTE:
// This function return a pointer equal to string pointer in the resbuf
// When the Groups released,referrence to that string would be a disaster.
int Entity::GetRString(int tag_code,TCHAR *&buf)
{
if (!groups || !groupsEx)
{
GetGroups();
}
Groups *list;
if ((list = (PGroups)XPrivate::get_xdata_tag_item((resbuf *)groupsEx, tag_code, NULL)) == NULL)
{
return RTERROR;
}
list = list->next;
buf = list->string;
return RTNORM;
}
int Entity::GetString(int tag_code,TCHAR *buf)
{
if (!groups || !groupsEx)
{
GetGroups();
}
TCHAR *temp;
int rt = GetRString(tag_code,temp);
if (rt == RTNORM)
{
_tcscpy(buf,temp);
}
return rt;
}
int Entity::GetPoint(int tag_code, XPoint &res)
{
if (!groups || !groupsEx)
{
GetGroups();
}
Groups *list;
if ((list = (PGroups)XPrivate::get_xdata_tag_item((resbuf *)groupsEx, tag_code, NULL)) == NULL)
{
return RTERROR;
}
list = list->next;
res = list->point;
return RTNORM;
}
int Entity::SetReal(int tag_code,ads_real val)
{
if (!groups || !groupsEx)
{
GetGroups();
}
PGroups tag_xdata = (PGroups)ads_newrb(XD_REAL);
tag_xdata->real = val;
XPrivate::set_xdata_tag_item((resbuf **)&groupsEx, tag_code, (resbuf*)tag_xdata, Entity::ApplicationName);
return RTNORM;
}
int Entity::SetInt(int tag_code,int val)
{
if (!groups || !groupsEx)
{
GetGroups();
}
PGroups tag_xdata = (PGroups)ads_newrb(XD_INT);
tag_xdata->shortInt = val;
XPrivate::set_xdata_tag_item((resbuf **)&groupsEx, tag_code, (resbuf*)tag_xdata, Entity::ApplicationName);
return RTNORM;
}
int Entity::SetString(int tag_code, const TCHAR *val, int isHandle)
{
if (!groups || !groupsEx)
{
GetGroups();
}
int xdCode = isHandle ? XD_HANDLE : XD_STR;
PGroups tag_xdata = (PGroups)ads_newrb(xdCode);
tag_xdata->string = _tcsdup(val);
XPrivate::set_xdata_tag_item((resbuf **)&groupsEx, tag_code, (resbuf*)tag_xdata, Entity::ApplicationName);
return RTNORM;
}
int Entity::SetPoint(int tag_code, const XPoint &pt)
{
if (!groups || !groupsEx)
{
GetGroups();
}
PGroups tag_xdata = (PGroups)ads_newrb(XD_POINT);
pt > tag_xdata->point;
XPrivate::set_xdata_tag_item((resbuf **)&groupsEx, tag_code, (resbuf*)tag_xdata, Entity::ApplicationName);
return RTNORM;
}
int Entity::SetBinary(int tag_code, short nBufLen, const char *buf)
{
assert(nBufLen<128 && nBufLen>0);
if (!groups || !groupsEx)
{
GetGroups();
}
PGroups tag_xdata = (PGroups)ads_newrb(1004);
tag_xdata->binary.length = nBufLen;
tag_xdata->binary.buffer = new char [nBufLen];
memcpy(tag_xdata->binary.buffer, buf, nBufLen);
XPrivate::set_xdata_tag_item((resbuf **)&groupsEx, tag_code, (resbuf*)tag_xdata, Entity::ApplicationName);
return RTNORM;
}
// API 2.0
int Entity::SetStruct(void *buf,int len, int tagCode)
{
if (!groups || !groupsEx)
{
GetGroups();
}
long *lp;
int v;
long ll;
TCHAR *p;
int base;
int i;
if (len <= 0)
{
return RTERROR;
}
DeleteTag(tagCode);
PGroups l = groupsEx;
if (!l)
{
ApplicationError(_T("Error in ::SetStruct.\n"));
return RTERROR;
}
while (l->next)
{
l = l->next;
}
l->next = (PGroups)ads_newrb(1070);
if (!l->next)
{
ApplicationError(_T("Error in ::SetStruct.\n"));
return RTERROR;
}
l = l->next;
l->shortInt = tagCode;
l->next = (PGroups)ads_newrb(1002);
if (!l->next)
{
ApplicationError(_T("Error in ::SetStruct.\n"));
return RTERROR;
}
l = l->next;
l->string = _tcsdup(_T("{"));
l->next = (PGroups)ads_newrb(XD_INT);
if (!l->next)
{
ApplicationError(_T("Error in ::SetStruct.\n"));
return RTERROR;
}
l = l->next;
l->shortInt = len;
lp = (long *)buf;
for (i = 0; i < len / 4; i++)
{
l->next = (PGroups)ads_newrb(XD_LONG);
if (!l->next)
{
ApplicationError(_T("Error in ::SetStruct.\n"));
return RTERROR;
}
l = l->next;
l->longInt = lp[i];
}
v = len % 4;
if (v)
{ //v = 1,2,3
p = (TCHAR *)&ll;
base = len / 4 * 4;
for (i = 0; i < v; i++)
{
p[i] = ((TCHAR *)buf)[base + i];
}
l->next = (PGroups)ads_newrb(XD_LONG);
if (!l->next)
{
ApplicationError(_T("Error in ::SetStruct.\n"));
return RTERROR;
}
l = l->next;
l->longInt = ll;
}
l->next = (PGroups)ads_newrb(1002);
if (!l->next)
{
ApplicationError(_T("Error in ::SetStruct.\n"));
return RTERROR;
}
l = l->next;
l->string = _tcsdup(_T("}"));
l->next = 0;
return RTNORM;
}
int Entity::GetStruct(void *buf,int len, int tagCode)
{
if (!groups || !groupsEx)
{
GetGroups();
}
PGroups l = SearchByTagCode(tagCode);
if (!l)
{
return RTERROR;
}
l = l->next;
if (!l)
{
ApplicationError(_T("Error in ::GetStruct\n"));
return RTERROR;
}
if (l->code == 1002 && l->string[0] == _T('{'))
{
l = l->next;
if (!l)
{
ApplicationError(_T("Error in ::GetStruct\n"));
return RTERROR;
}
// get the len
int len1;
if (l->code != XD_INT)
{
ApplicationError(_T("Error in ::GetStruct\n"));
return RTERROR;
}
len1 = l->shortInt;
len = len < len1 ? len : len1;
l = l->next;
if (!l)
{
ApplicationError(_T("Error in ::GetStruct\n"));
return RTERROR;
}
long *lp = (long *)buf;
while (len && l->code == XD_LONG)
{
if (len >= 4)
{
*lp = l->longInt;
lp++;
len -= 4;
}
else
{
TCHAR *cp1 = (TCHAR *)lp;
TCHAR *cp2 = (TCHAR *)&l->longInt;
for (int i = 0; i < len; i++)
{
cp1[i] = cp2[i];
}
len = 0;
}
l = l->next;
if (!l)
{
ApplicationError(_T("Error in ::GetStruct\n"));
return RTERROR;
}
}
return RTNORM;
}
return RTERROR;
}
int Entity::Make()
{
if (!groups)
{
GetGroups(0);
}
if (groups)
{
return (ads_entmake((struct resbuf *)groups));
}
else
{
ApplicationError(_T("\nError in Entity::Make().\nZero groups.\n"));
return RTERROR;
}
}
int Entity::Make(int type,...)
{
if (groups)
{
Release(groups);
groups = groupsEx = NULL;
}
groups = VBuildList(&type);
if (!groups)
{
return RTERROR;
}
if (ads_entmake((struct resbuf *)groups) != RTNORM || GetLast() != RTNORM)
{
ads_printf(_T("\nEntity::Make(...) Error!"));
return RTERROR;
}
return RTNORM;
}
int Entity::MakeEx(int type,...)
{
if (groups)
{
Release(groups);
groups = groupsEx = NULL;
}
groups = VBuildList(&type);
if (!groups) return RTERROR;
if (ads_entmake((struct resbuf *)groups) == RTERROR || GetLast() != RTNORM)
{
ads_printf(_T("\nEntity::Make(...) Error!"));
return RTERROR;
}
_MakeExGroups();
return RTNORM;
}
// 求模型的边界(忽略图纸实体: POINT, TEXT, ATTRIB, ATTDEF, DIMENSION)
// tranMat -- 当前实体为图块中的子实体时,需左乘的变换矩阵
// Status: When it's POLYLINE, the result still not verified
// return: RTNORM--确切求得边界; RTERROR--不能确切求得边界; RTNONE--模型边界不可求
int Entity::GetExtend(ads_point lowPt, ads_point upPt, ads_matrix tranMat)
{
if (!tranMat)
{
AcDbExtents geomExt;
XDbObject obj(name, AcDb::kForRead);
if (!obj)
{
return RTNONE;
}
AcDbEntity &objEnt = obj;
Acad::ErrorStatus es = objEnt.getGeomExtents(geomExt);
if (es == Acad::eOk)
{
XPoint ptLow = geomExt.minPoint();
XPoint ptUp = geomExt.maxPoint();
ptLow > lowPt;
ptUp > upPt;
return RTNORM;
}
}
if (!(*this))
{
return RTNONE;
}
XString eType;
if (GetData(0, eType) != RTNORM)
{
return RTNONE;
}
XPoint extrusion(0, 0, 1);
ads_real thickness = 0;
GetData(210, extrusion);
if (!(extrusion == Point(0,0,1)))
{
return RTNONE;
}
GetData(39, &thickness);
if (eType == _T("LINE"))
{
XLine aLine(*this, LS_FINITE, tranMat);
*(XPoint *)lowPt = Min(aLine.StartPoint(), aLine.EndPoint());
*(XPoint *)upPt = Max(aLine.StartPoint(), aLine.EndPoint());
upPt[Z] += thickness;
if (fabs(thickness) > 1E-6 && tranMat)
{
return RTERROR;
}
}
else if (eType == _T("3DFACE"))
{
X3DFace face(*this, tranMat);
return face.GetExtend(lowPt, upPt);
}
else if (eType == _T("ATTDEF") || eType == _T("ATTRIB") || eType == _T("TEXT") || eType == _T("DIMENSION"))
{
return RTNONE;
}
else if (eType == _T("ARC"))
{
XArc arc(*this, tranMat);
arc.GetExtend(lowPt, upPt);
upPt[Z] += thickness;
if (fabs(thickness) > 1E-6 && tranMat)
{
return RTERROR;
}
}
else if (eType == _T("CIRCLE"))
{
XCircle cir(*this, tranMat);
cir.GetExtend(lowPt, upPt);
upPt[Z] += thickness;
if (fabs(thickness) > 1E-6 && tranMat)
{
return RTERROR;
}
}
else if (eType == _T("INSERT"))
{
ads_matrix mat, mat1;
if (GetInsertMatrix(*this, mat) != RTNORM)
{
return RTNONE;
}
TCHAR blk[80]=_T("");
GetData(2, blk);
XBlockTable blkTab(blk);
if (tranMat)
{
AT_multiply_matrix(tranMat, mat, mat1);
}
else
{
memcpy(mat1, mat, sizeof(ads_matrix));
}
return blkTab.GetExtend(lowPt, upPt, mat1);
}
else if (eType == _T("POINT"))
{
return RTNONE;
}
else if (eType == _T("POLYLINE"))
{ // 不包含弧段时可求
int polyFlag;
GetData(70, &polyFlag);
if (polyFlag <= 1 && !tranMat)
{ // do not take ECS-Vertex into account
XPoly2D poly(*this);
poly.GetExtend(lowPt, upPt);
upPt[Z] += thickness;
return RTNORM;
}
Entity subEnt, nextEnt;
ads_entnext(*this, nextEnt);
XPoint ptm, ptn;
int rt = RTNORM;
int index = 0;
do
{
nextEnt.GetGroups(0);
if (!nextEnt.Is(_T("VERTEX")))
{
break;
}
int flg = 0;
ads_real bulge = 0;
nextEnt.GetData(70, &flg);
if ((flg&128) && !(flg&64))
{
break;
}
if (nextEnt.GetData(42, &bulge) == RTNORM && fabs(bulge)>0.0001)
{
rt = RTERROR;
}
XPoint vertex;
nextEnt.GetData(10, vertex);
{
XPoint vtPt = vertex;
if (tranMat)
{
AT_xformpt(tranMat, vtPt, vertex);
}
else
{
vertex = vtPt;
}
}
if (!index)
{
ptm = ptn = vertex;
}
else
{
ptm = Max(ptm, vertex); ptn = Min(ptn, vertex);
}
subEnt = nextEnt;
index ++;
} while(ads_entnext(subEnt, nextEnt) == RTNORM);
ptm.z += thickness;
ptm > upPt; ptn > lowPt;
return rt;
}
else if (eType == _T("SOLID") || eType == _T("TRACE"))
{
X3DFace notFace;
for (int i = 0; i < 4; i++)
{
XPoint vertex;
GetData(10+i, vertex);
if (tranMat)
{
XPoint ptNew;
AT_xformpt(tranMat, vertex, ptNew);
notFace.SetVertex(i,ptNew);
}
else
{
notFace.SetVertex(i, vertex);
}
}
return notFace.GetExtend(lowPt, upPt);
}
else
{
return RTNONE;
}
return RTNORM;
}
// 实体变换: 允许不等比缩放
int Entity::XTransform(ads_matrix mat)
{
XString eType;
ads_real thickness;
XPoint extrusion;
if (!(*this) || GetData(0, eType) != RTNORM)
{
return RTERROR;
}
if (eType == _T("LWPOLYLINE"))
{
XDbObject obj(name, AcDb::kForWrite);
if (!!obj)
{
AcDbPolyline *pline = AcDbPolyline::cast(obj.m_pObject);
if (pline)
{
//只对顶点进行变换, 不考虑弧度的变化
int nVerts = pline->numVerts();
for (int i = 0; i < nVerts; i++)
{
AcGePoint2d pt;
if (pline->getPointAt(i, pt) == Acad::eOk)
{
XPoint pt1 = pt;
XPoint pt2;
AT_xformpt(mat, pt1, pt2);
pline->setPointAt(i, pt2);
}
}
return RTNORM;
}
}
return RTERROR;
}
if (GetData(39, &thickness) == RTNORM || (GetData(210, extrusion) == RTNORM && !(extrusion == XPoint(0,0,1))))
{
return RTERROR;
}
if (eType == _T("LINE"))
{
XLine aLine(*this, LS_FINITE, mat);
return aLine.Modify(this);
}
else if (eType == _T("3DFACE"))
{
X3DFace face(*this, mat);
return face.Modify(*this);
}
else if (eType == _T("POINT"))
{
XPoint pt, npt;
GetData(10, &pt.x);
AT_xformpt(mat, pt, npt);
SetData(10, &npt.x);
return Modify();
}
else if (eType == _T("SOLID") || eType == _T("TRACE"))
{
for (int i = 0; i < 4; i++)
{
XPoint vertex, nVertex;
GetData(10 + i, (ads_real *)vertex);
AT_xformpt(mat, vertex, nVertex);
SetData(10 + i, (ads_real *)nVertex);
}
return Modify();
}
else if (eType == _T("POLYLINE"))
{
Entity subEnt, nextEnt;
XPoint base, nBase;
ads_entnext(*this, nextEnt);
GetData(10, base);
AT_xformpt(mat, base, nBase);
XPoint ptm, ptn;
int rt = RTNORM;
do
{
nextEnt.GetGroups(0);
if (!nextEnt.Is(_T("VERTEX"))) break;
int flg = 0;
ads_real bulge = 0;
nextEnt.GetData(70, &flg);
if ((flg&128) && !(flg&64))
{
break;
}
if (nextEnt.GetData(42, &bulge) == RTNORM && fabs(bulge) > 0.0001)
{
rt = RTERROR;
}
XPoint vertex, nVertex;
nextEnt.GetData(10, vertex);
AT_xformpt(mat, vertex, nVertex);
nextEnt.SetData(10, &nVertex.x);
nextEnt.Modify();
subEnt = nextEnt;
} while(ads_entnext(subEnt, nextEnt) == RTNORM);
SetData(10, &nBase);
Modify();
return rt;
}
else if (eType == _T("ARC"))
{
XArc ar(*this);
XPoint ptStart, ptEnd, ptMid;
ar.GetStartPoint(ptStart);
ar.GetEndPoint(ptEnd);
ar.MidPoint(ptMid);
XPoint ptNewStart, ptNewEnd, ptNewMid;
AT_xformpt(mat, ptStart, ptNewStart);
AT_xformpt(mat, ptEnd, ptNewEnd);
AT_xformpt(mat, ptMid, ptNewMid);
XArc arNew(ptNewStart, ptNewMid, ptNewEnd);
arNew.Modify(this);
return RTERROR;
}
XGeLib::adsout << sMsgPrompt[2] << eType;
return RTERROR;
}
// 求实体的范围
int Entity::GetExtend(ads_point cen, ads_real *x, ads_real *y, ads_real *z)
{
XPoint lowPt, upPt;
int rc = GetExtend(lowPt, upPt);
if (rc == RTNONE)
{
return rc;
}
XPoint extSize = upPt-lowPt;
if (cen)
{
Midpoint(lowPt, upPt, cen);
}
if (x)
{
*x = extSize.x;
}
if (y)
{
*y = extSize.y;
}
if (z)
{
*z = extSize.z;
}
return rc;
}
int Entity::MatchBase(const RBList &baseList)
{
for (Groups *rb = baseList.groups; rb != NULL; rb = rb->next)
{
if (!MatchBase(*rb))
{
return 0;
}
}
return 1;
}
int Entity::In(const PickSet *pSelectionSet)
{
ASSERT(pSelectionSet != NULL);
ads_name entT;
Adesk::Int32 lLen = 0L;
acedSSLength(pSelectionSet->name,&lLen);
for (long j = 0;j < lLen;j++)
{
acedSSName(pSelectionSet->name,j,entT);
if (entT[0] == name[0] &&
entT[1] == name[1])
{
return TRUE;
}
}
return FALSE;
// return (ads_ssmemb(name,pSelectionSet->name) == RTNORM ? TRACE:FALSE);
}