OBJECT ARX 總結5道題

/加載一個實體到數據庫,返回實體ID

static AcDbObjectId LoadEntity(AcDbEntity* entity)
{
 
 
AcDbBlockTable* pBlockTable;
acdbHostApplicationServices()->workingDatabase()->getBlockTable(pBlockTable,AcDb::kForRead);
 
 
AcDbBlockTableRecord* pBlockTableRecord;
pBlockTable->getAt(ACDB_MODEL_SPACE,pBlockTableRecord,AcDb::kForWrite);
 
 
AcDbObjectId Id;
pBlockTableRecord->appendAcDbEntity(Id,entity);
 
 
pBlockTable->close();
 
 
pBlockTableRecord->close();
 
 
entity->close();
return Id;
}





//彈出顏色選擇對話框,讓用戶選擇顏色,默認選擇的是當前層的顏色

static int SelColor()
{
////先獲得當前層的ID
AcDbObjectId layerId = acdbHostApplicationServices()->workingDatabase()->clayer();
////然後獲得當前層指針
AcDbLayerTableRecordPointer ptLayer(layerId,AcDb::OpenMode::kForRead);
////獲得當前層的顏色
AcCmColor oldColor = ptLayer->color();
int nCurColor = oldColor.colorIndex();//當前層的顏色
int nNewColor = oldColor.colorIndex();//用戶選擇的顏色
 
 
if (acedSetColorDialog(nNewColor,Adesk::kFalse,nCurColor))
{
 
 
return nNewColor;
}
else
{
 
 
return nCurColor;
}
}

 

//第一題:定義一個全局命令,功能:使用全局函數創建一個簡單實體-直線,頂點由用戶輸入;

static void TESTlineCmd()
{
 
 
ads_point inputStart;
ads_point inputEnd;
 
 
AcGePoint3d ptStart;
AcGePoint3d ptEnd;
 
 
////用戶輸入要畫的座標
if (acedGetPoint(NULL,_T("\nstart point"),inputStart) != RTNORM)
{
 
 
return;
}
ptStart[X] = inputStart[X];
ptStart[Y] = inputStart[Y];
ptStart[Z] = inputStart[Z];
 
 
if (acedGetPoint(NULL,_T("\nend point"),inputEnd) != RTNORM)
{
 
 
return;
}
ptEnd[X] = inputEnd[X];
ptEnd[Y] = inputEnd[Y];
ptEnd[Z] = inputEnd[Z];
 
 
AcDbLine* pLine = new AcDbLine(ptStart,ptEnd);
 
 
int colorIndex = SelColor();
AcCmColor color;
color.setColorIndex(colorIndex);
pLine->setColor(color);
 
 
LoadEntity(pLine);
}

 

 

//第二題:定義一個LISP函數,功能:使用全局函數創建一個簡單實體-圓,返回圓的實體數據鏈表,圓心和半徑由用戶輸入;

static int ads_circle()
{
 
 
ads_point pt;
if(acedGetPoint(NULL,_T("\n選擇圓心"),pt) != RTNORM)
{
 
 
return 0;
}
 
 
ads_real realNum;
if(acedGetReal(_T("\n輸入半徑"),&realNum)!= RTNORM)
{
 
 
return 0;
}
 
 
////垂直平面法向量
AcGeVector3d vec(0,0,1);
////圓心
AcGePoint3d ptCenter(pt[X],pt[Y],pt[Z]);
 
 
AcDbCircle* pCircle = new AcDbCircle(ptCenter,vec,realNum);
 
 
LoadEntity(pCircle);
 
 
////打印出類型爲字符串的接收參數
resbuf* pInput = acedGetArgs();
CString str;
while (pInput != NULL)
{
 
 
if (pInput->resval.rstring != NULL)
{
 
 
acutPrintf(pInput->resval.rstring);
acutPrintf(_T("\n"));
}
pInput = pInput->rbnext;
}
 
 
////構造圓形實體
struct resbuf* rb ;
rb = acutBuildList(
RTDXF0,_T("CIRCLE"),
62,1,//1 == RED
10,ptCenter,
40,realNum,//radius
0);
 
 
acedRetList(rb);
 
 
return RTNORM;
}////函數在調用的時候需要加上括號 (func "param")

//第三題;輸入三點,以中間點爲頂點,把旁邊兩條線做圓角,半徑用戶輸入

