jigging a block reference and a dimension object simultaneously

jigging a block reference and a dimension object simultaneously

a.kouchakzadeh
Advocate Advocate
803 Views
8 Replies
Message 1 of 9

jigging a block reference and a dimension object simultaneously

a.kouchakzadeh
Advocate
Advocate

Hello every one & @_gile 

I was wondering is it possible to jig a block reference along with a dimension object, by passing a point which is fixed and indicates one side of its position and the other side of the dimension changing along with the cursor?

and how can I limit the multiple objects jig to one axis. would this minimize the amount of calculation to maintain a smoother drag? 

 

NSV-removebg-preview.png

and if I need to change the color of the dimension object dynamically according to its number, what should I do?

should it be done in the jig class? or the test method?

0 Likes
Accepted solutions (1)
804 Views
8 Replies
Replies (8)
Message 2 of 9

a.kouchakzadeh
Advocate
Advocate

Mr. @norman.yuan Can you explain to us in your code provided on your blog, what is "this" in var res = _ed.drag(this) from your move method?

 

 

 

0 Likes
Message 4 of 9

a.kouchakzadeh
Advocate
Advocate

so by using "this", in that line, you are dragging which object? the selected one or the dimension you created?

 

0 Likes
Message 5 of 9

norman.yuan
Mentor
Mentor

Using "this" has nothing to do with what the Jig class does. It is the Editor.Drag() method requires Jig object as argument. If Editor.Drag() is called INSIDE the Jig class, as my example does, then you pass the Jig class itself to the Drag() method, hence the use of "this".

 

Norman Yuan

Drive CAD With Code

EESignature

0 Likes
Message 6 of 9

_gile
Consultant
Consultant
Accepted solution

Hi,

What you're asking for is far less than trivial.

EntityJig an only apply to a single entity and with DrawJig, we can use a transformation matrix to drag the block reference but not with the dimension. Perhaps it's possible to dynamicly draw a 'custom dimension' but this is all but simple.

I purpose you a workaround using a class derived from EntityJig using a 'dynamic dimension'.

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

            using (var tr = db.TransactionManager.StartTransaction())
            {
                var blockTable = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
                if (!blockTable.Has(blockName))
                    return;

                var pointResult = ed.GetPoint("\nFixed point: ");
                if (pointResult.Status != PromptStatus.OK)
                    return;
                var fixedPoint = pointResult.Value;

                var kwOptions = new PromptKeywordOptions("\nSpecify the rotation [0/90/180/270]: ", "0 90 180 270");
                var kwResult = ed.GetKeywords(kwOptions);
                if (kwResult.Status != PromptStatus.OK)
                    return;
                double rotation = double.Parse(kwResult.StringResult) * Math.PI / 180.0;

                using (var br = new BlockReference(fixedPoint, blockTable[blockName]))
                {
                    br.Rotation = rotation;
                    var dynmode = acap.GetSystemVariable("dynmode");
                    acap.SetSystemVariable("dynmode", 2);
                    try
                    {
                        var jig = new BlockDimJig(br);
                        var result = ed.Drag(jig);
                        if (result.Status == PromptStatus.OK)
                        {
                            var curSpace = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
                            curSpace.AppendEntity(br);
                            tr.AddNewlyCreatedDBObject(br, true);
                            var dim = new AlignedDimension(fixedPoint, br.Position, br.Position, "", db.Dimstyle);
                            curSpace.AppendEntity(dim);
                            tr.AddNewlyCreatedDBObject(dim, true);
                        }
                    }
                    finally
                    {
                        acap.SetSystemVariable("dynmode", dynmode);
                    }
                }

                tr.Commit();
            }
        }

        class BlockDimJig : EntityJig
        {
            BlockReference br;
            Point3d basePoint, dragPoint;
            bool isVertical;
            DynamicDimensionDataCollection dynDimDataCol;
            AlignedDimension dim;

            public BlockDimJig(BlockReference br) : base(br)
            {
                this.br = br;
                this.basePoint = br.Position;
                isVertical = br.Rotation == Math.PI * 0.5 || br.Rotation == Math.PI * 1.5;
                dynDimDataCol = new DynamicDimensionDataCollection();
                dim = new AlignedDimension();
                dim.XLine1Point = basePoint;
                dim.XLine2Point = basePoint;
                dim.DimLinePoint = basePoint;
                dynDimDataCol.Add(new DynamicDimensionData(dim));
            }

            protected override SamplerStatus Sampler(JigPrompts prompts)
            {
                var options = new JigPromptPointOptions("\nInsertion point: ");
                options.UseBasePoint = true;
                options.BasePoint = basePoint;
                var result = prompts.AcquirePoint(options);
                if (result.Value.IsEqualTo(basePoint))
                    return SamplerStatus.NoChange;
                dragPoint = result.Value;
                return SamplerStatus.OK;
            }

            protected override bool Update()
            {
                var point = isVertical ?
                    new Point3d(basePoint.X, dragPoint.Y, basePoint.Z) :
                    new Point3d(dragPoint.X, basePoint.Y, basePoint.Z);
                br.Position = point;
                dim.XLine1Point = basePoint;
                dim.XLine2Point = point;
                dim.DimLinePoint = point;
                return true;
            }

            protected override DynamicDimensionDataCollection GetDynamicDimensionData(double dimScale)
            {
                base.GetDynamicDimensionData(dimScale);
                return dynDimDataCol;
            }
        }


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 7 of 9

a.kouchakzadeh
Advocate
Advocate

Awesome and very nice. Thanks alot sir. and thanks to Mr. Yuan as well.

I have a ton of question:

Giles, can you tell us how does this work: 

isVertical = br.Rotation == Math.PI * 0.5 || br.Rotation == Math.PI * 1.5;

