Analyzing the BUG in IntersectWith() - AutoCAD .Net API





One of the common tasks while solving geometric problems in CAD environment is to find the intersection of two geometric entities such as Lines, Polylines, Polygons (Closed Polyline in CAD), Circle, Ellipse, Regions etc. Natural problems exist where a solution may solely depend upon the intersection and the count of intersections.

A practical example where intersection of geometric entities matters is Cutting a polygon into two parts. Another fundamental problem in computational geometry, CAD, GIS, motion planning and Computer Vision is to detect whether a given point lies inside or outside the given polygon or plane. The simple solution to this problem is to test how many times a ray starting from the given point extends towards the edges of a polygon. An even number of intersections implies that the point is outside of the polygon and vice versa.



Intersections are sometimes also referred when testing to detect overlap of two polygons. In such a case, the region of intersection may be computed instead of a point or points.


The AutoCAD .NET API enables programmers to manipulate the application and drawing files programmatically with the assemblies or libraries that are exposed. With these objects exposed, they can be accessed by many different programming languages such as C# VB.Net and environments such as visual studio.

Autodesk.AutoCAD.DatabaseServices Namespace implements IntersectWith method to populate a Point3dCollection object with intersection points. 



 IntersectWith() method plays a vital role to trim the geometric objects as there is NO trim() like method in API. The geometry of the object to be trimmed is needed to be modified using intersection points. Similarly, IntersectWith() method is also used to extend the linear geometric objects. However, Extend() method is provided in API, but there are some situations where  IntersectWith() method is highly useful and only solution to extend  the linear geometric objects.

The second argument of IntersectWith() method provides the type of the intersection as ExtendBoth, ExtendArgument, ExtendThis and OnBothOperands.


With the significance of intersection in computational geometry and its use in CAD automation explained, it may also be realized that a programmer may have to call IntersectWith() method whenever needed.

 

Recently, I was working on an algorithm to divide a polygon into multiple parts using AutoCAD .Net API. The algorithm was using sort of SweepLine technique calling IntersectWith() method frequently in iterations. Apparently the algorithm was simple, free from any logical error and well implemented but it was failing in most cases.  Interestingly, there was no exception raised but rather the program entered into an infinite loop and ultimately the AutoCAD application had to be forcefully ended from the Windows Task Manager. Debugging the code was hectic and a quite frustrating effort which took more than a month. The BUG was revealed in IntersectWith() method of Autodesk.AutoCAD.DatabaseServices Namespace. As shocking as it may seem, the code below demonstrates the bug. 


        [CommandMethod("IntersectionTest")]
        public static void IntersectionTest()
        {
            Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;   
            Editor ed = doc.Editor;
            
            // First Polyline
            Polyline pl1 = new Polyline();
            pl1.AddVertexAt(0, new Point2d(600097.3438, 494820.3637), 0, 0, 0);
            pl1.AddVertexAt(0, new Point2d(600101.7191, 494825.6028), 0, 0, 0);
            pl1.AddVertexAt(0, new Point2d(600107.4447, 494835.9176), 0, 0, 0);

            // 2nd  Polyline          
            Polyline pl2 = new Polyline();
            pl2.AddVertexAt(0, new Point2d(600110.2043, 494822.9429), 0, 0, 0);
            pl2.AddVertexAt(0, new Point2d(600096.5547, 494827.2256), 0, 0, 0);

            // Intersection Points Collection 
            Point3dCollection intPoints = new Point3dCollection();
            pl1.IntersectWith(pl2, Intersect.OnBothOperands, intPoints, IntPtr.Zero, IntPtr.Zero);

            ed.WriteMessage("\nNo. Of Intersection Points: {0}", intPoints.Count);
            for (int i=0; i < intPoints.Count; i++)
            {
                ed.WriteMessage("\n Point No. {0} X:{1} Y:{2}", i.ToString(), intPoints[i].X, intPoints[i].Y);
            }
        }
The coordinates of two polyline objects (pl1 and pl2) when plotted in CAD seems as below:


The code given above, when compiled, computes the intersection points and stores them in intPoints Points3DCollection. It is evident from the given geometry of both polylines that there should be a single point of intersection. On the contrary, the output returns two intersection points as shown below.


The only explanation for this second point computed using the AutoCAD API is due to presence of a bug in it.  Some interesting observations from trials are as follows:

·       It returns one additional fake intersection point

·       The additional fake intersection point is NOT any vertex of intersecting objects.

·       The code may return different output by moving the polylines to any other location.  


Significance of the issue:

 

Recall the starting paragraphs of this blog. The redundant fake intersection point may create serious issues in case of detecting whether a point is inside a polygon or not. Similarly, in case of computing region of intersection (overlaps) between two polygons, the IntersectWith method in AutoCAD .Net API will yield undesired results.

 

The Way Forward:

 

It is quite surprising that this bug exists in all versions of AutoCAD .Net API (from v2007 to v2021).  It is quite mandatory for Autodesk to notice this bug and fix it. Until, the release of any update or patch, the programmer may have to handle it by writing extra lines of the code to check the number of intersections whenever IntersectWith method is called.

 

Open Design Alliance (ODA) offers other convenient object oriented .Net API for processing DWG and DXF. Many industry driven CAD packages such as BricsCAD, ZwSoft ZWCAD, ProgeCAD, CADMATE, NanoCAD etc expose functionality for use by managed code built on the .NET Common Language Runtime (CLR) platform. The Teigha library by ODA implements IntersectWith method via Teigha.DatabaseServices Namespace with the same number of arguments and data types to populate a Point3dCollection object with intersection points.



The same code was implemented using BricsCAD .Net API. It returned a single point of intersection as below.


The objective of this blog is not to discriminate or defame any product rather it aims to help programmers/developers to handle run time errors while writing code for geometric intersections using AutoCAD .Net API.


Comments

  1. Same thing happens when using coordinates 500 000,6 000 000 and use returned point from IntersectWith to GetClosestPointTo: solution is to transform objects to 0,0.

    ReplyDelete
    Replies

    1. Thanks for your comment.

      The best option is to check for the Duplicate Points (within some tolerance) in 3D Point Collection populated by IntersectWith method and remove the duplicates.

      Delete

Post a Comment

Popular posts from this blog

SpaTools: Import Lidar Point Cloud (LAS/LAZ) files into AutoCAD

How to Clip objects in AutoCAD

Creating Contour Maps in ArcGIS and Conversion to AutoCAD drawing

SpaTools: Extract Topographic Profile From Contours In AutoCAD

Gunter Chain / Surveyor's Chain

SpaTools: Toolbar with all tools