ObjectARX & Dummies

Course Index

*Course support: Click here!
*Course and User samples: Download here!

Wednesday, March 09, 2005

Class 6 - Entities

Introduction

Entities are objects that has a graphical representation. They could be simple or complex depending on how many features and functionalities they implement. Entities are stored into BlockTableRecord container objects. Each of these containers will keep its entities until they are erased or Database is destroyed. As any other database resident object, each entity can be accessed through its unique ObjectId. Using its ObjectId we can then acquire its pointer (for Read, Write or Notify as we saw on previous class) and then perform desired operations.

Some special entities contains also another objects to simplify implementation and management. A good example of this approach is AcDb3dPolyline which has a collection of AcDb3dPolylineVertex objects that represents each of its vertexes.

Entity Properties


AutoCAD entities has several properties and some of them are common to all kind of entity. These properties are stored into entity's base class called AcDbEntity. This class, also derived from AcDbObject implements several common functionalities that will be used by every derived class and related implemented entity.

If we create a circle (AcDbCircle), for example, it will contain some properties that came from AcDbEntity. These properties are:

  • Color
  • Linetype
  • Linetype scale
  • Visibility
  • Layer
  • Line weight
  • Plot style name

These properties has specific access methods that will allow you to read or modify them accessing the AcDbEntity base class. So, if we get our AcDbCircle entity and would like to change its color we just need to open it for Write, access the proper method and then close the circle.

If we need to build an application that only access these properties we really don't need to know what kind of entity we are opening. In this situation we just need to open our entity, get its pointer as an AcDbEntity pointer and access the desired method.

Entity Transformations

Each AutoCAD entity is placed into a 3D space. You already know that we can move, rotate, scale, align and many other modifications over an entity. AutoCAD threats most of these operations using geometric algebra using matrixes. Remember that we have talked about ObjectARX classes and, specially in this case, about AcGe prefixed classes. The AcGe classes are geometric classes which will allow you to perform simple and complex geometric operations inside AutoCAD.

So let's suppose you need to perform a rotation over several entities (circles, polylines, lines, etc.) and need to do this with minimum effort and basic geometric knowledge. No big deal! We just need to build a transformation matrix and call the appropriate method called transformBy() implemented by AcDbEntity class. Yes, every entity could be potentially transformed!

This function receives an object of class AcGeMatrix3d which represents the matrix to be applied to the entity that will perform some geometric operation. This could be a transformation matrix, a rotation matrix and so on.

This class has wonderful utility functions that will reduce your work a lot! Among these functions I would like to quote the following:

  • setToRotation: You pass in the desired angle (in radians), the axis vector of rotation and the point of rotation. With this parameters this function will fill the AcGeMatrix3d with all elements. After that, just call your entity's transformBy() method passing this matrix in;
  • setToTranlation: You just pass in a 3D vector (AcGeVector3d) which represents the transformation you would like to perform. After that, do the same operation as mentioned above;
  • setToMirroring: This function has 3 versions that receives a point (AcGePoint3d), a line (AcGeLine3d) or a plane (AcGePlane). Depending on what type of parameter you pass in it will build the proper matrix to mirror your entity! Great hum?

Entity Intersection

Another important functionality implemented at AcDbEntity level is entity intersection. Probably one of your future products will need to analyze entities intersections. The method intersectWith() is the responsible to do this job for you.

The most common signature of this method receives the argument entity pointer (the entity you would like to test with yours), the intersection type, an array of 3D points to be filled out by this functions with intersection points found and, optionally the GS marker of both entities which represents the subentity index.

The intersection type must be one of the following operands:

  • kOnBothOperands: neither entity is extended;
  • kExtendThis: extend this entity;
  • kExtendArg: extend argument entity;
  • kExtendBoth: extend both entities.

If these two entities intercept each other (obviously depending on which type of intersection you specify) the passed array will receive the intersection points. This function is very useful and uses the core geometric engine of AutoCAD which make it fast and reliable.

Our next class will be a demo example and I would give you a couple of days to accomplish it and then I will post my solution to it. Stay tuned!

