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

ADN Club => AutoCAD .NET API => Тема начата: merta от 10-03-2019, 21:10:51

Название: Как можно найти расстояние между 2 объектами?
Отправлено: merta от 10-03-2019, 21:10:51
Как можно найти расстояние между 2 объектами?

У меня есть 2 объекта рандомной формы, как между ними можно найти кратчайшее расстояние??
Название: Re: Как можно найти расстояние между 2 объектами?
Отправлено: Александр Ривилис от 10-03-2019, 22:01:38
Как можно найти расстояние между 2 объектами?

У меня есть 2 объекта рандомной формы, как между ними можно найти кратчайшее расстояние??
Приветствую на форуме!
Общего решения для этой задачи нет. Нужна конкретика по поводу того что это за объекты, 2D или 3D они и т.д.
Название: Re: Как можно найти расстояние между 2 объектами?
Отправлено: merta от 11-03-2019, 07:59:11
2d объекты, могут быть любой формы.

Я думал в начале сделать, создать круг. Увеличивать его диаметр и проверять на пересечение объектов. Но это довольно таки ресурсо затратно. И я не знаю как проверять на пересечение объекты
Название: Re: Как можно найти расстояние между 2 объектами?
Отправлено: Дмитрий Загорулькин от 11-03-2019, 10:56:47
2d объекты, могут быть любой формы.
Формы-то они могут быть любой. Но что это за объекты? Отрезки, полилинии, тексты, блоки...?
Я думал в начале сделать, создать круг. Увеличивать его диаметр и проверять на пересечение объектов.
Для начала, можно попробовать находить расстояния между габаритными контейнерами объектов - см. свойство GeometricExtents.
Название: Re: Как можно найти расстояние между 2 объектами?
Отправлено: merta от 11-03-2019, 11:43:10
Отрезки, полилинии, блоки.
Гляну свойство.
Название: Re: Как можно найти расстояние между 2 объектами?
Отправлено: Дмитрий Загорулькин от 11-03-2019, 11:48:52
Всё-таки, как выше уже написал Александр Ривилис, нужно больше конкретики. Потому что для разных случаев варианты могут быть совершенно разными.
Название: Re: Как можно найти расстояние между 2 объектами?
Отправлено: merta от 11-03-2019, 12:20:25
Есть полилиния нужно найти кратчайшее расстояние до точки.

Вот так например.
А нельзя получить у каждого объекта массив точек, где проходит этот объект??
Название: Re: Как можно найти расстояние между 2 объектами?
Отправлено: Дмитрий Загорулькин от 11-03-2019, 12:44:54
Есть полилиния нужно найти кратчайшее расстояние до точки.

Вот так например.
Полилиния, как и любой другой наследник от Curve имеет метод GetClosesPointTo (http://help.autodesk.com/view/OARX/2018/ENU/?guid=OREFNET-Autodesk_AutoCAD_DatabaseServices_Curve_GetClosestPointTo_Point3d__MarshalAsUnmanagedType_U1__bool)
А нельзя получить у каждого объекта массив точек, где проходит этот объект??
У линейного - можно. А у блока, например, что это за массив точек?
Название: Re: Как можно найти расстояние между 2 объектами?
Отправлено: merta от 11-03-2019, 12:50:00
При создании линии мы задаем 3 координаты, а можно получить список координат где находится линия
Название: Re: Как можно найти расстояние между 2 объектами?
Отправлено: Владимир Шу от 11-03-2019, 12:52:18
А у блока, например, что это за массив точек?
Точки объектов внутри блока, преобразованные в единую систему координат, и для каждого объекта внутри блока, можно же так же найти GetClosesPointTо, перенеся эту точку внутрь блока..
Название: Re: Как можно найти расстояние между 2 объектами?
Отправлено: Александр Ривилис от 11-03-2019, 12:54:20
При создании линии мы задаем 3 координаты, а можно получить список координат где находится линия
Это вопрос или утверждение? Если вопрос, то где знак вопроса? Если утверждение, то оно неверное.
3 координаты - это одна из вершин полилинии или начало-конец отрезка. Но этих точек очевидно недостаточно для определения минимального расстояния. Вероятно следует выполнить аппроксимацию с заданной точностью.
Название: Re: Как можно найти расстояние между 2 объектами?
Отправлено: Дмитрий Загорулькин от 11-03-2019, 12:55:28
При создании линии мы задаем 3 координаты
Как это? Высшая математика в ВУЗе была? :)
Название: Re: Как можно найти расстояние между 2 объектами?
Отправлено: Дмитрий Загорулькин от 11-03-2019, 12:57:52
и для каждого объекта внутри блока, можно же так же найти GetClosesPointTо
Если это наследник от Curve. В общем случае - необязательно ;)
Название: Re: Как можно найти расстояние между 2 объектами?
Отправлено: Александр Ривилис от 11-03-2019, 12:58:13
А нельзя получить у каждого объекта массив точек, где проходит этот объект??
Это называется аппроксимация. Для линий/полилиний/отрезков и т.д. наследников Curve это возможно. Преобразуешь его в Curve3d и используешь метод Curve3d.GetNewSamplePoints
Название: Re: Как можно найти расстояние между 2 объектами?
Отправлено: merta от 11-03-2019, 13:00:58
Спасибо
Название: Re: Как можно найти расстояние между 2 объектами?
Отправлено: merta от 12-03-2019, 23:10:25
Подскажите, как из Enemy сделать Curve3d и  BlockReference, то каждый раз когда пытаюсь применить у Polyline пишет ошибку

