Разные FaceNormal у всех PlanarFace для DirectShape

Автор Тема: Разные FaceNormal у всех PlanarFace для DirectShape  (Прочитано 3081 раз)

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

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

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

  • ADN OPEN
  • Сообщений: 10
  • Карма: 0
Приветствую. Есть некоторый DirectShape(пример в аттаче). Я пытаюсь найти все внешние грани с помощью построения перпендикуляров из центра граней, с дальнейшей проверкой на пересечение с остальными гранями нашего DirectShape. Но проблема в том, что для каждого PlanarFace в нашем DirectShape мы имеем рзличные FaceNormal , и пересечения не наблюдается :'( Просьба подсказать, как можно выравнить все PlanarFace в одной плоскости. Заранее спасибо.


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

  • Administrator
  • *****
  • Сообщений: 1152
  • Карма: 338
  • Skype: alexandr.ignatovich.itc
Прочитал раз 5, но так и не понял, что ты хочешь. Если поверхности имеют разные нормали, то они не находятся в одной плоскости (или параллельных плоскостях), зачем их выравнивать? Что ты в данном случае подразумеваешь под "внешними" гранями? Геометрия твердотельная или mesh?


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

  • ADN OPEN
  • Сообщений: 10
  • Карма: 0
Просто странно, я строю этот DirectShape из выбранной на чертеже PlanarFace, но при этом поверхности имеют разные нормали Оо. Внешние грани - это внешние грани, описывающие полигон, а не те, что внутри него(смотри аттач.)


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

  • Administrator
  • *****
  • Сообщений: 1152
  • Карма: 338
  • Skype: alexandr.ignatovich.itc
Картинка не сильно помогает ::). Предположу, что могут быть ситуации, когда у соседних face-ов в разные стороны направлены, т.е., например, XYZ.BasisZ и -XYZ.BasisZ. Тогда может быть, что face.GetSurface().OrientationMatchesParametricOrientation  - false. При этом методом face.ComputeNormal всегда будет возвращаться корректное значение. Ну или проверить код создания самого shape-а

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

  • ADN OPEN
  • Сообщений: 10
  • Карма: 0
Вот пример кода создания DirectShape

Код - C# [Выбрать]
  1.     internal static ElementId NewDirectShape(
  2.           IList<Face> faces,
  3.           Transform transform,
  4.           Document doc,
  5.           string appGuid,
  6.           string shapeName)
  7.         {
  8.             int nFaces = 0;
  9.             int nFacesFailed = 0;
  10.  
  11.             ElementId materialId = GetMaterial(doc);
  12.  
  13.             TessellatedShapeBuilder builder = new TessellatedShapeBuilder { LogString = shapeName };
  14.  
  15.             builder.OpenConnectedFaceSet(true);
  16.             foreach (var face in faces)
  17.             {
  18.                 area += face.Area;
  19.  
  20.                 Mesh mesh = face.Triangulate(0.8);
  21.                 mesh = mesh.get_Transformed(transform);
  22.                 for (int i = 0; i < mesh.NumTriangles; i++)
  23.                 {
  24.                     List<XYZ> args = new List<XYZ>();
  25.  
  26.                     MeshTriangle triangle = mesh.get_Triangle(
  27.                       i);
  28.  
  29.                     XYZ p1 = triangle.get_Vertex(0);
  30.                     XYZ p2 = triangle.get_Vertex(1);
  31.                     XYZ p3 = triangle.get_Vertex(2);
  32.  
  33.                     args.Add(p1);
  34.                     args.Add(p2);
  35.                     args.Add(p3);
  36.  
  37.                     Coordinates.AddRange(args.Select(p => new Point3D { X = p.X, Y = p.Y, Z = p.Z }));
  38.  
  39.                     TessellatedFace tesseFace = new TessellatedFace(args,materialId);
  40.                    
  41.                     if (builder.DoesFaceHaveEnoughLoopsAndVertices(
  42.                       tesseFace))
  43.                     {
  44.                         builder.AddFace(tesseFace);
  45.                     }
  46.                 }
  47.             }
  48.  
  49.             builder.CloseConnectedFaceSet();
  50.            
  51.             builder.Target = TessellatedShapeBuilderTarget.AnyGeometry; // 2017
  52.             builder.Fallback = TessellatedShapeBuilderFallback.Mesh; // 2017
  53.            
  54.             builder.Build();
  55.             BuiltInCategory cat = GetBuiltInCategoryForShape();
  56.             DirectShape ds = DirectShape.CreateElement(doc, new ElementId(cat));
  57.  
  58.            
  59.             ds.ApplicationId = appGuid;
  60.             ds.ApplicationDataId = shapeName;    
  61.  
  62.             ds.SetShape(builder);
  63.         }

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

  • Administrator
  • *****
  • Сообщений: 1152
  • Карма: 338
  • Skype: alexandr.ignatovich.itc
Погонял, что-то не получается воспроизвести, Face-ы получаются с ожидаемыми направлениями нормалей, не важно, solid или mesh в результате. Может исходная поверхность вовсе не плоская?

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

  • ADN OPEN
  • Сообщений: 10
  • Карма: 0
Я разместил на чертеже трубу(горизонтально) и в качестве исходной поверхности взял фейс входа трубы(т.е. круг). Ума не приложу, почему получились разные нормали :'( :'(


Отмечено как Решение bronx 06-01-2022, 14:25:55

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

  • Administrator
  • *****
  • Сообщений: 1152
  • Карма: 338
  • Skype: alexandr.ignatovich.itc
Хах, всё теперь понятно. У тебя исходная геометрия очень далеко от начала координат, вероятно, за много километров, близко к design limits модели Revit или, возможно, даже вне их. Тут просто накапливается ошибка из-за ограничения количества значимых цифр в представлении double-а, поэтому вершины треугольников чуток "гуляют", это проблема исходной модели.

Ещё один совет, я, конечно, не в курсе решаемой тобой задачи, но, возможно, это решит часть следующих твоих задач, попробуй заменить TessellatedShapeBuilder на BRepBuilder (хоть с ним и сложнее построить shape), тогда у тебя вместо кучи треугольников будет одна поверхность.