Trang

Hiển thị các bài đăng có nhãn Thuc the Proxy. Hiển thị tất cả bài đăng
Hiển thị các bài đăng có nhãn Thuc the Proxy. Hiển thị tất cả bài đăng

Chủ Nhật, 2 tháng 6, 2013

Loại bỏ toàn bộ thực thể Proxy trong bản vẽ bằng ObjectARX

Đặt vấn đề
Nếu không có ứng dụng liên quan, làm thể nào để làm việc với bản vẽ có chứa nhiều thực thể proxy (custom entities). Hay làm thế nào để sử dụng dữ liệu trong bản vẽ, như là để xây dựng đối tượng hình học mới. Một vài thực thể có thể explode, nhưng một số khác lại không giống như không thể xóa được chúng vậy. Dù có được các thực thể AutoCAD tương đương nhưng những thực thể proxy vẫn còn đó. Cần phải làm gì?
Giải pháp
Hoàn toàn có thể dùng ObjectARX để chuyển mọi thực thể proxy thành bất cứ cái gì. Ví dụ sau sẽ lặp lại qua bản vẽ và đổi tất cả thực thể Proxy thành một block vo danh. Các block đó chưa đựng các thành phần đồ họa tương đương với thực thể Proxy. Lưu ý rằng việc làm đó không cho phép bạn tạo ra các thực thể mới để lấy được thông tin lưu giữ trong thực thể gốc.
AcDbObjectIdArray proxies;  

// Iterate through the records  
// Make a list of all the proxies, and then process them afterwards. 
AcDbBlockTable* pTable; 
acdbHostApplicationServices()->workingDatabase()->getBlockTable
                                                    (
                                                        pTable,
                                                        AcDb::kForRead
                                                    );
if(pTable == NULL)
    return

AcDbBlockTableIterator* pTableIter;
for( pTable->newIterator(pTableIter); !pTableIter->done(); pTableIter->step())
{     
    AcDbBlockTableRecord* pRecord;     
    pTableIter->getRecord(pRecord,AcDb::kForRead);  
    if(pRecord == NULL)
    {   
        acutPrintf(_T("\nCannot open a BTR"));  
        continue;   
    } 

    AcDbBlockTableRecordIterator* pRecordIter;
    for (    pRecord->newIterator(pRecordIter);
            ! pRecordIter->done();
            pRecordIter->step()
        )
    {
        AcDbEntity*pEnt;    
        pRecordIter->getEntity(pEnt, AcDb::kForRead);
        if(pEnt != NULL )
        {
            if( pEnt->isKindOf(AcDbProxyEntity::desc()))
            {        
                proxies.append(pEnt->objectId() );   
            }          
            pEnt->close();    
        }    
    }   
    delete pRecordIter;   
    pRecord->close(); 
}  

delete pTableIter;
if( Acad::eOk != pTable->upgradeOpen())
{   
    acutPrintf(_T("\nCannot open table for Write"));
    pTable->close();
    return;
}
int nProxies = proxies.length(); 
for( int i=0;i<nProxies; i++ )
    AcDbProxyEntity* pProxy;  
    AcDbObject* pObj;   
    acdbOpenAcDbObject(pObj, proxies[i], AcDb::kForRead);
    pProxy = AcDbProxyEntity::cast(pObj); 
    if( NULL == pProxy )
    {   
        pObj->close () ;  
        continue
    }    
    AcDbVoidPtrArray explodedEnts; 
    pProxy->explode(explodedEnts);
    int nExplodedEnts = explodedEnts.length();
    if( nExplodedEnts > 0 )
    {       
        AcDbBlockTableRecord*pRecord = new AcDbBlockTableRecord();
        pRecord->setName(_T("*B")); 
        AcDbObjectId blockId;   
        pTable->add(blockId, pRecord ); 
        for( int j=0; j<nExplodedEnts; j++)
        {        
            AcDbEntity*pEnt =(AcDbEntity*)(explodedEnts[j]);
            pRecord->appendAcDbEntity(pEnt);
            pEnt->setColorIndex(0);     
            pEnt->close();       
        }      
        pRecord->close(); 
        AcDbBlockTableRecord* pOwningRecord; 
        acdbOpenObject    (   
                            pOwningRecord,
                            pProxy->ownerId(),
                            AcDb::kForWrite
                        ); 
        if( NULL != pOwningRecord)
        {   
            AcDbBlockReference* pRef = new AcDbBlockReference; 
            pRef->setBlockTableRecord(blockId);      
            pOwningRecord->close();       
            pProxy->upgradeOpen();         
            pProxy->handOverTo(pRef); 
            pRef->setColor(pProxy->color()); 
            pRef->setLayer(pProxy->layerId()); 
            pRef->setVisibility(pProxy->visibility());
            delete pProxy;      
            pRef->close();       
        }     
    }     
    else
    { 
        pProxy->close();
    }  
}
pTable->close();


