Построение параллельного вида (трансформация)

Автор Тема: Построение параллельного вида (трансформация)  (Прочитано 1904 раз)

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

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

  • ADN OPEN
  • Сообщений: 3
  • Карма: 0
Всем привет.
Просьба помочь разобраться.
Проблема с пониманием алгоритма трансформации мировых координат в координаты вида.
Создаю Вид Узел, на основании выбранной балки. В случае горизонтального расположения узел создается горизонтально(как и задумывалось).
В случае негоризонтального расположения вид строится вертикально. Почему происходит этот разворот если базис для вида остается прежним?
Заранее благодарен.
Код - C# [Выбрать]
  1.         public Result Execute(
  2.           ExternalCommandData commandData,
  3.           ref string message,
  4.           ElementSet elements)
  5.         {
  6.             UIApplication uiapp = commandData.Application;
  7.             UIDocument uidoc = uiapp.ActiveUIDocument;
  8.             Document doc = uidoc.Document;
  9.             Selection sel = uidoc.Selection;
  10.             Element sel_elem = null;
  11.             ElementType sel_elem_type = null;
  12.             foreach (ElementId eId in sel.GetElementIds())
  13.             {
  14.                 sel_elem = doc.GetElement(eId);
  15.                 var type_id = sel_elem.GetTypeId();
  16.                 sel_elem_type = doc.GetElement(type_id) as ElementType;
  17.                 break;
  18.             }
  19.             FamilyInstance beam = sel_elem as FamilyInstance;
  20.  
  21.             if ((beam == null) || (beam.StructuralType != Autodesk.Revit.DB.Structure.StructuralType.Beam))
  22.             {
  23.                 message = "Please select exactly one beam element.";
  24.                 return Result.Failed;
  25.             }
  26.             LocationCurve lc = beam.Location as LocationCurve;
  27.             Line line = lc.Curve as Line;
  28.             if (null == line)
  29.             {
  30.                 message = "Unable to retrieve beam location line.";
  31.                 return Result.Failed;
  32.             }
  33.  
  34.             ViewFamilyType vft
  35.               = new FilteredElementCollector(doc)
  36.                 .OfClass(typeof(ViewFamilyType))
  37.                 .Cast<ViewFamilyType>()
  38.                 .FirstOrDefault<ViewFamilyType>(x =>
  39.                  ViewFamily.Detail == x.ViewFamily);
  40.  
  41.             XYZ firstPoint = line.GetEndPoint(0);
  42.             XYZ secondPoint = line.GetEndPoint(1);
  43.             XYZ line_direction = secondPoint - firstPoint;
  44.  
  45.             double minZ = firstPoint.Z;
  46.             double maxZ = secondPoint.Z;
  47.  
  48.             double width = line_direction.GetLength();
  49.             double offset = 0.1 * width;
  50.  
  51.             XYZ midpoint = (firstPoint + secondPoint) / 2;
  52.             XYZ minSecionBox; XYZ maxSectionBox;
  53.  
  54.             line_direction = line_direction.Normalize();
  55.             XYZ up_direction = XYZ.BasisZ;
  56.             XYZ view_direction = line_direction.CrossProduct(up_direction).Normalize();
  57.  
  58.             if (minZ != maxZ)
  59.             {
  60.                 up_direction = view_direction.CrossProduct(line_direction).Normalize();
  61.             }
  62.  
  63.             Transform t = Transform.Identity;
  64.             t.Origin = midpoint;
  65.             t.BasisX = line_direction;
  66.             t.BasisY = up_direction;
  67.             t.BasisZ = view_direction;
  68.                 minSecionBox = new XYZ(-width / 2 - offset, -offset, -offset);
  69.                 maxSectionBox = new XYZ(width / 2 + offset, offset, 0);
  70.  
  71.             BoundingBoxXYZ sectionBox = new BoundingBoxXYZ();
  72.             sectionBox.Transform = t;
  73.             sectionBox.Min = minSecionBox;
  74.             sectionBox.Max = maxSectionBox;
  75.  
  76.             ViewSection section = null;
  77.             using (Transaction tx = new Transaction(doc))
  78.             {
  79.                 tx.Start("Create Beam Section View");
  80.                 section = ViewSection.CreateDetail(doc, vft.Id, sectionBox);
  81.                 tx.Commit();
  82.             }
  83.             return Result.Succeeded;
  84.         }
  85.  
« Последнее редактирование: 07-06-2021, 23:57:25 от Александр Ривилис »

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

  • Administrator
  • *****
  • Сообщений: 1152
  • Карма: 338
  • Skype: alexandr.ignatovich.itc
Давай разберемся, что и чем являются оси координат в объекте Transform, когда мы используем его для создания разреза ViewSection

Начнём с BasisZ - это направление ViewDirection ("в глаз").

Я немного запутался с твоими горизонтальными / вертикальными расположениями. Если следовать логике твоего кода, тогда это будет векторное произведение line_direction и XYZ.BasisZ, тогда мы будем смотреть на балку с боку:
Код - C# [Выбрать]
  1. t.BasisZ = line_direction.CrossProduct(XYZ.BasisZ).Normalize();

Если хочешь смотреть сверху, как на плане, укажи:
Код - C# [Выбрать]
  1. t.BasisZ = XYZ.BasisZ;

BasisX
Направление "вправо" на будущем разрезе. Разрез не может быть наклонным, поэтому просто:
Код - C# [Выбрать]
  1. t.BasisX = new XYZ(line_direction.X, line_direction.Y, 0).Normalize();

