Пример #1
0
static void
drawAxes(pixel **     const pixels,
         unsigned int const pixcols,
         unsigned int const pixrows,
         pixval       const maxval,
         bool         const upvp,
         unsigned int const xBias,
         unsigned int const yBias) {
/*----------------------------------------------------------------------------
   Draw the axes, with tick marks every .1 units and labels.
-----------------------------------------------------------------------------*/
    pixel axisColor;  /* Color of axes and labels */
    unsigned int i;

    PPM_ASSIGN(axisColor, maxval, maxval, maxval);

    drawYAxis(pixels, pixcols, pixrows, maxval, xBias, yBias, axisColor);
    drawXAxis(pixels, pixcols, pixrows, maxval, xBias, yBias, axisColor);

    for (i = 1; i <= 9; i += 1) {
        tickX(pixels, pixcols, pixrows, maxval, xBias, yBias, axisColor, i);

        tickY(pixels, pixcols, pixrows, maxval, xBias, yBias, axisColor, i);
    }

    labelAxes(pixels, pixcols, pixrows, maxval, xBias, yBias, axisColor,
              upvp);
}
Пример #2
0
QGraphicsPixmapItem* Diagram::draw(QString title){
    if(pixmap == 0)
        return 0;
    QPainter p(pixmap);
    p.setPen(QPen(Qt::white));
    p.setBrush(Qt::white);
    p.drawRect(pixmap->rect());

    calculateAxisSteps();

    drawCaption(p, title);
    drawXAxis(p);
    drawYAxis(p);
    drawValues(p);
    drawHorizontalLines(p);

    return new QGraphicsPixmapItem(*pixmap,0,scene);
}
Пример #3
0
void BifurcationPlot::drawPlot() {
    /**
    *   Main drawing function for the plot classes.
    *
    *   The bifurcation plot is stored in a wxBitmap object so that we don't
    *   have to recalculate and draw every point every time we refresh the
    *   screen.  Since all of the ChaosPlots are buffered, this means that
    *   the Bifurcation drawing functions actually go through two buffers.
    *   This is not the most efficient way to do this, but it does allow us
    *   to use the functionality of the ChaosPlot subclass.
    *
    *   Steps for drawing:
    *
    *   Calculate X & Y axis values and size.
    *
    *   Store our current size.
    *
    *   Calls startDraw() to initalize the drawing DC. (Updates size)
    *
    *   Compare old size with current size to determine if it needs to redraw everything.
    *
    *   If so, draw axis on BufferedDC and copy them over to the MemoryDC,
    *   then redraw all points.
    *
    *   If not, collect points for up to 2 MDAC values and only draw 
    *   the new points on the MemoryDC.
    *
    *   Draw the MDAC reference line on the graph.
    *
    *   Finally, copy the MemoryDC over to the BufferedDC and draw it to the DC.
    *
    */
    float x_min, x_max;
    float y_min, y_max;
    wxString xaxis_title;
    wxMemoryDC bifMemDC;
    
    // Get information for the X axis
    if(ChaosSettings::BifXAxis == ChaosSettings::MDAC_VALUES) {
        xaxis_title = wxString(wxT("Mdac values"));
    } else {
        xaxis_title = wxString(wxT("Resistance (Ohms)"));
    }

    // Get scaling/label information for the Y axis
    if(ChaosSettings::YAxisLabels == ChaosSettings::Y_AXIS_VGND) {
        graph_subtitle = wxString::Format(wxT("Peaks (V) vs. %s"), xaxis_title.c_str());
        y_min = smallest_y_value*3.3/1024;
        y_max = largest_y_value*3.3/1024;
        x_min = smallest_x_value*3.3/1024;
        x_max = largest_x_value*3.3/1024;
    } else if(ChaosSettings::YAxisLabels == ChaosSettings::Y_AXIS_VBIAS) {
        graph_subtitle = wxString::Format(wxT("Peaks (V) vs. %s"), xaxis_title.c_str());
        y_min = smallest_y_value*3.3/1024 - 1.2;
        y_max = largest_y_value*3.3/1024 - 1.2;
        x_min = smallest_x_value*3.3/1024 - 1.2;
        x_max = largest_x_value*3.3/1024 - 1.2;
    } else {
        graph_subtitle = wxString::Format(wxT("Peaks (ADC) vs. %s"), xaxis_title.c_str());
        y_min = smallest_y_value;
        y_max = largest_y_value;
        x_min = smallest_x_value;
        x_max = largest_x_value;
    }
    
    // Store old size information for future comparison
    int old_width = width;
    int old_height = height;
    
    // Update size and draw background & titles
    startDraw();
    
    // Check and see if the size of the graph has changed
    // If it has, we need to redraw our cached image
    if(old_width != width || old_height != height) {
        ChaosSettings::BifRedraw = true;
    }
    
    // Do we need to redraw everything that we have cached?
    if(ChaosSettings::BifRedraw == true) {
        // Draw the Y axis on the buffered DC
        drawYAxis(y_min, y_max, (y_max-y_min)/4.0);
        
        // Draw the X axis on the buffered DC
        if(ChaosSettings::BifXAxis == ChaosSettings::MDAC_VALUES) { 
            drawXAxis(float(largest_x_value),
                  float(smallest_x_value),
                  -1*((largest_x_value-smallest_x_value)/4));
        } else {
            float min = libchaos_mdacToResistance(largest_x_value);
            float max = libchaos_mdacToResistance(smallest_x_value);
            drawXAxis(min, max, ((max-min)/4));
        }
        
        // If we aren't connected, then we're done
        if(device_connected == false) {
            endDraw();
            return;
        }

        // if we already have a cached image, delete it
        if(bifBmp)
            delete bifBmp;
            
        // Create a bitmap to cache our bifurcation drawing to
        bifBmp = new wxBitmap(width, height);
        
        // Select the bitmap to a memory DC so we can draw on it and initialize it with a background
        bifMemDC.SelectObject(*bifBmp);
        bifMemDC.SetBrush(dc->GetBackground());
        bifMemDC.SetPen(*wxTRANSPARENT_PEN);
        bifMemDC.DrawRectangle(0,0,width,height);
        
        // Copy what we have on the buffer so far (title, axis, labels) to the cache
        bifMemDC.Blit(0, 0, width, height, buffer, 0, 0);
    } else {
        // No need to redraw everything, just select the cache so we can draw more onto it
        bifMemDC.SelectObject(*bifBmp);
    }

    //Use blue pen
    wxPen bluePen(*wxBLUE, 1); // blue pen of width 1
    wxBrush blueBrush(*wxBLUE_BRUSH);
    bifMemDC.SetPen(bluePen);
    bifMemDC.SetBrush(blueBrush);

    int* peaks;
    int new_points;
    int step = (int)(float(graph_width) / float(ChaosSettings::BifStepsPerWindow));
    
    if(step == 0) step = 1;
    
    // If we are paused, don't collect new data points
    if(paused || ChaosSettings::Paused) {
        new_points = 0;
    } else {
        new_points = 2;
        libchaos_disableFFT();
    }


    // Draw points, collecting new data if necessary.
    int miss_mdac = -1;
    for(int i = 1; i < graph_width; i+=step) {
        int mdac_value = xToMdac(i);
        
        /* Since the user can technically zoom into areas slightly beyond
        our mdac limits, we have to ensure we have a correct value. */
        if (mdac_value > 4095) {
            mdac_value = 4095;
        } else if (mdac_value < 0) {
            mdac_value = 0;
        }
        
        bool cacheHit = libchaos_peaksCacheHit(mdac_value);

        if(!cacheHit) new_points--;
        if((ChaosSettings::BifRedraw && cacheHit) || (!cacheHit && new_points > 0)) {

            peaks = libchaos_getPeaks(mdac_value);
            if(cacheHit == false) {
                miss_mdac = mdac_value;
            }
            
            bifMemDC.SetPen(bluePen);
            for(int j = 0; j < ChaosSettings::PeaksPerMdac; j++) {
                int y = valueToY(peaks[j]);
                if(y < graph_height + top_gutter_size && y > top_gutter_size) {
                    drawPoint(&bifMemDC, valueToX(mdac_value), y);
                }
            }
        }
        
    }
    
    if( new_points > 0 ) libchaos_enableFFT();
    
    if(miss_mdac != -1) {
        device_mdac_value = miss_mdac;
    }
    
    // We're finished redrawing everything, so don't do it again unless we need to
    if(ChaosSettings::BifRedraw == true) {
        ChaosSettings::BifRedraw = false;
    }

    // Copy our cache onto the buffered DC
    // (It is redundant to use a MemoryDC and a BufferedDC, it may be more efficient
    // to not use the BufferedDC for the bifurcation)
    buffer->Blit(0,0, width, height, &bifMemDC, 0, 0);
    
    // Draw the line for the MDAC
    drawMdacLine(buffer);
    
    // Flush the buffer and output to the screen.
    endDraw();

}
Пример #4
0
void XTPlot::drawPlot() {
    /**
    *   Main drawing function for the XTPlot class.
    *
    *   Calculates the units for the axis and then draws them
    *   Draws an XT graph using X, X', and X'' depending on which ones
    *   the user has selected.
    *
    */
    const int xt_points = 300;

    // max time on the graph in ms
    float max_time = xt_points*(1/72000.0)*1000;

    static int times_called = 0;

    int x1,x2,x1_old,x2_old, x3, x3_old;
    int start;

    startDraw();
    if(ChaosSettings::YAxisLabels == ChaosSettings::Y_AXIS_VGND) {
        graph_subtitle = wxT("X (V) vs. T(ms)");
        drawYAxis(0.0,3.3,1);
    } else if(ChaosSettings::YAxisLabels == ChaosSettings::Y_AXIS_VBIAS) {
        graph_subtitle = wxT("X (V) vs. T(ms)");
        drawYAxis(-1.2,2.1,.5);
    } else {
        graph_subtitle = wxT("X (ADC) vs. T(ms)");
        drawYAxis(0,1024,341);
    }
    drawXAxis(0,max_time,max_time/5.0);

    if(device_connected == false) {
        endDraw();
        return;
    }

    int plot_width = width-side_gutter_size-2;
    int plot_points;
    float x_scale;
    float y_scale = float(graph_height)/1024.0;

    plot_points = xt_points;
    x_scale = float(plot_width)/xt_points;

    start = libchaos_getTriggerIndex();

    // Get first plot point
    libchaos_getPlotPoint(&x1,&x2,&x3, start);
    x3 = graph_height + top_gutter_size - int(x3*y_scale);
    x2 = graph_height + top_gutter_size - int(x2*y_scale);
    x1 = graph_height + top_gutter_size - int(x1*y_scale);
    x1_old = x1;
    x2_old = x2;
    x3_old = x3;

    for(int i = 1; i < plot_points; i++) {
        libchaos_getPlotPoint(&x1,&x2,&x3, i+start);
        x3 = graph_height + top_gutter_size - int(x3*y_scale);
        x2 = graph_height + top_gutter_size - int(x2*y_scale);
        x1 = graph_height + top_gutter_size - int(x1*y_scale);

        if(x1Visible == true) {
            //Use red pen
            wxPen rPen(*wxRED, 2); // red pen of width 2
            buffer->SetPen(rPen);
            buffer->DrawLine((int)(x_scale*(i-1)+side_gutter_size+1), x1_old, (int)(x_scale*i+side_gutter_size+1), x1);
        }

        if(x2Visible == true) {
            //Use blue pen
            wxPen bPen(*wxBLUE, 2); // blue pen of width 2
            buffer->SetPen(bPen);
            buffer->DrawLine((int)(x_scale*(i-1)+side_gutter_size+1), x2_old, (int)(x_scale*i+side_gutter_size+1), x2);
        }

        if(x3Visible == true) {
            //Use green pen
            wxPen gPen(*wxGREEN, 2); // blue pen of width 2
            buffer->SetPen(gPen);
            buffer->DrawLine((int)(x_scale*(i-1)+side_gutter_size+1), x3_old, (int)(x_scale*i+side_gutter_size+1), x3);
        }

        x1_old = x1;
        x2_old = x2;
        x3_old = x3;
    }
    times_called = 0;

    // Display buffer
    endDraw();
}
Пример #5
0
void Rotating3dPlot::drawPlot() {
    /**
    *   Main drawing function for the ChaosPlot classes.
    *
    *   Draws a rotating 3d plot by graphing xdot vs the formula:
    *       x*cos(a*n) + x''*sin(a*n)
    *
    *   In order to get this to look like it is rotating around it's axis
    *   instead of around the outside of a merry-go-round, we must subtract
    *   the bias from our ADC values before we calculate the rotation.
    *   bias = 2V/5V*1024 = 409
    */
    const float a = 2*3.14159/25;
    const int bias = 409;
    int x1,x2,x1_old,x2_old,x3;
    
    startDraw();
    float y_min, y_max;
    if(ChaosSettings::YAxisLabels == ChaosSettings::Y_AXIS_VGND) {
        graph_subtitle = wxT("-X' (V) vs. X (V)");
        y_min = smallest_y_value*3.3/1024;
        y_max = largest_y_value*3.3/1024;
    } else if(ChaosSettings::YAxisLabels == ChaosSettings::Y_AXIS_VBIAS) {
        graph_subtitle = wxT("-X' (V) vs. X (V)");
        y_min = smallest_y_value*3.3/1024 - 1.2;
        y_max = largest_y_value*3.3/1024 - 1.2;
    } else {
        graph_subtitle = wxT("-X' (ADC) vs. X (ADC)");
        y_min = smallest_y_value;
        y_max = largest_y_value;
    }

    drawYAxis(y_min, y_max, (y_max-y_min)/4.0);

    if(device_connected == false) {
        endDraw();
        return;
    }
    
    //Use red pen
    wxPen pen(*wxRED, 1); // red pen of width 1
    buffer->SetPen(pen);
    
    // Get first plot point
    libchaos_getPlotPoint(&x1,&x2,&x3, 0);
    
    // x1 = x*cos(a*n)+x3*sin(a*n), but we have to subtract the bias from it
    // so that it rotates around the origin, we then add bias so it is visible
    x1 = valueToX(int((x1 - bias)*cos(a*timer_ticks) + (x3-bias)*sin(a*timer_ticks))+bias);
    x2 = valueToY(x2);
    x1_old = x1;
    x2_old = x2;
    
    // Repeat the above math for all the other points and graph them.
    for(int i = 1; i < libchaos_getNumPlotPoints(); i++) {
        libchaos_getPlotPoint(&x1,&x2,&x3, i);
        x1 = valueToX(int((x1 - bias)*cos(a*timer_ticks) + (x3-bias)*sin(a*timer_ticks))+bias);
        x2 = valueToY(x2);
        if(x1 > side_gutter_size && 
           x2 < (graph_height + top_gutter_size) && x2 > top_gutter_size && 
           x1_old > side_gutter_size && 
           x2_old < (graph_height + top_gutter_size) && x2_old > top_gutter_size) {
            buffer->DrawLine(x1_old,x2_old,x1,x2);
        }
        x1_old = x1;
        x2_old = x2;
    }
    
    // Display buffer
    endDraw();
}
Пример #6
0
void XYPlot::drawPlot() {
    /**
    *   Main drawing function for the XYPlot class.
    *
    *   Calculates the units for the axis and then draws them
    *   Draws an XY phase portrait by graphing -X' vs. X
    *
    *   All size & plotting related functions should be handled using
    *   the 'smallest/largest_x/y_value' variables. These variables control
    *   the zooming on the graph.
    */
    int x1,x2,x1_old,x2_old,x3;
    
    startDraw();
    float x_min, x_max;
    float y_min, y_max;
    if(ChaosSettings::YAxisLabels == ChaosSettings::Y_AXIS_VGND) {
        graph_subtitle = wxT("-X' (V) vs. X (V)");
        y_min = smallest_y_value*3.3/1024;
        y_max = largest_y_value*3.3/1024;
        x_min = smallest_x_value*3.3/1024;
        x_max = largest_x_value*3.3/1024;
    } else if(ChaosSettings::YAxisLabels == ChaosSettings::Y_AXIS_VBIAS) {
        graph_subtitle = wxT("-X' (V) vs. X (V)");
        y_min = smallest_y_value*3.3/1024 - 1.2;
        y_max = largest_y_value*3.3/1024 - 1.2;
        x_min = smallest_x_value*3.3/1024 - 1.2;
        x_max = largest_x_value*3.3/1024 - 1.2;
    } else {
        graph_subtitle = wxT("-X' (ADC) vs. X (ADC)");
        y_min = smallest_y_value;
        y_max = largest_y_value;
        x_min = smallest_x_value;
        x_max = largest_x_value;
    }
    
    drawYAxis(y_min, y_max, (y_max-y_min)/6.0);
              
    drawXAxis(x_min, x_max, (x_max-x_min)/6.0);

    if(device_connected == false) {
        endDraw();
        return;
    }
    
    //Use red pen
    wxPen pen(*wxRED, 1); // red pen of width 1
    buffer->SetPen(pen);
    
    // Get first plot point
    libchaos_getPlotPoint(&x1,&x2,&x3, 0);
    x1 = valueToX(x1);
    x2 = valueToY(x2);
    x1_old = x1;
    x2_old = x2;
    
    for(int i = 1; i < libchaos_getNumPlotPoints(); i++) {
        libchaos_getPlotPoint(&x1,&x2,&x3, i);
        x1 = valueToX(x1);
        x2 = valueToY(x2);
        if(x1 > side_gutter_size && 
           x2 < (graph_height+top_gutter_size) && x2 > top_gutter_size &&
           x1_old > side_gutter_size && 
           x2_old < (graph_height+top_gutter_size) && x2_old > top_gutter_size) {
            buffer->DrawLine(x1_old,x2_old,x1,x2);
        }
        x1_old = x1;
        x2_old = x2;
    }
    
    // Display buffer
    endDraw();
}