Ricostruzione dell'asse del vaso con un frammento tramite le normali dei vertici
Sto progettando di ricostruire un intero vaso da un frammento di esso.
Ho già pensato a un modo per farlo, ma davvero non so come farlo accadere in codice.
Teoria: ogni frammento ha una certa piega. Questa curva contiene due informazioni:
- l'orientamento del frammento all'interno del vaso
- il diametro della pentola. Puoi facilmente vederlo quando attivi le normali ai vertici in modalità di modifica. Tecnicamente, dal processo di produzione della ceramica, c'è un asse centrale al centro di ogni vaso. Le normali dei vertici attraversano questo asse, in modo da poter vedere chiaramente l'asse quando si attivano le normali dei vertici.
Problema: come ricostruisco quell'asse tramite script? matematicamente è l'intersezione delle normali ai vertici con un cilindro sottile.
Il primo passo sarebbe selezionare le normali ai vertici solo da una certa selezione, poiché non ho bisogno di quella rivolta verso l'esterno ...

Test Shard
Risposte
Verifica teorica

Oltre a commentare, ho aggiunto questo come un modo per provare
Fistly qui è uno script che copia l'oggetto e la mesh in un altro, entra in modalità di modifica e lo converte in uno scafo convesso.
Seleziona il frammento ed esegui
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()
dopo di che nuovo wire frame dello scafo convesso dell'originale in modalità di modifica con tutta la geometria selezionata.
La sceneggiatura successiva attraversa i bordi dello scafo, trova il punto della mesh più vicino al suo punto medio, li usa per creare un cerchio dalla corda come descritto qui Come posso creare un arco / segmento circolare matematicamente corretto?
Per visualizzare hanno aggiunto un vert al centro del cerchio e i due bordi di giunzione. Poiché i dati vengono salvati come raggio, coordinata centrale e normale (asse di rotazione il prodotto incrociato normalizzato di due vettori di bordo)
Script di test, crea "cunei" del cerchio previsto per ogni bordo selezionato. Corri con la maglia dello scafo convessa in modalità di modifica, i bordi di interesse selezionati.

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()
Appunti.
Invece di prevedere un cerchio dal punto più vicino al centro del bordo, potresti camminare sul bordo e creare punti campione in cui scricchiolare https://meshlogic.github.io/posts/jupyter/curve-fitting/fitting-a-circle-to-cluster-of-3d-points/ e https://github.com/ndvanforeest/fit_ellipse come suggerito da @RobinBetts.
Allo stesso modo è possibile utilizzare la stima del cerchio generata per eseguire il test rispetto alla superficie mesh effettiva.
Guarda la normale restituita dal punto più vicino sulla mesh.
Restringere la selezione, sono presenti dati storici che suggeriscono raggi o angoli di cuneo entro un determinato intervallo.
Proietta (punto più vicino sulla mesh) "sottocorde" di uguale lunghezza del bordo sulla mesh, se ciascuna ha lo stesso raggio e angolo sarebbe una corrispondenza perfetta. Ridurre al minimo per una migliore vestibilità.
Guarda le dimensioni del riquadro di delimitazione. Se un bordo è più corto di una frazione della dimensione minima del bbox, probabilmente non è l'asse principale del piatto. Considera l'idea di raderti una certa percentuale.
Decimare la pulizia o levigare in qualche modo la rete di frammenti.