Algoritmo per la creazione di triangoli adiacenti


14

Ho un sistema in cui è possibile fare clic una volta per posizionare un nodo in una scena. Quando si posizionano 3 nodi, forma un triangolo. Quando si posizionano nodi futuri, viene creato un nuovo triangolo unendo quel nodo ai 2 nodi esistenti più vicini.

Funziona bene per la maggior parte del tempo ma è imperfetto se usato vicino a triangoli con angoli molto acuti, perché uno dei 2 nodi più vicini spesso non è uno che dovrebbe essere usato.

Ad esempio, vedi l'immagine qui sotto. Il triangolo magenta è il primo posto. Se poi faccio clic sulla posizione contrassegnata con X, quello che ottengo è un nuovo triangolo in cui si trova la sovrapposizione blu. Quello che voglio è un nuovo triangolo in cui si trova la sovrapposizione verde. (es. simmetrico a quello magenta, in questo esempio. Chiarimento: i triangoli verde e magenta non si sovrappongono - quello verde si estende sotto quello blu fino al nodo più a sinistra)

Esempio di comportamento attuale e desiderato

Come posso determinare quali 2 vertici esistenti usare quando si creano nuovi triangoli in modo che i triangoli non vengano sovrapposti in questo modo?

EDIT : la ricerca del bordo più vicino offre risultati migliori , ma non perfetti. Considera questa situazione:

inserisci qui la descrizione dell'immagine

Il test del "bordo più vicino" è ambiguo e può restituire AB o AC (poiché il punto più vicino a X per entrambi è in A). Il risultato desiderato sarebbe AC, per formare il triangolo ACX senza bordi sovrapposti. Come posso garantire questo risultato? (Preferirei non dover eseguire test di sovrapposizione dei singoli bordi come se fosse un pareggio, se possibile perché sono preoccupato che il test dei bordi più vicino non rilevi necessariamente che i 2 siano esattamente equidistanti, dati i problemi di precisione in virgola mobile.)


Non è sufficiente osservare gli ultimi 5 vertici posizionati e selezionare i due più vicini al vertice appena posizionato? Vorrei indicarti gli algoritmi per le strisce triangolari ( codercorner.com/Strips.htm ) ma quelli spesso usano solo gli ultimi due o gli ultimi tre saltando uno.
Roy T.

1
Il triangolo verde si sovrappone a quello magenta? Qual è l'obiettivo di questo? L'utente deve controllare dove e come vengono creati i triangoli o sarebbe accettabile la triangolazione di una nuvola di punti?
bummzack,

Per metterlo in un contesto grafico, essenzialmente vuoi connettere i tuoi nodi, senza che i bordi si sovrappongano? (Supponendo che i triangoli magenta / verde condividano un bordo)
MichaelHouse

Roy T: no - solo scegliere il 2 più vicino è sbagliato, come pensavo nell'esempio. C'è qualcosa di poco chiaro? Bummzack - Quello verde non si sovrappone a quello magenta. L'obiettivo è creare una mesh o un grafico di questi triangoli. L'utente ha bisogno di controllo, sì. Byte56: sì, nessun bordo deve incrociarsi.
Kylotan,

2
L'utente vedrà effettivamente i singoli triangoli? O sarà una superficie continua?
bummzack,

Risposte:


11

Invece di trovare la distanza minima dai nodi, trova la distanza minima dal bordo (ovvero il segmento di linea definito dai nodi).

Quindi, se il punto più vicino è un vertice (che dovrai usare un test epsilon ** in virgola mobile), confronta l'angolo tra la linea dal nuovo punto al vertice e ciascuno dei bordi collegati a quel vertice. Scegli quello con l'angolo assoluto minimo:

MinAngle(newPoint, vertex, edge1, edge2)
{
   newEdgeUnit = norm(newPoint - vertex); // don't actually need to normalize this
   edge1Unit = norm(edge1 - vertex);      // you probably have these from your dist to line tests
   edge2Unit = norm(edge2 - vertex);

   edge1Dot = dot(edge1Unit, newEdgeUnit);
   edge2Dot = dot(edge2Unit, newEdgeUnit);

   // you can simply compare dot products to find the minimum absolute angle
   if (edge1Dot > edge2Dot) return edge1;     // set up this way so you can generalize to an array
   return edge2;
}

** Per evitare l'aggiunta di triangoli degeneri, che potrebbero interrompere il test epsilon, potresti voler mettere una regione attorno a ciascun vertice in cui è vietato aggiungere punti (qualcosa come non consentire punti all'interno di un multiplo del epsilon usato sopra).


3
+1: questa è una risposta molto più semplice di IMHO rispetto alle altre e con maggiori probabilità di fornire i risultati corretti. Anche la distanza dal segmento è facile da calcolare, con uno schema intelligente.
Steven Stadnicki,

D'accordo, questo è un metodo più pulito. Probabilmente a cosa sarei arrivato se ci avessi pensato di più: /
MichaelHouse

Ah, così vicino! Ma, come nella risposta di Byte56 e nel diagramma di Jimmy, a volte ci sono 2 bordi equidistanti e uno di questi viola i vincoli. Ho aggiornato la mia domanda.
Kylotan,

@Kylotan Forse in quel caso, semplicemente controllando quale si sovrappone e prendendo l'altra opzione farebbe? Cerca i triangoli che condividono il bordo che hai scelto e controlla se il tuo nuovo triangolo si trova sullo stesso lato di quel bordo di quello esistente.
Kevin Reid,

