Dynamic Block not placing at user selected point but offset from selected point

kmkxperia
Advocate
Advocate

Dynamic Block not placing at user selected point but offset from selected point

kmkxperia
Advocate
Advocate

I have below code which simply uses user selected point place the Dynamic Block. Now the issue I have is when I run this code it works fine on new drawing. but when I try this on one of my clients template drawing it is always offset from user selected point. Issue is only when I try to place the block using below code, but when I place Manually it works fine. Not sure it is template issue, Dynamic Block or code. 
Also Attached the Dynamic Block dwg file that I am using

[CommandMethod("MyDynamicBlock")]
public static void PlaceDynamicBlock()
{
// Get the current document and database
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;

// Prompt the user to select a point for insertion
PromptPointOptions ppo = new PromptPointOptions("\nSpecify insertion point for the dynamic block: ");
PromptPointResult ppr = ed.GetPoint(ppo);
ed.WriteMessage("Point selected is : " + ppr.ToString());
if (ppr.Status != PromptStatus.OK)
return;

Point3d insertionPoint = ppr.Value;

// Prompt the user to select a dynamic block reference
PromptEntityResult per = ed.GetEntity("\nSelect a dynamic block reference: ");
if (per.Status != PromptStatus.OK)
return;

// Get the selected entity (dynamic block reference)
using (Transaction trans = db.TransactionManager.StartTransaction())
{
BlockReference blockRef = trans.GetObject(per.ObjectId, OpenMode.ForWrite) as BlockReference;

// Clone the dynamic block reference at the specified insertion point
BlockReference newBlockRef = blockRef.Clone() as BlockReference;
newBlockRef.Position = insertionPoint;

// Add the new block reference to the current space
BlockTableRecord currentSpace = trans.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
currentSpace.AppendEntity(newBlockRef);
trans.AddNewlyCreatedDBObject(newBlockRef, true);

// Update the attribute values of the new block reference
foreach (ObjectId attId in blockRef.AttributeCollection)
{
AttributeReference attRef = trans.GetObject(attId, OpenMode.ForRead) as AttributeReference;
AttributeReference newAttRef = attRef.Clone() as AttributeReference;

// Update the attribute reference's position based on the new block reference
Matrix3d transform = newBlockRef.BlockTransform.Inverse() * blockRef.BlockTransform;
Point3d transformedPosition = attRef.Position.TransformBy(transform);

newAttRef.Position = newBlockRef.Position + (transformedPosition - blockRef.Position);

// Add the new attribute reference to the new block reference
newBlockRef.AttributeCollection.AppendAttribute(newAttRef);
trans.AddNewlyCreatedDBObject(newAttRef, true);
}

// Commit the transaction
trans.Commit();

// Display a message to the user
ed.WriteMessage("\nDynamic block placed with attributes.");
}
}
}

0 Likes
Reply
Accepted solutions (1)
328 Views
3 Replies
Replies (3)

_gile
Mentor
Mentor
Accepted solution

Hi,

May be a User Cooordinate System issue.

Try replacing:

Point3d insertionPoint = ppr.Value;

with:

Point3d insertionPoint = ppr.Value.TransformBy(ed.CurrentUserCoordinateSystem);


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes

kmkxperia
Advocate
Advocate

Thanks This worked for me.

0 Likes

_gile
Mentor
Mentor

You should use DeepCloneObjects instead so that also the attribute references are cloned.

 

        [CommandMethod("COPYBLOCK")]
        public static void CopyBlockReference()
        {
            // Get the current document and database
            var doc = Application.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            var ed = doc.Editor;

            // Prompt the user to select a block reference
            var peo = new PromptEntityOptions("\nSelect block reference: ");
            peo.SetRejectMessage("\nSelected object is no a block reference.");
            peo.AddAllowedClass(typeof(BlockReference), true);
            var per = ed.GetEntity(peo);
            if (per.Status != PromptStatus.OK) 
                return;
            var sourceId = per.ObjectId;

            // Prompt the user to select a point for insertion
            var ppr = ed.GetPoint("\nSpecify insertion point: ");
            if (ppr.Status != PromptStatus.OK)
                return;
            var insertionPoint = ppr.Value.TransformBy(ed.CurrentUserCoordinateSystem);

            // Deep clone the selected block reference
            var ids = new ObjectIdCollection { per.ObjectId };
            var mapping = new IdMapping();
            db.DeepCloneObjects(ids, db.CurrentSpaceId, mapping, false);

            // Move the copy to the specified insertion point
            using (var tr = db.TransactionManager.StartTransaction())
            {
                var br = (BlockReference)tr.GetObject(mapping[sourceId].Value, OpenMode.ForWrite);
                br.TransformBy(Matrix3d.Displacement(br.Position.GetVectorTo(insertionPoint)));
                tr.Commit();
            }
        }

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes