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); }
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); }
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(); }
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(); }
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(); }