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

How to create class Jig Insert Block with distance and Length in C#

4 REPLIES 4
SOLVED
Reply
Message 1 of 5
Revit_API
1172 Views, 4 Replies

How to create class Jig Insert Block with distance and Length in C#

Hi Guys,

 

I am developing a plugin and I want to create class Jig Insert Block with distance and length same with Array.

This is test code. Please advice!

[CommandMethod("Test")]
    public void TestcodeSingle()
    {
        var doc = AcAp.DocumentManager.MdiActiveDocument;
        var db = doc.Database;
        var ed = doc.Editor;
        Matrix3d curUCSMatrix = ed.CurrentUserCoordinateSystem;
        CoordinateSystem3d curUCS = curUCSMatrix.CoordinateSystem3d;
        PromptPointOptions options = new PromptPointOptions("\nStart Point: ");
        PromptPointResult result = ed.GetPoint(options);
        if (result.Status != PromptStatus.OK)
            return;
        Point3d startPoint = result.Value;
        Line ent = new Line(startPoint, startPoint);
        try
        {
            AcAp.SetSystemVariable("osmode", 128);
            options.BasePoint = ent.EndPoint;
            options.UseBasePoint = true;
            options.Message = "\nNext Point: ";
            result = ed.GetPoint(options);
            if (result.Status != PromptStatus.OK)
            {
                AcAp.SetSystemVariable("osmode", 703);
                return;
            }
            ent = new Line(ent.EndPoint, result.Value);
            Point3d ptStart = ent.StartPoint;
            Point3d ptEnd = ent.EndPoint;
            double cur_Lenght = ptEnd.X - ptStart.X;
            int numberCol = Convert.ToInt32(cur_Lenght / 2000); 
            using (var tr = db.TransactionManager.StartTransaction())
            {
                BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
                BlockTableRecord btr = new BlockTableRecord();
                btr = tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
                ObjectId blkRecId = ObjectId.Null;
                blkRecId = bt["ABC"];


                for (int i = 0; i < numberCol; i++)
                {
                    using (BlockReference blkRef = new BlockReference(new Point3d(ptStart.X + (i * 2000), ptStart.Y, 0), blkRecId))
                    {
                        btr.AppendEntity(blkRef);
                        tr.AddNewlyCreatedDBObject(blkRef, true);
                    }
                }
                tr.Commit();
            }
        }
        catch (System.Exception e)
        {
            ed.WriteMessage(e.ToString());
        }
    }

e! 

Labels (1)
4 REPLIES 4
Message 2 of 5
norman.yuan
in reply to: Revit_API

I do not see how your code has anything to do with Jig, or how you want to use Jig into your process: you just want to insert multiple block references in calculated interval horizontally once user selects second point. 

 

Besides inserting multiple block references in a row/column manner, do you know there is a MInsertBlock class (corresponding to built-in command "MINSERT") you can use to create block references of the same block definition in row/column manner? or, you can use AssocArray (built-in command "ArrayRect[Polar/Path]") to do this kind of job?

 

Maybe, by "jig", you mean when asking and waiting user to pick second point (i.e. when user moves mouse going for the second point pick), you want to show ghost image of possible block references to be inserted, thus "JIG"? If that is what you want to do, you can search this forum or the Internet for JIG code samples: there would be plenty of them. But your JIG would be a bit tricker than regular block inserting Jig you could find, most of them derived from EntityJig. You might want to derive yours from DrawJig, because you have to draw multiple block images. You could also use Transient Graphics in conjunction with Editor.PointMonitor event handler to achieve the goal of drawing multiple block images while user moves mouse for second point.

 

If you code of inserting block references is not followed by other code execution immediately, using AssocArray might be the easiest way to do: after your code, user can easily drag the row/column of the array as needed.

 

Again, you may want to describe your intention in more details to may things clearer.

 

Norman Yuan

Drive CAD With Code

EESignature

