Sie sind auf Seite 1von 39

Diplomarbeit im Fachbereich Nachrichten- und Elektrotechnik

an der Fachhochschule Köln

Erstellung einer Visual C++ Anwendung zur Ermittlung der Ortsauflösung einer

Nuklearkamera nach NEMA

Index

INDEX

2

ZUSAMMENFASSUNG

3

EINLEITUNG

4

I DIGITALKAMERA IN DER NUKLEARMEDIZIN

4

II ORTSAUFLÖSUNG DER ENTSTANDENEN AUFNAHME

5

III ERSTELLUNG DES BILDES

6

IV QUALITÄTSKONTROLLE DES BILDES

8

PROGRAMMIERUNG DER ANWENDUNG

9

II DIE DATEIEN UND KLASSEN DES ANWENDUNGSGERÜSTES

16

III CDARBEIT29_07APP DAS ANWENDUNGSOBJEKT

17

IV CDARBEIT29_07DOC DIE DOKUMENTKLASSE

18

V CMAINFRAME DAS HAUPTFENSTER DER ANWENDUNG

18

VI CDARBEIT29_07VIEW DAS ANSICHTSFENSTER DER ANWENDUNG

19

VII ZEICHNEN

21

LITERATUR

28

ANHANG

29

Zusammenfassung

Die Digitalisierung analoger Signale ist in dem letzten Jahrzehnt ein großer

Aufgabenbereich in der Nachrichten- und Elektrotechnik geworden. Aufgrund

vieler

Vorteile

im

Umgang

mit

digitalisierten

Daten

(zum

Beispiel

Speicherung, Versendung) nimmt sie Einzug in sämtliche Bereiche, in denen

große Datenmengen

erhoben

werden.

Ein Anwendungsgebiet

stellt die

Nuklearmedizin dar. Dort werden im Bereich bildgebender Diagnoseverfahren

Nuklearkameras

eingesetzt,

Organe ermöglichen.

welche

die

Aufnahme

von

Bildern

innerer

In der folgenden Arbeit wird eine Software vorgestellt, die Bilder einer

solchen Nuklearkamera, nach vollzogener Digitalisierung auf ihre Qualität hin

überprüft. An einem Beispielbild (die Aufnahme von äquidistant angeordneten

Bleistreifen) soll die Ortsauflösung der Nuklearkamera geprüft werden, das

bedeutet wie gut die Distanz zwischen den oben genannten Flächen auf dem

Bild eingehalten wird.

Einleitung

Die Digitalisierung analoger Signale ist in dem letzten Jahrzehnt ein großer

Aufgabenbereich in der Nachrichten- und Elektrotechnik geworden. Aufgrund

einer Vielzahl von Vorteilen im Umgang mit digitalisierten Daten nimmt sie

Einzug

in

sämtliche

Bereiche,

in

denen

große

Datenmengen

erhoben

werden. So ist die Speicherung und Versendung digitaler Daten aufgrund von

Reduzierung und Komprimierung der Datenmengen deutlich vereinfacht und

der notwendige Speicherplatz drastisch reduziert.

Ein Anwendungsgebiet für die Digitalisierung stellt die Nuklearmedizin dar.

Dort

werden

im

Bereich

bildgebender

Diagnoseverfahren

Kameras

eingesetzt, die nach einer Injektion von radioaktivem Material die Aufnahme

von Bildern innerer Organe ermöglichen. Eine Art der Nuklearkameras stellt

die Gammakamera dar, benannt nach dem Frequenzbereich, in dem sie

Signale aufzunehmen vermag.

I Digitalkamera in der Nuklearmedizin

Die Nuklearmedizin dient vor allem der Untersuchung von Schilddrüsen-,

Herz-

und

Therapiepatienten.

Der

Patient

bekommt

ein

nukleares

Trägermaterial

injiziert,

zum

Beispiel

Technetium

oder

Jod,

das

vom

Stoffwechsel

aufgenommen

wird.

Eine

Gammakamera

wandelt

die

radioaktiven Strahlen der Substanzen in Bilder um. In einer Gammakamera

werden die radioaktiven Strahlen des Trägermaterials zunächst in einem

Kristall in ein Lichtsignal umgewandelt. Bis zu 100 Photomultiplier wandeln

dann das Lichtsignal in einen Stromimpuls um. Die Signale wurden in

analoger Verarbeitungsweise über mehrere Widerstandsnetzwerke addiert,

um

Koordinatensignale

zu

erzeugen.

Bauteiltoleranzen,

Offsetspannungen

und

führen.

Durch

eine

frühe

Digitalisierung

Dieses

kann

jedoch

aufgrund

Rauschen

zu Abbildungsfehler

der

Signale

hingegen

können

beschriebene

Abbildungsfehler

vermieden

werden,

so

dass

mittels

der

Bildaufbereitung

störungsärmere

Bilder

in

höherer

Auflösung

produziert

werden können.

Eine Nuklearkamera verarbeitet Signale aus bis zu 100 Kanäle mit je 50

MHz. Die digitale Signalverarbeitungsleistung für eine Gammakamera ist

dadurch

etwa

fünfzigtausendmal

höher

als

bei

einem

CD-Spieler.

Die

Digitalisierung

bewirkt

in

diesem

Fall,

dass

die

elektronische

Verarbeitungseinheit der digitalen Gammakamera mit der Größe zweier

Aktenordner nur noch ein Zehntel der analogen Kameras beträgt. Somit

können

zudem

sowohl

Fertigungs-

erheblichem Maße eingespart werden.

und

als

auch

Wartungskosten

in

II Ortsauflösung der entstandenen Aufnahme

„Die Ortsauflösung ist definiert als der kleinste meßtechnisch erfaßbare

Abstand

zweier

hannover.de].

Die

reflektierender

Ortsauflösung

Grenzflächen“

stellt

ein

