頂点法線を介して1つのシャードでポットの軸を再構築する

Aug 16 2020

ポットの破片からポット全体を再構築する予定です。

私はすでにそれを行う方法を考えましたが、コードでそれを実現する方法を本当に知りません。

理論:すべての破片には特定の曲がりがあります。このベンドには、次の2つの情報が含まれています。

  • ポット内の破片の向き
  • ポットの直径。編集モードで頂点法線をオンにすると、これを簡単に確認できます。技術的には、陶器を作る過程から、すべての鍋の真ん中に中心軸があります。頂点法線はこの軸と交差するため、頂点法線をオンにすると軸がはっきりと見えます。

問題:スクリプトを使用してその軸を再構築するにはどうすればよいですか?数学的には、頂点法線と細い円柱の交点です。

ステップ1は、特定の選択からのみ頂点法線を選択することです。外側を向いているものは必要ないからです。

テストシャード

回答

2 batFINGER Aug 18 2020 at 01:49

コンセプトの証明

凸包の単一の選択されたエッジでの結果

さらにコメントするために、これを概念実証への何らかの方法として追加しました。

まず、オブジェクトとメッシュを別のオブジェクトにコピーし、編集モードに切り替えて凸包に変換するスクリプトを次に示します。

シャードを選択して実行します

import bpy
bpy.ops.object.mode_set()
bpy.ops.object.duplicate(linked=False)
dupe = bpy.context.object
dupe.display_type = 'WIRE'
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.mesh.convex_hull()

その後、すべてのジオメトリが選択された編集モードで、元の凸包の新しいワイヤーフレーム。

次のスクリプトは、船体のエッジを通過し、メッシュ上の中間点に最も近いポイントを見つけ、これらを使用して、ここで説明するように弦から円を作成します。数学的に正しい円弧/円形セグメントを作成するにはどうすればよいですか?

視覚化するために、円の中心と2つの結合エッジに頂点を追加しました。データは半径、中心座標、および法線(回転軸、2つのエッジベクトルの正規化された外積)として保存されるため

テストスクリプトは、選択したエッジごとに予測される円の「ウェッジ」を作成します。編集モードで凸包メッシュを使用して実行し、対象のエッジを選択します。

凸包のすべてのエッジでの結果

import bpy
import bmesh
from math import asin, degrees
context = bpy.context
scene = context.scene
ob = context.object
me = ob.data
bm = bmesh.from_edit_mesh(me)
shard = scene.objects.get("3D_Scherbe_Model_50K")
#edges = bm.edges[:]  # all edges 
edges = [e for e in bm.edges if e.select]
#edges = [e for e in bm.select_history if isinstance(e, bmesh.types.BMEdge)]  
for edge in edges:

    o = (edge.verts[1].co + edge.verts[0].co) / 2

    hit, loc, _, _ = shard.closest_point_on_mesh(o)

    if hit:
        h = (loc - o).length
        if h < 0.1:
            print("On surface")
            continue
        a = edge.calc_length() / 2
        r = (a * a + h * h) / (2 * h)
        if abs(a / r) > 1:
            # math domain error on arcsin
            print("N/A")
        else:
            angle = 2 * asin(a / r)    
            print(f"{r} {degrees(angle)}")
            vc = bm.verts.new(o + r * (o - loc).normalized())
            for v in edge.verts:
                bm.edges.new((v, vc))  
bmesh.update_edit_mesh(me)
me.update()

ノート。

  • 最も近いポイントからエッジの中心までの円を予測する代わりに、エッジを歩いてサンプルポイントを作成してクランチすることができます https://meshlogic.github.io/posts/jupyter/curve-fitting/fitting-a-circle-to-cluster-of-3d-points/ そして https://github.com/ndvanforeest/fit_ellipse @RobinBettsによって提案されたように。

  • 同様に、生成された円の推定値を使用して、実際のメッシュサーフェスに対してテストできます。

  • メッシュ上の最も近い点から返される法線を見てください。

  • 選択範囲を絞り込むと、特定の範囲内の半径またはくさび角を示唆する履歴データがあります。

  • それぞれが同じ半径と角度を持っている場合、エッジの等しい長さの「サブコード」をメッシュに投影します(メッシュ上の最も近い点)。これは完全に一致します。最適化のために最小化します。

  • バウンディングボックスの寸法を見てください。エッジが最小bbox寸法の一部よりも短い場合、それはおそらく主ポット軸ではありません。いくつかのパーセンテージを削ることを検討してください。

  • 何らかの方法でシャードメッシュのクリーニングまたはスムージングを間引きます。