/**************************************************************************** ** ** 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 "globals.h" // ALL THE GLOBAL DEFINITIONS int deg2degmin(double decdeg, double *min, int minround) { double tmp = floor(decdeg); int deg = (int) tmp; tmp = decdeg - tmp; *min = rnd2dec(tmp*60.,minround); if(*min >= 60.) { *min -= 60.; deg += 1; } return deg; } double degmin2deg(int deg, double min) { return (double) deg + min/60.; } bool setSpin(double oldval, double *newval, double incr) {// resets the spinner if the start point is not a multiple of the increment if(qFabs(*newval - oldval) == incr) // indicates spinner was used instead of edit box { if(remainder(*newval, incr) != 0) { *newval = *newval > oldval ? qFloor(*newval/incr) * incr : qCeil(*newval/incr) * incr; } return true; } else return false; } int decl(bool si, bool hma) {// decimal places for length (mm or in) if(hma) return si ? DEC_MM : DEC_IN; else return si ? DEC_MM : DECR_IN; } int nint(double x) // provided by koahnig at qt-project.org {// avoids binary rounding error in (int) conversion return x < 0 ? (int)ceil(x) : (int)floor(x); } long nlong(double x) {// avoids binary rounding error in (long) conversion return x < 0 ? (long)ceil(x) : (long)floor(x); } int soilclass(double Silt, double Clay) { int s = 59; double Sand = 100. - Silt - Clay; if(Sand > 90) s = 1; // Sand else if(Sand > 80) s = 2; // Loamy Sand else if(Sand > 50) { if(Clay > 30) s = 9; // Sandy Clay else if(Clay > 20) s = 6; // Sandy Clay Loam else if(Clay > 10) s = 40; // Sandy Loam (plastic) else s = 3; // Sandy Loam (slightly plastic) } else if(Silt > 80) s = 41; // Silt else if(Silt > 50) { if(Clay > 30)s = 10; // Silty Clay else if(Clay > 20) s = 8; // Silty Clay Loam else if(Clay > 10) s = 42; // Silt Loam (plastic) else s = 5; // Silt Loam (slightly plastic) } else if(Clay > 30) s = 11; // Clay else if(Clay > 20) s = 7; // Clay Loam else s = 4; // Loam return s; } double incl(bool si) {// spin button increments for length (mm or in) return si ? INC_MM : INC_IN; } // The following facilitate conversions between stored and displayed data (SI or English units) // insi and outsi refer to the input and output units (true = SI) double convt(bool insi, double tin, bool outsi) {// temperature °C or °F if((insi && outsi) || (!insi && !outsi)) return tin; else if(insi) return tin * K_R + 32.; else return (tin - 32.) / K_R; } double convl(bool insi, double lin, bool outsi) {// length mm or in if((insi && outsi) || (!insi && !outsi)) return lin; else if(insi) return lin / IN_MM; else return lin * IN_MM; } double convll(bool insi, double lin, bool outsi) {// input length m or ft, output m if((insi && outsi) || (!insi && !outsi)) return lin; else if(insi) return lin / FT_M; else return lin * FT_M; } double convlll(bool insi, double lin, bool outsi) {// length km or mi if((insi && outsi) || (!insi && !outsi)) return lin; else if(insi) return lin / MI_KM; else return lin * MI_KM; } double convf(bool insi, double fin, bool outsi) {// force N (kN) or lbs (kips) if((insi && outsi) || (!insi && !outsi)) return fin; else if(insi) return fin / LB_N; else return fin * LB_N; } double convp(bool insi, double pin, bool outsi) {// pressure kPa (MPa) or psi (ksi) if((insi && outsi) || (!insi && !outsi)) return pin; else if(insi) return pin / PSI_KPA; else return pin * PSI_KPA; } double convd(bool insi, double din, bool outsi) {// density kg/m3 or pcf if((insi && outsi) || (!insi && !outsi)) return din; else if(insi) return din / PCF_KGM3; else return din * PCF_KGM3; } double log10(double val) { return log(val)/log(10); } double rnd2dec(double value, int dec, bool sigfig) {// RoundToDecimal written by Corey Spagnoli 1/14/98 adapted by Bruce Tanquist long temp_value; double ret_value; double raise_to; double tolerance; double final_diff; bool bneg = value < 0; if(bneg) value = -value; // Significant figures option added by Bruce Tanquist 5/11/01 if(sigfig) { dec = value == 0 ? 0 : dec - (1 + nint(log10(value))); if(dec > MAXDEC) dec = MAXDEC; } raise_to = pow(10.0, (double) dec); tolerance = 1.0 / raise_to; temp_value = (long)round(value * raise_to); ret_value = (double)temp_value / raise_to; final_diff = value - ret_value; if (final_diff < -tolerance || final_diff > tolerance) ret_value = value; value = ret_value; if(bneg) value = -value; return value; } QPoint rectIndex(bool ind, QRect* rect, QPoint pt, int xRects, int yRects) { // returns x and y index values for a point in an evenly divided grid // Clicking in the upper left cell returns (0,0) // Clicking in the lower right cell returns (xRects-1, yRects-1) // rect is changed to the inner rect // if ind is TRUE, pt holds index values of the inner rect and return is upper left coord. int x0, y0, w, h, xi, yi; QRect rectTmp = *rect; x0 = rectTmp.left(); y0 = rectTmp.top(); w = rectTmp.right() - x0; h = rectTmp.bottom() - y0; if(ind) { xi = pt.x(); yi = pt.y(); } else { xi = xRects * (pt.x() - x0) / w; yi = yRects * (pt.y() - y0) / h; } // Rectangle rectTmp = QRect(x0 + xi * w / xRects, y0 + yi * h / yRects, x0 + (xi+1) * w / xRects, y0 + (yi+1) * h / yRects); *rect = rectTmp; if(ind) return rectTmp.topLeft(); else return QPoint(xi, yi); } int pdfRect(QRect *rect, int wpage, int top, double ht, int ncells, int n) { // ncells <= 9 // returns the top of the next line's rect // n is the horizontal cell index (zero-based) // if n > 9, a range is represented (30 = from 0 to 3) // top gets updated for next line int n1, n2; int lt, wd; if(n < 10) { n1 = n; n2 = -1; // unused } else { n1 = n % 10; n2 = n/10; } wd = wpage/ncells; lt = n1*wd; if(n2 > -1) { wd *= n2-n1+1; } QRect rectTmp = QRect(lt, top, wd, ht); *rect = rectTmp; return rectTmp.bottom(); // return rectTmp.y() + rectTmp.height(); } QString bas2bas54(QString tnum, const QString &talpha1, const QString &talpha2, quint64 *udec, bool bdec) { // converts from any base >= 2 into decimal // *udec & bdec are used if decimal input is desired (tnum & talpha1 are ignored) // if bdec is false, *udec returns a decimal result // for some reason these calcs max out at 2^54-1 instead of 2^64-1 qint32 j, k; quint16 nsize = tnum.length(); quint16 nbase1 = talpha1.length(); quint16 nbase2 = talpha2.length(); quint16 nmax16 = ~(quint16(0)); quint64 nmax64 = ~(quint64(0)); quint64 ndec; if(nbase1 < 2 || nbase1 > nmax16 || nbase2 < 2 || nbase2 > nmax16 || nsize == 0 || nsize > floor(log((nmax64)/log(nbase1))+1)) return "out of range"; if(bdec) ndec = *udec; else if(talpha1 == A10) { ndec = tnum.toULongLong(); if(ndec > MAX54) return "max exceeded"; } else { // convert from base1 to decimal bool berr = false; QChar cc; quint16 nc; ndec = 0; for(j = 0; j < nsize; ++j) { cc = tnum.at(tnum.length()-1); nc = talpha1.indexOf(cc); if(nc > nbase1-1) berr = true; else if(ndec > MAX54 - nc * floor(pow(nbase1, j))) return "max exceeded"; else ndec += nc * floor(pow(nbase1, j)); tnum.chop(1); } if(berr) return "error in base to decimal conversion"; } if(!bdec) *udec = ndec; // makes decimal value available if(talpha2 == A10) return QString::number(ndec); // convert from decimal to base2 nsize = (quint16) floor(log(ndec)/log(nbase2)) + 1; // number of characters in output QString tbase = ""; bool bhigh; if(ndec < pow(nbase2, nsize)) { for(j = nsize-1; j >= 0; --j) { bhigh = true; for(k = nbase2; k > 1; --k) { if(bhigh && ndec < pow(nbase2, j) * (nbase2-k+1)) { bhigh = false; tbase.append(talpha2.at(nbase2-k)); ndec -= (quint64) floor(pow(nbase2, j)) * (nbase2-k); } } if(bhigh) { tbase.append(talpha2.at(nbase2-1)); ndec -= (quint64) floor(pow(nbase2, j)) * (nbase2-1); } } } return tbase; } QString txtt(bool si) { return si ? "°C" : "°F"; } QString txtl(bool si) { return si ? "mm" : "in."; } QString txtll(bool si) { return si ? "m" : "ft."; } QString txtlll(bool si) { return si ? "km" : "mi."; } QString txtf(bool si) { return si ? "N" : "lbs."; } QString txtff(bool si) { return si ? "kN" : "kips"; } QString txtp(bool si) { return si ? "kPa" : "psi"; } QString txte(bool si) { return si ? "MPa" : "ksi"; } QString txtu(bool si) { return si ? "µm" : "mils"; } QString tontxt(bool si) { return si ? "tonnes" : "tons"; } QString txtv(bool si) { return si ? "km/h" : "mph"; } QString trimright(QString txt, QString ttrim) {// trims all of the ttrim characters from the right side of txt while(txt.right(1) == ttrim) txt.resize(txt.size() - 1); return txt; } QString txtdbl(double value, int dec, bool sigfig, bool trimzero, bool comma) {// convert a double to text with options for decimal place, significant digits, remove extra zeroes and add commas int i, decimal; QString tnum; value = rnd2dec(value, dec, sigfig); // run conversion with precision 6 to make sure the decimal point is found tnum = QString::number(value, 'f', 6); decimal = tnum.indexOf("."); if(sigfig) { tnum = QString::number(value, 'e', dec-1); tnum = tnum.left(dec+1); // remove "e+00" notation } else tnum = QString::number(value, 'f', dec); tnum.remove("."); if(decimal > 0) { int lg = tnum.length(); if(decimal > lg) for(i = 0; i < decimal - lg; i++) tnum.insert(lg+i, "0"); tnum.insert(decimal, "."); if(trimzero) tnum = trimright(tnum, "0"); tnum = trimright(tnum, "."); } else if(decimal == 0) { tnum.insert(0, "."); tnum.insert(0, "0"); if(trimzero) tnum = trimright(tnum, "0"); } else // decimal < 0 { for(i = decimal; i < 0; i++) tnum.insert(0, "0"); tnum.insert(0, "."); tnum.insert(0, "0"); if(trimzero) tnum = trimright(tnum, "0"); } if(comma) { int length = tnum.indexOf("."); if(length == -1) length = tnum.size(); for(i = 1; i < 4; i++) if(i*3 < length) tnum.insert(length-i*3, ","); } return tnum; } QString txtdegmin(int deg, double min) { return QString::number(deg) + "°" + QString::number(min) + "'"; } QString txthrmin(int hour, int min, bool b24) {// convert hour and minute strings to one time string with option for 12 or 24 hour format if(hour < 0 || hour > 23) hour = 0; if(min < 0 || min > 59) min = 0; QString tm; QString th; QString tmin = QString::number(min); QString tc = ":"; QString tz = "0"; if(b24) tm = ""; else if(hour < 12) tm = " AM"; else tm = " PM"; if(min < 10) tmin = tc + tz + tmin; else tmin = tc + tmin; if(b24) { th = QString::number(hour); if(hour < 10) th = tz + th; } else { if(hour == 0) hour = 12; else if(hour > 12) hour -= 12; th = QString::number(hour); } return th + tmin + tm; } QTime TimeText(QString *time, bool b24) {// interpret a string with numbers, am, pm, a, p and other characters to produce // a QTime variable and formatted time string with option for 12 or 24 hour format QString ttime = *time; QString th; // hours QString tm = "0"; QString tmin; QString tc = ":"; QString tz = "0"; ttime.remove(" "); ttime.remove("."); ttime.remove(","); ttime.remove(";"); ttime.remove("-"); ttime.replace("a","A"); ttime.replace("p","P"); ttime.replace("m","M"); int na = ttime.indexOf("A"); ttime.remove("A"); int np = ttime.indexOf("P"); ttime.remove("P"); int nz; // indicates leading zero (military time) ttime.remove("M"); int nmin = 0; // minutes // check to see if there are more or less than 2 characters after the colon int nt = ttime.indexOf(":"); int nl = ttime.length(); if(nt > -1 && nl == nt+2) ttime.insert(nt+1, "0"); // insert 0 if only 1 char in minutes ttime.remove(":"); nl = ttime.length(); if(nl > 4) ttime.remove(4, nl-4); // remove extra digits QString ttmp = ttime.at(0); nz = ttmp.toInt(); // zero indicates military time nt = ttime.toInt(); if(nl > 2) // assume hours and minutes entered { tmin = ttime.right(2); nmin = tmin.toInt(); if(nt >= 100) nt /= 100; // remove minutes else if(b24) nt = 0; } if(na >= 0 && nt == 12) nt = 0; else if(np >= 0 && nt < 12) nt += 12; if(nt == 24) nt = 0; else if(nt > 24) nt = 12; else if(!b24 && na + np == -2 // no am or pm indicated && nz > 0 && nt < 6) // assume pm if 12:00 to 5:59 { nt += 12; } if(nmin >= 60) nmin = 0; tmin = QString::number(nmin); tmin = nmin < 10 ? tc + tz + tmin : tc + tmin; if(b24) { th = QString::number(nt); tm = ""; if(nt < 10) th = tz + th; } else { if(nt < 12) tm = " AM"; else tm = " PM"; if(nt == 0) th = "12"; else if(nt > 12) th = QString::number(nt-12); else th = QString::number(nt); } *time = th + tmin + tm; return QTime(nt, nmin); } QString tmat(bool bshort, int mat) { QString tMat[26]; if(bshort) { tMat[0] = QObject::tr("PCC"); tMat[1] = QObject::tr("HMA"); tMat[2] = QObject::tr("Old HMA"); tMat[3] = QObject::tr("CIR"); tMat[4] = QObject::tr("SFDR"); tMat[5] = QObject::tr("BSB"); tMat[6] = QObject::tr("MSB"); tMat[7] = QObject::tr("RPCC"); tMat[10] = QObject::tr("AggBase"); tMat[11] = QObject::tr("Subbase"); tMat[12] = QObject::tr("StabSoil"); tMat[13] = QObject::tr("EngSoil"); tMat[14] = QObject::tr("UndSoil"); tMat[20] = QObject::tr("Bedrock"); tMat[21] = QObject::tr("Gdwater"); tMat[25] = QObject::tr("Other"); } else { tMat[0] = QObject::tr("New Concrete"); tMat[1] = QObject::tr("Hot-Mix Asphalt"); tMat[2] = QObject::tr("Old HMA"); tMat[3] = QObject::tr("Cold In-Place Recycling"); tMat[4] = QObject::tr("Stabilized Full-Depth Reclaim"); tMat[5] = QObject::tr("Bituminous Stabilized Base"); tMat[6] = QObject::tr("Mineral Stabilized Base"); tMat[7] = QObject::tr("Rubblized Concrete"); tMat[10] = QObject::tr("Aggregate Base"); tMat[11] = QObject::tr("Aggregate Subase"); tMat[12] = QObject::tr("Stabilized Soil"); tMat[13] = QObject::tr("Engineered Soil"); tMat[14] = QObject::tr("Undisturbed Soil"); tMat[20] = QObject::tr("Bedrock"); tMat[21] = QObject::tr("Groundwater"); tMat[25] = QObject::tr("Other"); } return tMat[mat]; } QString tdet(bool bshort, int mat, int det) { int i; QString tDet[64]; for(i = 0; i < 64; ++i) tDet[i] = ""; if(mat > 0 && mat < 3) // HMA { // Viscosity Grades tDet[0] = QObject::tr("AC 2.5"); tDet[1] = QObject::tr("AC 5"); tDet[2] = QObject::tr("AC 10"); tDet[3] = QObject::tr("AC 20"); tDet[4] = QObject::tr("AC 40"); // Penetration Grades tDet[5] = QObject::tr("40/50 Pen."); tDet[6] = QObject::tr("60/70 Pen."); tDet[7] = QObject::tr("85/100 Pen."); tDet[8] = QObject::tr("120/150 Pen."); tDet[9] = QObject::tr("200/300 Pen."); // PG Grades tDet[10] = QObject::tr("N/A"); // user defined tDet[11] = QObject::tr("N/A"); tDet[12] = QObject::tr("N/A"); tDet[13] = QObject::tr("N/A"); tDet[14] = QObject::tr("PG46-34"); tDet[15] = QObject::tr("PG46-40"); tDet[16] = QObject::tr("PG46-46"); tDet[17] = QObject::tr("PG52-10"); tDet[18] = QObject::tr("PG52-16"); tDet[19] = QObject::tr("PG52-22"); tDet[20] = QObject::tr("PG52-28"); tDet[21] = QObject::tr("PG52-34"); tDet[22] = QObject::tr("PG52-40"); tDet[23] = QObject::tr("PG52-46"); tDet[24] = QObject::tr("PG58-10"); tDet[25] = QObject::tr("PG58-16"); tDet[26] = QObject::tr("PG58-22"); tDet[27] = QObject::tr("PG58-28"); tDet[28] = QObject::tr("PG58-34"); tDet[29] = QObject::tr("PG58-40"); tDet[30] = QObject::tr("PG58-46"); tDet[31] = QObject::tr("PG64-10"); tDet[32] = QObject::tr("PG64-16"); tDet[33] = QObject::tr("PG64-22"); tDet[34] = QObject::tr("PG64-28"); tDet[35] = QObject::tr("PG64-34"); tDet[36] = QObject::tr("PG64-40"); tDet[37] = QObject::tr("N/A"); tDet[38] = QObject::tr("PG70-10"); tDet[39] = QObject::tr("PG70-16"); tDet[40] = QObject::tr("PG70-22"); tDet[41] = QObject::tr("PG70-28"); tDet[42] = QObject::tr("PG70-34"); tDet[43] = QObject::tr("PG70-40"); tDet[44] = QObject::tr("N/A"); tDet[45] = QObject::tr("PG76-10"); tDet[46] = QObject::tr("PG76-16"); tDet[47] = QObject::tr("PG76-22"); tDet[48] = QObject::tr("PG76-28"); tDet[49] = QObject::tr("PG76-34"); tDet[50] = QObject::tr("N/A"); tDet[51] = QObject::tr("N/A"); tDet[52] = QObject::tr("PG82-10"); tDet[53] = QObject::tr("PG82-16"); tDet[54] = QObject::tr("PG82-22"); tDet[55] = QObject::tr("PG82-28"); tDet[56] = QObject::tr("PG82-34"); tDet[57] = QObject::tr("N/A"); tDet[58] = QObject::tr("N/A"); tDet[61] = QObject::tr(": Multi"); tDet[62] = QObject::tr(": Other"); tDet[63] = QObject::tr("Click Here"); if(bshort) { tDet[63] = QObject::tr("undefined"); tDet[det].replace(QObject::tr(" Pen."),QObject::tr("")); } return tDet[det]; } else if(mat > 9) { if(mat < 12) // base { if(bshort) { // Aggregate Base tDet[0] = QObject::tr(": FDR"); tDet[1] = QObject::tr(": Cl.6"); tDet[2] = QObject::tr(": Cl.5"); // Aggregate Subbase tDet[10] = QObject::tr(": Cl.4"); tDet[11] = QObject::tr(": Cl.3"); tDet[12] = QObject::tr(": SelGr"); tDet[13] = QObject::tr(": Gran"); tDet[61] = QObject::tr(": Multi"); tDet[62] = QObject::tr(": Other"); tDet[63] = QObject::tr(": undefined"); } else { // Aggregate Base tDet[0] = QObject::tr("FDR"); tDet[1] = QObject::tr("MnDOT Class 6"); tDet[2] = QObject::tr("MnDOT Class 5"); // Aggregate Subbase tDet[10] = QObject::tr("MnDOT Class 4"); tDet[11] = QObject::tr("MnDOT Class 3"); tDet[12] = QObject::tr("MnDOT Select Granular"); tDet[13] = QObject::tr("MnDOT Granular"); tDet[61] = QObject::tr("Multi-Layer"); tDet[62] = QObject::tr("Other"); tDet[63] = QObject::tr("Click Here"); } return tDet[det]; } else if(mat < 15) // soil { if(bshort) { // Soil // MN Classes tDet[0] = QObject::tr(": G"); tDet[1] = QObject::tr(": Sa"); tDet[2] = QObject::tr(": LSa"); tDet[3] = QObject::tr(": SaL(p)"); tDet[4] = QObject::tr(": SaL(sp)"); tDet[5] = QObject::tr(": L"); tDet[6] = QObject::tr(": SiL(p)"); tDet[7] = QObject::tr(": SiL(sp)"); tDet[8] = QObject::tr(": Si"); tDet[9] = QObject::tr(": SaCL"); tDet[10] = QObject::tr(": CL"); tDet[11] = QObject::tr(": SiCL"); tDet[12] = QObject::tr(": SaC"); tDet[13] = QObject::tr(": SiC"); tDet[14] = QObject::tr(": C"); // AASHTO Classes tDet[20] = QObject::tr(": A-1-a"); tDet[21] = QObject::tr(": A-1-b"); tDet[22] = QObject::tr(": A-3"); tDet[23] = QObject::tr(": A-2-4"); tDet[24] = QObject::tr(": A-2-5"); tDet[25] = QObject::tr(": A-2-6"); tDet[26] = QObject::tr(": A-2-7"); tDet[27] = QObject::tr(": A-4"); tDet[28] = QObject::tr(": A-5"); tDet[29] = QObject::tr(": A-6"); tDet[30] = QObject::tr(": A-7-5"); tDet[31] = QObject::tr(": A-7-6"); // Unified Classes tDet[40] = QObject::tr(": GW"); tDet[41] = QObject::tr(": GP"); tDet[42] = QObject::tr(": GM"); tDet[43] = QObject::tr(": GC"); tDet[44] = QObject::tr(": SW"); tDet[45] = QObject::tr(": SP"); tDet[46] = QObject::tr(": SM"); tDet[47] = QObject::tr(": SC"); tDet[48] = QObject::tr(": ML"); tDet[49] = QObject::tr(": CL"); tDet[50] = QObject::tr(": OL"); tDet[51] = QObject::tr(": MH"); tDet[52] = QObject::tr(": CH"); tDet[53] = QObject::tr(": OH"); tDet[54] = QObject::tr(": Pt"); tDet[62] = QObject::tr(": Other"); tDet[63] = QObject::tr(": undefined"); } else { // Eng. Soil tDet[0] = QObject::tr("Gravel"); tDet[1] = QObject::tr("Sand"); tDet[2] = QObject::tr("Loamy Sand"); tDet[3] = QObject::tr("Sandy Loam (plastic)"); tDet[4] = QObject::tr("Sandy Loam (slightly plastic)"); tDet[5] = QObject::tr("Loam"); tDet[6] = QObject::tr("Silt Loam (plastic)"); tDet[7] = QObject::tr("Silt Loam (slightly plastic)"); tDet[8] = QObject::tr("Silt"); tDet[9] = QObject::tr("Sandy Clay Loam"); tDet[10] = QObject::tr("Clay Loam"); tDet[11] = QObject::tr("Silty Clay Loam"); tDet[12] = QObject::tr("Sandy Clay"); tDet[13] = QObject::tr("Silty Clay"); tDet[14] = QObject::tr("Clay"); tDet[20] = QObject::tr("AASHTO A-1-a"); tDet[21] = QObject::tr("AASHTO A-1-b"); tDet[22] = QObject::tr("AASHTO A-3"); tDet[23] = QObject::tr("AASHTO A-2-4"); tDet[24] = QObject::tr("AASHTO A-2-5"); tDet[25] = QObject::tr("AASHTO A-2-6"); tDet[26] = QObject::tr("AASHTO A-2-7"); tDet[27] = QObject::tr("AASHTO A-4"); tDet[28] = QObject::tr("AASHTO A-5"); tDet[29] = QObject::tr("AASHTO A-6"); tDet[30] = QObject::tr("AASHTO A-7-5"); tDet[31] = QObject::tr("AASHTO A-7-6"); tDet[40] = QObject::tr("Unified GW"); tDet[41] = QObject::tr("Unified GP"); tDet[42] = QObject::tr("Unified GM"); tDet[43] = QObject::tr("Unified GC"); tDet[44] = QObject::tr("Unified SW"); tDet[45] = QObject::tr("Unified SP"); tDet[46] = QObject::tr("Unified SM"); tDet[47] = QObject::tr("Unified SC"); tDet[48] = QObject::tr("Unified ML"); tDet[49] = QObject::tr("Unified CL"); tDet[50] = QObject::tr("Unified OL"); tDet[51] = QObject::tr("Unified MH"); tDet[52] = QObject::tr("Unified CH"); tDet[53] = QObject::tr("Unified OH"); tDet[54] = QObject::tr("Unified Pt"); tDet[62] = QObject::tr("Other"); tDet[63] = QObject::tr("Click Here"); } return tDet[det]; } } return ""; } QPoint mpText(QPainter* painter, QFont font, QPoint start, QString text, int vert, bool italOffset) { // vert -1: subscript, 0: normal, 1: superscript int xs, ys, os, w; QFont oldFont; QFontMetrics fmOld(font); Qt::BGMode nbk = painter->backgroundMode(); // save existing mode in case it is opaque painter->setBackgroundMode(Qt::TransparentMode); // save existing font oldFont = painter->font(); double size = (double) fmOld.height(); double pwr = (double) abs(vert); font.setPointSizeF(font.pointSizeF() * pow(0.65, pwr)); // reduce size for sub & super os = nint(rnd2dec(size * -pow(0.25, pwr) * vert * pow(pwr, 0.25) + size * pow(0.15, pwr) * pow(pwr, 2.0),0)); xs = start.x(); ys = start.y() + os; if(pwr > 0) xs -= size/12.; if(italOffset && font.italic() && vert < 0) xs -= os / 4.; // adjust horiz. placement of subscript painter->setFont(font); painter->drawText(xs, ys, text); QFontMetrics fm(font); painter->setFont(oldFont); painter->setBackgroundMode(nbk); w = fm.width(text) * font.pointSizeF() * 0.85; // convert pixels to points? return QPoint(xs + w + nint(rnd2dec(size/8.,0)), start.y()); } void debugmsg(QString tmsg, QString tval) { QMessageBox msgBox; msgBox.setText(tmsg + " " + tval); msgBox.exec(); }