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

JIG multiple entities

16 REPLIES 16
Reply
Message 1 of 17
ditran7577
4197 Views, 16 Replies

JIG multiple entities

Hi Pro,

 

How to Jig multiple entities such as insert a block and add a line.

 

Thanks,

16 REPLIES 16
Message 2 of 17
_gile
in reply to: ditran7577

hi,

 

You can build a class which derives from DrawJig.

 

Here's a little example to drag multiple entities. The entites passed to DragEntitiesJig instance have to be opened within a transaction.

 

    class DragEntitiesJig : DrawJig
    {
        Point3d basePoint, dragPoint;
        IEnumerable<Entity> ents;

        public DragEntitiesJig(IEnumerable<Entity> ents, Point3d basePoint)
        {
            this.basePoint = basePoint;
            this.ents = ents;
        }

        protected override bool WorldDraw(WorldDraw draw)
        {
            WorldGeometry wGeom = draw.Geometry;
            Matrix3d disp = Matrix3d.Displacement(this.basePoint.GetVectorTo(this.dragPoint));
            wGeom.PushModelTransform(disp);
            foreach (Entity ent in this.ents)
            {
                wGeom.Draw(ent);
            }
            wGeom.PopModelTransform();
            return true;
        }

        protected override SamplerStatus Sampler(JigPrompts prompts)
        {
            JigPromptPointOptions options = new JigPromptPointOptions("\nSecond point: ");
            options.BasePoint = this.basePoint;
            options.UseBasePoint = true;
            options.Cursor = CursorType.RubberBand;
            options.UserInputControls = UserInputControls.Accept3dCoordinates;
            PromptPointResult ppr = prompts.AcquirePoint(options);
            if (ppr.Value.IsEqualTo(this.dragPoint))
                return SamplerStatus.NoChange;
            this.dragPoint = ppr.Value;
            return SamplerStatus.OK;
        }
    }

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 3 of 17

If you google internet you look many samples. For example:

http://forums.autodesk.com/t5/NET/Multiple-entities-jig/td-p/2304511

http://spiderinnet1.typepad.com/blog/2012/05/autocad-net-use-drawjig-to-move-multiple-entities-as-ma...

http://through-the-interface.typepad.com/through_the_interface/2007/05/using_a_jig_fro.html

http://through-the-interface.typepad.com/through_the_interface/2009/03/jigging-an-autocad-block-with...

Відповідь корисна? Клікніть на "ВПОДОБАЙКУ" цім повідомленням! | Do you find the posts helpful? "LIKE" these posts!
Находите сообщения полезными? Поставьте "НРАВИТСЯ" этим сообщениям!
На ваше запитання відповіли? Натисніть кнопку "ПРИЙНЯТИ РІШЕННЯ" | Have your question been answered successfully? Click "ACCEPT SOLUTION" button.
На ваш вопрос успешно ответили? Нажмите кнопку "УТВЕРДИТЬ РЕШЕНИЕ"


Alexander Rivilis / Александр Ривилис / Олександр Рівіліс
Programmer & Teacher & Helper / Программист - Учитель - Помощник / Програміст - вчитель - помічник
Facebook | Twitter | LinkedIn
Expert Elite Member

Message 4 of 17
Hallex
in reply to: ditran7577

Here is code example very limited tested on A2010

see if this works,keep in mind, to change Clone method jn