[www.ubicampus.mh-

Qualitätskriterium

der

Gammakamera dar, da nicht bestimmt werden wie groß beziehungsweise

klein

dieser

vorgegebener

Abstand

Abstand

ist

sondern

wie

auf

den

Bildern

gut

und

wirklichkeitsgetreu

ein

abgebildet

wird.

Die

folgende

Anwendungssoftware dient ihrer Überprüfung anhand von verschiedenen

Distanzparametern sowie deren graphischer Darstellung.

III Erstellung des Bildes

Zur

Bestimmung

der

Ortsauflösung

der

Gammakamera

wird

ein

Beispielbild

erstellt.

Dafür

wird

eine

reflektierende

Oberfläche,

die

als

Hintergrund dient, mit Blei bedeckt und aufgenommen. Diese Bleiobjekte

liegen

in

einem

bestimmten

Abstand

voneinander,

so

dass

schmale

Trennlinien zwischen ihnen entstanden sind. Der gleich bleibende Abstand

zwischen diesen Streifen wurde im voraus festgelegt und beträgt 30 mm.

Auf dem entstandenen Bild werden die Bleiobjekte als dunkle Flächen

abgebildet, die

nicht

bedeckten

Flächen

als

weisse,

hell

reflektierende

Trennlinien.

Das

entstandene

Bild

wird

in

einer

Datei

HiResData.dat

gespeichert. Diese Datei ist 32 MB groß und sie ist eine zwei dimensionale

Matrix, die aus 4096 mal 4096 Werten besteht. Jeder Wert in dieser Matrix

steht für einen Pixelwert (0 steht für Schwarz und 255 für weiß). Die zu

erstellende Anwendung soll

die HiResData.dat

einlesen, die Werte als

Pixelwerte interpretieren und anschließend als Bild auf dem Bildschirm

darstellen. Das Bild wird von oben nach unten in 16 gleich breite Streifen

unterteilt

und

die

darin

enthaltene

Pixelwerte

von

links

nach

rechts

spaltenweise aufsummiert. Die Ergebnisse

können dann als Kurve dargestellt werden

Die Ergebnisse können dann als Kurve dargestellt werden (siehe Abbildung 1). Der resultierende Verlauf beschreibt

(siehe

Abbildung

1).

Der

resultierende

Verlauf beschreibt eine flache Linie entlang

Abb. 1: Beispiel eines Kurvenverlauf und den Parametern MAX (233,224), FWHM (41, 40) und FWTM (65, 71)

der x-Achse mit y-Wert 0 in den Bereichen der schwarzen Streifen. Die

Bereiche auf der x-Achse, in denen die weißen Streifen zu finden sind,

werden

in

dieser

Darstellungsform

durch

den

Anstieg

der

Amplituden

abgebildet. Jede dieser Amplituden wird durch 3 Parameter charakterisiert:

durch das Maximum der Amplitude (MAX), dem FWHM-Wert (full width half

maximum) sowie dem FWTM- Wert (full

width tenth maximum, siehe Abbildung

2). Innerhalb einer Amplitude werden

die

Werte

der

Parameter

folgendermaßen

ermittelt:

Das

Maximum

entspricht

dem

Punkt

mit

dem

größten

y-Wert.

Dieser

Wert

Punkt mit dem größten y-Wert. Dieser Wert Abb. 2: Skizze einer Amplitude und die Zuordnung ihrer

Abb. 2: Skizze einer Amplitude und die Zuordnung ihrer Parameter MAX, FWHM und FWTM

befindet sich meist in der Mitte einer Trennlinie und bildet die Spitze der

Amplitude.

Zur

Bestimmung

des

FWHM-Wertes

wird

der

Maximalwert

halbiert. Auf dem linken und rechten Schenkel der Amplitude wird nach

Punkten gesucht, deren y-Werte mit dem ermittelten Wert übereinstimmen.

Die Distanz zwischen den beiden Punkten bezeichnet den FWHM-Wert.

Analog wird der FWTM-Wert ermittelt und beschreibt somit die Distanz der

Punkte mit dem y-Wert, der dem Zehntel des maximalen y-Wertes entspricht.

Im optimalen Fall sollte die Form der Amplitude einer Rechteckfunktion

nahekommen.

Der

kurvenartige

Verlauf

der

Intensitätswerte

hingegen

spiegelt

einen

eher

fließenden

Übergang

zwischen

den

angrenzenden

Bereichen wider.

IV

Qualitätskontrolle des Bildes

mittlerer Abstand

mittlerer Abstand

Nach dem man die Werte ermittelt hat, verfügt man über ein objektives

Mittel, das einem erlaubt, zu prüfen wie empfindlich beziehungsweise schnell

die Kamera reagiert wenn man von einer weißer zu einer schwarzen Stelle

übergeht und umge-

kehrt. Der Optimalfall

liegt

vor,

wenn

FWHM

und

FWTM

gleich wären und der

Abstand

zwischen

den

Linien

gleich

bliebe. Je größer der

Unterschied zwischen

diesen beiden Werten

ist,

ist

desto

schlechter

die

Qualität

des

Bildes.

Unsere

Messung

für das HighResData-

Bild

hat

folgende

250 250

200 200

150 150

100 100

50 50

235 235 235 A A B B 230 230 230 225 225 225 MAX MAX
235 235
235
A A
B B
230 230
230
225 225
225
MAX
MAX
FWTM
FWTM
220 220
220
FWHM
FWHM
215 215
215
210 210
210
0 0
0
2
2
2
4
4
4
6
6
6
8
8
8
10
10
10
12
12
12
Streifen
Streifen
Streifen
85,0
85,0
85,0
80,0
80,0
80,0
75,0
75,0
75,0
70,0
70,0
70,0
65,0
65,0
65,0
60,0
60,0
60,0
0 0
0
2
2
2
4
4
4
6
6
6
8
8
8
10
10
10
12
12
12
Streifen
Streifen
Streifen
55,0
55,0
55,0
1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10 11 12
10 11 12
50,0
50,0
50,0
Streifen
Streifen
45,0
45,0
45,0
40,0
40,0
40,0
35,0
35,0
35,0
30,0
30,0
30,0
0
0 0
2
2
2
4
4
4
6
6
6
8
8
8
10
10
10
12
12
12
Streifen
Streifen
Streifen
FWHM
FWHM
FWHM
FWTM
FWTM
FWTM
MAX
MAX
MAX

Abb.3: Darstellung der Mittelwerte (A) sowie Scatterplotts der einzelnen Messwerte (B) der drei Kurvenparameter MAX, FWHM und FWTM.

Werte ergeben, die Abbildung 3 zu entnehmen sind (Wertetabelle siehe

Anhang 5). Wir stellen fest, dass die Werte FWHM und FWTM sich von

einander unterscheiden. Das liegt daran, dass sich im schwarzen Teil des

Bildes ebenfalls Pixelwerte ungleich null befinden und umgekehrt.

Programmierung der Anwendung

Die beschriebene Anwendung wurde ein Visual C++ erstellt. Microsofts

Visual C++ 6.0 (VC++) ist eine integrierte Umgebung zum Entwickeln von

C++ - Programmen für Windows. Die Arbeit in dieser Umgebung erleichtert

die Erstellung einer Windows-Anwendung. Wenn man mit VC++ arbeitet, hat

man mittels des Dialogfeldes des Anwendungs-Assistenten, welches als

Schnittstelle zwischen dem Anwender und der Entwicklungsumgebung dient,

die Möglichkeit, schrittweise das Grundgerüst und die Art seiner Anwendung

zu bestimmen ohne dabei eine Code-Zeile selbst zu schreiben. Bei der

Erstellung dieser MFC Anwendung sind folgende Schritte notwendig:

Erstellen einer neuen

VC++-Anwendung durch

Aufrufen des Programms

Microsoft Visual C++ und

öffnen einer neuen Datei

unter

dem

Menüpunkt

Datei/Neu (Abbildung 4).

In

der

hier

beschriebenen

Anwen-

dung

wurde

mit

dem

Anwendungs-Assisten-

ten

(MFC-Anwendungs-

Assistent.exe)

das

Projekt

namens

DArbeit29_07

angelegt

(Abbildung 5).

namens DArbeit29_07 angelegt (Abbildung 5). Abb. 4: Öffnen einer VC++-Anwendung Abb. 5: Anlegen einer

Abb. 4: Öffnen einer VC++-Anwendung

DArbeit29_07 angelegt (Abbildung 5). Abb. 4: Öffnen einer VC++-Anwendung Abb. 5: Anlegen einer Anwendung 10

Abb. 5: Anlegen einer Anwendung

Im

ersten

Dialogfeld

des

Anwendungs-Assis-

tenten

wird

die

Option

Einzelnes Dokument SDI

ausgewählt

und

Kontrollkästchen

für

das

die

Unterstützung

ment

Ansicht

der

Doku-

Architektur

bleibt eingeschaltet (Abbil-

dung 6).

Im zweiten Schritt des

Assistenten

werden

die

Standardwerte

über-

nommen (Abbildung 7).

Im

dritten

Dialogfeld

des Assistenten wird das

Kontrollkästchen

für

die

Unterstützung von ActiveX

-Steuerelementen

ausgeschaltet

(Abbildung

8).

ActiveX -Steuerelementen ausgeschaltet (Abbildung 8). Abb. 6: Schritt 1 der MFC-Anwendung Abb. 7: Schritt 2 der

Abb. 6: Schritt 1 der MFC-Anwendung

(Abbildung 8). Abb. 6: Schritt 1 der MFC-Anwendung Abb. 7: Schritt 2 der MFC-Anwendung Abb.8: Schritt

Abb. 7: Schritt 2 der MFC-Anwendung

8). Abb. 6: Schritt 1 der MFC-Anwendung Abb. 7: Schritt 2 der MFC-Anwendung Abb.8: Schritt 3

