Hi James,

On 24/06/2013 20:23, James Lynes wrote:
Should be easy to
pull the generated file into a PaintDC if you don't want to launch an
outboard file viewer. I may or may not get to that.

I added a simple viewer to your code by:
1. changing your Graph method a little
2. adding display classes DisplayDialog and DisplayPanel

I though it would be useful to demo getting the raw data from your GD object and displaying it in a Wx::Panel without needing to save to a file. It also removes the need for an external viewer and is cross platform.

Hope it helps

Mark

#! /home/pete/CitrusPerl/perl/bin/perl

# ImpedanceGraph.pl
# Impedance calculator for Ls & Cs with graphic display
#
# Calculates the impedance for a range of frequencies and graphs.
#    Graph and save_chart borrowed(stolen) from GD::Graph sample51.pl
#
# James M. Lynes, Jr.
# Last Modified: June 24, 2013
#
package main;
use strict;
use warnings;
my $app = App->new();
$app->MainLoop;

package App;
use strict;
use warnings;
use base 'Wx::App';
sub OnInit {
    Wx::InitAllImageHandlers();
    my $frame = Frame->new();
    $frame->Show(1);
}

package DisplayPanel;
use strict;
use warnings;
use Wx qw(:everything);
use base qw(Wx::Panel);

use Wx::Event qw( EVT_PAINT );


sub new {
	my ($class, $parent, $bitmap) = @_;
	my $self = $class->SUPER::new($parent, -1, 
		wxDefaultPosition, 
		[ $bitmap->GetWidth, $bitmap->GetHeight ], 
		wxBORDER_NONE);
	
	$self->{bitmap} = $bitmap;
	EVT_PAINT($self, \&OnEvtPaint);
	return $self;
}

sub OnEvtPaint {
	my ($self, $event) = @_;
	my $dc = Wx::PaintDC->new($self);
    $dc->DrawBitmap($self->{bitmap}, 0,0,0);
}
	

package DisplayDialog;
use strict;
use warnings;
use Wx qw(:everything);
use base qw(Wx::Dialog);

sub new {
	my($class, $parent, $image) = @_;
	
	my $self = $class->SUPER::new($parent, -1, 'GD::Graph Image Display');
	
	my $bitmap = Wx::Bitmap->new($image);
	my $canvas = DisplayPanel->new($self, $bitmap);
	
	my $sizer = Wx::BoxSizer->new(wxVERTICAL);
	$sizer->Add($canvas,1,wxEXPAND|wxALL,0);
	$self->SetSizerAndFit($sizer);
	return $self;
	
}


package Frame;
use strict;
use warnings;
use Wx qw(:everything);
use base qw(Wx::Frame);
use Wx::Event qw(EVT_BUTTON EVT_CHOICE);
use GD::Graph::lines;
use Data::Dumper;

sub new {
    my($self) = @_;

    $self = $self->SUPER::new(undef, -1, "L or C Impedance Graph", 
                              wxDefaultPosition, wxDefaultSize);

    my @Inductors = ("nH", "uH", "mH");
    my @Capacitors = ("pF", "nF", "uF");
    $self->{lmultiplyer} = 1E-09;
    $self->{cmultiplyer} = 1E-12;
    $self->{freqs} = [1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000];

    $self->{st1} = Wx::StaticText->new($self, -1, "Inductor Value", Wx::Point->new(25,50),
                                       wxDefaultSize, wxALIGN_LEFT);
    $self->{st2} = Wx::StaticText->new($self, -1, "Capacitor Value", Wx::Point->new(25,100),
                                       wxDefaultSize, wxALIGN_LEFT);

    $self->{st5} = Wx::StaticText->new($self, -1, "Enter an L or C. Impedance Sweep will be Graphed",
                                       Wx::Point->new(25,15), wxDefaultSize, wxALIGN_LEFT);
 
    $self->{tc1} = Wx::TextCtrl->new($self, -1, "", Wx::Point->new(150,50), Wx::Size->new(100,20));
    $self->{tc2} = Wx::TextCtrl->new($self, -1, "", Wx::Point->new(150,100), Wx::Size->new(100,20));
    $self->{tc1}->SetValue(0);
    $self->{tc2}->SetValue(0);

    $self->{lc} = Wx::Choice->new($self, 1, Wx::Point->new(250, 50), wxDefaultSize, \@Inductors);
    $self->{cc} = Wx::Choice->new($self, 2, Wx::Point->new(250, 100), wxDefaultSize, \@Capacitors);

    $self->{bt1} = Wx::Button->new($self, 4, "Graph Cs", Wx::Point->new(25,200), wxDefaultSize);
    $self->{bt1} = Wx::Button->new($self, 5, "Graph Ls", Wx::Point->new(150,200), wxDefaultSize);
    $self->{bt1} = Wx::Button->new($self, 6, "Clear All", Wx::Point->new(25,150), wxDefaultSize);
    $self->{bt2} = Wx::Button->new($self, wxID_CLOSE, "Exit", Wx::Point->new(25,300), wxDefaultSize); 

    EVT_BUTTON($self, 4, \&CalcC);
    EVT_BUTTON($self, 5, \&CalcL);
    EVT_BUTTON($self, 6, \&ClearAll);
    EVT_BUTTON($self, wxID_CLOSE, \&Close);
    EVT_CHOICE($self, 1, \&ChoiceL);
    EVT_CHOICE($self, 2, \&ChoiceC);
    
    return $self;
}

