Come posso aggiungere e sottrarre poligoni convessi?


12

Ho due poligoni convessi 2D sovrapposti . Sto cercando un algoritmo per sottrarre e aggiungerli . Il risultato deve essere un singolo poligono concavo o (ancora meglio) un insieme di quelli più grandi convessi che formano il risultato concavo (ad esempio triangoli).

inserisci qui la descrizione dell'immagine

(A sinistra: i poligoni sovrapposti iniziali. Medio: il poligono concavo risultante dopo l'aggiunta. A destra: un insieme di poligoni convessi che formano il risultato concavo. Qui sarebbe meglio ottenere poligoni convessi più grandi di un triangolo per motivi di prestazioni. Una sottrazione del due poligoni sovrapposti porterebbero alla stessa immagine di sinistra ma con l'area di sovrapposizione non facente parte del poligono risultante.)

Come posso fare questo?


Stiamo parlando di 2D qui? perché in 3D la combinazione di poligoni non ha molto senso.
concept3d

Sì, tesoro, sto parlando di 2D! Anche se non vedo perché non abbia meno senso in 3D che in 2D.
Sebastian Barth

2
aggiungere due poligoni in 3D, se sono piatti, non ha molto senso se non si trovano sullo stesso piano, se hanno volume (solidi), allora è una storia diversa.
concept3d

Ok, ce l'ho. Non stavo pensando alla grafica, ma agli oggetti di collisione. Grazie per il chiarimento.
Sebastian Barth

Inoltre, trova tutti i punti che intersecano e aggiungi i vertici a un set. Il set è importante per evitare sovrapposizioni. Quindi, aggiungi semplicemente tutti gli altri vertici delle altre due forme nel set. Questo set contiene tutti i vertici della forma additiva.
Vaughan Hilts

Risposte:


9

TL; DR È necessario implementare operazioni booleane utilizzando alberi BSP.

Bene, sembra che stiamo parlando della geometria solida costruttiva qui. Ho implementato CSG a livello commerciale, quindi ne so una cosa o due.

Il classico documento su CSG si chiama Merging BSP Trees Yields Polyhedral Set Operations , ad essere sinceri, è troppo da spiegare qui, ma brevemente l'algoritmo si occupa dei poligoni che si trovano sullo stesso piano di un partizionamento dello spazio binario, fondamentalmente costruendo un albero BSP da ogni mesh poligonale. Il secondo passo è unire quegli alberi BSP; prendi semplicemente un albero e lo inserisci nell'altro. L'algoritmo procede quindi a spiegare come gestire ciascun nodo foglia per dividere e sottrarre i nodi, i nodi che non sono necessari nella forma finale verranno rimossi, ad altri verrà dato il genitore appropriato.

Ma aspetta! Quel documento parla fondamentalmente di mesh poligonali e piani 3D, NO?

L'algoritmo può essere generalizzato in qualsiasi dimensione, quindi nel tuo caso 2D è facile usare segmenti di linea anziché piano come partizioni binarie. Quindi ogni poligono verrà convertito in un albero BSP di quanto i due verranno uniti. Infine attraversi l'albero risultante per generare il poligono finale,

Si noti che questo algoritmo e CSG in generale non si occupano direttamente di rendering e mesh delle facce e non sono realmente pronti per il rendering, quindi è necessario estrarre le facce degli alberi BSP finali. Trovo anche il ray tracing un approccio più semplice per il rendering del risultato CSG, hai solo bisogno dei raggi per attraversare l'albero invece di estrarre e effettivamente dividere le facce (ricorda che ci occupiamo solo di partizioni binarie).

Per quanto riguarda la robustezza numerica. È bene notare che esistono due tipi di calcoli geometrici,

  • Quelli che si basano sulla costruzione, costruisci una forma in base al risultato di un'operazione precedente. Ad esempio, y = sqrt(x)quindi utilizzare yin una nuova operazione. Questo si chiama costruzione; il problema è che gli errori numerici si accumuleranno rapidamente.
  • In alternativa, ci sono operazioni che usano invece predicati , essenzialmente invece di usare la costruzione semplicemente chiedi se una condizione è vera / falsa e usi lo stesso valore in un'operazione diversa. I test classici includono l'incircle e il test di orientamento; questo è anche sospetto di errori numerici, soprattutto se si utilizza la precisione singola o doppia, ma di solito darà risultati molto migliori. esistono altre soluzioni che variano in termini di velocità e precisione. Ecco uno dei documenti recenti che evitano la costruzione utilizzando una geometria basata su un piano per fornire risultati accurati. Citerò anche dal documento:

Il concetto di rappresentazione basata su piano di maglie poligonali è stato descritto per la prima volta da Sugihara e Iri [SI89]. Questo tipo di rappresentazione offre un vantaggio importante quando si tratta di attività che comportano la modifica della topologia dei solidi rappresentata da mesh come la valutazione delle espressioni booleane: non è necessario costruire nuove informazioni sulla geometria primaria per ottenere il poliedro risultante

inserisci qui la descrizione dell'immagine

E infine vorrei aggiungere, se desideri iniziare l'implementazione di CSG BSP, ti consiglio di iniziare con le domande frequenti su BSP .


