Beispiel #1
0
void MapWindow::DrawVisualGlide(LKSurface& Surface, const DiagrammStruct& sDia) {

    const RECT& rci = sDia.rc;

    unsigned short numboxrows = 1;

#if BUGSTOP
    LKASSERT(Current_Multimap_SizeY < SIZE4);
#endif
    switch (Current_Multimap_SizeY) {
        case SIZE0:
        case SIZE1:
            numboxrows = 3;
            break;
        case SIZE2:
            numboxrows = 2;
            break;
        case SIZE3:
            numboxrows = 1;
            break;
        case SIZE4:
            return;
        default:
            LKASSERT(0);
            break;
    }

    if (!ScreenLandscape) {
        numboxrows++;
        if (numboxrows > 3) numboxrows = 3;
    }

    TCHAR tmpT[30];

    line1Font = LK8VisualTopFont;
    line2Font = LK8VisualBotFont;
    SIZE textSizeTop, textSizeBot;
    Surface.SelectObject(line1Font);
    _stprintf(tmpT, _T("MMMM"));
    Surface.GetTextSize(tmpT, &textSizeTop);
    Surface.SelectObject(line2Font);
    _stprintf(tmpT, _T("55.5%s 79%s%s "), Units::GetDistanceName(), MsgToken(2179), MsgToken(2183));
    Surface.GetTextSize(tmpT, &textSizeBot);

    // we can cut the waypoint name, but not the value data, so we use the second row of data
    // to size the box for everything.
    maxtSizeX = textSizeBot.cx;

    int a = (rci.right-rci.left) / (textSizeBot.cx+BOXINTERVAL);
    int b = (rci.right-rci.left) - a * (textSizeBot.cx)-(BOXINTERVAL * (a + 1));

    boxSizeX = textSizeBot.cx + (b / (a + 1));
    boxSizeY = textSizeTop.cy + 1; // single line (wp name) + distance from bottombar

    if (numboxrows > 1) {
        boxSizeY += (textSizeBot.cy * (numboxrows - 1)) - NIBLSCALE(2);
        if (numboxrows > 2) boxSizeY -= NIBLSCALE(1);
    }

#if DEBUG_SCR
    StartupStore(_T("boxX=%d boxY=%d  \n"), boxSizeX, boxSizeY);
#endif

#if DEBUG_SCR
    StartupStore(_T("VG AREA LTRB: %d,%d %d,%d\n"), rci.left, rci.top, rci.right, rci.bottom);
#endif

    const auto oldBrush = Surface.SelectObject(LKBrush_White);
    const auto oldPen = Surface.SelectObject(LK_BLACK_PEN);

    BrushReference brush_back;
    if (!INVERTCOLORS) {
        brush_back = LKBrush_Black;
    } else {
        brush_back = LKBrush_Nlight;
    }

    Surface.FillRect(&rci, brush_back);

    POINT center, p1, p2;
    center.y = rci.top + (rci.bottom - rci.top) / 2;
    center.x = rci.left + (rci.right - rci.left) / 2;

    // numSlotX is the number items we can print horizontally.
    unsigned short numSlotX = (rci.right - rci.left) / (boxSizeX + BOXINTERVAL);
    if (numSlotX > MAXBSLOT) numSlotX = MAXBSLOT;
#if BUGSTOP
    LKASSERT(numSlotX > 0);
#endif
    if (numSlotX == 0) return;

    unsigned short boxInterval = ((rci.right - rci.left)-(boxSizeX * numSlotX)) / (numSlotX + 1);
    unsigned short oddoffset = ( (rci.right-rci.left) - (boxSizeX * numSlotX) - boxInterval * (numSlotX + 1)) / 2;

    /*
    #if BUGSTOP
    // not really harmful
    LKASSERT(oddoffset<=boxInterval);
    #endif
     */

#if DEBUG_SCR
    StartupStore(_T("numSlotX=%d ScreenSizeX=%d boxSizeX=%d interval=%d offset=%d\n"), numSlotX, ScreenSizeX, boxSizeX, boxInterval, oddoffset);
#endif

    unsigned int t;

    // The horizontal grid
    unsigned int slotCenterX[MAXBSLOT + 1];
    for (t = 0; t < numSlotX; t++) {
        slotCenterX[t] = (t * boxSizeX) + boxInterval * (t + 1)+(boxSizeX / 2) + oddoffset+rci.left;
#if DEBUG_SCR
        StartupStore(_T("slotCenterX[%d]=%d\n"), t, slotCenterX[t]);
#endif
    }

    // Vertical coordinates of each up/down subwindow, excluding center line
    int upYtop = rci.top;
#if MIDCENTER
    int upYbottom = center.y + (boxSizeY / 2);
    int downYtop = center.y - (boxSizeY / 2);
#else
    int upYbottom = center.y - CENTERYSPACE;
    int downYtop = center.y + CENTERYSPACE;
#endif
    int upSizeY = upYbottom - upYtop - (boxSizeY);
    ;
    int downYbottom = rci.bottom;
    int downSizeY = downYbottom - downYtop - (boxSizeY);
    ;

#if 0
    // Reassign dynamically the vertical scale for each subwindow size
    double vscale = 1000 * (100 - Current_Multimap_SizeY) / 100;
#else
    // Set the vertical range
    double vscale;
    if (Units::GetUserAltitudeUnit() == unFeet)
        vscale = (1000 / TOFEET);
    else
        vscale = 300.0;
#endif



    Surface.SetBackgroundTransparent();

    RECT trc = rci;

    // Top part of visual rect, target is over us=unreachable=red
    trc.top = rci.top;
    trc.bottom = center.y - 1;
    #ifndef DITHER
    RenderSky(Surface, trc, RGB_WHITE, LKColor(150, 255, 150), GC_NO_COLOR_STEPS / 2);
    #else
    RenderSky(Surface, trc, RGB_WHITE, RGB_WHITE, GC_NO_COLOR_STEPS / 2);
    #endif
    // Bottom part, target is below us=reachable=green
    trc.top = center.y + 1;
    trc.bottom = rci.bottom;
    #ifndef DITHER
    RenderSky(Surface, trc, LKColor(255, 150, 150), RGB_WHITE, GC_NO_COLOR_STEPS / 2);
    #else
    RenderSky(Surface, trc, RGB_WHITE, RGB_WHITE,GC_NO_COLOR_STEPS / 2);
    #endif

    // Draw center line
    p1.x = rci.left + 1;
    p1.y = center.y;
    p2.x = rci.right - 1;
    p2.y = center.y;
    Surface.SelectObject(LKPen_Black_N1);
    Surface.DrawSolidLine(p1, p2, rci);

#if DEBUG_SCR
    StartupStore(_T("... Center line: Y=%d\n"), center.y);
#endif

    Surface.SelectObject(line1Font);
    Surface.SelectObject(LKPen_Black_N0);

    ResetVisualGlideGlobals();

    short res = GetVisualGlidePoints(numSlotX);

    if (res == INVALID_VALUE) {
#if DEBUG_DVG
        StartupStore(_T("...... GVGP says not ready, wait..\n"));
#endif
        return;
    }
    if (res == 0) {
#if DEBUG_DVG
        StartupStore(_T("...... GVGP says no data available!\n"));
#endif
        return;
    }

    // Print them all!
    int offset = (boxSizeY / 2) + CENTERYSPACE;

    LKBrush bcolor;
    LKColor rgbcolor, textcolor;
    int wp;

    unsigned short zeroslot = 0;
    double minbrgdiff = 999.0;
    double minabrgdiff = 999.0; // absolute never negative
    for (unsigned short n = 0; n < numSlotX; n++) {
        wp = slotWpIndex[n];
        if (!ValidWayPoint(wp)) {
            // empty slot nothing to print
            continue;
        }
        double brgdiff = WayPointCalc[wp].Bearing - DrawInfo.TrackBearing;
        // this check is worthless
        if (brgdiff < -180.0) {
            brgdiff += 360.0;
        } else {
            if (brgdiff > 180.0) brgdiff -= 360.0;
        }
        double abrgdiff = brgdiff;
        if (abrgdiff < 0) abrgdiff *= -1;

        if (abrgdiff < minabrgdiff) {
            zeroslot = n;
            minabrgdiff = abrgdiff;
            minbrgdiff = brgdiff;
        }
    }

    // Draw vertical line
#define DEGRANGE 10	// degrees left and right to perfect target
    if (minabrgdiff < 1) {
        p1.x = slotCenterX[zeroslot];
    } else {
        // set fullscale range
        if (minabrgdiff > DEGRANGE) {
            minabrgdiff = DEGRANGE;
            if (minbrgdiff < 0)
                minbrgdiff = -1 * DEGRANGE;
            else
                minbrgdiff = DEGRANGE;
        }
        // we shift of course in the opposite direction
        p1.x = slotCenterX[zeroslot]-(int) ((boxSizeX / (DEGRANGE * 2)) * minbrgdiff);
    }
    p2.x = p1.x;

    p1.y = rci.top + 1;
    p2.y = rci.bottom - 1;
    Surface.SelectObject(LKPen_Black_N1);
    Surface.DrawSolidLine(p1, p2, rci);



    for (unsigned short n = 0; n < numSlotX; n++) {

        wp = slotWpIndex[n];
        if (!ValidWayPoint(wp)) {
            // empty slot nothing to print
            continue;
        }
#if DEBUG_DVG
        StartupStore(_T("... DVG PRINT [%d]=%d <%s>\n"), n, wp, WayPointList[wp].Name);
#endif

        Sideview_VGWpt[n] = wp;

        double altdiff = WayPointCalc[wp].AltArriv[AltArrivMode];
        int ty;
#if DEBUG_SCR
        StartupStore(_T("... wp=<%s>\n"), WayPointList[wp].Name);
#endif

        // Since terrain can be approximated due to low precision maps, or waypoint position or altitude error,
        // we have a common problem: we get an obstacle to get to the waypoint because it is
        // positioned "BELOW" the terrain itself. We try to reduce this problem here.
#define SAFETERRAIN	50

        // Positive arrival altitude for the waypoint, upper window
        if (altdiff >= 0) {
            if (altdiff == 0)altdiff = 1;
            double d = vscale / altdiff;
            if (d == 0) d = 1;
            ty = upYbottom - (int) ((double) upSizeY / d)-(boxSizeY / 2);
#if DEBUG_SCR
            StartupStore(_T("... upYbottom=%d upSizeY=%d / (vscale=%f/altdiff=%f = %f) =- %d  ty=%d  offset=%d\n"),
                    upYbottom, upSizeY, vscale, altdiff, d, (int) ((double) upSizeY / d), ty, offset);
#endif
            if ((ty - offset) < upYtop) ty = upYtop + offset;
            if ((ty + offset) > upYbottom) ty = upYbottom - offset;
#if DEBUG_SCR
            StartupStore(_T("... upYtop=%d upYbottom=%d final ty=%d\n"), upYtop, upYbottom, ty);
#endif


            //
            // This is too confusing. We want simple colors, not shaded
            // rgbcolor = MixColors( LKColor(50,255,50), LKColor(230,255,230),  altdiff/(vscale-50));
            //

            if (altdiff <= SAFETERRAIN) {
                rgbcolor = RGB_LIGHTYELLOW;
            } else {
                if (!CheckLandableReachableTerrainNew(&DrawInfo, &DerivedDrawInfo,
                        WayPointCalc[wp].Distance, WayPointCalc[wp].Bearing)) {
                    rgbcolor = RGB_LIGHTRED;
                } else {
#ifdef DITHER
                    rgbcolor = RGB_WHITE;
#else
                    rgbcolor = RGB_LIGHTGREEN;
#endif
                }
            }
            bcolor.Create(rgbcolor);

        } else {
            double d = vscale / altdiff;
            if (d == 0) d = -1;
            ty = downYtop - (int) ((double) downSizeY / d)+(boxSizeY / 2); // - because the left part is negative, we are really adding.
            if ((ty - offset) < downYtop) ty = downYtop + offset;
            if ((ty + offset) > downYbottom) ty = downYbottom - offset;

#ifdef DITHER
            rgbcolor = RGB_WHITE; // negative part, no need to render dark
#else
            rgbcolor = RGB_LIGHTRED;
#endif
            bcolor.Create(rgbcolor);
        }

        TCHAR line2[40], line3[40];
        TCHAR value[40], unit[30];
        TCHAR name[NAME_SIZE + 1];
        double ar = (WayPointCalc[wp].AltArriv[AltArrivMode] * ALTITUDEMODIFY);
        _tcscpy(name, WayPointList[wp].Name);
        CharUpper(name);

        if (IsSafetyAltitudeInUse(wp))
            textcolor = RGB_DARKBLUE;
        else
            textcolor = RGB_BLACK;

        switch (numboxrows) {
            case 0:
#if BUGSTOP
                LKASSERT(0);
#endif
                return;

            case 1:
                // 1 line: waypoint name
                VGTextInBox(Surface, n, 1, name, NULL, NULL, slotCenterX[n], ty, textcolor, bcolor);
                break;

            case 2:
                // 2 lines: waypoint name + altdiff
                LKFormatAltDiff(wp, false, value, unit);
                // Should we print also the GR?
                if ((ar >= -9999 && ar <= 9999) && (WayPointCalc[wp].GR < MAXEFFICIENCYSHOW)) {
                    if (ar >= -999 && ar <= 999)
                        _stprintf(line2, _T("%s   "), value);
                    else
                        _stprintf(line2, _T("%s  "), value);
                    LKFormatGR(wp, false, value, unit);
                    _tcscat(line2, value);
                } else {
                    _stprintf(line2, _T("%s   ---"), value);
                }

                VGTextInBox(Surface, n, 2, name, line2, NULL, slotCenterX[n], ty, textcolor, bcolor);
                break;

            case 3:
                // 3 lines: waypoint name + dist + altdiff
                LKFormatDist(wp, false, value, unit);
                _stprintf(line2, _T("%s%s"), value, unit);

                LKFormatBrgDiff(wp, false, value, unit);
                _stprintf(tmpT, _T(" %s%s"), value, unit);
                _tcscat(line2, tmpT);

                LKFormatAltDiff(wp, false, value, unit);
                // Should we print also the GR?
                if ((ar >= -9999 && ar <= 9999) && (WayPointCalc[wp].GR < MAXEFFICIENCYSHOW)) {
                    if (ar >= -999 && ar <= 999)
                        _stprintf(line3, _T("%s   "), value);
                    else
                        _stprintf(line3, _T("%s  "), value);
                    LKFormatGR(wp, false, value, unit);
                    _tcscat(line3, value);
                } else {
                    _stprintf(line3, _T("%s   ---"), value);
                }

                VGTextInBox(Surface, n, 3, name, line2, line3, slotCenterX[n], ty, textcolor, bcolor);
                break;
            default:
#if BUGSTOP
                LKASSERT(0);
#endif
                return;
        }

    } // for numSlotX



    // Cleanup and return
    Surface.SelectObject(oldBrush);
    Surface.SelectObject(oldPen);
    return;
}
short MapWindow::GetVisualGlidePoints(unsigned short numslots) {

#if BUGSTOP
    LKASSERT(numslots <= MAXBSLOT);
#else
    if (numslots > MAXBSLOT) numslots = MAXBSLOT;
#endif

    static short currentFilledNumber = -1;
    static double tmpSlotBrgDiff[MAXBSLOT + 1];

    int i;

    // RESET COMMAND by passing 0, normally by EVENT_NEWRUN 
    if (numslots == 0) {
#if DEBUG_GVG
        StartupStore(_T("...... GVGP: RESET\n"));
#endif
        for (i = 0; i < MAXBSLOT; i++) {
            slotWpIndex[i] = INVALID_VALUE;
        }
        currentFilledNumber = INVALID_VALUE;
        ResetVisualGlideGlobals();

        return INVALID_VALUE;
    }

    bool ndr = NearestDataReady;
    NearestDataReady = false;

    // No data ready..
    // if cfn is -1 we did not ever calculate it yet
    // otherwise 0 or >0  means use what we have already in the list
    if (!ndr) {
#if DEBUG_GVG
        StartupStore(_T("...... GVGP: no data ready, currentFN=%d\n"), currentFilledNumber);
#endif
        return currentFilledNumber;
    }

    if (SortedNumber <= 0) {
#if DEBUG_GVG
        StartupStore(_T("...... GVGP: SortedNumber is 0, no available wpts in this range!\n"));
#endif
        return 0;
    }

    int *pindex;
    int wpindex = 0;
    pindex = SortedTurnpointIndex;
    //
    // Reset  content
    //
    currentFilledNumber = 0;
    for (i = 0; i < MAXBSLOT; i++) {
        slotWpIndex[i] = INVALID_VALUE;
        tmpSlotBrgDiff[i] = -999;
    }

    //
    // set up fine tuned parameters for this run
    //

    int maxgratio = 1, mingratio = 1;
    double maxdistance = 300; // in METERS, not in KM!
    if (ISPARAGLIDER) {
        maxgratio = (int) (GlidePolar::bestld / 2);
        mingratio = (int) (GlidePolar::bestld * 1.5);
        maxdistance = 100;
    }
    if (ISGLIDER) {
        maxgratio = (int) (GlidePolar::bestld / 2);
        mingratio = (int) (GlidePolar::bestld * 1.5);
        maxdistance = 300;
    }
    if (ISGAAIRCRAFT) {
        maxgratio = (int) (GlidePolar::bestld / 2);
        mingratio = (int) (GlidePolar::bestld * 2);
        maxdistance = 300;
    }
    if (ISCAR) {
        maxgratio = 1;
        mingratio = 999;
        maxdistance = 100;
    }

    //
    // WE USE THE 2.3 PAGE (Nearest turnpoints) sorted by DIRECTION
    //

    // We do this in several passes. 
#define MAXPHASES	4
    unsigned short phase = 1;

#if DEBUG_GVG
    StartupStore(_T("GVGP: USING  %d Sorted Items available\n"), SortedNumber);
    int count = 0;
#endif
_tryagain:

    for (i = 0; i < numslots; i++) {
        LKASSERT(phase <= MAXPHASES);
#if DEBUG_GVG
        if (i >= SortedNumber) {
            StartupStore(_T("...... GVGP: PHASE %d warning not enough SortedNumber (%d) for i=%d\n"), phase, SortedNumber, i);
        }
#endif

        // Did we found at least one valid in current phase? Otherwise we skip the rest of numslots.
        // And we pass directly to the next phase.
        bool found = false;

        // look up for an empty slot, needed if running after phase 1
        if (slotWpIndex[i] != INVALID_VALUE) continue;

        // browse results for the best usable items
        for (int k = 0; k < SortedNumber; k++) {
            wpindex = *(pindex + k);
            if (!ValidWayPoint(wpindex)) {
                // since we are not synced with DoNearest update cycle, we might fall here while it
                // has reset the sorted list. No worry, in the worst case we miss a waypoint printed
                // for a second, and the list might be inaccurate for the current second.
                // But in the next run it will be ok, because at the end of its run, the DoNearest
                // will be setting DataReady flag on and we shall update correctly.
                continue;
            }

#if DEBUG_GVG
            count++;
#endif

            // did we already use it?
            bool alreadyused = false;
            for (int j = 0; j < numslots; j++) {
                if (slotWpIndex[j] == INVALID_VALUE) break;
                if (slotWpIndex[j] == wpindex) {
                    alreadyused = true;
                    break;
                }
            }
            if (alreadyused) continue;

            // unused one, decide if good or not
            // We do this in 3 phases..
            double distance = WayPointCalc[wpindex].Distance;
            double brgdiff = WayPointCalc[wpindex].Bearing - DrawInfo.TrackBearing;
            if (brgdiff < -180.0) {
                brgdiff += 360.0;
            } else {
                if (brgdiff > 180.0) brgdiff -= 360.0;
            }
            double abrgdiff = brgdiff;
            if (abrgdiff < 0) abrgdiff *= -1;

#if 0
            // do we already have a wp with same bearing? 
            for (int j = 0; j < numslots; j++) {
                if ((int) tmpSlotBrgDiff[j] == (int) brgdiff) {
                    //StartupStore(_T("%s with bdiff=%d already used\n"),WayPointList[wpindex].Name,(int)brgdiff);
                    alreadyused = true;
                    break;
                }
            }
            if (alreadyused) continue;
#endif

            // Careful: we are selecting abrgdiff from a list that is tuned to max 60, so ok.
            // DIRECTIONRANGE definition in DoNearest

            // Then we make a selective insertion, in several steps

            // First, we pick mountain passes and task points, generally priority #1 points
            // accepted from +-45 deg, but only if they are not absolutely unreachable
            if (phase == 1) {
                if (abrgdiff > 45) continue;
                // if we are practically over the waypoint, skip it 
                if (distance < maxdistance) continue;

                // Consider only Mt.Passes and task points not below us...
                if ((WayPointList[wpindex].Style == STYLE_MTPASS) ||
                        ((WayPointList[wpindex].InTask) && (distance > 100))) {

                    // ... that are not within an obvious glide ratio
                    // (considering even strong headwind, we want a very positive arrival)
                    if (WayPointCalc[wpindex].AltArriv[AltArrivMode] > 150) {
                        if (WayPointCalc[wpindex].GR <= (maxgratio / 1.5)) continue;
                    }
                    if (WayPointCalc[wpindex].AltArriv[AltArrivMode]<-100) {
                        if (WayPointCalc[wpindex].GR >= mingratio) continue;
                    }
                    goto _takeit;
                }
                continue;
            }

            // Second we take anything not obviously reachable
            if (phase == 2) {
                if (abrgdiff > 45) continue;
                if (distance < maxdistance) continue;
                if (WayPointCalc[wpindex].AltArriv[AltArrivMode] > 150) {
                    if (WayPointCalc[wpindex].GR <= (maxgratio)) continue;
                }
                goto _takeit;
            }

            if (phase == 3) {
                if (abrgdiff > 45) continue;
                if (distance < maxdistance) continue;
                goto _takeit;
            }

            // else we accept anything, in the original sort order


_takeit:

            // ok good, use it
            slotWpIndex[i] = wpindex;
            tmpSlotBrgDiff[i] = brgdiff;
            found = true;

#if DEBUG_GVG
            StartupStore(_T("PHASE %d  slot [%d] of %d : wp=%d <%s> brg=%f\n"),
                    phase, i, numslots, wpindex, WayPointList[wpindex].Name, brgdiff);
#endif
            currentFilledNumber++;
            break;
        } // for all sorted wps

        if (!found) {
#if DEBUG_GVG
            StartupStore(_T("PHASE %d  nothing found during search (stop at slot %d), advance to next phase\n"), phase, i >= numslots ? numslots - 1 : i);
#endif
            break;
        }
        if (currentFilledNumber >= numslots) {
#if DEBUG_GVG
            StartupStore(_T("PHASE %d  stop search, all slots taken\n"), phase);
#endif
            break;
        }
    } // for all slots to be filled

    if ((currentFilledNumber < numslots) && (phase < MAXPHASES)) {
#if DEBUG_GVG
        StartupStore(_T("PHASE %d  filled %d of %d slots, going phase %d\n"), phase, currentFilledNumber, numslots, phase + 1);
#endif
        phase++;
        goto _tryagain;
    }
#if DEBUG_GVG
    else {
        StartupStore(_T("PHASE %d  filled %d of %d slots\n"), phase, currentFilledNumber, numslots);
    }
    StartupStore(_T("TOTAL COUNTS=%d\n"), count);
#endif


    //
    // All wpts in the array are shuffled, unsorted by direction.
    // We must reposition them horizontally, using their bearing
    //
    int tmpSlotWpIndex[MAXBSLOT + 1];
    for (i = 0; i < MAXBSLOT; i++) tmpSlotWpIndex[i] = INVALID_VALUE;

#if DEBUG_GVG
    for (i = 0; i < numslots; i++) {
        StartupStore(_T(">>> [%d] %f  (wp=%d)\n"), i, tmpSlotBrgDiff[i], slotWpIndex[i]);
    }
#endif

    bool invalid = true, valid = false;
    unsigned short g;

    for (unsigned short nslot = 0; nslot < numslots; nslot++) {
        g = 0;
        double minim = 999;
        valid = false;
#if DEBUGSORT
        StartupStore(_T(".... Slot [%d]:\n"), nslot);
#endif
        for (unsigned short k = 0; k < numslots; k++) {
            if (tmpSlotBrgDiff[k] <= minim) {
                // is this already used?
                invalid = false;
                if (slotWpIndex[k] == -1) {
#if DEBUGSORT
                    StartupStore(_T(".... not using g=%d, it is an invalid waypoint\n"), k);
#endif
                    continue;
                }
                for (unsigned short n = 0; n < nslot; n++) {
                    if (tmpSlotWpIndex[n] == slotWpIndex[k]) {
#if DEBUGSORT
                        StartupStore(_T(".... not using g=%d, it is already used in newslot=%d\n"), k, n);
#endif
                        invalid = true;
                        continue;
                    }
                }

                if (invalid || !ValidWayPoint(slotWpIndex[k])) continue;

                // We do have a valid choice 
                g = k;
                minim = tmpSlotBrgDiff[k];
#if DEBUGSORT
                StartupStore(_T(".... minim=%f g=%d\n"), minim, g);
#endif
                valid = true;
            }
        }

        if (valid) {
            tmpSlotWpIndex[nslot] = slotWpIndex[g];
#if DEBUGSORT
            StartupStore(_T(".... FINAL for SLOT %d:  minim=%f g=%d\n"), nslot, minim, g);
#endif
        }
#if DEBUGSORT
        else {
            StartupStore(_T(".... FINAL for SLOT %d:  no valid point\n"), nslot);
        }
#endif
    }


    for (i = 0; i < numslots; i++) {
        slotWpIndex[i] = tmpSlotWpIndex[i];
    }

    return currentFilledNumber;
}