Skip to content

Commit c4ac7f4

Browse files
author
wonder
committedMay 23, 2009
Fixed a crash when simplifying geometries with larger coordinates. By Richard Kostecky.
git-svn-id: http://svn.osgeo.org/qgis/trunk/qgis@10841 c8812cc2-4d05-0410-92ff-de0c093fc19c

File tree

2 files changed

+68
-26
lines changed

2 files changed

+68
-26
lines changed
 

‎src/app/qgsmaptoolsimplify.cpp

Lines changed: 66 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,12 @@ void QgsSimplifyDialog::simplify()
4949

5050
void QgsSimplifyDialog::setRange(int minValue, int maxValue)
5151
{
52-
horizontalSlider->setMinimum(minValue);
53-
horizontalSlider->setMaximum(maxValue);
54-
5552
// let's have 20 page steps
5653
horizontalSlider->setPageStep( (maxValue - minValue) / 20 );
54+
55+
horizontalSlider->setMinimum(minValue -1);// -1 for count with minimum tolerance end caused by double imprecision
56+
horizontalSlider->setMaximum(maxValue);
57+
5758
}
5859

5960

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

8384
// create a copy of selected feature and do the simplification
8485
QgsFeature f = mSelectedFeature;
85-
if ( mSelectedFeature.geometry()->type() == QGis::Line )
86-
{
87-
QgsSimplifyFeature::simplifyLine(f, mTolerance);
88-
}
89-
else
86+
//QgsSimplifyFeature::simplifyLine(f, mTolerance);
87+
if (mTolerance > 0)
9088
{
91-
QgsSimplifyFeature::simplifyPolygon(f, mTolerance);
89+
if ( mSelectedFeature.geometry()->type() == QGis::Line )
90+
{
91+
QgsSimplifyFeature::simplifyLine(f, mTolerance);
92+
}
93+
else
94+
{
95+
QgsSimplifyFeature::simplifyPolygon(f, mTolerance);
96+
}
9297
}
9398
mRubberBand->setToGeometry(f.geometry(), false);
9499
}
@@ -111,23 +116,37 @@ void QgsMapToolSimplify::storeSimplified()
111116
mCanvas->refresh();
112117
}
113118

114-
int QgsMapToolSimplify::calculateDivider(double num)
119+
int QgsMapToolSimplify::calculateDivider(double minimum, double maximum)
115120
{
116-
double tmp = num;
121+
double tmp = minimum;
117122
long i = 1;
123+
if (minimum == 0)
124+
{ //exception if min = 0 than divider must be counted from maximum
125+
tmp = maximum;
126+
}
127+
//count divider in such way so it can be used as whole number
118128
while (tmp < 1)
119129
{
120130
tmp = tmp*10;
121131
i = i *10;
122132
}
133+
if (minimum == 0)
134+
{ //special case that minimum is 0 to have more than 1 step
135+
i = i*100000;
136+
}
137+
//taking care of problem when multiplication would overflow maxint
138+
while (int(i * maximum) < 0)
139+
{
140+
i = i/10;
141+
}
123142
return i;
124143
}
125144

126145
bool QgsMapToolSimplify::calculateSliderBoudaries()
127146
{
128147
double minTolerance, maxTolerance;
129148

130-
double tol = 0.0000001;
149+
double tol = 0.000001;
131150
bool found = false;
132151
bool isLine = mSelectedFeature.geometry()->type() == QGis::Line;
133152
QVector<QgsPoint> pts = getPointList(mSelectedFeature);
@@ -137,40 +156,62 @@ bool QgsMapToolSimplify::calculateSliderBoudaries()
137156
return false;
138157
}
139158

