Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Fixed a crash when simplifying geometries with larger coordinates. By…
… Richard Kostecky.

git-svn-id: http://svn.osgeo.org/qgis/trunk@10841 c8812cc2-4d05-0410-92ff-de0c093fc19c
  • Loading branch information
wonder committed May 23, 2009
1 parent 1e6882a commit 3c267ee
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 26 deletions.
90 changes: 66 additions & 24 deletions src/app/qgsmaptoolsimplify.cpp
Expand Up @@ -49,11 +49,12 @@ void QgsSimplifyDialog::simplify()

void QgsSimplifyDialog::setRange(int minValue, int maxValue)
{
horizontalSlider->setMinimum(minValue);
horizontalSlider->setMaximum(maxValue);

// 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);

}


Expand Down Expand Up @@ -82,13 +83,17 @@ void QgsMapToolSimplify::toleranceChanged(int tolerance)

// create a copy of selected feature and do the simplification
QgsFeature f = mSelectedFeature;
if ( mSelectedFeature.geometry()->type() == QGis::Line )
{
QgsSimplifyFeature::simplifyLine(f, mTolerance);
}
else
//QgsSimplifyFeature::simplifyLine(f, mTolerance);
if (mTolerance > 0)
{
QgsSimplifyFeature::simplifyPolygon(f, mTolerance);
if ( mSelectedFeature.geometry()->type() == QGis::Line )
{
QgsSimplifyFeature::simplifyLine(f, mTolerance);
}
else
{
QgsSimplifyFeature::simplifyPolygon(f, mTolerance);
}
}
mRubberBand->setToGeometry(f.geometry(), false);
}
Expand All @@ -111,23 +116,37 @@ void QgsMapToolSimplify::storeSimplified()
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;
}

bool QgsMapToolSimplify::calculateSliderBoudaries()
{
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);
Expand All @@ -137,40 +156,62 @@ bool QgsMapToolSimplify::calculateSliderBoudaries()
return false;
}

// calculate min
// calculate minimum tolerance where no vertex is excluded
bool maximized = false;
int count = 0;
while (!found)
{
if (QgsSimplifyFeature::simplifyPoints(pts, tol).size() < size)
{
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 = tol/ 2;
} else {
minTolerance = 0;
}

if (QgsSimplifyFeature::simplifyPoints(pts, tol).size() < size)
{ //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;
}
}
found = false;
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;
}
Expand All @@ -181,19 +222,20 @@ bool QgsMapToolSimplify::calculateSliderBoudaries()
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) );
Expand Down
4 changes: 2 additions & 2 deletions src/app/qgsmaptoolsimplify.h
Expand Up @@ -71,7 +71,7 @@ public slots:

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();
Expand All @@ -90,7 +90,7 @@ public slots:
QgsFeature mSelectedFeature;

/** tolerance divider is value which tells with which delete value from sidebar */
int toleranceDivider;
long toleranceDivider;

/** real value of tolerance */
double mTolerance;
Expand Down

0 comments on commit 3c267ee

Please sign in to comment.