Код - C# [Выбрать]
  1.                         // получаем текущую БД
  2.                         Database db = HostApplicationServices.WorkingDatabase;
  3.  
  4.                         // начинаем транзакцию
  5.                         using (Transaction tr = db.TransactionManager.StartTransaction())
  6.                         {
  7.                                 // получаем ссылку на пространство модели (ModelSpace)
  8.                                 BlockTableRecord ms = (BlockTableRecord)tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead);
  9.  
  10.                                 string text = "";
  11.  
  12.                                 // "пробегаем" по всем объектам в пространстве модели
  13.                                 foreach (ObjectId id in ms)
  14.                                 {
  15.                                         // приводим каждый из них к типу Entity
  16.                                         Entity entity = (Entity)tr.GetObject(id, OpenMode.ForRead);
  17.                                         if ( entity.Layer.Equals("стены"))
  18.                                         {
  19.                                                 //BlockReference br = tr.GetObject(entity.ObjectId, OpenMode.ForRead) as BlockReference;
  20.                                                 //text += "br.Position.X=" + br.Position.X + " ;br.Position.Y=" + br.Position.Y + " 1\n\r";
  21.  
  22.                                                 acad.DocumentManager.MdiActiveDocument.Editor.WriteMessage(string.Format("\nLayer:{0}; Type:{1}; Color: {2},{3},{4},x={5}y={6}\n",//br.Position.X, br.Position.Y
  23.                                                         entity.Layer, entity.GetType().ToString(), entity.Color.Red.ToString(), entity.Color.Green.ToString(), entity.Color.Blue.ToString(), "dsf", "453"));
  24.                                         }
  25.                                 }
  26.                                 text += "\n\r";
  27.  
  28.                                 MessageBox.Show(text);
  29.                                 tr.Commit();
Название: Re: Как можно найти расстояние между 2 объектами?
Отправлено: Александр Ривилис от 12-03-2019, 23:17:08
merta
1. Enemy - это враг. Думаю, что речь идёт об Entity.
2. Entity нельзя преобразовать в Curve3d. Можно преобразовать Curve в Curve3d при помощи метода Curve.GetGeCurve
3. Форматируйте нормально код, как написано у меня в подписи.
Название: Re: Как можно найти расстояние между 2 объектами?
Отправлено: merta от 13-03-2019, 07:53:53
Извините за ошибки, быстро писал не заметил этого.
Спасибо. А еще подскажите. У меня есть BlockReference и polyline. Между ними нужно найти расстояние. Polyline я могу привести к curve3d, с BlockReference  что делать?
Создать на его позиции объект и его привести к polyline?
или есть еще метод
Название: Re: Как можно найти расстояние между 2 объектами?
Отправлено: Дмитрий Загорулькин от 13-03-2019, 11:36:43
У меня есть BlockReference и polyline. Между ними нужно найти расстояние.
Что подразумеваете под понятием "расстояние между блоком и полилинией"? Тут могут быть варианты - от точки вставки блока до линии, от крайнего ближайшего объекта блока до линии и пр.
Насколько точное должно быть расстояние?
Название: Re: Как можно найти расстояние между 2 объектами?
Отправлено: merta от 13-03-2019, 13:15:05
Расстояние между блоком и полилинией - от ближайшей точки блока к полилинии до этой точки на полилинии
Название: Re: Как можно найти расстояние между 2 объектами?
Отправлено: Александр Ривилис от 13-03-2019, 13:38:11
Расстояние между блоком и полилинией - от ближайшей точки блока к полилинии до этой точки на полилинии
Тебе придётся разобраться из чего состоит этот блок и найти расстояние от полилинии до каждого из элементов блока. Причем придется учесть масштабирование и поворот блока.
Название: Re: Как можно найти расстояние между 2 объектами?
Отправлено: Дмитрий Загорулькин от 13-03-2019, 14:07:24
Как вариант - просто взорвать его.
Название: Re: Как можно найти расстояние между 2 объектами?
Отправлено: merta от 13-03-2019, 23:04:25
Взорвать конечно интересное предложение. Но после того как сделаю!

