Author Topic: AutoCAD MEP: Determining if an object is located at a point  (Read 1294 times)

0 Members and 1 Guest are viewing this topic.

Keith Brown

  • Swamp Rat
  • Posts: 601
AutoCAD MEP: Determining if an object is located at a point
« on: February 10, 2014, 08:12:45 AM »
I am developing a routine where the user will select a Clevis Hanger (a multiview part) and insert that hanger onto a pipe (autocad mep object).  The routine will continue to run until they cancel or escape.  This portion of the routine appears to be working great.  What I am attempting to do is once the hanger is inserted into the drawing I want to determine if it was placed onto a pipe or on to empty space.  If it was placed onto a pipe then I would like to anchor (autocad mep entitytoentity anchor) that hanger to the pipe so that it moves with the pipe.  The actual anchoring of the hanger to the pipe appears to be working as well.  What I am having difficulty in doing is determining if the hanger is located on the pipe.  The routine I am using appears to only be working sporadically.  Here is my full method.
 
Code - C#: [Select]
  1.         /// <summary>
  2.         /// Repeatedly inserts hangers into model space until the user cancels the routine through the jig.  
  3.         /// Once the hanger is inserted it will be anchored to the pipe and a threaded rod will be drawn to
  4.         /// the desired elevation
  5.         /// </summary>
  6.         /// <param name="manufacturer">The manufacturer of the hanger</param>
  7.         /// <param name="model">The model number of the hanger</param>
  8.         /// <param name="partSize">The size of the hanger</param>
  9.         internal static void AddHanger(string manufacturer, string model, string partSize)
  10.         {
  11.             Document document = Application.DocumentManager.MdiActiveDocument;
  12.             Database database = document.Database;
  13.             Editor editor = document.Editor;
  14.            
  15.             while (true)
  16.             {
  17.                 try
  18.                 {
  19.                     Member member = GetHangerFromCatalog(manufacturer, model, partSize);
  20.                     if (member != null)
  21.                     {
  22.                         Member thisMember = member;
  23.                         member = (MultiViewPart) thisMember;
  24.                         thisMember.Normal = Vector3d.ZAxis.TransformBy(editor.CurrentUserCoordinateSystem);
  25.                         thisMember.Direction = Vector3d.XAxis.TransformBy(editor.CurrentUserCoordinateSystem);
  26.                         thisMember.Location = Point3d.Origin;
  27.                         thisMember.SetDefaultLayer();
  28.                         var jig = new HangerJig(ref thisMember);
  29.            
  30.                         // The user can cancel out of the routine by normal means during the jigging process
  31.                         if (jig.StartJig() != PromptStatus.OK)
  32.                         {
  33.                             break;
  34.                         }
  35.                         using (Transaction transaction = document.TransactionManager.StartOpenCloseTransaction())
  36.                         {
  37.                             var blockTable = transaction.GetObject(database.BlockTableId, OpenMode.ForWrite, false) as BlockTable;
  38.                             var blockTableRecord = transaction.GetObject(blockTable[BlockTableRecord.ModelSpace], OpenMode.ForWrite, false) as BlockTableRecord;
  39.                             Point3d point = jig.BasePoint;
  40.                             blockTableRecord.AppendEntity((member));
  41.                             transaction.AddNewlyCreatedDBObject(member, true);
  42.  
  43.                             // Determine if the hanger was located on a pipe.  If so then the hanger will be
  44.                             // anchored to the pipe using an entity anchor.  First get all objects in model space
  45.                             // and then if an object is a pipe check to see if the insertion point of the hanger
  46.                             // lies on the pipe curve.
  47.                             foreach (ObjectId objectId in blockTableRecord)
  48.                             {
  49.                                 var pipe = transaction.GetObject(objectId, OpenMode.ForRead) as Pipe;
  50.                                 if (pipe != null)
  51.                                 {
  52.                                     var line = new Line(pipe.StartPoint, pipe.EndPoint);
  53.                                     var pointOnLine = line.GetClosestPointTo(point, false);
  54.                                    
  55.                                     if (point.DistanceTo(pointOnLine) <= (GetPipeRadius(pipe) + .01))
  56.                                     {
  57.                                         // The hanger lies on a pipe so anchor the hanger to the pipe.
  58.                                         pipe.UpgradeOpen();
  59.                                         transaction.GetObject(member.ObjectId, OpenMode.ForWrite);
  60.                                         var anchor = new AnchorEntityToEntity();
  61.                                         anchor.SetToStandard(database);
  62.                                         anchor.SubSetDatabaseDefaults(database);
  63.                                         anchor.SetReferencedEntity(pipe);
  64.                                         anchor.SetReferencedEntityOldEcs(pipe.Ecs);
  65.                                         member.SetAnchor(anchor);
  66.                                         member.UpdateGeoEcs(true);
  67.                                         break;
  68.                                     }
  69.                                     pipe.Dispose();
  70.                                 }
  71.                             }
  72.                             transaction.Commit();
  73.                         }
  74.                     }
  75.                 }
  76.                 catch (Exception e)
  77.                 {
  78.                     Console.WriteMessage("\n**Error** Unable to create/insert hanger.");
  79.                 }
  80.             }
  81.         return;
  82.     }

