DZone Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

Snippets has posted 5883 posts at DZone. View Full User Profile

Wave Plotter //Pascal Class

06.15.2006
| 5834 views |
  • submit to reddit
        A wave plotter component that is able to draw sin, poly and squared lines, I used this in a osciloscope xD

I didn't liked this code, but the draw part (TWaveShape.paint) is looking cool, I used the same "X" coord to draw the 3 kinds of lines :)

I mean:

loop(x){
  case waveType of
    wtSin: y := lala;
    wtPoly: y := lele;
    wtSqr: y := lili;
  end;
}

unit WavePlotter;

interface

uses
  forms, dialogs, SysUtils, Classes, Controls, Graphics;

const
  PI2 = PI * 2;

type
  TWaveType = ( wtSqr, wtPoly, wtSin );

  TWave = class( TPersistent )
  public
    waveType: TWaveType;
    color: TColor;
    offset: integer;
    frequency, amplitude, volts, interval, gain: extended;

    procedure AssignTo(Dest: TPersistent); override;
  end;

  TWaveShape = class( TGraphicControl )
  protected
    fWaves: TList;
    fBoxSize: integer;
    fLineColor: TColor;

    function getWave(const index: integer): TWave;
    procedure setBoxSize(const Value: integer);

    function getBackgroundColor: TColor;
    procedure setBackgroundColor(const Value: TColor);
    procedure setLineColor(const Value: TColor);

  public
    constructor create( AOwner: TComponent ); override;
    destructor destroy; override;

    procedure clear;
    procedure delete( const index: integer );

    function add: integer;

    property waves[ const index: integer]: TWave read GetWave;

  published
    procedure paint; override;
    property boxSize: integer read fBoxSize write setBoxSize;
    property backgroundColor: TColor read getBackgroundColor write setBackgroundColor;
    property lineColor: TColor read fLineColor write setLineColor;

    //inherited
    //property Canvas;
    property Align;
    property Anchors;
    property Constraints;
    property DragCursor;
    property DragKind;
    property DragMode;
    property Enabled;
    //property Font;
    property ParentColor;
    //property ParentFont;
    property ParentShowHint;
    property PopupMenu;
    property ShowHint;
    property Visible;
    property OnClick;
    property OnContextPopup;
    property OnDblClick;
    property OnDragDrop;
    property OnDragOver;
    property OnEndDock;
    property OnEndDrag;
    property OnMouseDown;
    property OnMouseMove;
    property OnMouseUp;
    property OnStartDock;
    property OnStartDrag;
  end;

implementation

function max( const a, b: integer ): integer;
begin
  if a > b then
    result := a
  else
    result := b;
end;

{ TWaveShape }

function TWaveShape.add: integer;
begin
  result := fWaves.add( TWave.Create );
end;

procedure TWaveShape.clear;
begin
  while fWaves.count > 0 do begin
    TWave( fWaves[0] ).free;
    fWaves.delete( 0 );
  end;
end;

constructor TWaveShape.create(AOwner: TComponent);
begin
  inherited;
  fWaves := TList.create;
  fLineColor := clGray;
  color := clBtnFace;
  fBoxSize := 50;
end;

procedure TWaveShape.delete(const index: integer);
begin
  if ( index > -1 ) and ( index < fWaves.count ) then begin
    TWave( fWaves[index] ).free;
    fWaves.delete( index );
  end;
end;

destructor TWaveShape.destroy;
begin
  fWaves.free;
  inherited;
end;

function TWaveShape.getBackgroundColor: TColor;
begin
  result := color;
end;

function TWaveShape.getWave(const index: integer): TWave;
begin
  result := nil;
  if ( index > -1 ) and ( index < fWaves.count ) then
    result := TWave( fWaves[ index ] );
end;

procedure TWaveShape.paint;
var
  k, x: integer;
  lastX, lastY: array of integer;
  y: extended;
begin
  if not enabled then
    exit;
  canvas.brush.color := color;
  canvas.fillRect( clientRect );

  setLength( lastY, fWaves.count );
  setLength( lastX, fWaves.count );
  for k := 0 to high( lastY ) do begin
    lastY[k] := clientHeight div 2 + waves[k].offset;
    lastX[k] := 0;
  end;

  for x := 0 to max( clientWidth, clientHeight ) do begin
    with canvas do begin
      pen.color := fLineColor;
      pen.width := 1;
      pen.style := psDot;

      if x mod fBoxSize = 0 then begin
        moveTo( 0, x + trunc( frac( clientHeight / 2 / fBoxSize ) * fBoxSize ) );
        lineTo( clientWidth, x + trunc( frac( clientHeight / 2 / fBoxSize ) * fBoxSize ) );

        moveTo( x, 0 );
        lineTo( x, clientHeight );
      end;

      for k := 0 to fWaves.count - 1 do begin
        with waves[k] do begin
          pen.color := color;
          pen.width := 1;
          pen.style := psSolid;

          y := pi*k + PI2 * x * interval / fBoxSize * frequency;

          case waveType of
            wtSin:
              y := sin( y );
            wtPoly: begin
              y := frac( y / PI2 );
              if y <= 0.25 then
                y := y / 0.25
              else if y <= 0.75 then
                y := ( -y + 0.5 ) / 0.25
              else
                y := ( y - 1 ) / 0.25;
            end;
            wtSqr: begin
              if frac( y / PI2 ) <= 0.5 then
                y := 1
              else
                y := -1;
            end;
          end;
          y := ( y * ( fBoxSize / volts ) * amplitude * gain ) + clientHeight / 2 + offset;
          moveTo( lastX[k], lastY[k] );
          lastX[k] := x;
          lastY[k] := trunc( y );
          lineTo( x, lastY[k] );
        end;
      end;
    end;
  end;
end;

procedure TWaveShape.setBackgroundColor(const Value: TColor);
begin
  color := Value;
  Invalidate;
end;

procedure TWaveShape.setBoxSize(const Value: integer);
begin
  fBoxSize := Value;
  invalidate;
end;


procedure TWaveShape.setLineColor(const Value: TColor);
begin
  fLineColor := Value;
  Invalidate;
end;

{ TWave }

procedure TWave.AssignTo(Dest: TPersistent);
begin
  if Dest.ClassType <> TWave then
    inherited;
  with TWave( Dest ) do begin
    waveType := self.waveType;
    color := self.color;
    offset := self.offset;
    frequency := self.frequency;
    amplitude := self.amplitude;
    volts := self.volts;
    interval := self.interval;
    gain := self.gain;
  end;
end;

end.