#!perl ############################################################ ## graphplotter ## Written By: Rohit Mishra ( rohit[at]rohitmishra.com) ############################################################ use strict; use Tk 800; use Math::Trig; my $VERSION = "1.04"; my $ver='1.04'; my $bg_color='wheat2'; my $current_scale = 1; my $PI = 3.1415927; my $mw = MainWindow->new(-title=>"Graph $ver", -background=>$bg_color); $mw->minsize(qw/900 600/ ); my $menubar = $mw->Frame(-relief => 'raised', -borderwidth => 2)->form(-top=>'%0',-left=>'%0',-right=>'%100'); $menubar->Menubutton(qw/-text File -underline 0 -tearoff 0 -menuitems/ => [ [Button => 'Function', -command => \&Function], [Button => 'Refresh', -command => \&Refresh], [Separator => ''], [Button => 'Quit', -command => sub{exit}], ])->pack(-side=>'left'); my $canvas = $mw->Canvas( -confine => 'yes', -cursor=> 'crosshair', -background => $bg_color ); my $xscroll = $mw->Scrollbar(-orient => 'horizontal',-command => ['xview', $canvas]); my $yscroll = $mw->Scrollbar(-orient => 'vertical',-command => ['yview', $canvas]); my $bottom_menu = $mw->Frame( -relief => 'raised', -borderwidth => 2); $bottom_menu->form( -left=>'%0',-right=>'%100', -bottom=>'%100'); $canvas->form( -top=>$menubar,-left=>'%0',-right=>$yscroll, -bottom=> $xscroll ); $yscroll->form( -top => $menubar, -bottom => $bottom_menu, -right=>'%100'); $xscroll->form( -left => '%0', -right => $yscroll, -bottom=> $bottom_menu ); $canvas->configure(-xscrollcommand => ['set', $xscroll]); $canvas->configure(-yscrollcommand => ['set', $yscroll]); $canvas->configure(-scrollregion => [ 0,0,900,600 ] ); ####my $canvas = $mw->Scrolled('Canvas', -cursor=> 'crosshair', -background => $bg_color, -scrollbars => 'se' )->form(-top=>$menubar,-left=>'%0',-right=>'%100'); my $zoomin = $bottom_menu->Button(-text=>"Zoom In", -relief=> 'raised', -command=>[ sub{ &Zoom_In;} ])->pack(-side => 'left'); my $zoomout = $bottom_menu->Button(-text=>"Zoom Out", -relief=> 'raised', -command=>[ sub{ &Zoom_Out;} ])->pack(-side => 'left'); my $fullview = $bottom_menu->Button(-text=>"Full View", -relief=> 'raised', -command=>[ sub{ &Full_View;} ])->pack(-side => 'left'); $mw->bind( '' => [ sub{ &Scale;} ]); $mw->bind( '' => [ sub{ &Scale_Del;} ]); $canvas->bind( 'all', '' => [ sub{ &Select_Curve;} ] ); &Coordinates(); MainLoop; sub Refresh(){ $canvas->delete('all'); &Coordinates(); } sub Scale_Del(){ $canvas->delete('coord_bar'); $canvas->configure( -cursor => 'crosshair' ); #$canvas->scanDragto($Tk::event->x, $Tk::event->y); } sub Scale(){ my $xo = $Tk::event->x; my $yo = $Tk::event->y; my $text = "$xo,$yo"; $canvas->createText( $xo, $yo, -text => $text, -tags => 'coord_bar' ); } sub Scale1(){ my $xo = $Tk::event->x; my $yo = $Tk::event->y; my @pt = &Transform($xo,$yo); $pt[0] = $pt[0]/$current_scale; $pt[1] = $pt[1]/$current_scale; my $text = "$xo,$yo"; #my $text = "$pt[0],$pt[1]"; $canvas->configure( -cursor => 'plus' ); $canvas->createText( $xo, $yo, -text => $text, -tags => 'coord_bar' ); #$canvas->createLine( $xo, 0, $xo, 900, -tags => 'coord_bar' ); #$canvas->createLine( 0, $yo, 900, $yo, -tags => 'coord_bar' ); #$canvas->scanMark($xo,$yo); } sub Transform(){ my @coordinates = @_; my @transformed = (); $transformed[0] = $coordinates[0] - 140; $transformed[1] = -($coordinates[1] - 140); return( @transformed ); } sub Reverse_Transform(){ my @coordinates = @_; my @transformed = (); $transformed[0] = ($coordinates[0] + 140); $transformed[1] = -($coordinates[1] - 140); return( @transformed ); } sub Function () { my $curvetag = 'curve'; my $top = $mw->Toplevel( -title => "Enter Function" ); my $entryframe = $top->Frame( -relief => 'raised', -borderwidth => 2)->form( -top => '%0',-left=>'%0',-right=>'%100'); my $func_label = $entryframe->Label( -text => "Enter polynomial as a function of x" )->pack; my $func_entry = $entryframe->Entry( -relief => 'sunken')->pack( -fill => 'x' ); my $range_label = $entryframe->Label( -text => "Enter range of x" )->pack; my $range_entry = $entryframe->Entry( -relief => 'sunken')->pack( -fill => 'x' ); my $buttonframe = $top->Frame( -relief => 'raised', -borderwidth => 2)->form( -top => $entryframe, -left=>'%0',-right=>'%100', -bottom=>'%100'); my $plot = $buttonframe->Button(-text=>"Plot", -relief=> 'raised', -command=>[ sub{ &Plot_Function( $func_entry, $range_entry, $curvetag ); $curvetag++; }])->pack( -side => 'left'); my $close = $buttonframe->Button(-text=>"Close", -relief=> 'raised', -command=>[ sub{ $top->destroy;} ] )->pack( -side => 'left'); } sub Coordinates (){ my @xaxis_left = &Reverse_Transform( -3000, 0 ); my @xaxis_right = &Reverse_Transform( 3000, 0 ); my @yaxis_top = &Reverse_Transform( 0, 3000 ); my @yaxis_bot = &Reverse_Transform( 0, -3000 ); $canvas->createLine( $xaxis_left[0], $xaxis_left[1], $xaxis_right[0], $xaxis_right[1], -width => '1.0', -tags => 'Coords'); $canvas->createLine( $yaxis_top[0], $yaxis_top[1], $yaxis_bot[0], $yaxis_bot[1] , -width => '1.0', -tags => 'Coords'); } sub Plot_Function (){ my $entry1 = shift; my $entry2 = shift; my $curvetag = shift; my $function = $entry1->get; my $range = $entry2->get; my $x; my $y; my $delta = 0.1; my @pt = (); my @points = (); $function =~ s/\bx\b/\$x/g; my @range = split(/[\s\,]+/, $range ); $x = $range[0]; while ( $x <= $range[1] ){ $y = (eval $function); $x += $delta; @pt = &Reverse_Transform($x,$y); push( @points, @pt); @pt = (); } $canvas->createLine( @points, -smooth => 'yes', -splinesteps => '2', -width => '1.0', -joinstyle => 'round', -tags => $curvetag); return( $curvetag ); } sub Zoom_In(){ my $scale = 2; $current_scale *= $scale; $canvas->scale( 'all', 140, 140, $scale, $scale ); } sub Zoom_Out(){ my $scale = 0.5; $current_scale *= $scale; $canvas->scale( 'all', 140, 140, $scale, $scale ); } sub Full_View(){ my $scale; if( $current_scale != 1 ){ $scale = 1/$current_scale; $canvas->scale( 'all', 140, 140, $scale, $scale ); $current_scale = 1; } } sub Select_Curve(){ if( $canvas->itemcget('current', '-fill') eq 'red' ){ $canvas->itemconfigure( 'selected', -fill => 'black' ); $canvas->dtag('selected'); } else { $canvas->addtag('selected', 'withtag', 'current' ); $canvas->itemconfigure( 'selected', -fill => 'red' ); } } =head1 NAME graphPlotter-1.04.ptk =head1 DESCRIPTION graphPlotter is a simple perl/Tk application for plotting explicit polynomials. i.e the function should be of the form y = F(x). An example polynomial function would look like y = x^4 + x^2 - x + 7 or y = sin(x) or y = cos(x) If the polynomial function is y = F(x), then the script takes following inputs: 1. Range of the variable x. 2. The function itself. i.e F(x). 3. The tag or name to be attached to the polynomial curve. Following operations can be done using the menu items in the menu bar: 1. Zoom in 2. Zoom out 3. Refresh 4. Highlight curve =head1 README Following script is a graph plotter for the polynomials of the form y = F(x). Trigonometric functions are also supported. This script can find its application in solving complex polynomial equations using graphs. =head1 PREREQUISITES This script requires the C module. It also requires C and C. =head1 COREQUISITES Tk 800 =pod OSNAMES Unix, Solaris, Linux =head1 AUTHOR Rohit Mishra EFE =head1 COPYRIGHT Copyright (c) 2006 Rohit Mishra . All rights reserved This program is a free software; you can redistribute it and/or modify it under the same terms as Perl itself. =pod SCRIPT CATEGORIES Educational/ComputerScience Educational =cut