Optimaze with new mbed os for study

Dependencies:   TS_DISCO_F746NG BSP_DISCO_F746NG Graphics

RadarDemo/Radar.cpp

Committer:
ngtkien
Date:
2019-08-23
Revision:
5:64cafb3c6e7b
Parent:
2:8db224cc1fcb

File content as of revision 5:64cafb3c6e7b:

//
// Radar.h - example of graphic commands usage to create 2D graphics.
//

#include "Radar.h"
#include "math.h"
#include <cstdlib>

Radar::Radar(Display* display)
{
    _display = display;

    Initialize();
}

Radar::~Radar()
{
    for (std::list<Target>::iterator it = targetsList.begin(); it != targetsList.end(); ++it) {
        Target& target = *it;
        it = targetsList.erase(it);
    }
    targetsList.clear();
}


void Radar::Initialize()
{
    int margin = 4;

    // Set the size of display window
    window.y1 = margin;
    window.x1 = margin;

    window.y2 = _display->DisplayHeight() - 1 - margin;
    window.x2 = _display->DisplayWidth() - 1 - margin;

    // Set default center position
    SetCenter((window.x2 - window.x1) / 2 + window.x1, (window.y2 - window.y1) / 2 + window.y1);

    // Set default range
    SetRange(MAX_RANGE_INDEX);
}


void Radar::DrawTracks()
{
    // Draw every track on the list if in range
    for (std::list<Target>::iterator it = targetsList.begin(); it != targetsList.end(); ++it) {
        Target& target = *it;

        if (target.GetDistance() <= GetMaxRange()) {
            DrawTarget(&target);
        }
    }
}


void Radar::DrawMarkers()
{
    // Range markers
    //
    int localRange = (window.y2 - window.y1) / 2;
    float scale = localRange / GetRange();

    // First distance marker in local coordinates.
    int maxRadius = floor( 0.5f + GetMaxRange() * scale);
    int minRadius = floor( 0.5f + _rangeMarkersDelta[_rangeNumber] * scale);
    float radius = minRadius;
    while (radius <= maxRadius + 1) {
        _display->DrawCircle(_centerX, _centerY, floor( 0.5f + radius));
        radius += _rangeMarkersDelta[_rangeNumber] * scale;
    }
    _display->DrawCircle(_centerX, _centerY, maxRadius + 4);

    // DrawPoint in the center
    _display->DrawPoint(_centerX, _centerY, _display->GetDrawColor());

    // Azimuth markers, use the first and last marker radius calculated above.
    //
    double angle = 0;
    double angleDelta = M_PI / (double)azimuthMarkersCount;
    for (int i = 0; i<azimuthMarkersCount; i++) {
        float x = sin(angle);
        float y = cos(angle);
        _display->DrawLine(_centerX - x * minRadius, _centerY - y * minRadius, _centerX - x * maxRadius, _centerY - y * maxRadius);
        _display->DrawLine(_centerX + x * minRadius, _centerY + y * minRadius, _centerX + x * maxRadius, _centerY + y * maxRadius);
        angle += angleDelta;
    }
}


void Radar::DrawTarget(Target * target)
{
    const int radius = 6;
    uint32_t colorMask = 0xFF00FF00;
    _display->SetDrawColor((colorMask & 0x00FF0000) >> 16, (colorMask & 0x0000FF00) >> 8, (colorMask & 0x000000FF), (colorMask & 0xFF000000) >> 24);

    // Convert world location to local coordinates
    int x = _centerX + target->GetX() * _scaleRatio;
    int y = _centerY - target->GetY() * _scaleRatio;

    // Draw track
    //_display->DrawLine(x-radius, y, x+radius, y);
    _display->DrawPoint(x - radius, y, colorMask);
    _display->DrawPoint(x + radius, y, colorMask);
    for (int i = 1; i < radius; i++) {
        //_display->DrawLine(x - radius + i, y-i, x + radius - i, y-i);
        _display->DrawPoint(x - radius + i, y - i, colorMask);
        _display->DrawPoint(x + radius - i, y - i, colorMask);
        //_display->DrawLine(x - radius + i, y+i, x + radius - i, y+i);
        _display->DrawPoint(x - radius + i, y + i, colorMask);
        _display->DrawPoint(x + radius - i, y + i, colorMask);
    }
    _display->DrawPoint(x, y + radius, colorMask);
    _display->DrawPoint(x, y - radius, colorMask);

    // Draw vector
    const float maxSpeed = 800; // [km/h]
    float maxVectorLen = 20;
    float vectorLen = target->GetSpeed() * maxVectorLen / maxSpeed;

    // Convert world location to local coordinates
    int x1 = x + sin(target->GetDirection()) * vectorLen;
    int y1 = y - cos(target->GetDirection()) * vectorLen;
    _display->DrawLine(x, y, x1, y1);
}


void Radar::DrawPlot(Location* plot)
{
    const int size = 5;

    // Convert world location to local coordinates
    int x = _centerX + plot->GetX() * _scaleRatio;
    int y = _centerY - plot->GetY() * _scaleRatio;

    // Draw plot
    _display->DrawLine(x - size / 2, y, x + size / 2, y);
    _display->DrawLine(x, y - size / 2, x, y + size / 2);
}


