2012-04-03 4 views
10

Speravo che qualcuno potesse aiutarmi a capire un metodo computazionalmente economico per rilevare nodi in una linea tracciata parallelamente ad una curva di Bézier, come potete vedere quiDetect "Kinks" in linee parallele in curve di Bezier

Kink in Line Parallel to Bezier Curve

Quello che mi piacerebbe fare è essere in grado di determinare l'intersezione del nodo, il segmento con un punto di partenza prima dell'intersezione e il primo segmento con un punto finale dopo il nodo. In questo modo posso semplicemente rimuovere tutti i segmenti non necessari e regolare il primo e l'ultimo segmento da incontrare all'incrocio.

Mi scuso se sto usando i termini sbagliati. Ma per quanto ho capito, il modo in cui sto posizionando questi segmenti è determinando il vettore unitario dei segmenti per la curva di Bezier (giallo) e moltiplicandolo per l'offset e trovando il vettore normale per creare due nuovi punti di inizio e fine per il segmento offset (bianco).

La matematica non è il mio forte seme quindi spero che qualcuno possa darmi una spinta nella giusta direzione.

EDIT: L'immagine è stata ridimensionata in realtà da HTML, quindi se hai difficoltà a vedere di cosa sto parlando ecco il link diretto: http://i.stack.imgur.com/xtils.png

+0

Bel diagramma. Cosa vuoi fare nel caso in cui lo stesso Bezier si stia attraversando da solo? –

+1

Non ho bisogno di nulla di speciale in questi casi. –

+0

i ragazzi oltre a math.stackexchange.com potrebbero essere meglio equipaggiati per aiutarti in questo. –

risposta

5

In prima approssimazione, calcolare la radius of curvature del vostro Bezier curve. Se l'offset è maggiore o uguale al raggio di curvatura, dovresti cercare un nodo.

In particolare, per una Bezier cubica con punti di controllo P0, P1, P2, P3:

B(t) = P0 * (1-t)^3 + P1 * 3*t*(1-t)^2 + P2 * 3*t^2*(1-t) + P3 * t^3 
-> B'(t) = (P1-P0) * 3*(1-t)^2 + (P2-P1) * 6*t*(1-t) + (P3-P2) * 3*t^2 
-> B''(t) = (P2+P0-2*P1) * 6*(1-t) + (P3+P1-2*P2) * 6*t 

let: cross2d(p, q) = p.x*q.y - p.y*q.x 
then, radius of curvature = |B'(t)|^3/cross2d(B'(t), B''(t)) 

ho lasciato il raggio di curvatura in forma firmata; il segno dovrebbe indicare il lato della curva su cui ci si può aspettare il nodo.

Nota: è possibile avere un raggio di curvatura pari a zero o un raggio di curvatura infinito; potrebbe essere meglio confrontare |B'(t)|^3 con signed_offset * cross2d(B'(t), B''(t)) invece.

+0

Fantastico. Sembra che funzionerà. Farò un tentativo e tornerò da te. Potrebbe portarmi un po '.:) +1 –

+0

Perdonami se questa è una domanda stupida ma come ho detto che la matematica non è il mio forte seme. Mentre la tua funzione cross2d (p, q) prende atto che i miei punti P sono x e y coordina le funzioni B, B 'e B' 'no. Questo significa che ho eseguito questi una sola volta per ciascun asse? –

+0

'B (t)', 'B '(t)' e 'B' '(t)' dovrebbero essere vettori 2D, proprio come 'P0',' P1', 'P2' e' P3' . Inoltre, nota che '| B '(t) |' dovrebbe prendere la lunghezza del vettore 2-D. Probabilmente è meglio usare una struttura 'Vector2' (o qualsiasi struttura esistente che stai usando per i tuoi punti 2-D), quindi non devi ricalcolare le ponderazioni di Bézier più volte. Tuttavia, puoi scrivere funzioni scalari ed eseguirle per ciascun asse se lo desideri. Basta tenere a mente che sarà necessario rimetterli insieme per calcolare la lunghezza del vettore e cross2d(). – comingstorm