TRYING TO REPLACE DAINAMIC BLOCK IN PLACE OF OBJECTS

TRYING TO REPLACE DAINAMIC BLOCK IN PLACE OF OBJECTS

nesara_r
Participant Participant
1,202 Views
12 Replies
Message 1 of 13

TRYING TO REPLACE DAINAMIC BLOCK IN PLACE OF OBJECTS

nesara_r
Participant
Participant
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;

namespace Block_Replace
{
    public class Replace_objects
    {
        [CommandMethod("ReplaceObjects")]
        public void ReplaceObjects()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor editor = doc.Editor;
            PromptSelectionResult selectionResult = editor.GetSelection();

            if (selectionResult.Status != PromptStatus.OK)
            {
                editor.WriteMessage("No objects selected.");
                return;
            }

            SelectionSet selectionSet = selectionResult.Value;

            using (Transaction trans = db.TransactionManager.StartTransaction())
            {
                // Prompt user to select dynamic block reference
                PromptEntityOptions promptOptions = new PromptEntityOptions("\nSelect dynamic block reference: ");
                promptOptions.SetRejectMessage("Invalid selection. Please select a dynamic block reference.");
                promptOptions.AddAllowedClass(typeof(BlockReference), true);
                PromptEntityResult promptResult = editor.GetEntity(promptOptions);

                if (promptResult.Status != PromptStatus.OK)
                {
                    editor.WriteMessage("No dynamic block reference selected.");
                    return;
                }

                BlockReference dynamicBlockReference = trans.GetObject(promptResult.ObjectId, OpenMode.ForRead) as BlockReference;

                foreach (ObjectId objectId in selectionSet.GetObjectIds())
                {
                    Entity selectedEntity = trans.GetObject(objectId, OpenMode.ForRead) as Entity;

                    if (selectedEntity == null)
                        continue;

                    // Create a new block reference at the same position
                    BlockReference newBlockRef = dynamicBlockReference.Clone() as BlockReference;
                    newBlockRef.Position = selectedEntity.GeometricExtents.MinPoint;

                    // Add the new block reference to the model space
                    BlockTableRecord ms = trans.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForWrite) as BlockTableRecord;
                    ms.AppendEntity(newBlockRef);
                    trans.AddNewlyCreatedDBObject(newBlockRef, true);
                }

                trans.Commit();
            }
        }
    }
}

nesara_r_0-1706177615891.png

 

ABOVE BLOCK NEED TO BE REPLACED BY OTHER BLOCK

nesara_r_1-1706177634069.png

nesara_r_2-1706177760671.png

 

THE BLOCK GOT PASTE BUT IT IS LOOSING ITS DYNMIC  PROPERTIES I WANT TO RETAIN THOSE DAINAMIC PROPERTIES AFTER REPLACING ALSO.

 

I TRIED TO REPLACE THOSE BLOCKS BY THE ABOVE BLOCK

0 Likes
Accepted solutions (4)
1,203 Views
12 Replies
Replies (12)
Message 2 of 13

ActivistInvestor
Mentor
Mentor

You cannot use Clone() to do this. You have to use the DeepCloneObjectsl() method. Alternately, you can use the ActiveX Copy() method.

0 Likes
Message 3 of 13

norman.yuan
Mentor
Mentor
Accepted solution

It seems to me that you might not fully understand how dynamic block works, or you would not call Clone() to create a dynamic BlockReference instance, which is most likely an anonymous block. While you can use DeepCloneObjects() for your purpose, it would not help you to know how dynamic block reference is created and how the dynamic properties are set.

 

In your case, after user picks a dynamic blockreference to "copy", your code should do these:

 

1. Retrieve the dynamic blockreference's dynamic properties into collection, such as Dictionary<string, object>;

2. When looping through the selection set (in order to decide the insertion point of "copied" block reference), you create a NEW BlockReference instance of the dynamic block, then you set its dynamic properties use the retrieved property name/value pair in the Dictionary. When the dynamic properties are set, AutoCAD would automatically change the newly inserted BlockReference's block definition to an anonymous block definition, if necessary.

 

The code would look like (not tested):

 

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;

namespace Block_Replace
{
    public class Replace_objects
    {
        [CommandMethod("ReplaceObjects")]
        public void ReplaceObjects()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor editor = doc.Editor;
            PromptSelectionResult selectionResult = editor.GetSelection();

            if (selectionResult.Status != PromptStatus.OK)
            {
                editor.WriteMessage("No objects selected.");
                return;
            }

            SelectionSet selectionSet = selectionResult.Value;