bool Radar::UpdateTargetsLocation(float startAngle, float endAngle, uint32_t currentTime)
{
    int count = 0;
    for (std::list<Target>::iterator it = targetsList.begin(); it != targetsList.end(); ++it) {
        Target& target = *it;

        if( startAngle < endAngle ) {
            if (target.GetAzimuth() > startAngle && target.GetAzimuth() <= endAngle) {
                count++;
                target.UpdateLocationForTime(currentTime);
            }
        } else {
            if (target.GetAzimuth() > startAngle || target.GetAzimuth() <= endAngle) {
                count++;
                target.UpdateLocationForTime(currentTime);
            }
        }
    }

    return count > 0;
}


void Radar::DrawBorder()
{
    // Set display window coordinates
    int x1 = 0;
    int y1 = 0;
    int x2 = _display->DisplayWidth() - 1;
    int y2 = _display->DisplayHeight() - 1;

    _display->DrawRectangle(x1, y1, x2, y2);
    _display->DrawRectangle(window.x1, window.y1, window.x2, window.y2);

    float maxLen = 3;
    float delta = M_PI / (8 * 5);

    // top scale, y = 0;
    float angle = -M_PI / 2;
    while ((angle += delta) < M_PI / 2) {
        int yStart = y1;
        int xStart = _centerX + (yStart - _centerY) * tan(angle);

        if (xStart >= window.x1 && xStart <= window.x2) {
            int yEnd = yStart + maxLen;
            int xEnd = _centerX + (yEnd - _centerY) * tan(angle);

            _display->DrawLine(xStart, yStart, xEnd, yEnd);
        }
    }

    // bottom scale, y = y2;
    angle = M_PI / 2;
    while ((angle += delta) < 3 * M_PI / 2) {
        int yStart = y2;
        int xStart = _centerX + (yStart - _centerY) * tan(angle);

        if (xStart >= window.x1 && xStart <= window.x2) {
            int yEnd = yStart - maxLen;
            int xEnd = _centerX + (yEnd - _centerY) * tan(angle);

            _display->DrawLine(xStart, yStart, xEnd, yEnd);
        }
    }

    // left scale, x = 0;
    angle = -M_PI / 2;
    while ((angle += delta) < M_PI / 2) {
        int xStart = x1;
        int yStart = _centerY + (xStart - _centerX) * tan(angle);

        if (yStart >= window.y1 && yStart <= window.y2) {
            int xEnd = xStart + maxLen;
            int yEnd = _centerY + (xEnd - _centerX) * tan(angle);

            _display->DrawLine(xStart, yStart, xEnd, yEnd);
        }
    }

    // right scale, x = x2;
    angle = M_PI / 2;
    while ((angle += delta) < 3 * M_PI / 2) {
        int xStart = x2;
        int yStart = _centerY + (xStart - _centerX) * tan(angle);

        if (yStart >= window.y1 && yStart <= window.y2) {
            int xEnd = xStart - maxLen;
            int yEnd = _centerY + (xEnd - _centerX) * tan(angle);

            _display->DrawLine(xStart, yStart, xEnd, yEnd);
        }
    }
}


void Radar::DrawRadarBeam(float azimuth)
{
    // Maximum radius length i local coordinates
    int maxRadius = floor( 0.5f + GetMaxRange() * _scaleRatio);

    int endX = GetCenterX() + maxRadius * sin(azimuth);
    int endY = GetCenterY() - maxRadius * cos(azimuth);

    _display->SetDrawColor(0xFF, 0xFF, 0xFF, 0xFF);
    _display->DrawLine(_centerX, _centerY, endX, endY);
}

Display* Radar::GetDisplay()
{
    return _display;
}

void Radar::DrawRangeButtons(uint16_t raSize)
{
    const uint16_t signSize = 5;
    uint16_t centerX;
    uint16_t centerY;

    // Increase buton on right top
    if(_rangeNumber < MAX_RANGE_INDEX) {
        centerX = window.x2-raSize/2;
        centerY = raSize/2;
        
        _display->DrawRectangle(window.x2-raSize, window.y1, window.x2, raSize);
        _display->DrawLine(centerX-signSize, centerY, centerX+signSize, centerY);
    }

    // Decrease button on right bottom
    if(_rangeNumber > 0) {
        centerX = window.x2-raSize/2;
        centerY = window.y2-raSize/2;
        
        _display->DrawRectangle(window.x2-raSize, window.y2-raSize, window.x2, window.y2);
        _display->DrawLine(centerX-signSize, centerY, centerX+signSize, centerY);
        _display->DrawLine(centerX, centerY-signSize, centerX, centerY+signSize);
    }
}


void Radar::SetRange(uint8_t rangeNumber)
{
    if (rangeNumber <= MAX_RANGE_INDEX) {
        _rangeNumber = rangeNumber;

        int localRange = (window.y2 - window.y1) / 2;
        _scaleRatio = localRange / GetRange();
    }
}


bool Radar::ChangeRange(int change)
{
    if (change > 0 && _rangeNumber < MAX_RANGE_INDEX) {
        SetRange( _rangeNumber + 1);
        return true;
    }
    if (change < 0 && _rangeNumber > 0) {
        SetRange( _rangeNumber - 1);
        return true;
    }
    return false;
}


int Radar::_centerX;
int Radar::_centerY;
uint8_t Radar::_rangeNumber;
float Radar::_scaleRatio;