sub CalcC {
    my($self, $event) = @_;
    my @values;
    my $C = $self->{tc2}->GetValue * $self->{cmultiplyer};
    if($C == 0) {return};
    foreach my $F (@{$self->{freqs}}) {
        my $I = 1/(6.28 * $C * $F);
        push(@values, $I);
    }
    $self->Graph(\@values);
}

sub CalcL {
    my($self, $event) = @_;
    my @values;
    my $L = $self->{tc1}->GetValue * $self->{lmultiplyer};
    if($L == 0) {return};
    foreach my $F (@{$self->{freqs}}) {
        my $I = 6.28 * $L * $F;
        push(@values, $I);
    }
    $self->Graph(\@values);
}

sub ChoiceL {
    my($self, $event) = @_;
    if($self->{lc}->GetSelection == 0) {$self->{lmultiplyer} = 1E-09};
    if($self->{lc}->GetSelection == 1) {$self->{lmultiplyer} = 1E-06};
    if($self->{lc}->GetSelection == 2) {$self->{lmultiplyer} = 1E-03};
}

sub ChoiceC {
    my($self, $event) = @_;
    if($self->{cc}->GetSelection == 0) {$self->{cmultiplyer} = 1E-12};
    if($self->{cc}->GetSelection == 1) {$self->{cmultiplyer} = 1E-09};
    if($self->{cc}->GetSelection == 2) {$self->{cmultiplyer} = 1E-06};
}

sub ClearAll {
    my($self, $event) = @_;
    $self->{tc1}->SetValue(0);
    $self->{tc2}->SetValue(0);
}

sub Close {
    my($self, $event) = @_;
    $self->Destroy;
}

sub Graph {
    my($self, $values) = @_;
    my @data = ( 
        [ qw( 1 10 100 1K 10K 100K 1M 10M 100M 1G) ],
        [(@{$values})],
    );

    my $my_graph = new GD::Graph::lines(600,400);

    $my_graph->set( 
	x_label => 'Frequency(Hz)',
	y_label => 'Impedance(Ohms)',
	title => 'Impedance vs Frequency',
	y_max_value => 50000,
	y_min_value => 0,
	y_tick_number => 20,
	y_label_skip => 2,
	box_axis => 0,
	line_width => 3,
	transparent => 0,
        x_label_position => 1/2,
    );

    my $gd = $my_graph->plot(\@data);
    
    #save_chart($my_graph, 'impedance');
    #system('eog /home/pete/Projects/perlprojects/RFdesign/impedance.gif');
    
    # Get the raw PNG data
    my $png = $gd->png;
    
    # Get a file handle and load it as a wxImage
    open my $fh, '<', \$png;
    my $img = Wx::Image->new($fh, &Wx::wxBITMAP_TYPE_PNG);
    close $fh;
    
    my $dialog = DisplayDialog->new($self, $img);
    $dialog->Centre;
    $dialog->ShowModal();
    $dialog->Destroy;
    
}

sub save_chart
{
	my $chart = shift or die "Need a chart!";
	my $name = shift or die "Need a name!";
	local(*OUT);

	my $ext = $chart->export_format;

	open(OUT, ">$name.$ext") or 
		die "Cannot open $name.$ext for write: $!";
	binmode OUT;
	print OUT $chart->gd->$ext();
	close OUT;
}

1;

Reply via email to