Когда у новой линии пытаюсь получить Curve3d Автокад вылетает:
Приложение не поддерживает оперативную (JIT)
отладку. Подробная информацию приводится в конце данного сообщения.

************** Текст исключения **************
Autodesk.AutoCAD.Runtime.Exception: eInvalidInput
   в Autodesk.AutoCAD.DatabaseServices.Curve.GetGeCurve(Tolerance tolerance)
   в Autodesk.AutoCAD.DatabaseServices.Curve.GetGeCurve()
   в ClassLibraryExample2.Class1.AddPoint(Double x1, Double y1, Double x2, Double y2) в C:\Users\User\source\repos\ClassLibraryExample2\ClassLibraryExample2\Class1.cs:строка 137
   в ClassLibraryExample2.Class1.test123() в C:\Users\User\source\repos\ClassLibraryExample2\ClassLibraryExample2\Class1.cs:строка 73
   в Autodesk.AutoCAD.Runtime.CommandClass.InvokeWorker(MethodInfo mi, Object commandObject, Boolean bLispFunction)
   в Autodesk.AutoCAD.Runtime.CommandClass.InvokeWorkerWithExceptionFilter(MethodInfo mi, Object commandObject, Boolean bLispFunction)
   в Autodesk.AutoCAD.Runtime.CommandClass.CommandThunk.Invoke()

Код создания линии:
Ошибка в строке где "Тут"
Код - C# [Выбрать]
  1. private static void AddPoint(double x1, double y1, double x2, double y2)
  2.                 {
  3.                         // Get the current document and database
  4.                         Document acDoc = acad.DocumentManager.MdiActiveDocument;
  5.                         Database acCurDb = acDoc.Database;
  6.  
  7.                         // Start a transaction
  8.                         using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
  9.                         {
  10.                                 // Open the Block table for read
  11.                                 BlockTable acBlkTbl;
  12.                                 acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId,
  13.                                                                                                 OpenMode.ForRead) as BlockTable;
  14.  
  15.                                 // Open the Block table record Model space for write
  16.                                 BlockTableRecord acBlkTblRec;
  17.                                 acBlkTblRec = acTrans.GetObject(acBlkTbl[BlockTableRecord.ModelSpace],
  18.                                                                                                 OpenMode.ForWrite) as BlockTableRecord;
  19.                                 Line acLine;
  20.  
  21.                                 using (acLine = new Line(new Point3d(x1, y1, 0),
  22.                                                                                           new Point3d(x2, y2, 0)))
  23.                                 {
  24.  
  25.                                         acBlkTblRec.AppendEntity(acLine);
  26.                                         acLine.GetGeCurve();//Тут
  27.                                         acTrans.AddNewlyCreatedDBObject(acLine, true);
  28.                                 }
  29.                                 acTrans.Commit();
  30.                                
  31.                         }
  32.                 }
Название: Re: Как можно найти расстояние между 2 объектами?
Отправлено: Александр Ривилис от 14-03-2019, 00:01:33
merta,
Еще раз предупреждаю по поводу правила форматирования кода у нас на форуме - читай у меня в подписи!
Название: Re: Как можно найти расстояние между 2 объектами?
Отправлено: Александр Ривилис от 14-03-2019, 00:06:41
merta,
В коде у тебя полный бред, который даже непонятно как комментировать. Зачем ты создаёшь отрезок? Зачем пытаешься преобразовать его в Curve3d если для отрезка можно сразу создать LineSegment3d?

Название: Re: Как можно найти расстояние между 2 объектами?
Отправлено: merta от 14-03-2019, 07:21:18
Александр Ривилис, Извините за тэги. Тэг просто называется "Код", вот я и ошибся.