Link nguồn: Adndevblog

Thứ Bảy, 1 tháng 6, 2013

Lấy thông tin từ thực thể proxy (Getting proxy entity’s information)

Làm thế nào để lấy được thông tin của thực thể proxy?

Bạn có thể sử dụng lớp “AcDbProxyEntity” để lấy tên gốc (original name), tên dxf gốc (original dxf name) và số lượng tham chiếu của thực thể proxy (particular entity’s proxy) trong bản vẽ.
Đoạn mã dưới đây trình bày hàm để lấy tên gốc và tên dxf gốc của thực thể proxy.
int nReturn ;
ads_name name;
ads_point pt;

nReturn = acedEntSel(_T("Select proxy entity\n"), name, pt);

if (nReturn != RTNORM)
return;

//Lấy ObjectId của thực thể
AcDbObjectId Id;
if(acdbGetObjectId(Id, name) != Acad::eOk)
return;

//Mở thực thể được chọn
AcDbObject *pObject = NULL;
if(acdbOpenAcDbObject(pObject, Id, AcDb::kForRead) != Acad::eOk)
{
    return;
}

AcDbProxyEntity *pProxy = AcDbProxyEntity::cast(pObject);

if(pProxy != NULL)
{
    acutPrintf(_T("Original class name : %s\n"), pProxy->originalClassName());

    acutPrintf(_T("DXF name : %s\n"), pProxy->originalDxfName());

    acutPrintf(_T("Description : %s\n"), pProxy->applicationDescription());
}

pObject->close();
File Arx: Lệnh GPI hoặc hàm defun (lh_getproxyinform ent)
Download tại Mediafire

Ngoài ra, theo Zatopek từ diễn đàn AutoDesk có 02 cách để lấy được dữ liệu hình học của thực thể trong Proxy.
Trước tiên, bạn cần lấy được AcDbProxyEntity, từ đó dùng hàm getGeomExtens, và bạn có thể phá vỡ nó (nếu cho phép).
Hàm getGeomExtents:
Hàm này điền vào trong mở rộng (extent) với những mở rộng gần đúng. Nếu proxy có đồ họa được ghi lại, từ đó chúng được dùng để tính toán extent. Nếu proxy chỉ có đường bao thì mở rộng cũng chỉ là đường bao hộp mà thôi.
Phá vỡ Explode:
Hàm này tạo ra bản sao của tất cả đối tượng đồ họa nguyên thủy lưu giữ trong proxy và thêm con trỏ tới những thực thể mới tạo ra vào trong mảng thực thể entitySet. Hàm trả về Acad::eOk nếu thành công, ngược lại là Acad::eCannotExplodeEntity (không thể explode).

Hãy xem thêm các giải pháp bên trong:
[Arx path]\samples\database\ARXDBG\Inc\ArxDbgWorldDraw.h
[Arx path]\samples\database\ARXDBG\Tests\ArxDbgWorldDraw.cpp
[Arx path]\samples\database\ARXDBG\Inc\ArxDbgViewportDraw.h
[Arx path]\samples\database\ARXDBG\Tests\ArxDbgViewportDraw.cpp
Arx path là thư mục cài đặt bộ ObjectARX SDK.
 
Link tham khảo:
http://adndevblog.typepad.com
http://forums.autodesk.com

Thứ Bảy, 16 tháng 3, 2013

Bài 14: Tự tạo một thực thể (từng bước một)

Xin chào,

Trong bài này, tôi sẽ tiếp tục hoàn thành bài 13 với một hướng dẫn để trình bày cho bạn biết cách tạo một thực thể đơn giản, từng bước một. Thực thể này có một vài tính năng giúp bạn thấy được cái gì có thể xảy ra khi sử dụng ObjectARX.
Hãy đọc cẩn thận những chỉ dẫn sau đây.
-Tạo một Giải pháp trống (Blank Solution) gọi là CustomEntitySample;
-Thêm một dự án DBX có tên CustEntityDBX;
-Thêm dự án ARX tên là CustEntityARX;
-Hãy nhớ bật mở rộng MFC trong cả hai dự án;
-Tạo một phụ thuộc (dependency) từ dự án ARX tới DBX:

Tạo một phụ thuộc Dependency



-Vào dự án DBX và mở Autodesk Class Explorer;
-Click chuột phải vào nhánh CustEntityDBX và chọn "Add ObjectDBX Custom Object...":


-Chọn tên lớp MyCustomEntity và dẫn xuất nó từ lớp AcDbEntity;
-Các thông tin khác sẽ được điền tự động (Bạn có thể thay đổi nếu muốn);