DeepCloneObjects if your entities have Xdata embedded

        // based on Kean Walmsley example (jig mtext)
         [CommandMethod("dej")]
        public void MoveCopyJig()
        {
            Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
            Database db = HostApplicationServices.WorkingDatabase;
            Editor ed = doc.Editor;
            try
            {
                using (Transaction tr = doc.TransactionManager.StartTransaction())
                {
                    SelectionSet sset = ed.GetSelection().Value;
                    Point3d basept = ed.GetPoint("\nBase point: ").Value;
                    IEnumerable<Entity> objs = sset.GetObjectIds().Select(x => (Entity)tr.GetObject(x, OpenMode.ForRead)).ToArray();
                    BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
                    foreach (Entity e in objs)
                    {
                        Entity c = (Entity)e.Clone();// you may want to use DeepCloneObjects instead
                        btr.AppendEntity(c);
                        tr.AddNewlyCreatedDBObject(c, true);

                    }
                    ed.SetImpliedSelection(sset);

                    PromptSelectionResult psr = ed.SelectImplied();

                    // drag our jig

                    if (psr.Status == PromptStatus.OK)
                    {
                        // jig whole selection

                        PromptPointResult ppr =
                          ed.Drag(
                            psr.Value,
                            "\nSpecify displacement point: ",
                            delegate(Point3d pt, ref Matrix3d mat)
                            {
                                // If no change has been made, say so
                                if (basept == pt)
                                    return SamplerStatus.NoChange;
                                else
                                {
                                    // Otherwise we return the displacement
                                    // matrix for the current position
                                    mat = Matrix3d.Displacement(basept.GetVectorTo(pt)
                                      );
                                }
                                return SamplerStatus.OK;
                            }
                          );

                        // Assuming it works, transform our MText
                        // appropriately

                        if (ppr.Status == PromptStatus.OK)
                        {
                            // Get the final translation matrix

                            Matrix3d mat = Matrix3d.Displacement(basept.GetVectorTo(ppr.Value)
                              );

                            foreach (Entity en in objs)
                            {
                                en.UpgradeOpen();
                                en.TransformBy(mat);
                            }
                        }
                        // Finally we commit our transaction
                        tr.Commit();
                    }
                }
            }
            catch (System.Exception ex)
            {
                ed.WriteMessage(ex.ToString());
            }
        }

 

_____________________________________
C6309D9E0751D165D0934D0621DFF27919
Message 5 of 17
JanetDavidson
in reply to: _gile

Hello Gile,

I needed this and as usual, you solved it by simplest way.

Cheers,

 

Message 6 of 17
a.kouchakzadeh
in reply to: _gile

Giles, Hi
I was wondering how can I jig multiple block references with one base point using JIG?

I understood that in order to use your method and IEnumerable, I have to use yield return which requires object ID. but my block reference is not created yet to have an objectID.

Message 7 of 17


@a.kouchakzadeh wrote:

...I understood that in order to use your method and IEnumerable, I have to use yield return which requires object ID. but my block reference is not created yet to have an objectID.


You have to yield return not ObjectId but Entity.

Відповідь корисна? Клікніть на "ВПОДОБАЙКУ" цім повідомленням! | Do you find the posts helpful? "LIKE" these posts!
Находите сообщения полезными? Поставьте "НРАВИТСЯ" этим сообщениям!
На ваше запитання відповіли? Натисніть кнопку "ПРИЙНЯТИ РІШЕННЯ" | Have your question been answered successfully? Click "ACCEPT SOLUTION" button.
На ваш вопрос успешно ответили? Нажмите кнопку "УТВЕРДИТЬ РЕШЕНИЕ"


Alexander Rivilis / Александр Ривилис / Олександр Рівіліс
Programmer & Teacher & Helper / Программист - Учитель - Помощник / Програміст - вчитель - помічник
Facebook | Twitter | LinkedIn
Expert Elite Member

Message 8 of 17
_gile
in reply to: a.kouchakzadeh


@a.kouchakzadeh  a écrit :

I understood that in order to use your method and IEnumerable, I have to use yield return which requires object ID. but my block reference is not created yet to have an objectID.


The DragEntitiesJig constructors requires an IEnumerable<Entities> as argument, not an IEnumerable<ObjectId>.

That said, you can pass this constructor any generic collection type which implements the IEnumerable<Entity> interface such as a List<Entity> or Entity[].

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 9 of 17
a.kouchakzadeh
in reply to: _gile

thanks for the reply to both of you.
Giles, I modified your code because I didnt want the basepoint option. now I have a problem:

I cant see the block ref moving with my cursor. its only at (0,0,0).

what Im I doing wrong?

 

 

class DragEntitiesJig : DrawJig
    {
        Point3d dragPoint;
        IEnumerable<Entity> ents;

        public DragEntitiesJig(IEnumerable<Entity> ents)
        {
            
            this.ents = ents;
        }

        protected override bool WorldDraw(WorldDraw draw)
        {
            WorldGeometry wGeom = draw.Geometry;
            foreach (Entity ent in this.ents)
            {
                wGeom.Draw(ent);
            }
            wGeom.PopModelTransform();
            return true;
        }

        protected override SamplerStatus Sampler(JigPrompts prompts)
        {
            
            var options = new JigPromptPointOptions();
            options.UserInputControls = (UserInputControls.Accept3dCoordinates);
            var result = prompts.AcquirePoint(options);
            if (dragPoint.IsEqualTo(result.Value))
                return SamplerStatus.NoChange;
            else
                dragPoint = result.Value;
            return SamplerStatus.OK;

        }
        
    }