Abb.8: Schritt 3 der MFC-Anwendung

Im vierten Schritt des

Anwendungs- Assistenten

wird

auf

die

Merkmale

Drucken

und

Druck-

vorschau,

sowie

3D-

Steuerelemente

verzichtet.

Die

Auswahl

der beiden ersten Menü-

punkte

Andockbare

Symbolleiste und Status-

leiste zu Beginn werden

beibehalten (Abbildung 9).

Im fünften Schritt des

Anwendungs-Assistenten

werden

die

Standard-

einstellungen

übernom-

men (Abbildung 10).

Im letzten Schritt des

Anwendungs-Assistenten

wird

mit

die

Ansichtsklasse

dem

Namen

CDArbei29_07View

wird mit die Ansichtsklasse dem Namen CDArbei29_07View Abb 9: Schritt 4 der MFC-Anwendung Abb. 10: Schritt

Abb 9: Schritt 4 der MFC-Anwendung

Namen CDArbei29_07View Abb 9: Schritt 4 der MFC-Anwendung Abb. 10: Schritt 5 der MFC-Anwendung Abb. 11:

Abb. 10: Schritt 5 der MFC-Anwendung

Abb 9: Schritt 4 der MFC-Anwendung Abb. 10: Schritt 5 der MFC-Anwendung Abb. 11: Schritt 6

Abb. 11: Schritt 6 der MFC-Anwendung

12

markiert

um

sie

Später

im

Feld

Klassenname

in

CDArbei29_07View1

umzube-nennen

(Abbildung

 

11).

Im

Feld

Basisklasse

wird

die

Klasse

CScrollView

für

diese

Ansichts-datei

ausgewählt.

Vor

der

endgültigen

Fertigstellung

kann

man

in

dem

Feld

Basisklasse

eine

Klasse

aus

verschiedenen auswählen, aus der die Ansichtsklasse ihre Eigenschaften

beziehunsgweise Methoden erbt. Aufgrund der Größe des zu erstellenden

Bildes braucht die Anwendung Scrollbalken, um das gesamte Bild anschauen

zu

können.

ausgewählt.

Aus

diesem

Grund

wurde

die

Basisklasse

CScrollView

Ad 2: Die Option SDI–Grundgerüste (SDI- single document interface)

wurde in diesem Schritt ausgewählt, da sie universeller einsetzbar sind als

MDI-Gerüste (MDI- multiple document interface). Beide Grundgerüste, SDI

wie MDI, sind vorrangig für Dateibearbeitungsprogramme konzipiert, das

heißt für Programme, die den Inhalt von Dateien laden (Grafiken, Texte,

Sounddateien), bearbeiten und wieder abspeichern. Da in dieser Anwendung

eine gleichzeitige Bearbeitung mehrere Dateien nicht vorgesehen ist, eignen

sich SDI-Programme besser, da sie jeweils nur das Laden und Bearbeiten

einer einzigen Datei zur gleichen Zeit erlauben. SDI-Programme haben

aufgrund des simpleren und übersichtlicheren Programmtextes zudem den

Vorteil der leichteren Anpassung an Programme, die nicht der Bearbeitung

von

Dateien

dienen.

Außerdem

besteht

keine

Notwendigkeit

zu

der

Unterstützung von Ausführungen zusätzlicher untergeordneter Rahmen in

den eigenen Dokument/Ansicht-Klasseninstanzen.

Mit

der

Unterstützung

des

Doc/View-Modells

(Dokument/Ansicht-

Architektur) durch SDI-Grundgerüste verhält es sich genau umgekehrt: Das

Grundgerüst wird durch das Doc/View-Modell eher komplexer, manchmal

zudem ohne eindeutige Vorteile. Seine Verwendung hat daher folgenden

Grund: Je komplexer und professioneller die Anwendung mit der Zeit wird,

desto stärker zahlt sich die Verwendung von Doc/View aus.

Doc/View bezeichnet ein Modell zur Code-Organisation, das die Trennung

von Datenverwaltung und Datenanzeige propagiert. Letztere dient sowohl der

besseren Übersichtlichkeit als auch der Erleichterung der Programmierung,

zum Beispiel wenn man Daten auf zwei unterschiedliche Arten anzeigen

möchte, wie in unserem Falle die Darstellung der Daten als Kurve und Bild

(siehe auch CDarbeit29_07Doc). Die MFC (Microsoft Foundation Class) stellt

zur Unterstützung dieses Modells eine Reihe von speziellen Klassen und

Methoden zur Verfügung. Die Techniken zur Anzeige von Grafiken sind von

der Verwendung von Doc/View weitgehend unabhängig. Doc/View ist kein

substantielles Element einer Windows- Anwendung und auch keine spezielle

Programmiertechnik, die uns eine neue Funktionalität erschließt.

Ad 7: Die Umbenennung der Ansichtsklasse von CDArbeit29_07View in

CDArbeit29_07View1 gründet auf der Tatsache, dass diese Anwendung über

zwei Ansichten verfügen soll (Kurve und Bild), zwischen denen der User

beliebig umherschalten kann.

Die darzustellenden Daten für das Bild und die Kurven werden in dem

Dokument des SDI-Programms verwahrt und in seiner OnDraw() - Methode

auf den Bildschirm gemalt. In der OnDraw() - Methode des Ansichtsfensters

CDArbeit29_07View1

werden

die

Kurven