BasisY.
Приводим Transform к conformal (забыл как по-русски, сорри) виду:
Код - C# [Выбрать]
  1. t.BasisY = t.BasisZ.CrossProduct(t.BasisX).Normalize();

Если твой код работает правильно, на разрезе смотрим на балку с боку, тогда можно пойти чуть-чуть другим путём, определяя сначала BasisY:
Код - C# [Выбрать]
  1. t.BasisZ = line_direction.CrossProduct(XYZ.BasisZ).Normalize();
  2. t.BasisY = XYZ.BasisZ;
  3. t.BasisX = t.BasisY.CrossProduct(t.BasisZ).Normalize();

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

  • ADN OPEN
  • Сообщений: 3
  • Карма: 0
Александр Игнатович,
Спасибо за ответ.
Идея создать вид сбоку, на котором балка расположена горизонтально независимо от ориентации в модели.
В моем случае t.BasisX - line_direction
t.BasisY - up_direction
t.BasisZ - view_direction
В случае негоризонтального расположения балки я не могу использовать t.BasisY = XYZ.BasisZ, т.к. балка не горизонтальна
поэтому изначально я задаю его, только для определения t.BasisZ - view_direction ну или для случая когда балка горизонтальная
Код - C# [Выбрать]
  1. XYZ up_direction = XYZ.BasisZ;
  2. XYZ view_direction = line_direction.CrossProduct(up_direction).Normalize();
Но впоследствии, если балка не горизонтальная, я переопределяю t.BasisY с помощью view_direction и line_direction
Код - C# [Выбрать]
  1. if (minZ != maxZ)
  2. {
  3.     up_direction = view_direction.CrossProduct(line_direction).Normalize();
  4. }
И вот в этом случае вид создается развернутым на 90 градусов, хотя по сути переопределяется только t.BasisY
« Последнее редактирование: 19-05-2021, 14:20:32 от DimaNY4 »

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

  • ADN OPEN
  • Сообщений: 3
  • Карма: 0
Сделал код более удобочитаемым
Код - C# [Выбрать]
  1.     [Transaction(TransactionMode.Manual)]
  2.     public class Command : IExternalCommand
  3.     {
  4.         public Result Execute(
  5.           ExternalCommandData commandData,
  6.           ref string message,
  7.           ElementSet elements)
  8.         {
  9.             UIApplication uiapp = commandData.Application;
  10.             UIDocument uidoc = uiapp.ActiveUIDocument;
  11.             Document doc = uidoc.Document;
  12.             Selection sel = uidoc.Selection;
  13.             Element sel_elem = null;
  14.             ElementType sel_elem_type = null;
  15.             foreach (ElementId eId in sel.GetElementIds())
  16.             {
  17.                 sel_elem = doc.GetElement(eId);
  18.                 var type_id = sel_elem.GetTypeId();
  19.                 sel_elem_type = doc.GetElement(type_id) as ElementType;
  20.                 break;
  21.             }
  22.             FamilyInstance beam = sel_elem as FamilyInstance;
  23.  
  24.             if ((beam == null) || (beam.StructuralType != Autodesk.Revit.DB.Structure.StructuralType.Beam))
  25.             {
  26.                 message = "Please select exactly one beam element.";
  27.                 return Result.Failed;
  28.             }
  29.             LocationCurve lc = beam.Location as LocationCurve;
  30.             Line line = lc.Curve as Line;
  31.             if (null == line)
  32.             {
  33.                 message = "Unable to retrieve beam location line.";
  34.                 return Result.Failed;
  35.             }
  36.  
  37.             ViewFamilyType vft
  38.               = new FilteredElementCollector(doc)
  39.                 .OfClass(typeof(ViewFamilyType))
  40.                 .Cast<ViewFamilyType>()
  41.                 .FirstOrDefault<ViewFamilyType>(x =>
  42.                  ViewFamily.Detail == x.ViewFamily);
  43.  
  44.             XYZ firstPoint = line.GetEndPoint(0);
  45.             XYZ secondPoint = line.GetEndPoint(1);
  46.             XYZ line_direction = secondPoint - firstPoint;
  47.             XYZ midpoint = (firstPoint + secondPoint) / 2;
  48.                        
  49.             double width = line_direction.GetLength();
  50.             double offset = 0.1 * width;
  51.             XYZ minSecionBox = new XYZ(-width / 2 - offset, -offset, -offset);
  52.             XYZ maxSectionBox = new XYZ(width / 2 + offset, offset, 0);
  53.  
  54.             Transform t = Transform.Identity;
  55.             t.Origin = midpoint;
  56.             t.BasisX = line_direction.Normalize();
  57.             t.BasisZ = line_direction.CrossProduct(XYZ.BasisZ).Normalize();
  58.             t.BasisY = t.BasisZ.CrossProduct(t.BasisX).Normalize();
  59.  
  60.             BoundingBoxXYZ sectionBox = new BoundingBoxXYZ();
  61.             sectionBox.Transform = t;
  62.             sectionBox.Min = minSecionBox;
  63.             sectionBox.Max = maxSectionBox;
  64.  
  65.             ViewSection section = null;
  66.             using (Transaction tx = new Transaction(doc))
  67.             {
  68.                 tx.Start("Create Beam Section View");
  69.                 section = ViewSection.CreateDetail(doc, vft.Id, sectionBox);
  70.                 tx.Commit();
  71.             }
  72.             return Result.Succeeded;
  73.         }
  74.     }
В приложении изображение с результатом создания узла при выборе горизонтальной балки и балки с уклоном.
Сами балки в виде отображены как задумывалось. Основной вопрос почему второй вид строится вертикально?