140-
// calculate min
159+
// calculate minimum tolerance where no vertex is excluded
160+
bool maximized = false;
161+
int count = 0;
141162
while (!found)
142163
{
143-
if (QgsSimplifyFeature::simplifyPoints(pts, tol).size() < size)
144-
{
164+
count++;
165+
if (count == 30 && !maximized)
166+
{ //special case when tolerance is tool low to be correct so it's similat to 0
167+
// else in some special cases this algorithm would create infinite loop
145168
found = true;
146-
minTolerance = tol/ 2;
147-
} else {
169+
minTolerance = 0;
170+
}
171+
172+
if (QgsSimplifyFeature::simplifyPoints(pts, tol).size() < size)
173+
{ //some vertexes were already excluded
174+
if (maximized) //if we were already in second direction end
175+
{
176+
found = true;
177+
minTolerance = tol/ 2;
178+
}
179+
else //only lowering tolerance till it's low enough to have all vertexes
180+
{
181+
tol = tol/2;
182+
}
183+
}
184+
else
185+
{ // simplified feature has all vertexes therefore no need we need higher tolerance also ending flag set
186+
// when some tolerance will exclude some of vertexes
187+
maximized = true;
148188
tol = tol * 2;
149189
}
150190
}
151191
found = false;
152192
int requiredCnt = (isLine ? 2 : 4); //4 for polygon is correct because first and last points are the same
153193
bool bottomFound = false;
154194
double highTol, lowTol;// two boundaries to be used when no directly correct solution is found
155-
// calculate max
195+
// calculate minimum tolerance where minimum (requiredCnt) of vertexes are left in geometry
156196
while (!found)
157197
{
158198

159199
int foundVertexes = QgsSimplifyFeature::simplifyPoints(pts, tol).size();
160200
if (foundVertexes < requiredCnt + 1)
161-
{
201+
{ //requred or lower number of verticies found
162202
if (foundVertexes == requiredCnt)
163203
{
164204
found = true;
165205
maxTolerance = tol;
166206
}
167207
else
168-
{
208+
{ //solving problem that polygon would have less than minimum alowed vertexes
169209
bottomFound = true;
170210
highTol = tol;
171211
tol = (highTol + lowTol) /2;
172212
if (highTol/lowTol < 1.00000001)
173-
{
213+
{ //solving problem that two points are in same distance from line, so they will be both excluded at same time
214+
//so some time more than required count of vertices can stay
174215
found = true;
175216
maxTolerance = lowTol;
176217
}
@@ -181,19 +222,20 @@ bool QgsMapToolSimplify::calculateSliderBoudaries()
181222
lowTol = tol;
182223
tol = (highTol + lowTol) /2;
183224
if (highTol/lowTol < 1.00000001)
184-
{
225+
{ //solving problem that two points are in same distance from line, so they will be both excluded at same time
226+
//so some time more than required count of vertices can stay
185227
found = true;
186228
maxTolerance = lowTol;
187229
}
188230
}
189231
else
190-
{
232+
{ //still too much verticies left so we need to increase tolerance
191233
lowTol = tol;
192234
tol = tol * 2;
193235
}
194236
}
195237
}
196-
toleranceDivider = calculateDivider(minTolerance);
238+
toleranceDivider = calculateDivider(minTolerance, maxTolerance);
197239
// set min and max
198240
mSimplifyDialog->setRange( int(minTolerance * toleranceDivider),
199241
int(maxTolerance * toleranceDivider) );

‎src/app/qgsmaptoolsimplify.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public slots:
7171

7272
private:
7373
/** Divider calculation, because slider can go only by whole numbers */
74-
int calculateDivider(double num);
74+
int calculateDivider(double minimum, double maximum);
7575

7676
/** Function to calculate tolerance boudaries for simplifying */
7777
bool calculateSliderBoudaries();
@@ -90,7 +90,7 @@ public slots:
9090
QgsFeature mSelectedFeature;
9191

9292
/** tolerance divider is value which tells with which delete value from sidebar */
93-
int toleranceDivider;
93+
long toleranceDivider;
9494

9595
/** real value of tolerance */
9696
double mTolerance;

0 commit comments

Comments
 (0)
Please sign in to comment.