gezeichnet.

Der

zugehörige

Quellcode befindet sich im Anhang (Anhang 1). Zur Erstellung der zweiten

Ansicht

(des

Bildes)

ist

eine

zweite

Ansichtsklasse

zu

definieren,

CDArbeit29_07View2.

Man

legt

die

neue

Klasse

mit

dem

Klassen-

Assistenten an. Um dem Programm eine zweite Ansichtsklasse hinzuzufügen

muss man

(1) ein Objekt der neuen Ansichtsklasse instantiieren

(2) die Create() - Methode des Objekts aufrufen

(3) die Ansicht mit dem Dokument verbinden.

Ad (2): Die zweite Ansicht wird erzeugt in der CMainFrame-Methode

OnCreateClient().

Sie

ist

ein

geeigneter

Ort

dafür,

weil

sie

das

CCreateContext-Objekt für die Einrichtung der ersten Ansicht liefert. In

diesem Objekt ist unter anderem festgehalten, mit welchem Dokument die

Ansicht zu verbinden ist. Zur Identifizierung der beiden Ansichten definiert

man zwei IDs (View1, View2) und weist diese den Ansichtsfenster- Objekten

zu. Die Zuweisung erfolgt entweder über die Create() - Methode oder mit

Hilfe der CWnd-Methode GetDlgItem(). Unter Menü/Darstellung hat man die

Möglichkeit zwischen den Ansichten zu wechseln (siehe Anhang 2 für

Näheres hinsichtlich des zugrunde liegenden Quellcodes für die Erstellung

des Menü-Punktes ’Darstellung’).

II

Die Dateien und Klassen des Anwendungsgerüstes

Jedem Anwendungsgerüst liegen Klassen und Dateien zugrunde, die

miteinander in Beziehung stehen (wie man in Abbildung 12 erkennen kann).

in Beziehung stehen (wie man in Abbildung 12 erkennen kann). Abb.12: Dateien und Klassen des Anwendungsgerüstes.
in Beziehung stehen (wie man in Abbildung 12 erkennen kann). Abb.12: Dateien und Klassen des Anwendungsgerüstes.

Abb.12: Dateien und Klassen des Anwendungsgerüstes.

Dies

liegt

daran,

daß

der

Anwendungs-Assistent

zum

Aufbau

des

Anwendungsgerüst fünf Klassen erzeugen muß (für den Fall, dass die

Anwendung nur ein Ansichtsfenster hat, werden vier Klassen erstellt). Für

jede dieser Klassen werden eine Header-Datei und eine Quelltextdatei

erzeugt.

In der Header-Datei wird die Klasse deklariert, in der Quelltextdatei werden

die Methoden der Klasse definiert. Auf diese Weise wird der erzeugte Code

modularisiert. Die Klasse CAboutDlg, die den INFO-Dialog enthält, besitzt

keinen Einfluss auf das Funktionieren des Anwendungsgerüstes. Welche

Dateien im Einzelfall angelegt werden ist abhängig von den Einstellungen im

Dialogfeld des Anwendungs-Assistenten (SDI/MDI-Anwendung, Doc/View-

Modell). Im folgenden werden die fünf Klassen hinsichtlich ihres Inhaltes und

ihrer Funktion näher betrachtet:

III CDarbeit29_07App – das Anwendungsobjekt

Zuerst benötigt man ein Objekt, das geeignet ist, die Anwendung zu

repräsentieren. Die MFC definiert hierfür die Klasse CWinApp. Da es zur

Anpassung

der

Anwendung

an

unsere

Vorstellungen

nötig

ist,

einige

Methoden der Klasse CWinApp zu überschreiben, hat der Anwendungs-

Assistent eine eigene Klasse namens CDarbeit29_07App von CWinApp

abgeleitet. In der Datei Darbeit29_07.cpp sind nicht nur die überschriebenen

Methoden

implementiert,

hier

wird

auch

ein

globales

Objekt

der

Anwendungsklasse erzeugt: theApp. Im Quelltext des Projekts wird dieses

Objekt nicht weiter verwendet. Visual C++ fügt dem MFC-Programm einen

zusätzlichen Startcode hinzu, aus dem auf dieses Objekt zugegriffen wird.

Die wichtigsten Aufgaben des Anwendungsobjektes sind die Erzeugung des

Hauptfensters der Anwendung und die Kommunikation mit Windows.

IV

CDarbeit29_07Doc – die Dokumentklasse

Die

Klasse

CDarbeit29_07Doc

ist

von

der

MFC-Klasse

CDocument

abgeleitet. Sie unterstützt den Befehl Datei/Neu sowie das Laden und

Speichern von Daten aus und in Dateien. In dieser Anwendung wurde auf die

Implementierung

von

diesen

Funktionalitäten

verzichtet.

Im

Falle

der

Anwendung von der Bearbeitung anderer Bilder oder beim Testen ähnlicher

Geräte kann dies jedoch notwendig werden.

Die

Doc/

View-

Unterstützung

arbeitet

mit

sogenannten

Dokumentvorlagen.

Das

Dokumentobjekt

wird

zusammen

mit

der

Dokumentvorlage

eingerichtet.

Im

Konstruktor

dieser

Klasse

wird

die

HiResData.dat eingelesen und die dadurch gewonnenen Daten in einer

geeigneten Form in einem Feld neu gespeichert. Damit können die beiden

Ansichten unabhängig von einander darauf zugreifen (siehe Anhang 6).

V CMainFrame – das Hauptfenster der Anwendung

Die Klasse CMainFrame ist von der MFC-Klasse CFrameWnd abgeleitet.

Diese

Klasse

verleiht

der

Anwendung

ein

sichtbares

Rahmenfenster.

Letzteres sind Fenster mit einem speziellen Rahmen, in welchem bestimmte

Elemente wie zum Beispiel ein Menü integriert werden können. In dieser

Anwendung musste das Menü um eine weitere Funktionalität erweitert

werden um zwischen den Ansichten wechseln zu können. Diese Klasse ist

der geeigneter Ort um den Code einzubringen, damit die Funktion für beide

Ansichten zur Verfügung steht (siehe Anhang 2).

Um nun ein Rahmenfenster zu erzeugen sowie es mit der Anwendung zu

verbinden und anzuzeigen, sind folgende Schritte notwendig:

1. Um

das

Rahmenfenster

zu

erzeugen,

wird

ein

Objekt

einer

abgeleiteten Klasse CMainFrame instantiiert:

CMainFrame *pMainWnd = new CMainFrame;

2. Um das Rahmenfenster mit der Anwendung zu verbinden, wird der

Zeiger

auf

das

Fensterobjekt

an

die

globale

MFC-Variable

m_pMainWnd übergeben: m_pMainWnd = pMainWnd;

3. Um das Rahmenfenster anzeigen zu lassen, werden die Methoden

Show-Window() und UpdateWindow() aufgerufen:

m_pMainWnd->ShowWindow(SW_SHOW);

m_pMainWnd->UpdateWindow();

Es ist zu erwähnen, dass bei der Einrichtung der Dokumentvorlagen

