Qucs-GUI
0.0.19
|
00001 /*************************************************************************** 00002 curvediagram.cpp 00003 ------------------ 00004 begin : Sat Apr 9 2005 00005 copyright : (C) 2005 by Michael Margraf 00006 email : michael.margraf@alumni.tu-berlin.de 00007 ***************************************************************************/ 00008 00009 /*************************************************************************** 00010 * * 00011 * This program is free software; you can redistribute it and/or modify * 00012 * it under the terms of the GNU General Public License as published by * 00013 * the Free Software Foundation; either version 2 of the License, or * 00014 * (at your option) any later version. * 00015 * * 00016 ***************************************************************************/ 00017 00023 #if HAVE_CONFIG_H 00024 # include <config.h> 00025 #endif 00026 #include <cmath> 00027 #include <float.h> 00028 #if HAVE_IEEEFP_H 00029 # include <ieeefp.h> 00030 #endif 00031 00032 #include <QMessageBox> 00033 00034 #include "curvediagram.h" 00035 #include "main.h" 00036 #include "misc.h" 00037 00038 CurveDiagram::CurveDiagram(int _cx, int _cy) : Diagram(_cx, _cy) 00039 { 00040 x1 = 10; // position of label text 00041 y1 = y3 = 33; 00042 x2 = y2 = 200; // initial size of diagram 00043 x3 = 207; // with some distance for right axes text 00044 00045 Name = "Curve"; // BUG. 00046 calcDiagram(); 00047 } 00048 00049 CurveDiagram::~CurveDiagram() 00050 { 00051 } 00052 00053 // ------------------------------------------------------------ 00054 void CurveDiagram::calcCoordinate(const double*, const double* yD, const double*, 00055 float *px, float *py, Axis const *pa) const 00056 { 00057 double yr = yD[0]; 00058 double yi = yD[1]; 00059 if(xAxis.log) 00060 *px = float(log10(yr / xAxis.low)/log10(xAxis.up / xAxis.low) 00061 *double(x2)); 00062 else *px = float((yr-xAxis.low)/(xAxis.up-xAxis.low)*double(x2)); 00063 00064 if(pa->log) 00065 *py = float(log10(yi / pa->low)/log10(pa->up / pa->low) 00066 *double(y2)); 00067 else *py = float((yi-pa->low)/(pa->up-pa->low)*double(y2)); 00068 00069 if(std::isfinite(*px)) 00070 if(std::isfinite(*py)) 00071 return; 00072 00073 *px = *py = 0.0; 00074 } 00075 00076 // -------------------------------------------------------------- 00077 void CurveDiagram::finishMarkerCoordinates(float& fCX, float& fCY) const 00078 { 00079 if(!insideDiagram(fCX, fCY)) { 00080 fCX = fCY = 0.0; 00081 } 00082 } 00083 00084 // ------------------------------------------------------------ 00085 void CurveDiagram::calcLimits() 00086 { 00087 int i; 00088 double a, b, c; 00089 00090 if(xAxis.autoScale) {// check before, to preserve limit exchange (max < min) 00091 if(xAxis.log) { 00092 calcAxisLogScale(&xAxis, i, a, b, c, x2); 00093 xAxis.step = 1.0; 00094 } 00095 else calcAxisScale(&xAxis, a, b, c, xAxis.step, double(x2)); 00096 xAxis.limit_min = xAxis.low; 00097 xAxis.limit_max = xAxis.up; 00098 } 00099 00100 if(yAxis.autoScale) {// check before, to preserve limit exchange (max < min) 00101 if(yAxis.log) { 00102 calcAxisLogScale(&yAxis, i, a, b, c, y2); 00103 yAxis.step = 1.0; 00104 } 00105 else calcAxisScale(&yAxis, a, b, c, yAxis.step, double(y2)); 00106 yAxis.limit_min = yAxis.low; 00107 yAxis.limit_max = yAxis.up; 00108 } 00109 00110 if(zAxis.autoScale) {// check before, to preserve limit exchange (max < min) 00111 if(zAxis.log) { 00112 calcAxisLogScale(&zAxis, i, a, b, c, y2); 00113 zAxis.step = 1.0; 00114 } 00115 else calcAxisScale(&zAxis, a, b, c, zAxis.step, double(y2)); 00116 zAxis.limit_min = zAxis.low; 00117 zAxis.limit_max = zAxis.up; 00118 } 00119 } 00120 00121 // -------------------------------------------------------------- 00122 int CurveDiagram::calcDiagram() 00123 { 00124 Lines.clear(); 00125 Texts.clear(); 00126 Arcs.clear(); 00127 00128 double GridStep, corr, zD, zDstep, GridNum; 00129 // get size of text using the screen-compatible metric 00130 QFontMetrics metrics(QucsSettings.font, 0); 00131 y1 = QucsSettings.font.pointSize() + 6; 00132 00133 x1 = 10; // position of label text 00134 x3 = x2 + 7; 00135 QString tmp; 00136 bool back = false; 00137 int z, w, valid = 0; 00138 00139 // ===== give "step" the right sign (if user made it wrong) ============== 00140 xAxis.step = fabs(xAxis.step); 00141 if(xAxis.limit_min > xAxis.limit_max) 00142 xAxis.step *= -1.0; 00143 00144 yAxis.step = fabs(yAxis.step); 00145 if(yAxis.limit_min > yAxis.limit_max) 00146 yAxis.step *= -1.0; 00147 00148 zAxis.step = fabs(zAxis.step); 00149 if(zAxis.limit_min > zAxis.limit_max) 00150 zAxis.step *= -1.0; 00151 00152 00153 // ==== x grid ======================================================= 00154 if(xAxis.log) { 00155 if(xAxis.autoScale) { 00156 if(xAxis.max*xAxis.min <= 0.0) goto Frame; // invalid 00157 } 00158 else if(xAxis.limit_min*xAxis.limit_max <= 0.0) goto Frame; // invalid 00159 00160 back = calcAxisLogScale(&xAxis, z, zD, zDstep, corr, x2); 00161 00162 if(back) z = x2; 00163 while((z <= x2) && (z >= 0)) { // create all grid lines 00164 if(xAxis.GridOn) if(z < x2) if(z > 0) 00165 Lines.prepend(new Line(z, y2, z, 0, GridPen)); // x grid 00166 00167 if((zD < 1.5*zDstep) || (z == 0) || (z == x2)) { 00168 tmp = misc::StringNiceNum(zD); 00169 if(xAxis.up < 0.0) tmp = '-'+tmp; 00170 w = metrics.width(tmp); // width of text 00171 // center text horizontally under the x tick mark 00172 Texts.append(new Text(z-(w>>1), -y1, tmp)); 00173 Lines.append(new Line(z, 5, z, -5, QPen(Qt::black,0))); // x tick marks 00174 } 00175 00176 zD += zDstep; 00177 if(zD > 9.5*zDstep) zDstep *= 10.0; 00178 if(back) { 00179 z = int(corr*log10(zD / fabs(xAxis.up)) + 0.5); // int() implies floor() 00180 z = x2 - z; 00181 } 00182 else 00183 z = int(corr*log10(zD / fabs(xAxis.low)) + 0.5);// int() implies floor() 00184 } 00185 } 00186 else { // not logarithmical 00187 calcAxisScale(&xAxis, GridNum, zD, zDstep, GridStep, double(x2)); 00188 00189 double Expo; 00190 if(xAxis.up == 0.0) Expo = log10(fabs(xAxis.up-xAxis.low)); 00191 else Expo = log10(fabs(xAxis.up)); 00192 00193 zD += 0.5; // perform rounding 00194 z = int(zD); // "int(...)" implies "floor(...)" 00195 while((z <= x2) && (z >= 0)) { // create all grid lines 00196 if(fabs(GridNum) < 0.01*pow(10.0, Expo)) GridNum = 0.0;// make 0 really 0 00197 tmp = misc::StringNiceNum(GridNum); 00198 w = metrics.width(tmp); // width of text 00199 // center text horizontally under the x tick mark 00200 Texts.append(new Text(z-(w>>1), -y1, tmp)); // Text(x, y, str, ...) 00201 GridNum += GridStep; 00202 00203 if(xAxis.GridOn) if(z < x2) if(z > 0) 00204 Lines.prepend(new Line(z, y2, z, 0, GridPen)); // x grid 00205 Lines.append(new Line(z, 5, z, -5, QPen(Qt::black,0))); // x tick marks 00206 zD += zDstep; 00207 z = int(zD); 00208 } 00209 00210 if(xAxis.up >= 0.0) if(xAxis.low <= 0.0) { // paint origin cross ? 00211 z = int(double(x2) * fabs(xAxis.low / (xAxis.up-xAxis.low)) + 0.5); 00212 Lines.append(new Line(z, 0, z, y2, QPen(Qt::black,0))); 00213 } 00214 } // of "if(xlog) ... else ..." 00215 00216 00217 // ==== y grid ======================================================= 00218 if(zAxis.numGraphs > 0) if(calcYAxis(&zAxis, x2)) valid |= 2; 00219 if(yAxis.numGraphs > 0) if(calcYAxis(&yAxis, 0)) { 00220 valid |= 1; 00221 if(yAxis.up >= 0.0) if(yAxis.low <= 0.0) { // paint origin cross ? 00222 z = int(double(y2) * fabs(yAxis.low / (yAxis.up-yAxis.low)) + 0.5); 00223 Lines.append(new Line(0, z, x2, z, QPen(Qt::black,0))); 00224 } 00225 } 00226 00227 00228 Frame: 00229 // outer frame 00230 Lines.append(new Line(0, y2, x2, y2, QPen(Qt::black,0))); 00231 Lines.append(new Line(x2, y2, x2, 0, QPen(Qt::black,0))); 00232 Lines.append(new Line(0, 0, x2, 0, QPen(Qt::black,0))); 00233 Lines.append(new Line(0, y2, 0, 0, QPen(Qt::black,0))); 00234 return valid; 00235 } 00236 00237 // ------------------------------------------------------------ 00238 bool CurveDiagram::insideDiagram(float x, float y) const 00239 { 00240 return (regionCode(x, y) == 0); 00241 } 00242 00243 // ------------------------------------------------------------ 00244 void CurveDiagram::clip(Graph::iterator &p) const 00245 { 00246 rectClip(p); 00247 } 00248 00249 // ------------------------------------------------------------ 00250 Diagram* CurveDiagram::newOne() 00251 { 00252 return new CurveDiagram(); 00253 } 00254 00255 // ------------------------------------------------------------ 00256 Element* CurveDiagram::info(QString& Name, char* &BitmapFile, bool getNewOne) 00257 { 00258 Name = QObject::tr("Locus Curve"); 00259 BitmapFile = (char *) "curve"; 00260 00261 if(getNewOne) return new CurveDiagram(); 00262 return 0; 00263 }