69 Comments:

  • Hi Fernando,

    How can I access the attributes of an entity?

    Here's where I'm at in my code: I've iterated through the block table record, checked each entity to see if it's name is that of the entities I'm looking for, but now I don't know how to read the attributes.

    Thanks so much for any help you can provide.

    -Carlos

    By Blogger carlos, at 8:31 PM  

  • Hi Carlos,

    You may use something like this:

    static void ListAttributes_LISTATT(void) {
    ads_name ename ;
    ads_point pt ;

    if (acedEntSel ("Please, select an existing block: ", ename, pt) != RTNORM)
    return;

    AcDbObjectId id = AcDbObjectId::kNull;
    acdbGetObjectId (id, ename) ;

    if (id == AcDbObjectId::kNull)
    return;

    AcDbBlockReference *pRef = NULL;
    // Open the entity (it will be closed at the end of this funcion
    if (acdbOpenAcDbObject ((AcDbObject *&)pRef, id, AcDb::kForRead) != Acad::eOk) {
    acutPrintf("\nError opening the entity!!!");
    return;
    }

    // Check if it is a BlockReference
    if (!pRef->isKindOf(AcDbBlockReference::desc())) {
    pRef->close();
    acutPrintf("\nPlease, select a block reference!!!");
    return;
    }

    // First we will look into BlockReference entity looking for
    // all non-constant attributes which are stored into block insertions
    AcDbObjectIterator *pIter = pRef->attributeIterator() ;
    acutPrintf("\nBlock's Non-constant Attributes:");
    while ( !pIter->done () ) {
    AcDbEntity *pAttEnt = NULL;
    AcDbObjectId idAtt = pIter->objectId();
    if (acdbOpenObject(pAttEnt,idAtt,AcDb::kForRead) == Acad::eOk) {
    if (pAttEnt->isKindOf(AcDbAttribute::desc())) {
    // Here you can read Attribute information
    AcDbAttribute* pAtt = AcDbAttribute::cast(pAttEnt);
    CString msg;
    msg.Format("\nTAG:%s - VALUE:%s",pAtt->tag(),pAtt->textString());
    acutPrintf(msg);
    }
    pAttEnt->close();
    }
    pIter->step();
    }
    delete pIter ;

    // Now we will open the main block definition (BlockTableRecord)
    // and will look for the Constant Attribute information
    id = pRef->blockTableRecord();
    AcDbBlockTableRecord *pRec = NULL;

    if (acdbOpenAcDbObject((AcDbObject*&)pRec,id,AcDb::kForRead) == Acad::eOk) {
    if ( pRec->hasAttributeDefinitions () == Adesk::kTrue ) {
    // Create a new iterator
    AcDbBlockTableRecordIterator *pIter2 = NULL;
    pRec->newIterator(pIter2) ;
    acutPrintf("\n\nBlock's Constant Attributes:");

    // Walk through attributes
    while ( !pIter2->done () ) {
    AcDbEntity *pEnt = NULL;
    pIter2->getEntity(pEnt, AcDb::kForRead) ;

    if (pEnt) {
    if ( pEnt->isKindOf (AcDbAttributeDefinition::desc ()) ) {
    AcDbAttributeDefinition *pDef = AcDbAttributeDefinition::cast(pEnt);
    if ( pDef->isConstant () == Adesk::kTrue ) {
    CString msg;
    msg.Format("\nTAG:%s - VALUE:%s",pDef->tag(),pDef->textString());
    acutPrintf(msg);
    }
    }
    pEnt->close();
    }
    // Go to the next
    pIter2->step();
    }
    delete pIter2 ;
    }
    // Close the BTR
    pRec->close () ;
    }
    // Close the entity
    pRef->close () ;
    }

    By Blogger Fernando Malard, at 11:02 PM  

  • Carlos,

    If you prefer, download the sample from here:

    http://www.drawex.com/ThirdParty/files/ObjectARX/Samples/ListAttributes.zip

    Regards,
    Fernando.

    By Blogger Fernando Malard, at 11:07 PM  

  • Carlos:

    Nice article.

    Can you give me a sample of IntersectsWith code in .Net? I am basically looking to find all blocks which touch an endpoint or midpoint of my block and need to report on that.

    Naresh Nichani

    By Anonymous Naresh Nichani, at 10:34 AM  

  • Dear Fernanodo

    I have some problem
    1- I have MFC Dialog that contain 2 button on click first button the all entity colored with red and on click second button each entity reset to original color (black ... red ...Green…)

    What is the best way to do Color and undo Color?


    2- I have MFC Dialog that contain 2 buttons on click first the all entity hide and on click second click second button each entity reset hide

    What is the best way to do this?

    Best Regards
    M.S

    By Anonymous Anonymous, at 8:38 AM  

  • Dear Fernanodo

    I have a problem
    1- I have MFC Dialog that contain 2 button on click first button the all entity colored with red and on click second button each entity reset to original color (black ... red ...Green…)

    What is the best way to do Color and undo Color?
    Is any way to attach data to entity?

    By Anonymous Anonymous, at 3:31 AM  

  • Dear All

    please how to delete entity if I get Object id

    Regards,
    Ahmad Ali

    By Anonymous Anonymous, at 7:16 AM  

  • Hi M.S.,

    The only way to "remember" the old value is storing it inside somewhere. You may use the XData or XRecord of each entity and store the last value of color. With this information your command will be able to retrieve this information even at another drawing session.

    Take a look at the sample:
    \ObjectARX 2007\samples\database\xrecord_dg

    Regards,
    Fernando.

    By Blogger Fernando Malard, at 10:43 AM  

  • Hi Ahmad,

    You can not delete a database resident entity. You need to open it for write, call its erase() method and then call close() method.

    This will remove the entity from its database owner but will not free its used memory (this is a known AutoCAD API limitation).

    Regards,
    Fernando.

    By Blogger Fernando Malard, at 10:46 AM  

  • Hi Fernando,

    How to export some entity from drawing file to another drawing.

    cheers
    Jawad

    By Anonymous Anonymous, at 10:30 AM  

  • Hi Jawad,

    There is a sample which demonstrate this. The process is called wblockclone.

    Take a look at:
    ObjectARX2007\Samples\Database\Clones

    The process can be complex depending on what your entity may contain or refer to.

    Further, take a look at the AcDbDatabase::wblockCloneObjects() method. A good example of its use is inside ArxDbgCmdTests::testWblockCloneObjects() method at the sample:
    ObjectARX2007\Samples\Database\ArxDBG

    By Blogger Fernando Malard, at 10:43 AM  

  • Hi

    How to copy entityt to another entity

    I need to put value of entity pEntity1 to pEntity2

    AcDbEntity * pEntity1;//line Entity
    AcDbEntity * pEntity2;//Empty

    Jawad.

    By Anonymous Anonymous, at 4:03 AM  

  • I use Clone is it valid

    and how to convert AcRxObject to AcDbEntity


    Jawad.

    By Anonymous Anonymous, at 4:37 AM  

  • I cant understand parameter 4 from this line

    es = fromDb->wblockCloneObjects(cloneSet, destBlkId, idMap, static_cast< AcDb::DuplicateRecordCloning >(prDrc.value()));

    Jawad.

    By Anonymous Anonymous, at 5:31 AM  

  • Dear fernando,

    I use ARX sample and it work

    I copy entity from dwg to another

    Thanks....

    but is any way to move entity to exact(is it applicable) layer "layer5" for Example.

    Regards,
    Jawad.

    By Anonymous Anonymous, at 7:11 AM  

  • Hi,

    Take a look at the clone() method. Another approach is to use the AcDbDatabase method called deepCloneObjects().

    Regards,
    Fernando.

    By Blogger Fernando Malard, at 8:30 AM  

  • Hi,

    AcRxObject is the base class of almost all ObjectARX classes.

    To convert, you just need to use the cast() method which will cast the pointer if possible or set your pointer to NULL if it's not possible to cast.

    Regards,
    Fernando.

    By Blogger Fernando Malard, at 8:32 AM  

  • Hi,

    The 4th parameter is about how the process will handle duplicate records. Imagine you have a layer with the same name in both source and destination databases.

    In this scenario you have 2 options:

    1)Copy your entity and use the existing layer inside the destination database;

    2)Copy your entity and its layer replacing the destination database layer. In this case, if this layer has different properties it will affect the other entities inside the destination database which are using this layer.

    Regards,
    Fernando.

    By Blogger Fernando Malard, at 8:36 AM  

  • Hi Fernando,

    i Have this code
    void ExportData::SetExportedDataBase(AcDbDatabase *& pExpDB, AcDbDatabase *pCurrentDB, HandleArray handleArray)
    {
    AcDbObjectId destBlkId;
    AcDbObjectIdArray cloneSet;

    cloneSet = GetObjectIDByHandleArray(handleArray, pCurrentDB);

    AcDbIdMapping idMap;
    Acad::ErrorStatus eee = idMap.setDestDb(pExpDB);
    destBlkId = pExpDB->currentSpaceId();
    Acad::ErrorStatus error= pCurrentDB->wblockCloneObjects(cloneSet,destBlkId, idMap, AcDb::kDrcIgnore);
    }

    Please how to export cloneset to layer "MyLayer" on new DWG

    Note: -The new layer Does not exist in new DWG

    Note :Destination DWG is Empty DWG

    Regards,
    Jawad.

    By Anonymous Anonymous, at 9:21 AM  

  • Hi Jawad,

    The layer and all other objects that the cloned objects depend on are automatically cloned too.

    If your layer is not used by any object included into your clone set it will not be cloned.

    To force its clone you may add this layer's ObjectId into your clone set array.

    See if this works and let me know.
    Regards,

    Fernando.

    By Blogger Fernando Malard, at 9:44 AM  

  • Hi fernando,

    sorry My English language is bad.....My mather language is arabic language(I am From Lebanon)

    but My scenario is copy all line from orginal DWG(Has Different Layer) to New DWG(Empty DWG) and create on new DWG layer "MyLayer" and then add all line to this layer

    NEW DWG is Empty..

    Regards,
    Jawad

    By Anonymous Anonymous, at 10:18 AM  

  • Hi Jawad,

    You will need to first copy all lines and with their new ObjectId you will need to open each one and set the ObjectId of your new layer inside destination database.

    This way you will need to first create this new layer, get its ObjectId, clone all lines, get their new ObjectId into destination database. Then you will need to open each new line and set the layerId() with your new layer's ObjectdId.

    Regards,
    Fernando.

    By Blogger Fernando Malard, at 10:50 AM  

  • Hi Fernanod,

    Thanks, I Start with this soloution

    Regards,
    Jawad

    By Anonymous Anonymous, at 2:55 AM  

  • Thanks so much Fernando,

    I finshed, really it solved my problem.

    Regards,
    Jawad.

    By Anonymous Anonymous, at 11:26 AM  

  • Hi Fernando!
    First of all thank you for all precious responses to my posts!
    I know time is critic, hope not to abuse..


    I try to create a some parametric 2D shapes.
    I just want to use the “classic” blocks, so I do not want to use custom entities, and not even the new dynamic blocks, just simple blocks.
    It is possible to have lets say 10 blocks, with 10 different aspects (different sizes, or more/less number of entities!!! in the same block), BUT ONLY ONE, a single definition of the block (AcDbBlockTableRecord)?

    If it's possible the block atributes can help here? If block atributes do not help, can I use other methods like in ObjectArx Labs Step 4 - Xrecords - Named Objects Dictionary or Step 5 - Custom Objects - Extension Dictionary?

    Best regards!
    Ioan

    By Blogger Bordei, at 8:51 AM  

  • Ioan,

    AcDbBlockTableRecord is an entity container like ModelSpace. It has a unique name definition by instance because its name is a key inside AcDbBlockTable container structure (exactly due that you cannot create two blocks with the same name).

    I cannot imagine any other way to do that except by creating a custom entity or a dynamic block.

    XRecords will not help you in this case.

    Regards.

    By Blogger Fernando Malard, at 9:04 AM  

  • Hello Fernando!
    I'm working with IAcadBlock COM entities.
    How could I determine and acces if exist, of course, the block references for a COM block?

    I'm asking if for COM does exist an ObjectARX equivalent like:

    ...
    AcDbBlockTableRecord *pBlockTableRecord ; AcDbObjectIdArray ids;
    pBlockTableRecord->getBlockReferenceIds(ids, true, false);
    ...

    It is possible to determine if
    this kind of entity BUT ONLY IN COM, has some reference.
    Using COM I can get the block, the name of it, but I want to check if has some references (inserts) in the current drawing, and if has to delete these references.

    Kind regards!
    Ioan

    By Blogger Bordei, at 4:29 PM  

  • Ioan,

    IAcadBlock does not have this method exposed. You will need to check the entire database and collect every IAcadBlockReference entity. For each one, you will need to use get_Name() and then search for this name inside BlockTable.

    I recommend you to create a MAP structure to cache found blocks because next time you don`t need to traverse the BlockTable again searching for the name you already found previously.

    Regards.

    By Blogger Fernando Malard, at 5:06 PM  

  • Excelent!
    Thank you Fernando!
    "I recommend you to create a MAP structure.." how it possbile to to this? Can you indicate some few steps, or to point some link to help me? I have never use MAP ..

    Best regards!
    Ioan

    By Blogger Bordei, at 5:21 PM  

  • Ioan, nevermind.
    I thought you will need to keep the ObjectId of each BlockTableRecord but you only need to know the BlockReferences names.

    So basically you need to get the name of each existing BlockReference and test if it is equal to the desired block name.

    Good luck.

    By Blogger Fernando Malard, at 5:29 PM  

  • Hello Fernando!
    I would like to get some information from a block insert using GetXData.

    To write XData is OK using the following code:

    long pos0 = 0;
    long pos1 = 1;
    long pos2 = 2;
    long pos3 = 3;
    short eString = 100;
    short eInteger = 90;

    _variant_t vType2Array;
    vType2Array.vt = VT_I2|VT_ARRAY;
    vType2Array.parray = SafeArrayCreateVector(VT_I2,0,4);
    SafeArrayPutElement(vType2Array.parray, &pos0, &eString);
    SafeArrayPutElement(vType2Array.parray, &pos1, &eString);
    SafeArrayPutElement(vType2Array.parray, &pos2, &eInteger);
    SafeArrayPutElement(vType2Array.parray, &pos3, &eInteger);

    _variant_t vData2Array;
    vData2Array.vt = VT_VARIANT|VT_ARRAY;
    vData2Array.parray = SafeArrayCreateVector(VT_VARIANT,0,4);
    SafeArrayPutElement(vData2Array.parray, &pos0, &_variant_t("TESTVALUE1"));
    SafeArrayPutElement(vData2Array.parray, &pos1, &_variant_t("TESTVALUE2"));
    SafeArrayPutElement(vData2Array.parray, &pos2, &_variant_t(long(111111)));
    SafeArrayPutElement(vData2Array.parray, &pos3, &_variant_t(long(222222)));

    hr = xrecord->SetXRecordData(vType2Array,vData2Array);

    I can not obtain XRecod using:


    VARIANT vType2Array;
    vType2Array.vt = VT_I2|VT_ARRAY;
    vType2Array.parray = SafeArrayCreateVector(VT_I2,0,4);
    VARIANT vData2Array;
    vData2Array.parray = SafeArrayCreateVector(VT_VARIANT,0,4);
    vData2Array.vt = VT_VARIANT|VT_ARRAY;
    hr =iblock->GetXData(_bstr_t("MYAPP"),&vType2Array,&vData2Array);

    CComBSTR szTmp;
    int i=3;
    SafeArrayGetElement(vData2Array.parray, (LONG*)&i, reinterpret_cast(void*)(&szTmp));


    What is wrong?
    Kind regards!
    Ioan

    By Blogger Bordei, at 1:45 PM  

  • Hello Ioan,

    I think the problem is the missing Application name when you are storing the data.

    The XData structure requires an "application name" as the root of its XData chain.

    So adding an application name as the first element of your XRecord XData should solve the problem.

    Regards.

    By Blogger Fernando Malard, at 2:16 PM  

  • Hello Fernando!
    To store the record I have used the following line:

    dictionary->AddXRecord(_bstr_t("MYAPP"),&xrecord);
    and the application name is the same in the both moments (write/read).

    Anyway thank you for all help provided in this virtual space!

    Best regards!
    Ioan

    By Blogger Bordei, at 2:22 PM  

  • Ioan,

    XData and XRecord are two different things. Are you mixing these features?

    You cannot add the data as XRecord and then get it as XData. You need to use the same data package to set and get.

    Check your method names:
    SetXRecordData()
    and
    GetXData()

    Regards.

    By Blogger Fernando Malard, at 2:27 PM  

  • Hello Fernando!
    You have absolute right! I have mixed the SetXRecordData with GetXData..

    All I want to do is to retrieve those data set using Xrecord SetXRecordData .

    From block insert I can get the dictionary.
    The problem is that the dictionary hasn't something like GetXRecordData..

    Could you indicate what is the way to get back these data already stored?

    Using C++ COM is an absolute dark in the ObjectARX documentation..

    Kind regards!
    Ioan

    By Blogger Bordei, at 2:40 PM  

  • Ioan,

    To get XRecord back you will need to open entity XRecords and look for an entry with your name "MYAPP". One you have found it, you can read the information.

    The best source of AutoCAD COM documentation is the VBA documentation because VBA uses COM behind the scenes to access AutoCAD. Of course COM syntax is much more complex but the methods are the same.

    Regards.

    By Blogger Fernando Malard, at 2:46 PM  

  • Thank you Fernando!
    Extremely valuable info here!

    Best regards!
    Ioan

    By Blogger Bordei, at 3:12 PM  

  • Hi Carlos,

    thanks for your help, all your suggestions are very useful.

    I have a problem with .net.
    I try to find an entity (like a text) in the drawing,
    and replace the text with another. But any attempt is failed. Can you help me?

    Thanks for any idea.

    Umbe

    By Anonymous Anonymous, at 1:55 PM  

  • Hello Umbe,

    Could you provide the code (or part of it) you are using for this?

    Regards.

    By Blogger Fernando Malard, at 2:07 PM  

  • Hi,

    How can I delete the XData associated with a DBObject using the managed API? I tried by setting it to nullptr (dbObj->Xdata = nullptr) but it somehow doesn't work.

    By Anonymous Anonymous, at 6:10 PM  

  • Hi,

    You need to remove XData through the setXData() method:

    "To remove an appName (and its xdata) from an object, just use a resbuf with restype == 1001, resval == and no data resbufs following it (that is, either its rbnext == NULL or the next resbuf is another 1001)"

    Remember that xData is per application so you should remove only your application data.

    Regards,

    By Blogger Fernando Malard, at 12:47 AM  

  • Thanks, Fernando!

    By Anonymous Anonymous, at 1:31 PM  

  • Hey Fernando,

    Sorry to bother you again, I'm able to insert a lot of points into a Layer '0'. Now I'd like to go thru all of those points and add text to each of those points (their 'z').
    How can I retrieve those points from Layer '0'?
    Also, how can I create a new layer and select it so that the points I add go to that layer??
    Another question, I tried to make a Dialog in MFC (customized dialog) but when I call the function in ARX, it says something like "operation not permitted" or something like that, can I make customized dialogs (classes derived from CDialog) and call them?? Or I should just call standard dialogs?

    Thank you for your time and answer..

    By Blogger Estudiante, at 7:42 PM  

  • Hello,

    I think the MFC part of your question was solved by the MFC class.

    There are several ways of retrieving the entities at some specific layers. Take a look at my selecion set class into the filter subject.

    To change the layer you need to get its ObjectId and set it to your class by using the setLayer() method.

    To create a new layer you will need to create a new AcDbLayerTableRecord inside AcDbLayer table. This process is well documented into ObjectARX SDK.

    Regards.

    By Blogger Fernando Malard, at 8:44 AM  

  • Happy new year Fernando !

    I have a question. I'm trying to implement this create line function but i get an error:

    left of '->workingDatabase' must point to class/struct/union/generic type
    'acdbHostApplicationServices': identifier not found

    i have added libs acad.lib rxapi.lib and acdb17.lib (arx 2008)

    what am i doing wrong ?

    By Anonymous Anonymous, at 10:49 AM  

  • Hello,

    You need to check both your .H (header) and .LIB (library) include paths.

    Have you tried to create a new application using ARXWizard and place your code there?

    Have you check your VS2005 directories and the ObjectARX location?

    Regards,

    By Blogger Fernando Malard, at 12:21 AM  

  • Hi Fernando:
    I can get the sphere center using the following code:
    //********************************************
    AcDb3dSolid* pSphere=NULL;
    acdbTransactionManager->getObject((AcDbObject*&)pSphere, SphereID, AcDb::kForRead);
    AcGePoint3d Center;
    double volume;
    double momInertia[3];
    double prodInertia[3];
    double prinMoments[3];
    AcGeVector3d prinAxes[3];
    double radiiGyration[3];
    AcDbExtents extents;
    pPto->getMassProp(volume,Center,momInertia,
    prodInertia,prinMoments,prinAxes,radiiGyration,extents);
    acdbTransactionManager->endTransaction();
    //********************************************
    It works perfect but this function has too many variables. Is there any way I can use the function center from AcGeSphere knowing the sphere ID??

    Racso Apres

    By Blogger Racso, at 1:24 PM  

  • Racso,

    Have you tried to use getGeomExtents(). It will return the bounding box of your solid. I'm not sure about how precise this method is but you may give a try.

    Regards.

    By Blogger Fernando Malard, at 5:28 PM  

  • Fernando:
    As allways, your help works. I used getGeomExtents() to get max and min point, then the center of the sphere is (max+min)/2
    Thanks a lot.

    Racso.

    By Blogger Racso, at 6:52 PM  

  • In your example, you have the line:

    msg.Format("\nTAG:%s - VALUE:%s",pAtt->tag(),pAtt->textString());

    According to the documentation, that is a memory leak! Both tag and textString create duplicate strings that the application is responsible for releasing.

    You should use:

    msg.Format("\nTAG:%s - VALUE:%s",pAtt->tagConst(),pAtt->textStringConst());

    instead. Note that some other functions, like: AcDbEntity::layer() also create copies of strings that need to be released, but has no const-counterpart!

    By Anonymous Anonymous, at 10:24 AM  

  • Yes, you are correct.
    Thank you.

    By Blogger Fernando Malard, at 10:48 AM  

  • Hi Fernando, I'm using VS2008 Sp1 and Autocad 2010, so I have the ObjectArx 2010 installed. I need to use the parametric surface class, in order to calculate some derivatives (parcial respect to parameter u,v and mixed), but I'm having problems declaring for example a Torus, Sphere, Cone.
    ex:
    AcGeTorus t1(major_r,
    minor_r,Pt_org,Sym_Vector);
    I have added this code to the exercise that you explained in Lab1, in the cents void. I'm receiving an error with the linker that says that I have an unresolved external symbol. How can i fix this problem??
    Thanks for your help.

    By Blogger camilo andres, at 5:22 PM  

  • Hi Camilo,

    Are you sure your project is linking with acge17.lib or acge18.lib?

    Those are supposed libraries where AcGeTorus class is defined.

    If you are explicit adding the necessary libraries to your project you will need to add it too.

    Let me know if it did work.

    Regards.

    By Blogger Fernando Malard, at 5:29 PM  

  • Hi Fernando, thanks for your fast answer, I have added the inc, inc-x64 and lib-x64 folder to their respective places in the c++ directories. Do I have to add some other parameters in the linker?
    pd: I'm able to use for example the AcGeVector3d, AcGeLine3d classes and even the AcGePlane class without getting any errors.

    By Blogger camilo andres, at 5:47 PM  

  • Camilo,

    This class is not inside the basic libraries. I have found it inside acgex18.lib module which is inside BRep library folder:

    \ObjectARX 2010\utils\brep\lib-x64

    and

    \ObjectARX 2010\utils\brep\lib-win32

    If you add this path to your project it should link ok.

    Regards.

    By Blogger Fernando Malard, at 6:35 PM  

  • Thank you so much, I just compiled without any errors.Just to set this clear so others can solve this issue too: I added the path suggested by Fernando \ObjectARX 2010\utils\brep\lib-x64 (in my case) to the VC++ directories (in the lib files)and then went to project properties>linker>Input>Additional dependencies and wrote there acgex18.lib.
    After that I was able to compile without any errors.

    Again thanks a lot Fernando!!!

    By Blogger camilo andres, at 8:32 PM  

  • Hi Fernando,
    I would like to clear Result Buffer of myApplicationName. For this I have tried with
    >acutRelRb(pRB);
    But When I closed Entity and get Result buffer Its not NULL.
    How can I delete completely and assign new resbuf??

    By Blogger Rajendra, at 11:24 PM  

  • Rajendra,

    acutRelRb() does not delete the resbuf but just release the current pointer to the data.

    To actually remove, try the following:

    // Suppose you have a pEnt pointing to your entity and it was opened for WRITE

    void CleanAppData(AcDnEntity* pEnt)
    {

    struct resbuf *pRb = pEnt->xData( "YourAppName" );

    if (pRb == NULL)
    {
    // The entity does not have my APP data
    pEnt->close();
    return;
    }

    pRb = acutBuildList( 1001, "YourAppName", RTNONE );

    pEnt->setXData(pRb);
    acutRelRb(pRb);

    pEnt->close();

    }

    Please let me know if it works.
    Regards,

    By Blogger Fernando Malard, at 8:18 AM  

  • *The correct class name is AcDbEntity

    By Blogger Fernando Malard, at 8:19 AM  

  • Hi Fernando,
    I am stuck with one problem while confirming the delete.

    For gaining the same error i do as follow:
    1. Load the arx file.
    2. Make line from Autocad function.
    3. Make result buffer and append in it.
    4. SetResultBuffer.
    5. No error in setting.
    6. When I try to access result buffer, it gives Null on same application name.

    But same process is valid if i make some entity from code and then make line from autocad. this time i can set and get the values of result buffer.

    If i make line first(from autocad) and the make entities from program and try to access result buffer. i get null value in result buffer.

    What might be the possible reason?

    By Blogger Rajendra, at 10:41 AM  

  • Rajendra,

    This does not make sense.
    The fact of creating a line prior to create your own should not affect anything related to XData.

    There is a sample called ArxDbg under "\ObjectARX 2010\samples\database\ARXDBG" which contains some XData testing functions. Try to compile this sample and load it inside AutoCAD.

    It will create a new right-click entry that you can use for several debugging purposes including XData analysis.

    Try to monitor each step of your data manipulation and make sure it is correctly structured.

    Try to comment your code and start to test it incrementally by restoring each part and testing the data portion accordingly.

    Good luck.

    By Blogger Fernando Malard, at 10:06 AM  

  • How to modify the xdata for an entity.

    By Anonymous Anonymous, at 11:20 PM  

  • Hi,

    You will need to retrieve the xData as usual, work with the resbuf.

    If you want to completely replace it just set a new resbuf pointing to the same application name.

    Take a look at the ArxDbg sample inside ObjectARX SDK. It does demonstrate how to better manipulate xData through an utility class called ArxDbgXdata.

    Regards,
    Fernando.

    By Blogger Fernando Malard, at 10:07 AM  

  • Hi Fernando!
    How to explode an non uniform scaled AcDbBlockReference? explodeToOwnerSpace requires uniform scaled blocks.

    Best regards
    badziewiak

    By Anonymous Anonymous, at 1:17 PM  

  • Hi badziewiak,

    I think you will need to use the basic explode() method which will return an AcDbVoidPtrArray of entities representing your block. You will need to walk through this array and add those entities to the BTR you want them to be inserted.

    Regards.

    By Blogger Fernando Malard, at 9:08 AM  

  • Hi Fernando,
    I can't download "Course support" and "Course and User samples". Please help me? Thanksss!

    By Anonymous Anonymous, at 10:27 AM  

  • Sorry about the inconvenience. The files were moved to Google docs:

    https://docs.google.com/leaf?id=0By7BVn8vCBxnYjZjNWJhZjYtZjE3MC00ZjdiLTlmMjMtNTVhNTNjNjE0YjUy&hl=en

    Regards.

    By Blogger Fernando Malard, at 10:20 AM  

  • Hi Fernando.

    I wonder if I can access an entity by a cordinate X, Y and get your ads_name but not to click on the segment.

    Thank you.

    By Anonymous Anonymous, at 5:45 AM  

  • Hello,

    There are some resources to select entities by a crossing/window selection or even by a Fence line.

    If you want to select specifically an entity at the XYZ coordinate you would need to select it through a tiny window/crossing around that point.

    I would need more information about what you are trying to achieve in order to give more suggestions.

    Regards,

    By Blogger Fernando Malard, at 8:01 AM  

Post a Comment

<< Home