It is this section of code that determines if the hanger is on a pipe.
 
Code - C#: [Select]
  1.  
  2. if (pipe != null)
  3. {
  4.       var line = new Line(pipe.StartPoint, pipe.EndPoint);
  5.       var pointOnLine = line.GetClosestPointTo(point, false);
  6.                                    
  7.       if (point.DistanceTo(pointOnLine) <= (GetPipeRadius(pipe) + .01))
  8.      {
  9.      \\ ANCHOR CODE GOES HERE
  10.      }
  11. }
  12.  

The insertion point of the clevis hanger is in the center of the hanger where it attaches to the pipe.  When I place the hanger I make sure to snap to the center of the pipe so that the hanger is always centered exactly on the pipe.  Unfortunately this bit of code doesn't work 100% of the time.  It is actually only working about 40% of the time and I am unable to determine why.    I added a tolerance of half the diameter of the pipe to account for not exactly placing the hanger on the pipe but it didn't appear to make a difference.  Does anyone have any ideas why this routine might fail or have a better idea on how to determine if an object is located at a point?  The bottom line of what I need to do is determine is a pipe object is located at a specific point.
 
Any help would be appreciated.
Keith Brown | AutoCAD MEP Blog | RSS Feed
AutoCAD MEP 2014 / Revit MEP 2014 / EastCoast CAD/CAM addon / Visual Studio 2013

Keith Brown

  • Swamp Rat
  • Posts: 601
Re: AutoCAD MEP: Determining if an object is located at a point
« Reply #1 on: February 10, 2014, 06:19:01 PM »
I was able to figure this one out today.  My problem was that I was assuming that the insertion point of the hanger(mvpart) was the same as the jig basepoint or the point that the user clicked to insert the hanger.  This was incorrect thinking on my part.  Where the user clicks to place the hanger(mvpart) and where it actually ends up are two different things because of Osnaps.  So instead of using the point where the user selected which was the jig.BasePoint I used the hanger.Location point instead.  I also removed the pipe radius tolerance from the point.DistanceTo method as it was no longer needed.
Here is the working method with the changes
 
