Выбрать ближайшую к точке стену

Автор Тема: Выбрать ближайшую к точке стену  (Прочитано 3862 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн shssАвтор темы

  • ADN Club
  • ***
  • Сообщений: 214
  • Карма: 5
  • Sergey
  • Skype: sergey.s.shevtsov
Добрый день!
Есть задача, стены строятся из файла точек с помощью процедуры
Код - C# [Выбрать]
  1. private void CreateWalls() {
  2.            for (int i = 0; i < points.Count; i++) {
  3.                 if (i % 2 == 1) {
  4.                     using (Transaction tr = new Transaction(_doc, "Create wall")) {
  5.                         tr.Start();
  6.                         string[] start = points[i - 1].Split(' ');
  7.                         string[] end = points[i].Split(' ');
  8.                         Line geomLine = Line.CreateBound(new XYZ(double.Parse(start[0].Split('=')[1]),
  9.                                                                  double.Parse(start[1].Split('=')[1]),
  10.                                                                  0) / Consts.scale,
  11.                                                          new XYZ(double.Parse(end[0].Split('=')[1]),
  12.                                                                  double.Parse(end[1].Split('=')[1]),
  13.                                                                  0) / Consts.scale);
  14.                         walls.Add(Wall.Create(_doc, geomLine, _level.Id, true));
  15.                         richTextBox1.Text += "Wall created...\n";
  16.                         tr.Commit();
  17.                     }
  18.                 }
  19.             }
  20.             UIDocument uidoc = new UIDocument(_doc);
  21.             UIView uiview = uidoc.GetOpenUIViews().Cast<UIView>().First(q => q.ViewId == _doc.ActiveView.Id);
  22.             uidoc.RefreshActiveView();
  23.             uiview.ZoomToFit();
  24.           }
  25.  

Все замечательно с помощью RevitLookup просматриваю элементы, все стены создаются.
Затем из другого файла беру точку (я знаю что это точка находится на линии, по которой создавалась стена) и пытаюсь с помощью мат фунции по принадлежности точки отрезку заданным двумя точками (уравнение прямой) определить лежит ли точка на прямой стены.
Код - C# [Выбрать]
  1.                     string[] insertion = points[0].Split(' ');
  2.                     XYZ insert = new XYZ(double.Parse(insertion[0].Split('=')[1]),
  3.                                          double.Parse(insertion[1].Split('=')[1]),
  4.                                          double.Parse(insertion[2].Split('=')[1]));
  5.   foreach (Wall wall in walls) {
  6.                     XYZ start = (wall.Location as LocationCurve).Curve.GetEndPoint(0);
  7.                     XYZ end = (wall.Location as LocationCurve).Curve.GetEndPoint(1);
  8.                     start = start * Consts.scale;
  9.                     end = end * Consts.scale;
  10.                     WallType wt = wall.WallType;
  11.  
  12.                    double y3 = a * insert.X + b;
  13.                    double b1 = insert.X - start.X;
  14.                    double b2 = end.Y - start.Y;
  15.                    double b3 = end.X - start.X;
  16.                    double b4 = insert.Y - start.Y;
  17.  
  18.                    double r = b1 * b2 - b3 * b4;
  19.  

Но равенство не выполняется, недоумеваю почему, есть подозрение что изза системы координат, но не могу быть уверенным. Но опять же используя RevitLookup я вижу верные координаты по которым изначально создавалась стена.
Простая проверка: беру начальну точку стены и строю новую стену со второй координатой в роли этой точки - стены накладываются друг на друга.

Вторая идея была построить сферу с необходимым радиусом и искать пересечение со стеной:
Код - C# [Выбрать]
  1. static public Solid CreateSphereAt(CreationApp creapp,  XYZ centre, double radius )
  2.   {
  3.      Frame frame = new Frame( centre,
  4.       XYZ.BasisX, XYZ.BasisY, XYZ.BasisZ );
  5.  
  6.     Arc arc = creapp.NewArc(
  7.       centre - radius * XYZ.BasisZ,
  8.       centre + radius * XYZ.BasisZ,
  9.       centre + radius * XYZ.BasisX );
  10.  
  11.     Line line = creapp.NewLineBound(
  12.       arc.get_EndPoint( 1 ),
  13.       arc.get_EndPoint( 0 ) );
  14.  
  15.     CurveLoop halfCircle = new CurveLoop();
  16.     halfCircle.Append( arc );
  17.     halfCircle.Append( line );
  18.  
  19.     List<CurveLoop> loops = new List<CurveLoop>( 1 );
  20.     loops.Add( halfCircle );
  21.  
  22.     return GeometryCreationUtilities
  23.       .CreateRevolvedGeometry(
  24.         frame, loops, 0, 2 * Math.PI );
  25.   }
  26.  

Но в Revit 2015 нет функции NewArc.
Есть еще какие-нибудь варианты или решения для данной задачи?

Спасибо

Отмечено как Решение shss 31-07-2015, 09:53:07

Оффлайн Александр Игнатович

  • Administrator
  • *****
  • Сообщений: 1152
  • Карма: 338
  • Skype: alexandr.ignatovich.itc
Re: Выбрать ближайшую к точке стену
« Ответ #1 : 31-07-2015, 09:18:53 »
А почему бы не попроще:
Код - C# [Выбрать]
  1. (wall.Location as LocationCurve).Curve.Project(pnt).Distance

Т.к. значение типа double, то сравнивать надо Math.Abs(value) < epsilon, где в epsilon - нужная погрешность, имхо 1E-5 хватит за глаза.

А дуги в R2015 создаются Arc.Create
« Последнее редактирование: 31-07-2015, 09:55:15 от Александр Игнатович »

Оффлайн shssАвтор темы

  • ADN Club
  • ***
  • Сообщений: 214
  • Карма: 5
  • Sergey
  • Skype: sergey.s.shevtsov
Re: Выбрать ближайшую к точке стену
« Ответ #2 : 31-07-2015, 09:53:04 »
(wall.Location as LocationCurve).Curve.Project(pnt).Distance
Воспользуюсь, пожалуй вот этим! Спасибо.
А дуги в R2015 создаются Arc.Create
Спасибо, нашел после сообщения и реализовал вариант с Solid, но вариант выше, намного быстрее.

Оффлайн Александр Игнатович

  • Administrator
  • *****
  • Сообщений: 1152
  • Карма: 338
  • Skype: alexandr.ignatovich.itc
Re: Выбрать ближайшую к точке стену
« Ответ #3 : 31-07-2015, 09:57:24 »
Еще маленький момент, в общем случае нужно сначала получить проекцию
Код - C# [Выбрать]
  1. var intersectionResult = (wall.Location as LocationCurve).Curve.Project(pnt)

проверить её на null, и только потом уже проверять intersectionResult.Distance