void DesignerWindow::HighlightSelection( wxDC& dc ) { // do not highlight if AUI is used in floating mode VisualEditor *editor = wxDynamicCast( GetParent(), VisualEditor ); if( editor && editor->m_auimgr ) { wxWindow *windowItem = wxDynamicCast( m_selItem, wxWindow ); while( windowItem ) { wxAuiPaneInfo info = editor->m_auimgr->GetPane( windowItem ); if( info.IsOk() ) { if( info.IsFloating() ) return; else break; } windowItem = windowItem->GetParent(); } } wxSize size; PObjectBase object = m_selObj.lock(); if ( m_selSizer ) { wxPoint point = m_selSizer->GetPosition(); size = m_selSizer->GetSize(); wxPen bluePen( *wxBLUE, 1, wxSOLID ); dc.SetPen( bluePen ); dc.SetBrush( *wxTRANSPARENT_BRUSH ); PObjectBase sizerParent = object->FindNearAncestorByBaseClass( wxT("sizer") ); if( !sizerParent ) sizerParent = object->FindNearAncestorByBaseClass( wxT("gbsizer") ); if ( sizerParent && sizerParent->GetParent() ) { DrawRectangle( dc, point, size, sizerParent ); } } if ( m_selItem ) { wxPoint point; bool shown; wxWindow* windowItem = wxDynamicCast( m_selItem, wxWindow ); wxSizer* sizerItem = wxDynamicCast( m_selItem, wxSizer ); if ( NULL != windowItem ) { point = windowItem->GetPosition(); size = windowItem->GetSize(); shown = windowItem->IsShown(); } else if ( NULL != sizerItem ) { point = sizerItem->GetPosition(); size = sizerItem->GetSize(); shown = true; } else { return; } if ( shown ) { wxPen redPen( *wxRED, 1, wxSOLID ); dc.SetPen( redPen ); dc.SetBrush( *wxTRANSPARENT_BRUSH ); DrawRectangle( dc, point, size, object ); } } }
wxBitmap BacklashGraph::CreateGraph(int bmpWidth, int bmpHeight) { wxMemoryDC dc; wxBitmap bmp(bmpWidth, bmpHeight, -1); wxPen axisPen("BLACK", 3, wxCROSS_HATCH); wxPen redPen("RED", 3, wxSOLID); wxPen bluePen("BLUE", 3, wxSOLID); wxBrush redBrush("RED", wxSOLID); wxBrush blueBrush("BLUE", wxSOLID); //double fakeNorthPoints[] = //{152.04, 164.77, 176.34, 188.5, 200.25, 212.36, 224.21, 236.89, 248.62, 260.25, 271.34, 283.54, 294.79, 307.56, 319.22, 330.87, 343.37, 355.75, 367.52, 379.7, 391.22, 403.89, 415.34, 427.09, 439.41, 450.36, 462.6}; //double fakeSouthPoints[] = //{474.84, 474.9, 464.01, 451.83, 438.08, 426, 414.68, 401.15, 390.39, 377.22, 366.17, 353.45, 340.75, 328.31, 316.93, 304.55, 292.42, 280.45, 269.03, 255.02, 243.76, 231.53, 219.43, 207.35, 195.22, 183.06, 169.47}; //std::vector <double> northSteps(fakeNorthPoints, fakeNorthPoints + 27); //std::vector <double> southSteps(fakeSouthPoints, fakeSouthPoints + 27); std::vector <double> northSteps = m_BLT->GetNorthSteps(); std::vector <double> southSteps = m_BLT->GetSouthSteps(); double xScaleFactor; double yScaleFactor; int xOrigin; int yOrigin; int ptRadius; int graphWindowWidth; int graphWindowHeight; int numNorth; double northInc; int numSouth; // Find the max excursion from the origin in order to scale the points to fit the bitmap double maxDec = -9999.0; double minDec = 9999.0; for (std::vector<double>::const_iterator it = northSteps.begin(); it != northSteps.end(); ++it) { maxDec = wxMax(maxDec, *it); minDec = wxMin(minDec, *it); } for (std::vector<double>::const_iterator it = southSteps.begin(); it != southSteps.end(); ++it) { maxDec = wxMax(maxDec, *it); minDec = wxMin(minDec, *it); } graphWindowWidth = bmpWidth; graphWindowHeight = 0.7 * bmpHeight; yScaleFactor = (graphWindowHeight) / (maxDec - minDec + 1); xScaleFactor = (graphWindowWidth) / (northSteps.size() + southSteps.size()); // Since we get mount coordinates, north steps will always be in ascending order numNorth = northSteps.size(); northInc = (northSteps.at(numNorth - 1) - northSteps.at(0)) / numNorth; numSouth = southSteps.size(); // Should be same as numNorth but be careful dc.SelectObject(bmp); dc.SetBackground(*wxLIGHT_GREY_BRUSH); dc.SetFont(wxFont(12, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL)); dc.Clear(); // Bottom and top labels dc.SetTextForeground("BLUE"); dc.DrawText(_("Ideal"), 0.7 * graphWindowWidth, bmpHeight - 25); dc.SetTextForeground("RED"); dc.DrawText(_("Measured"), 0.2 * graphWindowWidth, bmpHeight - 25); dc.DrawText(_("North"), 0.1 * graphWindowWidth, 10); dc.DrawText(_("South"), 0.8 * graphWindowWidth, 10); // Draw the axes dc.SetPen(axisPen); xOrigin = graphWindowWidth / 2; yOrigin = graphWindowHeight + 40; // Leave room at the top for labels and such dc.DrawLine(0, yOrigin, graphWindowWidth, yOrigin); // x dc.DrawLine(xOrigin, yOrigin, xOrigin, 0); // y // Draw the north steps dc.SetPen(redPen); dc.SetBrush(redBrush); ptRadius = 2; for (int i = 0; i < numNorth; i++) { wxPoint where = wxPoint(i * xScaleFactor, round(yOrigin - (northSteps.at(i) - minDec) * yScaleFactor)); dc.DrawCircle(wxPoint(i * xScaleFactor, round(yOrigin - (northSteps.at(i) - minDec) * yScaleFactor)), ptRadius); } // Draw the south steps for (int i = 0; i < numSouth; i++) { dc.DrawCircle(wxPoint((i + numNorth) * xScaleFactor, round(yOrigin - (southSteps.at(i) - minDec) * yScaleFactor)), ptRadius); } // Now show an ideal south recovery line dc.SetPen(bluePen); dc.SetBrush(blueBrush); double peakSouth = southSteps.at(0); for (int i = 1; i <= numNorth; i++) { wxPoint where = wxPoint((i + numNorth)* xScaleFactor, round(yOrigin - (peakSouth - i * northInc - minDec) * yScaleFactor)); dc.DrawCircle(where, ptRadius); } dc.SelectObject(wxNullBitmap); return bmp; }
void MFCClipItemView::Draw(Graphics &dc, CRect &clipBox) { // !!!??? need to clip properly for short instances with long names cerr << "clip item draw " << item->sym->name << endl; Pen blackPen(Color(250, 0, 0, 0), 1); Pen redPen(Color(250, 238, 100, 100), 1); Pen orangePen(Color(200, 250, 150, 10), 1); SolidBrush blueBrush(Color(100, 100, 100, 238)); SolidBrush blackBrush(Color(200, 0, 0, 0)); SolidBrush orangeBrush(Color(190, 250, 150, 10)); dc.DrawLine( &orangePen, bounds.left, 0, bounds.left, bounds.bottom); bool isMarker = false; if (item != NULL && item->duration.ticks <= 0) { isMarker = true; } if (!isMarker) { dc.DrawLine( &orangePen, bounds.right, 0, bounds.right, bounds.bottom); } PointF tri[3]; Font labelFont(L"Arial", 8.0, FontStyleRegular, UnitPoint, NULL); wstring nm; const char *cp = item->sym->uniqueName(); while (*cp) { nm.push_back(*cp++); } PointF p; UINT py = 0; do { if (!isMarker) { // a triangle bit tri[0].X = bounds.left; tri[0].Y = py; tri[1].X = bounds.left+6; tri[1].Y = py+3; tri[2].X = bounds.left; tri[2].Y = py+6; dc.FillPolygon(&orangeBrush, tri, 3); } p.X = bounds.left-1; p.Y = py+5; RectF box; StringFormat sff = StringFormatFlagsDirectionVertical; dc.MeasureString(nm.c_str(), -1, &labelFont, p, &sff, &box); dc.DrawString(nm.c_str(), -1, &labelFont, box, &sff, &blackBrush); if (!isMarker) { // a nother triangle bit tri[0].X = bounds.right; tri[1].X = bounds.right-6; tri[2].X = bounds.right; dc.FillPolygon(&orangeBrush, tri, 3); p.X = bounds.right-10; p.Y = py+5; dc.MeasureString(nm.c_str(), -1, &labelFont, p, &sff, &box); dc.DrawString(nm.c_str(), -1, &labelFont, box, &sff, &blackBrush); } py += editor->bounds.bottom; } while (py < bounds.bottom); }
void QCompass::paintEvent(QPaintEvent *) { QPainter painter(this); QBrush bgGround(QColor(48,172,220)); QPen whitePen(Qt::white); QPen blackPen(Qt::black); QPen redPen(Qt::red); QPen bluePen(Qt::blue); QPen greenPen(Qt::green); whitePen.setWidth(1); blackPen.setWidth(2); redPen.setWidth(2); bluePen.setWidth(2); greenPen.setWidth(2); painter.setRenderHint(QPainter::Antialiasing); painter.translate(width() / 2, height() / 2); // draw background { painter.setPen(blackPen); painter.setBrush(bgGround); painter.drawEllipse(-m_size/2, -m_size/2, m_size, m_size); } // draw yaw lines { int nyawLines = 36; float rotAng = 360.0 / nyawLines; int yawLineLeng = m_size/25; double fx1, fy1, fx2, fy2; int fontSize = 8; QString s; blackPen.setWidth(1); painter.setPen(blackPen); for(int i=0; i<nyawLines; i++) { if( i == 0 ) { s = "N"; painter.setPen(bluePen); painter.setFont(QFont("", fontSize*1.3)); } else if ( i == 9 ) { s = "W"; painter.setPen(blackPen); painter.setFont(QFont("", fontSize*1.3)); } else if ( i == 18 ) { s = "S"; painter.setPen(redPen); painter.setFont(QFont("", fontSize*1.3)); } else if ( i == 27 ) { s = "E"; painter.setPen(blackPen); painter.setFont(QFont("", fontSize*1.3)); } else { s = QString("%1").arg(i*rotAng); painter.setPen(blackPen); painter.setFont(QFont("", fontSize)); } fx1 = 0; fy1 = -m_size/2 + m_offset; fx2 = 0; if( i % 3 == 0 ) { fy2 = fy1 + yawLineLeng; painter.drawLine(QPointF(fx1, fy1), QPointF(fx2, fy2)); fy2 = fy1 + yawLineLeng+4; painter.drawText(QRectF(-50, fy2, 100, fontSize+2), Qt::AlignCenter, s); } else { fy2 = fy1 + yawLineLeng/2; painter.drawLine(QPointF(fx1, fy1), QPointF(fx2, fy2)); } painter.rotate(-rotAng); } } // draw S/N arrow { int arrowWidth = m_size/5; double fx1, fy1, fx2, fy2, fx3, fy3; fx1 = 0; fy1 = -m_size/2 + m_offset + m_size/25 + 15; fx2 = -arrowWidth/2; fy2 = 0; fx3 = arrowWidth/2; fy3 = 0; painter.setPen(Qt::NoPen); painter.setBrush(QBrush(Qt::blue)); QPointF pointsN[3] = { QPointF(fx1, fy1), QPointF(fx2, fy2), QPointF(fx3, fy3) }; painter.drawPolygon(pointsN, 3); fx1 = 0; fy1 = m_size/2 - m_offset - m_size/25 - 15; fx2 = -arrowWidth/2; fy2 = 0; fx3 = arrowWidth/2; fy3 = 0; painter.setBrush(QBrush(Qt::red)); QPointF pointsS[3] = { QPointF(fx1, fy1), QPointF(fx2, fy2), QPointF(fx3, fy3) }; painter.drawPolygon(pointsS, 3); } // draw yaw marker { int yawMarkerSize = m_size/12; double fx1, fy1, fx2, fy2, fx3, fy3; painter.rotate(-m_yaw); painter.setBrush(QBrush(QColor(0xFF, 0x00, 0x00, 0xE0))); fx1 = 0; fy1 = -m_size/2 + m_offset; fx2 = fx1 - yawMarkerSize/2; fy2 = fy1 + yawMarkerSize; fx3 = fx1 + yawMarkerSize/2; fy3 = fy1 + yawMarkerSize; QPointF points[3] = { QPointF(fx1, fy1), QPointF(fx2, fy2), QPointF(fx3, fy3) }; painter.drawPolygon(points, 3); painter.rotate(m_yaw); } // draw altitude { int altFontSize = 13; int fx, fy, w, h; QString s; char buf[200]; w = 130; h = 2*(altFontSize + 8); fx = -w/2; fy = -h/2; blackPen.setWidth(2); painter.setPen(blackPen); painter.setBrush(QBrush(Qt::white)); painter.setFont(QFont("", altFontSize)); painter.drawRoundedRect(fx, fy, w, h, 6, 6); painter.setPen(bluePen); sprintf(buf, "ALT: %6.1f m", m_alt); s = buf; painter.drawText(QRectF(fx, fy+2, w, h/2), Qt::AlignCenter, s); sprintf(buf, "H: %6.1f m", m_h); s = buf; painter.drawText(QRectF(fx, fy+h/2, w, h/2), Qt::AlignCenter, s); } }
void TimeBar::paintEvent( QPaintEvent * event ) { QPen pen(QColor(0,0,0)); QPen GrayPen(QColor(0,0,0,50)); QBrush bush(QColor(0,0,0,70)); QPainter painter(this); pen.setWidth(1); painter.setPen(pen); painter.setBrush(bush); for(int i=0;i<100;i++) { if (mZoom*i<=event->rect().right()) { //绘制大刻度 painter.drawLine(QPointF(mZoom*i,15),QPointF(mZoom*i,25)); painter.drawText(QPointF(mZoom*i,10),QString("%1.0S").arg(i)); //绘制小刻度 for (int j=1;j<mZoom/MIN_SCALE_SIZE;j++) { painter.drawLine(QPointF(MIN_SCALE_SIZE*j+mZoom*i,20),QPointF(MIN_SCALE_SIZE*j+mZoom*i,25)); } //绘制TimeLine QMapIterator<int,QVector<TimeLine*>*> mapIt(mTimeLine); while (mapIt.hasNext()) { mapIt.next(); for (QVector<TimeLine*>::const_iterator it=mapIt.value()->begin();it!=mapIt.value()->end();it++) { if ((*it)->startTime>=i*1000 && (*it)->startTime<=(i+1)*1000) { //计算TimeLine起始位置 float startX=mZoom*((*it)->startTime/1000.0); painter.drawRoundedRect (QRectF(startX,28+mapIt.key()*15+mapIt.key()*3,mZoom*((*it)->len()/1000.0),15),5,3); } } } //绘制对齐线 painter.setPen(GrayPen); painter.drawLine(QPointF(mZoom*i,15),QPointF(mZoom*i,event->rect().bottom())); painter.setPen(pen); } else { break; } } //绘制当前位置 QPen redPen(QColor(255,0,0,125)); painter.setPen(redPen); painter.setBrush(QBrush(QColor(255,0,0,125))); float startX=mZoom*(mCurrTime/1000.0); painter.drawLine(QPointF(startX,25),QPointF(startX,event->rect().bottom())); painter.drawRect(QRect(startX-3,10,6,15)); //绘制工具提示 if(!mToopTip.isEmpty()) { redPen.setColor(QColor(255,0,0)); painter.setBrush(QBrush(QColor(255,255,255))); painter.setPen(redPen); QFontMetrics fm(painter.font()); painter.drawRect(QRect(mToolTipX-3,mToolTipY-fm.height(),fm.width(mToopTip)+3,fm.height()+6)); painter.drawText(mToolTipX,mToolTipY,mToopTip); } }
// Build the calibration "step" graph which will appear on the lefthand side of the panels wxBitmap CalReviewDialog::CreateGraph(bool AO) { wxMemoryDC memDC; wxBitmap bmp(CALREVIEW_BITMAP_SIZE, CALREVIEW_BITMAP_SIZE, -1); wxPen axisPen("BLACK", 3, wxCROSS_HATCH); wxPen redPen("RED", 3, wxSOLID); wxPen bluePen("BLUE", 3, wxSOLID); wxBrush redBrush("RED", wxSOLID); wxBrush blueBrush("BLUE", wxSOLID); CalibrationDetails calDetails; double scaleFactor; int ptRadius; if (!pSecondaryMount) { pMount->GetCalibrationDetails(&calDetails); // Normal case, no AO } else { if (AO) { pMount->GetCalibrationDetails(&calDetails); // AO tab, use AO details } else { pSecondaryMount->GetCalibrationDetails(&calDetails); // Mount tab, use mount details } } // Find the max excursion from the origin in order to scale the points to fit the bitmap double biggestVal = -100.0; for (std::vector<wxRealPoint>::const_iterator it = calDetails.raSteps.begin(); it != calDetails.raSteps.end(); ++it) { biggestVal = wxMax(biggestVal, fabs(it->x)); biggestVal = wxMax(biggestVal, fabs(it->y)); } for (std::vector<wxRealPoint>::const_iterator it = calDetails.decSteps.begin(); it != calDetails.decSteps.end(); ++it) { biggestVal = wxMax(biggestVal, fabs(it->x)); biggestVal = wxMax(biggestVal, fabs(it->y)); } if (biggestVal > 0.0) scaleFactor = ((CALREVIEW_BITMAP_SIZE - 5) / 2) / biggestVal; // Leave room for circular point else scaleFactor = 1.0; memDC.SelectObject(bmp); memDC.SetBackground(*wxLIGHT_GREY_BRUSH); memDC.Clear(); memDC.SetPen(axisPen); // Draw the axes memDC.SetDeviceOrigin(wxCoord(CALREVIEW_BITMAP_SIZE / 2), wxCoord(CALREVIEW_BITMAP_SIZE / 2)); memDC.DrawLine(-CALREVIEW_BITMAP_SIZE / 2, 0, CALREVIEW_BITMAP_SIZE / 2, 0); // x memDC.DrawLine(0, -CALREVIEW_BITMAP_SIZE / 2, 0, CALREVIEW_BITMAP_SIZE / 2); // y if (calDetails.raStepCount > 0) { // Draw the RA data memDC.SetPen(redPen); memDC.SetBrush(redBrush); ptRadius = 2; // Scale the points, then plot them individually for (int i = 0; i < (int) calDetails.raSteps.size(); i++) { if (i == calDetails.raStepCount + 2) // Valid even for "single-step" calibration { memDC.SetPen(wxPen("Red", 1)); // 1-pixel-thick red outline memDC.SetBrush(wxNullBrush); // Outline only for "return" data points ptRadius = 3; } memDC.DrawCircle(IntPoint(calDetails.raSteps.at(i), scaleFactor), ptRadius); } // Show the line PHD2 will use for the rate memDC.SetPen(redPen); if ((int)calDetails.raSteps.size() > calDetails.raStepCount) // New calib, includes return values memDC.DrawLine(IntPoint(calDetails.raSteps.at(0), scaleFactor), IntPoint(calDetails.raSteps.at(calDetails.raStepCount), scaleFactor)); else memDC.DrawLine(IntPoint(calDetails.raSteps.at(0), scaleFactor), IntPoint(calDetails.raSteps.at(calDetails.raStepCount - 1), scaleFactor)); } // Handle the Dec data memDC.SetPen(bluePen); memDC.SetBrush(blueBrush); ptRadius = 2; if (calDetails.decStepCount > 0) { for (int i = 0; i < (int) calDetails.decSteps.size(); i++) { if (i == calDetails.decStepCount + 2) { memDC.SetPen(wxPen("Blue", 1)); // 1-pixel-thick red outline memDC.SetBrush(wxNullBrush); // Outline only for "return" data points ptRadius = 3; } memDC.DrawCircle(IntPoint(calDetails.decSteps.at(i), scaleFactor), ptRadius); } // Show the line PHD2 will use for the rate memDC.SetPen(bluePen); if ((int)calDetails.decSteps.size() > calDetails.decStepCount) // New calib, includes return values memDC.DrawLine(IntPoint(calDetails.decSteps.at(0), scaleFactor), IntPoint(calDetails.decSteps.at(calDetails.decStepCount), scaleFactor)); else memDC.DrawLine(IntPoint(calDetails.decSteps.at(0), scaleFactor), IntPoint(calDetails.decSteps.at(calDetails.decStepCount - 1), scaleFactor)); } memDC.SelectObject(wxNullBitmap); return bmp; }
void CPDObjectFrameSelected::DrawThreadRects(Gdiplus::Graphics* pGraphics, Gdiplus::Color& color, IPDMatrix* matrix) { Gdiplus::Pen pen(color); Gdiplus::SolidBrush brush(color); CComQIPtr<IPDObjectFrame> frame = m_object; if (frame) { CComPtr<IPDObject> content; frame->get_content(&content); CComQIPtr<IPDContentText> contentText = content; if (contentText) { PointD m_threadPtLeft; PointD m_threadPtRight; contentText->get_threadPtIn(&m_threadPtLeft); contentText->get_threadPtOut(&m_threadPtRight); double rotation; matrix->getRotation(&rotation); CComPtr<IPDObjectText> previousContentText; contentText->get_previousTextThread(&previousContentText); CComPtr<IPDObjectText> nextContentText; contentText->get_nextTextThread(&nextContentText); Gdiplus::SolidBrush whiteBrush(Gdiplus::Color(255, 255, 255)); { PointD xpt; matrix->transformPoint(&m_threadPtLeft, &xpt); Gdiplus::Rect rc(xpt.x-4, xpt.y-4, 9, 9); pGraphics->FillRectangle(&whiteBrush, rc); pGraphics->DrawRectangle(&pen, rc); if (previousContentText != NULL) { DrawThreadRectArrow(pGraphics, &brush, rc, rotation); } } { PointD xpt; matrix->transformPoint(&m_threadPtRight, &xpt); Gdiplus::Rect rc(xpt.x-4, xpt.y-4, 9, 9); pGraphics->FillRectangle(&whiteBrush, rc); VARIANT_BOOL overflow; contentText->get_overflow(&overflow); if (nextContentText != NULL) { pGraphics->DrawRectangle(&pen, rc); DrawThreadRectArrow(pGraphics, &brush, rc, rotation); } else { if (overflow) { Gdiplus::Pen redPen(Gdiplus::Color(255, 0, 0), 1); pGraphics->DrawRectangle(&redPen, rc); pGraphics->DrawLine(&redPen, rc.X+rc.Width/2, rc.Y+2, rc.X+rc.Width/2, rc.GetBottom()-1); pGraphics->DrawLine(&redPen, rc.X+2, rc.Y+rc.Height/2, rc.GetRight()-1, rc.Y+rc.Height/2); } else { pGraphics->DrawRectangle(&pen, rc); } } } } CComPtr<IPDPathText> pathText; frame->get_pathText(&pathText); if (pathText) { CComPtr<IPDMatrix> mat0; mat0.CoCreateInstance(CLSID_PDMatrix); CComPtr<IPDMatrix> mat1; mat0->translate(-m_pthreadPtLeft.x, -m_pthreadPtLeft.y, &mat1); CComPtr<IPDMatrix> mat2; mat1->rotate(m_pthreadRotationLeft, &mat2); CComPtr<IPDMatrix> mat3; mat2->translate(m_pthreadPtLeft.x, m_pthreadPtLeft.y, &mat3); CComPtr<IPDMatrix> mat; mat3->multiply(matrix, &mat); double x = m_pthreadPtLeft.x; double y = m_pthreadPtLeft.y; // { PointD xpt1; mat->transformPoint((PointD*)&CDblPoint(x, y), &xpt1); PointD xpt2; mat->transformPoint((PointD*)&CDblPoint(x, y+20), &xpt2); pGraphics->DrawLine(&pen, (float)xpt1.x, (float)xpt1.y, (float)xpt2.x, (float)xpt2.y); } { PointD pts[4] = { x, y, x-12, y, x-12, y+12, x, y+12 }; PointD xpts[4]; for (int i = 0; i < 4; i++) { mat->transformPoint(&pts[i], &xpts[i]); } pGraphics->DrawLine(&pen, (float)xpts[0].x, (float)xpts[0].y, (float)xpts[1].x, (float)xpts[1].y); pGraphics->DrawLine(&pen, (float)xpts[1].x, (float)xpts[1].y, (float)xpts[2].x, (float)xpts[2].y); pGraphics->DrawLine(&pen, (float)xpts[2].x, (float)xpts[2].y, (float)xpts[3].x, (float)xpts[3].y); pGraphics->DrawLine(&pen, (float)xpts[3].x, (float)xpts[3].y, (float)xpts[0].x, (float)xpts[0].y); } } } }
void BpDocument::composeFireCharacteristicsDiagram( void ) { // Surface Module must be active and using fuel model inputs PropertyDict *prop = m_eqTree->m_propDict; if ( ! prop->boolean( "surfaceModuleActive" ) || ! prop->boolean( "surfaceCalcFireCharacteristicsDiagram" ) ) { return; } // Graph fonts. QFont textFont( property()->string( "graphTextFontFamily" ), property()->integer( "graphTextFontSize" ) ); QColor textColor( property()->color( "graphTextFontColor" ) ); QPen textPen( textColor ); QFont subTitleFont( property()->string( "graphSubtitleFontFamily" ), property()->integer( "graphSubtitleFontSize" ) ); QColor subTitleColor( property()->color( "graphSubtitleFontColor" ) ); // Open the result file QString resultFile = m_eqTree->m_resultFile; FILE *fptr = 0; if ( ! ( fptr = fopen( resultFile.latin1(), "r" ) ) ) // This code block should never be executed! { QString text(""); translate( text, "BpDocument:FireCharacteristicsDiagram:NoLogOpen", resultFile ); error( text ); return; } // Allocate ros and hpua data arrays int rows = tableRows(); int cols = tableCols(); int cells = rows * cols; double *hpua = new double[ cells ]; checkmem( __FILE__, __LINE__, hpua, "double hpua", cells ); double *ros = new double[ cells ]; checkmem( __FILE__, __LINE__, ros, "double ros", cells ); // Set the variable names we're looking for const char* hpuaName = "vSurfaceFireHeatPerUnitArea"; const char* rosName = "vSurfaceFireSpreadAtHead"; if ( prop->boolean( "surfaceConfSpreadDirInput" ) ) { rosName = "vSurfaceFireSpreadAtVector"; } // Read and store the ros and hpua values char buffer[1024], varName[128], varUnits[128]; int row, col, cell; double value; double rosMax = 0.0; double hpuaMax = 0.0; while ( fgets( buffer, sizeof(buffer), fptr ) ) { if ( strncmp( buffer, "CELL", 4 ) == 0 ) { if ( strstr( buffer, hpuaName ) ) { sscanf( buffer, "CELL %d %d %s cont %lf %s", &row, &col, varName, &value, varUnits ); cell = ( col - 1 ) + ( cols * ( row - 1) ); if ( ( hpua[ cell ] = value ) > hpuaMax ) { hpuaMax = value; } } else if ( strstr( buffer, rosName ) ) { sscanf( buffer, "CELL %d %d %s cont %lf %s", &row, &col, varName, &value, varUnits ); cell = ( col - 1 ) + ( cols * ( row - 1) ); if ( ( ros[ cell ] = value ) > rosMax ) { rosMax = value; } } } } fclose( fptr ); // Get variable pointers EqVar *hpuaVar = m_eqTree->m_varDict->find( "vSurfaceFireHeatPerUnitArea" ); EqVar *rosVar = m_eqTree->m_varDict->find( "vSurfaceFireSpreadAtHead" ); EqVar *fliVar = m_eqTree->m_varDict->find( "vSurfaceFireLineIntAtHead" ); EqVar *flVar = m_eqTree->m_varDict->find( "vSurfaceFireFlameLengAtHead" ); // Conversion factor double flFactor, fliFactor, rosFactor, hpuaFactor, offset; appSiUnits()->conversionFactorOffset( flVar->m_nativeUnits, flVar->m_displayUnits, &flFactor, &offset ); appSiUnits()->conversionFactorOffset( fliVar->m_nativeUnits, fliVar->m_displayUnits, &fliFactor, &offset ); appSiUnits()->conversionFactorOffset( hpuaVar->m_nativeUnits, hpuaVar->m_displayUnits, &hpuaFactor, &offset ); appSiUnits()->conversionFactorOffset( rosVar->m_nativeUnits, rosVar->m_displayUnits, &rosFactor, &offset ); // Determine which of four different chart scales to use static const int Scales = 4; static double RosScale[Scales] = { 100., 200., 400., 800. }; // ft/min static double HpuaScale[Scales] = { 2000., 4000., 8000., 16000. }; // Btu/ft2 double rosScale = 0.; // Max y-axis ros double hpuaScale = 0.; // Max x-axis hpua int scale; for ( scale=0; scale<Scales; scale++ ) { if ( rosMax < ( rosScale = RosScale[ scale ] ) ) { break; } } for ( scale=0; scale<Scales; scale++ ) { if ( hpuaMax < ( hpuaScale = HpuaScale[scale] ) ) { break; } } // Set axis maximums to appropriate predefined scale in display units rosMax = rosFactor * rosScale; hpuaMax = hpuaFactor * hpuaScale; double ratio = rosMax / hpuaMax; // Create the graph Graph graph; GraphLine *graphLine; GraphMarker *graphMarker; static const int Points = 100; double l_x[Points]; double l_y[Points]; // Draw the four standard hauling chart fli-fl levels static const int Lines = 4; static const double Fli[Lines] = { 100., 500., 1000., 2000. }; // Btu/ft/s static const double Fl[Lines] = { 4., 8., 11., 15. }; // ft // Create the hauling chart lines // Put Fireline Int label 65% of the way along the HPUA axis (display units) double xPosFli = 0.65 * hpuaMax; // Put Flame Length label 85% of the way along the HPUA axis (display units) double xPosFl = 0.85 * hpuaMax; // Fireline Int and Flame Length label Y positions (display units) double yPosFl[Lines], yPosFli[Lines]; // Icon locations (in display units) double xIcon[Lines+1], yIcon[Lines+1]; double diff, minDiff; QString label; QPen redPen( "red", 1 ); QColor blackColor( "black" ); int alignCenter = Qt::AlignHCenter | Qt::AlignVCenter; // Fireline intensity - flame length curves int line, point; for ( line = 0; line < Lines; line++ ) { minDiff = 999999999.; for ( point = 0; point < Points; point++ ) { // Hpua value in native units (Btu/ft2) l_x[point] = ( (point+1) * hpuaScale ) / (double) Points; // Ros value in native units (ft/min) l_y[point] = 60. * Fli[line] / l_x[point]; // Convert to display units l_x[point] *= hpuaFactor; l_y[point] *= rosFactor; // Check for curve inflection point (for icon placement) if ( ( diff = fabs( l_y[point]/l_x[point] - ratio ) ) < minDiff ) { minDiff = diff; xIcon[line+1] = l_x[point]; yIcon[line+1] = l_y[point]; } } // Create a graph line (with its own copy of the data). graphLine = graph.addGraphLine( Points, l_x, l_y, redPen ); // Fireline intensity label label = QString( "%1" ).arg( ( Fli[line] * fliFactor ), 0, 'f', 0 ); yPosFli[line] = rosFactor * ( 60. * Fli[line] / ( xPosFli / hpuaFactor ) ); graph.addGraphMarker( xPosFli, yPosFli[line], label, textFont, blackColor, alignCenter ); // Flame length label label = QString( "%1" ).arg( ( Fl[line] * flFactor ), 0, 'f', 0 ); yPosFl[line] = rosFactor * ( 60. * Fli[line] / ( xPosFl / hpuaFactor ) ); graph.addGraphMarker( xPosFl, yPosFl[line], label, textFont, blackColor, alignCenter ); } // Next line // Fireline intensity label and units translate( label, "BpDocument:FireCharacteristicsDiagram:FLI" ); graph.addGraphMarker( xPosFli, ( yPosFli[Lines-1] + 0.10 * rosMax ), label, textFont, blackColor, alignCenter ); graph.addGraphMarker( xPosFli, ( yPosFli[Lines-1] + 0.05 * rosMax ), fliVar->m_displayUnits, textFont, blackColor, alignCenter ); // Flame length label and units translate( label, "BpDocument:FireCharacteristicsDiagram:FL" ); graph.addGraphMarker( xPosFl, ( yPosFl[Lines-1] + 0.10 * rosMax ), label, textFont, blackColor, alignCenter ); graph.addGraphMarker( xPosFl, ( yPosFl[Lines-1] + 0.05 * rosMax ), flVar->m_displayUnits, textFont, blackColor, alignCenter ); // Add icons QPixmap pixmap[Lines]; pixmap[0] = QPixmap( fireman_xpm ); pixmap[1] = QPixmap( dozer_xpm ); pixmap[2] = QPixmap( torchtree_xpm ); pixmap[3] = QPixmap( mtnfire_xpm ); xIcon[0] = yIcon[0] = 0.0; for ( line=0; line<Lines; line++ ) { graphMarker = graph.addGraphMarker( xIcon[line] + ( 0.5 * ( xIcon[line+1] - xIcon[line] ) ), yIcon[line] + ( 0.5 * ( yIcon[line+1] - yIcon[line] ) ), "", textFont, blackColor, alignCenter ); graphMarker->setGraphMarkerPixmap( pixmap[line] ); } // Finally, add a marker for each output result QColor bluePen( "blue" ); for ( cell=0; cell<cells; cell++ ) { //fprintf( stderr, "%02d: %3.2f %3.2f\n", i, hpua[i], ros[i] ); graph.addGraphMarker( hpua[cell], ros[cell], QString( "%1" ).arg( cell + 1 ), textFont, bluePen, alignCenter ); } // Compose the graph EqVar *zVar = 0; GraphAxleParms xParms( 0.0, hpuaMax, 11 ); GraphAxleParms yParms( 0.0, rosMax, 11 ); composeGraphBasics( &graph, true, hpuaVar, rosVar, zVar, Lines, &xParms, &yParms ); // Create a separate page for this graph. translate( label, "BpDocument:FireCharacteristicsDiagram:Caption" ); graph.setSubTitle( label, subTitleFont, subTitleColor ); startNewPage( label, TocHaulChart ); // This is how we save the graph and its composer. m_composer->graph( graph, m_pageSize->m_marginLeft + m_pageSize->m_bodyWd * property()->real( "graphXOffset" ), m_pageSize->m_marginTop + m_pageSize->m_bodyHt * property()->real( "graphYOffset" ), m_pageSize->m_bodyWd * property()->real( "graphScaleWidth" ), m_pageSize->m_bodyHt * property()->real( "graphScaleHeight" ) ); // Be polite and stop the composer. m_composer->end(); delete[] ros; ros = 0; delete[] hpua; hpua = 0; return; }
void BehavePlusApp::drawSplashPage( void ) { // If unable to load the picture, make a plain cyan backdrop instead if ( m_pixmap.isNull() ) // This code block should never be executed! { m_pixmap.resize( 700, 500 ); QPainter paint( &m_pixmap ); paint.fillRect( 0, 0, 700, 500, QBrush( "cyan", SolidPattern ) ); paint.end(); } // Painter attributes int align = Qt::AlignHCenter | Qt::AlignTop ; //static QString fontName( "Times New Roman" ); static QString fontName( "Arial" ); QFont fnt1( fontName, 48, QFont::Bold, false ); QFont fnt2( fontName, 24, QFont::Bold, false ); QFont fnt3( fontName, 16, QFont::Bold, false ); QFontMetrics fm1( fnt1 ); QFontMetrics fm2( fnt2 ); QFontMetrics fm3( fnt3 ); QPen blackPen( black ); QPen grayPen( gray ); QPen redPen( red ); QPen whitePen( white ); // Draw shadowed name QPainter paint( &m_pixmap ); int wd = m_pixmap.width(); int ht = m_pixmap.height() + 3 * fm3.lineSpacing(); paint.setFont( fnt1 ); paint.setPen( grayPen ); int y0 = fm1.lineSpacing()/8; paint.drawText( 4, y0+4, wd, ht, align, m_program ); paint.setPen( blackPen ); paint.drawText( 2, y0+2, wd, ht, align, m_program ); paint.setPen( whitePen ); paint.drawText( 0, y0, wd, ht, align, m_program ); // Draw sub name and version y0 += 3*fm1.lineSpacing()/4; paint.setFont( fnt2 ); paint.drawText( 0, y0, wd, ht-y0, align, "fire modeling system" ); y0 += 3*fm2.lineSpacing()/4; paint.drawText( 0, y0, wd, ht-y0, align, "Version " + m_version ); // Warning if ( ShowWarning ) { y0 += 3 * fm2.lineSpacing(); paint.setFont( fnt2 ); paint.setPen( redPen ); paint.drawText( 0, y0, wd, ht-y0, align, "This is pre-release software" ); y0 += fm2.lineSpacing(); paint.drawText( 0, y0, wd, ht-y0, align, "for testing purposes only!" ); y0 += fm2.lineSpacing(); paint.drawText( 0, y0, wd, ht-y0, align, "Use at Your Own Risk!" ); } // Authors y0 = ht - 6 * fm3.lineSpacing(); paint.setFont( fnt3 ); paint.setPen( whitePen ); paint.drawText( 0, y0, wd, ht-y0, align, "US Forest Service, Rocky Mountain Research Station" ); y0 += fm3.lineSpacing(); paint.drawText( 0, y0, wd, ht-y0, align, "& Systems for Environmental Management" ); paint.end(); // Status message display area m_statusLine = ht - 2 * fm3.lineSpacing(); return; }