and this is my test method:

public class JigTest
    {
        [CommandMethod("test")]
        public void Test()
        {
            var doc = acap.DocumentManager.MdiActiveDocument;
            var ed = doc.Editor;
            var db = doc.Database;

            using (var tr = db.TransactionManager.StartTransaction())
            {
                var blkTable = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
                var blk1 = new ObjectId();
                var blk2 = new ObjectId();
                var curSpace = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);

                blk1 = blkTable["1"];
                blk2 = blkTable["2"];

                var blkref1 = new BlockReference(Point3d.Origin, blk1);
                var blkref2 = new BlockReference(Point3d.Origin, blk2);

                var blkList = new List<Entity>()
                {
                    blkref1, 
                    blkref2
                };

                var jig = new DragEntitiesJig(blkList);
                var jigResult = ed.Drag(jig);
                if (jigResult.Status == PromptStatus.OK)
                {
                    curSpace.AppendEntity(blkref1);
                    tr.AddNewlyCreatedDBObject(blkref1, true);
                    curSpace.AppendEntity(blkref2);
                    tr.AddNewlyCreatedDBObject(blkref2, true);
                }
                tr.Commit();
            }
        }
    }

also can you tell me how to modify the class driven from EntityJig to get multiple entities?  can I remove :base(br) in the line :

public JigBlockReference(BlockReference br)
            : base(br)
public class JigBlockReference : EntityJig
    {
        protected Point3d dragPoint;
        protected BlockReference br;

        public JigBlockReference(BlockReference br)
            : base(br)
        {
            this.br = br;
            dragPoint = br.Position;
        }

        protected override SamplerStatus Sampler(JigPrompts prompts)
        {
            var options = new JigPromptPointOptions(
                "\nSpecify destination point or rotate 90° [Left/Right]: ", "Left Right");
            options.UserInputControls = (UserInputControls.GovernedByOrthoMode);
            var result = prompts.AcquirePoint(options);
            if (dragPoint.IsEqualTo(result.Value))
                return SamplerStatus.NoChange;
            else
                dragPoint = result.Value;
            return SamplerStatus.OK;
        }

        protected override bool Update()
        {
            br.Position = dragPoint;
            return true;
        }
    }

 

Message 10 of 17
_gile
in reply to: a.kouchakzadeh


@a.kouchakzadeh  a écrit :

Giles, I modified your code because I didnt want the basepoint option. now I have a problem:

I cant see the block ref moving with my cursor. its only at (0,0,0).

what Im I doing wrong?


You need a base point to define the displacement from this base to the cursor (dragPoint), and you need to call PushModelTransform passing it this displacement to see the block moving.

 


@a.kouchakzadeh  a écrit :

also can you tell me how to modify the class driven from EntityJig to get multiple entities?  can I remove :base(br) in the line :

