E 'abbastanza facile tracciare i punti di controllo e consentire all'utente di trascinare in giro. Sfortunatamente, la curva non passa attraverso tutti i punti di controllo, quindi l'esperienza non corrisponde esattamente a ciò che stai suggerendo.
Per fare ciò che stai suggerendo, devi prima rispondere alla domanda "l'utente sta toccando la curva?" Questo è lo stesso della domanda "è un dato punto all'interno di una certa distanza della curva". Questa non è una domanda banale, ma può essere calcolata. Probabilmente l'approccio più semplice è semplicemente calcolare i punti X lungo la curva (dove X è sufficientemente alto per darti una ragionevole precisione) e controllare la distanza per ciascuno. In linea di principio, potresti anche prendere la derivata dell'equazione della distanza e risolverla per i suoi zeri, ma ciò richiede l'iterazione. Nella mia esperienza è possibile calcolare le circa 1000 distanze necessarie abbastanza velocemente (anche su un iPad 1) che potrebbe non valerne la complessità aggiuntiva.
Una volta che l'utente sta effettivamente toccando la curva, è facile capire quale sia il punto di controllo più vicino. La cosa difficile a questo punto è decidere cosa fare al riguardo. Alcune opzioni:
- Spostare il punto di controllo più vicino nella direzione in cui si muove l'utente. Potrebbe essere necessario eseguire più calcoli finché non trovi una nuova curva che passa attraverso il punto di contatto. Questo è l'approccio più semplice e probabilmente da dove iniziare.
- È possibile suddividere la curva nel punto toccato e spostare gli endpoint appena creati. (Vedere l'algoritmo De Casteljau's per questo.) Questo tenderà a creare spigoli vivi a meno che non si regolino gli altri punti di controllo per creare pendenze corrispondenti. Ciò consente curve più arbitrarie, ma potrebbe diventare molto difficile sapere cosa volesse veramente l'utente. Avresti anche quasi certamente bisogno di applicare Ramer-Douglas-Peucker per evitare che il tuo numero di curve esploda.
Attualmente sono abbastanza interessato ai problemi con la curva di Bézier in Objective-C. Potresti essere interessato al mio first post on the subject. Il mio lavoro iniziale in quest'area è disponibile su GitHub nel codice di esempio iOS:PTL. Spero di avere un altro post su questa settimana. Il tuo problema particolare è interessante, quindi potrei vedere cosa posso costruire intorno a questo.
fonte
2012-02-13 16:01:22
Puntatore eccellente. Sarei un po 'nervoso nel cercare di disegnare una polilinea in questo modo, comunque. La mia esperienza è che CGPath molto grandi tendono ad essere estremamente costosi da disegnare. Ma è possibile convertire un Catmull-Rom in un Bézier: http://stackoverflow.com/questions/1030596/drawing-hermite-curves-in-opengl. Quello potrebbe essere uno strumento utile. Lascia ancora la complessità di dividere la curva e quindi semplificarla di nuovo in cubico, ma un ottimo punto di partenza. –
Ho diviso il percorso di alcuni segmenti per ottimizzare il processo (aggiornamenti, disegno), inoltre c'è un trucco: il parametro t può essere variabile. Possiamo controllare la lunghezza del segmento della curva e regolare la t, in modo che i punti di chiusura ottengano poche "linee di levigatura" mentre i punti di distanza possono avere una dozzina di linee di approssimazione. – Gobra
Vero. Il mio codice collegato qui sotto include "dammi il' t' per una determinata distanza lungo il percorso ", così puoi assicurarti di non provare mai a disegnare linee troppo corte (sicuramente mai più brevi di 1px, cosa che può facilmente accadere se passi oltre 't' linearmente). I miei gravi problemi di prestazioni si sono verificati nei dintorni di 4000-5000 segmenti di linea, e questa tecnica potrebbe tenerti sotto. –