【问题标题】:How to sort edges in a special surface mesh如何对特殊表面网格中的边进行排序
【发布时间】:2011-10-19 23:40:46
【问题描述】:

这是一个函数,它使用了我几天前提出的问题的答案中的建议。让我们在 Mathematica 中创建一个 Graphics3D 对象。我使用来自here 的这个 3D 几何数据。

cd = Import[NotebookDirectory[] <> "withwake.obj"];
vertices = cd[[1, 2, 1]];
polygons = Flatten[cd[[1, 2, 2, 1]] /. Polygon -> List, 2];
Graphics3D[GraphicsComplex[vertices, Polygon[polygons]]]

对于每个多边形,我们创建一个列表,其中包含指向其顶点的数字,然后是指向每个边所连接的多边形的数字。需要注意的是表面法线;定义面板的节点顺序应该是逆时针的。根据右手定则,如果手指弯曲以跟随编号,拇指将显示应该指向“向外”几何图形的法线向量。

如果Graphics3D 对象中的所有多边形都是三角形,则此函数会创建这样一个列表。

EdgeSorting[vertices_, polygons_] := 
Block[{triangleEdges, singleEdges, edgesNeighbors, relations, n, n1,
 n2, trires, triangleNeigbours, TriangleMaker, polygonArea, tring},
(*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*)
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];
Print[MatrixPlot[relations]];
(*Build a neighborhood list*)
triangleNeigbours = 
Table[Flatten[Position[relations[[i]], 1]], {i, 
  triangleEdges // Length}];
trires = 
Table[Flatten[{polygons[[i]], triangleNeigbours[[i]]}], {i, 1, 
  Length@polygons}];
TriangleMaker[{a_, b_, c_}] := {vertices[[a]], vertices[[b]], 
 vertices[[c]]};
{trires}
];

我不完全理解这个函数的工作方式。而且我无法理解如何实现以下目标。

  1. 对于每个三角形四边形,如前所述,如何形成列表
  2. 远离 3D 水翼的平面网格称为尾流面板。对于每个唤醒四边形面板/多边形,我们需要形成一个指向其顶点的数字列表,然后是指向两个多边形的数字列表,它共享其唯一连接边缘的边具有主要水翼几何形状的尾流四边形面板/多边形。

【问题讨论】:

  • 你的函数中有哪些不明白的地方?
  • 主要是edgesNeighbors部分。我尝试添加edgesNeighbors[#1[[4]]] = Flatten[{edgesNeighbors[#1[[4]]], #2[[1]]}];,但没有奏效。而且尾流似乎更难处理。
  • 如果您的代码适用于三角形并且您有四边形......为什么不按对角线分割它们?
  • 我需要四边形。我需要他们使用外部程序。不需要简单的三角形网格。这些四边形是绝对必要的。

标签: wolfram-mathematica mesh


【解决方案1】:

要创建所有多边形及其邻居的列表,您可以执行以下操作:

neighbours[polygons_] := {#, 
  Flatten@Position[polygons, 
    a_List /; Length[Intersection[a, #]] == 2]} & /@ polygons;

然后neighbours[polygons] 创建一个列表,其中i-th 条目由polygons[[i]]polygons[[i]] 的邻居的索引组成。

对于你问题的第二部分,你可以做类似的事情

wake[polygons_] := 
 Module[{edges, boundaries, wakelist, body}, 
  edges[polylist_] := Flatten[Map[Partition[#, 2, 1, 1] &, polylist], 1];
  boundaries = Cases[Tally[
     edges[polygons], (Sort[#1] == Sort[#2]) &], {a_, b_} /; b == 1 :> a];
  wakelist = 
   DeleteDuplicates[
    Map[Cases[polygons, a_ /; (Length[Intersection[a, #]] == 2)][[1]] &,
      boundaries]];
  {#, Flatten@Position[polygons, a_List /; (Length[Intersection[#, a]] == 2 && 
          Not[MemberQ[wakelist, a]])]} & /@ wakelist]

wake 中,如果多边形包含没有任何相邻多边形的边,则该多边形被视为唤醒面板。我不知道这是否始终有效,但它似乎适用于问题中的示例。

编辑 要将完整的多边形列表拆分为尾流和身体多边形,您可以执行以下操作

split[polygons_] := Module[{edges, boundaries, wakelist}, 
   edges[polylist_] := Flatten[Map[Partition[#, 2, 1, 1] &, polygons], 1];
   boundaries = Cases[Tally[edges[polygons], 
       (Sort[#1] == Sort[#2]) &], {a_, b_} /; b == 1 :> a];
   wakelist = DeleteDuplicates[Map[Cases[polygons, 
        a_ /; (Length[Intersection[a, #]] == 2)][[1]] &, boundaries]];
   {wakelist, Complement[polygons, wakelist]}];

然后split[polygons] 将生成一个包含两个子列表的列表。第一个子列表包含属于尾流的所有多边形,第二个子列表包含属于身体的所有多边形。由于split已经将唤醒与身体分开,我们可以根据

重写wake
wake2[wakelist_, bodylist_] := {#, Flatten@Position[bodylist,
      a_List /; (Length[Intersection[#, a]] == 2)]} & /@ wakelist

然后找到身体多边形列表及其邻居的索引,以及尾流多边形列表以及您可以做的相邻身体多边形的索引

{wakepols, bodypols} = split[polygons];
bodylist = neighbours[bodypols];
wakelist = wake[wakepols, bodypols];

请注意,bodylistwakelist 中的多边形索引现在指的是bodypols 中的多边形,而不是完整列表中的那些polygons

【讨论】:

  • 非常感谢您的帮助。你的解释非常清楚。干杯!!
  • @Heike 对偏离主题的消息感到抱歉,但您可能需要考虑将您的 Area 51 个人资料链接到您的 SO 个人资料。 (考虑到您的代表水平,这将有助于网站达到进入测试阶段的目标。)
  • @Verbeia 我没有想到这一点。你知道怎么做吗?
  • @Heike 答案在这里:meta.stackexchange.com/questions/18232/… 我不知道为什么它在你的情况下不起作用,因为你使用的是相同的电子邮件地址。可能是因为用户名不同。
  • @Heike neighbours[plygons] 也给出了包括尾迹在内的所有多边形关系。我们如何排除唤醒,因为我们可以通过wake[polygons] 单独获取唤醒?是否可以仅将三角形和四边形作为列表?我无法将唤醒与 neighbours[plygons] 分开。
猜你喜欢
  • 2020-10-12
  • 2012-12-08
  • 1970-01-01
  • 1970-01-01
  • 2023-03-28
  • 1970-01-01
  • 2021-05-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多