@Kylotan Assicuri che i tuoi triangoli abbiano sempre lo stesso avvolgimento? Se sì, potresti escludere il bordo che ha un normale puntamento lontano dal tuo nuovo vertice (usando il punto-prodotto).
Bummzack,

6

Dopo aver posizionato il primo triangolo, quando si posiziona un nuovo vertice, verranno sempre generati due nuovi bordi. Il terzo bordo per il nuovo triangolo sarà sempre un bordo condiviso con un triangolo precedente. Se potessi trovare un modo per determinare il bordo condiviso, sapresti a quali vertici connettersi, ma questa è la parte difficile. Credo che in un modo puoi farlo tracciando una linea dal tuo nuovo vertice al centro di ciascuno degli ultimi tre bordi generati (o probabilmente i 3 bordi più vicini).

inserisci qui la descrizione dell'immagine

Se la linea dal vertice al centro del bordo non attraversa nessuno degli altri due bordi, hai il bordo condiviso. Il bordo condiviso ti dirà a quali due vertici collegare il tuo nuovo vertice.

Jimmy ha sollevato il caso per un punto ambiguo su dove andrebbe il nuovo triangolo in questo modo:

triangolo ambiguo

Ciò ti darebbe l'opportunità di scegliere tra due triangoli validi. Forse la rottura del pareggio è il punto centrale più vicino.

Considerando il tuo aggiornamento, sebbene più complesso, la mia soluzione si tradurrà in un pareggio solo quando hai due triangoli validi. Usando questo metodo la tua seconda immagine di esempio produrrebbe il risultato che desideri.

inserisci qui la descrizione dell'immagine


È possibile avere una situazione in cui due delle linee non si intersecano con i bordi (quando X è più vicina a un vertice di quanto non sia al bordo)
Jimmy

@Jimmy puoi disegnare un'immagine di una situazione del genere?
MichaelHouse


Ah sì, allora hai due scelte su dove posizionare il triangolo! Entrambe le parti avrebbero funzionato. Forse puoi legare la rottura con quella che ha la distanza più breve dal centro.
MichaelHouse

@Kylotan questa soluzione non funziona? In un commento a Jeff hai menzionato che l'immagine di Jimmy ha due casi e uno viola i vincoli, ma non è vero. Nell'immagine di Jimmy i due casi avrebbero entrambi prodotto triangoli validi usando il mio metodo.
MichaelHouse

1

Avendo il tuo triangolo magenta ABC, allora incorpori un nuovo vertice X. Penso che sia ovvio che ci saranno due linee che iniziano in D che non si intersecheranno tra i bordi del triangolo ABC.

Queste due linee potrebbero essere AX & BX, BX & CX o AX & CX. Puoi quindi trattare il tuo problema come il classico problema di "intersecare due linee"? È quindi possibile verificare quale di queste coppie di linee non si interseca con nessuno dei bordi del triangolo ABC seguendo, ad esempio, nessuno dei metodi di questa domanda . Quindi, avrai i due nuovi bordi del nuovo triangolo.


Questo sembra buono, ma il modo in cui hai affermato sembra presumere che esista un solo triangolo. Come si generalizzerebbe a molti?
Kylotan,

Hum ... se la tua X e il tuo triangolo ABC sono fissi, immagino ce ne sia solo uno, no?
Dan

Il sistema crea un nuovo triangolo per ogni nodo dopo il secondo.
Kylotan,

Scusa, ho frainteso la tua domanda. Fammi vedere come posso estenderlo a molti triangoli.
Dan,

Beh, immagino che potresti cercare i due vertici più vicini a X che non attraversano alcun bordo quando sono collegati a X?
bummzack,

1

Capire se ti trovi in ​​una delle regioni non ambigue (1, 2, 3 in basso), è abbastanza facile: tratta ogni bordo del tuo triangolo come un piano 2D e verifica su quale lato del piano si trova il tuo nuovo punto. Se ci sei dentro due ma fuori da uno, allora quello corrisponde al bordo del triangolo che contribuisce con due vertici al tuo nuovo triangolo.

Regioni di Voronoi di un triangolo

Se sei dentro uno e fuori due, sei nel caso ambiguo in cui la parte più vicina del triangolo al tuo nuovo punto è un angolo. In tal caso, puoi formare un piano 2D dal punto medio del bordo opposto (quello all'interno del quale ti trovi) e il vertice più vicino (quello condiviso dai due piani di cui sei all'esterno). Puoi scegliere un bordo a seconda del lato di questo piano su cui si trova il tuo nuovo punto.

Nota che un test del piano in 2D funziona allo stesso modo del 3D: punti un vettore da qualsiasi punto del piano al tuo punto con il normale del piano (in 2D, questa è la linea perpendicolare).

(Per inciso, le regioni delimitate da magenta in questa immagine sono chiamate regioni Voronoi; sono le aree dello spazio che contengono punti che sono più vicini a una particolare caratteristica - bordo o vertice - del triangolo. Modifica: la mia terminologia qui non è in realtà abbastanza corretto, queste non sono esattamente le regioni Voronoi.)


Non mi è subito chiaro come questo generalizzi a più triangoli nella scena, specialmente se la caratteristica più vicina è un vertice che può essere condiviso da più di 1 triangolo.
Kylotan,

@Kylotan Basta eseguire l'algoritmo per tutti i triangoli e selezionare la funzione complessiva più vicina. Hai bisogno di un po 'di logica vincolante, non importa quale. Se alla fine la caratteristica più vicina è un vertice condiviso, allora dovresti trovarti nella regione del bordo (# 1, # 2, # 3) per un solo triangolo, quindi forse puoi sceglierlo?
John Calsbeek,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.