Let's take a look at the code i wrote for the very first graph of a basic DC signal:
$(function() {
  var renderer = dsp_graph.initCanvas('#canvas-dc', null);
  var stage = new PIXI.Container();
  dsp_graph.drawPositiveAxis(stage);
  var graphics = new PIXI.Graphics();
  graphics.lineStyle(2, 0x00bbdd, 1);
  graphics.moveTo(15, 150);
  graphics.lineTo(535, 150);
  stage.addChild(graphics);
  animate();
  function animate() {
    renderer.render(stage);
  }
});The next issue is that I've used a bunch of magic numbers in drawing the DC curve (a straight line, really). It looks innocent enough when it's just a few lines with numbers in them in a small function, but these numbers hide a problem that will continue to grow as the graphs get more complicated. There's a coordinate offset hidden in these numbers because of the margins outside of the graph axes, and things will be much simpler later if I create an origin for the axes and a set graph unit size that can be used throughout the drawing code to draw curves on axes with an origin of (0, 0). Luckily, any decent graphics library has a transform function, and PixiJS is no exception. I can set up a transform on the graphics object that is used to draw the DC curve:
$(function() {
  var renderer = dsp_graph.initCanvas('#canvas-dc', null);
  var stage = new PIXI.Container();
  dsp_graph.drawPositiveAxis(stage);
  var graphics = new PIXI.Graphics();
  stage.addChild(graphics);
  graphics.setTransform(15, 280, 26, -26);
  graphics.lineStyle(2/26.0, 0x00bbdd, 1);
  graphics.moveTo(0, 5);
  graphics.lineTo(20, 5);
  renderer.render(stage);
});    createCurve: function(stage) {
      var curve = new PIXI.Graphics();
      stage.addChild(curve);
      curve.setTransform(15, 280, 26, -26);
      return curve;
    },      stage.origin = {x: X_AXIS_START, y: Y_AXIS_END};
    createCurve: function(stage) {
      var curve = new PIXI.Graphics();
      stage.addChild(curve);
      curve.setTransform(stage.origin.x, stage.origin.y, TICK_STEP, -TICK_STEP);
      return curve;
    },    drawCurve: function(curve, color, points) {
      curve.lineStyle(2.0/TICK_STEP, color, 1);
      curve.moveTo(points.x[0], points.y[0]);
      for (var i = 1; i < points.x.length; i++) {
        curve.lineTo(points.x[i], points.y[i]);
      }
    },$(function() {
  var renderer = dsp_graph.initCanvas('#canvas-dc', null);
  var stage = new PIXI.Container();
  dsp_graph.drawPositiveAxis(stage);
  var dc_signal = dsp_graph.createCurve(stage);
  dsp_graph.drawCurve(dc_signal, 0x00bbdd, {x:[0, 20], y:[5, 5]});
  renderer.render(stage);
});Cleaning up Animation
The next graph, the impulse function, is the first animated graph, so we'll have some additional things to refactor to try to make setting up an animation a little cleaner. In the interest of brevity, I'll show each new graph code with the changes from previous refactorings already applied. There's no need to be verbose about API improvements that we've just gone over, and it would take forever to show them anyway. As we add more functionality to the API, it should get easier and easier to clean up the later graph code. Here's the updated code for the animated impulse graph:
$(function() {
  var renderer = dsp_graph.initCanvas('#canvas-impulse', null);
  var stage = new PIXI.Container();
  dsp_graph.drawPositiveAxis(stage);
  var impulse = dsp_graph.createCurve(stage);
  var t = 20;
  animate();
  function animate() {
    t -= 0.08;
    if (t < 0) t = 20;
    impulse.clear();
    dsp_graph.drawCurve(impulse, 0x00bbdd, {x:[0, t, t, t, 20], y:[1, 1, 9, 1, 1]})
    renderer.render(stage);
    requestAnimationFrame( animate );
  }
});  (function animate() {
    t -= 0.08;
    if (t < 0) t = 20;
    impulse.clear();
    dsp_graph.drawCurve(impulse, 0x00bbdd, {x:[0, t, t, t, 20], y:[1, 1, 9, 1, 1]})
    renderer.render(stage);
    requestAnimationFrame( animate );
  }());Next Up, the Sine Function
The next graph of the step function doesn't show anything new, so let's move on to the graph of the sine function. Here's what the code looks like with the latest improvements:
$(function() {
  var renderer = dsp_graph.initCanvas('#canvas-sine', null);
  var stage = new PIXI.Container();
  dsp_graph.drawZeroAxis(stage);
  var sinewave = dsp_graph.createCurve(stage);
  var t = 20;
  var amplitude = 4;
  (function animate() {
    t += 0.08;
    if (t > 20) t = 0;
    sinewave.clear();
    sinewave.lineStyle(2/26.0, 0x00bbdd, 1);
    var y = amplitude*Math.sin((t)/10.0*Math.PI);
    sinewave.moveTo(0, y);
    for (var x = 0.5; x <= 20; x+=0.5) {
      y = amplitude*Math.sin((x+t)/10.0*Math.PI);
      sinewave.lineTo(x, y);
    }
    renderer.render(stage);
    requestAnimationFrame( animate );
  }());
});    drawSine: function(sinewave, amplitude, offset, freq, phase, start, end) {
      start = typeof start != 'undefined' ? start : 0
      end = typeof end != 'undefined' ? end : 520
      var step = freq > 0.1 ? 12/freq : (freq < -0.1 ? 12/-freq : 104);
      var y = amplitude*Math.sin((start*freq + phase)/260.0*Math.PI) + offset;
      sinewave.moveTo(start, -y);
      for (var x = start; x < end; x+=step) {
        y = amplitude*Math.sin((x*freq + phase)/260.0*Math.PI) + offset;
        sinewave.lineTo(x, -y);
        sinewave.moveTo(x, -y);
      }
      y = amplitude*Math.sin((end*freq + phase)/260.0*Math.PI) + offset;
      sinewave.lineTo(end, -y);
    },    generateSine: function(amplitude, offset, freq, phase, start, end) {
      var step = Math.abs(freq) > 0.1 ? 0.5/Math.abs(freq) : 5;
      var points = {x:[],y:[]};
      for (var x = start; x <= end; x+=step) {
        points.x.push(x);
        points.y.push(amplitude*Math.sin((x*freq + phase)/10.0*Math.PI) + offset);
      }
      return points;
    },    drawSine: function(sinewave, color, amplitude, offset, freq, phase, start, end) {
      start = typeof start != 'undefined' ? start : 0
      end = typeof end != 'undefined' ? end : 20
      var points = this.generateSine(amplitude, offset, freq, phase, start, end);
      this.drawCurve(sinewave, color, points);
    },The last graph in this post has been nicely simplified with this refactoring:
$(function() {
  var renderer = dsp_graph.initCanvas('#canvas-sine', null);
  var stage = new PIXI.Container();
  dsp_graph.drawZeroAxis(stage);
  var sinewave = dsp_graph.createCurve(stage);
  var t = 20;
  (function animate() {
    t += 0.08;
    if (t > 20) t = 0;
    sinewave.clear();
    dsp_graph.drawSine(sinewave, 0x00bbdd, 4, 0, 1, t);
    renderer.render(stage);
    requestAnimationFrame( animate );
  }());
});
No comments:
Post a Comment