オンラインでグラフィックを描く

それはすべて、3、4年前に私がJavaで自分のパーサーと数式の計算機-jExpressionsを書いたという事実から始まりました。



そして今、比較的最近、Java EEテクノロジーを習得するという観点から、このパーサーに基づいてオンラインでグラフを描くというアイデアが生まれました。



当時のパーサーには、関数を呼び出すためのかなりエキゾチックな構文がありました(たとえば、exp(3)の代わりにexp#3、beta#1:2の代わりにbeta(1:2))。

また、時々バグが発生しました。



数時間の仕上げと非アクティブ化の後、バージョンjExpressions 1.0が生まれました



その後、仕事に取りかかることができました。





チャートの描画は次のように配置されます。



1.サーブレットは、N番目のポイント(単純な場合は250、パラメトリックな場合は1000)の関数値を計算し、結果をjson形式で提供します。

2. Webページはサーブレットからjsonを受け取り、Flotプラグインを使用してグラフを描画します。



サーブレットprocessRequest()関数コード:



private void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/plain;charset=UTF-8"); PrintWriter out = response.getWriter(); String result = "{ \"result\" : "; String func = request.getParameter("func"); String var = request.getParameter("variable"); String begin = request.getParameter("begin"); String end = request.getParameter("end"); if (func==null||var==null||begin==null||end==null) { result += "\"error\", \"err\" : \"param\"}"; out.println(result); return; } // upd: //Double x0 = Double.parseDouble(begin); //Double x1 = Double.parseDouble(end); Double x0; Double x1; try { x0 = Double.parseDouble(begin); x1 = Double.parseDouble(end); } catch (Exception e) { result += "\"error\", \"err\" : \"param\"}"; out.println(result); return; } int num = 0; try { Parser parser = new Parser(); num = parser.setAlias(var); //     long time0 = System.nanoTime(); Expr expr = parser.parseExpr(parser.prepareExpr(func)); //       String xArr = "["; String yArr = "["; long time1 = System.nanoTime(); for (int i=0; i<=points; i++) { if (i>0) { xArr += ", "; yArr += ", "; } Double x = x0 + ((x1-x0)/points)*i; parser.setVar(num, x); //    Double y = expr.evaluate(); //   xArr += x.toString(); yArr += y.toString(); } long time2 = System.nanoTime(); Integer parse_time = (int)((time1-time0)/1e6); Integer calc_time = (int)((time2-time1)/1e6); Integer total_time = (int)((time2-time0)/1e6); System.out.println("Parse time: "+parse_time.toString() +"; Calc time: "+calc_time.toString()); xArr += "]"; yArr += "]"; result += "\"ok\", \"time\" : \""+total_time.toString() +"\", \"x\" : \""+xArr+"\", \"y\" : \""+yArr+"\"}"; } catch (BadVarException e) { result += "\"error\", \"err\" : \"badvar\"}"; } catch (Exception e) { result += "\"error\", \"err\" : \"wrong\"}"; } finally { out.print(result); } }
      
      







プロット用のjsコード:



 window.getResult = function(func,variable,begin,end){ $('#draw').prop('disabled',true); $('#info').text(' ...'); $.post('/functions/calc', {func: func, variable: variable, begin: begin, end: end}, function(data){ window.result = $.parseJSON(data); if (result.result == 'error') { if (result.err == 'wrong') $('#info').text('  '); if (result.err == 'badvar') $('#info').text('  '); $('#draw').prop('disabled',false); return; } window.xArr = $.parseJSON(result.x); result.y = result.y .split('-Infinity').join('null') .split('Infinity').join('null') .split('NaN').join('null'); window.yArr = $.parseJSON(result.y); window.data = []; for (i=0; i<xArr.length; i++) { y = window.yArr[i]; window.data[i] = [window.xArr[i],window.yArr[i]]; } window.drawFunc(); var millis = result.time%1000; var sec = (result.time-millis)/1000; $('#info').text('  '+sec+'.'+millis+' '); $('#draw').prop('disabled',false); }); }; window.drawFunc = function() { var data_arr = []; data_arr[0] = {data:window.data, color:'#f00'}; $.plot($('#graph'),data_arr); };
      
      







結果ここ (単純な関数)とここ (パラメトリック)で見ることができます。



注:サーバーはRaspberry Pi上で回転しているため、動作が非常に遅くなります。




All Articles