-Vào TAB Protocols và bật cả hai giao thức OsnapGrip-points:


-Xây dựng lại Rebuild dự án nếu mọi việc hoàn thành;
-Bây giờ mở lại Autodesk Class Explorer, vào dự án CustEntityDBX;
-Chọn nhánh MyCustomEntity (nếu không nhìn thấy, click vào biểu tượng Refresh);
-Click chuột phải vào nó và chọn "Add Variable...":


-Đặt tên nó là "m_PtA", kiểu AcGePoint3d và kiểu truy suất là protected;
-Bật "Participate to DWG filing protocol" (tham gia giao thức điền DWG), Tắt "Increase Version number" (Tăng số hiệu phiên bản);
-Bật "Implement Get/Put methods" và điền ghi chú cần thiết;
-Lặp lại quá trình trên với các biến : "m_PtB", "m_PtAB" và "m_PtBA":


-Bây giờ, thêm một biến kiểu CString có tên "m_Text";
-Nhớ sửa chữa thao tác CString và điền đầy đủ như những gì ta đã làm trong Lab3;
-Bây giờ bạn đã có thể chạy biên dịch;


Trước khi tiếp tục, chúng ta cần loại bỏ vài hàm không sử dụng đến. Đầu tiên loại bỏ trong tệp tiêu đề Header (*.h):

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);
Có 4 phương thức getOsnapPoints(). Chúng ta chỉ sử dụng một phương thức sau:

virtual Acad::ErrorStatus getOsnapPoints (
AcDb::OsnapMode osnapMode,
int gsSelectionMark,
const AcGePoint3d &pickPoint,
const AcGePoint3d &lastPoint,
const AcGeMatrix3d &viewXform,
AcGePoint3dArray &snapPoints,
AcDbIntArray &geomIds) const ;

Nào, bạn sẽ cần xóa phần thân của các hàm trong tệp tin cpp.

WORLDDRAW


-Để vẽ thực thể custom entity, chúng ta cần thêm đoạn mã sau vào phương thức worldDraw():

assertReadEnabled();
// Bounding Polyline
AcGePoint3d pts[4];
pts[0] = m_PtA;
pts[1] = m_PtAB;
pts[2] = m_PtB;
pts[3] = m_PtBA;
mode->subEntityTraits().setSelectionMarker(1); // Mark 1
mode->subEntityTraits().setColor(1); // Red
mode->geometry().polygon(4,pts);
// Entity's Text
mode->subEntityTraits().setSelectionMarker(2); // Mark 2
mode->subEntityTraits().setColor(256); // ByLayer
AcGiTextStyle style;
style.setFileName(_T("txt.shx"));
style.setBigFontFileName(_T(""));
style.setTextSize(25);
style.loadStyleRec();
AcGePoint3d txtPt((m_PtB.x+m_PtA.x)/2.0, (m_PtB.y+m_PtA.y)/2.0, m_PtA.z);
mode->geometry().text(txtPt, AcGeVector3d::kZAxis,
(m_PtAB-m_PtA),m_Text, m_Text.GetLength(),Adesk::kFalse, style);
return Adesk::kTrue;

Các điểm GRIP

-Mở phương thức getGripPoints() bên trong thực thi MyCustomEntity (cpp);
-Chúng ta sẽ bật 5 điểm grips cho thực thể. Các điểm góc (A,B,AB và BA) cộng với điểm ở tâm;
-Bên trong getGripPoints(), thêm đoạn mã sau:
gripPoints.append(m_PtA);
gripPoints.append(m_PtAB);
gripPoints.append(m_PtB);
gripPoints.append(m_PtBA);
gripPoints.append(AcGePoint3d((m_PtB.x+m_PtA.x)/2.0,
(m_PtB.y+m_PtA.y)/2.0,m_PtA.z));
-Bây giờ, khi người dùng click vào mỗi điểm Grip, chúng ta sẽ tiến hành các hành động tương ứng thông qua phương thức moveGripPointsAt();
-Chúng ta cần phải kiểm tra chỉ số của mỗi điểm Grip được kích hoạt tương ứng với phương thức getGripPoints() và áp dụng các biến đổi cần thiết;
-Trong phương thức còn lại moveGripPointsAt(), thêm đoạn mã sau:
assertWriteEnabled();
for(int i=0; i<indices.length(); i++) {
int idx = indices.at(i);
// For A and center point
if (idx==0 idx==4) m_PtA += offset;
// For AB and center point
if (idx==1 idx==4) m_PtAB += offset;
// For B and center point
if (idx==2 idx==4) m_PtB += offset;
// For BA and center point
if (idx==3 idx==4) m_PtBA += offset;
}
return (Acad::eOk);

Các điểm OSNAP

