Jigs to place drawing autogenerated drawings

vkpunique
Advocate
Advocate

Jigs to place drawing autogenerated drawings

vkpunique
Advocate
Advocate

So i am building autocad addin to generate drawing using user inputs. Currently user is selecting base point to generate drawing on that location.  this can lead to overlapping with existing drawing if drawing is large.

 

I am wondering if we have any generalize jig which allow me to place generated drawing with visualization, i am thinking about similar jigs like move. using this user will be able to adjust drawing position without overlapping with existing drawings

 

0 Likes
Reply
Accepted solutions (1)
270 Views
5 Replies
Replies (5)

_gile
Mentor
Mentor

Hi,

 

To jig multiple entities, you have to use a class derived from DrawJig.

Here's a little example with two usable classes, one to move a set of entities, the other one to rotate a set entities.

public abstract class EntitiesJig : DrawJig
{
    protected IEnumerable<Entity> entities;
    protected Point3d basePoint;

    public abstract Matrix3d Transform { get; }

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

    protected override bool WorldDraw(WorldDraw draw)
    {
        WorldGeometry geometry = draw.Geometry;
        if (geometry != null)
        {
            geometry.PushModelTransform(Transform);
            foreach (Entity ent in entities)
            {
                geometry.Draw(ent);
            }
            geometry.PopModelTransform();
        }
        return true;
    }
}

public class MoveJig : EntitiesJig
{
    readonly bool rubberBand;
    string message;

    public Point3d Point { get; private set; }

    public override Matrix3d Transform =>
        Matrix3d.Displacement(basePoint.GetVectorTo(Point));

    public MoveJig(IEnumerable<Entity> entities, Point3d basePoint, string message, bool rubberBand = false)
        : base(entities, basePoint)
    {
        this.message = message;
        this.rubberBand = rubberBand;
    }

    protected override SamplerStatus Sampler(JigPrompts prompts)
    {
        var options = new JigPromptPointOptions(message)
        {
            BasePoint = basePoint,
            UseBasePoint = true
        };
        if (rubberBand)
            options.Cursor = CursorType.RubberBand;
        options.UserInputControls =
            UserInputControls.Accept3dCoordinates;
        PromptPointResult result = prompts.AcquirePoint(options);
        if (result.Value.IsEqualTo(Point))
            return SamplerStatus.NoChange;
        Point = result.Value;
        return SamplerStatus.OK;
    }
}

public class RotateJig : EntitiesJig
{
    Vector3d axis;
    string message;

    public double Angle { get; private set; }

    public override Matrix3d Transform =>
        Matrix3d.Rotation(Angle, axis, basePoint);

    public RotateJig(IEnumerable<Entity> entities, Point3d basePoint, Vector3d axis, string message)
        : base(entities, basePoint)
    {
        this.axis = axis;
        this.message = message;
    }

    protected override SamplerStatus Sampler(JigPrompts prompts)
    {
        var options = new JigPromptAngleOptions(message)
        {
            BasePoint = basePoint,
            UseBasePoint = true,
            Cursor = CursorType.RubberBand,
            DefaultValue = 0.0,
            UserInputControls =
            UserInputControls.NullResponseAccepted |
            UserInputControls.Accept3dCoordinates |
            UserInputControls.GovernedByUCSDetect
        };
        PromptDoubleResult result = prompts.AcquireAngle(options);
        if (result.Value == Angle)
            return SamplerStatus.NoChange;
        Angle = result.Value;
        return SamplerStatus.OK;
    }
}

 

An example using these classes to move and rotate a selection set.

[CommandMethod("MRS")]
public static void MoveRotateSelection()
{
    var doc = Application.DocumentManager.MdiActiveDocument;
    var db = doc.Database;
    var ed = doc.Editor;
    var selection = ed.GetSelection();
    if (selection.Status != PromptStatus.OK) return;
    var ppr = ed.GetPoint("\nBase point: ");
    if (ppr.Status != PromptStatus.OK) return;
    var ucs = ed.CurrentUserCoordinateSystem;
    using (var tr = db.TransactionManager.StartTransaction())
    {
        var entities = selection.Value
            .GetObjectIds()
            .Select(id => (Entity)tr.GetObject(id, OpenMode.ForWrite))
            .ToList();
        var moveJig = new MoveJig(entities, ppr.Value.TransformBy(ucs), "\nDestination point: ", true);
        if (ed.Drag(moveJig).Status == PromptStatus.OK)
        {
            entities.ForEach(e => e.TransformBy(moveJig.Transform));
            var rotateJig = new RotateJig(entities, moveJig.Point, ucs.CoordinateSystem3d.Zaxis, "\nRotation: ");
            if (ed.Drag(rotateJig).Status == PromptStatus.OK)
            {
                entities.ForEach(e => e.TransformBy(rotateJig.Transform));
                tr.Commit();
            }
        }
    }
}


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes

vkpunique
Advocate
Advocate
what if drawing that i want to jig is not drawn yet. Means user will trigger my custom command enter dimension via editor , program will generate all entity using fix 0,0 base point, and all of entity will by passed to move jig.

can i do this in single transaction or i have to do multiple transactions
0 Likes

_gile
Mentor
Mentor
Accepted solution

@vkpunique  a écrit :
what if drawing that i want to jig is not drawn yet. Means user will trigger my custom command enter dimension via editor , program will generate all entity using fix 0,0 base point, and all of entity will by passed to move jig.

can i do this in single transaction or i have to do multiple transactions

Here's an example adding newly created entities to the current space before dragging them with a jig.

 