            using (Transaction trans = db.TransactionManager.StartTransaction())
            {
                // Prompt user to select dynamic block reference
                PromptEntityOptions promptOptions = new PromptEntityOptions("\nSelect dynamic block reference: ");
                promptOptions.SetRejectMessage("Invalid selection. Please select a dynamic block reference.");
                promptOptions.AddAllowedClass(typeof(BlockReference), true);
                PromptEntityResult promptResult = editor.GetEntity(promptOptions);

                if (promptResult.Status != PromptStatus.OK)
                {
                    editor.WriteMessage("No dynamic block reference selected.");
                    return;
                }

                BlockReference dynamicBlockReference = trans.GetObject(promptResult.ObjectId, OpenMode.ForRead) as BlockReference;
                
                // Retrieve dynamic properties from the block reference
                Dictionary<string, object> props=GetDynamicProperties(dynamicBlockReference)
                ObjectId blockDefinitionId=dynamicBlockReference.DynamicBlockTableRecord;

                foreach (ObjectId objectId in selectionSet.GetObjectIds())
                {
                    Entity selectedEntity = trans.GetObject(objectId, OpenMode.ForRead) as Entity;

                    if (selectedEntity == null)
                        continue;

                    // Create a new block reference at the same position
                    ////BlockReference newBlockRef = dynamicBlockReference.Clone() as BlockReference;
                    ////newBlockRef.Position = selectedEntity.GeometricExtents.MinPoint;

                    // Create new dynamic block reference
                    var newBlockRef = new BlockReference(selectedEntity.GeometricExtents.MinPoint, blockDefinitionId)

                    // Add the new block reference to the model space
                    BlockTableRecord ms = trans.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForWrite) as BlockTableRecord;
                    ms.AppendEntity(newBlockRef);
                    trans.AddNewlyCreatedDBObject(newBlockRef, true);

                    // if the block definition has attributes defined,
                    // you would want to add AttributeReferences accordingly here
                    ... ...

                    // set dynamic properties of the new block reference
                    foreach (DynamicBlockReferenceProperty prop in newBlockRef.DynamicBlockReferencePropertyCollection)
                    {
                       var propName=prop.PropertyName;
                       var propValue=props[propName];
                       prop.Value = propValue;
                    }
                }

                trans.Commit();
            }
        }

        private Dictionary<string, object> GetDynamicProperties(BlockReference blkRef)
        {
            var dict= new Dictionary<string, object>();
            foreach (DynamicBlockReferenceProperty prop in blkRef.DynamicBlockReferencePropertyCollection)
            {
                dict.Add(prop.PropertyName, prop.Value);
            }
            return dict;
        }
    }
}

 

Norman Yuan

Drive CAD With Code

EESignature

Message 4 of 13

ActivistInvestor
Mentor
Mentor

.

0 Likes
Message 5 of 13

ActivistInvestor
Mentor
Mentor
Accepted solution

If you want to create copies of objects, whether they are Dynamic block references or anything else, then you use the API methods that are provided to copy them, which are the ones I mentioned previously.

 

That is what they are there for, there is no need for you to reinvent those methods.

 

If you use those APIs, then you do not have to also deal with all of the other potential issues related to copying Dynamic blocks, such as attributes; fields in attributes; and so forth.

 

See this post for an example use of  DeepCloneObjects.

 

 

Message 6 of 13

nesara_r
Participant
Participant

thankyou for advice after going through your solution i used it in my project now it is  working

0 Likes
Message 7 of 13

ActivistInvestor
Mentor
Mentor

Great. The example I pointed to was courtesy of @_gile, for the record.

0 Likes
Message 8 of 13

nesara_r
Participant
Participant

can i give select similar option to the user while selecting the objects in the same code above

0 Likes
Message 9 of 13

ActivistInvestor
Mentor
Mentor

Yes you could do that, but it involves some work, and to provide the full functionality of the SELECTSIMILAR command would be non-trivial (actually, I always felt that select similar functionality should have been better-integrated, and be available at any select objects prompt, but that's another story...).

 

You could also just instruct the user to do it in-advance by right-clicking (or using the SELECTSIMILAR command),  and then starting your command and specifying the Previous selection set in response to the Select Objects: prompt.

 

 

0 Likes
Message 10 of 13

nesara_r
Participant
Participant

i tried using select similar in first place and then run my command but when i run my command the objects selected previously is getting deselected.

0 Likes
Message 11 of 13

ActivistInvestor
Mentor
Mentor
Accepted solution

@nesara_r wrote:

i tried using select similar in first place and then run my command but when i run my command the objects selected previously is getting deselected.


 

You have to use the CommandFlags.UsePickSet flag in your CommandMethod:

 

[CommandMethod("ReplaceObjects", CommandFlags.UsePickSet)]
public void ReplaceObjects()
{
   ....
}

 

0 Likes
Message 12 of 13

nesara_r
Participant
Participant
Accepted solution
    // Get the newly created block reference
    var newBlockRefId = mapping[dynamicBlockId].Value;
    var newBlockRef = (BlockReference)trans.GetObject(newBlockRefId, OpenMode.ForWrite);

    // Set the position of the new block reference to the position of the selected entity
    newBlockRef.Position = selectedEntity.GeometricExtents.MinPoint;

 

0 Likes
Message 13 of 13

nesara_r
Participant
Participant
    // Get the newly created block reference
    var newBlockRefId = mapping[dynamicBlockId].Value;
    var newBlockRef = (BlockReference)trans.GetObject(newBlockRefId, OpenMode.ForWrite);

    // Set the position of the new block reference to the position of the selected entity
    newBlockRef.Position = selectedEntity.GeometricExtents.MinPoint;

i want to get coordinates of OBJECT I select and need to paste the new block reference there  

0 Likes