00001 #include "DocumentModelCoords.h"
00002 #include "EngaugeAssert.h"
00003 #include "GridInitializer.h"
00004 #include "Logger.h"
00005 #include <math.h>
00006 #include <qmath.h>
00007 #include "Transformation.h"
00008
00009 GridInitializer::GridInitializer ()
00010 {
00011 }
00012
00013 void GridInitializer::axisScale (double xMin,
00014 double xMax,
00015 bool linearAxis,
00016 double &xStart,
00017 double &xStop,
00018 double &xDelta,
00019 int &xCount) const
00020 {
00021 const double range_epsilon = 0.00000000001;
00022 double xAverage, xAverageRoundedUp, xRange;
00023 int nDigitRange;
00024
00025
00026
00027
00028
00029 const int nDigitsPrecision = 8;
00030
00031
00032 if (xMin > xMax) {
00033 double xTemp = xMin;
00034 xMin = xMax;
00035 xMax = xTemp;
00036 }
00037
00038
00039 if (!linearAxis) {
00040 ENGAUGE_ASSERT(xMin > 0);
00041 ENGAUGE_ASSERT(xMax > 0);
00042 xMin = log10(xMin);
00043 xMax = log10(xMax);
00044 }
00045
00046
00047 xAverage = (xMin + xMax) / 2.0;
00048 xRange = xMax - xMin;
00049 if (xRange == 0) {
00050 xRange = fabs (xAverage / 10.0);
00051 }
00052 nDigitRange = valuePower (xRange);
00053 xDelta = pow ((double) 10.0, (double) nDigitRange);
00054 xAverageRoundedUp = xDelta * floor ((xAverage + xDelta / 2.0) / xDelta);
00055
00056 if (xRange > range_epsilon) {
00057
00058 while (fabs (xRange / xDelta) <= 2.000001) {
00059 xDelta /= 2.0;
00060 }
00061 }
00062
00063
00064 xStart = xAverageRoundedUp;
00065 while (xStart > xMin) {
00066 xStart -= xDelta;
00067 }
00068
00069
00070 xStop = xAverageRoundedUp;
00071 while (xStop < xMax) {
00072 xStop += xDelta;
00073 }
00074
00075 xCount = 1 + (int) floor ((xStop - xStart) / xDelta + 0.5);
00076
00077 if (!linearAxis) {
00078
00079
00080 xStart = pow((double) 10.0, xStart);
00081 xStop = pow((double) 10.0, xStop);
00082 xDelta = pow((double) 10.0, xDelta);
00083
00084 } else {
00085
00086
00087 int power = valuePower (xDelta) - nDigitsPrecision;
00088 xStart = roundOffToPower(xStart, power);
00089 xStop = roundOffToPower(xStop, power);
00090 xDelta = roundOffToPower(xDelta, power);
00091
00092 }
00093 }
00094
00095 int GridInitializer::computeCount (bool linearAxis,
00096 double start,
00097 double stop,
00098 double step) const
00099 {
00100 int count;
00101
00102 if (linearAxis) {
00103 if (step == 0) {
00104 count = 1;
00105 } else {
00106 count = (int) (1.0 + (stop - start) / step);
00107 }
00108 } else {
00109 if ((start <= 0) || (step <= 0.0)) {
00110 count = 1;
00111 } else {
00112 count = (int) (1.0 + log10 (stop / start) / log10 (step));
00113 }
00114 }
00115
00116 return count;
00117 }
00118
00119 double GridInitializer::computeStart (bool linearAxis,
00120 double stop,
00121 double step,
00122 int count) const
00123 {
00124 double start;
00125
00126 if (linearAxis) {
00127 start = stop - step * (count - 1);
00128 } else {
00129 start = stop / pow (step, (double) (count - 1));
00130 }
00131
00132 return start;
00133 }
00134
00135 double GridInitializer::computeStep (bool linearAxis,
00136 double start,
00137 double stop,
00138 int count) const
00139 {
00140 double step;
00141
00142 if (linearAxis) {
00143 if (count > 1) {
00144 step = (stop - start) / (count - 1);
00145 } else {
00146 step = stop - start;
00147 }
00148 } else {
00149 if (start <= 0.0) {
00150 step = 1.0;
00151 } else {
00152 if (count > 1) {
00153 step = pow (stop / start, (double) 1.0 / (count - 1));
00154 } else {
00155 step = stop / start;
00156 }
00157 }
00158 }
00159
00160 return step;
00161 }
00162
00163 double GridInitializer::computeStop (bool linearAxis,
00164 double start,
00165 double step,
00166 int count) const
00167 {
00168 double stop;
00169
00170 if (linearAxis) {
00171 stop = start + step * (count - 1);
00172 } else {
00173 stop = start * pow (step, (double) (count - 1));
00174 }
00175
00176 return stop;
00177 }
00178
00179 DocumentModelGridDisplay GridInitializer::initializeWithNarrowCoverage (const QRectF &boundingRectGraph,
00180 const DocumentModelCoords &modelCoords) const
00181 {
00182 LOG4CPP_INFO_S ((*mainCat)) << "GridInitializer::initializeWithNarrowCoverage";
00183
00184 DocumentModelGridDisplay modelGridDisplay;
00185
00186 int count;
00187 double start, stop, step;
00188
00189
00190 axisScale (boundingRectGraph.x(),
00191 boundingRectGraph.x() + boundingRectGraph.width(),
00192 (modelCoords.coordScaleXTheta() == COORD_SCALE_LINEAR),
00193 start,
00194 stop,
00195 step,
00196 count);
00197
00198 modelGridDisplay.setDisableX (GRID_COORD_DISABLE_COUNT);
00199 modelGridDisplay.setCountX (count);
00200 modelGridDisplay.setStartX (start);
00201 modelGridDisplay.setStepX (step);
00202 modelGridDisplay.setStopX (stop);
00203
00204
00205 axisScale (boundingRectGraph.y(),
00206 boundingRectGraph.y() + boundingRectGraph.height(),
00207 (modelCoords.coordScaleYRadius() == COORD_SCALE_LINEAR),
00208 start,
00209 stop,
00210 step,
00211 count);
00212
00213 modelGridDisplay.setDisableY (GRID_COORD_DISABLE_COUNT);
00214 modelGridDisplay.setCountY (count);
00215 modelGridDisplay.setStartY (start);
00216 modelGridDisplay.setStepY (step);
00217 modelGridDisplay.setStopY (stop);
00218
00219 modelGridDisplay.setStable (true);
00220
00221 return modelGridDisplay;
00222 }
00223
00224 DocumentModelGridDisplay GridInitializer::initializeWithWidePolarCoverage (const QRectF &boundingRectGraph,
00225 const DocumentModelCoords &modelCoords,
00226 const Transformation &transformation,
00227 const QSize &imageSize) const
00228 {
00229 LOG4CPP_INFO_S ((*mainCat)) << "GridInitializer::initializeWithWidePolarCoverage";
00230
00231 DocumentModelGridDisplay modelGridDisplay = initializeWithNarrowCoverage (boundingRectGraph,
00232 modelCoords);
00233
00234 if (modelCoords.coordsType() == COORDS_TYPE_POLAR) {
00235
00236 overridePolarCoordinateSettings (modelCoords,
00237 transformation,
00238 modelGridDisplay,
00239 imageSize);
00240 }
00241
00242 return modelGridDisplay;
00243 }
00244
00245 void GridInitializer::overridePolarCoordinateSettings (const DocumentModelCoords &modelCoords,
00246 const Transformation &transformation,
00247 DocumentModelGridDisplay &modelGridDisplay,
00248 const QSize &imageSize) const
00249 {
00250 ENGAUGE_ASSERT (modelCoords.coordsType() == COORDS_TYPE_POLAR);
00251
00252
00253
00254 double startX = 0.0;
00255 double stopX = 360.0;
00256 double stepX = 30.0;
00257 int countX = (int) (0.5 + (stopX - startX) / stepX);
00258 modelGridDisplay.setStartX (startX);
00259 modelGridDisplay.setStepX (stepX);
00260 modelGridDisplay.setStopX (stopX);
00261 modelGridDisplay.setCountX (countX);
00262
00263
00264
00265 QPointF posTL, posBL, posTR, posBR;
00266 transformation.transformScreenToRawGraph (QPointF (0 , imageSize.height ()), posTL);
00267 transformation.transformScreenToRawGraph (QPointF (0 , 0 ), posBL);
00268 transformation.transformScreenToRawGraph (QPointF (imageSize.width (), imageSize.height ()), posTR);
00269 transformation.transformScreenToRawGraph (QPointF (imageSize.width (), 0 ), posBR);
00270
00271 double radiusTL = qSqrt (posTL.x () * posTL.x () + posTL.y () * posTL.y ());
00272 double radiusBL = qSqrt (posBL.x () * posBL.x () + posBL.y () * posBL.y ());
00273 double radiusTR = qSqrt (posTR.x () * posTR.x () + posTR.y () * posTR.y ());
00274 double radiusBR = qSqrt (posBR.x () * posBR.x () + posBR.y () * posBR.y ());
00275
00276 double radius = qMax (qMax (qMax (radiusTL, radiusBL), radiusTR), radiusBR);
00277
00278 double startY = (modelCoords.coordScaleYRadius() == COORD_SCALE_LINEAR ?
00279 0.0 :
00280 modelCoords.originRadius());
00281 double stopY = radius;
00282 double stepY = modelGridDisplay.stepY ();
00283 int countY = (modelCoords.coordScaleYRadius() == COORD_SCALE_LINEAR ?
00284 (int) (0.5 + (stopY - startY) / stepY) :
00285 (int) (0.5 + (qLn (stopY) - qLn (startY)) / qLn (stepY)));
00286
00287 modelGridDisplay.setStartY (startY);
00288 modelGridDisplay.setStopY (stopY);
00289 modelGridDisplay.setCountY (countY);
00290 }
00291
00292 double GridInitializer::roundOffToPower(double arg,
00293 int power) const
00294 {
00295 double powerOf10 = pow ((double) 10, power);
00296 return powerOf10 * floor (arg / powerOf10 + 0.5);
00297 }
00298
00299 int GridInitializer::valuePower(double value) const
00300 {
00301 const int minPower = -30;
00302
00303 double avalue = fabs(value);
00304 if (avalue < pow(10.0, minPower)) {
00305 return minPower;
00306 } else {
00307 return (int) floor (log10 (avalue));
00308 }
00309 }