gleichzeitig das Rahmenfenster eingerichtet wird, was dazu führen kann,

dass

manche

der

oben

genannten

abgespeichert werden.

Methoden

versteckt

im

Quelltext

VI CDarbeit29_07View – das Ansichtsfenster der Anwendung

Das Ansichtsfenster ist ein untergeordnetes Fensterobjekt, das in den

Client – Bereich des Rahmenfensters eingefügt und eingebaut wird. In

diesem Bereich kann man zum Beispiel einen Text ausgeben oder eine

Grafik zeichnen. Das ginge auch über das Rahmenfenster ohne von dem

Ansichtsfenster Gebrauch zu machen. Mit vorliegendem Vorgehen erzielt

man eine klare Aufgabenteilung: Das Rahmenfenster ist die Hauptschnitt-

stelle der Anwendung, wenn man dieses schließt, wird auch die Anwendung

beendet.

Ein

weiterer

Vorteil

dieses

Vorgehens

ist,

dass

somit

das

Ansichtsfensterobjekt einer eigenen Basisklasse angehört, die wichtige und

weitere

Methoden

dem

Ansichtsfensterobjekt

zur

Verfügung

stellt,

und

unabhängig ist von derjenigen, der das Rahmenfensterobjekt zugeordnet ist.

Im letzten Schritt des Dialogfeldes des Anwendungs-Assistenten hat man

die

Möglichkeit

eine

geeignete

Basisklasse

auszuwählen,

die

ihre

Eigenschaften der Ansichtsklasse der Anwendung vererbt. Für die hier

beschriebene

Anwendung

wurde

CScrollView

ausgewählt,

was

dem

Ansichtsfenster einen Scrollbalken hinzufügte. Dieser war notwendig, um das

Bild mit der Größe von 4096 Pixel mal 4096 Pixel vollständig anzeigen zu

können. Zudem wurden zwei weitere Funktionen der CDArbeit29_07View2

Klasse hinzugefügt: OnZoomin() und OnZoomout(), die, wie ihre Namen

vermuten lassen, in das Bild hinein – und herauszoomen (siehe Anhang 7).

Eine

Methode,

die

die

Basisklasse

zur

Verfügung

stellt

ist

die

SetScaleToFitSize()-Methode. Diese passt das gesamte Bild an das zur

Verfügung stehenden Ansichtsfenster an, und erst nach Verwendung der

Zoom-funktion

erscheinen

die

Scrollbalken

am

Rande

der

Benutzer-

oberflächen.

Zur

Einpassung

des

Ansichtsfensters

in

den

Client-Bereich

des

Rahmenfensters übergibt man ersterem bei der Erzeugung einen Zeiger auf

das übergeordnete Rahmenfenster. Die Einrichtung des Ansichtsfensters und

seine Verknüpfung mit dem Rahmenfenster sind ebenfalls in der Erzeugung

der CSingleDocTemplate-Dokumentvorlage enthalten.

VII

Zeichnen

Die wichtigste Stelle in unserem Quellcode stellt die Methode OnDraw()

dar, enthalten in der Klasse CDarbeit29-07View. Die OnDraw() - Methode

dient

der

Rekonstruktion

des

Fensterinhaltes

und

wird

automatisch

ausgeführt, wenn Windows eine WM_Paint-Nachricht an das Fenster schickt,

um ihm mitzuteilen, dass es seinen Fensterinhalt neu zeichnen soll. Die

OnDraw() - Methode wird auf einem Umweg aufgerufen. Die WM_Paint-

Nachricht wird von den Fensterklassen der MFC in einer OnPaint() - Methode

abgefangen.

Diese

bereitet

einen

passenden

Gerätekontext

für

die

Zeichenausgabe vor und übergibt diesen an die Methode OnDraw().

Für die Konstruktion des Fensterinhaltes, in unserem Fall die Erstellung

des

Bildes

und

der

Kurve

muss

man

die

OnDraw()

-

Methode

der

Ansichtsklasse modifizieren. In einem ersten Schritt werden (a) Leinwand (b)

Stift und (c) Farbe ausgewählt.

(a) Die Leinwand (Gerätekontext): Für Grafikausgaben am Computer

braucht man einen Gerätekontext, der zu dem Fenster korrespondiert in das

man

zeichnen

will.

Man

spricht

die

Ausgabegeräte

wie

Drucker

oder

Bildschirm nicht direkt an sondern über einen Gerätekontext. Das hat den

Vorteil,

dass

der

Programmierer

sich nicht

um

die

jeweils

installierten

Hardware zu kümmern braucht. Der Programmierer schreibt direkt in den

Gerätekontext und überläßt Windows die Übergabe an die Hardware.

In der Tabelle 1 sind die verschiedenen Ausgabegeräte zusammengestellt,

die MFC zur Verfügung stellt.

Tabelle 1: Ausgabegeräte, die MFC zur Verfügung stellt

Klasse

Ausgabeeinheit

CDC

Basisklasse aller Gerätekontextklassen mit reicher Auswahl an Zeichen- und Ausgabeoperationen.

CPaintDC

Spezieller Fenster-DC zur Implementierung von Behandlungsmethoden zur WM_PAINT-Nachricht.

CClientDC

Gerätekontext für die Ausgabe in den Client-Bereich eines Fensters

CWindowDC

Gerätekontext für den gesamten Bereich eines Fensters ( einschließlich Rahmen, Titel und vieles mehr)

(b) STIFTE( CPen) und PINSEL( CBrush): Für die Linien und Konturen der

dargestellten Kurven in dem Programm wird ein CPen-Objekt zum Auftragen

der Farbe verwendet. CPen ist das hauptsächliche Ressourcenwerkzeug, mit

CPen ist das hauptsächliche Ressourcenwerkzeug, mit Abb.13: Ansicht der On-Draw()-Methode der Klasse

Abb.13: Ansicht der On-Draw()-Methode der Klasse Cdarbeit29_07View2

dem man Linien aller Art auf dem Bildschirm darstellt. Erzeugt man eine

Instanz der Klasse CPen, kann man den Typ, die Farbe und die Breite der

Linie spezifizieren. Nachdem der Stift erzeugt ist, läßt er sich als aktuelles

Zeichenwerkzeug

für

den

Gerätekontext

auswählen

und

damit

für

alle

Zeichenbefehle in diesen Geräte-kontext verwenden.

(c) DIE FARBEN (RGB): Die Farbe ist als RGB-Wert anzugeben, der sich

aus drei separaten Werten für die Helligkeit der roten (R), grünen (G) und

blauen

(B)

Komponenten

der

Pixel

auf

dem

Computerbildschirm

zusammensetzt. Die einzelnen Komponenten können Werte im Bereich

zwischen 0 und 255 annehmen. Die Funktion RGB faßt die Einzelwerte in

einem Format zusammen, das Windows für die Ausgabe benötigt. Dem

Ansichtsfenster, welches das Bild (siehe Abbildung 13) beinhaltet, liegt

folgende modifizierte OnDraw()-Methode zugrunde:

