Index

Welcome
Requirements
Class 1 - Overview
Class 2 - AutoCAD's Database
Class 3 - Application Overview
Class 3a - Minimum application
Class 3b - Minimum application using ARXWizard
Class 4 - Object Lifecycle
Class 5 - Object Management
Class 6 - Entities
Class 7 - Containers
Class 8 - Selection sets
Class 9 - Interacting with AutoCAD
Class 10 - Using MFC
Class 11 - Custom ObjectARX Class
Class 12 - Deriving from AcDbObject
Class 13 - Deriving from AcDbEntity
Class 14 - Creating a Custom Entity (step by step)
Lab 1 - Creating and Editing Entities
Lab 1 - Solved
Lab 2 - Using a MFC Dialog
Lab 2 - Solved
Lab 3 - Creating a custom object
Lab 3 - Solved
Appendix A - Debug versus Release

17 comments :

anith raj said...

Hello Malard,

I have questions (Doubts) for you.

1.
How to retrieve the Drawing Units in BricsCAD using ObjectARX.
like MM,inch etc...


2.
I have attached material to the solid body to different faces different materials,
m able to get the material id like Bricks02 as 196, Bricks05 as 205.(of integer value in ODA code).

Please let me know is there any solution to map the material id to material name.
so that i can achieve my bottle neck problem.

Here is the code.

OdBrFaceLoopTraverser faLoTrav;
OdBrFace face = FaceTr.getFace();

face.getMaterialID(nMaterialId) // Retrieve the material id (Integer)


3.
Why BREP APRI is not working in ObjectARX ?

Regards
Anithraj T
anith.raj@thedesignsense.com

Fernando Malard said...

Hello anith,

1. Probably the same way you do within AutoCAD: AcDbDatabase::lunits() and AcDbDatabase::aunits() (they correspond to the System Variables LUNITS and AUNITS respectively).

2. The ID returned by this method is an ObjectId of AcDbMaterial class. So you just need to open the object with this ID and call the method name() to retrieve its name.

3. Brep requires additional libraries and headers usually located at "C:\ObjectARX 2015\utils\brep" so they need to be added to your project to be able to compile and build your code.

Regards,

Kumari Pritam said...

Hello Malard,

I am not getting the API for the command Array3D.Is there any API for the same?
I would like to select an AcDb3dSolid and create a rectangular array of the same objects.

Regards,
Kumari Pritam

Fernando Malard said...

Hi Kumari,

There isn't any API for cloning entities.
You will need to manually calculate the transformation for each position e create clones of original entities thus transforming them from the start position to the new position relative to the row/column they would belong to.

So having your original solid, open it for read, call clone() method to get a new in-memory copy of this solid, transform it to the destination by using a translation matrix passing it into transformBy() call. After that, add this clone to ModelSpace and close it.

Regards,

Dhanraj D said...

Hello Sir,
I want to take intersection between cylinder and line, initially I was working with autocad 2014 and arx 2013 my code was working fine and then I switched to autocad 2015 and arx 2015
and then intersection API returns false. I am clueless what is wrong.
below is sample code
static void CheckIntersection()
{
//AcGeContext::gTol.setEqualPoint(1.0e-8);
//AcGeContext::gTol.setEqualVector(1.0e-6);
double m_DH = 2000.0;
AcGePoint3d org(0,0,0);
AcGeVector3d m_xAxis(1,0,0);
AcGeCylinder cylA(m_DH/2, org, m_xAxis);


AcGeLineSeg3d intLine;
AcGePoint3d pt1(0.52257073158706313,10.637171608585087,-1000.0000000000000);
AcGePoint3d pt2(0.52257073158700185,10.637171608585087,0.00000000000000000);
intLine.set(pt1, pt2);
int nrInt;
AcGePoint3d p3, p4;
//AcGeTol TOL;
//TOL.setEqualPoint(1.1);
//TOL.setEqualVector(1.1);
Adesk::Boolean stat = cylA.intersectWith(intLine, nrInt, p3, p4, AcGeContext::gTol);
if(stat == Adesk::kTrue)
{
ads_printf(L"cylA.intersectWith successfull");
}
else
{
ads_printf(L"cylA.intersectWith FAIL");
}

}

Dont know what is wrong with 2015

Fernando Malard said...

Hi,

The AcGeCylinder constructor you are using created a infinite cylinder.
Have you tried with the other constructor with the cylinder's height defined?

Further, I think intersectWith() will fail once this line is placed almost at the cylinder's cap. I know you are moving 0.52257073 towards X direction but you will need to play with the AcGeContext::gTol to see how you need to tweak it so the intersection will be found.

In Z direction you are also using 1000 as the line's length which will make its endpoint touch exactly the cylinder's side which also could be a problem in terms of tolerance.

Hope this helps.

Regards,

