ObjectARX
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

AcDbEvalGraph, AcDbEvalExpr related question

17 REPLIES 17
SOLVED
Reply
Message 1 of 18
renencon
1001 Views, 17 Replies

AcDbEvalGraph, AcDbEvalExpr related question

Hello,

 

Is it possible to add a custom entity already resident in the drawing as a node in a AcDbEvalGraph using AcDbEvalExpr directly or do I need to use reference ids instead?

 

Thanks

Anastassios

17 REPLIES 17
Message 2 of 18
Balaji_Ram
in reply to: renencon

A node class is derived from AcDbEvalExpr and the implementation of its Evaluate method is based on what you are trying to do with the custom entity. So, since it is your class which is acting as a node, I think both the ways are possible, but I havent tried adding the entity directly as a node.

 

If the custom entity is already database resident, you will need its ObjectId to access and perform the evaluation and storing its ObjectId is the straight-forward approach.

 

Storing the custom entity pointer in a AcDbEvalExpr is troublesome and in this case you will need to ensure that you can access the custom entity inside the Evaluate method.

 

If you can provide more details on what kind of evaluation you are trying to perform using the graph and some details about the custom entity, then it might help in providing a more specific answer.



Balaji
Developer Technical Services
Autodesk Developer Network

Message 3 of 18
renencon
in reply to: Balaji_Ram

Hello Balaji,

 

Here is what I am trying to accomplish and the approach that I am currently implementing.

I have created two custom entities that are drawing special graphics in the drawing. They are working OK at the moment.

 

I have created links between them using AcDbObjectIdArrays because they are interrelated and data on one affect the behavior of the other on the drawing.

 

I wanted to write an algorithm to search the data and collect for example a group of my custom entities drawn on the drawing according to specified criteria that the user will enter. Like the shortest route problem for example.

 

I came across Evaluation Graphs in ObjectArx and currently I am investigating how to replace the links that I already store in my custom entities using AcDbObjectIdArrays with a Graph instead.

 

I believe that will be more efficient. Is that correct?

 

The approach I am using at the moment is that I created a custom AcDbEvalGraph and stored it in a custom dictionary container as an individual named entry not as extension dictionary. I also create two different types of custom AcDbEvalConnectable nodes, the first one is interrelated to the first custom entity and the other to the other one.

 

I store on the Node the objectId of the Graphic entity and on the graphic entity the objectId of the node that way when the user erases an entity from the drawing, the graph, I noticed, can be updated whenever the objectId's stored on the nodes become invalid so the graph can remove those nodes.

 

Now, I came that far. I am having real trouble figuring out how the mechanism of AcDbEvalConnectable works, and more specifically how do you add keys on them. I cannot find any guidance anywhere can you advice?

 

Thank you very much for your advice,

regards

Anastassios

 

 

 

 

 

Message 4 of 18
renencon
in reply to: Balaji_Ram

Hello again, Do I need to override every AcDbEvalConnectable method to implement keys that will be stored on custom arrays within the object as well as the connection AcDbEvalNodeIds of the nodes that this node is connected to. Is this the right approach? Thanks again. Anastassios
Message 5 of 18
renencon
in reply to: renencon

The concept of graphs is relatively new to me. After further reading I have decided to use AcDbObjectIdGraph instead. Create new nodes corresponding to each custom entity that I have and create the links between the entities within the graph which I will store in the same container as before within a custom AcDbObject so I will have the capability to save and restore with dwg before any custom entities that are contained within are saved or restored.

 

Now, do I recreate the graph nodes and links (now edges of the graph) within dwgin of my existing custom entities in thus replacing the arrays that I already use to store those links with edges within the graph, Is that correct?

 

Anastassios 

 

Message 6 of 18
Balaji_Ram
in reply to: renencon

Hi Anastassios,

 

Sorry for the delay in replying to you.

 

I donot think that the AcDbObjectIdGraph can be persisted while the drawing is saved and so you will need to reconstruct the graph everytime. Using an AcDbEvalGraph should serve your purpose or instead of the graph, you may consider using the persistent reactors.

 

If entity1 is being associated with entity2, you will first create a custom object that holds the ObjectId of the entity2. The custom object will be stored in the Named Object Dictionary and its ObjectId will be set as the persistent reactor to entity1. This way, an entity may be associated with more than one entity and they get saved along with the drawing.

 

I have attached a sample project demonstrating this. To try it :

- Appload the arx

- Run the "Test1" command which creates a few circles and lines

