Array to SVG, algorithm flessibile con PHP

problema: ho un paio di arrays diversi, ad esempio:

il mio problema ora è: sto cercando un algorithm per calcolare un path SVG per un grafico semplice come: inserisci la descrizione dell'immagine qui

il mio problema attuale è l'algorithm generale e il calcolo della viewbox per each SVG.

al momento ho memorizzato un esempio come:

{ "path": ".....", "min_value": 2, // min. value of arrays "max_value": 31, // max. value of arrays "raw_data": [2, 3, 3, 5, 25, 31], } 

EDIT: Ora ho aggiunto il calcolo dinamico dei passi come: $step = (($width/$height) * (max($points)-min($points)))/count($points);

quindi il codice attuale sembra:

 $width=200; $height=50; $paths = ''; $i= 0; $j = 0; $step = (($width/$height) * (max($points)- min($points)))/count($points); foreach($points as $point) { if($j == 0) { $paths = 'M 0 '.$point; } else if($j == 1) { $paths .= ' L '.$i.' '.$point; } else { $paths .= ' '.$i.' '.$point; } $i+=$step; $j++; } $viewbox = '0 0 '.(count($points)+1).' '.(max($points)+1); 

ora sembra molto meglio, ma ha ancora il seguente problema: piccoli valori (tutti <1.0) e stroke-width = 1px: inserisci la descrizione dell'immagine qui

 <svg width="200" height="50" viewBox="0 0 31 1.99" style="background-color: white;"> <path fill="none" stroke="blue" stroke-width="1px" d="M 0 0.91 L 0.12333333333333 0.16 0.24666666666667 0.285 0.37 0.845 0.49333333333333 0.87 0.61666666666667 0.14 0.74 0.935 0.86333333333333 0.955 0.98666666666667 0.51 1.11 0.855 1.2333333333333 0.41 1.3566666666667 0.97 1.48 0.115 1.6033333333333 0.095 1.7266666666667 0.885 1.85 0.49 1.9733333333333 0.83 2.0966666666667 0.115 2.22 0.555 2.3433333333333 0.99 2.4666666666667 0.23 2.59 0.21 2.7133333333333 0.14 2.8366666666667 0.265 2.96 0.435 3.0833333333333 0.11 3.2066666666667 0.485 3.33 0.725 3.4533333333333 0.48 3.5766666666667 0.065"/> </svg> 

valori grandi (tutti> 1000.0) e width del tratto = 100 px: inserisci la descrizione dell'immagine qui

 <svg width="200" height="50" viewBox="0 0 31 4797.885" style="background-color: white;"> <path fill="none" stroke="blue" stroke-width="1px" d="M 0 3401.91 L 185.99666666667 3515.16 371.99333333333 4007.285 557.99 4149.845 743.98666666667 4141.87 929.98333333333 4176.14 1115.98 4227.935 1301.9766666667 4416.955 1487.9733333333 4594.51 1673.97 4486.855 1859.9666666667 4302.41 2045.9633333333 4413.97 2231.96 4584.115 2417.9566666667 4740.095 2603.9533333333 4796.885 2789.95 4629.49 2975.9466666667 4567.83 3161.9433333333 4484.115 3347.94 4383.555 3533.9366666667 4363.99 3719.9333333333 4362.23 3905.93 4352.21 4091.9266666667 4236.14 4277.9233333333 4120.265 4463.92 4049.435 4649.9166666667 4046.11 4835.9133333333 4138.485 5021.91 4165.725 5207.9066666667 4242.48 5393.9033333333 4358.065"/> </svg> 929,98333333333 4176,14 1115,98 4227,935 1301,9766666667 4416,955 1487,9733333333 4594,51 1673,97 4486,855 1859,9666666667 4302,41 2045,9633333333 4413,97 2231,96 4584,115 <svg width="200" height="50" viewBox="0 0 31 4797.885" style="background-color: white;"> <path fill="none" stroke="blue" stroke-width="1px" d="M 0 3401.91 L 185.99666666667 3515.16 371.99333333333 4007.285 557.99 4149.845 743.98666666667 4141.87 929.98333333333 4176.14 1115.98 4227.935 1301.9766666667 4416.955 1487.9733333333 4594.51 1673.97 4486.855 1859.9666666667 4302.41 2045.9633333333 4413.97 2231.96 4584.115 2417.9566666667 4740.095 2603.9533333333 4796.885 2789.95 4629.49 2975.9466666667 4567.83 3161.9433333333 4484.115 3347.94 4383.555 3533.9366666667 4363.99 3719.9333333333 4362.23 3905.93 4352.21 4091.9266666667 4236.14 4277.9233333333 4120.265 4463.92 4049.435 4649.9166666667 4046.11 4835.9133333333 4138.485 5021.91 4165.725 5207.9066666667 4242.48 5393.9033333333 4358.065"/> </svg> 3161,9433333333 4484,115 3347,94 4383,555 3533,9366666667 4363,99 3719,9333333333 4362,23 3905,93 4352,21 4091,9266666667 4236,14 4277,9233333333 4120,265 4463,92 4049,435 4649,9166666667 4046,11 4835,9133333333 4138,485 5021,91 4165,725 5207,9066666667 4242,48 5393,9033333333 4358,065 <svg width="200" height="50" viewBox="0 0 31 4797.885" style="background-color: white;"> <path fill="none" stroke="blue" stroke-width="1px" d="M 0 3401.91 L 185.99666666667 3515.16 371.99333333333 4007.285 557.99 4149.845 743.98666666667 4141.87 929.98333333333 4176.14 1115.98 4227.935 1301.9766666667 4416.955 1487.9733333333 4594.51 1673.97 4486.855 1859.9666666667 4302.41 2045.9633333333 4413.97 2231.96 4584.115 2417.9566666667 4740.095 2603.9533333333 4796.885 2789.95 4629.49 2975.9466666667 4567.83 3161.9433333333 4484.115 3347.94 4383.555 3533.9366666667 4363.99 3719.9333333333 4362.23 3905.93 4352.21 4091.9266666667 4236.14 4277.9233333333 4120.265 4463.92 4049.435 4649.9166666667 4046.11 4835.9133333333 4138.485 5021.91 4165.725 5207.9066666667 4242.48 5393.9033333333 4358.065"/> </svg> 

tutti i grafici dovrebbero utilizzare il 100% dello spazio in width e altezza con la stessa width del tratto.

Quanto è difficile generare un path SVG ? Ecco un esempio di SVG :

 <svg width="512" height="512" viewBox="-3.775377 -42.30107 144.356959 147.801089" > <path fill="none" stroke="blue" stroke-width="1px" transform="matrix(1,0,0,1,0,0)" d="M 70 30 q 0.466506 0.468696 1.055021 -0.160683 q 0.529113 -0.764957 -0.278312 -1.82735 q -0.968481 -1.043055 -2.776709 -0.511966 q -1.848076 0.710151 -2.220084 3.142734 q -0.198986 2.550856 2.278312 4.32735 q 2.680178 1.650105 5.941772 0.029915 q 3.229646 -1.888998 3.385148 -6.124785 q -0.13114 -4.336754 -4.278312 -6.82735 q -4.391875 -2.257156 -9.106836 0.452135 q -4.611215 3.067846 -4.550211 9.106836 q 0.461267 6.122652 6.278312 9.32735 q 6.103572 2.864207 12.2719 -0.934186 q 5.992785 -4.246694 5.715275 -12.088886 q -0.791394 -7.908551 -8.278312 -11.82735 q -7.815269 -3.471258 -15.436963 1.416237 q -7.374355 5.425541 -6.880338 15.070937 q 1.121521 9.694449 10.278312 14.32735 q 9.526965 4.078309 18.602026 -1.898287 q 8.755925 -6.604389 8.045402 -18.052988 q -1.451648 -11.480347 -12.278312 -16.82735 q -11.238662 -4.685359 -21.76709 2.380338 q -10.137495 7.783236 -9.210465 21.035039 q 1.781775 13.266246 14.278312 19.32735 q 12.950359 5.29241 24.932153 -2.862389 q 11.519065 -8.962084 10.375529 -24.01709 q -2.111902 -15.052144 -16.278312 -21.82735 q -14.662056 -5.899461 -28.097217 3.34444 q -12.900635 10.140931 -11.540592 26.99914 q 2.442029 16.838043 18.278312 24.32735 q 16.373753 6.506512 31.26228 -3.826491 q 14.282204 -11.319779 12.705656 -29.981191 q -2.772156 -18.623941 -20.278312 -26.82735 q -18.08545 -7.113563 -34.427344 4.308541 q -15.663774 12.498627 -13.870719 32.963242 q 3.102283 20.409839 22.278312 29.32735 q 19.797147 7.720613 37.592407 -4.790592 q 17.045344 -13.677474 15.035783 -35.945293 q -3.43241 -22.195738 -24.278312 -31.82735 q -21.508844 -8.327664 -40.757471 5.272643 q -18.426914 14.856322 -16.200846 38.927344 q 3.762537 23.981636 26.278312 34.32735 q 23.22054 8.934715 42.922534 -5.754694 q 19.808484 -16.035169 17.36591 -41.909394 q -4.092664 -25.767535 -28.278312 -36.82735 q -24.932237 -9.541766 -47.087598 6.236745 q -21.190054 17.214017 -18.530973 44.891445 q 4.422791 27.553433 30.278312 39.32735 q 26.643934 10.148817 50.252661 -6.718795 q 22.571624 -18.392864 19.696037 -47.873496 q -4.752918 -29.339331 -32.278312 -41.82735 q -28.355631 -10.755867 -53.417725 7.200846 q -23.953193 19.571712 -20.8611 50.855547 q 5.083045 31.12523 34.278312 44.32735 q 30.067328 11.362918 56.582788 -7.682897 q 25.334763 -20.75056 22.026164 -53.837598 q -5.413172 -32.911128 -36.278312 -46.82735 q -31.779025 -11.969969 -59.747852 8.164948 q -26.716333 21.929407 -23.191227 56.819648 q 5.7433 34.697026 38.278312 49.32735 q 33.490722 12.57702 62.912915 -8.647 "/> </svg> 

Quindi, codifica l'intestazione e i tag in modo così semplice … e poi crea la parte d="" compresi i punti del tuo path … Inizia con il command M sposta e poi per il resto usa solo L (row su, Non è necessario ripetere il command L finché non viene utilizzato un command diverso). Maiuscolo significa coordinate assolute e comandi minuscoli significa coordinate relative. Qui anteprima:

anteprima

Vedi le specifiche SVG per l'utilizzo dei comandi di path … Se i tuoi dati contengono punti x, y, allora sarebbe come questo:

 d="M x0,y0 L x1 y1 x2 y2 x3 y3 ... xn yn" 

Quindi basta creare uno script php che generi tale contenuto dall'arrays.

La parte importnte è la viewBox e la vista che definisce la vista del browser. Se non è impostato correttamente o affatto, alcuni brownser non renderanno correttamente il tuo SVG .

Usando l'arrays campione e x-step = 1 ho ottenuto:

 x = { 0,1,2,3, 4, 5 } y = { 2,3,3,5,25,31 } 

quindi usa x=<-1,+6> e y=<1,32> come riquadro di visualizzazione (min max + qualche bordo):

 <svg width="512" height="512" viewBox="-1 1 6 32" > <path fill="none" stroke="blue" stroke-width="1px" transform="matrix(1,0,0,1,0,0)" d="M 0 2 L 1 3 2 3 3 5 4 25 5 31"/> </svg> 

anteprima

Come puoi vedere, l'asse Y sta scendendo, puoi aggiustare le posizioni y o usare la matrix per quello …

[Edit2] Ho creato script C ++ / VCL (come promesso) per questo

  { int xs=512,ys=256; // view resolution float x0,x1,y0,y1; // data bbox float x,dx,px; AnsiString svg; float data[]={ 3401.91, 3515.16, 4007.285, 4149.845, 4141.87, 4176.14, 4227.935, 4416.955, 4594.51, 4486.855, 4302.41, 4413.97, 4584.115, 4740.095, 4796.885, 4629.49, 4567.83, 4484.115, 4383.555, 4363.99, 4362.23, 4352.21, 4236.14, 4120.265, 4049.435, 4046.11, 4138.485, 4165.725, 4242.48, 4358.065 }; // float data[]={ 0.21, 0.001, 0.0245, 0.31, 0.05 }; // float data[]={ 1234, 1342, 1232, 1625, 2200, 2205, 1804 }; // float data[]={ 5, 12, 42, 2, 32, 42 }; int i,n=sizeof(data)/(sizeof(data[0])); y0=data[0]; y1=y0; for (i=0;i<n;i++) { if (y0>data[i]) y0=data[i]; if (y1<data[i]) y1=data[i]; } x0=0.0; x1=x0+((y1-y0)*float(xs)/float(ys)); dx=(x1-x0)/float(n); px=(x1-x0)/float(xs); svg="<svg width=\""+AnsiString(xs)+"\" height=\""+AnsiString(ys)+"\"" +" viewBox=\""+AnsiString(x0)+" "+AnsiString(y0)+" "+AnsiString(x1-x0)+" "+AnsiString(y1-y0)+"\">\r\n" +" <path fill=\"none\" stroke=\"black\" stroke-width=\""+AnsiString(px)+"px\" transform=\"matrix(1,0,0,1,0,0\" d=\"M "+AnsiString(x0)+" "+AnsiString(y0)+" L"; for (x=x0+dx,i=0;i<n;i++,x+=dx) { svg+=" "+AnsiString(x)+" "+AnsiString(data[i]); if ((i&3)==3) svg+="\r\n "; } svg+="\"/>\r\n"; svg+="</svg>\r\n"; Memo1->Text=svg; i=FileCreate("test.svg"); FileWrite(i,svg.c_str(),svg.Length()); FileClose(i); } 

Qui output:

 <svg width="512" height="256" viewBox="0 3401.90991210938 2789.94970703125 1394.97485351563"> <path fill="none" stroke="black" stroke-width="5.44912052154541px" transform="matrix(1,0,0,1,0,0" d="M 0 3401.90991210938 L 92.9983215332031 3401.90991210938 185.996643066406 3515.15991210938 278.994964599609 4007.28491210938 371.993286132813 4149.84521484375 464.991607666016 4141.8701171875 557.989929199219 4176.14013671875 650.98828125 4227.93505859375 743.986572265625 4416.955078125 836.98486328125 4594.509765625 929.983154296875 4486.85498046875 1022.9814453125 4302.41015625 1115.97973632813 4413.97021484375 1208.97802734375 4584.115234375 1301.97631835938 4740.09521484375 1394.974609375 4796.884765625 1487.97290039063 4629.490234375 1580.97119140625 4567.830078125 1673.96948242188 4484.115234375 1766.9677734375 4383.55517578125 1859.96606445313 4363.990234375 1952.96435546875 4362.22998046875 2045.96264648438 4352.2099609375 2138.9609375 4236.14013671875 2231.95922851563 4120.26513671875 2324.95751953125 4049.43505859375 2417.95581054688 4046.11010742188 2510.9541015625 4138.48486328125 2603.95239257813 4165.72509765625 2696.95068359375 4242.47998046875 2789.94897460938 4358.06494140625"/> </svg> 

anteprima

Hai dimenticato la transform e hai anche bisogno di impostare correttamente la width del tratto px .