GraphicsPath Poligono Montaggio in C #
-
28-09-2019 - |
Domanda
Ho bisogno di "fit", un GraphicsPath arbitrariamente forma in uno spazio definito (quasi sempre un rettangolo o un cerchio).
Attualmente scala GraphicsPath utilizzando l'oggetto Matrix e il ridimensionamento funziona bene, ma il problema sta ottenendo i fattori di scala.
La tecnica migliore che posso venire in mente è la conversione del GraphicsPath ad una regione, la conversione del rettangolo o un cerchio ad una Regione, e l'esecuzione di una:
rgnShape.Intersect(rgnCircle);
e quindi verificare se:
rgnShape.IsEmpty()
Tuttavia, questo solo mi dice che se la forma è troppo grande per forma, e si rende necessario per scalare la forma più piccola, e riprovare (forse molte, molte volte).
C'è un modo semplice per calcolare all'istante i fattori di scala per adattarsi a un GraphicsPath poligono in modo che si adatti completamente in un cerchio. Il risultato dovrebbe essere il più grande poligono che si adatta ancora del tutto all'interno del cerchio.
Soluzione
http://en.wikipedia.org/wiki/Smallest_circle_problem per la discussione di questa problema in termini di punti, piuttosto che percorsi, trovato da Simon.
-
Quindi, fare questo, l'uso
rgnShape.Intersect(rgnCircle);
per verificare se ha funzionato. Se non è riuscito, prendere ogni curva e afferrare i punti più lontani dal centro del cerchio che hai trovato (ci possono essere più di uno di tali punti per ogni regione). -
Aggiungi loro di elencare riapplicare l'algoritmo di tuoi punti. Non avrete bisogno di ripartire da zero; non è necessario prendere in considerazione i punti non sul confine (vale a dire, ignorano i punti non in "Set Q" che è stato trovato dalla chiamata originale per l'algoritmo).
Si noti che questo non è più lineare, poiché la probabilità di generare chiamate ricorsive è più 1 / i per il punto esimo.
Questa è una condizione bordo è necessario gestire in modo esplicito. Nel caso in cui una delle curve trovato trovato fuori della regione trovato durante la prima iterazione della fase 1 è perfettamente circolare e toccando il cerchio esterno, ci saranno infiniti punti all'interno "Set Q" e questo algoritmo sicuro sprecando. Così, dopo l'applicazione rgnShape.Intersect(rgnCircle);
per la prima volta, si dovrebbe verificare eventuali curve perfettamente rotonde esplicitamente per questo caso. Ad esempio, se la forma è (}
si dovrebbe verificare in modo esplicito ()
(per fini di questa discussione, ()
finta è un cerchio) se si trova (
al di fuori della regione hanno trovato durante la prima iterazione.
Questo è ancora piuttosto male, ma è meglio che cambiare tutti Curva in punti.
Altri suggerimenti
Non vedo il motivo per cui è necessario il binario di ricerca.
Una volta che si ottiene il rettangolo di delimitazione per la tua forma, e si ha il rettangolo di destinazione in cui si desidera per adattarsi alla forma, è possibile confrontare i due rapporti targetHeight / shapeHeight
e targetWidth / shapeWidth
.
Prendere il rapporto più piccolo, e utilizzare questo come il fattore di scala per scalare la forma.
Se il bersaglio è un cerchio e non un rettangolo, è possibile utilizzare una soluzione simile prendendo il rapporto tra targetCircleDiameter / boundingRectangleDiagonal
e utilizzare questo come fattore di scala.
Si potrebbe usare GetBounds sul GraphicsPath e la Regione, quindi confrontare le dimensioni dei rettangoli per ottenere almeno si chiude.
Se lo spazio definito è una piazza che dovrebbe essere esatto.
Se lo spazio definito qualcos'altro, che sarebbe ottenere almeno si chiude. È quindi possibile utilizzare una ricerca binaria per trovare l'importo effettivo ridimensionamento.
Non puoi calcolare il centro del GraphicsPath e un raggio?
Si potrebbe centro o di calcolo di gravità (media di coordinate) e aggiungere 2 volte deviazione standard - questo dovrebbe farti circa il 92% del grafico - la maggior parte del tempo sarebbe bene, ma non riuscirà se il grafico ha più 'peso' in una delle estremità.
Si potrebbe anche calcolare il centro dei punti - corsa attraverso tutti i punti, ricevere / min punti massimi in tutte le direzioni come quando si calcola BoundingBox, prendere il centro di questo e di misurare la distanza più lunga per i punti (max / min) come raggio .
Si potrebbe probabilmente trovare un algoritmo più sofisticato se cercate un algoritmo di sfera di delimitazione - ma se è solo alla visualizzazione qualcosa che si potrebbe fare un po 'compromessi. Se stai facendo il rilevamento delle collisioni esiste alcuni algoritmi veloci anche per questo :)
Come circa andando nella direzione opposta utilizzando la matematica semplice? Cioè ottenere la delimitazione scatola / cerchio del percorso, calcolare il rapporto rettangolare predefinito di altezza / larghezza, confrontare che allo stesso valore di BB, allungare il BB conseguenza (ad esempio se razione predefinito è inferiore a 1, il BB è allungata orizzontalmente e verticalmente altrimenti per abbinare lo stesso rapporto), per poi scalare il tutto alla dimensione rettangolare predefinita. Il fattore di scala è ora solo il minimo tra altezza predefinita diviso altezza BB e predefiniti larghezza divisa per la larghezza BB. (Per il cerchio di delimitazione non v'è alcuna necessità di regolare le dimensioni.)