000

Index Labels

Determine Whether 2 Attributes of A BlockReference Overlap

.
Using Attributes in a block to present textual information is a convenient way in AutoCAD. However, it is often that because of the visual limitation of a block, we expect the Attribute's value (text string) not to be too long to exceed the block's visual boundary.

For example, I have a table-like block, and each row host 2 attributes. The left attribute is left-justified, while the right attribute is right-justified. When setting the attributes' value, it is possible that the 2 attributes get overlapped because of the attributes' value text string is too long. If the attributes are updated by user manually, the user obviously can see what happens and can handle it as needed, for example, change the text value of the attributes to try to fit the allowed space. However, when the attributes are to be updated by code, as programmer, we may want to know if the 2 attributes would overlap when certain attribute values are set.

I ran into an similar situation. In this case, if I can test the 2 target attributes would be overlap with given attribute values, the code should change the block's dynamic property to avoid the overlap.

So, I wrote some code to see how easy (or, difficult) to test if 2 attributes are overlap. In my case, to make things easier, the attribute in the block is not MText type. So, it is just a single line of text. Therefore, I only need to find out each attribute's bounding box (GeometricExtents) and whether one of the corner points of entents A is inside entents B, then the 2 extents are overlap. Of course, this only applies to attributes with rotation angle equal to 0. if the block has to be inserted into certain rotation angle, I can do this overlapping test before the block is rotated.

Here is the code:

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Geometry;
using CadApp = Autodesk.AutoCAD.ApplicationServices.Application;

[assemblyCommandClass(typeof(AttributeOverlapTest.MyCadCommands))]

namespace AttributeOverlapTest
{
    public class MyCadCommands
    {
        [CommandMethod("AttOverlap")]
        public static void TestAttributeOverlap()
        {
            Document dwg = CadApp.DocumentManager.MdiActiveDocument;
            Editor ed = dwg.Editor;

            try
            {
                ObjectId attrId1 = PickAttribute(ed);
                if (!attrId1.IsNull)
                {
                    ObjectId attrId2 = PickAttribute(ed);
                    if (!attrId2.IsNull)
                    {
                        bool overlap = TestAttributeOverlap(
                            dwg.Database, attrId1, attrId2);
                        ed.WriteMessage("\n{0}."
                            overlap ? "Overlapped" : "Not overlapped");
                    }
                }
                
            }
            catch (System.Exception ex)
            {
                ed.WriteMessage("\nError: {0}\n{1}", ex.Message, ex.StackTrace);
            }
            finally
            {
                Autodesk.AutoCAD.Internal.Utils.PostCommandPrompt();
            }
        }

        private static ObjectId PickAttribute(Editor ed)
        {
            ObjectId id = ObjectId.Null;

            while (true)
            {
                PromptNestedEntityOptions opt =
                    new PromptNestedEntityOptions(
                        "\nSelect an attribute in a block:");

                PromptNestedEntityResult res = ed.GetNestedEntity(opt);
                if (res.Status == PromptStatus.OK)
                {
                    if (res.ObjectId.ObjectClass.DxfName.ToUpper() == "ATTRIB")
                    {
                        id = res.ObjectId;
                        break;
                    }
                    else
                    {
                        ed.WriteMessage(
                            "\nInvalid selection: not an attribute.");
                    }
                }
                else
                {
                    break;
                }
            }

            return id;
        }

        private static bool TestAttributeOverlap(
            Database db, ObjectId attId1, ObjectId attId2)
        {
            Extents3d ext1;
            Extents3d ext2;
            using (Transaction tran=db.TransactionManager.StartTransaction())
            {
                Entity ent1 = (Entity)tran.GetObject(attId1, OpenMode.ForRead);
                Entity ent2 = (Entity)tran.GetObject(attId2, OpenMode.ForRead);
                ext1 = ent1.GeometricExtents;
                ext2 = ent2.GeometricExtents;
                tran.Commit();
            }

            if (ExtentsOverlap(ext1, ext2)) return true;

            return false;
        }

