Задача программирования с Mathematica - PullRequest
1 голос
/ 14 сентября 2011

Я подключаю внешнюю программу к Mathematica.Я создаю входной файл для внешней программы.Речь идет о преобразовании геометрических данных из графики, сгенерированной Mathematica, в предопределенный формат.Вот пример Geometry.

Figure 1

Figure 1

Геометрия может быть описана многими способами в Mathematica.Один трудоемкий способ заключается в следующем.

dat={{1.,-1.,0.},{0.,-1.,0.5},{0.,-1.,-0.5},{1.,-0.3333,0.},{0.,-0.3333,0.5},
{0.,-0.3333,-0.5},{1.,0.3333,0.},{0.,0.3333,0.5},{0.,0.3333,-0.5},{1.,1.,0.},
{0.,1.,0.5},{0.,1.,-0.5},{10.,-1.,0.},{10.,-0.3333,0.},{10.,0.3333,0.},{10.,1.,0.}};

Show[ListPointPlot3D[dat,PlotStyle->{{Red,PointSize[Large]}}],Graphics3D[{Opacity[.8],
Cyan,GraphicsComplex[dat,Polygon[{{1,2,5,4},{1,3,6,4},{2,3,6,5},{4,5,8,7},{4,6,9,7},
{5,6,9,8},{7,8,11,10},{7,9,12,10},{8,9,12,11},{1,2,3},{10,12,11},{1,4,14,13},
{4,7,15,14},{7,10,16,15}}]]}],AspectRatio->GoldenRatio]

Это создает необходимую трехмерную геометрию в формате GraphicsComplex MMA.enter image description here

Эта геометрия описывается как следующий входной файл для моей внешней программы.

# GEOMETRY
# x y z [m]
NODES 16
1. -1. 0.
0. -1. 0.5
0. -1. -0.5
1. -0.3333 0.
0. -0.3333 0.50. -0.3333 -0.5
1. 0.3333 0.
0. 0.3333 0.5
0. 0.3333 -0.5
1. 1. 0.
0. 1. 0.5
0. 1. -0.5
10. -1. 0.
10. -0.3333 0.
10. 0.3333 0.
10. 1. -0.
# type node_id1 node_id2 node_id3 node_id4  elem_id1 elem_id2 elem_id3 elem_id4
PANELS 14
1 1 4 5 2 4 2 10 0
1 2 5 6 3 1 5 3 10
1 3 6 4 1 2 6 10 0
1 4 7 8 5 7 5 1 0
1 5 8 9 6 4 8 6 2
1 6 9 7 4 5 9 3 0
1 7 10 11 8 8 4 11 0
1 8 11 12 9 7 9 5 11
1 9 12 10 7 8 6 11 0
2 1 2 3 1 2 3
2 10 12 11 9 8 7
10 4 1 13 14 1 3
10 7 4 14 15 4 6
10 10 7 15 16 7 9
# end of input file

Теперь описание, которое я имею из документации этой внешней программыдовольно короткий.Я цитирую это здесь.


  1. Первое ключевое слово NODES указывает общее количество узлов.После этой строки не должно быть комментариев или пустых строк.Следующие строки состоят из трех значений x, y и z, координаты узла и количество строк должны совпадать с числом узлов.
  2. Следующее ключевое слово PANEL и указывает, сколько панелей у нас есть.После этого у нас есть строки, определяющие каждую панель.Первое целое число определяет тип панели
  3. ID 1 - четырехсторонняя панель - определяется четырьмя узлами и четырьмя соседними панелями.Соседние панели - это панели с одинаковыми сторонами (пара узлов), которые необходимы для расчета скорости и давления (методы 1 и 2).Недостающие соседи (например, для панелей около задней кромки) заполняются значением 0 (см. Рисунок 1 ).
  4. ID 2 - треугольная панель - определяется тремя узлами и тремя соседними панелями.
  5. ID 10 - wake panel - четырехугольная панель, определяемая четырьмя узлами и двумя (соседними)панели, которые расположены на задней кромке (панели, к которым панель пробуждения применяет условие Кутты).
  6. Типы панелей 1 и 2 должны быть определены до типа 10 во входном файле.Важно отметить, что поверхность нормальная;порядок узлов, определяющих панели, должен быть против часовой стрелки.По правилу правой руки, если пальцы согнуты, чтобы следовать нумерации, большой палец покажет нормальный вектор, который должен указывать «наружу» геометрию.

Задача !!

Мы находимсядано с трехмерной CAD-моделью в файле с именем One.obj , и оно отлично экспортируется в MMA.