Prashansa Agrawal said...

Hi Malard,

I want to edit standard style of AcDbTable. Actually, I want to use standard style table only but all rows should have same height & should be Data type row only.Can you suggest me functions for the same.

Thankyou

Fernando Malard said...

Hi Prashansa,

The Table's properties are driven both by the AcDbTableStyle attached to it and also by the AcDbTable itself.
Things like Cell formatting are inherited by the style attached to it but other properties like setRowHeight() are defined directly into the inserted table (AcDbTable entity).

The data type is defined on AcDbTableStyle and at the AcDbTable level you define only if a cell is a text or a block.

I don't recommend you to use the default table style and change it. The recommended approach is to create your own application table style with a unique name thus avoiding conflicts with other styles created either by the user or by other applications running at the same time.

Take a look at those classes to better understand how to use them.

Regards,

Prashansa Agrawal said...

Hi Malard,

Thank-you for the suggestion & I will try to create my own style but I was trying to fix the row height of header and title row same as data row. I tried setRowHeight() to set same row height for all types of rows but it was not working so, I fixed the text height of all rows using setTextHeight() & after that row height of all rows are same.

Thanks & regards

Prashansa Agrawal said...

Hi Malard,

I want to know how to convert a 3Dsolid figure into component? Is there is any API to select a 3Dsolid figure & then save it as a component with its layer name?

Thanks & regards

Fernando Malard said...

Hi Prashansa,

One option is to call explode() method through the solid's pointer. This method will return a AcDbVoidPtrArray of the corresponding exploded entities. Those pointers represent "in-memory" entities so you need to either delete the pointers after doing your stuff or add them to database so they become database-resident entities.

The original solid entity will still be there and if you want to delete it call erase() method after collecting the entities from explode() call and finally close() it.

The layer can be changed through the returned entities pointers because the default is going to be layer "0" as usual.

Hope this helps.

Prashansa Agrawal said...

Hello Malard,

I want to know Is there is an API for "BMFORM" command? After selecting 3dSolid figure using AcDbEntity, how I can save the entity as a component in some particular folder with the same name as its layer name?.

Thanks & regards

Fernando Malard said...

I believe BMFORM is a BricsCAD command, not AutoCAD.
In AutoCAD you would need to first create the block with BMAKE or BLOCK command then export the block you have just created with WBLOCK command. If you don't need the block (or component) sitting into the current drawing you can directly use WBLOCK and select the entities you want to export.

This process can be achieved programmatically in AutoCAD by the overall following steps:

- Create a new AcDbBlockTableRecord and name it as you wish
- Add the desired entities to this container (can be existing entities in ModelSpace or entities you will create programmatically)
- Create a new "in-memory" AcDbDatabase and copy the block table record to it through AcDbDatabase::wblock() function
- Save this AcDbDatabase to an external file using the AcDbDatabase::saveAs() method

Hope this helps.

Prashansa Agrawal said...

Hello Malard,

I used WBLOCK command and created a block reference, But the problem is that WBLOCK Doesn’t treat the converted Block as component part of an assembly.
The individual components converted into Wblock are not part of the BOM (Bill of Materials).
I have sent you an email regarding this to your yahoo id & I have attached 2 images describing my requirements.
Please see to it & give a suggestion to automate BOM Command using objectarx API & my requirement is like second image(ComponentsUsingBmform.JPG).

Thanks & regards
Prashansa

Fernando Malard said...

Hi Prashansa,

I don't know what command BOM is nor how it works...it seems something specific from Bricscad.

Unfortunately I can't help with this specific API.

pradeep sharma said...

I fernando ,
I have a question to ask you .How to invoke the suberase function .Does it get a call when explode function is successfully run .

thanks
Pradeep Sharma

Fernando Malard said...

Hi pradeep,

In fact the explode process will eventually delete the entity. Here is what the SDK help says:

This function must not add the new entities to the database, nor should it erase the entity it is a part of. Both of these steps will be taken care of by AutoCAD (or whatever other application calls this function). This also means that if an ObjectARX application calls the explode method of an object, the calling application is responsible for the resulting entities (that is, either appending them to a database or deleting them when they are no longer needed) and for erasing the original entity (if appropriate).

That said, if your subErase() method is not being called it is probably because the exploded entity is failing to be erased OR the explode method is being called by a non-native AutoCAD process. For example, if you put a routine to manually explode the entities the very call to explode method doesn't erase the entity. As stated at the documentation text above, the caller is responsible for erasing the entity after the call to explode is made.

Double check if the explode process is indeed called by AutoCAD and also if your entity can't be exploded. For example, a AcDbLine entity cannot be exploded so subErase() won't never be called for it. If your entity doesn't support proper exploding through any particular workflow it won't be erased thus subErase() won't be called.

Hope this helps.
Regards,