[CommandMethod("TEST1")]
public static void Test1()
{
    var doc = Application.DocumentManager.MdiActiveDocument;
    var db = doc.Database;
    var ed = doc.Editor;
    var ucs = ed.CurrentUserCoordinateSystem;

    // Create some entities
    var entities = new List<Entity>();
    var circle = new Circle(Point3d.Origin, Vector3d.ZAxis, 10.0);
    entities.Add(circle);
    var line = new Line(new Point3d(-10.0, -10.0, 0.0), new Point3d(10.0, 10.0, 0.0));
    entities.Add(line);
    line = new Line(new Point3d(-10.0, 10.0, 0.0), new Point3d(10.0, -10.0, 0.0));
    entities.Add(line);

    using (var tr = db.TransactionManager.StartTransaction())
    {
        // Add the entities to the current space
            var curSpace = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
        foreach (var entity in entities)
        {
            entity.TransformBy(ucs);
            curSpace.AppendEntity(entity);
            tr.AddNewlyCreatedDBObject(entity, true);
        }

        // Drag the entities using a MoveJig instance
        var jig = new MoveJig(entities, ucs.CoordinateSystem3d.Origin, "\nSpecify insertion point: ");
        var result = ed.Drag(jig);

        // Transform the entities if PromptResult.Status is OK
        if (result.Status == PromptStatus.OK)
        {
            entities.ForEach(e => e.TransformBy(jig.Transform));
        }
        // erase them otherwise
        else
        {
            entities.ForEach(e => e.Erase());
        }
        tr.Commit();
    }
}

 

 

Another example which only add the newly created entities if the Jig PromptResult.Status is OK

 

[CommandMethod("TEST2")]
public static void Test2()
{
    var doc = Application.DocumentManager.MdiActiveDocument;
    var db = doc.Database;
    var ed = doc.Editor;
    var ucs = ed.CurrentUserCoordinateSystem;

    // Create some entities and add them to a List
    var entities = new List<Entity>();
    var circle = new Circle(Point3d.Origin, Vector3d.ZAxis, 10.0);
    entities.Add(circle);
    var line = new Line(new Point3d(-10.0, -10.0, 0.0), new Point3d(10.0, 10.0, 0.0));
    entities.Add(line);
    line = new Line(new Point3d(-10.0, 10.0, 0.0), new Point3d(10.0, -10.0, 0.0));
    entities.Add(line);
    entities.ForEach(e => e.TransformBy(ucs));

    // Drag the entities using a MoveJig instance
    var jig = new MoveJig(entities, ucs.CoordinateSystem3d.Origin, "\nSpecify insertion point: ");
    var result = ed.Drag(jig);
    // Add the entities to the current space if PromptResult.Status is OK
    if (result.Status == PromptStatus.OK)
    {
        using (var tr = db.TransactionManager.StartTransaction())
        {
            var curSpace = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
            foreach (var entity in entities)
            {
                curSpace.AppendEntity(entity);
                tr.AddNewlyCreatedDBObject(entity, true);
                entity.TransformBy(jig.Transform);
            }
            tr.Commit();
        }
    }
    // dispose them otherwise
    else
    {
        entities.ForEach(e => e.Dispose());
    }
}

 

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes

vkpunique
Advocate
Advocate

Thank you @_gile  it's working perfectly, i was stuck on this problem since past few months. 

One last question what's DisposableList Class, i've never used it before and it's not availble in .net framework. In second command i've replaced DisposableList with regular List and e.Dispose() with e.Erase()

0 Likes

_gile
Mentor
Mentor

@vkpunique  a écrit :

One last question what's DisposableList Class, i've never used it before and it's not availble in .net framework. In second command i've replaced DisposableList with regular List and e.Dispose() with e.Erase()


This is a mistake: the code above uses a List<Entity> and calls the Dispose method on all entities if the PromptResult is not OK (the code above is corrected).


The DisposableList<T> class (CF below) does the same thing implicitly.

 

[CommandMethod("TEST2")]
public static void Test2()
{
    var doc = Application.DocumentManager.MdiActiveDocument;
    var db = doc.Database;
    var ed = doc.Editor;
    var ucs = ed.CurrentUserCoordinateSystem;

    // Create some entities and add them to a List
    using (var entities = new DisposableList<Entity>())
    {
        var circle = new Circle(Point3d.Origin, Vector3d.ZAxis, 10.0);
        entities.Add(circle);
        var line = new Line(new Point3d(-10.0, -10.0, 0.0), new Point3d(10.0, 10.0, 0.0));
        entities.Add(line);
        line = new Line(new Point3d(-10.0, 10.0, 0.0), new Point3d(10.0, -10.0, 0.0));
        entities.Add(line);
        entities.ForEach(e => e.TransformBy(ucs));

        // Drag the entities using a MoveJig instance
        var jig = new MoveJig(entities, ucs.CoordinateSystem3d.Origin, "\nSpecify insertion point: ");
        var result = ed.Drag(jig);
        // Add the entities to the current space if PromptResult.Status is OK
        if (result.Status == PromptStatus.OK)
        {
            using (var tr = db.TransactionManager.StartTransaction())
            {
                var curSpace = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
                foreach (var entity in entities)
                {
                    curSpace.AppendEntity(entity);
                    tr.AddNewlyCreatedDBObject(entity, true);
                    entity.TransformBy(jig.Transform);
                }
                tr.Commit();
            }
        }
    }
}

class DisposableList<T> : List<T>, IDisposable where T : IDisposable
{
    public void Dispose()
    {
        var list = this.ToList();
        Clear();
        foreach (T item in list)
        {
            item.Dispose();
        }
    }
}

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes