Create Copy of Leader with annotation

Create Copy of Leader with annotation

vkpunique
Advocate Advocate
499 Views
4 Replies
Message 1 of 5

Create Copy of Leader with annotation

vkpunique
Advocate
Advocate

Hello ,I have some leader with mtext. Mtext contain text with reinforcement bar data something like "2-T16+2-T20+4-T25" .

From this leader i want to create 3 separate leader with each leader containining only one bar data like leader 1 with 2-T16 text, leader 2 with 2-T20 text, , leader 3 with 4-T25 text.

 

I wrote some sample code to try to clone existing leader with text annotation but it's not valid input warning

here's my sample code

[CommandMethod("CloneLeaderWithMText")]
public void CloneLeaderWithMText()
{
    Document doc = Application.DocumentManager.MdiActiveDocument;
    Database db = doc.Database;
    Editor ed = doc.Editor;

    using (Transaction tr = db.TransactionManager.StartTransaction())
    {
        // Prompt for the leader to clone
        PromptEntityOptions peo = new PromptEntityOptions("\nSelect a leader to clone: ");
        peo.SetRejectMessage("\nSelected entity is not a leader.");
        peo.AddAllowedClass(typeof(Leader), true);
        PromptEntityResult per = ed.GetEntity(peo);

        if (per.Status != PromptStatus.OK)
            return;

        Leader originalLeader = tr.GetObject(per.ObjectId, OpenMode.ForRead) as Leader;

        if (originalLeader == null)
            return;

        // Clone the leader
        Leader clonedLeader = originalLeader.Clone() as Leader;

        if (clonedLeader == null)
            return;

        // Add the cloned leader to the database
        BlockTableRecord btr = tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
        btr.AppendEntity(clonedLeader);
        tr.AddNewlyCreatedDBObject(clonedLeader, true);

        // Clone the associated MText
        MText originalMText = tr.GetObject(originalLeader.Annotation, OpenMode.ForRead) as MText;

        if (originalMText != null)
        {
            MText clonedMText = originalMText.Clone() as MText;

            if (clonedMText != null)
            {
                btr.AppendEntity(clonedMText);
                tr.AddNewlyCreatedDBObject(clonedMText, true);

                // Associate the cloned MText with the cloned leader
                clonedLeader.Annotation = clonedMText.ObjectId;

                clonedLeader.TransformBy(Matrix3d.Displacement(new Vector3d(1000, 500, 0)));
                clonedMText.TransformBy(Matrix3d.Displacement(new Vector3d(1000, 500, 0)));
            }
        }

        tr.Commit();
    }
}
0 Likes
Accepted solutions (1)
500 Views
4 Replies
Replies (4)
Message 2 of 5

_gile
Consultant
Consultant
Accepted solution

Hi,

 

What about using DeepCloneObjects instead of Clone?

[CommandMethod("CloneLeaderWithMText")]
public void CloneLeaderWithMText()
{
    var doc = Application.DocumentManager.MdiActiveDocument;
    var db = doc.Database;
    var ed = doc.Editor;

    // Prompt for the leader to clone
    var peo = new PromptEntityOptions("\nSelect a leader to clone: ");
    peo.SetRejectMessage("\nSelected entity is not a leader.");
    peo.AddAllowedClass(typeof(Leader), true);
    var per = ed.GetEntity(peo);
    if (per.Status != PromptStatus.OK)
        return;

    using (var tr = db.TransactionManager.StartTransaction())
    {
        var leader = (Leader)tr.GetObject(per.ObjectId, OpenMode.ForRead);

        // Clone the leader and its annotation (if any)
        var ids = new ObjectIdCollection { leader.ObjectId };
        if (!leader.Annotation.IsNull)
            ids.Add(leader.Annotation);
        var mapping = new IdMapping();
        db.DeepCloneObjects(ids, leader.OwnerId, mapping, false);

        // Displace the cloned entitie(s)
        var displace = Matrix3d.Displacement(new Vector3d(1000.0, 500.0, 0.0));
        foreach (IdPair pair in mapping)
        {
            if (pair.IsCloned && pair.IsPrimary)
            {
                var entity = (Entity)tr.GetObject(pair.Value, OpenMode.ForWrite);
                entity.TransformBy(displace);
            }
        }
        tr.Commit();
    }
}


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 3 of 5

ActivistInvestor
Mentor
Mentor

While @_gile offered a very good 'textbook' example of using DeepCloneObjects(), textbook examples are good for learning, but aren't always the most-efficient or easiest way to solve a problem. Like this case, in most use cases where DeepCloneObjects() is used, there needs to be post-processing of the clones. That involves starting a transaction; iterating through the IdMapping,to find each clone; and opening the clone to transform it. 

 

That typical use case is a good example of where creative use of Overrules can greatly reduce the amount of code that's needed, and also perform the operation much more efficiently.  

 

In this file, you'll find the source code needed by the example below. The example copies a selection of objects, and transforms the copies by the user-specified displacement. How it differs from the textbook example presented above, is that it completes the operation faster, without any kind of 'post-processing', and does that in one line of code.

 

/// Included below is the basic example, MyCopyCommand() 
/// method. As can be seen in the example, there's no need 
/// to start a transaction; iterate over an IdMapping; or
/// open each clone to transform it. The delegate passed to
/// the DeepCloneObjects<T>() method does all that's needed, 
/// effectively reducing the task of transforming the clones
/// to a single line of code.
///   
/// Example:
/// 
/// Basic emulation of the COPY command, sans dragging support.
/// </summary>

[CommandMethod("MYCOPY")]
public static void MyCopyCommand()
{
   var pso = new PromptSelectionOptions();
   pso.RejectObjectsFromNonCurrentSpace = true;
   pso.RejectPaperspaceViewport = true;
   Document doc = Application.DocumentManager.MdiActiveDocument;
   Editor ed = doc.Editor;
   var psr = ed.GetSelection(pso);
   if(psr.Status != PromptStatus.OK)
      return;
   var ppo = new PromptPointOptions("\nBase point: ");
   var ppr = ed.GetPoint(ppo);
   if(ppr.Status != PromptStatus.OK)
      return;
   ppo.Message = "\nDisplacment point: ";
   Point3d from = ppr.Value;
   ppo.BasePoint = from;
   ppo.UseBasePoint = true;
   ppr = ed.GetPoint(ppo);
   if(ppr.Status != PromptStatus.OK)
      return;
   Matrix3d xform = Matrix3d.Displacement(from.GetVectorTo(ppr.Value));
   var ids = new ObjectIdCollection(psr.Value.GetObjectIds());
   ids.CopyObjects<Entity>((source, clone) => clone.TransformBy(xform));
}

 

 

Message 4 of 5

vkpunique
Advocate
Advocate
db.DeepCloneObjects<Entity>(ids, (source, clone) => clone.TransformBy(xform));
deepclone method giving error
Error : CS0308 The non-generic method 'Database.DeepCloneObjects(ObjectIdCollection, ObjectId, IdMapping, bool)' cannot be used with type arguments CadApp
0 Likes
Message 5 of 5

ActivistInvestor
Mentor
Mentor

If you read my reply, you would have seen the link to a code file that's needed. 

 

0 Likes