void CDarbeit29_07View2::OnDraw(CDC* pDC)

{

CDarbeit29_07Doc* pDoc = (CDarbeit29_07Doc*) GetDocument();

// ZU ERLEDIGEN: Code zum Zeichnen hier einfügen /*

Wir definieren unser Array, indem wir alle Elemente auf 0 setzen, und verbinden es anschließend mit Bild über die Funktion CreateBitmap( */ for(int n = 0; n< 4096*4096; n++)

):

{

B[4*n] = B[(4*n) +1] = B[(4*n) +2] = pDoc->A[n]; B[(4*n)+3] = 0;

}

Bild.CreateBitmap(4096, 4096, 1, 32, B); /* Die Struktur vom Typ BITMAP definiert Typ, Höhe, Breite, Farbformat und Bit-Werte eines Bitmaps

*/ BITMAP bm; /* Hier kommt die Funktion

int CGdiObject::GetObject ( int nCount, LPVOID lpObject ) zum Einsatz. Bedeutung der Funktions-Parameter:

nCount:

Anzahl Bytes, die in den lpObject-Puffer kopiert werden.

lpObject:

Zeiger auf einen Puffer, der die Daten aufnimmt.

*/ Bild.GetObject( sizeof (bm), &bm);

/* Die MFC-Klasse CDC umhüllt die Funktion eines Windows-Geräte-Kontexts (device context), der die Bildschirm- oder Druckerausgabe gewährleistet. Die MFC-Funktion virtual BOOL CreateCompatibleDC(CDC*pDC ) erzeugt einen Speicher-Geräte-Kontext. Dieser ist "kompatibel" mit dem durch den Zeiger pDC (gleichbedeutend mit der Speicheradresse des Geräte-Kontexts) angegebenen Geräte-Kontext. Ein mit dieser Funktion erstellter Speicher-Geräte-Kontext ist ein Speicher- bereich, der die Bildschirmausgabe erzeugen kann. */ CDC SpeicherDC; SpeicherDC.CreateCompatibleDC(pDC);

/* Die MFC-Funktion CDC::SelectObject tritt hier in folgender Variante auf:

CBitmap* SelectObject( CBitmap* pBitmap ); Hiermit wird das CBitmap-Objekt Bild in den Speicher-Geräte-Kontext SpeicherDC kopiert. Die Funktion erwartet als Parameter die Adresse von Bild also &Bild. */ SpeicherDC.SelectObject(&Bild);

/* Die MFC-Funktion CDC::StretchBlt kopiert ein Bitmap aus einem Quell- Rechteck in ein Ziel-Rechteck. Die Quelle ist hier der Speicher-Geräte-Kontext, das Ziel der für die Ausgabe zuständige Geräte-Kontext CDC* pDC. Hierbei wird das Bitmap den Abmessungen des Ziel-Rechtecks durch Dehnung oder Streckung angepaßt. Die allgemeine Syntax dieser Funktion lautet:

BOOL StretchBlt ( int x, int y, int nWidth, int nHeight, CDC* pSrcDC, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, DWORD dwRop ); */ pDC->StretchBlt(0, 0, pDoc->k*4096, pDoc->k*4096, &SpeicherDC, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);

// ** SpeicherDC.DeleteDC(); Bild.DeleteObject();

}

**

Gerätekontextobjekte

gehören

genau

wie

alle

Arten

von

Zeichenobjekten

zu

den

Ressourcen

im

Betriebssystem Windows.

Das

Betriebssystem verfügt über eine begrenzte Zahl dieser Ressourcen. Obwohl

die Gesamtzahl der Ressourcen in den neueren Versionen von Windows

recht groß ist, kann dennoch ein Mangel entstehen, wenn eine Anwendung

die Ressourcen zwar reserviert, nicht aber wieder korrekt freigibt.

Diesen Verlust bezeichnet man als Ressourcenlücke, die analog zu einer

Speicherlücke das System des Benutzer blockieren kann. Es empfiehlt sich

also, die Ressourcen in Funktionen zu erzeugen, wo sie zum Einsatz

kommen, und sie sobald wie möglich wieder freizugeben, wenn die Arbeit mit

den betreffenden Ressourcen abgeschlossen ist.

Dementsprechend

nutzt

man

Gerätekontexte

und

deren

Zeichenressourcen fast ausschließlich als lokale Variablen innerhalb einer

einzigen

Funktion.

Die

Gerätekontextobjekt

von

Windows

erzeugt

und

in

eine

ereignis-

verarbeitende

Funktion

als

Argument

über-

geben wird. Für diese

Anwendung

ist

ein

weiteres

Ansichts-

fenster notwendig, zur

Darstellung

der

dem

Bild

zugehörigen

Intensitätskurven (siehe

Abbildung 14).

einzige

echte

Ausnahme

liegt

vor,

wenn

das

Abbildung 14). einzige echte Ausnahme liegt vor, wenn das Abb. 14: Ansicht der On-Draw()-Methode der Klasse

Abb. 14: Ansicht der On-Draw()-Methode der Klasse Cdarbeit29_07View1

Die Eckpfeiler der OnDraw()-Methode des zweiten Ansichtsfensters sind

folgende Schritte:

1.

die Leinwand wird vorbereitet (void CDarbeit29_07View::OnDraw(CDC* pDC))

-die MFC übergibt der OnDraw ()-Funktion als Argument einen Zeiger auf dem

Gerätekontext CDC, OnDraw(CDC* pDC). CDC ist eine Basisklasse aller

Gerätekontextklassen mit reicher Auswahl an Zeichen- und

 

Ausgabeoperationen.

 

2.

Anschließend werden die Pinsel bestimmt, in diesem Fall zwei: einen Blaue und

den anderen Rosa (

 
 

CPen PenBlau;

 

PenBlau.CreatePen(PS_SOLID, 1, RGB(200, 0, 200));

 

CPen PenRosa;

 

PenRosa.CreatePen(PS_SOLID, 1, RGB(0, 12, 200)); )

 

3.

Berechnung

der

3

Parameter

MAX

(Programmablauf

siehe

Diagramm in Anhang 3), FWHM und FWTM (Programmablauf siehe

Diagramm in Anhang 4).

Ad 3: Um die Maxima und den Abstand zwischen zwei aufeinander

folgenden Maxima zu bestimmen sind einige Laufvariablen notwendig: die

Laufvariabe h steht für die Anzahl der Streifen und läuft daher von 0 bis 15.

Innerhalb eines Streifens verläuft die Laufvariable k entlang der x-Achse. Sie

deckt den Bereich von 0 bis ((h+1)*4096)-1 ab.

Die entsprechenden y-Werte werden mit dem Wert 150 verglichen, wobei

150 als unterer Grenzwert für ein Maximum festgelegt ist. Sobald ein Treffer

gefunden ist, wird der Wert der Variable k in einer Konstanten Z gespeichert.

Im Bereich von Z bis Z + 49 wird von nun an die Suche fortgesetzt, wobei der

