Automated CAD Drawing: Implementing Polylines and Point-Based Graphics Generation

1. Requirements Analysis

In CAD development, we often need to implement these functionalities:

  1. Allow users to click multiple points to automatically draw polylines
  2. Enable users to click multiple points and automatically draw graphics at those locations
  3. Remove blocks that intersect with lines or graphics

2. Automated Polyline Drawing

Implementation Approach:

  1. Prompt the user to select the entire area of operation
  2. Use selection filters to identify all blocks within the specified layer
  3. Create a dedicated layer for polylines
  4. Initiate a loop for drawing multiple polylines
  5. For each polyline, recursively collect point selections from the user
  6. Analyze the collected points to determine the optimal connection path
  7. Draw the polyline on the designated layer
  8. Utilize CAD's IntersectWith API to detect intersections with blocks
  9. Remove any blocks that intersect with the polyline

Code Implementation:

/// <summary>
/// Creates polylines based on user input and removes intersecting blocks
/// </summary>
[CommandMethod("CREATEPL")]
public void CreatePolylines()
{
    string targetLayer = CommonConstant.PHALANX_DIVISION_LAYER;
    var doc = Application.DocumentManager.MdiActiveDocument;
    Editor editor = doc.Editor;
    Database db = doc.Database;
    
    // Filter selection to find all blocks in the specified layer
    TypedValue[] filters = {
        new TypedValue((int)DxfCode.Start, "INSERT"),
        new TypedValue((int)DxfCode.LayerName, targetLayer)
    };
    SelectionFilter selectionFilter = new SelectionFilter(filters);
    PromptSelectionResult selectionResult = editor.GetSelection(selectionFilter);
    
    if (selectionResult.Status == PromptStatus.OK)
    {
        // Get all selected blocks
        SelectionSet selectedSet = selectionResult.Value;
        editor.WriteMessage("\nTotal blocks selected: {0}", selectedSet.Count);
        List<BlockReference> blockRefs = new List<BlockReference>();
        
        using (Transaction ts = db.TransactionManager.StartTransaction())
        {
            foreach (SelectedObject selectedObj in selectedSet)
            {
                BlockReference blockRef = selectedObj.ObjectId.GetObject(OpenMode.ForWrite) as BlockReference;
                blockRefs.Add(blockRef);
            }
            ts.Commit();
        }
        
        // Create new layer for polylines
        AddLayerResult layerResult = LayerTool.AddLayer(db, CommonConstant.ROAD_LAYER);
        
        int polylineCounter = 1;
        bool continueDrawing = true;
        
        while (continueDrawing)
        {
            int nodeCounter = 1;
            PromptPointOptions pointOptions = new PromptPointOptions("\nStart point for polyline " + polylineCounter + ", node " + nodeCounter + ":");
            PromptPointResult pointResult = editor.GetPoint(pointOptions);
            List<Point3d> polylineNodes = new List<Point3d>();
            
            if (pointResult.Status == PromptStatus.OK)
            {
                polylineNodes.Add(pointResult.Value);
                pointService.CollectPoints(polylineNodes, polylineCounter, nodeCounter, editor);
                drawingService.CreateAndCleanPolyline(blockRefs, polylineNodes, layerResult.layerName);
            }
            else
            {
                continueDrawing = false;
            }
            polylineCounter++;
        }
    }
}
/// <summary>
/// Collects points from user for polyline creation
/// </summary>
/// <param name="collectedPoints">List of points collected so far</param>
/// <param name="polylineIndex">Current polyline number</param>
/// <param name="nodeCount">Number of nodes collected</param>
/// <param name="editor">CAD editor interface</param>
public void CollectPoints(List<Point3d> collectedPoints, int polylineIndex, int nodeCount, Editor editor)
{
    nodeCount++;
    PromptPointOptions pointOptions = new PromptPointOptions("\nSelect point " + polylineIndex + ", node " + nodeCount + ":");
    PromptPointResult pointResult = editor.GetPoint(pointOptions);
    
    if (pointResult.Status == PromptStatus.OK)
    {
        collectedPoints.Add(pointResult.Value);
        CollectPoints(collectedPoints, polylineIndex, nodeCount, editor);
    }
}
/// <summary>
/// Creates polyline and removes intersecting blocks
/// </summary>
/// <param name="blockReferences">List of blocks to check for intersections</param>
/// <param name="polylinePoints">Points defining the polyline</param>
/// <param name="layerName">Name of the layer for the polyline</param>
public void CreateAndCleanPolyline(List<BlockReference> blockReferences, List<Point3d> polylinePoints, string layerName)
{
    using (Transaction tr = doc.TransactionManager.StartTransaction())
    {
        if (blockReferences.Count > 0)
        {
           // Determine optimal connection path
           polylinePoints = geometryTool.OptimizePath(polylinePoints);
           List<Point2d> points2D = polylinePoints.Select(p => new Point2d(p.X, p.Y)).ToList();
           
           // Draw the polyline
           ObjectId polylineId = db.AddPolylineToModelSpace(false, 10, layerName, points2D.ToArray());
           
           // Remove blocks that intersect with the polyline
           DBObject dbObject = tr.GetObject(polylineId, OpenMode.ForWrite);
           if (dbObject is Polyline)
           {
               Polyline polyline = (Polyline)dbObject;
               List<Point3d> intersectionPoints = new List<Point3d>();
               
               for (var i = 0; i < blockReferences.Count; i++)
               {
                   Point3dCollection intersections = new Point3dCollection();
                   polyline.IntersectWith(blockReferences[i], Intersect.OnBothOperands, intersections, IntPtr.Zero, IntPtr.Zero);
                   
                   if (intersections.Count > 0)
                   {
                       intersectionPoints.Add(blockReferences[i].Position);
                   }
               }
               
               if (intersectionPoints.Count > 0)
               {
                   blockManager.RemoveBlocksByLocation(db, CommonConstant.BRACKET_BLOCK_NAME, intersectionPoints);
               }
           }
        }
        tr.Commit();
    }
}