        private static bool ExtentsOverlap(Extents3d ext1, Extents3d ext2)
        {
            //Get 4 points from one of the extents
            Point3d[] pts = new Point3d[]
            {
                new Point3d(ext2.MinPoint.X, ext2.MinPoint.Y, 0.0),
                new Point3d(ext2.MaxPoint.Y, ext2.MaxPoint.Y, 0.0),
                new Point3d(ext2.MinPoint.X, ext2.MaxPoint.Y, 0.0),
                new Point3d(ext2.MaxPoint.X, ext2.MinPoint.Y, 0.0)
            };

            //Add each point into the other extents, 
            //if the extents is not changed,
            //that means the 2 extents are overlapped in 2D plane
            foreach (var p in pts)
            {
                Extents3d ext = new Extents3d(
                    new Point3d(ext1.MinPoint.X, ext1.MinPoint.Y, 0.0),
                    new Point3d(ext1.MaxPoint.X, ext1.MaxPoint.Y, 0.0));

                ext.AddPoint(p);

                if (ext == ext1) return true;
            }

            return false;
        }
    }
}

Go to this video clip to see how the code runs.

With this piece of code, I can update one of my existing application to avoid overlapped attributes when updating the attribute values programmatically.



Blog Archive

Labels

3D Modeling 3D Sketch Inventor AI Design AI in Manufacturing AI Tools Architecture Artificial Intelligence AutoCAD AutoCAD advice AutoCAD Basics AutoCAD Beginners AutoCAD Civil3D AutoCAD commands AutoCAD efficiency AutoCAD features AutoCAD File Management AutoCAD Layer AutoCAD learning AutoCAD print settings AutoCAD productivity AutoCAD Teaching AutoCAD Techniques AutoCAD tips AutoCAD training. AutoCAD tricks AutoCAD Tutorial AutoCAD workflow AutoCAD Xref Autodesk Autodesk 2025 Autodesk AI Tools Autodesk AutoCAD Autodesk Fusion 360 Autodesk Inventor Autodesk Inventor Frame Generator Autodesk Inventor iLogic Autodesk Recap Autodesk Revit Autodesk Software Autodesk Video Automation Automation Tutorial Basic Commands Basics Beginner Beginner Tips BIM BIM Implementation Block Editor ByLayer CAD comparison CAD Design CAD File Size Reduction CAD line thickness CAD Optimization CAD Productivity CAD software clean CAD file cleaning command Cloud Collaboration command abbreviations Construction Technology Contraints Create resizable blocks CTB STB Data Reference Data Shortcut design software Design Workflow Digital Design Digital Twin Drafting Standards Drawing Automation Dref Dynamic Block Dynamic Block AutoCAD Dynamic Blocks Dynamic doors Dynamic windows eco design editing commands energy efficiency Engineering Engineering Design Engineering Innovation Engineering Technology engineering tools Excel Express Tools External Reference Fast Structural Design Fusion 360 Generative Design green building Grips heavy CAD file Heavy CAD Files iLogic Industry 4.0 Insight Inventor API Inventor Drawing Template Inventor Frame Generator Inventor Graphics Issues Inventor IDW Inventor Tips Keyboard Shortcuts Learn AutoCAD Machine Learning in CAD maintenance command Management Manufacturing Innovation Metal Structure ObjectARX .NET API Organization OVERKILL OVERKILL AutoCAD Palette PDF Plot Style AutoCAD Practice Drawing Printing Quality professional printing Professional Tips PTC Creo PURGE PURGE AutoCAD ReCap reduce CAD file size Resizable Block Revit Revit Best Practices Revit Workflow Ribbon screen shortcut keys Shortcuts Siemens NX Sketch Small Firms Smart Block Smart Factory SolidWorks Steel Structure Design sustainability Sustainable Manufacturing toolbar Tutorial User Interface (UI) Workbook Workspace XLS Xref