Получение нормали к поверхности стены

Автор Тема: Получение нормали к поверхности стены  (Прочитано 6266 раз)

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

Тема содержит сообщение с Решением. Нажмите здесь чтобы посмотреть его.

Оффлайн Илья ДрягинАвтор темы

  • ADN OPEN
  • Сообщений: 25
  • Карма: 2
  • Стройтэкпроект
Здравствуйте!
Есть задачка над которой думаю уже несколько дней.
Имеется помещение (Room), окруженное стенами. Задача построить новые стены, которые будут параллельны имеющимся стенам по всей границе помещения и смещены на заданную дистанцию внутрь этого помещения.

Для создания стен необходимо задать кривые (Curve), остальные параметры (уровень, высота и т.д.) заданы.

Получить кривые сегментов границы помещения не сложно через:
Код - C# [Выбрать]
  1. SpatialElementBoundaryOptions opt = new SpatialElementBoundaryOptions();
  2. IList<IList<BoundarySegment>> segs = selectedroom.GetBoundarySegments(opt);

Код - C# [Выбрать]
  1. Curve newcurve = seg.GetCurve();

А вот дальше эту кривую надо сместить внутрь помещения wallLine.Move(translationVector). И тут возникла проблема с определением вектора (а точнее направления) для смещения.
По моим размышлениям надо получить вектор нормали поверхности геометрии помещения, относящейся к данному сегменту границы, либо нормаль поверхности стены, которой образован данный сегмент  границы. и каждый способ ведет к перебору пересечений всех поверхностей стены и поверхностей геометрии помещения и сравнивания их и то я еще не понял как это реализовать. Но может есть более простой способ?

« Последнее редактирование: 17-03-2017, 15:50:38 от Александр Ривилис »

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13886
  • Карма: 1788
  • Рыцарь ObjectARX
  • Skype: rivilis
Пока напомню про правила форматирования кода на форуме, которые у нас приняты и указаны у меня в подписи.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн shss

  • ADN Club
  • ***
  • Сообщений: 214
  • Карма: 5
  • Sergey
  • Skype: sergey.s.shevtsov
Это перемещение стены:

Код - C# [Выбрать]
  1. double moveDistance = 100;
  2. Line geomLine = Line.CreateBound(wallStartPoint, wallEndPoint); //создание прямой из полученных точек стены или кривой
  3. XYZ lineDirection = geomLine.Direction; //направление прямой
  4. XYZ normal = XYZ.BasisZ.CrossProduct(lineDirection).Normalize(); // нормаль к прямой
  5. XYZ transform = normal.Multiply(moveDistance); //минус определяет направление сдвига
  6. LocationCurve wallLine = wall.Location as LocationCurve;
  7. wallLine.Move(transform);
  8.  

Переделать под создание стены, достаточно просто.

Оффлайн Илья ДрягинАвтор темы

  • ADN OPEN
  • Сообщений: 25
  • Карма: 2
  • Стройтэкпроект
Спасибо, но вопрос направления нормали полученной Вашим способом остается для меня открытым. Заранее не известно ориентация стены, создающей границу помещения и помещения могут быть с обоих сторон одной стены. В этом случае созданная стена в одном помещении сдвинется в нужную сторону, а вот в соседнем в обратную (наружу от границы помещения).

Отмечено как Решение Илья Дрягин 21-03-2017, 15:10:28

Оффлайн shss

  • ADN Club
  • ***
  • Сообщений: 214
  • Карма: 5
  • Sergey
  • Skype: sergey.s.shevtsov
Тогда работайте с полученными сегментами.
Я вместо стен создал линии внутри комнаты:
Код - C# [Выбрать]
  1. foreach (ElementId id in selectedIds) {
  2.     Room room = doc.GetElement(id) as Room;
  3.     IList<IList<Autodesk.Revit.DB.BoundarySegment>> loops = room.GetBoundarySegments(new SpatialElementBoundaryOptions());
  4.     foreach (IList<Autodesk.Revit.DB.BoundarySegment> loop in loops) {
  5.         n = loop.Count;
  6.         int j = 0;
  7.         foreach (Autodesk.Revit.DB.BoundarySegment seg in loop) {
  8.             Element e = doc.GetElement(seg.ElementId) as Element;
  9.             string s = "Element property";
  10.             XYZ p = seg.GetCurve().GetEndPoint(0);
  11.             XYZ q = seg.GetCurve().GetEndPoint(1);
  12.             ModelLineCreation(uiapp, p, q, j);
  13.         }
  14.     }
  15. }
  16.  