static void TESTcomplexentcmd()
{
 
 
ads_point pt1;
ads_point pt2;
ads_point pt3;
ads_real r;
 
 
if (acedGetPoint(NULL,_T("\n輸入第一點"),pt1) != RTNORM)
{
return;
}
 
 
if (acedGetPoint(NULL,_T("\n輸入第二點"),pt2) != RTNORM)
{
return;
}
 
 
if (acedGetPoint(NULL,_T("\n輸入第三點"),pt3) != RTNORM)
{
return;
}
 
 
if (acedGetReal(_T("\n輸入內切圓半徑"),&r) != RTNORM)
{
return;
}
 
 
////座標維度轉化
AcGePoint3d pt3d1 = asPnt3d(pt1);
AcGePoint3d pt3d2 = asPnt3d(pt2);
AcGePoint3d pt3d3 = asPnt3d(pt3);
 
 
////構造兩條直線計算頂點到切點的距離
AcDbLine line1(pt3d2,pt3d1);
AcDbLine line2(pt3d2,pt3d3);
 
 
////得到以PT2爲頂點的兩個向量
AcGeVector3d v1(pt1[X]-pt2[X],pt1[Y]-pt2[Y],pt1[Z] - pt2[Z]);
AcGeVector3d v2(pt3[X]-pt2[X],pt3[Y] - pt2[Y],pt3[Z] - pt2[Z]);
AcGeVector3d v3(0,0,1);
 
 
double PI = 3.1415926536;
////計算兩個向量的夾角
 
 
double angle = v1.angleTo(v2,v3);
double angle1 = angle > PI ? 2 * PI - angle : angle;
 
 
////計算切點到頂點距離
double dist = r / tan(angle1 / 2);
 
 
////切點1
AcGePoint3d ptQ1;
////切點2
AcGePoint3d ptQ2;
 
 
////找到切點
line1.getPointAtDist(dist,ptQ1);
line2.getPointAtDist(dist,ptQ2);
 
 
////求出bulge值(是圓心角1/4的正切值 - - ,之前當成正切值的四分之一了 - -!!!)
double bulge;
bulge = tan((PI - angle1) / 4);
if(angle > 0 && angle <= PI)
{
bulge = - bulge;
}
 
 
 
 
AcDbPolyline* pl = new AcDbPolyline();
AcGePoint2d pt2d1(pt3d1[X],pt3d1[Y]);
AcGePoint2d pt2dq1(ptQ1[X],ptQ1[Y]);
AcGePoint2d pt2dq2(ptQ2[X],ptQ2[Y]);
AcGePoint2d pt2d3(pt3d3[X],pt3d3[Y]);
 
 
pl->addVertexAt(0,pt2d1,0);
pl->addVertexAt(1,pt2dq1,bulge);
pl->addVertexAt(2,pt2dq2,0);
pl->addVertexAt(3,pt2d3,0);
 
 
LoadEntity(pl);
 
 
 
 
CString out;
out.Format(_T("\nangle:%.2f,bulge:%.2f,\ndist:%.2f\n,pt[z]:%.2f,%.2f,%.2f"),angle,bulge,dist,pt1[Z],pt2[Z],pt3[Z]);
acutPrintf(out);
 
 
}


 

//第四題:定義一個全局命令,功能:使用類庫創建一個塊表記錄,並插入塊;

