Sunday, December 18, 2011

C#.Net: Circle All MText Objects in a Drawing

This program places a red circle around all MText objects in a drawing. The functionality is pretty much stripped down to a basic starting point. This should be a fun program to add additional features to in order to continue exploring C#.Net concepts.

The inline comments should explain each segment, a few things to point out are:

  • We use two functions - one as our entry point with the AutoCAD defined command, and the other as a support function called by the main one.
  • We use some of the provided object methods from the AutoCAD API. For example, as we work with an MText object we use the predefined Location method to determine the coordinates.
Some of the features we will add on in future posts can be:
  • Prompt options to allow the user to change the circle color, size, etc.
  • Place circles around Text objects as well as MText.
  • Place circles around Text/MText objects that match a string provided by the user.
Here is the C# code:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;

namespace SLD
{
    public class SLDtools
    {
        [CommandMethod("SLDcirText")]
        public void SLDcirText()
        {
            //get current document
            Document acDoc =
                Application.DocumentManager.MdiActiveDocument;

            //get AutoCAD database
            Database acCurDb = acDoc.Database;

            //start db transaction
            using (Transaction acTrans =
                acCurDb.TransactionManager.StartTransaction())
            {
                //open block table
                /*all drawing objects are in the block table so in
                 order to look at each object we need to have the
                 block table open for read*/
                BlockTable bt = (BlockTable)acTrans.GetObject
                    (acCurDb.BlockTableId, OpenMode.ForRead);

                BlockTableRecord btr = (BlockTableRecord)
                    acTrans.GetObject(bt[BlockTableRecord.ModelSpace],
                    OpenMode.ForRead);

                //iterate through block table to locate mtext objects
                /*this foreach loop will loop through the block table
                 record looking at each object in the drawing.*/
                foreach (ObjectId id in btr)
                {
                    //open each object to read
                    DBObject obj = acTrans.GetObject
                        (id, OpenMode.ForRead);

                    //only deal with MText objects
                    MText dbMText = obj as MText;

                    //if current object is Mtext then draw a circle
                    //around it
                    if (dbMText != null)
                    {
                        //call separate function to draw circle
                        /*here we want to pass the acad db, the current
                         transaction, and the mtext object that we want
                         to draw a circle around*/
                        SLDdrawCir(acCurDb, acTrans, dbMText);
                    }
                }
                //commit the transaction so we do not leave the db open
                acTrans.Commit();
            }

        }

        //function to draw circle around an MText object
        public void SLDdrawCir(Database acCurDb,
            Transaction acTrans, MText MtextObj)
        {
            //define a new point object for the center point of circle
            Point3d cenPoint = new Point3d();

            //use the location method of the Mtext object to define
            //the center point coordinates
            cenPoint = MtextObj.Location;

            //define a new Circle object
            /*we use the center point defined above, assign a diameter
             and assign a color using the ColorIndex method from the
             circle object*/
            Circle textCir = new Circle();
            textCir.Center = cenPoint;
            textCir.Diameter = 1.0;
            textCir.ColorIndex = 1;

            //now add the circle to the drawing (model space)
            /*We need to add it to the block table, this is the same
             basic operations when adding geometry to a drawing*/
            BlockTable acBlkTbl;
            acBlkTbl = acTrans.GetObject(
                acCurDb.BlockTableId, OpenMode.ForRead) as BlockTable;

            BlockTableRecord acBlkTblRec;
            acBlkTblRec = acTrans.GetObject(
                acBlkTbl[BlockTableRecord.ModelSpace],
                OpenMode.ForWrite)
                as BlockTableRecord;

            acBlkTblRec.AppendEntity(textCir);
            acTrans.AddNewlyCreatedDBObject(textCir, true);
        }
    }
}

To test this build the solution and NETLOAD the .dll into AutoCAD. Place some MText objects in the drawing and then type in SLDcirText at the command line.

5 comments:

  1. Hi I have just seen your post about drawing circles around mtext. This would be extremely useful for what I am trying to do. However I am having difficulty getting your programme to work. You will have to excuse me I am very new to this side of AutoCAD having only just started using lisp files. Is there any way you could simplify the steps of what I need to do to get this programme to work. I am currently using AutoCAD 2012. Many thanks for your time. Sally

    ReplyDelete
    Replies
    1. Hi Sally, thanks for reading! To get this program to work you can just copy and paste the code into a C#.Net solution using Microsoft Visual Studio. This might sound intimidating if you are new to programming but please read my post on getting started with this development environment http://www.streamlined-design.blogspot.com/2010/09/custom-apps.html
      This will guide you through the entire process of downloading the (Free) software from Microsoft, installing it, creating a new solution, and then loading the program into AutoCAD. Please let me know if this helps.

      Delete
  2. This comment has been removed by the author.

    ReplyDelete
  3. Hi, I am new to progaramming. How to do if I want a circle a text which is on a certain layer? Thanks

    ReplyDelete
  4. Hi oakam, great question which is a good exercise for learning. In the original code we are looking through each object in the drawing and then only dealing with MText objects. We could further our requirements (i.e. only deal with MText objects on a certain layer by adding an additional check in the:
    if (dbMtext != null) section. It would look like this:

    if (dbMtext != null)
    {
    if (dbMtext.Layer == "G-TEXT") //this is the new conditional check
    {
    SLDdrawCir(acCurDb, acTrans, dbMtext);
    }
    }

    This updated code will only call the SLDdrawCir function if the MText entity is on the layer G-TEXT.

    I hope this helps.

    ReplyDelete