Я вызываю у полилинии GetClosesPointTо и передавал туда линию (выходила ошибка чуть ниже), а теперь попытался передать GetClosesPointTо, все равно вылетает ошибка(.

Как можно передать в метод GetClosesPointTо передать только созданную GetClosesPointTо?
Название: Re: Как можно найти расстояние между 2 объектами?
Отправлено: Александр Ривилис от 14-03-2019, 09:17:58
Прочитай вопрос, который ты задал. Поставь себя на место читателя. Что из этого вопроса можно понять?
Название: Re: Как можно найти расстояние между 2 объектами?
Отправлено: merta от 14-03-2019, 10:31:34
Чет устал.
Как можно в объекте polyline в метод getgeclosespointto, передать только что созданный lineSegment3d?
Название: Re: Как можно найти расстояние между 2 объектами?
Отправлено: Александр Ривилис от 14-03-2019, 11:21:04
getgeclosespointto
Нет такого метода. Внимательнее!  Есть метод GetClosestPointTo.
Как можно в объекте polyline в метод getgeclosespointto, передать только что созданный lineSegment3d?
Никак. Polyline - это класс унаследованный от Curve (т.е. Autodesk.AutoCAD.DatabaseServices.Curve). Его метод GetClosestPointTo  принимает только точку (Point3d) - смотри документацию.
Метод Curve3d.GetClosestPointTo  позволяет передать другую кривую (Curve3d) в качестве параметра.
Название: Re: Как можно найти расстояние между 2 объектами?
Отправлено: Александр Ривилис от 14-03-2019, 16:57:43
Красные линии показывают кратчайшее расстояние между кривыми (попарно):
(https://farm8.staticflickr.com/7889/40412041793_9751d0608f_o.png)

Код - C# [Выбрать]
  1. using System;
  2. using Autodesk.AutoCAD.Runtime;
  3. using Autodesk.AutoCAD.ApplicationServices;
  4. using Autodesk.AutoCAD.DatabaseServices;
  5. using Autodesk.AutoCAD.Geometry;
  6. using Autodesk.AutoCAD.EditorInput;
  7.  
  8. #pragma warning disable 0618
  9.  
  10. // This line is not mandatory, but improves loading performances
  11. [assembly: CommandClass(typeof(Rivilis.GetNearest))]
  12.  
  13. namespace Rivilis
  14. {
  15.   public class GetNearest
  16.   {
  17.  
  18.     [CommandMethod("GetNearest")]
  19.     public void GetNearestHandler() // This method can have any name
  20.     {
  21.       Document doc = Application.DocumentManager.MdiActiveDocument;
  22.       if (doc == null) return;
  23.       Editor ed = doc.Editor;
  24.       PromptEntityOptions prOpt = new PromptEntityOptions("");
  25.       prOpt.Message = "\nВыберите первую кривую: ";
  26.       prOpt.SetRejectMessage("\nЭто не кривая!");
  27.       prOpt.AddAllowedClass(typeof(Curve), false);
  28.       PromptEntityResult prRes1 = ed.GetEntity(prOpt);
  29.       if (prRes1.Status != PromptStatus.OK)
  30.         return;
  31.       prOpt.Message = "\nВыберите вторую кривую: ";
  32.       PromptEntityResult prRes2 = ed.GetEntity(prOpt);
  33.       if (prRes2.Status != PromptStatus.OK)
  34.         return;
  35.       using (Curve curve1 = prRes1.ObjectId.Open(OpenMode.ForRead) as Curve)
  36.       using (Curve curve2 = prRes2.ObjectId.Open(OpenMode.ForRead) as Curve)
  37.       {
  38.         using (Curve3d c3d1 = curve1.GetGeCurve())
  39.         using (Curve3d c3d2 = curve2.GetGeCurve())
  40.         {
  41.           PointOnCurve3d[] ptsOnc3d = c3d1.GetClosestPointTo(c3d2);
  42.           if (ptsOnc3d != null && ptsOnc3d.Length == 2)
  43.           {
  44.             using (BlockTableRecord btrSpace =
  45.               doc.Database.CurrentSpaceId.Open(OpenMode.ForWrite) as BlockTableRecord)
  46.             {
  47.               using (Line line = new Line(ptsOnc3d[0].Point, ptsOnc3d[1].Point))
  48.               {
  49.                 line.SetDatabaseDefaults();
  50.                 line.ColorIndex = 1; // Отметим красным цветом
  51.                 btrSpace.AppendEntity(line);
  52.               }
  53.             }
  54.           }
  55.         }
  56.       }
  57.     }
  58.   }
  59. }
Название: Re: Как можно найти расстояние между 2 объектами?
Отправлено: merta от 14-03-2019, 20:04:17
Спасибо
Название: Re: Как можно найти расстояние между 2 объектами?
Отправлено: merta от 17-03-2019, 21:24:56
При нахождение короткого пути между 2 списками polyline  пишет ошибку: "System.NullReferenceException".
Как это исправляется

При первом прохождении 1 цикла все нормально работает. После второго прохождения первого цикла пишет ошибку выше.
Код - C# [Выбрать]
  1. foreach (Entity curvPoint in listPoint)//1-цикл
  2.                                 {
  3.                                         using (Curve curve1 = curvPoint.ObjectId.GetObject(OpenMode.ForRead) as Curve)
  4.                                         using (Curve3d c3d1 = curve1.GetGeCurve())
  5.                                         {
  6.                                                 foreach (Entity block in listPolyline)//2-цикл
  7.                                                 {
  8.                                                         try
  9.                                                         {
  10.                                                                 using (Curve curve2 = block as Curve)
  11.                                                                 using (Curve3d c3d2 = curve2.GetGeCurve())
  12.                                                                 {
  13.                                                                         PointOnCurve3d[] ptsOnc3d = c3d1.GetClosestPointTo(c3d2);
  14.                                                                                 AddLineBetweenDist(ptsOnc3d[0].Point, ptsOnc3d[1].Point);
  15.                                                                         acad.DocumentManager.MdiActiveDocument.Editor.WriteMessage("\n\r curve2 " + ptsOnc3d.Length + " x1=" + ptsOnc3d[0].Point.X + " y1=" +
  16.                                                                                 ptsOnc3d[0].Point.Y + " x2=" + ptsOnc3d[0].Point.X + " y2=" + ptsOnc3d[0].Point.Y);
  17.                                                                 }
  18.                                                         }
  19.                                                         catch { }
  20.                                                 }
  21.                                         }
  22.                                 }
Название: Re: Как можно найти расстояние между 2 объектами?
Отправлено: Александр Ривилис от 17-03-2019, 21:28:33
При первом прохождении 1 цикла все нормально работает. После второго прохождения первого цикла пишет ошибку выше.
Запусти под отладчиком и найди место, где возникает исключение.
P.S.: В настройках VS измени величину табуляции (сравни мой код и свой) - читать такой сдвинутый на половину экрана код невозможно.
Название: Re: Как можно найти расстояние между 2 объектами?
Отправлено: merta от 17-03-2019, 21:54:50
Ошибка возникает в Curve3d c3d2 = curve2.GetGeCurve(). Но при прохождении цикла в первый раз все нормально работает
Название: Re: Как можно найти расстояние между 2 объектами?
Отправлено: Александр Ривилис от 17-03-2019, 21:57:35
Ошибка возникает в Curve3d c3d2 = curve2.GetGeCurve(). Но при прохождении цикла в первый раз все нормально работает
Я так понимаю, что в этом случае curve2 == null, т.е. block as Curve возвращает null и соответственно block не наследник Curve. Проверяй что туда попадает.
Название: Re: Как можно найти расстояние между 2 объектами?
Отправлено: Владимир Шу от 17-03-2019, 22:00:43
Off-Topic: показать
В настройках VS измени величину табуляции (сравни мой код и свой) - читать такой сдвинутый на половину экрана код невозможно.
Дополню. В стандартных настройках VS, автоматическое выравнивание кода - Ctrl+K+D

Название: Re: Как можно найти расстояние между 2 объектами?
Отправлено: Александр Ривилис от 17-03-2019, 22:01:56
merta,
Стоп!!! А зачем вообще using в
Код - C# [Выбрать]
  1. using (Curve curve2 = block as Curve)
???
Ты понимаешь что происходит в этом случае или это просто копипастинг чужого кода?
Тогда объясню, что после завешения блока using curve2 будет закрыт (выполнен метод Close) и соответственно повторно к нему до его открытия обратиться нельзя. Так что этот using просто выкини из кода. Он в нём не нужен.
Название: Re: Как можно найти расстояние между 2 объектами?
Отправлено: merta от 17-03-2019, 22:25:46
Александр Ривилис, Спасибо. Ещё раз прочитал, делает using все стало на свои места. Спасибо.