[QGIS Commit] r10841 - trunk/qgis/src/app

svn_qgis at osgeo.org svn_qgis at osgeo.org
Sat May 23 11:42:24 EDT 2009


Author: wonder
Date: 2009-05-23 11:42:24 -0400 (Sat, 23 May 2009)
New Revision: 10841

Modified:
   trunk/qgis/src/app/qgsmaptoolsimplify.cpp
   trunk/qgis/src/app/qgsmaptoolsimplify.h
Log:
Fixed a crash when simplifying geometries with larger coordinates. By Richard Kostecky.


Modified: trunk/qgis/src/app/qgsmaptoolsimplify.cpp
===================================================================
--- trunk/qgis/src/app/qgsmaptoolsimplify.cpp	2009-05-23 09:20:42 UTC (rev 10840)
+++ trunk/qgis/src/app/qgsmaptoolsimplify.cpp	2009-05-23 15:42:24 UTC (rev 10841)
@@ -49,11 +49,12 @@
 
 void QgsSimplifyDialog::setRange(int minValue, int maxValue)
 {
-  horizontalSlider->setMinimum(minValue);
+  // let's have 20 page steps
+  horizontalSlider->setPageStep( (maxValue - minValue) / 20 );
+
+  horizontalSlider->setMinimum(minValue -1);// -1 for count with minimum tolerance end caused by double imprecision
   horizontalSlider->setMaximum(maxValue);
 
-  // let's have 20 page steps
-  horizontalSlider->setPageStep( (maxValue - minValue) / 20 );
 }
 
 
@@ -82,14 +83,18 @@
 
   // create a copy of selected feature and do the simplification
   QgsFeature f = mSelectedFeature;
-  if ( mSelectedFeature.geometry()->type() == QGis::Line )
+  //QgsSimplifyFeature::simplifyLine(f, mTolerance);
+  if (mTolerance > 0)
   {
-    QgsSimplifyFeature::simplifyLine(f, mTolerance);
+    if ( mSelectedFeature.geometry()->type() == QGis::Line )
+    {
+      QgsSimplifyFeature::simplifyLine(f, mTolerance);
+    }
+    else
+    {
+      QgsSimplifyFeature::simplifyPolygon(f, mTolerance);
+    }
   }
-  else
-  {
-    QgsSimplifyFeature::simplifyPolygon(f, mTolerance);
-  }
   mRubberBand->setToGeometry(f.geometry(), false);
 }
 
@@ -111,15 +116,29 @@
   mCanvas->refresh();
 }
 
-int QgsMapToolSimplify::calculateDivider(double num)
+int QgsMapToolSimplify::calculateDivider(double minimum, double maximum)
 {
-  double tmp = num;
+  double tmp = minimum;
   long i = 1;
+  if (minimum == 0)
+  { //exception if min = 0 than divider must be counted from maximum
+    tmp = maximum;
+  }
+  //count divider in such way so it can be used as whole number
   while (tmp < 1) 
   {
     tmp = tmp*10;
     i = i *10;
   }
+  if (minimum == 0)
+  { //special case that minimum is 0 to have more than 1 step
+    i = i*100000;
+  }
+//taking care of problem when multiplication would overflow maxint
+  while (int(i * maximum) < 0)
+  {
+    i = i/10;
+  }
   return i;
 }
 
@@ -127,7 +146,7 @@
 {
   double minTolerance, maxTolerance;
 
-  double tol = 0.0000001;
+  double tol = 0.000001;
   bool found = false;
   bool isLine = mSelectedFeature.geometry()->type() == QGis::Line;
   QVector<QgsPoint> pts = getPointList(mSelectedFeature);
@@ -137,14 +156,35 @@
     return false;
   }
 
-  // calculate min
+  // calculate minimum tolerance where no vertex is excluded
+  bool maximized = false;
+  int count = 0;
   while (!found)
   {
+    count++;
+    if (count == 30 && !maximized)
+    { //special case when tolerance is tool low to be correct so it's similat to 0
+      // else in some special cases this algorithm would create infinite loop
+      found = true;
+      minTolerance = 0;
+    }
+
     if (QgsSimplifyFeature::simplifyPoints(pts, tol).size() < size)
-    {
-      found = true;
-      minTolerance = tol/ 2;
-    } else {
+    { //some vertexes were already excluded
+      if (maximized) //if we were already in second direction end
+      {
+        found = true;
+        minTolerance = tol/ 2;
+      }
+      else //only lowering tolerance till it's low enough to have all vertexes
+      {
+        tol = tol/2;
+      }
+    }
+    else
+    { // simplified feature has all vertexes therefore no need we need higher tolerance also ending flag set
+      // when some tolerance will exclude some of vertexes
+      maximized = true;
       tol = tol * 2;
     }
   }
@@ -152,25 +192,26 @@
   int requiredCnt = (isLine ? 2 : 4); //4 for polygon is correct because first and last points are the same
   bool bottomFound = false;
   double highTol, lowTol;// two boundaries to be used when no directly correct solution is found
-  // calculate max
+  // calculate minimum tolerance where minimum (requiredCnt) of vertexes are left in geometry
   while (!found)
   {
 
     int foundVertexes = QgsSimplifyFeature::simplifyPoints(pts, tol).size();
     if (foundVertexes < requiredCnt + 1)
-    {
+    { //requred or lower number of verticies found
       if (foundVertexes == requiredCnt)
       {
         found = true;
         maxTolerance = tol;
       }
       else
-      {
+      { //solving problem that polygon would have less than minimum alowed vertexes
         bottomFound = true;
         highTol = tol;
         tol = (highTol + lowTol) /2;
         if (highTol/lowTol < 1.00000001)
-        {
+        { //solving problem that two points are in same distance from  line, so they will be both excluded at same time
+          //so some time more than required count of vertices can stay
           found = true;
           maxTolerance = lowTol;
         }
@@ -181,19 +222,20 @@
         lowTol = tol;
         tol = (highTol + lowTol) /2;
         if (highTol/lowTol < 1.00000001)
-        {
+        { //solving problem that two points are in same distance from  line, so they will be both excluded at same time
+          //so some time more than required count of vertices can stay
           found = true;
           maxTolerance = lowTol;
         }
       }
       else
-      {
+      { //still too much verticies left so we need to increase tolerance
         lowTol = tol;
         tol = tol * 2;
       }
     }
   }
-  toleranceDivider = calculateDivider(minTolerance);
+  toleranceDivider = calculateDivider(minTolerance, maxTolerance);
   // set min and max
   mSimplifyDialog->setRange( int(minTolerance * toleranceDivider),
                              int(maxTolerance * toleranceDivider) );

Modified: trunk/qgis/src/app/qgsmaptoolsimplify.h
===================================================================
--- trunk/qgis/src/app/qgsmaptoolsimplify.h	2009-05-23 09:20:42 UTC (rev 10840)
+++ trunk/qgis/src/app/qgsmaptoolsimplify.h	2009-05-23 15:42:24 UTC (rev 10841)
@@ -71,7 +71,7 @@
 
 private:
   /** Divider calculation, because slider can go only by whole numbers */
-  int calculateDivider(double num);
+  int calculateDivider(double minimum, double maximum);
 
   /** Function to calculate tolerance boudaries for simplifying */
   bool calculateSliderBoudaries();
@@ -90,7 +90,7 @@
   QgsFeature mSelectedFeature;
 
   /** tolerance divider is value which tells with which delete value from sidebar */
-  int toleranceDivider;
+  long toleranceDivider;
 
   /** real value of tolerance */
   double mTolerance;



More information about the QGIS-commit mailing list