Thread Agnesi - Netter Programmierspaß (4 answers)
Opened by hlubenow at 2014-05-18 01:58

hlubenow
 2014-05-18 21:39
#175568 #175568
User since
2009-02-22
875 Artikel
BenutzerIn
[default_avatar]
Keine Sorge, Perl kommt schon noch. ;)

Ideen, was man mal so programmieren kann (vielleicht auch sowas wie "Projekt Euler") können doch ruhig nach "Allgemeines", finde ich.
Umstricken braucht ihr nicht (wenn ihr nicht wollt), meist mach' ich das selbst, wenn die Zeit dafür da ist.
Hier also noch eine Perl-Übersetzung meiner Version:
more (44.4kb):
Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#!/usr/bin/perl

use warnings;
use strict;

use Tk;
use Math::Trig;

# Screen resolution:
my $RESX = 800;
my $RESY = 600;

# Zoom-factor and Up/Down-correction:
my $XFAC = 70;
my $XSUM = $RESX / 2;
my $YFAC = 60;
my $YSUM = $RESY / 2;

my $mw = MainWindow -> new();
$mw -> optionAdd(font => "Arial 12 normal");
$mw -> title("Agnesi");
$mw -> geometry("+90+45");
my $cv = $mw->Canvas(-bg => "white", -width => $RESX,
                     -height => $RESY);
$cv->pack();
my $btn = $mw->Button(-text => "Ok", -command => sub {$mw ->destroy()});
$mw->bind('<Key-space>', sub {pause()});
$mw->bind('<Return>', sub {$mw->destroy()});
$mw->bind('<Control-q>', sub {$mw->destroy()});
$btn->pack(-side => 'right', -padx => 10, -pady => 10);
my $angle = 130;

my %points = ("up" => [cos(deg2rad(270)), sin(deg2rad(270))],
              "down" => [cos(deg2rad(90)), sin(deg2rad(90))],
              "circle" => [cos(deg2rad($angle)), sin(deg2rad($angle))],
              "upline"   => [0, 0],
              "downline" => [0, 0],
              "curve"    => [0, 0]);
my @withdraw = [];
drawStatic();
calculatePoints();
drawDynamic();
my $running = -1;
$mw->after(1000, \&run);
$mw->MainLoop();

sub drawStatic {
    $cv->createLine(0, $points{up}[1] * $YFAC + $YSUM,
                    $RESX, $points{up}[1] * $YFAC + $YSUM);
    $cv->createLine(0, $points{down}[1] * $YFAC + $YSUM,
                   $RESX, $points{down}[1] * $YFAC + $YSUM);
    $cv->createOval(($points{up}[0] - cos(deg2rad(0))) * $XFAC + $XSUM,
                    $points{up}[1] * $YFAC + $YSUM,
                    ($points{up}[0] + cos(deg2rad(0))) * $XFAC + $XSUM,
                    $points{down}[1] * $YFAC + $YSUM);
    plotDot($points{down}, 0);
}

sub plotDot {
    my $wd = pop;
    my @point = @{$_[0]};
    @point = @{getZoom(@point)};
    my $o = $cv->createOval($point[0] - 5, $point[1] - 5,
                            $point[0] + 5, $point[1] + 5, -fill => 'black');
    if ($wd) {
        push(@withdraw, $o);
    }
}

sub drawLine {
    my @from_ = @{$_[0]};
    my @to_ = @{$_[1]};
    @from_ = @{getZoom(@from_)};
    @to_ = @{getZoom(@to_)};
    my $o = $cv->createLine($from_[0], $from_[1],
                            $to_[0], $to_[1]);
    push(@withdraw, $o);
}

sub plotPoint {
    my @point = @{$_[0]};
    @point = @{getZoom(@point)};
    $cv->createLine($point[0], $point[1], $point[0] + 1, $point[1] + 1);
}

sub getZoom {
    return [$_[0] * $XFAC + $XSUM, $_[1] * $YFAC + $YSUM];
}

sub calculatePoints {
    $points{circle} = [cos(deg2rad($angle)), sin(deg2rad($angle))];

    # Strahlensatz:   #
    #                ##
    #              #  #
    #            #    #
    #          #      #
    #        # #      #
    #      #   #      #
    #    #     #      #

    my $d = $points{up}[1] - $points{down}[1];
    my $a = $points{circle}[1] - $points{down}[1];
    my $b = $points{down}[0] - $points{circle}[0];
    $points{upline} = [$points{down}[0] - $d / $a * $b,
                       $points{up}[1]];
    $points{downline} = [$points{upline}[0],
                         $points{down}[1]];
    $points{curve} = [$points{upline}[0],
                      $points{circle}[1]];
}

sub drawDynamic {
    drawLine($points{down}, $points{upline});
    drawLine($points{upline}, $points{downline});
    drawLine($points{curve}, $points{circle});
    plotDot($points{circle}, 1);
    plotDot($points{upline}, 1);
    plotDot($points{downline}, 1);
    plotDot($points{curve}, 1);
    plotPoint($points{curve});
}

sub run {
    $running = 1;
    draw();
}

sub pause {
    $running *= -1;
    if ($running == 1) {
        draw();
    }
}

sub draw {
    if ($running == -1) {
            return;
    }
    if ($angle <= 410) {
            $cv->delete(@withdraw);
            calculatePoints();
            drawDynamic();
            $angle += 1;
            $mw->after(50, \&draw);
    }
}

Perl/Tk führt bei mir meist dazu, daß ich recht viele globale Variablen verwende, die dann in allen Funktionen bekannt sind. Wenn das Programm nicht wirklich groß ist, ist das vielleicht gar nicht so schlimm.
Hier hab' ich auch die Daten (für die Punkte) in einer globalen Variable (HoA). Ist hier eigentlich ganz praktisch, obwohl globale Variablen allgemein ja eher verpönt sind ...

modedit Editiert von pq: more-tag hinzugefügt
Last edited: 2014-05-19 11:14:02 +0200 (CEST)

View full thread Agnesi - Netter Programmierspaß