in your code, fixing the movement on X or Y axis is with this part?

var point = isVertical ?
                    new Point3d(basePoint.X, dragPoint.Y, basePoint.Z) :
                    new Point3d(dragPoint.X, basePoint.Y, basePoint.Z);

how can I make it work with a specific angle, if my block ref isnt exactly at the X or Y axis?

 

I noticed I can set the distance by typing a value, but it does not set it accurately. for example if I type in 13, it would insert the block on 12.8767. how can I modify the code so it would work for example with XXX number accuracy?

 

in the picture below, I assume the dynDimDataCol the indicated object?

NSV-removebg-preview.png

 

is there any way I can change the color of the text based on some calculation? i.e. if its greater than a value, how can I make it red, and if its less, make it green? I tried

dim.Dimclrt = Color.FromColorIndex(ColorMethod.ByAci, 5)

in the override bool Update() method, but nothing happened with the text color. what am I doing wrong? 

 

and what does this recursive method do?

protected override DynamicDimensionDataCollection GetDynamicDimensionData(double dimScale)
            {
                base.GetDynamicDimensionData(dimScale);
                return dynDimDataCol;
            }

 

0 Likes
Message 8 of 9

a.kouchakzadeh
Advocate
Advocate

Mr. Yuan I have made little changes in your original code:

public class DimMoveJig : DrawJig
    {
        private ObjectId _entityId;
        private Point3d _basePoint = Point3d.Origin;
        private Point3d _prevPoint = Point3d.Origin;
        private Point3d _movingPoint = Point3d.Origin;

        private Document _dwg;
        private Editor _ed;
        private double _number;
        private Entity _entity;
        private AlignedDimension _dim = null;

        public DimMoveJig(double number) : base()
        {
            _number = number;
            _dwg = acap.DocumentManager.MdiActiveDocument;
            _ed = _dwg.Editor;
        }

        public void Move()
        {
            if (!SelectEntity(out ObjectId entId, out Point3d basePt)) return;
            _entityId = entId;
            _basePoint = basePt;
            _prevPoint = basePt;
            _movingPoint = basePt;
            var offset = GetDimLineOffset(_entityId);
            var dimTextPt = GetMidOffsetPoint(_basePoint, _movingPoint, offset);
            try
            {
                _dim = new AlignedDimension(_basePoint,_movingPoint,dimTextPt,"0000",_dwg.Database.DimStyleTableId);
                using (var tran = _dwg.TransactionManager.StartTransaction())
                {
                    _entity = new BlockReference(_movingPoint, entId) as Entity;
                    var curSpace = (BlockTableRecord)tran.GetObject(_dwg.Database.CurrentSpaceId, OpenMode.ForWrite);
                    var res = _ed.Drag(this);
                    if (res.Status == PromptStatus.OK)
                    {
                        curSpace.AppendEntity(_entity);
                        tran.AddNewlyCreatedDBObject(_entity, true);
                        tran.Commit();
                    }
                    else
                    {
                        tran.Abort();
                    }
                }
            }
            finally
            {
                if (_dim != null) _dim.Dispose();
            }
            _ed.WriteMessage("\n");
        }

        protected override SamplerStatus Sampler(JigPrompts prompts)
        {
            ...
        }

        protected override bool WorldDraw(WorldDraw draw)
        {
            ...
        }
        
        private bool SelectEntity(out ObjectId entId, out Point3d basePoint)
        {
            entId = ObjectId.Null;
            basePoint = Point3d.Origin;
            var ok = true;
            using (var tr = _dwg.Database.TransactionManager.StartTransaction())
            {
                var blockTable = tr.GetObject(_dwg.Database.BlockTableId, OpenMode.ForRead) as BlockTable;
                if (!(blockTable.Has("1")))
                    ok=false;
                else
                {
                    entId = blockTable["1"];
                    var pRes = _ed.GetPoint("\nSelect base point:");
                    if (pRes.Status == PromptStatus.OK)
                        basePoint = pRes.Value;
                    else
                        ok = false;
                }
            }
            if (!ok) _ed.WriteMessage("\n*Cancel*\n");
            return ok;
        }
        private double GetDimLineOffset(ObjectId entId)
        {
            Extents3d ext;
            using (var tran = entId.Database.TransactionManager.StartOpenCloseTransaction())
            {
//this works but I strongly feel Im doing nasty stuff. what is the correct way to do it?
                var ent = new BlockReference(Point3d.Origin, entId) as Entity;
                ext = ent.GeometricExtents;
            }
            var w = ext.MaxPoint.X - ext.MinPoint.X;
            var h = ext.MaxPoint.Y - ext.MinPoint.Y;
            return (w > h ? w : h) / 5.0;
        }
        private Point3d GetMidOffsetPoint(Point3d startPt, Point3d endPt, double offset)
        {
            ....
        }
    }

I was wondering how can I add another block ref to the jigged block which is moving along the cursor?
also, is it possible to add another dimension to the other side of the jigged block?

 

in this picture, I have clicked on the right side. but, can the code be modified so the user would select two points then have both dimensions jigged?

akouchakzadeh_1-1689635770256.png

 

TIA

 

 

 

 

 

 

0 Likes
Message 9 of 9

a.kouchakzadeh
Advocate
Advocate

Solved. I just had to get another point in the SelectEntity method and add another AlignedDimension to the move method. in order to change the dimension color, I had to manipulate the sample method and add this:

 if (_basePoint.DistanceTo(res.Value) > _number)
      _dim.Dimclrt = Color.FromColorIndex(ColorMethod.ByAci, 5);
 else
      _dim.Dimclrt = Color.FromColorIndex(ColorMethod.ByAci, 3);

 

0 Likes