Showing posts with label blocks. Show all posts
Showing posts with label blocks. Show all posts

Jigging Block Properties

A few days ago, I noticed a post on the AutoDesk Forums, asking for a way to edit a block property, immediately after inserting the block.

I bet that there is more than one way to handle this kind of action, but I’ll describe how I’d do it.

There are a few steps to do, before you can do this action.

First, to insert a Block and Jig it, you need to insert the block into the drawing. Next step is to position the block with a Jig. And then use a Jig that controls some properties of the Jig.
In my case I will use a Jig that controls the rotation of the block, and the length-property.

Note that this could be easily mimicked by just a regular rectangle, but you’ll get the point. I believe that being creative with this technique can lead to powerful, very user-friendly mechanisms.

To the code: Setting up the basics first, as these will happen exactly as in my last post, I will not include these in the code samples. Complete files of the code can be found on Google Code. Just go to the tab ‘Source’, click on ‘Browse’, expand the trunk and choose ‘BlockPropertyDrag’.

The first thing we need to do, is to set everything up. So basically, insert a block.

   1: Database db = doc.Database;
   2: BlockTable blockTable = t.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
   3:  
   4: // first, create the block reference in memory
   5: ObjectId blockDefinitionId = blockTable["dummy"];
   6: BlockReference blockReference = new BlockReference(
   7:     new Point3d(0, 0, 0), blockDefinitionId);
   8:  
   9: // first append the block
  10: BlockTableRecord modelSpace = t.GetObject(
  11:     blockTable[BlockTableRecord.ModelSpace], OpenMode.ForWrite, false) as BlockTableRecord;
  12:  
  13: modelSpace.AppendEntity(blockReference);
  14:  
  15: t.AddNewlyCreatedDBObject(blockReference, true);


Then we will first call the ‘place-the-block-into-position’-Jig:



   1: // allow user to move the block around with the InsertBlockJig
   2: InsertBlockJig insertBlockJig = new InsertBlockJig(blockReference);
   3:  
   4: if (ed.Drag(insertBlockJig).Status != PromptStatus.OK)
   5:     return;

And then we call the property-drag Jig:



   1: // do the property drag jig on the block
   2: BlockPropertyDragJig dragJig = new BlockPropertyDragJig(blockReference);
   3:  
   4: if (ed.Drag(dragJig).Status != PromptStatus.OK)
   5:     return;
   6:  
   7: t.Commit();

So far for the command. Of course, the real action is in the jigs. I’ll only show the Update() methods, the rest of the code is very default, and again, can be found on Google Code.


I did add 2 readonly properties to the Jigs: CurrentPosition and JiggedBlockReference. These properties basically just cast the protected Entity to BlockReference and return its position.


Our InsertBlockJig Update() method is very simple, we simply add the resulting Vector the the Block’s Position.



   1: protected override bool Update()
   2: {
   3:     JiggedBlockReference.Position = JiggedBlockReference.Position.Add(currentVector);
   4:     return true;
   5: }

That’s it for positioning. The currentVector variable is a global variable, set in the Sampler() Method. It just holds the Vector from the current Block’s Position and the registered mouse position in Sampler(). This is also how I did it in my last post on post on jigging multiple entities.


Now, for the BlockPropertyDragJig, where we will be updating the block properties, we need to fill in the Update() as follows:



   1: protected override bool Update()
   2: {
   3:  
   4:     // only 2d
   5:     Point2d oldPosition = new Point2d(CurrentPosition.X, CurrentPosition.Y);
   6:     Point2d newPosition = new Point2d(lastMousePosition.X, lastMousePosition.Y);
   7:  
   8:     JiggedBlockReference.Rotation = oldPosition.GetVectorTo(newPosition).Angle - Math.PI/2;
   9:  
  10:     // loop properties to find the ones we need
  11:     foreach (DynamicBlockReferenceProperty prop in JiggedBlockReference.DynamicBlockReferencePropertyCollection)
  12:     {
  13:         if (prop.PropertyName.ToUpper() == "LENGTH")
  14:         {
  15:             prop.Value = oldPosition.GetDistanceTo(newPosition);
  16:         }
  17:     }
  18:         
  19:     return true;
  20: }


Basically, we’re calculating 2 things here: the distance and the angle from the mouse position to the Block’s position (which is his Insertion Point).


The angle is controlling the rotation of the Block. The distance is controlling the Length property.


So that’s all there is to it. Full code on Google Code.


One more thing, I personally find working with Blocks in the AutoCad API very inefficient and cumbersome. I can only suggest that you create a Wrapper for your Blocks, and service classes that provide all the needed functionality for you. If you’ll decide to create all your Block-Handling code on-the-fly, you’ll most likely have a very error-prone process and lots of duplicate code.

Posted by Bert Vanpeteghem 4 reacties

Editing block properties performance issue

When working with dynamic blocks, I can imagine that the functionality most used are
- Block Properties
- Block Attributes
- Maybe some Extension Dictionary editing.

At least, that is what we worked with most in our last project. It was pretty much based on positioning and editing Dynamic Blocks.
At the time, we had noticed some performance issues when we were inserting or editing a lot of blocks. This actually became annoying when we were doing operations that changed 40 or more blocks.

At first, we thought that the problem was in our calculation and processing. We had a pretty intense Processing engine for the blocks and our reaction was that we were processing things too much.

When we started investigating what caused the performance lag, we actually found that our processing was quite fast, but that the problem was editing a lot of Blocks. So, the problem was not our code; the timely operation was, waiting for AutoCAD operations to complete.

So we isolated the functionality of accessing and editing blocks to see what exactly went wrong.

We tried:
- using less transactions (all can be done in one single transaction), no luck.
- rewriting our code, so there would be less loops, no luck.

As we investigated a little further, with timers on each operation we did, we finally found out that it were actually the block properties that were the slowness factor...

The results were quite remarkable, as a reference:

Inserting 100 blocks with 4 attributes and 4 properties takes us: 1000ms, so 1 second.

In this second we have:

Code overhead: 62ms
Inserting block: 32ms
Set attributes: 47ms
Set properties: 859ms

This means that setting the properties takes more than 85% of complete operation time.

Now, you can say that, since this all still happens in one second, that there isn't a big performance issue. However, our blocks easily had 8-10 properties. So spending 85% of your time in updating properties is in fact a lot.

Next time, we'll look in how to get around this issue.

Posted by Bert Vanpeteghem 3 reacties