static void TESTaddblkcmd()
{
////根據用戶的輸入設置塊表記錄的名稱
CString blkName;
if (acedGetString(Adesk::kFalse,_T("\n輸入塊名稱"),blkName.GetBuffer(20)) != RTNORM)
{
return;
}
 
 
////用完getBuffer要及時release
blkName.ReleaseBuffer();
 
 
AcDbBlockTable* pBlkTbl;
acdbHostApplicationServices()->workingDatabase()->getBlockTable(pBlkTbl,AcDb::kForWrite);
 
 
AcDbObjectId rcdId ;
 
 
////如果沒有,添加新的
if (!pBlkTbl->has(blkName))
{
////創建新塊
AcDbBlockTableRecord* pBlkTblRcd;
pBlkTblRcd = new AcDbBlockTableRecord();
pBlkTblRcd->setName(blkName);
 
 
////將塊表記錄添加到塊表中,設置ID
pBlkTbl->add(rcdId,pBlkTblRcd);
 
 
////向塊表記錄中添加實體
AcGePoint3d ptStart(-10,0,0),ptEnd(10,0,0);
AcDbLine* pLine1 = new AcDbLine(ptStart,ptEnd);
ptStart.set(0,-10,0);
ptEnd.set(0,10,0);
AcDbLine *pLine2 = new AcDbLine(ptStart,ptEnd);
 
 
AcGeVector3d vecNormal(0,0,1);
AcDbCircle *pCircle = new AcDbCircle(AcGePoint3d::kOrigin,vecNormal,6);
AcDbObjectId entId;
pBlkTblRcd->appendAcDbEntity(entId,pLine1);
pBlkTblRcd->appendAcDbEntity(entId,pLine2);
pBlkTblRcd->appendAcDbEntity(entId,pCircle);
////關閉實體塊表記錄
 
 
pLine1->close();
pLine2->close();
pCircle->close();
pBlkTblRcd->close();
 
 
}////如果已經有了,那就根據名字讀出RECORDID,插入塊參照時會用到
else
{
pBlkTbl->getAt(blkName,rcdId,false);////以讀的方式獲取
}
 
 
////在和用戶交互之前,需要關閉塊表,否則容易出錯
pBlkTbl->close();
////插入塊
 
 
////獲得用戶輸入的塊參照的插入點
ads_point pt;
if(acedGetPoint(NULL,_T("\n輸入塊參照的插入點"),pt) != RTNORM)
{
pBlkTbl->close();
return;
}
AcGePoint3d ptInsert = asPnt3d(pt);
 
 
////創建塊參照
AcDbBlockReference* pBlkRef = new AcDbBlockReference(ptInsert,rcdId);
 
 
////將塊參照添加到模型空間
 
 
AcDbBlockTableRecord* pBlkTblRcd2;
pBlkTbl->getAt(ACDB_MODEL_SPACE,pBlkTblRcd2,AcDb::kForWrite);
pBlkTblRcd2->appendAcDbEntity(pBlkRef);
 
 
////關閉數據庫對象
pBlkRef->close();
pBlkTblRcd2->close();
pBlkTbl->close();
 
 
 
 
}


//第五題:定義一個命令,功能:讓用戶選擇界面上的直線實體,然後修改所有選中實體的顏色;
static void TESTchangecolorcmd()
{
 
 
ads_name ssname;
resbuf strFilter;
////只能選擇直線對象,構造選擇集過濾器,只能選直線
strFilter.resval.rstring = _T("LINE");
strFilter.rbnext = NULL;
strFilter.restype = 0;
 
 
////選擇多個實體,傳遞NULL,讓用戶自己來選
if(acedSSGet(NULL,NULL,NULL,&strFilter,ssname) != RTNORM)
{
 
 
return;
}
 
 
long len;
acedSSLength(ssname,&len);
CString ss;
ss.Format(_T("已選中%d個實體"),len);
acutPrintf(ss);
 
 
ads_name entname;
 
 
AcDbObjectId id;
AcDbEntity* ent = NULL;
CString strName;
 
 
 
 
////彈出顏色選擇對話框,選中一個顏色,默認是當前層的顏色
int nNewColor = SelColor();
 
 
for (int i=0;i<len;i++)
{
 
 
if (acedSSName(ssname, i, entname) == RTNORM)
{
 
 
////根據名稱得到ID
acdbGetObjectId(id,entname);
 
 
////以寫模式,根據ID索引到對象,並打開ENTITY
acdbOpenObject(ent,id,AcDb::OpenMode::kForWrite);
strName.Format(_T("%d"),ent->colorIndex());
acutPrintf(_T("\n"));
acutPrintf(strName);
 
 
ent->setColorIndex(nNewColor);
ent->close();
}
}
 
 
acedSSFree(ssname);
 
 
}
 
 
 
//-----------------------------------------------------------------------------
IMPLEMENT_ARX_ENTRYPOINT(CArxProject2App)
 
 
ACED_ARXCOMMAND_ENTRY_AUTO(CArxProject2App, TEST, lineCmd, lineCmd, ACRX_CMD_MODAL, NULL)
 
 
//ACED_ARXCOMMAND_ENTRY_AUTO(CArxProject2App, TEST, circlecmd, circlecmd, ACRX_CMD_MODAL, NULL)
 
 
ACED_ADSSYMBOL_ENTRY_AUTO(CArxProject2App, circle, false)
 
 
ACED_ARXCOMMAND_ENTRY_AUTO(CArxProject2App, TEST, changecolorcmd, changecolorcmd, ACRX_CMD_MODAL, NULL)
 
 
ACED_ARXCOMMAND_ENTRY_AUTO(CArxProject2App, TEST, addblkcmd, addblkcmd, ACRX_CMD_MODAL, NULL)
 
 
ACED_ARXCOMMAND_ENTRY_AUTO(CArxProject2App, TEST, complexentcmd, complexentcmd, ACRX_CMD_MODAL, NULL)

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章