größte y-Wert als das Maximum angenommen wird. Der zugehörige x-Wert

wird anschließend in einer Konstanten namens mo gespeichert, wobei der

Wert ebenfalls als mo-h*4096 in einer Konstanten a abgespeichert wird.

Sobald das Maximum gefunden wurde nimmt die Laufvariable k ihre Aufgabe

wieder auf, die Kurve auf y-Werte > 150 abzutasten. Den Ausgangspunkt

bildet dabei x = Z + 49. Sobald das folgende Maximum gefunden ist, wird der

Konstanten a der dem zweiten Maximum zugehörige x-Wert zugewiesen. Die

Differenz zwischen dem neuen und dem bestehenden Wert von a stellt die

Distanz zwischen den aufeinander folgenden Maxima dar und wird als ’MAX

zu Max’-Wert ausgegeben.

Sobald der Wert mo einmal bestimmt ist, wird in einem Bereich aus 70

Punkten zu beiden Seiten von mo entlang der x-Achse nach Punkten, die auf

dem Verlauf der Amplitude liegen und deren y-Wert die Hälfte des MAX-

Wertes (der y mo -Wert) beträgt, gesucht. Der Abstand zwischen den beiden

Punkten stellt den gesuchten FWHM-Wert dar. Analog wird mit dem y-Wert in

Höhe eines Zehntels des MAX-Wertes zur Bestimmung des FWTM-Wertes

verfahren.

Literatur

1- Chapman (1999). Visual C++6 in 21 Tagen. Markt&Technik, Buch- und

Software-Verlag GmbH

2- Louis

D

(2005)

entwickler.press

Visual

3- www.henkessoft.de

C++

2005.

Professionell

einsteigen.

Anhang

Anhang 1: Quellcode der OnDraw() - Methode für das Ansichtsfenster

CDArbeit29_07View1

///////////////////////////////////////////////////////////////////////////// // CDarbeit29_07View1 Zeichnen

void CDarbeit29_07View1::OnDraw(CDC* pDC)

{

 

CDarbeit29_07Doc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // ZU ERLEDIGEN: Hier Code zum Zeichnen der ursprünglichen Daten hinzufügen CPen PenBlack; PenBlack.CreatePen(PS_SOLID, 1, RGB(200, 0, 200));

CPen PenBlue; PenBlue.CreatePen(PS_SOLID, 1, RGB(0, 12, 200));

CPoint Pt;

CPoint PtPrev;

int i=0, h=0, s=0, j=0, k=0; int kurv[16*4096]; for (h=0; h<16; h++)

{

for(i=0; i< 4096; i++)

 

{

for(j=h*256; j< (h+1)*256; j++) s= s+ pDoc->A[i+j*4096]; kurv[k]=s;

kurv[k]=kurv[k]/255;

k++;

s=0;

}

 

}

j=0;

h=0;

int mo=0, mol=0, mor=0, tor=0, tol=0, FWHM=0, FWTM=0; int a=0, b=0, dif=0; char buff[80]; pDC->SelectObject(&PenBlack);

for(h=0; h<16; h++)

{

int z=0, hl=0;

i=0;

a=0, b=0, dif=0;

k=h*4096;

do

{

//

Maximum suchen int max =150; if (kurv[k]>max)

{

z=k; for(j=z+1; j<z+50; j++)

{

}

if (kurv[j]>max)

{

mo = j; max = kurv[mo];

}

a=mo-h*4096;

dif=a-b;

i=i+dif;

b=a;

if(b==0|| dif>300|| dif<200) dif=0;

if(dif!=0)

{

sprintf(buff,"<-%d->", dif) ; pDC->TextOut(10*i-2050, h*1500-5*255-100, buff);

}

pDC->MoveTo(10*i, h*1500); pDC->LineTo(10*i, h*1500-4*kurv[mo]);

//

Der linke Punkt FWHM int ymol=0; for(j=mo-70; j<mo; j++)

{

if (kurv[j]==max/2)

{

mol=j;

ymol=kurv[mol];

break;

}

else if (kurv[j]<max/2 && kurv[j+1]>max/2)

{

mol=j;

ymol=max/2;

break;

}

}

//

Der rechte Punkt FWHM int ymor=0; for(j=mo; j<mo+70; j++)

{

if (kurv[j]==max/2)

{

mor=j;

ymor=kurv[mor];

break;

}

else if (kurv[j]>max/2 && kurv[j+1]<max/2)

{

mor=j+1;

ymor=max/2;

break;

}

}

pDC->MoveTo(10*(mol-h*4096), h*1500-4*ymol); pDC->LineTo(10*(mor-h*4096), h*1500-4*ymor);

dif = mor-mol; sprintf(buff," %d", dif) ; pDC->TextOut(10*(mol-h*4096)-800, h*1500-7*ymor, buff);

//

Der linke Punkt FWTM

int tol=0, ytol=0;

for(j=mo-80; j<mo; j++)

{

if (kurv[j]==max/10)

{

 

tol=j;

ytol=kurv[tol];

break;

 

}

else if(kurv[j]<max/10 && kurv[j+1]>max/10)

{

 

tol=j; if (max%10>5) ytol= max/10+1; else ytol=max/10; break;

 

}

}

//

Der rechte Punkt FWTM

int tor=0, ytor=0; for(j=mo; j<mor+80; j++)

{

 

if (kurv[j]==max/10)

{

tor=j;

ytor=kurv[tor];

break;

}

else if(kurv[j]>max/10 && kurv[j+1]<max/10)

{

tor=j+1;

if (max%10>5) ytor= max/10+1; else ytor=max/10; break;

}

}

pDC->MoveTo(10*(tol-h*4096), h*1500-4*ytol); pDC->LineTo(10*(tor-h*4096), h*1500-4*ytor);

dif = tor-tol; sprintf(buff," %d", dif) ; pDC->TextOut(10*(tor-h*4096)+50, h*1500-4*ytor-350, buff);

k=k+49;

}

// if k

k++;

}while(k<((h+1)*4096)-1);

} // for h

DeleteObject(&PenBlack); pDC->SelectObject(&PenBlue); for(h=0; h<16; h++)

{

 

i=0;

for(k=h*4096; k<((h+1)*4096)-1; k++)

 

{

PtPrev.x=10*i;

PtPrev.y= h*1500-4*kurv[k];

Pt.x=10*(i+1);

Pt.y=h*1500-4*kurv[k+1];

pDC->MoveTo(PtPrev);

pDC->LineTo(Pt);

i++;

}

//for(k)

}

// for(h)

DeleteObject(&PenBlue);

}

Anhang 2: Die Methoden innerhalb der Klasse CMainFrame die den

Wechsel zwischen den Darstellungsformen ermöglicht.

void CMainFrame::OnDarstellungKurve()

