File: AUTOJUST\TRANSFRM.CPP

    1 #include "utils\u_utils.h"
    2 
    3 #include "detecuse\detecuse.h"
    4 #include "motrstrg\motrstrg.h"
    5 #include "swintrac\m_dlg.h"
    6 
    7 // Module für die automatische Justage
    8 #include "autojust\autojust.h"
    9 
   10 #include "autojust\matrix.h"
   11 #include "autojust\transfrm.h"
   12 #include "autojust\m_justag.h"
   13 
   14 #pragma hdrstop
   15 
   16 //--||--\\--||--//--||--\\--||--//--||--\\--||--//--||--\\--||--//--||--\\--||--
   17 
   18 //! definiert in m_justage.cpp
   19 extern int nMotorDF, nMotorTL, nMotorCC;
   20 extern bool bWriteLogfile;
   21 
   22 const double GOLD= 0.61803;
   23 
   24 // *************************************************************************
   25 // ***************** Transformationsklasse *********************************
   26 // zur Durchführung von Koordinatentransformationen
   27 
   28 
   29 // Konstruktor
   30 TransformationClass::TransformationClass(void) : buf(0), buf1(0)
   31 {
   32         TVektor tempVektor(0, 0, 0);
   33         PosVektor= tempVektor;
   34         anzahl_koordinatentrafos= 0;
   35         bIntensityTooHigh= false;
   36 
   37         buf= new char[1024];
   38         if (!buf)
   39         {
   40                 MessageBox(GetFocus(), "Fehler bei Speicherreservierung", "TransformationClass", MBSTOP);
   41                 PostQuitMessage( -1);
   42         }
   43         else
   44         {
   45                 buf1= new char[1024];
   46                 if (!buf1)
   47                 {
   48                         MessageBox(GetFocus(), "Fehler bei Speicherreservierung", "TransformationClass", MBSTOP);
   49                         PostQuitMessage( -1);
   50                 }
   51         }
   52 }
   53 
   54 // Destruktor
   55 TransformationClass::~TransformationClass(void)
   56 {
   57         _FREELIST(buf);
   58         _FREELIST(buf1);
   59 }
   60 
   61 // Initialisierung der Intervallgrenzen der Motoren
   62 bool TransformationClass::Initialize(double MaxDF, double MaxTL, double MaxCC)
   63 {
   64         double fPosition, fTemp;
   65         // Ermittlung der aktuellen Motorpositionen und
   66         // Festlegen der Intervallgrenzen zur Justage
   67         // Antrieb:Tilt
   68         // setzen der aktuellen Antriebsachse
   69         mlSetAxis(nMotorTL);
   70         // aktuelle Position des Antriebs bestimmen
   71         mGetDistance(fPosition);
   72         Wertebereich.OrigTL= fPosition;
   73         // Tilt: Wertebereich +/- 20 Minuten
   74         Wertebereich.MinTL= ( -1) * MaxTL;
   75         Wertebereich.MaxTL= MaxTL;
   76         // Antrieb:Beugung fein
   77         mlSetAxis(nMotorDF);
   78         mGetDistance(fPosition);
   79         Wertebereich.OrigDF= fPosition;
   80         // DF: Wertebereich +/- 200 Sekunden
   81         Wertebereich.MinDF= ( -1) * MaxDF;
   82         Wertebereich.MaxDF= MaxDF;
   83         // Antrieb:Kollimator
   84         mlSetAxis(nMotorCC);
   85         mGetDistance(fPosition);
   86         Wertebereich.OrigCC= fPosition;
   87         // CC: Wertebereich +/- 100 Mikrometer
   88         Wertebereich.MinCC= ( -1) * MaxCC;
   89         Wertebereich.MaxCC= MaxCC;
   90         // Vergleich mit Softwareschranken und ggf. Änderung der Wertebereiche
   91         if ((fTemp= mlGetValue(nMotorTL, MinDistance)) > Wertebereich.MinTL +
   92                         Wertebereich.OrigTL)
   93         {
   94                 Wertebereich.MinTL= fTemp - Wertebereich.OrigTL;
   95         }
   96         if ((fTemp= mlGetValue(nMotorTL, MaxDistance)) < Wertebereich.MaxTL +
   97                         Wertebereich.OrigTL)
   98         {
   99                 Wertebereich.MaxTL= fTemp - Wertebereich.OrigTL;
  100         }
  101         if ((fTemp= mlGetValue(nMotorDF, MinDistance)) > Wertebereich.MinDF +
  102                         Wertebereich.OrigDF)
  103         {
  104                 Wertebereich.MinDF= fTemp - Wertebereich.OrigDF;
  105         }
  106         if ((fTemp= mlGetValue(nMotorDF, MaxDistance)) < Wertebereich.MaxDF +
  107                         Wertebereich.OrigDF)
  108         {
  109                 Wertebereich.MaxDF= fTemp - Wertebereich.OrigDF;
  110         }
  111         if ((fTemp= mlGetValue(nMotorCC, MinDistance)) > Wertebereich.MinCC +
  112                         Wertebereich.OrigCC)
  113         {
  114                 Wertebereich.MinCC= fTemp - Wertebereich.OrigCC;
  115         }
  116         if ((fTemp= mlGetValue(nMotorCC, MaxDistance)) < Wertebereich.MaxCC +
  117                         Wertebereich.OrigCC)
  118         {
  119                 Wertebereich.MaxCC= fTemp - Wertebereich.OrigCC;
  120         }
  121         return true;
  122 }
  123 
  124 
  125 // Berechnung der Weltkoordinaten eines Punktes im akt. KS
  126 TVektor TransformationClass::translate_from_worldpoints(TVektor OrigVektor)
  127 {
  128         // 1. vektor homogen machen
  129         OrigVektor.mache_homogen();
  130 
  131         // 2. (HIN-Transformation)
  132         // Multiplikation des homog. Vektors mit den Trafo-Matrizen von Anfang an
  133         // (1. bis letzte Trafo-Matrix durchlaufen)
  134         for (unsigned i= 1; i <= trafo_hin.elementanzahl(); i++)
  135         {
  136                 OrigVektor= trafo_hin.zeige(i) * OrigVektor;
  137         }
  138 
  139         // 3. Rückgabe des Vektors in kartesischer Form
  140         return OrigVektor.mache_kartesisch();
  141 }
  142 
  143 // Umrechnung eines Punktes im Welt-KS in Koordinaten im akt. KS
  144 TVektor TransformationClass::translate_to_worldpoints(TVektor OrigVektor)
  145 {
  146         // 1. vektor homogen machen
  147         OrigVektor.mache_homogen();
  148 
  149         // 2. (RÜCK-Transformation)
  150         //    Multiplikation des homog. Vektors mit den Trafo-Matrizen
  151         //    vom Ende der Liste bis zum Anfang
  152         for (unsigned i= trafo_rueck.elementanzahl(); i > 0; i--)
  153         {
  154                 OrigVektor= trafo_rueck.zeige(i) * OrigVektor;
  155         }
  156 
  157         // 3. Rückgabe des Vektors in kartesischer Form
  158         return OrigVektor.mache_kartesisch();
  159 }
  160 
  161 
  162 // Übersetzung der Originalintervalle in akt. Koordinaten
  163 TMotorPositionsWerte TransformationClass::translate_PosBorders(void)
  164 {
  165         TVektor Punkt3D(3);
  166         TMotorPositionsWerte Intervalle;
  167         double X, Y, Z;
  168 
  169         // Übersetzung der Intervalle in akt. Koordinaten
  170         // unbedingt mit Vergleich der Softwareschranken !!!
  171         // d.h. notwendige Rückrechnung (translate_to_worldpoints)
  172         // der akt. Schranken in Weltkoordinaten
  173         // aktSchranke(x,y,z) -> weltkoord_aktSchranke(x_w,y_w,z_w)
  174         // x_w-Werte mit Wertebereich.Min/MaxTL bzw. Softwareschranke vergl. usw.
  175 
  176         // Intervallgrenzen aus Wertebereich für TL umrechnen
  177         Punkt3D.set_XYZ(Wertebereich.MinTL, 0, 0);
  178         Punkt3D= translate_from_worldpoints(Punkt3D);
  179         Punkt3D.get_XYZ(Intervalle.MinTL, Y, Z);
  180         Punkt3D.set_XYZ(Wertebereich.MaxTL, 0, 0);
  181         Punkt3D= translate_from_worldpoints(Punkt3D);
  182         Punkt3D.get_XYZ(Intervalle.MaxTL, Y, Z);
  183 
  184         // Intervallgrenzen für DF umrechnen
  185         Punkt3D.set_XYZ(0, Wertebereich.MinDF, 0);
  186         Punkt3D= translate_from_worldpoints(Punkt3D);
  187         Punkt3D.get_XYZ(X, Intervalle.MinDF, Z);
  188         Punkt3D.set_XYZ(0, Wertebereich.MaxDF, 0);
  189         Punkt3D= translate_from_worldpoints(Punkt3D);
  190         Punkt3D.get_XYZ(X, Intervalle.MaxDF, Z);
  191 
  192         // Intervallgrenzen für TL umrechnen
  193         Punkt3D.set_XYZ(0, 0, Wertebereich.MinCC);
  194         Punkt3D= translate_from_worldpoints(Punkt3D);
  195         Punkt3D.get_XYZ(X, Y, Intervalle.MinCC);
  196         Punkt3D.set_XYZ(0, 0, Wertebereich.MaxCC);
  197         Punkt3D= translate_from_worldpoints(Punkt3D);
  198         Punkt3D.get_XYZ(X, Y, Intervalle.MaxCC);
  199 
  200         return Intervalle;
  201 }
  202 
  203 float TransformationClass::GetIntensityOnPosition(unsigned nMeasureCount)
  204 // fährt die zu übersetzenden (TRAFO Klasse) Motorpositionen des Vektors an
  205 // und gibt Intensität zurück
  206 // muss alle 3 Motorachsen anfahren
  207 // 1. translate_to_worldpoints(akt.anzufahrenderPosVektor)
  208 // 2. worldkoordinaten-Vektor.get_XYZ(&x,&y,&z)
  209 // 3. nMotorTL mMoveToDistance (x + Wertebereich.OrigTL) weil Ursprung (0,0,0)
  210 //    nMotorDF mMoveToDistance (y + Wertebereich.OrigDF)
  211 //    nMotorCC mMoveToDistance (z + Wertebereich.OrigCC)
  212 // 4. Rückgabe der Intensität
  213 {
  214         float fIntensity;
  215         double x, y, z, x2, y2, z2;
  216 
  217         // Infos fürs Logging aufbereiten
  218         PosVektor.get_XYZ(x2, y2, z2);
  219         sprintf(buf, "Move2Dist:aktVektor (%.2f,%.2f,%.2f) -> ", x2, y2, z2);
  220 
  221         // Umrechnung des PosVektors in Weltkoordinaten
  222         PosVektor= translate_to_worldpoints(PosVektor);
  223 
  224         // Infos fürs Logging aufbereiten
  225         PosVektor.get_XYZ(x, y, z);
  226         sprintf(buf1, "weltVektor (%.2f,%.2f,%.2f)[%d.KS]", x, y, z,
  227                         get_koordinatentrafos());
  228         strcat (buf, buf1);
  229         // ins Logfile schreiben
  230         if (bWriteLogfile)
  231                 WriteToJustageLog(buf);
  232 
  233         // Auslesen der Weltkoordinaten des PosVektors
  234         PosVektor.get_XYZ(x, y, z);
  235 
  236         // setzen der Antriebsachse TL und Anfahren der TL-Position
  237         mlSetAxis(nMotorTL);
  238         mMoveToDistance (x + GetOrigPosBorders().OrigTL);
  239         // setzen der Antriebsachse DF und Anfahren der DF-Position
  240         while (!mIsMoveFinish())
  241                 ProcessMessages(1)/* wait until finish */;
  242         SetCursor( LoadCursor(NULL,IDC_WAIT) );
  243 
  244         mlSetAxis(nMotorDF);
  245         mMoveToDistance (y + GetOrigPosBorders().OrigDF);
  246         // setzen der Antriebsachse CC und Anfahren der CC-Position
  247         while (!mIsMoveFinish())
  248                 ProcessMessages(1)/* wait until finish */;
  249         SetCursor( LoadCursor(NULL,IDC_WAIT) );
  250 
  251         mlSetAxis(nMotorCC);
  252         mMoveToDistance (z + GetOrigPosBorders().OrigCC);
  253         // Warten bis Bewegung beendet ist
  254         while (!mIsMoveFinish())
  255                 ProcessMessages(1)/* wait until finish */;
  256         SetCursor( LoadCursor(NULL,IDC_WAIT) );
  257 
  258         // Median ausgeben
  259         fIntensity= MeasureIntensity(nMeasureCount);    
  260         if ( TCounterWindow::GetWindow() ) TCounterWindow::GetWindow()->ShowCounterSetRequest(fIntensity); // sprintf(buf, "I: %.0f", fIntensity); SetInfo(buf);
  261 
  262         // ins Logfile schreiben
  263         strcat(buf, "\n");
  264         if (bWriteLogfile)
  265                 WriteToJustageLog(buf);
  266         // Werte für den PosVektor zurückschreiben
  267         PosVektor.set_XYZ(x2, y2, z2);
  268         return fIntensity;
  269 }
  270 
  271 
  272 int TransformationClass::Goldener_Schnitt(ELaufachse achse,
  273                 double & intervall_li, double & intervall_re,
  274                 unsigned nMeasureCount)
  275 {
  276         double a, b, u, v, fu, fv, x, y, z;
  277         int step;
  278 
  279         a= intervall_li;
  280         b= intervall_re;
  281 
  282         u= GOLD * a + (1 - GOLD) * b;
  283         v= (1 - GOLD) * a + GOLD * b;
  284 
  285         // Komponenten des Positionsvektors auslesen
  286         PosVektor.get_XYZ(x, y, z);
  287 
  288         // # Logging #
  289         sprintf(buf, ">>GoldenerSchnitt: PosVektor (%.2f,%.2f,%.2f)\n", x, y, z);
  290         if (bWriteLogfile)
  291                 WriteToJustageLog(buf);
  292 
  293         switch (achse)
  294         {
  295                 case Laufachse_X:   // Setzen der jew. Komponente im PosVektor
  296                         PosVektor.set_XYZ(u, y, z);
  297                         // Bestimmung der Intensität
  298                         fu= GetIntensityOnPosition(nMeasureCount);
  299                         PosVektor.set_XYZ(v, y, z);
  300                         fv= GetIntensityOnPosition(nMeasureCount);
  301                         break;
  302 
  303                 case Laufachse_Y:
  304                         PosVektor.set_XYZ(x, u, z);
  305                         fu= GetIntensityOnPosition(nMeasureCount);
  306                         PosVektor.set_XYZ(x, v, z);
  307                         fv= GetIntensityOnPosition(nMeasureCount);
  308                         break;
  309 
  310                 case Laufachse_Z:
  311                         PosVektor.set_XYZ(x, y, u);
  312                         fu= GetIntensityOnPosition(nMeasureCount);
  313                         PosVektor.set_XYZ(x, y, v);
  314                         fv= GetIntensityOnPosition(nMeasureCount);
  315                         break;
  316 
  317                 default:
  318                         return -1;
  319         }
  320 
  321         step= 2;
  322 
  323         while ( (fabs(a - b) > toleranz) )
  324         {
  325                 if (fu > fv)
  326                 {
  327                         b= v; // re. Intervallgrenze nach links verschieben
  328                         v= u;
  329                         u= GOLD * a + (1 - GOLD) * b; // neue li. Intervall-Position
  330                         fv= fu;
  331                         // Bestimmung des neuen Funktionswertes  (Intensität)
  332                         switch (achse)
  333                         {
  334                                 case Laufachse_X:
  335                                         PosVektor.set_XYZ(u, y, z);
  336                                         fu= GetIntensityOnPosition(nMeasureCount);
  337                                         break;
  338 
  339                                 case Laufachse_Y:
  340                                         PosVektor.set_XYZ(x, u, z);
  341                                         fu= GetIntensityOnPosition(nMeasureCount);
  342                                         break;
  343 
  344                                 case Laufachse_Z:
  345                                         PosVektor.set_XYZ(x, y, u);
  346                                         fu= GetIntensityOnPosition(nMeasureCount);
  347                                         break;
  348                         }
  349                         step++;
  350                 }
  351                 else // wenn (fu <= fv)
  352                 {
  353                         a= u; // li. Intervallgrenze nach rechts verschieben
  354                         u= v;
  355                         v= (1 - GOLD) * a + GOLD * b; // neue re. Intervall-Position
  356                         fu= fv;
  357                         // Bestimmung des neuen Funktionswertes (Intensität)
  358                         switch (achse)
  359                         {
  360                                 case Laufachse_X:
  361                                         PosVektor.set_XYZ(v, y, z);
  362                                         fv= GetIntensityOnPosition(nMeasureCount);
  363                                         break;
  364 
  365                                 case Laufachse_Y:
  366                                         PosVektor.set_XYZ(x, v, z);
  367                                         fv= GetIntensityOnPosition(nMeasureCount);
  368                                         break;
  369 
  370                                 case Laufachse_Z:
  371                                         PosVektor.set_XYZ(x, y, v);
  372                                         fv= GetIntensityOnPosition(nMeasureCount);
  373                                         break;
  374                         }
  375                         step++;
  376                 }
  377         }
  378         intervall_li= u;
  379         intervall_re= v;
  380         return step;
  381 }
  382 
  383 float TransformationClass::MeasureIntensity(unsigned nMeasureCount)
  384 {
  385         float fIntensity, fIntensity_temp, ftemp, fMedian;
  386         unsigned counter= 0;
  387         float *Medianliste= 0;
  388 
  389         // Speicher für Medianliste reservieren
  390         Medianliste= new float[nMeasureCount+1];
  391         if (!Medianliste)
  392         {
  393                 MessageBox(GetFocus(), "Fehler bei Speicherreservierung", "MeasureIntensity", MBSTOP);
  394                 PostQuitMessage( -1);
  395         }
  396         // aktuelles Zählergerät setzen
  397         TDetector *Detektor= TDetectorManager::DetectorManager().GetDetector();
  398         do
  399         {
  400                 // Zähler starten
  401                 Detektor->MeasureStart();
  402 
  403                 // Auslesen der Detektorkarte veranlassen
  404                 // im Fehlerfall muss die Messung neugestartet werden
  405                 while (Detektor->PollDetector() != R_MeasOk)
  406                 {
  407                         // Messung neustarten
  408                         // Detektor->MeasureStop();
  409                         SetInfo("Warte auf Messwerte...");
  410                         //Detektor->MeasureStart();
  411                 }
  412                 // Intensität auslesen (Membervariable fIntensity von Sensor)
  413                 while (Detektor->GetIntegral(fIntensity) != R_OK)
  414                 {
  415                         SetInfo("Hole Daten vom Counter...");
  416                 }
  417 
  418                 // erfolgreiche Messung
  419                 counter++;
  420 
  421                 // Medianliste erweitern & sortieren *****
  422                 fIntensity_temp= fIntensity;            
  423 
  424                 if (fIntensity > 100000.0)
  425                 {
  426                         if (!bIntensityTooHigh)
  427                         {
  428                                 MessageBox(GetFocus(), "MeasureIntensity: Die Maximalanzahl von 100.000\n"
  429                                                    "Detektorcounts wurde überschritten.\n\n"
  430                                                    "Die 'Automatische Justage' wird abgebrochen.\n"
  431                                                    "Bitte regeln Sie die Spannung des Röntgengenerators nach.\n",
  432                                                    "Überschreitung des Detektormaximums", MBINFO);
  433                                 bIntensityTooHigh= true;
  434                         }
  435                 }               
  436 
  437                 // noch keine Messwerte in der Liste
  438                 if ((counter - 1) == 0)
  439                 {
  440                         Medianliste[0]= fIntensity_temp;
  441                 }
  442                 // Messwertliste besteht schon
  443                 else
  444                 {
  445                         // solange bis alle bisherigen Messwerte durchgelaufen wurden
  446                         for (int i= 0; i < counter - 1; i++)
  447                         {
  448                                 // kleine Elemente zuerst einsortieren
  449                                 if (fIntensity_temp < Medianliste[i])
  450                                 {
  451                                         // Wert an der akt. Stelle merken
  452                                         ftemp= Medianliste[i];
  453                                         // Wert an der akt. Stelle durch Messwert ersetzen
  454                                         Medianliste[i]= fIntensity_temp;
  455                                         // Trick, um die weiteren Elemente durchzusortieren
  456                                         fIntensity_temp= ftemp;
  457                                 }
  458                         }
  459                         // übrig gebliebener Wert wird ans Ende angehängt
  460                         Medianliste[counter - 1]= fIntensity_temp;
  461                 }
  462 
  463                 // Medianbestimmung
  464                 // ungerade Anzahl von Messungen
  465                 if ((counter % 2) == 1)
  466                 {
  467                         if (counter == 1)
  468                         {
  469                                 // einziges Element
  470                                 fMedian= Medianliste[counter - 1];
  471                         }
  472                         else
  473                         {
  474                                 // mittleres Element der Medianliste
  475                                 fMedian= Medianliste[((counter + 1) / 2) - 1];
  476                         }
  477                 }
  478                 // gerade Anzahl von Messungen
  479                 else
  480                 {
  481                         // Mittelwert der beiden mittleren Elemente
  482                         fMedian= (Medianliste[(counter / 2) - 1] + Medianliste[((counter / 2) + 1) - 1]) / 2;
  483                 }
  484                 // Infos ins Logfile schreiben
  485                 if (bWriteLogfile)
  486                 {
  487                         sprintf(buf, "\r\nM:%d I:%.2f Median:%.2f ", counter, fIntensity, fMedian);
  488                         WriteToJustageLog(buf);
  489                 }
  490 
  491         }
  492         while (counter < nMeasureCount);
  493         _FREELIST(Medianliste);
  494         return fMedian;
  495 }
  496 
  497 // Durchführung einer kompletten Koordinatentransformation um best. Achse
  498 bool TransformationClass::KoordinatenTransformation(EDrehachse achse,
  499                 TVektor VerschiebeVektor)
  500 {
  501         TVektor Einheitsvektor(3);
  502         TMatrix Matrix;
  503         double winkel;
  504 
  505         switch (achse)
  506         {
  507                 case Drehachse_X:   // Einheitsvektor der Z-Achse
  508                         Einheitsvektor.set_XYZ(0, 0, 1);
  509                         break;
  510 
  511                 case Drehachse_Z:   // Einheitsvektor der X-Achse
  512                         Einheitsvektor.set_XYZ(1, 0, 0);
  513                         break;
  514 
  515                 default: // bei Automatischer Justage wird nur um X bzw. Z gedreht
  516                         return false;
  517         }
  518 
  519         // Berechnung des Winkels von Vektor zur Koordinatenachse (Einheitsvektor)
  520         winkel= VerschiebeVektor.winkel(Einheitsvektor);
  521 
  522         // Ausführung der jew. KS-Transformation (Hin - und Rück)
  523         // Drehung um X-Achse
  524         if (achse == Drehachse_X)
  525         {
  526                 // Abspeichern der Hintransformation
  527                 Matrix.transformiere(XYZ, ( -1)*VerschiebeVektor, -winkel, 0, 0);
  528                 trafo_hin.push(Matrix);
  529                 // Abspeichern der Rücktransformation
  530                 Matrix.transformiere(ZYX, VerschiebeVektor, winkel, 0, 0);
  531                 trafo_rueck.push(Matrix);
  532         }
  533         // Drehung um Z-Achse
  534         else if (achse == Drehachse_Z)
  535         {
  536                 // Abspeichern der Hintransformation
  537                 Matrix.transformiere(XYZ, ( -1)*VerschiebeVektor, 0, 0, -winkel);
  538                 trafo_hin.push(Matrix);
  539                 // Abspeichern der Rücktransformation
  540                 Matrix.transformiere(ZYX, VerschiebeVektor, 0, 0, winkel);
  541                 trafo_rueck.push(Matrix);
  542         }
  543 
  544         anzahl_koordinatentrafos ++;
  545 
  546         // # Logging #
  547         sprintf(buf, "%d. KS-Drehung: Winkel= %.2f Grad\n", anzahl_koordinatentrafos,
  548                         winkel*180 / M_PI);
  549         if (bWriteLogfile)
  550                 WriteToJustageLog(buf);
  551 
  552         return true;
  553 }
  554 
  555 void TransformationClass::DFCorrection(unsigned nMeasureCount, double & fDFPos,
  556                                                                            float & fInt)
  557 {
  558         double a, b, u, v, fu, fv;
  559         double fPosition, toleranz= .1;
  560 
  561         // Intervallgrösse selbst angeben
  562         // Bereich kann klein sein (DF: sek)
  563         a= -5;
  564         b= 5;
  565 
  566         u= GOLD * a + (1 - GOLD) * b;
  567         v= (1 - GOLD) * a + GOLD * b;
  568 
  569         // Position festlegen
  570         mlSetAxis(nMotorDF);
  571         mGetDistance(fPosition);
  572         mMoveToDistance(u + fPosition);
  573         while (!mIsMoveFinish())
  574                 ProcessMessages(1)/* wait until finish */;
  575         SetCursor( LoadCursor(NULL,IDC_WAIT) );
  576         fu= MeasureIntensity(nMeasureCount);
  577 
  578         mMoveToDistance(v + fPosition);
  579         while (!mIsMoveFinish())
  580                 ProcessMessages(1)/* wait until finish */;
  581         SetCursor( LoadCursor(NULL,IDC_WAIT) );
  582         fv= MeasureIntensity(nMeasureCount);
  583 
  584         while ((fabs(a - b) > toleranz))
  585         {
  586                 if (fu > fv)
  587                 {
  588                         b= v; // re. Intervallgrenze nach links verschieben
  589                         v= u;
  590                         u= GOLD * a + (1 - GOLD) * b; // neue li. Intervall-Position
  591                         fv= fu;
  592                         // Bestimmung des neuen Funktionswertes (Intensität)
  593                         mMoveToDistance(u + fPosition);
  594                         while (!mIsMoveFinish())
  595                                 ProcessMessages(1)/* wait until finish */;
  596                         SetCursor( LoadCursor(NULL,IDC_WAIT) );
  597                         fu= MeasureIntensity(nMeasureCount);
  598                 }
  599                 else // if (fu <= fv)
  600                 {
  601                         a= u; // li. Intervallgrenze nach rechts verschieben
  602                         u= v;
  603                         v= (1 - GOLD) * a + GOLD * b; // neue re. Intervall-Position
  604                         fu= fv;
  605                         // Bestimmung des neuen Funktionswertes (Intensität)
  606                         mMoveToDistance(v + fPosition);
  607                         while (!mIsMoveFinish())
  608                                 ProcessMessages(1)/* wait until finish */;
  609                         SetCursor( LoadCursor(NULL,IDC_WAIT) );
  610                         fv= MeasureIntensity(nMeasureCount);
  611                 }
  612         }
  613         // Intensität & Position zurückliefern
  614         fInt= fv;
  615         fDFPos= v + fPosition;
  616         // Position angefahren
  617 }
  618 
  619 
  620