Code - C#: [Select]
  1.         /// <summary>
  2.         /// Repeatedly inserts hangers into model space until the user cancels the routine through the jig.
  3.         /// Once the hanger is inserted it will be anchored to the pipe and a threaded rod will be drawn to
  4.         /// the desired elevation
  5.         /// </summary>
  6.         /// <param name="manufacturer">The manufacturer of the hanger</param>
  7.         /// <param name="model">The model number of the hanger</param>
  8.         /// <param name="partSize">The size of the hanger</param>
  9.         internal static void AddHanger(string manufacturer, string model, string partSize)
  10.         {
  11.             Document document = Application.DocumentManager.MdiActiveDocument;
  12.             Database database = document.Database;
  13.             Editor editor = document.Editor;
  14.             const double tolerance = 0.25;
  15.            
  16.             while (true)
  17.             {
  18.                 try
  19.                 {
  20.                     Member hanger = GetHangerFromCatalog(manufacturer, model, partSize);
  21.                     if (hanger != null)
  22.                     {
  23.                         Member jigHanger = hanger;
  24.                         hanger = jigHanger as MultiViewPart;
  25.                         jigHanger.Normal = Vector3d.ZAxis.TransformBy(editor.CurrentUserCoordinateSystem);
  26.                         jigHanger.Direction = Vector3d.XAxis.TransformBy(editor.CurrentUserCoordinateSystem);
  27.                         jigHanger.Location = Point3d.Origin;
  28.                         jigHanger.SetDefaultLayer();
  29.                         var jig = new HangerJig(ref jigHanger);
  30.            
  31.                         // The user can cancel out of the routine by normal means during the jigging process
  32.                         if (jig.StartJig() != PromptStatus.OK)
  33.                         {
  34.                             break;
  35.                         }
  36.                         using (Transaction transaction = document.TransactionManager.StartOpenCloseTransaction())
  37.                         {
  38.                             var blockTable = transaction.GetObject(database.BlockTableId, OpenMode.ForWrite, false) as BlockTable;
  39.                             var blockTableRecord = transaction.GetObject(blockTable[BlockTableRecord.ModelSpace], OpenMode.ForWrite, false) as BlockTableRecord;
  40.                             blockTableRecord.AppendEntity((hanger));
  41.                             transaction.AddNewlyCreatedDBObject(hanger, true);
  42.                             // Determine if the hanger was located on a pipe.  If so then the hanger will be
  43.                             // anchored to the pipe using an entity hanger.  First get all objects in model space
  44.                             // and then if an object is a pipe check to see if the insertion point of the hanger
  45.                             // lies on the pipe curve.
  46.                             foreach (ObjectId objectId in blockTableRecord)
  47.                             {
  48.                                 var pipe = transaction.GetObject(objectId, OpenMode.ForRead) as Pipe;
  49.                                 if (pipe != null)
  50.                                 {
  51.                                     Point3d point = hanger.Location;
  52.                                     var lineSegment3D = new LineSegment3d(pipe.StartPoint, pipe.EndPoint);
  53.                                     var pointOnLine = lineSegment3D.GetClosestPointTo(point);
  54.                                     if (point.DistanceTo(pointOnLine.Point) <= tolerance)
  55.                                     {
  56.                                         // At this point the hanger should either be on the pipe or be
  57.                                         // within the tolerance.
  58.                                         pipe.UpgradeOpen();
  59.                                         transaction.GetObject(hanger.ObjectId, OpenMode.ForWrite);
  60.                                         var anchor = new AnchorEntityToEntity();
  61.                                         anchor.SetToStandard(database);
  62.                                         anchor.SubSetDatabaseDefaults(database);
  63.                                         anchor.SetReferencedEntity(pipe);
  64.                                         anchor.SetReferencedEntityOldEcs(pipe.Ecs);
  65.                                         hanger.SetAnchor(anchor);
  66.                                         hanger.UpdateGeoEcs(true);
  67.                                         break;
  68.                                     }
  69.                                     pipe.Dispose();
  70.                                 }
  71.                             }
  72.                             transaction.Commit();
  73.                         }
  74.                     }
  75.                 }
  76.                 catch (Exception e)
  77.                 {
  78.                     Console.WriteMessage("\n**Error** Unable to create/insert hanger.");
  79.                 }
  80.             }
  81.         return;
  82.     }
  83.  

Now to just complete the code that will insert the threaded rod up to the under slab elevation.
Keith Brown | AutoCAD MEP Blog | RSS Feed
AutoCAD MEP 2014 / Revit MEP 2014 / EastCoast CAD/CAM addon / Visual Studio 2013