- Run the "Test2" command and select the first entity and then the second entity to associate.

- You can repeat "Test2" to associate other entities to the first entity.

- If the color of the first entity is modified, then the persistent reactor will change the color of all the associated entities.

 

If you have any specific issue with the use of AcDbEvalGraph or with the use of persistent reactors, please do let me know.

 



Balaji
Developer Technical Services
Autodesk Developer Network

Message 7 of 18
renencon
in reply to: Balaji_Ram

Hi Balaji,
 
You have opened a new door with persistent reactors which I haven't considered before.

The way I build object links at the moment is as follows.
For simplification assume that myLine entity is derived from AcDbLine.
MyLine has a member variable mLinks(AcDbObjectIdArray).

When I create a sequence of MyLine entities I do the following

  1. get startPoint
  2. get endPoint.
  3. create fromMyLine(startPoint, endPoint)
  4. get fromMyLineObjectId
  5. start a while loop
  6. startPoint = endPoint
  7. get endPoint
  8. create toMyLine(startPoint, endPoint)
  9. get toMyLineObjectId
  10. append fromMyLine->mLinks(toMyLineObjectId)
  11. append toMyLine->mLinks(fromMyLineObjectId)
  12. fromMyLine = toMyLine
  13. fromMyLineObjectId = toMyLineObjectId
  14. continue the while until invalid endPoint

at the end of the above sequence every one of MyLine's has its mLink variable with one or two objectId's

 

Now, I updated the above sequence and used ssget "x" to find at every point that the user inputs whether there are any existing MyLine's with startPoint or endPoint equal to the given one. If found I also update the mLinks of every found or newly created entity.

 

At the end everyone of MyLine entities knows the other MyLine entities that it is linked with, by holding one or more objectIs's within the mLink variable.

 

Now, you are suggesting to replace the above with persistent reactors.

 

First question, I will create a new MyLineLinks custom object with mLinks member variable and add it as a persistent reactor to MyLine entity.

Can I store this object within the extension dictionary of MyLine entity?

 

That way I do not populate ASDK_DICT with MyLineLinks objects of erased entities. Is that correct?

 

Second question, I found, I think, I haven't fully implemented it yet, a way using AcDbSpatialIndex that I could use, so that when the user starts a grip edit operation on either the startPoint or endPoint of MyLine entity that entity will be able to find other MyLine entities at the end of the grip edit operation and update the mLinks member variables of all involved MyLine entities. Is this OK or there is another better way of doing this. What are AcEdInputContextReactor AcEdSSGetFilter classes used for? How can I initiate these reactors?

 

Third question, will a persisted reactor's modified function be called whenever I open MyLine, update one of its member variable's and close it? or does it need user intervention, or I simply call the modified function? can that be propagated to every linked object by updating some member variable on each visited one?

 

Thanks again, I hope the above is clearly presented.

Anastassios.

Message 8 of 18
Balaji_Ram
in reply to: renencon

Hi Anastassios,

 

I hope this answers your queries :

 

Q) Can I store this object within the extension dictionary of MyLine entity? That way I do not populate ASDK_DICT with MyLineLinks objects of erased entities. Is that correct?

 

Yes, The “addPersistentReactor” method only requires an ObjectId and it does not matter the custom object is stored in NOD or the entity extension dictionary.

 

Q) Second question, I found, I think, I haven't fully implemented it yet, a way using AcDbSpatialIndex that I could use, so that when the user starts a grip edit operation on either the startPoint or endPoint of MyLine entity that entity will be able to find other MyLine entities at the end of the grip edit operation and update the mLinks member variables of all involved MyLine entities. Is this OK or there is another better way of doing this. What are AcEdInputContextReactor AcEdSSGetFilter classes used for? How can I initiate these reactors?

 

If entity-1 has multiple persistent reactors set, simply changing the property (say its color) of entity-1 will intitiate the reactors.

 

Q)Third question, will a persisted reactor's modified function be called whenever I open MyLine, update one of its member variable's and close it? or does it need user intervention, or I simply call the modified function? can that be propagated to every linked object by updating some member variable on each visited one?

 

It does not need an user intervention. For example, if entity-1 has a persistent reactor that modifies entity-2 and Entity-2 has a persistent reactor that modifies entity-3 :

A property change in entity-1 will initiate the whole chain of persistent reactors and all the three entities will get modified.



Balaji
Developer Technical Services
Autodesk Developer Network

Message 9 of 18
renencon
in reply to: Balaji_Ram

Hi Balaji

 