-Mở phương thức getOsnapPoints(). Chúng ta sẽ thêm 3 điểm Osnap kiểu: EndPoint, MidPoint and Center:
assertReadEnabled();
switch (osnapMode) {
case AcDb::kOsModeEnd:
snapPoints.append(m_PtA);
snapPoints.append(m_PtAB);
snapPoints.append(m_PtB);
snapPoints.append(m_PtBA);
break;
case AcDb::kOsModeMid:
snapPoints.append(m_PtA+((m_PtAB-m_PtA).length()/2.0)*((m_PtAB-m_PtA).normalize()));
snapPoints.append(m_PtAB+((m_PtB-m_PtAB).length()/2.0)*((m_PtB-m_PtAB).normalize()));
snapPoints.append(m_PtB+((m_PtBA-m_PtB).length()/2.0)*((m_PtBA-m_PtB).normalize()));
snapPoints.append(m_PtBA+((m_PtA-m_PtBA).length()/2.0)*((m_PtA-m_PtBA).normalize()));
break;
case AcDb::kOsModeCen:
snapPoints.append(AcGePoint3d((m_PtB.x+m_PtA.x)/2.0,
(m_PtB.y+m_PtA.y)/2.0, m_PtA.z));
break;
}
return (Acad::eOk);

BIẾN ĐỔI


-Thực thể biến đổi được thực hiện bởi phương thức transformBy();
-Mở Autodesk Class Explorer, mở rộng nhánh MyCustomEntity, -> nhánh Base Classes và sau cùng là nhánh AcDbEntity;
-Kéo danh sách xuống và lựa chọn:

Acad::ErrorStatus transformBy(const AcGeMatrix3d &);

-Click chuột phải trong phương thức này và chọn "Implement Base Class Method";
-Hàm logic này rất đơn giản, chỉ cần thêm đoạn mã sau:

assertWriteEnabled();
m_PtA.transformBy(xform);
m_PtAB.transformBy(xform);
m_PtB.transformBy(xform);
m_PtBA.transformBy(xform);
return (Acad::eOk);
-Hàm này sẽ cho phép thực thể có thể biến đổi được;

DỰ ÁN ARX


-Đầu tiên chúng ta sẽ thêm lệnh mới có tên "MyCustEnt";
-Nó sẽ tạo ra phương thức bên trong tệp acxrEntryPoint.cpp;
-Bây giờ, thêm chỉ thị cần cần thiết sau #include "StdAfx.h":

#include "..\CustEntityDBX\MyCustomEntity.h"
-Trong phương thức, chúng ta sẽ tạo ra thực thể:

// Input information
ads_point pt1,pt2;
if (acedGetPoint(NULL,_T("Set the first point:\n"),pt1) != RTNORM)
return;
if (acedGetCorner(pt1,_T("Set the second point:\n"),pt2) != RTNORM)
return;

TCHAR buffer[512];
if (acedGetString(0,_T("Enter the text:\n"),buffer) != RTNORM)
return;

// Setup entity
MyCustomEntity *pEnt = new MyCustomEntity();
pEnt->put_m_PtA(asPnt3d(pt1));
pEnt->put_m_PtAB(AcGePoint3d(pt2[X],pt1[Y],pt1[Z]));
pEnt->put_m_PtB(asPnt3d(pt2));
pEnt->put_m_PtBA(AcGePoint3d(pt1[X],pt2[Y],pt2[Z]));
pEnt->put_m_Text(buffer);

// Post to Database
AcDbBlockTable *pBlockTable;
acdbHostApplicationServices()->workingDatabase()->getSymbolTable(pBlockTable,
AcDb::kForRead);

AcDbBlockTableRecord *pBlockTableRecord;
pBlockTable->getAt(ACDB_MODEL_SPACE, pBlockTableRecord,AcDb::kForWrite);
pBlockTable->close();

AcDbObjectId retId = AcDbObjectId::kNull;
pBlockTableRecord->appendAcDbEntity(retId, pEnt);
pBlockTableRecord->close();
pEnt->close();

TEST


-Rebuild lại dự án;
-Mở AutoCAD và tải module DBX trước tiên rồi tải ARX;
-Bắt đầu lệnh MYCUSTENT và tạo bao nhiêu thực thể bạn muốn;
-Kiểm tra nó thông qua chỉnh sửa GRIP, MOVE, ROTATE, SCALE;
-Thực hiện lệnh LINE và thử bắt điểm (EndPoint, MidPoint và Center) trên thực thể xem sao;


Link nguồn: Arxdummies

Thư viện AutoLISP mở rộng Doslib (Phần 2)

Các hàm thiết lập -------------------------------------------------------------------------------- dos_getini Trả về giá trị từ tệp tin INI ...