Bello, ma controintuitivo, considerando che un BSP di un poligono convesso o poliedro è un elenco. Ottima carta
3Daveva il

@David Sì, ma può renderlo un albero bilanciato scegliendo il piano della radice in modo che non sia facce. In realtà questo fa parte della sfida di cui non parlano
concept3d

Ah, ha senso. Sorta di un BSP ibrido, quindi.
3Dave l'

@DavidLively anche il BSP non è davvero facile da rendere, anche se la domanda OP è un caso semplice, in un caso più complesso con geometria di milioni di poligoni, una volta terminata la costruzione dell'albero sei tutt'altro che finito.
concept3d

@ concept3d Spero che questo non sia troppo fastidioso poiché questa è una risposta di 5 anni, ma ci sono due cose che non capisco davvero: quando provo a determinare se un punto si trova a sinistra o a destra di un piano / linea, non sarebbe più semplice semplicemente ruotare l'intera cosa in modo che il piano / linea corrisponda a un piano / linea banali, e quindi considerare solo le coordinate del punto ruotato? Che ne dici di usare l'algoritmo Sutherland-Hodgman invece degli alberi BSP? Sembra abbastanza simile a questo approccio.
John P

1

Seguendo il tuo esempio:

Scegli un vertice iniziale sul poligono A, quindi inizia a verificare la presenza di bordi intersecanti in senso orario (o antiorario). Se non c'è un'intersezione, aggiungi il vertice precedente al poligono risultante. Se è presente un'intersezione, aggiungi il punto in cui si intersecano al poligono risultante, quindi inizia a scorrere il poligono B, nello stesso ordine di avvolgimento. Fai la stessa cosa, scambiando di nuovo con il poligono A se si verifica un'intersezione.

Dopo aver accumulato tutti i vertici per il nuovo poligono, esegui un algoritmo di triangolazione su di esso. Il metodo del clipping dell'orecchio è facile da implementare, ma ci sono opzioni più veloci là fuori.

Importante: assicurati che il vertice da cui inizi non si trovi all'interno dell'altro poligono (consulta questo articolo per individuare i test poligonali).

Iterando su ciascun bordo, per verificare un'intersezione sarebbe un algoritmo O (n ^ 2). Potresti accelerarlo trovando prima i vertici che si trovano all'interno dell'altro poligono, poiché i bordi collegati a quei vertici saranno quelli che si intersecano.


0

Se vuoi un poligono concavo , seleziona il bordo più vicino tra i due poligoni di input e aggiungi due nuovi bordi:

inserisci qui la descrizione dell'immagine

Convesso diventa leggermente più complicato:

inserisci qui la descrizione dell'immagine

Un approccio è iterativo in quanto aggiunge vertici dal secondo poligono al primo, uno alla volta, trasformando il primo poligono in un contenitore che racchiude tutto.

Fondamentalmente:

  • Scorrere i vertici del secondo poligono.
  • Per ogni vertice V, scorrere i bordi del primo poligono:
  • Trova un "intervallo" di spigoli che siano tutti rivolti verso il vertice
  • prendere la coppia esterna di vertici che definiscono quell'intervallo e rimuovere tutti i bordi nell'intervallo che li collega
  • Disegna due nuovi segmenti da quei vertici esterni al nuovo vertice (dal secondo poligono), assicurandoti che i nuovi bordi siano rivolti nella direzione corretta.
  • Passa al vertice successivo dal secondo poligono

Ecco un diagramma che illustra il processo per il primo vertice:

inserisci qui la descrizione dell'immagine

Un metodo più rapido consiste nel trovare l'elenco di spigoli su ciascun poligono che non è rivolto verso l'altro poligono, rimuovere tutto il resto e collegare gli estremi delle strisce di linee rimanenti tra loro.

Forse qualcun altro può intervenire con qualche consiglio di sottrazione.


Questo sembra solo affrontare metà del problema (aggiunta). Potrebbe anche essere utile sottolineare come funzionano gli algoritmi o potrebbe essere ottimizzato se i poligoni si sovrappongono.

L'algoritmo ignora implicitamente i vertici che si trovano "all'interno" del poligono target, il che compensa anche il problema in cui un bordo del secondo poligono incrocia il primo.
3Daveva il

Ciò equivale quasi alla fase di unione (punto 4. dell'algoritmo di fusione dello scafo . Nel mio caso non è una soluzione corretta racchiudere più area dopo aver combinato i poligoni. La soluzione corretta sarebbe quella di mantenere entrambi i poligoni così come sono poiché non sono " non si sovrappongono, né si toccano
Sebastian Barth,

@luftgewehrindianer Ah - Sì, questo fa una grande differenza. Forse ho frainteso la domanda. Stai cercando di aggiungere i poligoni insieme, senza preoccuparti se il risultato è convesso o concavo? O generare un set convesso basato sull'intersezione? (Ignorando la sottrazione per il momento.)
3Dave il

@DavidLively Immagina due poligoni convessi dello stesso colore e senza bordi. Quando si sovrappongono, sembra un nuovo poligono convesso o concavo. Cerca di trovare una triangolazione della forma combinata. Non aggiungere un'area tra entrambi i poligoni.
danijar,
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.