{

 

// TODO: Code für Befehlsbehandlungsroutine hier einfügen CView *pView, *pAktView; CDocument *pDoc; pAktView = GetActiveView(); pDoc = pAktView->GetDocument(); POSITION pos = pDoc->GetFirstViewPosition(); while(pos != NULL)

{

pView = pDoc->GetNextView(pos);

if (pView->IsKindOf(RUNTIME_CLASS(CDarbeit29_07View1)))

{

SetActiveView(pView);

pView->ShowWindow(SW_SHOWNORMAL);

pView->SetDlgCtrlID(AFX_IDW_PANE_FIRST); pAktView->ShowWindow(SW_HIDE);

pAktView->SetDlgCtrlID(VIEW2);

}

}

RecalcLayout();

}

void CMainFrame::OnDarstellungBild()

{

// TODO: Code für Befehlsbehandlungsroutine hier einfügen CView *pView, *pAktView; CDocument *pDoc; pAktView = GetActiveView(); pDoc = pAktView->GetDocument(); POSITION pos = pDoc->GetFirstViewPosition(); while(pos != NULL)

{

pView = pDoc->GetNextView(pos); if (pView->IsKindOf(RUNTIME_CLASS(CDarbeit29_07View2)))

{

SetActiveView(pView);

pView->ShowWindow(SW_SHOWNORMAL);

pView->SetDlgCtrlID(AFX_IDW_PANE_FIRST); pAktView->ShowWindow(SW_HIDE);

pAktView->SetDlgCtrlID(VIEW1);

}

}

RecalcLayout();

}

h:= 0 k:= h*4096 b:= 0 max= 150 n kurv[k]> max k++ j j Z:=
h:= 0
k:= h*4096
b:= 0
max= 150
n
kurv[k]> max
k++
j
j
Z:= k
k< ((h+1)*4096)-1
j:= z+1
n
n
h++
kurv[j]> max
b:=0
j
mo:= j
k:= h*4096
max:= kurv[mo]
j
j< z+50
j++
n
n

a:= mo-h*4096

dif:= a-b

b:= a

b==0|| n dif>300|| dif<200 j
b==0||
n
dif>300||
dif<200
j

sprintf(buff,"<-%d->", dif) ; pDC->TextOut(10*i-2050, h*1500-5*255-100,

sprintf(buff,"<-%d->", dif) ; pDC->TextOut(10*i-2050, h*1500-5*255-100,
sprintf(buff,"<-%d->", dif) ; pDC->TextOut(10*i-2050, h*1500-5*255-100,
sprintf(buff,"<-%d->", dif) ; pDC->TextOut(10*i-2050, h*1500-5*255-100,
dif) ; pDC->TextOut(10*i-2050, h*1500-5*255-100, pDC->MoveTo(10*i, h*1500); pDC->LineTo(10*i,

pDC->MoveTo(10*i, h*1500); pDC->LineTo(10*i, h*1500-4*kurv[mo]);

dif:= 0
dif:= 0

Anhang 3: PAP zur Bestimmung des maximalen Wertes (MAX) der Amplituden und des Abstandes zwischen zwei aufeinander folgenden MAX in Pixeln (dif)

j:= mo-70 kurv[j] = j kurv[j]>max/2 kurv[j+1]<max/2
j:= mo-70
kurv[j] =
j
kurv[j]>max/2
kurv[j+1]<max/2

Anhang 4: PAP zur Bestimmung des FWHM

n

mol=j; j:= mo ymol=kurv[mol]; max/2 n kurv[j] = n max/2 j mol=j; && ymol=kurv[mol]; j
mol=j;
j:= mo
ymol=kurv[mol];
max/2
n
kurv[j] =
n
max/2
j
mol=j;
&&
ymol=kurv[mol];
j
mor=j;
ymor=kurv[mor];
n
j++
kurv[j]>max/2
j
mor=j+1;
&&
ymor=max/2;
kurv[j+1]<max/2
n
j< mo+70
j++
j
j++
dif = mor-mol; sprintf(buff,"%d", dif) ; pDC->TextOut(10*(mol-h*4096)-800, h*1500-7*ymor,
dif = mor-mol;
sprintf(buff,"%d", dif) ;
pDC->TextOut(10*(mol-h*4096)-800, h*1500-7*ymor,

Anhang 5: Tabelle aller ermittlelten Werte für die Kurvenparameter MAX,

FWHM und FWTM

Spalte

1

2

3

4

5

6

7

8

9

10

11

12

Max

219

233

224

221

219

225

226

227

216

221

229

214

FWHM_l

46

39

41

40

54

40

45

39

51

43

40

40

FWHM_r

39

41

40

54

40

45

39

51

43

40

40

44

FWTM_l

83

65

71

67

81

62

68

63

81

68

65

63

FWTM_r

65

71

67

81

62

68

63

81

68

65

63

70

Max

227

228

216

228

218

229

219

228

216

226

223

227

FWHM_l

41

45

45

40

49

40

50

40

47

40

47

46

FWHM_r

45

45

40

49

40

50

40

47

40

47

46

39

FWTM_l

66

66

70

62

74

61

79

62

72

63

72

70

FWTM_r

66

70

62

74

61

79

62

72

63

72

70

64

Max

225

224

223

229

214

229

219

231

219

222

226

224

FWHM_l

41

43

42

41

49

40

48

41

49

44

46

42

FWHM_r

43

42

41

49

40

48

41

49

44

46

42

43

FWTM_l

65

67

64

63

75

60

71

61

72

68

64

67

FWTM_r

67

64

63

75

60

71

61

72

68

64

67

66

Max

220

227

224

218

221

224

226

229

217

224

231

215

FWHM_l

38

44

44

41

47

40

51

39

45

41

50

45

FWHM_r

44

44

41

47

40

51

39

45

41

50

45

40

FWTM_l

59

67

71

63

72

67

75

62

68

64

71

69

FWTM_r

67

71

63

72

67

75

62

68

64

71

69

63

Max

220

225

220

225

220

228

222

225

225

216

228

228

FWHM_l

39

41

42

40

50

39

47

39

48

39

46

38

FWHM_r

41

42

40

50

39

47

39

48

39

46

38

44

FWTM_l

62

66

64

62

74

64

71

57

73

63

73

63

FWTM_r

66

64

62

74

64

71

57

73

63

73

63

66

Max

229

223

223

218

221

234

219

222

225

219

231

221

FWHM_l

40

43

43

40

48

39

47

39

50

39

46

41

FWHM_r

43

43

40

48

39

47

39

50

39

46

41

45

FWTM_l

64

63

64

63

69

61

72

58

74

60

71

61

FWTM_r

63

64

63

69

61

72

58

74

60

71

61

69

Max

216

231

216

225

226

221

225

227

221

218

228

213

FWHM_l

41

42

44

39

46

40

46

39

47

41

46

41

FWHM_r

42

44

39

46

40

46

39

47

41

46

41

47

FWTM_l

66

67

67

61

70

58

72

58

71

62

68

65

FWTM_r

67

67

61

70

58

72

58

71

62

68

65

72

Max

225

223

219

228

217

235

214

226

224

215

229

225

FWHM_l

41

40

44

39

49

40

45

40

47

42

45

40

FWHM_r

40

44

39

49

40

45

40

47

42

45

40

48

FWTM_l

65

63