cd = Import["One.obj"]

Выходные данные - объект MMA Graphics3D enter image description here

Теперь я могу легко получить доступ к данным геометрии, поскольку MMA читает их изнутри.

{ver1, pol1} = cd[[1]][[2]] /. GraphicsComplex -> List;
MyPol = pol1 // First // First;
Graphics3D[GraphicsComplex[ver1,MyPol],Axes-> True]

enter image description here

  1. Как мы можем использовать информацию о вершинах и многоугольникахв ver1 и pol1 и запишите их в текстовый файл, как описано в примере с файлом ввода выше.В этом случае у нас будут только (треугольные) панели типа ID2 .
  2. Используя триангуляцию Mathematica, как найти площадь поверхности этого трехмерного объекта.Есть ли встроенная функция, которая может вычислять площадь поверхности в MMA?
  3. Нет необходимости создавать панель пробуждения или элементы типа ID10 прямо сейчас.Подойдет входной файл только с треугольными элементами.

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

BR

1 Ответ

5 голосов
/ 15 сентября 2011

Q1 и Q2 достаточно просты, чтобы вы могли отбросить ярлыки «вызов» в своем вопросе.Q3 может использовать некоторые пояснения.

Q1

edges = cd[[1, 2, 1]];

polygons = cd[[1, 2, 2, 1, 1, 1]];

Обновление Q1

Основная проблема заключается внайти соседа каждого многоугольника.Это делается следующим образом:

(* Split every triangle in 3 edges, with nodes in each edge sorted *)
triangleEdges = (Sort /@ Subsets[#, {2}]) & /@ polygons;

(* Generate a list of edges *)
singleEdges = Union[Flatten[triangleEdges, 1]];

(* Define a function which, given an edge (node number list), returns the bordering  *)
(* triangle numbers. It's done by working through each of the triangles' edges       *)
ClearAll[edgesNeighbors]
edgesNeighbors[_] = {};
MapIndexed[(
   edgesNeighbors[#1[[1]]] = Flatten[{edgesNeighbors[#1[[1]]], #2[[1]]}];
   edgesNeighbors[#1[[2]]] = Flatten[{edgesNeighbors[#1[[2]]], #2[[1]]}];
   edgesNeighbors[#1[[3]]] = Flatten[{edgesNeighbors[#1[[3]]], #2[[1]]}];
   ) &, triangleEdges
];

(* Build a triangle relation table. Each '1' indicates a triangle relation *)
relations = ConstantArray[0, {triangleEdges // Length, triangleEdges // Length}];
Scan[
  (n = edgesNeighbors[##]; 
     If[Length[n] == 2, 
        {n1, n2} = n; 
        relations[[n1, n2]] = 1;  relations[[n2, n1]] = 1];
   ) &, singleEdges
]

MatrixPlot[relations]

triangle relationships

(* Build a neighborhood list *)
triangleNeigbours = 
    Table[Flatten[Position[relations[[i]], 1]], {i,triangleEdges // Length}];

(* Test: Which triangles border on triangle number 1? *)
triangleNeigbours[[1]]

(* ==> {32, 61, 83} *)

(* Check this *)
polygons[[{1, 32, 61, 83}]]

(* ==> {{1, 2, 3}, {3, 2, 52}, {1, 3, 50}, {19, 2, 1}} *)
(* Indeed, they all share an edge with #1 *)

Вы можете использовать функции вывода низкого уровня, описанные здесь , для их вывода.Я оставлю вам детали (это моя задача для вас).

Q2
Площадь крыла - это суммарная площадь отдельных многоугольников.Отдельные области можно рассчитать следующим образом:

ClearAll[polygonArea];
polygonArea[pts_List] :=
 Module[{dtpts = Append[pts, pts[[1]]]},
   If[Length[pts] < 3, 
      0, 
      1/2 Sum[Det[{dtpts[[i]], dtpts[[i + 1]]}], {i, 1, Length[dtpts] - 1}]
   ]
 ]

на основе этой страницы Mathworld .

Область подписана КСТАТИ, поэтому вы можете использовать Abs.

ИСПРАВЛЕНИЕ
Вышеуказанная функция площади может использоваться только для общих полигонов в 2D .Для области треугольника в 3D может использоваться следующее:

ClearAll[polygonArea];
polygonArea[pts_List?(Length[#] == 3 &)] := 
    Norm[Cross[pts[[2]] - pts[[1]], pts[[3]] - pts[[1]]]]/2
...