2012-01-07 1 views
6

Supponendo che abbia funzioni come x² o 2x + 3x² come si fa a creare un percorso SVG adatto a queste funzioni ?.Adattare una curva SVG a un polinomio

Dalla mia comprensione limitata di SVG e Bezier curve credo sto cercando per è una tecnica semplice da costruire i punti di controllo di Bezier che farà in modo che il grafico risultante si adatta alla funzione data. Puoi tranquillamente supporre (se non l'hai già indovinato) che sono un principiante nella programmazione grafica. So che framework come gnuplot possono eseguire questo tipo di interpolazione ma sto cercando una spiegazione su come farlo a mano usando SVG e JavaScript.

MODIFICA: Un adattamento esatto non è un requisito rigoroso, ma il grafico risultante deve essere ragionevolmente accurato (per scopi didattici).

+0

io non sono sicuro se è possibile * esattamente * descrivere un polinomio con una curva di Bézier di nella stessa misura. – CodesInChaos

+0

@CodeInChaos ottimo feedback, per curiosità come fanno le persone a tracciare un polinomio con SVG ?, l'ho visto fare ma non sono sicuro di come le persone passano da una funzione all'altra. L'esatto adattamento non è un requisito rigoroso, anche se il grafico deve essere ragionevolmente accurato. –

+0

Suppongo che lo rappresentino graficamente come qualsiasi altra funzione: calcola il valore della funzione in molti punti lungo la curva (circa 1000) e quindi adatta una funzione attraverso di essa. È il caso più semplice con le linee, ma con le curve bézier di grado più elevato avrà sicuramente un aspetto migliore, ma non ricordo un modo conveniente per calcolare i punti di controllo. – CodesInChaos

risposta

8
<?xml version="1.0" standalone="no"?> 

SVG fornisce le curve di Bézier di ordini 2 e 3, che dovrebbe essere abbastanza buona per polinomi quadratiche e cubiche.

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
    "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> 
<svg width="20cm" height="20cm" viewBox="0 0 1000 1000" 
    xmlns="http://www.w3.org/2000/svg" version="1.1"> 
    <style type="text/css"><![CDATA[ 
    .axis { fill: none; stroke: black; stroke-width: 3; } 
    .tick { fill: none; stroke: black; stroke-width: 1; } 
    .fun1 { fill: none; stroke: blue; stroke-width: 2; } 
    .fun2 { fill: none; stroke: red; stroke-width: 2; } 
    ]]></style> 
    <polyline class="axis" points="0,500 1000,500" /> 
    <polyline class="tick" points="0,490 0,510" /> 
    <polyline class="tick" points="100,490 100,510" /> 
    <polyline class="tick" points="200,490 200,510" /> 
    <polyline class="tick" points="300,490 300,510" /> 
    <polyline class="tick" points="400,490 400,510" /> 
    <polyline class="tick" points="600,490 600,510" /> 
    <polyline class="tick" points="700,490 700,510" /> 
    <polyline class="tick" points="800,490 800,510" /> 
    <polyline class="tick" points="900,490 900,510" /> 
    <polyline class="tick" points="1000,490 1000,510" /> 
    <polyline class="axis" points="500,0 500,1000" /> 
    <polyline class="tick" points="490,0 510,0" /> 
    <polyline class="tick" points="490,100 510,100" /> 
    <polyline class="tick" points="490,200 510,200" /> 
    <polyline class="tick" points="490,300 510,300" /> 
    <polyline class="tick" points="490,400 510,400" /> 
    <polyline class="tick" points="490,600 510,600" /> 
    <polyline class="tick" points="490,700 510,700" /> 
    <polyline class="tick" points="490,800 510,800" /> 
    <polyline class="tick" points="490,900 510,900" /> 
    <polyline class="tick" points="490,1000 510,1000" /> 

asporto y = x² - 4, con gli endpoint (-3, 5) e (3, 5); le tangenti sono y = -6x - 13 ey = 6x - 13. Posizionare il punto di controllo Q su entrambe le tangenti, a (0, -13). Questo dovrebbe funzionare facilmente per qualsiasi quadratico.

<path class="fun1" d="M200,0 Q500,1800 800,0" /> 

I cubi sono un po 'più complicati. Con y = (x³ - 9x)/16 da (-5, -5) a (5, 5), le tangenti sono y = (33x + 125)/8 ey = (33x - 125)/8. Vedendo che la curva deve passare attraverso (0, 0) con slope -9/16, è un semplice calcolo per trovare i punti di controllo C (-5/3, 35/4) e (5/3, 35/4). Probabilmente non è fattibile a mano per la maggior parte del tempo ma penso che questo approccio dovrebbe essere numericamente fattibile per qualsiasi altro cubico - due variabili per quanto distano lungo ogni tangente i punti di controllo, e due vincoli che costringono un particolare punto e direzione.

<path class="fun2" d="M0,1000 C333,-375 667,1375 1000,0" /> 

(Animated Bézier Curves è stato molto utile quando stavo lavorando questi fuori.)

</svg> 

+0

Risposta fantastica. Ho ragione nell'osservare che non c'è generalizzazione nei polinomi di ordine superiore (a parte cucire insieme una tonnellata di piccole linee rette?). –

+0

@LarsTackmann, se SVG avesse ordine Béziers, mi aspetterei di poter disegnare polinomi quartici e così via. Ma questo si complicherebbe rapidamente. L'uso delle spline di Bézier (dovrebbe essere in grado di eguagliare la prima e la seconda derivata) sembrerebbe più bello dei segmenti di linea, ma in entrambi i casi, non sarebbe esatto. – ephemient