예제 #1
0
//
// Sollfarh / Dolphin Speed calculator
//
void SpeedToFly(NMEA_INFO *Basic, DERIVED_INFO *Calculated) {


    if (((AutoMcMode == amcFinalGlide) || (AutoMcMode == amcFinalAndClimb)) 
            && DoOptimizeRoute() && Calculated->NextAltitude > 0.) {

        // Special case for Conical end of Speed section
        int Type = -1;
        double ConeSlope = 0.0;
        LockTaskData();
        if (ValidTaskPoint(ActiveWayPoint)) {
            GetTaskSectorParameter(ActiveWayPoint, &Type, NULL);
            ConeSlope = Task[ActiveWayPoint].PGConeSlope;
        }
        UnlockTaskData();
        if (Type == CONE && ConeSlope > 0.0) {
            double VOpt = GlidePolar::FindSpeedForSlope(ConeSlope);
            double eqMC = GlidePolar::EquMC(VOpt);
            if(eqMC <= MACCREADY ) {
                Calculated->VOpt = VOpt;
                return;
            }
        }
    }

    double HeadWind = 0;
    if (Calculated->FinalGlide && ValidTaskPoint(ActiveWayPoint)) {
        // according to MC theory STF take account of wind only if on final Glide
        // TODO : for the future add config parameter for always use wind.
        if (Calculated->HeadWind != -999) {
            HeadWind = Calculated->HeadWind;
        }
    }

    // this is IAS for best Ground Glide ratio acounting current air mass ( wind / Netto vario )
    double VOptnew = GlidePolar::STF(MACCREADY, Calculated->NettoVario, HeadWind);

    // apply cruises efficiency factor.
    VOptnew *= CRUISE_EFFICIENCY;
    
    if (Calculated->NettoVario > MACCREADY) {
        // this air mass is better than maccready, so don't fly at speed less than minimum sink speed adjusted for load factor
        double n = fabs((Basic->AccelerationAvailable) ? Basic->AccelZ : Calculated->Gload);
        VOptnew = max(VOptnew, GlidePolar::Vminsink() * sqrt(n));
    } else {
        // never fly at speed less than min sink speed
        VOptnew = max(VOptnew, GlidePolar::Vminsink());
    }

    // use low pass filter for avoid big jump of value.
    Calculated->VOpt = LowPassFilter(Calculated->VOpt, VOptnew, 0.6);
}
예제 #2
0
파일: PGTaskMgr.cpp 프로젝트: LK8000/LK8000
void PGTaskMgr::Initialize() {

    std::for_each(m_Task.begin(), m_Task.end(), safe_delete());
    m_Task.clear();

    // build Mercator Reference Grid
    // find center of Task
    double minlat = 0.0, minlon = 0.0, maxlat = 0.0, maxlon = 0.0;
    for (int curwp = 0; ValidTaskPoint(curwp); ++curwp) {
        if (curwp == 0) {
            maxlat = minlat = WayPointList[Task[curwp].Index].Latitude;
            maxlon = minlon = WayPointList[Task[curwp].Index].Longitude;
        } else {
            minlat = std::min(minlat, WayPointList[Task[curwp].Index].Latitude);
            maxlat = std::max(maxlat, WayPointList[Task[curwp].Index].Latitude);

            minlon = std::min(minlon, WayPointList[Task[curwp].Index].Longitude);
            maxlon = std::max(maxlon, WayPointList[Task[curwp].Index].Longitude);
        }
    }

    m_Grid.lat0 = deg2rad(minlat + maxlat) * 1 / 2;
    m_Grid.lon0 = deg2rad(minlon + maxlon) * 1 / 2;
    m_Grid.k0 = 1;
    m_Grid.false_e = 0.0; // ????
    m_Grid.false_n = 0.0; // ????

    // build task point list
    for (int curwp = 0; ValidTaskPoint(curwp); ++curwp) {
        int TpType = 0;
        double Radius;
        GetTaskSectorParameter(curwp, &TpType, &Radius);
        switch (TpType) {
            case CIRCLE:
                AddCircle(curwp);
                break;
            case SECTOR:
            case DAe:
                AddSector(curwp);
                break;
            case LINE:
                AddLine(curwp);
                break;
            case CONE:
                AddCone(curwp);
                break;
            case ESS_CIRCLE:
                AddEssCircle(curwp);
                break;
        }
    }
}
예제 #3
0
void DoAutoMacCready(NMEA_INFO *Basic, DERIVED_INFO *Calculated) {

    if (!Calculated->AutoMacCready) return;

    bool is_final_glide = false;
    bool is_conical_ess = false;

    double ConeSlope = 0.0;

    //  LockFlightData();
    LockTaskData();

    double mc_new = MACCREADY;
    static bool first_mc = true;

    if (AutoMcMode == amcEquivalent) {
        if ((!Calculated->Circling) && (!Calculated->OnGround)) {
            if (Calculated->EqMc >= 0) {
                // MACCREADY = LowPassFilter(MACCREADY,Calculated->EqMc,0.8);
                CheckSetMACCREADY(Calculated->EqMc);
            } else {
                // -1.0 is used as an invalid flag. Normally flying at -1 MC means almost flying
                // at stall speed, which is pretty unusual. Maybe in wave conditions?
                if (Calculated->EqMc >-1) {
                    CheckSetMACCREADY(Calculated->EqMc*-1);
                }
            }
        }
        UnlockTaskData();
        return;
    }

    // otherwise, if AutoMc for finalglide or "both", return if no goto
    if (ValidTaskPoint(ActiveWayPoint)) {
        if (Calculated->FinalGlide && ActiveIsFinalWaypoint()) {
            is_final_glide = true;
        } else {
            first_mc = true;
        }

        if (DoOptimizeRoute() && Calculated->NextAltitude > 0.) {
            // Special case for Conical end of Speed section
            int Type = -1;
            GetTaskSectorParameter(ActiveWayPoint, &Type, NULL);
            ConeSlope = Task[ActiveWayPoint].PGConeSlope;
            if (Type == CONE && ConeSlope > 0.0) {
                is_final_glide = true;
                is_conical_ess = true;
            }
        }
    }

    double av_thermal = -1;
    if (flightstats.ThermalAverage.y_ave > 0) {
        if (Calculated->Circling && (Calculated->AverageThermal > 0)) {
#if BUGSTOP
            LKASSERT((flightstats.ThermalAverage.sum_n + 1) != 0);
#endif
            if (flightstats.ThermalAverage.sum_n == -1) {
                flightstats.ThermalAverage.sum_n = -0.99;
            }
            av_thermal = (flightstats.ThermalAverage.y_ave
                    * flightstats.ThermalAverage.sum_n
                    + Calculated->AverageThermal) /
                    (flightstats.ThermalAverage.sum_n + 1);
        } else {
            av_thermal = flightstats.ThermalAverage.y_ave;
        }
    } else if (Calculated->Circling && (Calculated->AverageThermal > 0)) {
        // insufficient stats, so use this/last thermal's average
        av_thermal = Calculated->AverageThermal;
    }

    if (!ValidTaskPoint(ActiveWayPoint)) {
        if (av_thermal > 0) {
            mc_new = av_thermal;
        } else {
            mc_new = 0;
        }
    } else if (((AutoMcMode == amcFinalGlide) || (AutoMcMode == amcFinalAndClimb)) && is_final_glide) {

        if (Calculated->TaskAltitudeDifference0 > 0) {

            // only change if above final glide with zero Mc
            // otherwise when we are well below, it will wind Mc back to
            // zero

#if BUGSTOP
            LKASSERT((Calculated->WaypointDistance + 1) != 0);
#endif
            if (Calculated->WaypointDistance < 0) Calculated->WaypointDistance = 0; // temporary but ok
            double slope =
                    (Calculated->NavAltitude + Calculated->EnergyHeight
                    - FAIFinishHeight(Basic, Calculated, ActiveWayPoint)) /
                    (Calculated->WaypointDistance + 1);

            double mc_pirker = PirkerAnalysis(Basic, Calculated,
                    Calculated->WaypointBearing,
                    slope);
            mc_pirker = max(0.0, mc_pirker);
            if (first_mc) {
                // don't allow Mc to wind down to zero when first achieving
                // final glide; but do allow it to wind down after that
                if (mc_pirker >= mc_new) {
                    mc_new = mc_pirker;
                    first_mc = false;
                } else if (AutoMcMode == amcFinalAndClimb) {
                    // revert to averager based auto Mc
                    if (av_thermal > 0) {
                        mc_new = av_thermal;
                    }
                }
            } else {
                mc_new = mc_pirker;
            }

            if (is_conical_ess) {
                const double VOpt = GlidePolar::FindSpeedForSlope(ConeSlope);
                const double eqMC = GlidePolar::EquMC(VOpt);
                if(mc_new > eqMC) {
                    mc_new = eqMC;
                }
            }

        } else { // below final glide at zero Mc, never achieved final glide
            if (first_mc && (AutoMcMode == amcFinalAndClimb)) {
                // revert to averager based auto Mc
                if (av_thermal > 0) {
                    mc_new = av_thermal;
                }
            }
        }
    } else if ((AutoMcMode == amcAverageClimb) || ((AutoMcMode == amcFinalAndClimb)&& !is_final_glide)) {
        if (av_thermal > 0) {
            mc_new = av_thermal;
        }
    }

    CheckSetMACCREADY(LowPassFilter(MACCREADY, mc_new, 0.6));

    UnlockTaskData();
    //  UnlockFlightData();

}
예제 #4
0
//
// THIS FUNCTION IS THREAD SAFE, but not using optimized clipping
//
void MapWindow::DrawTaskPicto(HDC hdc,int TaskIdx, RECT rc, double fScaleFact)
{
int center_x = (rc.right-rc.left)/2;
int center_y = (rc.bottom-rc.top)/2;
int SecType = SectorType;
int width = center_x-2;
HPEN oldpen = 0;
HBRUSH oldbrush = 0;
if(AATEnabled)
  oldbrush = (HBRUSH) SelectObject(hdc, LKBrush_LightGrey);
else
  oldbrush = (HBRUSH) SelectObject(hdc, GetStockObject(HOLLOW_BRUSH));

oldpen = (HPEN) SelectObject(hdc, hpStartFinishThick);
int finish=0;

while( ValidTaskPoint(finish))
 finish++;
finish--;

if(center_y < width)
  width = center_y-2;

POINT startfinishline[2] = {{0,-width/ScreenScale},
                            {0,width/ScreenScale}};

POINT track[3] = {{0,-width/5/ScreenScale},
                  {width/2/ScreenScale,0},
                  {0,width/5/ScreenScale}};
if(TaskIdx == finish)
{
  track[0].x = -width/2/ScreenScale; track[0].y= -width/5/ScreenScale;
  track[1].x = 0 ; track[1].y= 0;
  track[2].x = -width/2/ScreenScale ; track[2].y= width/5/ScreenScale;
}

LockTaskData(); // protect from external task changes
double StartRadial = Task[TaskIdx].AATStartRadial;
double FinishRadial = Task[TaskIdx].AATFinishRadial;

if(TaskIdx==0)
{
  FinishRadial = Task[TaskIdx].AATStartRadial;
  StartRadial = Task[TaskIdx].AATFinishRadial;
}

double LineBrg;
double SecRadius;
GetTaskSectorParameter( TaskIdx, &SecType,&SecRadius);

    switch (SecType)
    {
        case CIRCLE:
            CircleNoCliping(hdc,
             center_x,
             center_y,
             width-2, rc, true);
            break;
        case SECTOR:
            Segment(hdc,
             center_x,
             center_y, width, rc,
             StartRadial,
             FinishRadial);
            break;
        case DAe:
            if (!AATEnabled) { // this Type exist only if not AAT task
                // JMW added german rules
                CircleNoCliping(hdc,
                 center_x,
                 center_y,
                 width/8, rc, true);

                Segment(hdc,
                 center_x,
                 center_y, width, rc,
                 StartRadial,
                 FinishRadial);
            }
            break;
       default:
       case LINE:
            if (TaskIdx == 0) {
                LineBrg = Task[TaskIdx].OutBound-90;
            } else if (TaskIdx == finish) {
                LineBrg = Task[TaskIdx].InBound-90;
            } else {
                LineBrg = Task[TaskIdx].Bisector;
            }
            threadsafePolygonRotateShift(startfinishline, 2, center_x, center_y, LineBrg);
            Polygon(hdc, startfinishline, 2);
            if ((TaskIdx == 0) || (TaskIdx == finish)) {
                threadsafePolygonRotateShift(track, 3, center_x, center_y, LineBrg);
                Polygon(hdc, track, 3);
            }
       break;
        case CONE:
            if (DoOptimizeRoute()) {

                int radius = width-2;
                CircleNoCliping(hdc, center_x, center_y, radius, rc, true);
                HPEN prevPen = (HPEN)::SelectObject(hdc, hpTerrainLine);
                for( int i = 1; i < 4 && radius > (width/5); ++i) {
                    CircleNoCliping(hdc, center_x, center_y, radius -= width/5, rc, true);
                }
                ::SelectObject(hdc, prevPen);
            }
            break;
    }
UnlockTaskData();

SelectObject(hdc, oldpen);
SelectObject(hdc, oldbrush);
}
예제 #5
0
void MapWindow::DrawTask(HDC hdc, RECT rc, const POINT &Orig_Aircraft) {
    int i;
    double tmp;

    COLORREF whitecolor = RGB_WHITE;
    COLORREF origcolor = SetTextColor(hDCTemp, whitecolor);
    HPEN oldpen = 0;
    HBRUSH oldbrush = 0;

    static short size_tasklines=0;

    if (DoInit[MDI_DRAWTASK]) {
switch (ScreenSize) {
case ss480x272:
case ss272x480:
case ss320x240:
case ss240x320:
size_tasklines=NIBLSCALE(4);
break;
default:
size_tasklines=NIBLSCALE(3);
break;
}
DoInit[MDI_DRAWTASK]=false;
    }

    if (!WayPointList) return;

    oldpen = (HPEN) SelectObject(hdc, hpStartFinishThick);
    oldbrush = (HBRUSH) SelectObject(hdc, GetStockObject(HOLLOW_BRUSH));

    LockTaskData(); // protect from external task changes

    for (i = 1; ValidTaskPoint(i); i++) {
        if (!ValidTaskPoint(i + 1)) { // final waypoint
            if (ActiveWayPoint > 1 || !ValidTaskPoint(2)) {
                // only draw finish line when past the first
                // waypoint. FIXED 110307: or if task is with only 2 tps
                DrawStartEndSector(hdc, rc, Task[i].Start, Task[i].End, Task[i].Index, FinishLine, FinishRadius);
            }
        } else { // normal sector
            if (AATEnabled != TRUE) {
                //_DrawLine(hdc, PS_DASH, NIBLSCALE(3), WayPointList[Task[i].Index].Screen, Task[i].Start, RGB_PETROL, rc);
                //_DrawLine(hdc, PS_DASH, NIBLSCALE(3), WayPointList[Task[i].Index].Screen, Task[i].End, RGB_PETROL, rc);
         // DrawDashLine(hdc, size_tasklines, WayPointList[Task[i].Index].Screen, Task[i].Start, RGB_PETROL, rc);
         // DrawDashLine(hdc, size_tasklines, WayPointList[Task[i].Index].Screen, Task[i].End, RGB_PETROL, rc);
            }

            int Type = 0;
            double Radius = 0.;
            GetTaskSectorParameter(i, &Type, &Radius);
            switch (Type) {
                case CIRCLE:
                    tmp = Radius * zoom.ResScaleOverDistanceModify();
                    Circle(hdc,
                            WayPointList[Task[i].Index].Screen.x,
                            WayPointList[Task[i].Index].Screen.y,
                            (int) tmp, rc, false, false);
                    break;
                case SECTOR:
                    tmp = Radius * zoom.ResScaleOverDistanceModify();
                    Segment(hdc,
                            WayPointList[Task[i].Index].Screen.x,
                            WayPointList[Task[i].Index].Screen.y, (int) tmp, rc,
                            Task[i].AATStartRadial - DisplayAngle,
                            Task[i].AATFinishRadial - DisplayAngle);
                    break;
                case DAe:
                    if (!AATEnabled) { // this Type exist only if not AAT task
                        // JMW added german rules
                        tmp = 500 * zoom.ResScaleOverDistanceModify();
                        Circle(hdc,
                                WayPointList[Task[i].Index].Screen.x,
                                WayPointList[Task[i].Index].Screen.y,
                                (int) tmp, rc, false, false);

                        tmp = 10e3 * zoom.ResScaleOverDistanceModify();

                        Segment(hdc,
                                WayPointList[Task[i].Index].Screen.x,
                                WayPointList[Task[i].Index].Screen.y, (int) tmp, rc,
                                Task[i].AATStartRadial - DisplayAngle,
                                Task[i].AATFinishRadial - DisplayAngle);
                    }
                    break;
                case LINE:
                    if (!AATEnabled) { // this Type exist only if not AAT task
                    	if(ISGAAIRCRAFT) {
                    		POINT start,end;
                    		double rotation=AngleLimit360(Task[i].Bisector-DisplayAngle);
                    		int length=14*ScreenScale; //Make intermediate WP lines always of the same size independent by zoom level
                    		start.x=WayPointList[Task[i].Index].Screen.x+(long)(length*fastsine(rotation));
                    		start.y=WayPointList[Task[i].Index].Screen.y-(long)(length*fastcosine(rotation));
                    		rotation=Reciprocal(rotation);
                    		end.x=WayPointList[Task[i].Index].Screen.x+(long)(length*fastsine(rotation));
                    		end.y=WayPointList[Task[i].Index].Screen.y-(long)(length*fastcosine(rotation));
                    		_DrawLine(hdc, PS_SOLID, NIBLSCALE(3), start, end, taskcolor, rc);
                    	} else _DrawLine(hdc, PS_SOLID, NIBLSCALE(3), Task[i].Start, Task[i].End, taskcolor, rc);
                    }
                    break;
                case CONE:
                    tmp = Radius * zoom.ResScaleOverDistanceModify();
                    int center_x = WayPointList[Task[i].Index].Screen.x;
                    int center_y = WayPointList[Task[i].Index].Screen.y;
                    Circle(hdc, center_x, center_y, (int) tmp, rc, false, false);
                    HPEN prevPen = (HPEN)::SelectObject(hdc, hpTerrainLine);
                    for( int j = 1; j < 5 && tmp > 0; ++j) {
                        Circle(hdc, center_x, center_y, tmp -= NIBLSCALE(5), rc, true, true);
                    }
                    ::SelectObject(hdc, prevPen);
                    break;
            }

            if (AATEnabled && !DoOptimizeRoute()) {
                // ELSE HERE IS *** AAT ***
                // JMW added iso lines
                if ((i == ActiveWayPoint) || (mode.Is(Mode::MODE_TARGET_PAN) && (i == TargetPanIndex))) {
                    // JMW 20080616 flash arc line if very close to target
                    static bool flip = false;

                    if (DerivedDrawInfo.WaypointDistance < AATCloseDistance()*2.0) {
                        flip = !flip;
                    } else {
                        flip = true;
                    }
                    if (flip) {
                        for (int j = 0; j < MAXISOLINES - 1; j++) {
                            if (TaskStats[i].IsoLine_valid[j]
                                    && TaskStats[i].IsoLine_valid[j + 1]) {
                                _DrawLine(hdc, PS_SOLID, NIBLSCALE(2),
                                        TaskStats[i].IsoLine_Screen[j],
                                        TaskStats[i].IsoLine_Screen[j + 1],
                                        RGB(0, 0, 255), rc);
                            }
                        }
                    }
                }
            }
        }
    }

    if ((ActiveWayPoint < 2) && ValidTaskPoint(0) && ValidTaskPoint(1)) {
        DrawStartEndSector(hdc, rc, Task[0].Start, Task[0].End, Task[0].Index, StartLine, StartRadius);
        if (EnableMultipleStartPoints) {
            for (i = 0; i < MAXSTARTPOINTS; i++) {
                if (StartPoints[i].Active && ValidWayPoint(StartPoints[i].Index)) {
                    DrawStartEndSector(hdc, rc, StartPoints[i].Start, StartPoints[i].End,
                            StartPoints[i].Index, StartLine, StartRadius);
                }
            }
        }
    }
    
    for (i = 0; ValidTaskPoint(i + 1); i++) {
        int imin = min(Task[i].Index, Task[i + 1].Index);
        int imax = max(Task[i].Index, Task[i + 1].Index);
        // JMW AAT!
        double bearing = Task[i].OutBound;
        POINT sct1, sct2;
        if (AATEnabled) {
            LatLon2Screen(Task[i].AATTargetLon,
                    Task[i].AATTargetLat,
                    sct1);
            LatLon2Screen(Task[i + 1].AATTargetLon,
                    Task[i + 1].AATTargetLat,
                    sct2);
            DistanceBearing(Task[i].AATTargetLat,
                    Task[i].AATTargetLon,
                    Task[i + 1].AATTargetLat,
                    Task[i + 1].AATTargetLon,
                    NULL, &bearing);

            // draw nominal track line
            DrawDashLine(hdc, NIBLSCALE(1), // 091217
                    WayPointList[imin].Screen,
                    WayPointList[imax].Screen,
                    taskcolor, rc);
        } else {
            sct1 = WayPointList[imin].Screen;
            sct2 = WayPointList[imax].Screen;
        }

        if ((i >= ActiveWayPoint && DoOptimizeRoute()) || !DoOptimizeRoute()) {
            POINT ClipPt1 = sct1, ClipPt2 = sct2;
            if(LKGeom::ClipLine((POINT) {rc.left, rc.top}, (POINT) {rc.right, rc.bottom}, ClipPt1, ClipPt2)) {
                DrawMulticolorDashLine(hdc, size_tasklines,
                        sct1,
                        sct2,
                        taskcolor, RGB_BLACK,rc);
                
                // draw small arrow along task direction
                POINT p_p;
                POINT Arrow[2] = {
                    {6, 6},
                    {-6, 6}
                };
                ScreenClosestPoint(sct1, sct2,
                        Orig_Aircraft, &p_p, NIBLSCALE(25));
                threadsafePolygonRotateShift(Arrow, 2, p_p.x, p_p.y, bearing - DisplayAngle);

                _DrawLine(hdc, PS_SOLID, size_tasklines-NIBLSCALE(1), Arrow[0], p_p, taskcolor, rc);
                _DrawLine(hdc, PS_SOLID, size_tasklines-NIBLSCALE(1), Arrow[1], p_p, taskcolor, rc);
            }
        }
    }
    
    // Draw DashLine From current position to Active TurnPoint center
    if(ValidTaskPoint(ActiveWayPoint)) {
        POINT ptStart;
        LatLon2Screen(DrawInfo.Longitude, DrawInfo.Latitude, ptStart);
        DrawDashLine(hdc, NIBLSCALE(1),
                    ptStart,
                    WayPointList[Task[ActiveWayPoint].Index].Screen,
                    taskcolor, rc);

    }

    {
        UnlockTaskData();
    }

    // restore original color
    SetTextColor(hDCTemp, origcolor);
    SelectObject(hdc, oldpen);
    SelectObject(hdc, oldbrush);
}
예제 #6
0
void MapWindow::DrawTaskAAT(LKSurface& Surface, const RECT& rc) {
    int i;
    double tmp1 = 0.0;

    if (WayPointList.empty()) return;
    if (!AATEnabled) return;

    LockTaskData(); // protect from external task changes
    /**********************************************/
    /* Check if not Validated Waypoint is visible */
    bool bDraw = false;
    int maxTp = 1;
    rectObj rcrect = (rectObj){(double) rc.left, (double) rc.top, (double) rc.right, (double) rc.bottom};
    RECT rcDraw = (RECT){rc.right, rc.bottom, rc.left, rc.top};

    for (maxTp = std::max(1, ActiveTaskPoint); ValidTaskPoint(maxTp + 1); ++maxTp) {
        if (ValidTaskPoint(maxTp)) {
            int Type = 0;
            double Radius = 0.;
            GetTaskSectorParameter(maxTp, &Type, &Radius);
            switch (Type) {
                case CONE:
                case CIRCLE:
                    tmp1 = Task[maxTp].AATCircleRadius * zoom.ResScaleOverDistanceModify();
                    break;
                case SECTOR:
                    tmp1 = Task[maxTp].AATSectorRadius * zoom.ResScaleOverDistanceModify();
                    break;
                default:
                    tmp1 = 0.0;
                    break;
            }
        }

        PixelScalar x = WayPointList[Task[maxTp].Index].Screen.x;
        PixelScalar y = WayPointList[Task[maxTp].Index].Screen.y;
        rectObj rect = (rectObj){x - tmp1, y - tmp1, x + tmp1, y + tmp1};

        if (msRectOverlap(&rect, &rcrect) == MS_TRUE) {
            rcDraw.top = std::min((PixelScalar)rect.miny, rcDraw.top);
            rcDraw.bottom = std::max((PixelScalar) rect.maxy, rcDraw.bottom);
            rcDraw.left = std::min((PixelScalar) rect.minx, rcDraw.left);
            rcDraw.right = std::max((PixelScalar) rect.maxx, rcDraw.right);
            bDraw = true;
        }
    }
    /**********************************************/

    if (bDraw) { // Draw Only if one is Visible
#ifdef USE_GDI
        rcDraw.top = std::max(rc.top, rcDraw.top);
        rcDraw.bottom = std::min(rc.bottom, rcDraw.bottom);
        rcDraw.left = std::max(rc.left, rcDraw.left);
        rcDraw.right = std::min(rc.right, rcDraw.right);


        LKColor whitecolor = RGB_WHITE;
        LKColor origcolor = TempSurface.SetTextColor(whitecolor);

        const auto oldpen = TempSurface.SelectObject(LK_WHITE_PEN);
        const auto oldbrush = TempSurface.SelectObject(LKBrush_White);
        if(LKSurface::AlphaBlendSupported()) {
            // copy original bitmap into temp (for saving fully transparent areas)
            TempSurface.Copy(rcDraw.left, rcDraw.top,
                    rcDraw.right - rcDraw.left, rcDraw.bottom - rcDraw.top, 
                    Surface, rcDraw.left, rcDraw.top);
        } else {
            TempSurface.Rectangle(rcDraw.left, rcDraw.top, rcDraw.right, rcDraw.bottom);
        }
        
        TempSurface.SelectObject(LK_NULL_PEN);
#ifdef HAVE_HATCHED_BRUSH          
        TempSurface.SelectObject(hAirspaceBrushes[iAirspaceBrush[AATASK]]);
#else
        TempSurface.SelectObject(LKBrush_Yellow);
#endif  
        // this color is used as the black bit
        TempSurface.SetTextColor(Colours[iAirspaceColour[AATASK]]);
        // this color is the transparent bit
        TempSurface.SetBkColor(whitecolor);
        
        LKSurface & AliasSurface = TempSurface;
#else
        LKSurface & AliasSurface = Surface;
        Surface.SelectObject(LKBrush(LKColor(255U,255U,0U).WithAlpha(AlphaLevel)));
#endif
        for (i = maxTp - 1; i > std::max(0, ActiveTaskPoint - 1); i--) {
        if (ValidTaskPoint(i)) {
            int Type = 0;
            double Radius = 0.;
            GetTaskSectorParameter(i, &Type, &Radius);

            switch (Type) {
                case CONE:
                case CIRCLE:
                    tmp1 = Radius * zoom.ResScaleOverDistanceModify();
                    AliasSurface.DrawCircle(
                            WayPointList[Task[i].Index].Screen.x,
                            WayPointList[Task[i].Index].Screen.y,
                            (int) tmp1, rc, true);
                    break;
                case SECTOR:
                    tmp1 = Radius * zoom.ResScaleOverDistanceModify();
                    AliasSurface.Segment(
                            WayPointList[Task[i].Index].Screen.x,
                            WayPointList[Task[i].Index].Screen.y, (int) tmp1, rc,
                            Task[i].AATStartRadial - DisplayAngle,
                            Task[i].AATFinishRadial - DisplayAngle);
                    break;
            }
        }
        }
#ifdef USE_GDI
        // restore original color
        TempSurface.SetTextColor(origcolor);
        TempSurface.SelectObject(oldpen);
        TempSurface.SelectObject(oldbrush);
        
        if(!Surface.AlphaBlend(rcDraw, TempSurface,rcDraw, AlphaLevel)) {
            // if AlphaBlend is not supported, use TransparentBld
            Surface.TransparentCopy(
                    rcDraw.left, rcDraw.top,
                    rcDraw.right - rcDraw.left, rcDraw.bottom - rcDraw.top,
                    TempSurface,
                    rcDraw.left, rcDraw.top);
        }
#endif
	}
    
    {
        UnlockTaskData();
    }
}
예제 #7
0
파일: DrawTask.cpp 프로젝트: rafagdn/LK8000
void MapWindow::DrawTaskPicto(HDC hdc,int TaskIdx, RECT rc, double fScaleFact)
{
#ifdef PICTORIALS
int center_x = (rc.right-rc.left)/2;
int center_y = (rc.bottom-rc.top)/2;
int SecType = SectorType;
int width = center_x-2;
HPEN oldpen = 0;
HBRUSH oldbrush = 0;
if(AATEnabled)
  oldbrush = (HBRUSH) SelectObject(hdc, LKBrush_LightGrey);
else
  oldbrush = (HBRUSH) SelectObject(hdc, GetStockObject(HOLLOW_BRUSH));

oldpen = (HPEN) SelectObject(hdc, hpStartFinishThick);
int finish=0;

while( ValidTaskPoint(finish))
 finish++;
finish--;

if(center_y < width)
  width = center_y-2;

fScaleFact /= (2500.0);

//width = (int)((double)width*(fScaleFact));


POINT startfinishline[2] = {{0,-width/2},
                            {0,+width/2}};

POINT track[3] = {{0,-width/10},
{width/4,0},
                  {0,width/10}};
if(TaskIdx == finish)
{
track[0].x = -width/4 ; track[0].y= -width/10;
track[1].x = 0 ; track[1].y= 0;
track[2].x = -width/4 ; track[2].y= width/10;
}

LockTaskData(); // protect from external task changes
double StartRadial = Task[TaskIdx].AATStartRadial;
double FinishRadial = Task[TaskIdx].AATFinishRadial;

if(TaskIdx==0)
{
  FinishRadial = Task[TaskIdx].AATStartRadial;
  StartRadial = Task[TaskIdx].AATFinishRadial;
}

double SecRadius;
GetTaskSectorParameter( TaskIdx, &SecType,&SecRadius);

    switch (SecType)
    {
        case CIRCLE:
            Circle(hdc,
             center_x,
             center_y,
             width-2, rc, true, true);
            break;
        case SECTOR:
            Segment(hdc,
             center_x,
             center_y, width, rc,
             StartRadial,
             FinishRadial);
            break;
        case DAe:
            if (!AATEnabled) { // this Type exist only if not AAT task
                // JMW added german rules
                Circle(hdc,
                 center_x,
                 center_y,
                 width/8, rc, false, true);

                Segment(hdc,
                 center_x,
                 center_y, width, rc,
                 StartRadial,
                 FinishRadial);
            }
            break;
       case LINE:
       default:
    PolygonRotateShift(startfinishline, 2, center_x, center_y, Task[TaskIdx].AATStartRadial);
    Polygon(hdc,startfinishline ,2 );
     if((TaskIdx == 0) || (TaskIdx == finish))
     {
     PolygonRotateShift(track, 3, center_x, center_y, Task[TaskIdx].AATStartRadial);
     Polygon(hdc,track ,3 );
     }
       break;
    }
UnlockTaskData();

SelectObject(hdc, oldpen);
SelectObject(hdc, oldbrush);
#endif
}
예제 #8
0
bool MapWindow::Event_NearestWaypointDetails(double lon, double lat) {

    double Dist;
    unsigned int i;
    const double range = zoom.RealScale()*500;  
    double dyn_range = std::max(5000.0, range*3.5);

    //StartupStore(_T("RANGE=%f\n"),dyn_range);
    LKSound(TEXT("LK_BELL.WAV"));

start_search:

#ifdef BUTTONS_MS
    LockFlightData();
    DistanceBearing(lat,lon, GPS_INFO.Latitude,GPS_INFO.Longitude, &Dist, NULL);
    UnlockFlightData();

    if(Dist < dyn_range) {
	#ifdef OWN_POS_MS
  	dlgAddMultiSelectListItem(NULL,0, IM_OWN_POS, Dist);
	#endif
	#ifdef ORACLE_MS
  	dlgAddMultiSelectListItem(NULL,0, IM_ORACLE, Dist);
	#endif
	#ifdef TEAM_CODE_MS
  	dlgAddMultiSelectListItem(NULL,0, IM_TEAM, Dist);
	#endif
    }
#endif	// BUTTONS_MS


    for(size_t i=NUMRESWP;i<WayPointList.size();++i) {    // Consider only valid markers
        if ((WayPointCalc[i].WpType==WPT_AIRPORT)|| (WayPointCalc[i].WpType==WPT_OUTLANDING)) {
            DistanceBearing(lat,lon, WayPointList[i].Latitude, WayPointList[i].Longitude, &Dist, NULL);
            if(Dist < dyn_range) {
    	        dlgAddMultiSelectListItem(NULL,i, IM_WAYPOINT, Dist);
            }
        }
    }

#ifdef FLARM_MS
    if((MapWindow::mode.Is(MapWindow::Mode::MODE_PAN) || MapWindow::mode.Is(MapWindow::Mode::MODE_TARGET_PAN))) {
        LastDoTraffic=0;
        DoTraffic(&DrawInfo,&DerivedDrawInfo);
        for (unsigned i=0; i<FLARM_MAX_TRAFFIC; ++i) {
	    if (LKTraffic[i].Status != LKT_EMPTY) {
                DistanceBearing(lat,lon, LKTraffic[i].Latitude, LKTraffic[i].Longitude, &Dist, NULL);
                if(Dist < range) {
    	            dlgAddMultiSelectListItem((long*)&LKTraffic[i],i, IM_FLARM, Dist);
                }
            }
        }
    }
#endif

    int  HorDist=0, Bearing=0, VertDist=0; 
    CAirspaceList reslist = CAirspaceManager::Instance().GetNearAirspacesAtPoint(lon, lat, (int)(dyn_range/2));

    for (CAirspaceList::const_iterator it = reslist.begin(); it != reslist.end(); ++it) {
        LKASSERT((*it));
        (*it)->CalculateDistance(&HorDist, &Bearing, &VertDist,lon, lat);
        dlgAddMultiSelectListItem((long*) (*it),0, IM_AIRSPACE, HorDist);
    }


    for(i=1;i<WayPointList.size();i++) {    // Consider only valid markers
        if ((WayPointCalc[i].WpType != WPT_AIRPORT)|| (WayPointCalc[i].WpType != WPT_OUTLANDING)) {
            DistanceBearing(lat,lon, WayPointList[i].Latitude, WayPointList[i].Longitude, &Dist, NULL);
            if(Dist < (dyn_range)) {
    	        dlgAddMultiSelectListItem(NULL,i, IM_WAYPOINT, Dist);
            }
        }
    }


    // TASK MULTISELECT
    int SecType= DAe;
    double SecRadius =0;
    double Bear=0;
    bool Angleinside = false;

    LockTaskData();
    for(i=0; ValidTaskPoint(i); i++) {
        LKASSERT(Task[i].Index <=(int)WayPointList.size());
        DistanceBearing(lat,lon,
            WayPointList[Task[i].Index].Latitude,
            WayPointList[Task[i].Index].Longitude, &Dist, &Bear);

        GetTaskSectorParameter(i, &SecType, &SecRadius);

        Angleinside = true;
        if( SecRadius < (dyn_range)) SecRadius =dyn_range;

        if((Dist < SecRadius) && Angleinside) {
  	    dlgAddMultiSelectListItem(NULL,i, IM_TASK_PT, Dist);
        }
    }
    UnlockTaskData();

    #if (WINDOWSPC>0)
    if (EnableSoundModes) Poco::Thread::sleep(1000); // let the sound be heard in sequence
    #endif
    if(dlgGetNoElements() ==0) { 
        if(dyn_range < 120000) {
            dyn_range *=2;
            goto start_search;
        } else {
            DoStatusMessage(gettext(TEXT("_@M2248_")));  // _@M2248_  "No Near Object found!"
        }
    } else {
        LKSound(TEXT("LK_GREEN.WAV"));
        dlgMultiSelectListShowModal();
        if(ValidTaskPoint(PanTaskEdit)) {
            MapWindow::Event_Pan(1);
        }
        return true;
    }

    return false;
}