ADN Open CIS
Сообщество программистов Autodesk в СНГ

24/09/2014

Как средствами AutoCAD определить расположение точки относительно контура.

Вопрос:

Есть ли встроенные средства для определения как расположена точка относительно контура в AutoCAD .NET API?

Ответ:

Специальных средств для этого нет. Но есть по меньшей мере два способа, которыми можно воспользоваться для этого:

  1. С использованием BREP .NET API (Autodesk.AutoCAD.BoundaryRepresentation) – Если превратить контур в Region, то можно будет воспользоваться возможностью Brep для определения положения точки внутри Region. Для этого можно воспользоваться методом BrepEntity.GetPointContainment, который возвращает объект-перечисление PointContainment, которое может принимать одно из трёх значений: Inside (внутри), Outside (снаружи), OnBoundary (на самом контуре).
  2. C использованием класса примитива MPolygon. Обычно этот класс используется в Civil 3D, но так как он есть и в базовом AutoCAD, то мы можем им воспользоваться.

В данной статье мы рассмотрим второй способ. Будем считать, что в качестве контура у нас имеется замкнутая полилиния. В общем случае она может иметь и дуговые сегменты, но не должна быть самопересекающейся – иначе теряется смысл понятия «внутри контура». Ниже пример команды, которая просит пользователя указать точку и полилинию. Обратите внимание на следующие моменты:

  • В конструкторе класса происходит загрузка файла AcMPolygonObjXX.dbx, который необходим для нормальной работы сборки AcMPolygonMGD.dll (XX зависит от версии AutoCAD)
  • Необходимо добавит ссылку на AcMPolygonMGD.dll для возможности работы с классом MPolygon
  • Код не адаптирован для работы в ПСК отличной в МСК. Для адаптации указанную точку следует преобразовать из ПСК в МСК.

Код - C#: [Выделить]
  1. using System;
  2. using System.Reflection;
  3. using Autodesk.AutoCAD.Runtime;
  4. using Autodesk.AutoCAD.ApplicationServices;
  5. using Autodesk.AutoCAD.DatabaseServices;
  6. using Autodesk.AutoCAD.Geometry;
  7. using Autodesk.AutoCAD.EditorInput;
  8. using AcEd = Autodesk.AutoCAD.EditorInput;
  9. using AcRx = Autodesk.AutoCAD.Runtime;
  10. using AcAp = Autodesk.AutoCAD.ApplicationServices;
  11. using AcDb = Autodesk.AutoCAD.DatabaseServices;
  12. using AcGe = Autodesk.AutoCAD.Geometry;
  13.  
  14. //////////////////////////////////////////////////////////////////////////
  15. //  Необходимо подключить ссылку на AcMPolygonMGD.dll !!!
  16. //////////////////////////////////////////////////////////////////////////
  17.  
  18. [assembly: CommandClass(typeof(MakeContour.MyCommands))]
  19.  
  20. namespace MakeContour
  21. {
  22.  
  23.   public class MyCommands
  24.   {
  25.     static MyCommands()
  26.     {
  27.       AcRx.SystemObjects.DynamicLinker
  28.          .LoadModule("AcMPolygonObj" + AcAp.Application.Version.Major + ".dbx", false, false);
  29.     }
  30.     [CommandMethod("TestPointInContour")]
  31.     public void TestPointInContour()
  32.     {
  33.       AcAp.Document doc = AcAp.Application.DocumentManager.MdiActiveDocument;
  34.       AcDb.Database db = doc.Database;
  35.       AcEd.Editor ed = doc.Editor;
  36.       AcEd.PromptPointOptions pr =
  37.          new AcEd.PromptPointOptions("\nУкажите точку: ");
  38.       AcEd.PromptPointResult res = ed.GetPoint(pr);
  39.       if (res.Status != AcEd.PromptStatus.OK) return;
  40.       AcEd.PromptEntityOptions pre =
  41.          new AcEd.PromptEntityOptions("\nУкажите контур (замкнутую полилинию): ");
  42.       pre.SetRejectMessage("Это не контур (полилиния)");
  43.       pre.AddAllowedClass(typeof(AcDb.Polyline), true);
  44.       AcEd.PromptEntityResult rese = ed.GetEntity(pre);
  45.       if (rese.Status != AcEd.PromptStatus.OK) return;
  46.       using (AcDb.MPolygon mp = new AcDb.MPolygon()) {
  47.         using (AcDb.Polyline poly = rese.ObjectId.Open(AcDb.OpenMode.ForRead) as AcDb.Polyline) {
  48.           try {
  49.             mp.AppendLoopFromBoundary(poly, true, AcGe.Tolerance.Global.EqualPoint);
  50.             if (mp.IsPointOnLoopBoundary(res.Value, 0, AcGe.Tolerance.Global.EqualPoint)) {
  51.               ed.WriteMessage("\nТочка на границе контура!");
  52.             } else if (mp.IsPointInsideMPolygon(res.Value, AcGe.Tolerance.Global.EqualPoint).Count > 0) {
  53.               ed.WriteMessage("\nТочка внутри контура!");
  54.             } else {
  55.               ed.WriteMessage("\nТочка вне контура!");
  56.             }
  57.           } catch { }
  58.         }
  59.       }
  60.     }
  61.   }
  62. }

Автор: Александр Ривилис
Автор перевода: Александр Ривилис

Обсуждение: http://adn-cis.org/forum/index.php?topic=979

Опубликовано 24.09.2014