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