Код - C# [Выбрать]
  1.  public ModelCurve ModelLineCreation(UIApplication app, XYZ startPoint, XYZ endPoint, int counter, string style = "") {
  2.             ModelCurve mc = null;
  3.  
  4.             Autodesk.Revit.DB.Document doc = app.ActiveUIDocument.Document;
  5.             View view = doc.ActiveView;
  6.  
  7.             using (Transaction tr = new Transaction(doc, "ModelLine creation")) {
  8.                 tr.Start();
  9.                 CurveArray ca = new CurveArray();
  10.                 XYZ origin = new XYZ(-1000, -1000, 0);
  11.                 Line mLine = Line.CreateBound(startPoint, endPoint);
  12.                 ca.Append(mLine);
  13.                 ca.Append(Line.CreateBound(mLine.GetEndPoint(1), origin));
  14.                 ca.Append(Line.CreateBound(origin, mLine.GetEndPoint(0)));
  15.                 Plane verticalGeometryPlane = app.Application.Create.NewPlane(ca);
  16.                 SketchPlane verticalSkplane = SketchPlane.Create(doc, verticalGeometryPlane);
  17.                 mc = doc.Create.NewModelCurve(mLine, verticalSkplane);
  18.  
  19.                 XYZ lineDirection = (Line.CreateBound(startPoint, endPoint)).Direction; ////// код из первого ответа
  20.                 XYZ normal = XYZ.BasisZ.CrossProduct(lineDirection).Normalize();
  21.                 XYZ transform = normal.Multiply(0.5);
  22.                 LocationCurve mcLine = mc.Location as LocationCurve;
  23.                 mcLine.Move(transform);
  24.  
  25.                 XYZ baseVec1 = XYZ.BasisX;
  26.                 XYZ upVec1 = XYZ.BasisZ;
  27.                 double lineWidth = 1.0/12.0;
  28.                 TextNoteOptions to = new TextNoteOptions();
  29.                 to.HorizontalAlignment = HorizontalTextAlignment.Center;
  30.                 to.TypeId = doc.GetDefaultElementTypeId(ElementTypeGroup.TextNoteType);
  31.                
  32.                 if (style != "") {
  33.                     GraphicsStyle debugStyle = GetLineStyleByName(doc, mc, style);
  34.                     mc.LineStyle = debugStyle;
  35.                 }
  36.  
  37.                 tr.Commit();
  38.             }
  39.             return mc;
  40.         }
  41.  
  42.         public GraphicsStyle GetLineStyleByName(Autodesk.Revit.DB.Document doc, CurveElement element, string styleName) {
  43.             foreach (Element style in GetLineStyles(doc, element)) {
  44.                 GraphicsStyle anyStyle = style as GraphicsStyle;
  45.                 if (anyStyle.Name == styleName) {
  46.                     if (anyStyle.GraphicsStyleType == GraphicsStyleType.Projection) {
  47.                         return anyStyle;
  48.                     }
  49.                 }
  50.             }
  51.  
  52.             return null;
  53.         }
  54.         public List<GraphicsStyle> GetLineStyles(Autodesk.Revit.DB.Document doc, CurveElement element) {
  55.             List<GraphicsStyle> styles = new List<GraphicsStyle>();
  56.             ICollection<ElementId> lineIDs = element.GetLineStyleIds();
  57.             foreach (ElementId lineID in lineIDs) {
  58.                 Element elem = doc.GetElement(lineID);
  59.                 if (elem != null) {
  60.                     GraphicsStyle style = elem as GraphicsStyle;
  61.                     if (style != null)
  62.                         styles.Add(style);
  63.                 }
  64.             }
  65.             return styles;
  66.         }
  67.  

В этом случае выбирая любую комнату, все линии будут внутри.

Со стенами та же история. Только их еще надо будет подрезать правильно, но вообщем это не проблема, потому что будет пересечение.


Оффлайн Илья ДрягинАвтор темы

  • ADN OPEN
  • Сообщений: 25
  • Карма: 2
  • Стройтэкпроект
Огромное спасибо, буду тестить

Оффлайн shss

  • ADN Club
  • ***
  • Сообщений: 214
  • Карма: 5
  • Sergey
  • Skype: sergey.s.shevtsov
Не за что, но будьте аккуратны в любом случае, так как сегменты, это очень специфичная область.
Одна стена может состоять из двух и более сегментов (например врезка стены с другой стороны комнаты образует два сегмента стены).
Ну и как на картинке выше, сегменты могут не пересекаться, соответственно нужно будет продлевать их, для получения точки пересечения, и построения стены.