Great support, you have clarified all my queries and now I have a better understanding of how this mechanism works.

This has saved me a lot of trial and error.

I will go ahead and implement it now.

 

Thanks again

Regards

Anastassios

 

 

Message 10 of 18
renencon
in reply to: renencon

Hi Balaji

 

I have on more question.

 

Is it necessary to update a spatial index everytime, prior to spatial intex iteration or this is done automatically by AutoCAD at the regen level and everytime entities are added to the drawing.

 

Thanks again

Regards

Anastassios

Message 11 of 18
renencon
in reply to: renencon

Hello Balaji,

 

One more thing

 

As a general rule you never modify a notifier from within one of its reactor functions.

 

That is why you store the _associatedId within the persistent reactor object.

 

Which means I need to move the association links from my custom objects to their appropriate prersistent reactor objects which in turn will be stored within the extension dictionary of my custom objects(the notifiers). That way I will be able to update their values (linked objects) form within the reactor modified function.

 

Is that correct?

 

Thanks again

Anastassios.

 

Message 12 of 18
Balaji_Ram
in reply to: renencon

Hi Anastassios,

 

Sorry for the delay. I was out-of-office for a few days.

 

Regarding your query related to spatial index :

 

I dont see the need to use spatial index with persistent reactors. A change in the object property will automatically ensure that the associated persistent reactors gets a call.

 

Regarding your other query on using a reactor function to modify a notifier :

 

You are right, in general reactor callbacks should not be used to modify the database entities, but I havent come across any issues while using persistent reactor callbacks. Please let me know if you have any specific issue while using it.

 



Balaji
Developer Technical Services
Autodesk Developer Network

Message 13 of 18
renencon
in reply to: Balaji_Ram

Hello Balaji,

 

I wanted to use spatial index so that I will find quickly from the database the objects that are on the same point after a grip edit operation within the GripOpStatFunc when the GripStatus is kGripEnd and then I could update the links between the involved entities. However, I abandoned that approach and I try now again to use setInputPointFunc, but came across the same problem.

When I hover over other entities, pickedEntities parameter will indicate to me whether the type of entity that I am looking for is under the cursor. Then I want to display custom graphics next to the cursor (like Civil3d's Pipe Network, when you grip edit a pipe and you move it over another pipe or structure from the same network then a special glyph is drawn to indicate that the network connections will be updated. This is the process that I would like to mimic).

 

Now, the question is how do I draw the special graphics from within GripInputPointPtr function. When you use the equivalent AcEdInputPointMonitor::monitorInputPoint  you get a AcGiViewportDraw* drawContext parameter which could be used to draw the special glyph but with GripInputPointPtr function you only get 

viewContext const AcGiViewport& and viewportID const AcDbObjectId& parameters how these could be used to draw custom glyph graphics while I am dragging the grip?

 

Maybe, I am wrong with this approach and need to use something else as well.

 

Thanks again

Regards

Anastassios

 

 

Message 14 of 18
renencon
in reply to: renencon

Hello Balaji

 

As far as the GripInputPointPtr question is concerned in my previous post I think I got it I started using setDrawAtDragImageGripPoint to true and modified the worlddraw method for the grip. So I hope I will get the result that I am looking for.

 

Is there another approach.

What about my comments on spatial index and picked entities on my previous post.

 

Thanks again

Regards

Anastassios

Message 15 of 18
renencon
in reply to: renencon

One more thing is there a way to get the environment grip colors that are set at the AutoCAD options dialog from within a grip's worlddraw function.

 

Thanks again

Anastassios

 

Message 16 of 18
renencon
in reply to: renencon

More specifically if you do not use subEntityTraits().setColor then graphics are drawn with grip colors except GRIPCONTOUR so when you draw a filled square grip then the outline of the square is drawn in the default GRIPCOLOR not GRIPCONTOUR color as in standard AutoCAD grips.

 

Thanks,

Anastassios

Message 17 of 18
Balaji_Ram
in reply to: renencon

Hi Anastassios,

 

I was busy with other activities.

 

If you can create different posts, each one with a specific question, I am sure you will get answers more quickly.

Because this post is marked as answered, experts in this discussion group may not look into your latest query.

 

It will also help me understand your question better and also help others who will be searching for related info in this forum.

 

 

 

 

 



Balaji
Developer Technical Services
Autodesk Developer Network

Message 18 of 18
renencon
in reply to: Balaji_Ram

Fair enough, I do apologise, I will repost the queries under a different topic. Thanks Anastassios

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report

”Boost