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

ADN Club => AutoCAD .NET API => Тема начата: Николай Коломоец от 21-07-2013, 11:29:42

Название: Анализ пересечения объектов
Отправлено: Николай Коломоец от 21-07-2013, 11:29:42
Доброго всем времени суток.

Есть задача - проанализировать, находится ли точка на блоке (на каком-либо из его примитивов, за исключением текста или атрибута, штриховки).
Написал такой текст:

Код - C# [Выбрать]
  1. private int Compare(Point3d point, BlockReference br, double radius)
  2.         {
  3.             Database db = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Database;
  4.             Editor ed = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor;
  5.             bool intersect = false;
  6.             using (Transaction trans = db.TransactionManager.StartTransaction())
  7.             {
  8.                 BlockTableRecord btr = trans.GetObject(br.BlockTableRecord,OpenMode.ForRead) as BlockTableRecord;
  9.                 //BlockTableRecord modelBTR = trans.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
  10.                 Matrix3d brTransformedCoord = br.BlockTransform;
  11.  
  12.                 foreach (ObjectId objId in btr)
  13.                 {
  14.                     DBObject obj = trans.GetObject(objId, OpenMode.ForWrite);
  15.                     if ((obj is Entity) && (!(obj is DBText)) && (!(obj is MText)) && (!(obj is Hatch)) && (!(obj is Spline)))
  16.                     {
  17.                         Entity ent = (Entity)obj;
  18.                         Entity tempEnt = ent;
  19.                         tempEnt.TransformBy(brTransformedCoord);
  20.                         Point3dCollection pts = new Point3dCollection();
  21.                         //Plane pl = new Plane();
  22.                         Circle pointCircle = new Circle(point, new Vector3d(0, 0, 1), radius);
  23.                         //modelBTR.AppendEntity(pointCircle);
  24.                         //trans.AddNewlyCreatedDBObject(pointCircle, true);
  25.                         try
  26.                         {
  27.                             tempEnt.IntersectWith(pointCircle, Intersect.OnBothOperands, pts, IntPtr.Zero, IntPtr.Zero);
  28.                         }
  29.                         catch (Autodesk.AutoCAD.Runtime.Exception ex)
  30.                         {
  31.                         //    MessageBox.Show(ex.Message + ex.Source + "\n");
  32.                         }
  33.                         if (pts.Count > 0)
  34.                             intersect = true;
  35.                         //pointCircle.Erase();
  36.                     }
  37.                 }
  38.                 trans.Commit();
  39.             }
  40.             if (intersect == true)
  41.                 return 0;
  42.                         return -1;
  43.         }

Тут point - точка; br - вставка блока: функция должна вернуть 0, если точка находится на блоке; radius - "допуск", тут используется для прорисовки малого круга: считаю, что точка находится на блоке, если круг радиуса radius с центром в точке point пересекает какой-либо из примитивов блока.

В общем, данная функция никогда не возвращает 0 в реальной жизни. Как мне кажется, я неправильно понимаю работу метода IntersectWith.

Анализировать отдельно каждый тип примитива (линию, дугу и т.п.) тоже наверное неправильно. Как правильнее всего поступить в данной ситуации?
Название: Re: Анализ пересечения объектов
Отправлено: Алексей Кулик от 21-07-2013, 20:37:11
В порядке предположения: а система координат вхождения блока мировая? Угол поворота 0? Масштабы по разным осям тоже равны 1?
Название: Re: Анализ пересечения объектов
Отправлено: Николай Коломоец от 21-07-2013, 21:01:35
Система координат мировая. Масштабы все по 1, хотя тут хотелось бы узнать, что делать, если будет не так - программа все-таки должна работать при любых блоках. А вот насчет поворота - тут интереснее: блоки в большинстве своем динамические. Угол вставки самого блока почти всегда 0, но динамический параметр - угол поворота! Вообще, блоки могут быть любые, в т.ч. динамические, параметрические.
Выходит, что Entity.TransformBy(BlockReference.BlockTransform) не учитывает все эти параметры?

P.S. Пока, чтобы работало, сделал анализ пересечения с конкретным типом данных примитива из br.BlockTableRecord - Circle, Arc, Curve и Polyline. Работает "почти" нормально, но это явно неверный способ решения проблемы.
Название: Re: Анализ пересечения объектов
Отправлено: Алексей Кулик от 22-07-2013, 09:32:14
Могу попытаться помочь только с общим алгоритмом, но никак не с реализацией :(
Что бы сделал я:
Как-то так, наверное...
P.S. На caduser.ru, кажется, были варианты лисповых решений поиска пересечения примитивов и блоков, но я особо за ними не следил, поскольку не требовалось решать подобные задачи.
Название: Re: Анализ пересечения объектов
Отправлено: Александр Ривилис от 31-07-2013, 22:55:47
Для примитивов унаследованных от Curve я вообще не вижу смысла так усложнять код. Достаточно проверять расстояние от точки до примитива при помощи метода GetClosestPointTo. С остальными типами примитивов придётся разбираться отдельно. Для Region и Solid3d потребуется использовать BREP .NET API.
Название: Re: Анализ пересечения объектов
Отправлено: Николай Коломоец от 01-08-2013, 12:31:18
Это "исторически" сложилось так - я думал, что метод IntersectWith работает для всех типов Entity, и что одной командой можно решить все вопросы. Потом начал применять его по-разному к разным типам примитивов, но саму команду оставил.

Переделаю, спасибо за совет :)