Message 3 of 5
Revit_API
in reply to: norman.yuan

Thank you very much about your advice.

''(i.e. when user moves mouse going for the second point pick), you want to show ghost image of possible block references to be inserted, thus "JIG"?''---> Yes, I want to do this for my code above. I have searched any sample code on internet but that sample code jig don't same with my require. Can you share some sample code or what solution that can help me handle this problem? Currently, I don't know how to do and start where. Please advice!

Cheer.

Message 4 of 5
norman.yuan
in reply to: Revit_API

Sorry for the late reply: I just managed a bit time to come up a runnable code sample. Here you go:

 

The EntityArrayJig class:

using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.GraphicsInterface;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.ApplicationServices;
using System;
using System.Collections.Generic;
using Autodesk.AutoCAD.Geometry;

namespace CustomJigs
{
    public class EntityArrayJig : DrawJig, IDisposable
    {
        private Document _dwg;
        private Editor _ed;
        private Database _db;

        private ObjectId _baseEntity = ObjectId.Null;

        private Entity _baseGhost = null;
        private List<Tuple<Entity, Matrix3d>> _ghostEntities =
            new List<Tuple<Entity, Matrix3d>>();

        private Point3d _basePoint;
        private Point3d _currPoint;
        private double _distance = 0.0;
        private int _colorIndex = 2;

        public void Dispose()
        {
            if (_baseGhost != null) _baseGhost.Dispose();
            ClearGhostEntities();
        }

        public void DrawArray()
        {
            _dwg = Application.DocumentManager.MdiActiveDocument;
            _ed = _dwg.Editor;
            _db = _dwg.Database;
            if (!SelectBaseEntity(out _baseEntity, out _basePoint, out _distance)) return;
            _baseGhost = CreateBaseGhost();
            _currPoint = _basePoint;

            var res = _ed.Drag(this);
            if (res.Status == PromptStatus.OK && _ghostEntities.Count > 0)
            {
                using (var tran = _db.TransactionManager.StartTransaction())
                {
                    var space = (BlockTableRecord)tran.GetObject(
                        _db.CurrentSpaceId, OpenMode.ForWrite);
                    var baseEnt = (Entity)tran.GetObject(_baseEntity, OpenMode.ForRead);
                    for (int i = 0; i < _ghostEntities.Count; i++)
                    {
                        CreateEntityCopy(baseEnt, space, i, tran);
                    }

                    tran.Commit();
                }
            }
        }

        protected override SamplerStatus Sampler(JigPrompts prompts)
        {
            var opt = new JigPromptPointOptions("\nSelect array's end:");
            opt.BasePoint = _basePoint;
            opt.UseBasePoint = true;
            opt.Cursor = CursorType.RubberBand;
            var res = prompts.AcquirePoint(opt);
            if (res.Status== PromptStatus.OK)
            {
                if (res.Value==_currPoint)
                {
                    return SamplerStatus.NoChange;
                }
                else
                {
                    _currPoint = res.Value;
                    return SamplerStatus.OK;
                }
            }
            else
            {
                return SamplerStatus.Cancel;
            }
        }

        protected override bool WorldDraw(WorldDraw draw)
        {
            RecreateGhosts();

            foreach (var item in _ghostEntities)
            {
                draw.Geometry.Draw(item.Item1);
            }
            
            return true;
        }

        #region private methods

