/**************************************************************************** ** ** Copyright (C) 2019 Minnesota Department of Transportation ** Office of Materials & Road Research ** 1400 Gervais Avenue ** Saint Paul, Minnesota 55109-2044 ** USA ** http://www.dot.state.mn.us/materials/pvmtdesign/software.html ** ** ** $QT_BEGIN_LICENSE:GPL$ ** ** This program is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** If you did not receive a copy of the GNU General Public License ** see http://www.gnu.org/licenses ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "mnpave.h" #include "ui_mnpave.h" #include "globals.h" #include "calc.h" #include "aboutdlg.h" #include "climatedlg.h" #include "helpdlg.h" #include "layerdlg.h" #include "mapdlg.h" #include "mydoublespinbox.h" #include "notesdlg.h" #include "outputdlg.h" #include "trafficdlg.h" #include "weslea.h" mnpave::mnpave(QWidget *parent) : QMainWindow(parent), ui(new Ui::mnpave) { ui->setupUi(this); calc c; this->setWindowTitle(newWinTitle(tName)); setMouseTracking(true); nCount = 0; double tt = c.airT(45., 2); quint64 ntst = 0; QString ttst = bas2bas54("10111100100011", "01", A32RFC4648, &ntst); int i, j; int k = A64.indexOf("4"); QString a = A64.at(k); // qDebug() << a; QFont font; font.setBold(true); ui->infoGroup->setFont(font); font.setBold(false); ui->infoGroup->setFont(font); // Initialize lists (serialized) bList.reserve(89); // expected number of items in the list bList.append(false); // 0 units (False = English, True = SI) bList.append(true); // 1 show thickness warnings bList.append(true); // 2 show binder warnings bList.append(false); // 3 always show allowable stress bList.append(true); // 4 only show if failed bList.append(false); // 5 design (false) or research (true) mode bList.append(false); // 6 ESAL (false) or spectrum (true) bList.append(false); // 7 simple (false) or compound (true) growth bList.append(false); // 8 Perpetual Pavement all strains (false) or ignore low (true) bList.append(false); // 9 user entered climate data bList.append(true); // 10 Tpave (false) or Tair (true) bList.append(false); // 11 Use same temperature depth for all HMA lifts bList.append(false); // 12 User depth for temperature calculation bList.append(false); // 13 life ESALs (false) or 1st year (true) bList.append(true); // 14 spectrum: interpolate strains bList.append(false); // 15 MnDOT vehicles (false) or FHWA (true) bList.append(false); // 16 Use HCADT in Spectrum estimate (false = ADT) bList.append(false); // 17 seasonal spectra bList.append(false); // 18 Use WIM data to calculate spectrum bList.append(false); // 19 User changed Structure (don't set default layers) bList.append(false); // 20 Use mean H & E values (instead of reduced for confidence) bList.append(false); // 21 Show rutting for overlay design bList.append(false); // 22 Mill & Overlay bList.append(false); // 23 SI units in FWDSim bList.append(true); // 24 SI units in LWDSim bList.append(false); // 25 use BELLS3 temperature calculation in FWDSim bList.append(true); // 26 Use overburden in simulations bList.append(false); // 27 Show pavement life in years (true = damage factor) bList.append(false); // 28 Define z location by percent bList.append(false); // 29 batch damage limit for(i = 0; i < 5; ++i) {bList.append(false);} // 30-34 are agg test check boxes for(i = 0; i < 5; ++i) {bList.append(false);} // 35-39 are soil test check boxes // Research Mode for(i = 0; i < 5; ++i) {bList.append(true);} // 40-44 are season check boxes for(i = 0; i < 7; ++i) {bList.append(i < 4 ? true : false);} // 47-51 are axle check boxes for(i = 0; i < 35; ++i) {bList.append(false);} // 52-86 indicate if there are at least 3 load categories for strain interpolation // end BOOL imports from MnPAVE 6.4 bList.append(false); // 87 widened outer lane bList.append(false); // 88 tied PCC shoulder iList.reserve(4931); iList.append(20); // 0 HMA Design Life iList.append(3); // 1 HMA layers (number of layers = index + 1) iList.append(0); // 2 Struc Mode (basic) iList.append(2); // 3 Agg Test (E, R-Value, DCP, CBR) iList.append(1); // 4 Soil Test (E, R-Value, DCP, SiltClay iList.append(5000); // 5 MC Cycles iList.append(1); // 6 Spectrum Mode (1 = Intermediate) iList.append(1); // 7 Witczak Version (1 = 2002) iList.append(0); // 8 ESAL axle selection (Old: 0=Dual,1=DTan,2=DTri,3=Single..., New: 0=ESAL, 1=Dual...) iList.append(3); // 9 Spectrum Road Type (3 = Rural Highway) for(i = 0; i < 3; ++i) {iList.append(0);} // 10-12 number of lifts in 1st 3 layers for(i = 0; i < 5; ++i) {iList.append(-1);} // 13-17 materials in each layer for(i = 0; i < 4; ++i) {iList.append(25);} // 18-21 % depth in each layer for(i = 0; i < 4; ++i) {iList.append(0);} // 22-25 eval responses (NormStress, ShearStress, NormStrain, Deflection, Prin. Stress) for(i = 0; i < 4; ++i) {iList.append(0);} // 26-29 eval directions (X, Y, Z) for(i = 0; i < 4; ++i) {iList.append(0);} // 30-33 eval locations (top, middle, bottom) for(i = 0; i < 6; ++i) {iList.append(0);} // 34-39 number of load categories for each season for(i = 0; i < 360; ++i) {iList.append(0);} // 40-399 all load classes [axle type][load class] for(i = 0; i < 2160; ++i) {iList.append(0);} // 400-2559 seasonal life reps (Fall, Winter..., All) for(i = 0; i < 2160; ++i) {iList.append(0);} // 2560-4719 seasonal life reps (Fall, Winter..., All) for(i = 0; i < 180; ++i) {iList.append(-1);} // 4720-4899 material subtypes for each material type for(i = 0; i < 6; ++i) {iList.append(0);} // 4900-4905 binder spec, nom max size for 3 lifts for(i = 0; i < 3; ++i) {iList.append(0);} // 4906-4908 temperature depth selections for 3 lifts (0 = 1/3, 1 = 1/2, 2 = constant depth) for(i = 0; i < 3; ++i) {iList.append(0);} // 4909-4911 nFWDSIM (season, layer, sensors) iList.append(3); // 4912 nLWDLayer (selected layer) for(i = 0; i < 5; ++i) {iList.append(2);} // 4913-4917 nLWDMoist (selected moisture column) iList.append(0); // 4918 Bituminous Sublayer (0 = Old HMA, 1 = CIR, 2 = SFDR) iList.append(0); // 4919 Fatigue Model Selected iList.append(0); // 4920 Rutting Model Selected iList.append(-1); // 4921 Agg layer containing geogrid (-1: no geogrid) // End of int imported from MnPAVE 6.4 iList.append(35); // 4922 PCC life iList.append(0); // 4923 number of lanes (two-way) iList.append(0); // 4924 axle load spectrum selection iList.append(0); // 4925 joint spacing iList.append(0); // 4926 pcc base material (CL5S, CL5Q, OGAB) iList.append(0); // 4927 pcc base thickness (4 or 12") iList.append(3); // 4928 rigid layers index (number of layers = index + 1) iList.append(1); // 4929 soil type iList.append(2); // 4930 wheels per half axle (custom axle type) iList.append(1); // 4931 construction type (HMA or PCC) 20180725 temporarily select PCC dList.reserve(452); dList.append(0.0); // 0 ESALs (millions) for(i = 0; i < 12; ++i) {dList.append(0.0);} // 1-12 sublayer thickness (3 per layer) for(i = 0; i < 4; ++i) {dList.append(0.0);} // 13-16 layer thickness COV for(i = 0; i < 20; ++i) {dList.append(0.0);} // 17-36 aggregate test values for(i = 0; i < 20; ++i) {dList.append(0.0);} // 37-56 soil test values for(i = 0; i < 5; ++i) {dList.append(0.0);} // 57-61 other test values for(i = 0; i < 25; ++i) {dList.append(0.0);} // 62-86 user moduli for(i = 0; i < 25; ++i) {dList.append(0.0);} // 87-111 user Poissons ratios for(i = 0; i < 25; ++i) {dList.append(0.0);} // 112-136 user modulus COVs for(i = 0; i < 42; ++i) {dList.append(0.0);} // 137-178 Witczak values dList.append(1.0); // 179 ipct traffic growth rate (%) dList.append(8.0); // 180 Va air voids at bottom of HMA (%) dList.append(60); // 181 mph traffic speed dList.append(18); // 182 thawDepth early spring for(i = 0; i < 5; ++i) {dList.append(0.0);} // 183-187 user season durations for(i = 0; i < 5; ++i) {dList.append(0.0);} // 188-192 user seasonal air temperatures for(i = 0; i < 5; ++i) {dList.append(0.0);} // 193-197 user seasonal pavement temperatures dList.append(0.0); // 198 AADT dList.append(70.0); // 199 Confidence for(i = 0; i < 42; ++i) {dList.append(0.0);} // 200-241 user Witczak a values for(i = 0; i < 6; ++i) {dList.append(0.0);} // 242-247 user Witczak b values for(i = 0; i < 10; ++i) {dList.append(100.0);} // 248-257 Tire pressure for each axle type (8 is for ESAL, 9 is for custom) for(i = 0; i < 10; ++i) {dList.append(13.5);} // 258-267 xSpace lateral tire spacing for(i = 0; i < 10; ++i) {dList.append(54.0);} // 268-277 ySpace longitudinal tire spacing dList.append(1.9); // 278 MnDOT Class 4 dList.append(0.9); // 279 MnDOT Class 5 dList.append(0.1); // 280 MnDOT Class 6 dList.append(0.2); // 281 MnDOT Class 7 dList.append(4.5); // 282 MnDOT Class 8 (new: 5+ Axle Semi) dList.append(0.0); // 283 MnDOT Class 9a (new: 5+ Max) dList.append(0.0); // 284 MnDOT Class 9b (new: 5+ Other) dList.append(0.4); // 285 MnDOT Class 10 dList.append(0.8); // 286 MnDOT Class 11 dList.append(0.0); // 287 unused for(i = 0; i < 10; ++i) {dList.append(0.0);} // 288-297 vFHWA % vehicle classes for(i = 0; i < 6; ++i) {dList.append(0.0);} // 298-303 WIMDays (time of WIM testing for each axle type) for(i = 0; i < 48; ++i) {dList.append(0.0);} // 304-351 Mohr Weight [Fall, Winter, ... All][Axle] for(i = 0; i < 12; ++i) {dList.append(0.0);} // 352-363 C, Phi AggBase for(i = 0; i < 12; ++i) {dList.append(0.0);} // 364-375 C, Phi Subbase dList.append(22.0); // 376 Mohr Weight 1 (kips) dList.append(28.0); // 377 Mohr Weight 2 (kips) dList.append(100.0); // 378 Mohr Pressure 1 (psi) dList.append(100.0); // 379 Mohr Pressure 2 (psi) dList.append(0.0); // 380 Mohr lateral spacing 1 (in) dList.append(13.5); // 381 Mohr lateral spacing 2 (in) for(i = 0; i < 5; ++i) {dList.append(0.0);} // 382-386 Intermediate Poisson's Ratios for(i = 0; i < 5; ++i) {dList.append(0.0);} // 387-391 Intermediate COV for(i = 0; i < 5; ++i) {dList.append(0.0);} // 392-396 Intermediate Resistance Factors for(i = 0; i < 5; ++i) {dList.append(0.0);} // 397-401 Other Poisson's Ratios for(i = 0; i < 3; ++i) {dList.append(0.0);} // 402-404 User A values (viscosity) for(i = 0; i < 3; ++i) {dList.append(0.0);} // 405-407 User VTS for(i = 0; i < 3; ++i) {dList.append(0.0);} // 408-410 User Kinematic Viscosity for(i = 0; i < 4; ++i) {dList.append(0.0);} // 411-414 User Gamma (unit weight, pcf) for(i = 0; i < 4; ++i) {dList.append(0.0);} // 415-418 User Ko (coef of earth pressure at rest) for(i = 0; i < 6; ++i) {dList.append(0.0);} // 419-424 FWD dia, kips, TLo, THi, hour, Temp F for(i = 0; i < 10; ++i) {dList.append(0.0);} // 425-434 FWD sensor offset for(i = 0; i < 3; ++i) {dList.append(0.0);} // 435-437 LWD dia, load, resistance factor for(i = 0; i < 5; ++i) {dList.append(0.0);} // 438-442 LWDmils dList.append(-70.0); // 443 HMA Threshold dList.append(300.0); // 444 Soil Threshold dList.append(2.5); // 445 Pt, AASHTO terminal serviceability for LEF dList.append(0.0); // 446 effective geogrid modulus dList.append(0.0); // 447 FatMCRel dList.append(0.0); // 448 RutMCRel dList.append(18.0); // 449 Custom Axle Wtj (kips) // End of double imported from MnPAVE 6.4 dList.append(0.0); // 450 HCADT dList.append(0.0); // 451 HPCC sList.reserve(14); sList.append(""); // 0 District sList.append(""); // 1 County sList.append(""); // 2 City sList.append(""); // 3 SP sList.append(""); // 4 Hwy sList.append(""); // 5 RP1 sList.append(""); // 6 RP2 sList.append(""); // 7 ConstType sList.append(""); // 8 Designer sList.append(""); // 9 SoilsEngineer sList.append(""); // 10 Notes for(i = 0; i < 3; ++i) {sList.append("User Defined " + QString::number(i+1));} // 11-13 custom HMA spec names assignPointers(); // hide research mode for now *bResearch = false; HCADTadj = 1.0; // (rigid) adjusts HCADT for very heavy loads ui->actionResearch->setVisible(false); ui->menuWarnings->setEnabled(false); ui->menuTraffic->setEnabled(false); ui->menuPerpetual_Pavement->setEnabled(false); if(PAVEMENT < BOTH) { *nConstType = PAVEMENT; ui->constCombo->setEnabled(false); if(PAVEMENT == RIGID) { *nRigidLayer = 3; *nSoil = 15; ui->distCombo->removeItem(8); // Remove "All" ui->coLabel->setVisible(false); ui->coCombo->setVisible(false); ui->mapButton->setVisible(false); ui->climateButton->setVisible(false); ui->outGroup->setTitle(tr("Calculate")); ui->calcButton->setText(tr("Calculate thickness")); } } *pTire[ESAL] = 80.; // reset ESAL tire pressure to 80 psi vList.reserve(2); vList.append(QDate()); // 0 let date vList.append(QPointF()); // 1 location (lon, lat) pAction[0] = ui->action1; pAction[1] = ui->action2; pAction[2] = ui->action3; pAction[3] = ui->action4; pAction[4] = ui->action5; pAction[5] = ui->action6; for(i = 0; i < MaxRecentFiles; ++i) { pAction[i]->setVisible(false); } pButton[0] = ui->layerButton1; pButton[1] = ui->layerButton2; pButton[2] = ui->layerButton3; pButton[3] = ui->layerButton4; pButton[4] = ui->layerButton5; pSpin[0] = ui->layerSpin1; pSpin[1] = ui->layerSpin2; pSpin[2] = ui->layerSpin3; pSpin[3] = ui->layerSpin4; loadW(); // load widget pointers & geometries // Initialize other variables bdefault = false; bspin = false; bopen = false; bxml = false; nDistrict = 8; // no district selected nCounty = -1; // no county selected nHlab = 0; // "Thickness" vList[0] = QDate::currentDate(); vList[1] = QPointF(-1,-1); nVersion = QApplication::applicationVersion().toInt(); tFile = ""; // initialize variables for temporary user data for(i = 0; i < 8; ++i) bedit[i] = false; for(i = 0; i < 4; ++i) val[i] = 0.0; for(i = 0; i < 5; ++i) tval[i] = ""; mpSettings("", READBOOL); updateView(); bmodified = false; tDisclaimer = tr("Disclaimer: The Minnesota Department of Transportation makes no guarantee or warranty, either express or implied, with respect to the reuse of the data provided herewith, regardless of its format or means of its transmission. The user accepts the data \"as is\", and assumes all risks associated with its use. By accepting of this data, the user agrees not to transmit this data or provide access to it or any part of it to another party unless the user shall include with the data a copy of this disclaimer. The Minnesota Department of Transportation assumes no responsibility, actual or consequential, for damage that results from any user's reliance on this data."); } mnpave::~mnpave() { delete ui; } void mnpave::assignPointers() { // assign pointers to clarify code int i, j, k; bsi = &bList[0]; // SI or English units bHWarn = &bList[1]; // Warn if HMA is too thin for critical stress bBWarn = &bList[2]; // Warn if -34 binder is required bMohrAlways = &bList[3]; // Always show Mohr window bMohrFail = &bList[4]; // only show Mohr window if critical stress test fails bResearch = &bList[5]; // research mode bSpectrum = &bList[6]; // load spectrum traffic bCompound = &bList[7]; // traffic growth mode bPerpetual = &bList[8]; // ignore strains below perpetual pavement threshold bUserClimate = &bList[9]; // user climate data instead of weather station bPaveT = &bList[10]; // user Pavement temperatures (false = Air) bzTSame = &bList[11]; // Use the same depth for all HMA lifts bMNTABLE = &bList[12]; // include load spectra from MNTABLE for comparison bFirstYearESAL = &bList[13]; // First year ESALS (false = design life ESALs) bInterpSpec = &bList[14]; // Interpolate spectrum strains to speed calc bFHWA = &bList[15]; // Use FHWA vehicle types bHCADT = &bList[16]; // Use HCADT in Spectrum estimate (false = ADT) bSeasSpec = &bList[17]; // Seasonal Spectra bWIM2Spec = &bList[18]; // Use WIM data to calculate Spectrum bUserStruc = &bList[19]; // User changed Structure (don't set default layers) bMeanHE = &bList[20]; // Use mean H & E values (instead of reduced for confidence) bOverlayRut = &bList[21]; // Show rutting for overlay design bOverlayMill = &bList[22]; // Enter milled thickness bSIFWD = &bList[23]; // SI units in FWD SIM bSILWD = &bList[24]; // SI units in LWD SIM bBELLS = &bList[25]; // use BELLS3 calculation for FWD pavement temperature bOverBurden = &bList[26]; // use overburden values in simulations bOutDamage = &bList[27]; // show damage factor (true = Life) bOutZPct = &bList[28]; // specify depth percent for layer simulation results bBatchLimits = &bList[29]; // eliminate extreme damage values from batch results for(i = 0; i < 5; ++i) {bAggtest[i] = &bList[30+i];} for(i = 0; i < 5; ++i) {bSoiltest[i] = &bList[35+i];} for(i = 0; i < 5; ++i) {bSeason[i] = &bList[40+i];} for(i = 0; i < 7; ++i) {bAxle[i] = &bList[45+i];} for(i = 0; i < 5; ++i) {for(j = 0; j < 7; ++j) {bSpecEst[i][j] = &bList[52+i*7+j];}} bWidened = &bList[87]; bTied = &bList[88]; nFlexLife = &iList[0]; nFlexLayer = &iList[1]; nStrucMode = &iList[2]; nAggTest = &iList[3]; nSoilTest = &iList[4]; nCycles = &iList[5]; nSpecMode = &iList[6]; nWitczak = &iList[7]; nCustWheel = &iList[4930]; nCustAxle = &iList[8]; nSpecRoad = &iList[9]; for(i = 0; i < 3; ++i) {nLifts[i] = &iList[10+i];} for(i = 0; i < 5; ++i) {nMat[i] = &iList[13+i];} for(i = 0; i < 4; ++i) {nEvalZ[i] = &iList[18+i];} for(i = 0; i < 4; ++i) {nResponse[i] = &iList[22+i];} for(i = 0; i < 4; ++i) {nDirection[i] = &iList[26+i];} for(i = 0; i < 4; ++i) {nLocation[i] = &iList[30+i];} for(i = 0; i < 6; ++i) {nLoads[i] = &iList[34+i];} for(i = 0; i < 8; ++i) {for(j = 0; j < 45; ++j) {nLoadRange[i][j] = &iList[40+i*45+j];}} for(k = 0; k < 6; ++k) {for(i = 0; i < 8; ++i) {for(j = 0; j < 45; ++j) {nSeasRange[k][i][j] = &iList[400+k*8*45+i*45+j];}}} for(k = 0; k < 6; ++k) {for(i = 0; i < 8; ++i) {for(j = 0; j < 45; ++j) {nWIMRange[k][i][j] = &iList[2560+k*8*45+i*45+j];}}} for(k = 0; k < 3; ++k) {for(i = 0; i < 5; ++i) {for(j = 0; j < 12; ++j) {nDet[k][i][j] = &iList[4720+k*5*12+i*12+j];}}} // additional sublayers assigned below for(i = 0; i < 3; ++i) {nSpec[i] = &iList[4900+i];} for(i = 0; i < 3; ++i) {nNomMax[i] = &iList[4903+i];} for(i = 0; i < 3; ++i) {nzT[i] = &iList[4906+i];} for(i = 0; i < 3; ++i) {nFWDSIM[i] = &iList[4909+i];} nLWDLayer = &iList[4912]; for(i = 0; i < 5; ++i) {nLWDMoist[i] = &iList[4913+i];} nGeogrid = &iList[4918]; // aggregate layer containing geogrid (-1: no geogrid) nOtherBit = &iList[4919]; // Bituminous Sublayer (0 = Old HMA, 1 = CIR, 2 = SFDR) nFatSel = &iList[4920]; // selected fatigue model (mnpave is the only default model) nRutSel = &iList[4921]; // selected rutting model (mnpave is the only default model) // End of int imported from MnPAVE 6.4 nRigidLife = &iList[4922]; nLanes = &iList[4923]; nRigidSpec = &iList[4924]; nJoint = &iList[4925]; nRigidBase = &iList[4926]; nRigidHBase = &iList[4927]; nRigidLayer = &iList[4928]; nSoil = &iList[4929]; nConstType = &iList[4931]; esal = &dList[0]; // ESALs / 1,000,000 for(i = 0; i < 4; ++i) {for(j = 0; j < 3; ++j) {H[i][j] = &dList[1+i*3+j];}} // next index = 13 for(i = 0; i < 4; ++i) {HCOV[i] = &dList[13+i];} // next index = 17 for(i = 0; i < 4; ++i) {for(j = 0; j < 5; ++j) {aggTest[i][j] = &dList[17+i*5+j];}} // next index = 37 for(i = 0; i < 4; ++i) {for(j = 0; j < 5; ++j) {soilTest[i][j] = &dList[37+i*5+j];}} // next index = 57 for(i = 0; i < 5; ++i) {otherTest[i] = &dList[57+i];} // next index = 62 for(i = 0; i < 5; ++i) {for(j = 0; j < 5; ++j) {userE[i][j] = &dList[62+i*5+j];}} // next index = 87 for(i = 0; i < 5; ++i) {for(j = 0; j < 5; ++j) {userU[i][j] = &dList[87+i*5+j];}} // next index = 112 for(i = 0; i < 5; ++i) {for(j = 0; j < 5; ++j) {userECOV[i][j] = &dList[112+i*5+j];}} // next index = 137 for(i = 0; i < 3; ++i) {for(j = 0; j < 14; ++j) {Wit[i][j] = &dList[137+i*14+j];}} // next index = 179 ipct = &dList[179]; // traffic growth rate Va = &dList[180]; // air voids at bottom of HMA (%) mph = &dList[181]; // traffic speed thawDepth = &dList[182]; // early spring thaw depth for(i = 0; i < 5; ++i) {userDur[i] = &dList[183+i];} // next index = 188 for(i = 0; i < 5; ++i) {userAirT[i] = &dList[188+i];} // next index = 193 for(i = 0; i < 5; ++i) {userPaveT[i] = &dList[193+i];} // next index = 198 AADT = &dList[198]; simConf = &dList[199]; for(i = 0; i < 3; ++i) {for(j = 0; j < 14; ++j){aWit[i][j] = &dList[200+i*14+j];}} // next index = 242 for(i = 0; i < 3; ++i) {for(j = 0; j < 2; ++j){bWit[i][j] = &dList[242+i*2+j];}} // next index = 248 for(i = 0; i < 10; ++i) {pTire[i] = &dList[248+i];} // next index = 258 for(i = 0; i < 10; ++i) {xSpace[i] = &dList[258+i];} // next index = 268 for(i = 0; i < 10; ++i) {ySpace[i] = &dList[268+i];} // next index = 278 for(i = 0; i < 10; ++i) {vMnDOT[i] = &dList[278+i];} // next index = 288 for(i = 0; i < 10; ++i) {vFHWA[i] = &dList[288+i];} // next index = 298 for(i = 0; i < 6; ++i) {WIMdays[i] = &dList[298+i];} // next index = 304 for(i = 0; i < 6; ++i) {for(j = 0; j < 8; ++j) {MohrWtS[i][j] = &dList[304+i*8+j];}} // next index = 352 for(i = 0; i < 6; ++i) {for(j = 0; j < 2; ++j) {CPhiAggBase[i][j] = &dList[352+i*2+j];}} // next index = 364 for(i = 0; i < 6; ++i) {for(j = 0; j < 2; ++j) {CPhiSubbase[i][j] = &dList[364+i*2+j];}} // next index = 376 MohrWt[0] = &dList[376]; MohrWt[1] = &dList[377]; MohrP[0] = &dList[378]; MohrP[1] = &dList[379]; MohrX[0] = &dList[380]; MohrX[1] = &dList[381]; for(i = 0; i < 5; ++i) {UInter[i] = &dList[382+i];} // next index = 387 for(i = 0; i < 5; ++i) {COVInter[i] = &dList[387+i];} // next index = 392 for(i = 0; i < 5; ++i) {RFInter[i] = &dList[392+i];} // next index = 397 for(i = 0; i < 5; ++i) {UOther[i] = &dList[397+i];} // next index = 402 for(i = 0; i < 3; ++i) {userA[i] = &dList[402+i];} // next index = 405 for(i = 0; i < 3; ++i) {userVTS[i] = &dList[405+i];} // next index = 408 for(i = 0; i < 3; ++i) {userKV[i] = &dList[408+i];} // next index = 411 for(i = 0; i < 4; ++i) {Gamma[i] = &dList[411+i];} // next index = 415 for(i = 0; i < 4; ++i) {Ko[i] = &dList[415+i];} // next index = 419 for(i = 0; i < 6; ++i) {FWDSIM[i] = &dList[419+i];} // next index = 425 for(i = 0; i < 10; ++i) {FWDOffset[i] = &dList[425+i];} // next index = 435 for(i = 0; i < 3; ++i) {LWDSIM[i] = &dList[435+i];} // next index = 438 for(i = 0; i < 5; ++i) {LWDmils[i] = &dList[438+i];} // next index = 443 HMAThreshold = &dList[443]; SoilThreshold = &dList[444]; Pt = &dList[445]; //AASHTO terminal serviceability for LEF EGeogrid = &dList[446]; FatMCRel = &dList[447]; RutMCRel = &dList[448]; custWt = &dList[449]; HCADT = &dList[450]; // rigid design HPCC = &dList[451]; tDistrict = &sList[0]; tCounty = &sList[1]; tCity = &sList[2]; tSP = &sList[3]; tHwy = &sList[4]; tRP1 = &sList[5]; tRP2 = &sList[6]; tConstType = &sList[7]; tDesigner = &sList[8]; tSoilsEngineer = &sList[9]; tNotes = &sList[10]; for(i = 0; i < 3; ++i) {tSpec[i] = &sList[11+i];} // next index = 14 } void mnpave::mpSettings(const QString &fileName, const int &nMode) { int i; QSettings settings; QStringList files = settings.value(RECENT_FILES_KEY).toStringList(); switch (nMode) { case READREG: { tPath = settings.value(DEFAULT_DIR_KEY).toString(); } break; case SETREG: { settings.setValue(DEFAULT_DIR_KEY, QFileInfo(fileName).absolutePath()); files.removeAll(fileName); files.prepend(fileName); while (files.size() > MaxRecentFiles) files.removeLast(); settings.setValue(RECENT_FILES_KEY, files); } break; case NOFILE: { files.removeAll(fileName); settings.setValue(RECENT_FILES_KEY, files); } break; case SETBOOL: { QString tbool = bList[2] ? "1" : "0"; //qDebug() << tbool; settings.setValue(UNITS_SI_KEY, *bsi ? "1" : "0"); // 0 units (False = English, True = SI) settings.setValue(WARN_H_KEY, bList[1] ? "1" : "0"); // 1 show thickness warnings settings.setValue(WARN_B_KEY, bList[2] ? "1" : "0"); // 2 show binder warnings settings.setValue(STRESS_ALWAYS, bList[3] ? "1" : "0"); // 3 always show allowable stress settings.setValue(STRESS_FAILED, bList[4] ? "1" : "0"); // 4 only show if failed settings.setValue(STRAIN_PERPET, bList[5] ? "1" : "0"); // 5 use all strains (false) or ignore low (true) settings.setValue(FWD_E_MEAN, bList[6] ? "1" : "0"); // 6 FWD Emean -2SD (false) or Emean (true) } case READBOOL: { *bsi = settings.value(UNITS_SI_KEY).toInt(); bList[1] = settings.value(WARN_H_KEY).toInt(); bList[2] = settings.value(WARN_B_KEY).toInt(); bList[3] = settings.value(STRESS_ALWAYS).toInt(); bList[4] = settings.value(STRESS_FAILED).toInt(); bList[5] = settings.value(STRAIN_PERPET).toInt(); bList[6] = settings.value(FWD_E_MEAN).toInt(); updateView(); } break; } // populate recent files in ui int nRecentFiles = qMin(files.size(), (int)MaxRecentFiles); for(i = 0; i < nRecentFiles; ++i) { QString text = tr("&%1 %2").arg(i + 1).arg(QFileInfo(files[i]).fileName()); pAction[i]->setText(text); pAction[i]->setData(files[i]); pAction[i]->setVisible(true); } for (i = nRecentFiles; i < MaxRecentFiles; ++i) pAction[i]->setVisible(false); } void mnpave::openRecent() { QAction *action = qobject_cast(sender()); if(action) { if(!tName.isEmpty()) { mnpave *other = new mnpave; if(other->Read(action->data().toString())) { other->resize(this->size()); other->move(this->pos() + QPoint(40,40)); other->show(); } else { other->destroy(); mpSettings(action->data().toString(), NOFILE); } } else { if(!Read(action->data().toString())) mpSettings(action->data().toString(), NOFILE); } } } void mnpave::launchTraffic(int nMode) {// nMode 0: return spectrum only; 1: launch rigid; 2: launch ESALs; 3: launch flex spec int i; TrafficDlg tdlg(this); tdlg.bsi = *bsi; tdlg.bResearch = *bResearch; tdlg.bCompound = *bCompound; tdlg.bFirstYearESAL = *bFirstYearESAL; tdlg.bFHWA = *bFHWA; tdlg.nMode = nMode; tdlg.nFlexLife = *nFlexLife; tdlg.nCustWheel = *nCustWheel; tdlg.nCustAxle = *nCustAxle; tdlg.ipct = *ipct; tdlg.esal = *esal; tdlg.esal1 = tdlg.calcESAL(false, *esal); tdlg.esalP = *pTire[ESAL]; tdlg.esalX = *xSpace[ESAL]; tdlg.HCADT = *HCADT; tdlg.custP = *pTire[CUSTOM]; tdlg.custX = *xSpace[CUSTOM]; tdlg.custY = *ySpace[CUSTOM]; tdlg.custWt = *custWt; for(i = 0; i < 2; ++i) { tdlg.mohrP[i] = *MohrP[i]; tdlg.mohrWt[i] = *MohrWt[i]; tdlg.mohrX[i] = *MohrX[i]; } for(i = 0; i < 10; ++i) { tdlg.mndot[i] = *vMnDOT[i]; tdlg.fhwa[i] = *vFHWA[i]; } tdlg.setWidgets(); tdlg.setValues(); *nRigidSpec = tdlg.calcTraffic(-1); ui->trafButton1->setText(SPECTXT[*nRigidSpec]); if(nMode < 4) { tdlg.resize(mnpave::size()); if(tdlg.exec()) { *bCompound = tdlg.bCompound; *bFirstYearESAL = tdlg.bFirstYearESAL; *bFHWA = tdlg.bFHWA; *nCustWheel = tdlg.nCustWheel; *nCustAxle = tdlg.nCustAxle; *nRigidSpec = tdlg.nRigidSpec; *esal = tdlg.esal; *pTire[ESAL] = tdlg.esalP; *xSpace[ESAL] = tdlg.esalX; *pTire[CUSTOM] = tdlg.custP; *xSpace[CUSTOM] = tdlg.custX; *ySpace[CUSTOM] = tdlg.custY; *custWt = tdlg.custWt; for(i = 0; i < 2; ++i) { *MohrP[i] = tdlg.mohrP[i]; *MohrWt[i] = tdlg.mohrWt[i]; *MohrX[i] = tdlg.mohrX[i]; } for(i = 0; i < 10; ++i) { *vMnDOT[i] = tdlg.mndot[i]; *vFHWA[i] = tdlg.fhwa[i]; } bmodified = true; } } } void mnpave::resizeEvent(QResizeEvent *e) {// proportional widget resizing int ew = e->size().width(); // MainWindow int eh = e->size().height(); int i, nw, nh; double ht; if(ew >= eh) { // Landscape nw = LANDW; nh = LANDH; wRect[61] = QRect(428,10,208,47); // mptextFrame wRect[62] = QRect(428,200,208,200); // outGroup } else { // Portrait nw = PORTW; nh = PORTH; wRect[61] = QRect(4,406,208,47); // relocate mptextFrame wRect[62] = QRect(216,406,208,200); // relocate outGroup } for(i = 0; i < 64; ++i) // resize widgets pW[i]->setGeometry(wRect[i].x()*ew/nw, wRect[i].y()*eh/nh, wRect[i].width()*ew/nw, wRect[i].height()*eh/nh); // test height/width ratio if((double) eh / (double) ew < 0.75) ht = (double) ew * 0.75 / (double) nw * 8.; // new font size else ht = (double) eh / (double) nh * 8.; // new font size eh = nint(ht); QFont newFont = ui->projLabel->font(); if(eh != newFont.pointSize()) { newFont.setPointSize(eh); QApplication::setFont(newFont); for(i = 0; i < 5; ++i) pButton[i]->setFont(newFont); } QMainWindow::resizeEvent(e); } void mnpave::paintEvent(QPaintEvent *) { QFont fontmn(mnpave::font().family(), mnpave::font().pointSize(), QFont::Bold); QImage mptxt(*bResearch ? ":/images/mptxtRM.png" : ":/images/mptxt.png"); QImage mn(":/images/mn72.png"); QPainter painter(this); QPen pen, penmn; tVersion = QString::number(VERSION-RIGADJ); tVersion.insert(1,'.'); pen.setBrush(Qt::black); pen.setWidth(1); penmn.setBrush(MNBLUE); // MnDOT blue penmn.setWidth(1); painter.setPen(pen); painter.setBrush(Qt::white); // adjust rectangle to fit inside frame QPoint mb(ui->menuBar->rect().bottomRight()); QPoint tb(ui->mainToolBar->rect().bottomRight()); int gx = ui->mptxtFrame->x(); int gy = ui->mptxtFrame->y(); int gw = ui->mptxtFrame->width(); int gh = ui->mptxtFrame->height(); int sp = mnpave::font().pointSize(); gy += mb.y() + tb.y(); painter.drawImage(gx,gy,mptxt.scaled(gw, gh, Qt::KeepAspectRatio)); gy += gh; gh = 2*sp; QRect sr(gx, gy, gw, gh); painter.setFont(fontmn); painter.drawText(sr, tr("MnDOT %1 Pavement Design").arg(PAVETXT[PAVEMENT])); gy += gh; sr = QRect(gx, gy, gw, gh); painter.setFont(mnpave::font()); painter.drawText(sr, tr(BETA ? "Beta Version %1, %2 %3" : "Version %1, %2 %3") .arg(BETA ? tVersion: tVersion.left(3), QDate::longMonthName(MONTH), QString::number(YEAR))); gy += gh; sr = QRect(gx, gy, gw, gh); painter.drawText(sr, tr("%1 2001-%2").arg(COPYRIGHT, QString::number(YEAR))); gy += sp*7/3; painter.drawImage(gx,gy,mn.scaled(sp*6, sp*3, Qt::KeepAspectRatio)); gx += sp*7; gy -= sp/2; sr = QRect(gx, gy, sp*18, gh*2); // control text wrapping painter.setFont(fontmn); painter.setPen(penmn); painter.drawText(sr, tr("Department of Transportation")); } void mnpave::closeEvent(QCloseEvent *event) { if(bmodified) { if(askSave()) { mpSettings("", SETBOOL); event->accept(); } else event->ignore(); } else { mpSettings("", SETBOOL); event->accept(); } } void mnpave::ctrlkey(int nkey) { QWidget* focused = QApplication::focusWidget(); if( focused != 0 ) { QApplication::postEvent( focused, new QKeyEvent( QEvent::KeyPress, nkey, Qt::ControlModifier )); } } void mnpave::updateView() { // This will show and hide widgets updateMenu(); updateInfo(); updateClimate(); updateTraffic(); updateStruc(); updateOutput(); } void mnpave::updateMenu() { ui->actionEnglish->setChecked(!*bsi); ui->actionSI->setChecked(*bsi); ui->actionShow_Thickness_Warnings->setChecked(*bHWarn); ui->actionShow_Binder_Warnings->setChecked((bBWarn)); ui->actionAlways_Show_Allowable_Stress->setChecked(*bMohrAlways); ui->actionShow_Allowable_Stress_if_Failed->setChecked(*bMohrFail); ui->actionDesign->setChecked(!*bResearch); ui->actionResearch->setChecked(*bResearch); ui->actionESAL->setChecked(!*bSpectrum); ui->actionSpectrum->setChecked(*bSpectrum); ui->actionUse_All_Strains->setChecked(!*bPerpetual); ui->actionPerpetual_Mode->setChecked(*bPerpetual); } void mnpave::updateInfo() { ui->constCombo->setCurrentIndex(*nConstType); switch(*nConstType) { case FLEXIBLE: // HMA { ui->lifeEdit->setText(QString::number(*nFlexLife)); } break; case RIGID: // PCC { ui->lifeEdit->setText(QString::number(*nRigidLife)); } break; } ui->projEdit->setText(*tSP); ui->dateEdit->setDate(vList[0].toDate()); ui->routeEdit->setText(*tHwy); ui->rp1Edit->setText(*tRP1); ui->rp2Edit->setText(*tRP2); ui->distCombo->setCurrentIndex(nDistrict); ui->coCombo->setCurrentIndex(loadCoCombo(nDistrict, nCounty)); ui->desEdit->setText(*tDesigner); ui->senEdit->setText(*tSoilsEngineer); } void mnpave::updateClimate() { MapDlg mapd; if(*nConstType == FLEXIBLE && *nSoil >= 0 && *nSoil <= 14) { QString ts = mapd.tSoilClass[*nSoil]; if(*nSoil == 3) { ts.remove("ightly"); ts.remove("astic"); } ui->layerButton4->setText(ts); ui->layerButton5->setText(mapd.tSoilClass[*nSoil]); } } void mnpave::updateTraffic() { if(!*bResearch) { *bCompound = false; *bSpectrum = false; *nCustWheel = 2; //dual tire *nCustAxle = 0; // ESAL } ui->trafEdit2->setText(txtdbl(*ipct,1)); // growth rate ui->trafCombo3->setItemText(0,*bsi ? "3.7" : "12"); ui->trafCombo3->setItemText(1,*bsi ? "4.6" : "15"); ui->trafLabel5u->setText(txtll(*bsi)); switch(*nConstType) { case FLEXIBLE: // HMA { ui->trafEdit1->setEnabled(true); ui->trafEdit2->setEnabled(true); ui->trafLabel3->setVisible(false); ui->trafLabel4->setVisible(false); ui->trafLabel5->setVisible(false); ui->trafLabel5u->setVisible(false); ui->trafCombo1->setVisible(false); ui->trafCombo2->setVisible(false); ui->trafCombo3->setVisible(false); ui->axleButton->setVisible(true); ui->axleButton->setText(*bSpectrum ? tr("Load Spectrum") : *nCustAxle == 0 ? tr("ESAL Details") : tr("Axle Details")); ui->trafCheck1->setVisible(false); ui->trafCheck2->setVisible(false); ui->trafLabel1->setText(*nCustAxle == 0 ? tr("Design ESALs") : tr("Repetitions")); ui->trafLabel1u->setText("million"); if(*esal == 0) ui->trafEdit1->setText(""); else ui->trafEdit1->setText(txtdbl(*esal,3,false,true)); // ESAL ui->trafButton1->setVisible(false); // may not be needed //ui->trafEdit2->setText(QString::number(*nFlexLife)); // life } break; case RIGID: // PCC { ui->trafEdit1->setEnabled(true); ui->trafEdit2->setEnabled(true); ui->trafLabel3->setVisible(true); ui->trafLabel4->setVisible(true); ui->trafLabel5->setVisible(true); ui->trafLabel5u->setVisible(true); ui->trafCombo1->setVisible(true); ui->trafCombo2->setVisible(*bResearch); ui->trafCombo3->setVisible(true); ui->axleButton->setVisible(!*bResearch); ui->trafCombo2->setCurrentIndex(*nRigidSpec); ui->axleButton->setText(ui->trafCombo2->currentText()); ui->trafCheck1->setVisible(true); ui->trafCheck2->setVisible(true); ui->trafLabel1->setText("HCADT"); ui->trafLabel1u->setText(""); if(*HCADT == 0) ui->trafEdit1->setText(""); else ui->trafEdit1->setText(txtdbl(*HCADT,3,false,true)); // HCADT ui->trafCombo1->setCurrentIndex(*nLanes); // axle load spectra ui->trafCombo2->setCurrentIndex(*nRigidSpec); // axle load spectra ui->trafCombo3->setCurrentIndex(*nJoint); // joint spacing ui->trafCheck1->setChecked(*bWidened); // widened outer lane ui->trafCheck2->setChecked(*bTied); // tied PCC shoulder ui->trafButton1->setVisible(false); // may not be needed calcRigid(false); } break; case 2: // nothing { ui->trafLabel1->setText(""); ui->trafLabel1u->setText(""); ui->trafEdit1->setText(""); ui->trafEdit2->setText(""); // ui->trafEdit3->setText(""); ui->trafEdit1->setEnabled(false); ui->trafEdit2->setEnabled(false); // ui->trafEdit3->setEnabled(false); ui->trafLabel4->setVisible(false); ui->trafLabel5->setVisible(false); ui->trafLabel5u->setVisible(false); ui->trafCombo2->setVisible(false); ui->trafCombo3->setVisible(false); ui->trafCheck1->setVisible(false); ui->trafCheck2->setVisible(false); } break; } } void mnpave::updateStruc() { calc c; //enable special functions in calc bspin = false; // only check increment for user input bool bhma = *nConstType == FLEXIBLE; // true if flexible bool bmulti; int i, j; double min, max, incr, htot; ui->strucLabel2->setText(txtl(*bsi)); pButton[1]->setStyleSheet(c.getPBColor(NYELLOW, 4)); pButton[2]->setStyleSheet(c.getPBColor(NRED, 4)); pButton[3]->setStyleSheet(c.getPBColor(NCYAN, 4)); pButton[4]->setStyleSheet(c.getPBColor(NCYAN, 2)); switch(*nConstType) { case FLEXIBLE: // HMA { ui->strucCombo1->setVisible(true); ui->strucButton1->setVisible(true); ui->strucCombo1->setCurrentIndex(*nFlexLayer-1); pSpin[0]->setVisible(true); ui->layerEdit1->setVisible(false); pButton[0]->setText("PG 58-34"); // Button text will be automated later pButton[0]->setStyleSheet(c.getPBColor(NGRAY, 1)); pButton[0]->setEnabled(true); pButton[1]->setVisible(true); ui->layerCombo2->setVisible(false); pButton[2]->setEnabled(true); pButton[3]->setEnabled(true); for(i = 1; i < 4; ++i) { if(i < *nFlexLayer) { pButton[i+1]->setVisible(true); pSpin[i]->setVisible(true); } else { pButton[i+1]->setVisible(false); pSpin[i]->setVisible(false); } } if(nHlab == 2) // COV { for(i = 0; i < 4; ++i) { pSpin[i]->setDecimals(0); pSpin[i]->setValue(rnd2dec(*HCOV[i],0)); pSpin[i]->setMinimum(COV_MIN); pSpin[i]->setMaximum(COV_MAX); pSpin[i]->setSingleStep(1); pSpin[i]->setReadOnly(false); } } else // H or adj H { calc c; for(i = 0; i < 4; ++i) { pButton[i]->setEnabled(true); if(i == 0) // HMA { min = rnd2dec(convl(false,H_MIN_IN1,*bsi),0); max = rnd2dec(convl(false,H_MAX_IN1,*bsi),0); incr = *bsi ? INCR_MM1 : INCR_IN1; } else { min = rnd2dec(convl(false,H_MIN_IN,*bsi),0); max = rnd2dec(convl(false,H_MAX_IN,*bsi),0); incr = *bsi ? INCR_MM : INCR_IN; } htot = 0; for(j = 0; j < 3; ++j) // sublayers { htot += *H[i][j]; } bmulti = htot > *H[i][0]; if(nHlab == 1) // adjusted { htot = c.ConfidenceValue(htot,*HCOV[i],*simConf,false); } pSpin[i]->setDecimals(decl(*bsi)); pSpin[i]->setMinimum(min); pSpin[i]->setMaximum(max); pSpin[i]->setSingleStep(incr); pSpin[i]->setValue(rnd2dec(convl(false,htot,*bsi),decl(*bsi))); pSpin[i]->setReadOnly(bmulti || nHlab == 1); } } } break; case RIGID: // PCC { ui->strucCombo1->setCurrentIndex(*nRigidLayer-1); for(i = 1; i < 4; ++i) { if(i < *nRigidLayer) { pButton[i+1]->setVisible(true); pSpin[i]->setVisible(true); } else { pButton[i+1]->setVisible(false); pSpin[i]->setVisible(false); } } pButton[0]->setText("PCC"); ui->strucCombo1->setCurrentIndex(3); for(i = 0; i < 4; ++i) { pSpin[i]->setDecimals(*bsi ? 0 : 1); pSpin[i]->setMinimum(0); pSpin[i]->setMaximum(rnd2dec(convl(false,H_MAX_IN,*bsi),0)); pSpin[i]->setSingleStep(*bsi ? INCR_MM : INCR_IN); } ui->strucCombo1->setVisible(false); ui->strucButton1->setVisible(false); nHlab = 0; // thickness only pButton[0]->setEnabled(false); pSpin[0]->setVisible(false); ui->layerEdit1->setVisible(true); pButton[1]->setVisible(false); ui->layerCombo2->setVisible(true); ui->layerCombo2->setEditable(true); ui->layerCombo2->lineEdit()->setAlignment(Qt::AlignHCenter); ui->layerCombo2->lineEdit()->setReadOnly(true); ui->layerCombo2->setCurrentIndex(*nRigidBase); pButton[2]->setEnabled(false); pButton[3]->setEnabled(false); pButton[0]->setStyleSheet(c.getPBColor(NGRAY, 7, true));; //pSpin[0]->setValue(rnd2dec(convl(false,*HPCC,*bsi),decl(*bsi,false))); switch(*nRigidHBase) { case 0: { pSpin[1]->setValue(*bsi ? 100.0 : 4.0); // mm or in. pSpin[2]->setValue(*bsi ? 300.0 : 12.0); // mm or in. } break; case 1: { pSpin[1]->setValue(*bsi ? 300.0 : 12.0); // mm or in. pSpin[2]->setValue(*bsi ? 100.0 : 4.0); // mm or in. } break; } pSpin[2]->setReadOnly(false); ui->layerSpin4->setVisible(false); ui->layerButton5->setVisible(false); //pSpin[3]->setReadOnly(true); } break; case 2: // nothing { } break; } switch(nHlab) // thickness output selection { case 0: // Thickness { } break; case 1: // Adjusted { } break; case 2: // COV { } break; default: { } break; } bspin = true; } void mnpave::updateOutput() { } void mnpave::loadW() {// pointers to all widgets for resizing pW[0] = ui->infoGroup; pW[1] = ui->constCombo; pW[2] = ui->lifeLabel; pW[3] = ui->lifeEdit; pW[4] = ui->lifeLabelu; pW[5] = ui->projLabel; pW[6] = ui->dateLabel; pW[7] = ui->projEdit; pW[8] = ui->dateEdit; pW[9] = ui->routeLabel; pW[10] = ui->routeEdit; pW[11] = ui->rpLabel; pW[12] = ui->rp1Edit; pW[13] = ui->toLabel; pW[14] = ui->rp2Edit; pW[15] = ui->distLabel; pW[16] = ui->coLabel; pW[17] = ui->distCombo; pW[18] = ui->coCombo; pW[19] = ui->mapButton; pW[20] = ui->climateButton; pW[21] = ui->desLabel; pW[22] = ui->desEdit; pW[23] = ui->senLabel; pW[24] = ui->senEdit; pW[25] = ui->notesButton; pW[26] = ui->trafGroup; pW[27] = ui->trafLabel1; pW[28] = ui->trafEdit1; pW[29] = ui->trafLabel1u; pW[30] = ui->trafLabel2; pW[31] = ui->trafEdit2; pW[32] = ui->trafLabel2u; pW[33] = ui->trafLabel3; pW[34] = ui->trafCombo1; pW[35] = ui->trafLabel4; pW[36] = ui->trafCombo2; pW[37] = ui->axleButton; pW[38] = ui->trafLabel5; pW[39] = ui->trafCombo3; pW[40] = ui->trafLabel5u; pW[41] = ui->trafCheck1; pW[42] = ui->trafCheck2; pW[43] = ui->trafButton1; pW[44] = ui->strucGroup; pW[45] = ui->strucCombo1; pW[46] = ui->strucButton1; pW[47] = ui->StrucHLabel; pW[48] = ui->strucLabel1; pW[49] = ui->strucLabel2; pW[50] = ui->layerButton1; pW[51] = ui->layerSpin1; pW[52] = ui->layerEdit1; pW[53] = ui->layerButton2; pW[54] = ui->layerCombo2; pW[55] = ui->layerSpin2; pW[56] = ui->layerButton3; pW[57] = ui->layerSpin3; pW[58] = ui->layerButton4; pW[59] = ui->layerSpin4; pW[60] = ui->layerButton5; pW[61] = ui->mptxtFrame; pW[62] = ui->outGroup; pW[63] = ui->calcButton; // geometries wRect[0] = QRect(4,4,208,396); wRect[1] = QRect(9,18,190,22); wRect[2] = QRect(10,46,70,20); wRect[3] = QRect(86,46,54,20); wRect[4] = QRect(146,46,52,20); wRect[5] = QRect(10,69,100,16); wRect[6] = QRect(120,69,78,16); wRect[7] = QRect(8,88,104,20); wRect[8] = QRect(118,88,82,20); wRect[9] = QRect(10,114,60,20); wRect[10] = QRect(76,114,124,20); wRect[11] = QRect(10,140,188,16); wRect[12] = QRect(8,159,80,20); wRect[13] = QRect(94,159,20,20); wRect[14] = QRect(120,159,80,20); wRect[15] = QRect(10,185,56,16); wRect[16] = QRect(76,185,116,16); wRect[17] = QRect(9,208,60,22); wRect[18] = QRect(75,208,118,22); wRect[19] = QRect(8,240,72,24); wRect[20] = QRect(86,240,108,24); wRect[21] = QRect(10,272,188,16); wRect[22] = QRect(8,291,192,20); wRect[23] = QRect(10,317,188,16); wRect[24] = QRect(8,336,192,20); wRect[25] = QRect(8,364,192,24); wRect[26] = QRect(216,4,208,190); wRect[27] = QRect(10,18,80,20); wRect[28] = QRect(96,18,54,20); wRect[29] = QRect(156,18,42,20); wRect[30] = QRect(10,42,80,20); wRect[31] = QRect(96,42,54,20); wRect[32] = QRect(156,42,42,20); wRect[33] = QRect(10,66,142,22); wRect[34] = QRect(158,66,40,22); wRect[35] = QRect(10,92,64,22); wRect[36] = QRect(80,92,118,22); wRect[37] = QRect(80,92,114,22); wRect[38] = QRect(10,118,84,22); wRect[39] = QRect(100,118,46,22); wRect[40] = QRect(152,118,46,22); wRect[41] = QRect(10,144,124,16); wRect[42] = QRect(10,166,124,16); wRect[43] = QRect(140,142,60,40); wRect[44] = QRect(216,200,208,200); wRect[45] = QRect(10,18,100,22); wRect[46] = QRect(116,18,84,24); wRect[47] = QRect(130,22,60,16); wRect[48] = QRect(12,46,120,16); wRect[49] = QRect(142,46,52,16); wRect[50] = QRect(10,64,124,24); wRect[51] = QRect(140,64,58,24); wRect[52] = QRect(140,64,42,24); wRect[53] = QRect(10,90,124,24); wRect[54] = QRect(10,90,124,24); wRect[55] = QRect(140,90,58,24); wRect[56] = QRect(10,116,124,24); wRect[57] = QRect(140,116,58,24); wRect[58] = QRect(10,142,124,24); wRect[59] = QRect(140,142,58,24); wRect[60] = QRect(10,168,124,24); wRect[61] = QRect(428,10,208,47); wRect[62] = QRect(428,200,208,200); wRect[63] = QRect(10,20,120,40); } void mnpave::calcRigid(bool bmsg) { QString ttmp = checkRigidData(); if(ttmp != "") { *HPCC = 0.0; ui->layerEdit1->setText(*bsi ? "0" : "0.0"); if(bmsg) { QMessageBox msg; msg.setText(ttmp); msg.exec(); } return; } calc c; int i; QString ss, tmsg; TrafficDlg traf; int rign[7]; //index values to query data double rigd[4]; if(nDistrict < 6) rign[0] = nDistrict; // climate = district else rign[0] = 6; // Dist 7 & 8 have RDF climate if(*nRigidSpec == 2) rign[1] = 0; // MEPDG else rign[1] = *nRigidSpec + 1; // load spectrum rign[2] = *bWidened ? 1 : 0; // widened outside lane rign[3] = *nJoint; // joint spacing (0=12, 1=15) rign[4] = *bTied ? 1 : 0; // tied PCC shoulders rign[5] = *nRigidBase; // Base rign[6] = *nRigidHBase; // HBase double mdtmp[9]; // array to pass into adjHCADT for(i = 0; i < 9; ++i) mdtmp[i] = *vMnDOT[i]; HCADTadj = traf.adjHCADT(mdtmp, *HCADT); rigd[0] = *HCADT * HCADTadj; // hcadt, adjusted if necessary rigd[1] = desLane(*nLanes); // percent traffic in design lane rigd[2] = (double) *nRigidLife; // deslife rigd[3] = *ipct; // growth; *HPCC = c.calcRigid(rign, rigd, &trucks, &reliability, &cracked); // need trucks for MnPAVE-Rigid Design Summary //pSpin[0]->setValue(rnd2dec(convl(false,*HPCC,*bsi),decl(*bsi,false))); if(HCADTadj > 1.0) { ui->axleButton->setText(SPECTXT[2] + "*"); ui->axleButton->setToolTip(tr("Effective HCADT = HCADT * %1 due to 5+ Axle Max vehicles.").arg(txtdbl(HCADTadj,3))); } else { ui->axleButton->setText(SPECTXT[*nRigidSpec]); ui->axleButton->setToolTip(""); } ui->layerEdit1->setText(txtdbl(convl(false,*HPCC,*bsi),decl(*bsi,false))); } bool mnpave::Open() { QString tOpenFile = QFileDialog::getOpenFileName(this, tr("Open %1 File").arg(APP), tPath, tr("%1 Files (*.%2)").arg(APP).arg(APPEXT)); if (tOpenFile.isEmpty()) return false; else return Read(tOpenFile); } bool mnpave::askSave() { QMessageBox::StandardButton ret; ret = QMessageBox::warning(this, QApplication::applicationName(), tr("The document has been modified.") + "\n" + tr("Do you want to save your changes?"), QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); if(ret == QMessageBox::Yes) return Save(tFile); else if(ret == QMessageBox::Cancel) return false; else return true; } bool mnpave::Save(const QString &fileName) { if(!fileName.isEmpty()) return Write(fileName); else return SaveAs(fileName); } bool mnpave::SaveAs(const QString &fileName) { mpSettings("", READREG); QString newName = fileName; if(newName.isEmpty()) newName = tName; if(newName.isEmpty()) newName = sList[0].isEmpty() ? QApplication::applicationName() + "1" : sList[0]; newName = QFileDialog::getSaveFileName(this, tr("Save %1 File").arg(APP), tPath + "/" + newName, tr("%1 Files (*.%2)").arg(APP).arg(APPEXT)); if(!newName.isEmpty()) return Write(newName); else return false; } bool mnpave::Write(const QString &fileName) { QSaveFile mFile(fileName); mFile.setFileName(fileName); mFile.setDirectWriteFallback(true); if(!mFile.open(QFile::WriteOnly)) { QMessageBox msgBox; msgBox.setText(tr("File could not be saved.")); msgBox.exec(); return false; } QDataStream out(&mFile); // Keep datastream version consistent to prevent Read errors when Qt is updated out.setVersion(QDataStream::Qt_5_7); // this is consistent with the static version (5.7.1) // Create header with verification number and version number out << qint32(0xb0071ace); out << nVersion; out << bList; // QList of bool out << iList; // QList of int out << dList; // QList of double out << sList; // QList of QString out << vList; // QList of QVariant bool bcom = mFile.commit(); if(bcom) { QFileInfo mInfo(fileName); tName = mInfo.fileName(); tFile = fileName; updateView(); bmodified = false; mpSettings(fileName, SETREG); mnpave::setWindowTitle(newWinTitle(tName)); } return bcom; } bool mnpave::Read(const QString &fileName) {// To do: update window title int i; int n = 0; QMessageBox msg; bopen = false; QFile mFile(fileName); if(!mFile.open(QFile::ReadOnly)) { msg.setText(tr("File not found.")); msg.exec(); return false; } QDataStream in(&mFile); // Verify header information qint32 verify, version; in >> verify; if(verify == 0xb0071ace) { // Get Qt version int qver = in.version(); // binary serialization version in >> version; if(version > nVersion) { QMessageBox msgBox; msgBox.setTextFormat(Qt::RichText); msgBox.setText(tr("This file is from a newer version of mnpave." "
Please update to the current version at" "
" "www.dot.state.mn.us/app/mnpave")); msgBox.exec(); return false; } if(version < nVersion) {// or if(version < 7000), if(version >= 7009)... // update values if necessary } in >> bList; // QList of bool in >> iList; // QList of int in >> dList; // QList of double in >> sList; // QList of QString in >> vList; // QList of QVariant mFile.close(); assignPointers(); // pointers need to be reassigned after import } else { mFile.close(); QFile txtFile(fileName); txtFile.open(QIODevice::ReadOnly); QXmlStreamReader xml(&txtFile); xml.readNext(); i = 0; while(xml.name() != "verify" && i < 10) { i += 1; xml.readNext(); } verify = xml.readElementText().toInt(); if(verify == 0x0B501E7E) {// text file exported from MnPAVE 6.4 while(xml.name() != "bList") xml.readNext(); foreach(const QXmlStreamAttribute &attr, xml.attributes()) { if(attr.name().toString() == QLatin1String("size")) {//note: QLatin1String is needed because the above const does not accept unicode. n = attr.value().toInt(); // number of elements } } // qDebug() << QString::number(n); for(i = 0; i < n; ++i) { xml.readNextStartElement(); bList[i] = xml.readElementText().toInt(); } // xml code completed to here in MnPAVE 6.4 while(xml.name() != "iList") xml.readNext(); foreach(const QXmlStreamAttribute &attr, xml.attributes()) { if(attr.name().toString() == QLatin1String("size")) {//note: QLatin1String is needed because the above const does not accept unicode. n = attr.value().toInt(); // number of elements } } for(i = 0; i < n; ++i) { xml.readNextStartElement(); iList[i] = xml.readElementText().toInt(); } while(xml.name() != "dList") xml.readNext(); foreach(const QXmlStreamAttribute &attr, xml.attributes()) { if(attr.name().toString() == QLatin1String("size")) {//note: QLatin1String is needed because the above const does not accept unicode. n = attr.value().toInt(); // number of elements } } for(i = 0; i < n; ++i) { xml.readNextStartElement(); dList[i] = xml.readElementText().toDouble(); } while(xml.name() != "sList") xml.readNext(); foreach(const QXmlStreamAttribute &attr, xml.attributes()) { if(attr.name().toString() == QLatin1String("size")) {//note: QLatin1String is needed because the above const does not accept unicode. n = attr.value().toInt(); // number of elements } } for(i = 0; i < n; ++i) { xml.readNextStartElement(); sList[i] = xml.readElementText(); } while(xml.name() != "vList") xml.readNext(); foreach(const QXmlStreamAttribute &attr, xml.attributes()) { if(attr.name().toString() == QLatin1String("size")) {//note: QLatin1String is needed because the above const does not accept unicode. n = attr.value().toInt(); // number of elements } } int ntmp[n]; for(i = 0; i < n; ++i) { xml.readNextStartElement(); ntmp[i] = xml.readElementText().toDouble(); } vList[0] = QDate(ntmp[0], ntmp[1], ntmp[2]); vList[1] = QPointF(ntmp[5] + ntmp[6]/60., ntmp[3] + ntmp[4]/60.); if (xml.hasError()) { QMessageBox msgBox; msgBox.setText(tr("xml error")); msgBox.exec(); return false; } // Convert Custom Axle info if(*nCustAxle > 3) { *nCustAxle -= 3; *nCustWheel = 1; // custom axles 4-6 were super single, tandem & tridem } else *nCustWheel = 2; // dual tire *custWt *= EN3; // convert from lbs to kips if(*custWt == 0.) *custWt = 18.; // Import MnDOT vehicles into new format *vMnDOT[4] += *vMnDOT[5]; // old Classes 8 & 9 (5 & 6 axle semis) are now combined *vMnDOT[8] = *vMnDOT[7]; // Classes 10 & 11 are shifted to make room for new 9a & 9b *vMnDOT[7] = *vMnDOT[6]; *vMnDOT[5] = *vMnDOT[6] = 0.0; // new Classes 9a & 9b (5+ Max & 5+ Other) tName = QFileInfo(fileName).fileName(); QMessageBox msgBox; msgBox.setText(tr("File imported successfully.")); msgBox.exec(); txtFile.close(); *nConstType = 0; // Flexible (Asphalt) bxml = true; } else { QMessageBox msgBox; msgBox.setText(tr("Incorrect file format.%1Code %2").arg("\n").arg(QString::number(verify))); msgBox.exec(); txtFile.close(); return false; } } QFileInfo mInfo(fileName); tName = mInfo.fileName(); tFile = fileName; bopen = true; MapDlg mapd; QPoint xy = mapd.ll2xy(vList[1].toPointF()); nDistrict = mapd.getDistrictIndex(MASKD.pixel(xy)); nCounty = mapd.getCountyIndex(MASKC.pixel(xy)); updateView(); if(*nConstType == RIGID) { //pButton[1]->setText(RBASE[*nRigidBase]); ui->layerCombo2->setCurrentIndex(*nRigidBase); calcRigid(false); } bmodified = bxml; // prompt to save if xml was imported bxml = false; mpSettings(fileName, SETREG); mnpave::setWindowTitle(newWinTitle(tName)); return true; } QString mnpave::newWinTitle(const QString &tTitle) { // QString ttmp = QApplication::applicationName() + " " + txtdbl((double) nint((double) (nVersion*.01))*.1, 1); QString ttmp = APPTITLE + " " + PAVETXT[PAVEMENT] + " " + txtdbl((double) (VERSION-RIGADJ)*EN3,1); if(!tTitle.isEmpty()) { ttmp = ttmp + " - " + tTitle; } return ttmp; } int mnpave::loadCoCombo(int ndist, int nco) { int i, i87, imax; int i20 = -1; // indicates if a new index isn't assigned // fill county combo ui->coCombo->clear(); MapDlg mnmap; if(ndist == 8) // no district selected { for(i = 0; i < 87; ++i) { ui->coCombo->addItem(mnmap.getCountyName(i)); } return nco; } else { for(i = 0; i < 20; ++i) { i87 = mnmap.getCounty(ndist, i); if(i87 >= 0) { imax = i; ui->coCombo->addItem(mnmap.getCountyName(i87)); } // get CurSel if(i87 == nco) i20 = i; // new index of the county already selected } if(i20 < 0) i20 = imax+1; // select blank selection if selected county isn't in the new district } return i20; } double mnpave::desLane(int nLanes) { double pctTrucks[] = {100.,90.,70.,60.}; return pctTrucks[nLanes]; } QString mnpave::checkRigidData() { QString tmsg = ""; if(*nRigidLife <= 0) tmsg = ("Enter a value for Design Life.\n"); if(nDistrict < 0 || nDistrict > 7) tmsg += tr("Select a District.\n"); if(*HCADT <= 0.) tmsg += ("Enter a value for HCADT."); return tmsg; } // Private Slots void mnpave::on_actionCreate_PDF_Report_triggered() { // font: 72 pts/in; pdf: 1200 pixels/in QString ttmp = checkRigidData(); if(ttmp != "") { QMessageBox msg; msg.setText(ttmp); msg.exec(); return; } else calcRigid(false); if(tName.isEmpty()) on_actionSave_triggered(); mpSettings("", READREG); ttmp = tName.left(tName.length()-4); QString newName = ttmp + tr(" Report.pdf"); // Use file dialog to prompt if file exists already if(tName.isEmpty()) newName = QApplication::applicationName() + QApplication::applicationVersion() + " Report"; newName = QFileDialog::getSaveFileName(this, tr("Save") + " PDF " + tr("Report"), tPath + "/" + newName, "PDF " + tr("Files") + " (*.pdf)"); if(!newName.isEmpty()) { QPdfWriter mpdf(newName); mpdf.setPageSize(QPagedPaintDevice::Letter); mpdf.setPageMargins(QMarginsF(72,54,54,54)); // L 1", R,T,B 0.75" mpdf.setTitle(newWinTitle("") + " " + tr("Report")); mpdf.newPage(); QDateTime now; QPainter painter(&mpdf); QFont arial6("Arial"); //disclaimer arial6.setPointSize(6); QFont arial10("Arial"); arial10.setPointSize(10); QFont arial14("Arial"); arial14.setPointSize(14); QFont arial14B("Arial"); arial14B.setPointSize(14); arial14B.setBold(true); QFont arial16("Arial"); arial16.setPointSize(16); QFont arial16B("Arial"); arial16B.setPointSize(16); arial16B.setBold(true); QFont arial18("Arial"); arial18.setPointSize(18); arial18.setBold(true); QTextOption tleft, tcenter, tright; tleft.setAlignment(Qt::AlignLeft); tcenter.setAlignment(Qt::AlignCenter); tright.setAlignment(Qt::AlignRight); QPen pen; pen.setBrush(Qt::black); pen.setWidth(8); painter.setPen(pen); QPoint pt1, pt2; QRect txrect; int top, bot, wid, ht, h10, h14, h16, h18; top = 0; //wid = 8400; // 7" wid = 7800; // 6.5" ht = 11400; // 9.5" h10 = 200; // row height h14 = 300; h16 = 400; h18 = 500; top = pdfRect(&txrect,wid,top,h18,1,0); QImage mdlogo(":/images/mndotLogo.png"); painter.drawImage(txrect.topLeft(),mdlogo.scaled(txrect.width(), txrect.height(), Qt::KeepAspectRatio)); top += h10; painter.setFont(arial14B); bot = pdfRect(&txrect,wid,top,h16,1,0); // "bot" keeps the next section on the same line ttmp = tr("%1 %2 %3 Design Summary").arg(APPTITLE, PAVETXT[PAVEMENT], txtdbl((double) (VERSION-RIGADJ)*EN3,1)); painter.drawText(txrect,ttmp,tleft); painter.setFont(arial10); ttmp = tr("Created %1").arg(now.currentDateTime().toLocalTime().toString(Qt::SystemLocaleShortDate)); top = pdfRect(&txrect,wid,top,h16,3,2); // "top" advances the next section to a new line painter.drawText(txrect,ttmp,tright); top = pdfRect(&txrect,wid,top,h16,1,0); pt1 = QPoint(txrect.left(), txrect.top()+h16/2); // center vertically ttmp = tr("%1 %2 File%3").arg(APPTITLE, PAVETXT[PAVEMENT], ": "); // put punctuation & spaces outside of translation to avoid errors pt1 = mpText(&painter,arial14B,pt1,ttmp); pt1 = mpText(&painter,arial14,pt1,tName); top = pdfRect(&txrect,wid,top,h18,1,0); pt1 = QPoint(txrect.left(), txrect.top()+h18/2); // center vertically ttmp = tr("Calculated thickness%1").arg(": "); pt1 = mpText(&painter,arial14B,pt1,ttmp); ttmp = QString("%1 %2").arg(ui->layerEdit1->text(), txtl(*bsi)); pt1 = mpText(&painter,arial16,pt1,ttmp); painter.setFont(arial16B); top = pdfRect(&txrect,wid,top,h18,1,0); painter.drawText(txrect,"Main Inputs",tleft); painter.drawLine(txrect.topLeft(), txrect.topRight()); painter.setFont(arial14); bot = pdfRect(&txrect,wid,top,h16,9,40); // 9 columns, merge 1-5 pt1 = QPoint(txrect.left(), txrect.top()+h16/2); // center vertically ttmp = tr("Design life%1").arg(": "); pt1 = mpText(&painter,arial14B,pt1,ttmp); ttmp = tr("%1 years").arg(QString::number(*nRigidLife)); pt1 = mpText(&painter,arial14,pt1,ttmp); top = pdfRect(&txrect,wid,top,h16,9,85); // 9 columns, merge 6-9 pt1 = QPoint(txrect.left(), txrect.top()+h16/2); // center vertically ttmp = tr("Climate (MnDOT district)%1").arg(": "); pt1 = mpText(&painter,arial14B,pt1,ttmp); pt1 = mpText(&painter,arial14,pt1,DISTRICT[ui->distCombo->currentIndex()]); bot = pdfRect(&txrect,wid,top,h16,9,40); pt1 = QPoint(txrect.left(), txrect.top()+h16/2); // center vertically ttmp = tr("Initial 2-way traffic%1").arg(": "); pt1 = mpText(&painter,arial14B,pt1,ttmp); ttmp = tr("%1 HCADT%2").arg(txtdbl(*HCADT,0), HCADTadj > 1.0 ? "*" : ""); pt1 = mpText(&painter,arial14,pt1,ttmp); top = pdfRect(&txrect,wid,top,h16,9,85); pt1 = QPoint(txrect.left(), txrect.top()+h16/2); // center vertically ttmp = tr("Linear traffic growth%1").arg(": "); pt1 = mpText(&painter,arial14B,pt1,ttmp); pt1 = mpText(&painter,arial14,pt1,txtdbl(*ipct,1)); bot = pdfRect(&txrect,wid,top,h16,9,40); pt1 = QPoint(txrect.left(), txrect.top()+h16/2); ttmp = tr("Axle load spectra%1").arg(": "); pt1 = mpText(&painter,arial14B,pt1,ttmp); pt1 = mpText(&painter,arial14,pt1,SPECTXT[*nRigidSpec]); top = pdfRect(&txrect,wid,top,h16,9,85); pt1 = QPoint(txrect.left(), txrect.top()+h16/2); ttmp = tr("Number of lanes (2-way)%1").arg(": "); pt1 = mpText(&painter,arial14B,pt1,ttmp); pt1 = mpText(&painter,arial14,pt1,ui->trafCombo1->currentText()); bot = pdfRect(&txrect,wid,top,h16,9,40); pt1 = QPoint(txrect.left(), txrect.top()+h16/2); ttmp = tr("Base material%1").arg(": "); pt1 = mpText(&painter,arial14B,pt1,ttmp); ttmp = tr("%1 Aggregate").arg(ui->layerCombo2->currentText()); pt1 = mpText(&painter,arial14,pt1,ttmp); top = pdfRect(&txrect,wid,top,h16,9,85); pt1 = QPoint(txrect.left(), txrect.top()+h16/2); ttmp = tr("Base thickness%1").arg(": "); pt1 = mpText(&painter,arial14B,pt1,ttmp); ttmp = tr("%1 %2").arg(txtdbl(ui->layerSpin2->value(),decl(*bsi,false)), txtl(*bsi)); pt1 = mpText(&painter,arial14,pt1,ttmp); bot = pdfRect(&txrect,wid,top,h16,9,40); pt1 = QPoint(txrect.left(), txrect.top()+h16/2); ttmp = tr("Subbase material%1").arg(": "); pt1 = mpText(&painter,arial14B,pt1,ttmp); ttmp = tr("Select Granular"); pt1 = mpText(&painter,arial14,pt1,ttmp); top = pdfRect(&txrect,wid,top,h16,9,85); pt1 = QPoint(txrect.left(), txrect.top()+h16/2); ttmp = tr("Subbase thickness%1").arg(": "); pt1 = mpText(&painter,arial14B,pt1,ttmp); ttmp = tr("%1 %2").arg(txtdbl(ui->layerSpin3->value(),decl(*bsi,false)), txtl(*bsi)); pt1 = mpText(&painter,arial14,pt1,ttmp); bot = pdfRect(&txrect,wid,top,h16,9,40); pt1 = QPoint(txrect.left(), txrect.top()+h16/2); ttmp = tr("Joint spacing%1").arg(": "); pt1 = mpText(&painter,arial14B,pt1,ttmp); ttmp = QString("%1 %2").arg(ui->trafCombo3->currentText(), txtll(*bsi)); pt1 = mpText(&painter,arial14,pt1,ttmp); top = pdfRect(&txrect,wid,top,h16,9,85); pt1 = QPoint(txrect.left(), txrect.top()+h16/2); ttmp = tr("Widened lane%1").arg("? "); pt1 = mpText(&painter,arial14B,pt1,ttmp); ttmp = *bWidened ? tr("Yes") : tr("No"); pt1 = mpText(&painter,arial14,pt1,ttmp); top = pdfRect(&txrect,wid,top,h16,1,0); pt1 = QPoint(txrect.left(), txrect.top()+h16/2); ttmp = tr("Shoulder type%1").arg(": "); pt1 = mpText(&painter,arial14B,pt1,ttmp); ttmp = *bTied ? tr("Tied PCC") : tr("HMA, Untied PCC, or Aggregate"); pt1 = mpText(&painter,arial14,pt1,ttmp); top += 200; painter.setFont(arial16B); top = pdfRect(&txrect,wid,top,h18,1,0); painter.drawText(txrect,"Defaults",tleft); painter.drawLine(txrect.topLeft(), txrect.topRight()); top = pdfRect(&txrect,wid,top,h16,1,0); pt1 = QPoint(txrect.left(), txrect.top()+h16/2); ttmp = tr("Reliability analysis%1").arg(": "); pt1 = mpText(&painter,arial14B,pt1,ttmp); ttmp = tr("Monte Carlo (MnPAVE Flexible)"); pt1 = mpText(&painter,arial14,pt1,ttmp); bot = pdfRect(&txrect,wid,top,h16,9,40); pt1 = QPoint(txrect.left(), txrect.top()+h16/2); ttmp = tr("Allowable cracked slabs%1").arg(": "); pt1 = mpText(&painter,arial14B,pt1,ttmp); ttmp = QString("%1%").arg(cracked); pt1 = mpText(&painter,arial14,pt1,ttmp); top = pdfRect(&txrect,wid,top,h16,9,85); pt1 = QPoint(txrect.left(), txrect.top()+h16/2); ttmp = tr("Reliability level%1").arg(": "); pt1 = mpText(&painter,arial14B,pt1,ttmp); ttmp = QString("%1%").arg(reliability); pt1 = mpText(&painter,arial14,pt1,ttmp); top = pdfRect(&txrect,wid,top,h16,1,0); pt1 = QPoint(txrect.left(), txrect.top()+h16/2); ttmp = tr("Flexural strength%1").arg(": "); pt1 = mpText(&painter,arial14B,pt1,ttmp); ttmp = *bsi ? "4480 kPa" : "650 psi"; pt1 = mpText(&painter,arial14,pt1,ttmp); bot = pdfRect(&txrect,wid,top,h16,9,40); pt1 = QPoint(txrect.left(), txrect.top()+h16/2); ttmp = tr("COV, PCC thickness%1").arg(": "); pt1 = mpText(&painter,arial14B,pt1,ttmp); pt1 = mpText(&painter,arial14,pt1,"3.0%"); top = pdfRect(&txrect,wid,top,h16,9,85); pt1 = QPoint(txrect.left(), txrect.top()+h16/2); ttmp = tr("COV, Flexural strength%1").arg(": "); pt1 = mpText(&painter,arial14B,pt1,ttmp); pt1 = mpText(&painter,arial14,pt1,"8.6%"); bot = pdfRect(&txrect,wid,top,h16,9,40); pt1 = QPoint(txrect.left(), txrect.top()+h16/2); ttmp = tr("MEPDG coefficient 1%1").arg(": "); pt1 = mpText(&painter,arial14B,pt1,ttmp); pt1 = mpText(&painter,arial14,pt1,"0.90"); top = pdfRect(&txrect,wid,top,h16,9,85); pt1 = QPoint(txrect.left(), txrect.top()+h16/2); ttmp = tr("MEPDG coefficient 2%1").arg(": "); pt1 = mpText(&painter,arial14B,pt1,ttmp); pt1 = mpText(&painter,arial14,pt1,"-2.64"); top = pdfRect(&txrect,wid,top,h16,1,0); pt1 = QPoint(txrect.left(), txrect.top()+h16/2); ttmp = tr("Calculated total trucks over service life%1").arg(": "); pt1 = mpText(&painter,arial14B,pt1,ttmp); ttmp = txtdbl(trucks,0,false,false,true); pt1 = mpText(&painter,arial14,pt1,ttmp); top += 200; top = pdfRect(&txrect,wid,top,h10,1,0); painter.drawLine(txrect.topLeft(), txrect.topRight()); top = pdfRect(&txrect,wid,top,h14,1,0); pt1 = QPoint(txrect.left(), txrect.top()+h16/2); ttmp = tr("Designer%1").arg(": "); pt1 = mpText(&painter,arial14B,pt1,ttmp); pt1 = mpText(&painter,arial14,pt1,*tDesigner); top = pdfRect(&txrect,wid,top,h14,1,0); pt1 = QPoint(txrect.left(), txrect.top()+h16/2); ttmp = tr("Notes%1").arg(": "); pt1 = mpText(&painter,arial14B,pt1,ttmp); if(HCADTadj > 1.0) bot = ht-top-h18-h14; // reusing bot for notes height else bot = ht-top-h18; // no need to leave space for HCADT* top = pdfRect(&txrect,wid,top,bot,1,0); painter.setFont(arial10); painter.drawText(txrect,*tNotes,tleft); // footer painter.setFont(arial6); top = pdfRect(&txrect,wid,ht-h18,h18,1,0); painter.drawText(txrect,tDisclaimer,tleft); painter.setFont(arial10); top = pdfRect(&txrect,wid,top-h18-h14,h10,1,0); if(HCADTadj > 1.0) ttmp = tr("%1Effective HCADT = %2 due to 5+ Axle Max vehicles (adjustment factor = %3)") .arg("*", txtdbl(*HCADT * HCADTadj, 0), txtdbl(HCADTadj, 3)); else ttmp = ""; painter.drawText(txrect,ttmp,tleft); painter.end(); //Open file with default PDF application QDesktopServices::openUrl((QUrl("file:/" + newName))); } } void mnpave::on_constCombo_activated(int index) { if(index != *nConstType) { *nConstType = index; updateView(); bmodified = true; } } void mnpave::on_lifeEdit_textEdited(const QString &arg1) { if(*nConstType == FLEXIBLE) *nFlexLife = arg1.toInt(); // HMA life else if(*nConstType == RIGID) { *nRigidLife = arg1.toInt(); // PCC life pSpin[0]->setValue(0.0); } bmodified = true; } void mnpave::on_lifeEdit_editingFinished() { updateView(); } void mnpave::on_projEdit_textEdited(const QString &arg1) { *tSP = arg1; bmodified = true; } void mnpave::on_dateEdit_userDateChanged(const QDate &date) { vList[0] = date; bmodified = true; } void mnpave::on_routeEdit_textEdited(const QString &arg1) { *tHwy = arg1; bmodified = true; } void mnpave::on_rp1Edit_textEdited(const QString &arg1) { *tRP1 = arg1; bmodified = true; } void mnpave::on_rp2Edit_textEdited(const QString &arg1) { *tRP2 = arg1; bmodified = true; } void mnpave::on_distCombo_activated(int index) { if(index != nDistrict && index < 8) { MapDlg mapd; nDistrict = index; if(*nConstType == RIGID) {// set default county nCounty = DISTCO[nDistrict]; calcRigid(false); } vList[1] = mapd.xy2ll(mapd.getCountyPoint(nDistrict, nCounty)); updateView(); bmodified = true; } } void mnpave::on_coCombo_activated(int index) { if(index != nCounty) { MapDlg mapd; if(nDistrict < 0 || nDistrict > 7) // no district selected { nCounty = index; nDistrict = mapd.getDistrict(nCounty,0); updateView(); } else { nCounty = mapd.getCounty(nDistrict, index); updateView(); } vList[1] = mapd.xy2ll(mapd.getCountyPoint(nDistrict, nCounty)); bmodified = true; } } void mnpave::on_mapButton_clicked() { MapDlg mapd(this); mapd.bClick = true; mapd.mapll = vList[1].toPointF(); mapd.setvalues(); mapd.resize(mnpave::size()); mapd.setWindowTitle(tr("Map of Minnesota Districts and Counties")); if(mapd.exec() && (mapd.nDistrictSel != nDistrict || mapd.nCountySel != nCounty || (mapd.bSoil && mapd.nSoilSel != *nSoil))) { if(mapd.nDistrictSel > -1 && mapd.nCountySel > -1) { nDistrict = mapd.nDistrictSel; nCounty = mapd.nCountySel; if(mapd.bSoil && mapd.nSoilSel >= 0 && mapd.nSoilSel <= 14) *nSoil = mapd.nSoilSel; else *nSoil = -1; } else { nDistrict = 8; // All nCounty = -1; // none } vList[1] = mapd.mapll; updateView(); bmodified = true; } } void mnpave::on_climateButton_clicked() { ClimateDlg cdlg(this); cdlg.resize(mnpave::size()); if(cdlg.exec()) { updateView(); bmodified = true; } } void mnpave::on_desEdit_textEdited(const QString &arg1) { *tDesigner = arg1; bmodified = true; } void mnpave::on_senEdit_textEdited(const QString &arg1) { *tSoilsEngineer = arg1; bmodified = true; } void mnpave::on_notesButton_clicked() { NotesDlg notes; notes.setWindowTitle(tr("%1 %2 Notes").arg(APPTITLE,PAVETXT[PAVEMENT])); notes.tNotes = *tNotes; notes.loadText(); // set proportional size but keep aspect ratio notes.resize(QSize(ui->mptxtFrame->width()*1.6, ui->mptxtFrame->width()*1.2)); if(notes.exec()) { if(notes.tNotes != *tNotes) { *tNotes = notes.tNotes; bmodified = true; } } } void mnpave::on_trafEdit1_textEdited(const QString &arg1) { if(*nConstType == FLEXIBLE) *esal = arg1.toDouble(); // ESAL else if(*nConstType == RIGID) { *HCADT = arg1.toDouble(); // HCADT *HPCC = 0.0; ui->layerEdit1->setText(*bsi ? "0" : "0.0"); } bmodified = true; } void mnpave::on_trafEdit1_editingFinished() { updateView(); calcRigid(false); } void mnpave::on_trafEdit2_textEdited(const QString &arg1) { *ipct = arg1.toDouble(); // traffic growth rate if(*nConstType == RIGID) { *HPCC = 0.0; ui->layerEdit1->setText(*bsi ? "0" : "0.0"); } bmodified = true; } void mnpave::on_trafEdit2_editingFinished() { updateView(); calcRigid(false); } void mnpave::on_trafCombo1_activated(int index) { if(index != *nLanes) { *nLanes = index; if(*nConstType == RIGID) calcRigid(false); bmodified = true; } } void mnpave::on_trafCombo2_activated(int index) { if(index != *nRigidSpec) { *nRigidSpec = index; if(*nConstType == RIGID) calcRigid(false); bmodified = true; } } void mnpave::on_trafCombo3_activated(int index) { if(index != *nJoint) { *nJoint = index; if(*nConstType == RIGID) calcRigid(false); bmodified = true; } } void mnpave::on_axleButton_clicked() { if(*nConstType == FLEXIBLE) launchTraffic(*bSpectrum ? 3 : 2); // rigid spec not used in flexible design else launchTraffic(0); updateTraffic(); } void mnpave::on_trafCheck1_clicked(bool checked) { *bWidened = checked; if(*nConstType == RIGID) calcRigid(false); bmodified = true; } void mnpave::on_trafCheck2_clicked(bool checked) { *bTied = checked; if(*nConstType == RIGID) calcRigid(false); bmodified = true; } void mnpave::on_trafButton1_clicked() {// may not be needed } void mnpave::on_calcButton_clicked() { switch(*nConstType) { case FLEXIBLE: { // weslea w; // w.calcwes(); } break; case RIGID: { calcRigid(true); } break; } bmodified = true; } void mnpave::on_strucCombo1_currentIndexChanged(int index) { if(*nConstType == 0) *nFlexLayer = index+1; // HMA layers else if(*nConstType == 1) *nRigidLayer = index+1; // PCC layers updateView(); bmodified = true; } void mnpave::on_actionHelp_Topics_triggered() {// create a modeless help window QFile hfile(DEFHELP); if(!hfile.exists()) { QMessageBox msg; msg.setText(tr("Help file could not be located.")); msg.exec(); } else { HelpDlg *hlp = new HelpDlg(this); hlp->setWindowTitle(APPTITLE + " " + tr("Help")); hlp->resize(mnpave::size()); hlp->show(); } } void mnpave::on_strucButton1_clicked() { QString lyrlab[3] = {"Thickness", "Adjusted", "COV"}; nHlab = nHlab < 2 ? nHlab+1 : 0; ui->strucButton1->setText(lyrlab[nHlab]); updateStruc(); } void mnpave::on_layerButton1_clicked() { LayerDlg ldlg(this); ldlg.resize(mnpave::size()); ldlg.bResearch = *bResearch; if(ldlg.exec()) { updateStruc(); bmodified = true; } } void mnpave::on_layerButton2_clicked() { LayerDlg ldlg(this); if(ldlg.exec()) { updateStruc(); bmodified = true; } } void mnpave::on_layerCombo2_activated(int index) { *nRigidBase = index; calcRigid(false); } void mnpave::on_layerButton3_clicked() { LayerDlg ldlg(this); if(ldlg.exec()) { updateStruc(); bmodified = true; } } void mnpave::on_layerButton4_clicked() { LayerDlg ldlg(this); if(ldlg.exec()) { updateStruc(); bmodified = true; } } void mnpave::on_layerButton5_clicked() { LayerDlg ldlg(this); if(ldlg.exec()) { updateStruc(); bmodified = true; } } void mnpave::on_layerSpin1_valueChanged(double arg1) { if(*nConstType == FLEXIBLE) { if(bspin) { switch(nHlab) { case 0: { *H[0][0] = convl(*bsi,arg1); } break; case 2: { *HCOV[0] = arg1; } break; } bmodified = true; } } } void mnpave::on_layerSpin2_valueChanged(double arg1) { if(bspin) { switch(*nConstType) { case FLEXIBLE: // flexible { switch(nHlab) { case 0: { *H[1][0] = convl(*bsi,arg1); } break; case 2: { *HCOV[1] = arg1; } break; } bmodified = true; } break; case RIGID: // rigid { val[1] = rnd2dec(convl(*bsi,arg1),0); // switch values between 4 & 12" *nRigidHBase = val[1] == 4.0 || (val[1] > 8.0 && val[1] != 12.0) ? 0 : 1; updateStruc(); calcRigid(false); } break; } } } void mnpave::on_layerSpin3_valueChanged(double arg1) { if(bspin) { switch(*nConstType) { case FLEXIBLE: // flexible { switch(nHlab) { case 0: { *H[2][0] = convl(*bsi,arg1); } break; case 2: { *HCOV[2] = arg1; } break; } bmodified = true; } break; case RIGID: // rigid { val[2] = rnd2dec(convl(*bsi,arg1),0); // switch values between 4 & 12" *nRigidHBase = val[2] == 4.0 || (val[2] > 8.0 && val[2] != 12.0) ? 1 : 0; updateStruc(); calcRigid(false); } break; } } } void mnpave::on_layerSpin4_valueChanged(double arg1) { if(bspin) { switch(nHlab) { case 0: { *H[3][0] = convl(*bsi,arg1); } break; case 2: { *HCOV[3] = arg1; } break; } bmodified = true; } } void mnpave::on_actionNew_triggered() { // Create a new window mpSettings("", SETBOOL); // make same settings as open document mnpave *other = new mnpave; other->resize(this->size()); other->move(this->pos() + QPoint(40,40)); other->show(); } void mnpave::on_actionOpen_triggered() { mpSettings("", READREG); // File opens in a new window unless the old window is unmodified if(!tName.isEmpty()) { mnpave *other = new mnpave; other->mpSettings("", READREG); if(other->Open()) { other->resize(this->size()); other->move(this->pos() + QPoint(40,40)); other->show(); } else other->destroy(); } else Open(); } void mnpave::on_actionClose_triggered() { mnpave::close(); } void mnpave::on_actionSave_triggered() { Save(tFile); } void mnpave::on_actionSave_As_triggered() { SaveAs(tFile); } void mnpave::on_action1_triggered() { openRecent(); } void mnpave::on_action2_triggered() { openRecent(); } void mnpave::on_action3_triggered() { openRecent(); } void mnpave::on_action4_triggered() { openRecent(); } void mnpave::on_action5_triggered() { openRecent(); } void mnpave::on_action6_triggered() { openRecent(); } void mnpave::on_actionExit_triggered() { if(bmodified) { if(askSave()) qApp->exit(); } else qApp->exit(); } void mnpave::on_actionCut_triggered() { ctrlkey(Qt::Key_X); } void mnpave::on_actionCopy_triggered() { ctrlkey(Qt::Key_C); } void mnpave::on_actionPaste_triggered() { ctrlkey(Qt::Key_V); } void mnpave::on_actionEnglish_triggered() { *bsi = false; ui->actionSI->setChecked(false); updateTraffic(); updateStruc(); updateOutput(); bmodified = true; } void mnpave::on_actionSI_triggered() { *bsi = true; ui->actionEnglish->setChecked(false); updateTraffic(); updateStruc(); updateOutput(); bmodified = true; } void mnpave::on_actionShow_Binder_Warnings_triggered() { *bBWarn = !*bBWarn; ui->actionShow_Binder_Warnings->setChecked(*bBWarn); bmodified = true; } void mnpave::on_actionShow_Thickness_Warnings_triggered() { *bHWarn = !*bHWarn; ui->actionShow_Thickness_Warnings->setChecked(*bHWarn); bmodified = true; } void mnpave::on_actionAlways_Show_Allowable_Stress_triggered() { *bMohrAlways = !*bMohrAlways; ui->actionAlways_Show_Allowable_Stress->setChecked(*bMohrAlways); if(*bMohrAlways && *bMohrFail) { *bMohrFail = false; ui->actionShow_Allowable_Stress_if_Failed->setChecked(false); } bmodified = true; } void mnpave::on_actionShow_Allowable_Stress_if_Failed_triggered() { *bMohrFail = !*bMohrFail; ui->actionShow_Allowable_Stress_if_Failed->setChecked(*bMohrFail); if(*bMohrFail && *bMohrAlways) { *bMohrAlways = false; ui->actionAlways_Show_Allowable_Stress->setChecked(false); } bmodified = true; } void mnpave::on_actionDesign_triggered() { *bResearch = false; bmodified = true; updateMenu(); updateView(); repaint(); } void mnpave::on_actionResearch_triggered() { *bResearch = true; bmodified = true; updateMenu(); updateView(); repaint(); } void mnpave::on_actionAbout_mnpave_triggered() { AboutDlg about; about.setWindowTitle(tr("About %1 %2").arg(APPTITLE,PAVETXT[PAVEMENT])); // set proportional size but keep aspect ratio about.resize(QSize(ui->mptxtFrame->width()*1.6, ui->mptxtFrame->width()*1.2)); about.exec(); }