public JigBlockReference(BlockReference br)
            : base(br

EntityJig is to be used to jig a single entity and the derived class must pass this entity to the base class.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 11 of 17
a.kouchakzadeh
in reply to: _gile


@_gile wrote:
You need a base point to define the displacement from this base to the cursor (dragPoint), and you need to call PushModelTransform passing it this displacement to see the block moving.

 can you please give me an example how to do it?

Message 12 of 17
_gile
in reply to: a.kouchakzadeh

Here's an example inspired your upper one. The "base point" is Point3d.Origin (insertion point of newly created block references).

To make the Test command safer, it checks if the current drawing block table contains "1" and "2" block definitons, and use s using statements to ensure the disposing of newly created block references in case they're not added to the  transaction (i.e. the user cancels the jig).

 

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

            using (var tr = db.TransactionManager.StartTransaction())
            {
                var blkTable = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;

                // check if the block table has "1" and "2" blocks
                if (!(blkTable.Has("1") && blkTable.Has("2")))
                    return;

                // wrap the newly created block reference in using statements to ensure
                // they're disposed in case the user cancels the jig
                using (var blkref1 = new BlockReference(Point3d.Origin, blkTable["1"]))
                using (var blkref2 = new BlockReference(Point3d.Origin, blkTable["2"]))
                {
                    var blkList = new List<Entity>()
                    {
                        blkref1,
                        blkref2
                    };

                    var jig = new DragEntitiesFromOriginJig(blkList);
                    var jigResult = ed.Drag(jig);
                    if (jigResult.Status == PromptStatus.OK)
                    {
                        var curSpace = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
                        blkref1.TransformBy(jig.Transform);
                        curSpace.AppendEntity(blkref1);
                        tr.AddNewlyCreatedDBObject(blkref1, true);
                        blkref2.TransformBy(jig.Transform);
                        curSpace.AppendEntity(blkref2);
                        tr.AddNewlyCreatedDBObject(blkref2, true);
                    }
                }
                tr.Commit();
            }
        }

        class DragEntitiesFromOriginJig : DrawJig
        {
            Point3d dragPoint;
            IEnumerable<Entity> ents;

            public Matrix3d Transform { get; private set; }

            public DragEntitiesFromOriginJig(IEnumerable<Entity> ents)
            {
                this.ents = ents;
            }

            protected override bool WorldDraw(WorldDraw draw)
            {
                var wGeom = draw.Geometry;
                if (wGeom != null)
                {
                    // Update the Transform matrix (displacement from origin to dragPoint)
                    Transform = Matrix3d.Displacement(dragPoint.GetAsVector());
                    wGeom.PushModelTransform(Transform);
                    foreach (Entity ent in this.ents)
                    {
                        wGeom.Draw(ent);
                    }
                    wGeom.PopModelTransform();
                }
                return true;
            }

            protected override SamplerStatus Sampler(JigPrompts prompts)
            {
                var options = new JigPromptPointOptions("\nSpecify destination point: ");
                options.UserInputControls = UserInputControls.Accept3dCoordinates;
                var ppr = prompts.AcquirePoint(options);
                if (ppr.Value.IsEqualTo(dragPoint))
                    return SamplerStatus.NoChange;
                dragPoint = ppr.Value;
                return SamplerStatus.OK;
            }
        }

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 13 of 17
a.kouchakzadeh
in reply to: ditran7577

thanks Sir. 
I was wondering what happens if we do not dispose blkref? in general, when do we have to dispose some thing?

also, what does blkref1.TransformBy(jig.Transform) do?

Message 14 of 17
_gile
in reply to: a.kouchakzadeh


@a.kouchakzadeh  a écrit :

I was wondering what happens if we do not dispose blkref? in general, when do we have to dispose some thing?


If you do not dispose newly created DBObjects (or any other disposable object) the memory they occupy cannot be freed, and AutoCAD may crash at an unpredictable moment.

That said, we have to disposed any newly created or opened disposable object as soon as possible.

Regarding DBObjects, when we open them with a transaction (transaction.GetObject) or when we add newly created ones to a transaction (transaction.AddNewlyCreatedDBObject) they will be autoamically disposed with the transaction disposing.

In the upper case,  if the jig succeeds (the user specify a point) the newly created block references are added to the transaction and the disposing of the transaction sould take care of disposing them, but if the user cancels the jig, the block references won't be added to the transaction, this is why it's a recommended practice to wrap the 'new BlockReference) expression in a using statement.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 15 of 17
_gile
in reply to: a.kouchakzadeh


@a.kouchakzadeh  a écrit :

also, what does blkref1.TransformBy(jig.Transform) do?


DrawJig uses transient graphics to display the entities jigging, but the block references where insrted at Point3d.Origin, so to reflect the jigging result, we need to displace the block references using the last transformation matrix used in the DrawJig class.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 16 of 17
a.kouchakzadeh
in reply to: _gile

nicely explained sir. thank you

Message 17 of 17
kdub_nz
in reply to: _gile

@_gile,

>>> Here's an example inspired your upper one. > . .

 

very nice !

//

Everything will work just as you expect it to, unless your expectations are incorrect.

class keyThumper<T> : Lazy<T>;      another  Swamper

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

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report

”Boost