        private bool SelectBaseEntity(
            out ObjectId baseEnt, out Point3d basePoint, out double distance)
        {
            baseEnt = ObjectId.Null;
            basePoint = Point3d.Origin;
            distance = 0.0;

            var res = _ed.GetEntity(
                "\nSelect an entity:");
            if (res.Status== PromptStatus.OK)
            {
                baseEnt = res.ObjectId;
                basePoint = res.PickedPoint;

                var pOpt = new PromptPointOptions(
                    $"\nBase point: {basePoint}. Select different base point:");
                pOpt.AllowNone = true;
                pOpt.AppendKeywordsToMessage = true;
                pOpt.Keywords.Add("Continue");
                pOpt.Keywords.Add("Cancel");
                pOpt.Keywords.Default = "Continue";

                bool ptOk = false;
                var pRes = _ed.GetPoint(pOpt);
                if (pRes.Status == PromptStatus.OK)
                {
                    basePoint = pRes.Value;
                    ptOk = true;
                }
                else if (pRes.Status == PromptStatus.Keyword)
                {
                    if (pRes.StringResult == "Continue") ptOk = true;
                }

                if (ptOk)
                {
                    var dOpt = new PromptDistanceOptions(
                        "\nPick/Enter the distance between entities:");
                    dOpt.AllowNegative = false;
                    dOpt.AllowZero = false;
                    dOpt.UseBasePoint = true;
                    dOpt.BasePoint = basePoint;
                    dOpt.UseDashedLine = true;

                    var dRes = _ed.GetDistance(dOpt);
                    if (dRes.Status== PromptStatus.OK)
                    {
                        distance = dRes.Value;
                        return true;
                    }
                }
            }

            return false;
        }

        private Entity CreateBaseGhost()
        {
            Entity ghost = null;
            using (var tran=_db.TransactionManager.StartTransaction())
            {
                var ent = (Entity)tran.GetObject(_baseEntity, OpenMode.ForRead);
                ghost = ent.Clone() as Entity;
                ghost.ColorIndex = _colorIndex;
                tran.Commit();
            }
            return ghost;
        }

        private void ClearGhostEntities()
        {
            foreach (var item in _ghostEntities)
            {
                item.Item1.Dispose();
            }
            _ghostEntities.Clear();
        }

        private void RecreateGhosts()
        {
            ClearGhostEntities();
            using (var line=new Line(_basePoint, _currPoint))
            {
                var l = _distance;
                while(l<line.Length)
                {
                    var pt = line.GetPointAtDist(l);
                    var mt = Matrix3d.Displacement(_basePoint.GetVectorTo(pt));
                    var ghost = _baseGhost.Clone() as Entity;
                    ghost.ColorIndex = _colorIndex;
                    ghost.TransformBy(mt);
                    _ghostEntities.Add(new Tuple<Entity, Matrix3d>(ghost, mt));
                    l += _distance;
                }
            }
        }

        private void CreateEntityCopy(
            Entity sourceEntity, BlockTableRecord space, int index, Transaction tran)
        {
            var newEnt = sourceEntity.Clone() as Entity;
            if (newEnt != null)
            {
                var mt = _ghostEntities[index].Item2;
                newEnt.TransformBy(mt);
                space.AppendEntity(newEnt);
                tran.AddNewlyCreatedDBObject(newEnt, true);
            }
        }

        #endregion
    }
}

 

 The CommandClass to use EntityArrayJig (incredibly simple, isn't it?):

 

        [CommandMethod("EntArray")]
        public static void RunMyCommand()
        {
            try
            {
                using (var arrayJig = new EntityArrayJig())
                {
                    arrayJig.DrawArray();
                }
            }
            catch(System.Exception ex)
            {
                CadApp.ShowAlertDialog(
                    $"Error:\n{ex.Message}");
            }
        }

 

Please note that for simplicity, I just used Entity.Clone() to create new entities be be eventually added into database. In real production, you might want to use DeepClone() or call new XXXX() to create entities, depending on your situation.

 

Based on this simplified jig, you can easily enhance it to show ghost entities in multiple dimension (row, column), or show the ghosts along a curve (line. arc, polyline...).

 

See the video clip showing the jig in action:

 

Norman Yuan

Drive CAD With Code

EESignature

Message 5 of 5
Revit_API
in reply to: norman.yuan

Thank you very much.

Your sample code have helped for me too much. Thank you again.

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

Post to forums  

Forma Design Contest


AutoCAD Beta