การสร้างแกนของหม้อใหม่ด้วยชิ้นส่วนเดียวผ่านบรรทัดฐานจุดยอด

Aug 16 2020

ฉันกำลังวางแผนที่จะสร้างหม้อใหม่ทั้งหมดจากเศษชิ้นส่วนเดียว

ฉันคิดวิธีที่จะทำแล้ว แต่ฉันไม่รู้ว่าจะทำให้มันเกิดขึ้นในโค้ดได้อย่างไร

ทฤษฎี: ทุกชิ้นมีส่วนโค้งงอ โค้งนี้มีข้อมูลสองส่วน:

  • การวางแนวของชิ้นส่วนภายในหม้อ
  • เส้นผ่านศูนย์กลางของหม้อ คุณสามารถเห็นสิ่งนี้ได้อย่างง่ายดายเมื่อเปิดบรรทัดฐานจุดยอดในโหมดแก้ไข ในทางเทคนิคตั้งแต่ขั้นตอนการทำเครื่องปั้นดินเผามีแกนกลางอยู่ตรงกลางของหม้อทุกใบ บรรทัดฐานจุดยอดข้ามแกนนี้ดังนั้นคุณจะเห็นแกนได้ชัดเจนเมื่อเปิดบรรทัดฐานจุดยอด

ปัญหา: ฉันจะสร้างแกนนั้นใหม่ผ่านสคริปต์ได้อย่างไร ในทางคณิตศาสตร์มันคือจุดตัดของบรรทัดฐานจุดยอดด้วยทรงกระบอกบาง ๆ

ขั้นตอนที่หนึ่งคือการเลือกบรรทัดฐานจุดยอดจากการเลือกบางรายการเท่านั้นเนื่องจากฉันไม่ต้องการสิ่งที่หันออกไปด้านนอก ...

ทดสอบ Shard

คำตอบ

2 batFINGER Aug 18 2020 at 01:49

หลักฐานแนวคิด

ผลลัพธ์ของขอบนูนที่เลือกไว้ด้านเดียว

นอกจากนี้เพื่อแสดงความคิดเห็นได้เพิ่มสิ่งนี้เพื่อพิสูจน์แนวคิด

Fistly นี่คือสคริปต์ที่คัดลอกออบเจ็กต์ของคุณและเมชไปยังอีกอันหนึ่งเข้าสู่โหมดแก้ไขและแปลงเป็นตัวถังนูน

เลือกชาร์ดและเรียกใช้

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()

หลังจากนั้นโครงลวดใหม่ของตัวถังนูนของต้นฉบับในโหมดแก้ไขโดยเลือกรูปทรงเรขาคณิตทั้งหมด

สคริปต์ถัดไปจะผ่านขอบของตัวถังค้นหาจุดที่ใกล้ที่สุดบนตาข่ายถึงจุดกลางใช้สิ่งเหล่านี้เพื่อสร้างวงกลมจากคอร์ดตามที่อธิบายไว้ที่นี่ฉันจะสร้างส่วนโค้ง / วงกลมที่ถูกต้องทางคณิตศาสตร์ได้อย่างไร

เพื่อให้เห็นภาพได้เพิ่มจุดยอดที่ศูนย์กลางวงกลมและขอบเชื่อมทั้งสอง เนื่องจากข้อมูลจะบันทึกเป็นรัศมีพิกัดศูนย์กลางและปกติ (แกนของการหมุนผลคูณไขว้ที่เป็นมาตรฐานของเวกเตอร์ขอบสองเส้น)

สคริปต์ทดสอบสร้างวงกลมที่คาดการณ์ "เวดจ์" สำหรับแต่ละขอบที่เลือก ทำงานด้วยตาข่ายตัวถังนูนในโหมดแก้ไขเลือกขอบที่สนใจ

ส่งผลให้ขอบทั้งหมดของตัวถังนูน

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 ขั้นต่ำอาจไม่ใช่แกนหม้อหลัก ลองโกนหนวดออกบ้าง.

  • การกำจัดตาข่ายทำความสะอาดหรือทำให้เรียบในบางวิธี