3. Drawing Graphics at Specified Points

Implementation Approach:

  1. Similar to polyline drawing but focuses on creating graphics at specific points
  2. Uses selection filters to identify blocks in the target area
  3. Creates a new layer for the graphics
  4. Collects points from user input
  5. Generates graphics at each specified point
  6. Checks for intersections and removes conflicting blocks

Code Implementation:

/// <summary>
/// Creates graphics at user-specified points
/// </summary>
[CommandMethod("DRAWGP")]
public void CreatePointGraphics()
{
    string targetLayer = CommonConstant.PHALANX_DIVISION_LAYER;
    var doc = Application.DocumentManager.MdiActiveDocument;
    Editor editor = doc.Editor;
    Database db = doc.Database;
    
    // Filter selection to find all blocks in the specified layer
    TypedValue[] filters = {
        new TypedValue((int)DxfCode.Start, "INSERT"),
        new TypedValue((int)DxfCode.LayerName, targetLayer)
    };
    SelectionFilter selectionFilter = new SelectionFilter(filters);
    PromptSelectionResult selectionResult = editor.GetSelection(selectionFilter);
    
    if (selectionResult.Status == PromptStatus.OK)
    {
        // Get all selected blocks
        SelectionSet selectedSet = selectionResult.Value;
        editor.WriteMessage("\nTotal blocks selected: {0}", selectedSet.Count);
        List<BlockReference> blockRefs = new List<BlockReference>();
        
        using (Transaction ts = db.TransactionManager.StartTransaction())
        {
            foreach (SelectedObject selectedObj in selectedSet)
            {
                BlockReference blockRef = selectedObj.ObjectId.GetObject(OpenMode.ForWrite) as BlockReference;
                blockRefs.Add(blockRef);
            }
            ts.Commit();
        }
        
        // Create new layer for graphics
        AddLayerResult layerResult = LayerTool.AddLayer(db, CommonConstant.TRANSFORMER_LAYER);
        
        graphicsGenerator.GenerateAtPoints(blockRefs, layerResult, doc);
    }
}
/// <summary>
/// Generates graphics at specified points and removes intersecting blocks
/// </summary>
/// <param name="blockReferences">List of blocks to check for intersections</param>
/// <param name="layerInfo">Layer information for the graphics</param>
/// <param name="document">CAD document reference</param>
public void GenerateAtPoints(List<BlockReference> blockReferences, AddLayerResult layerInfo, Document document)
{
    if (blockReferences.Count > 0)
    {
        Editor editor = document.Editor;
        Database db = document.Database;
        
        // Group blocks by color
        var blockGroups = blockReferences.GroupBy(reference => reference.Color)
            .ToDictionary(group => group.Key, 
                group => group.ToList());
        
        int groupCount = blockGroups.Count;
        List<Point3d> graphicPoints = new List<Point3d>();
        
        // Collect points from user
        while (groupCount > 0)
        {
            PromptPointOptions pointOptions = new PromptPointOptions("\nSelect location for graphic " + groupCount);
            PromptPointResult pointResult = editor.GetPoint(pointOptions);
            
            if (pointResult.Status == PromptStatus.OK)
            {
                graphicPoints.Add(pointResult.Value);
            }
            groupCount--;
        }
        
        // Generate graphics at each point
        foreach (var point in graphicPoints)
        {
            Dictionary blockProperties = blockTool.GetMaximumBlockDimensions(db, blockReferences[0]);
            ObjectId graphicId = db.AddPolygonToModelSpace(
                new Point2d(point.X, point.Y), 
                blockProperties["maxXSpacing"] / 2, 
                5, 
                90, 
                layerInfo.layerName);
            
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                DBObject dbObject = tr.GetObject(graphicId, OpenMode.ForWrite);
                if (dbObject is Polyline)
                {
                    Polyline graphic = (Polyline)dbObject;
                    List<Point3d> intersectionPoints = new List<Point3d>();
                    
                    // Check for intersections with blocks
                    for (var i = 0; i < blockReferences.Count; i++)
                    {
                        Point3dCollection intersections = new Point3dCollection();
                        graphic.IntersectWith(blockReferences[i], Intersect.OnBothOperands, intersections, IntPtr.Zero, IntPtr.Zero);
                        
                        if (intersections.Count > 0)
                        {
                            intersectionPoints.Add(blockReferences[i].Position);
                        }
                    }
                    
                    // Remove intersecting blocks if any
                    if (intersectionPoints.Count > 0)
                    {
                        blockTool.RemoveBlocksByLocation(db, CommonConstant.BRACKET_BLOCK_NAME, intersectionPoints); 
                    }
                    
                    // Add label text
                    textTool.AddText(db, "GRAPHIC", new Point2d(point.X, point.Y), blockProperties["maxYSpacing"], layerInfo.layerName);
                }
                tr.Commit();
            }  
        }
    }
}

Tags: CAD Development AutoCAD Polylines automation Graphics Generation

Posted on Wed, 12 Aug 2026 16:49:12 +0000 by Jmz