@@ -49,11 +49,12 @@ void QgsSimplifyDialog::simplify()
49
49
50
50
void QgsSimplifyDialog::setRange (int minValue, int maxValue)
51
51
{
52
- horizontalSlider->setMinimum (minValue);
53
- horizontalSlider->setMaximum (maxValue);
54
-
55
52
// let's have 20 page steps
56
53
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
+
57
58
}
58
59
59
60
@@ -82,13 +83,17 @@ void QgsMapToolSimplify::toleranceChanged(int tolerance)
82
83
83
84
// create a copy of selected feature and do the simplification
84
85
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 )
90
88
{
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
+ }
92
97
}
93
98
mRubberBand ->setToGeometry (f.geometry (), false );
94
99
}
@@ -111,23 +116,37 @@ void QgsMapToolSimplify::storeSimplified()
111
116
mCanvas ->refresh ();
112
117
}
113
118
114
- int QgsMapToolSimplify::calculateDivider (double num )
119
+ int QgsMapToolSimplify::calculateDivider (double minimum, double maximum )
115
120
{
116
- double tmp = num ;
121
+ double tmp = minimum ;
117
122
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
118
128
while (tmp < 1 )
119
129
{
120
130
tmp = tmp*10 ;
121
131
i = i *10 ;
122
132
}
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
+ }
123
142
return i;
124
143
}
125
144
126
145
bool QgsMapToolSimplify::calculateSliderBoudaries ()
127
146
{
128
147
double minTolerance, maxTolerance;
129
148
130
- double tol = 0.0000001 ;
149
+ double tol = 0.000001 ;
131
150
bool found = false ;
132
151
bool isLine = mSelectedFeature .geometry ()->type () == QGis::Line;
133
152
QVector<QgsPoint> pts = getPointList (mSelectedFeature );
@@ -137,40 +156,62 @@ bool QgsMapToolSimplify::calculateSliderBoudaries()
137
156
return false ;
138
157
}
139
158
140
- // calculate min
159
+ // calculate minimum tolerance where no vertex is excluded
160
+ bool maximized = false ;
161
+ int count = 0 ;
141
162
while (!found)
142
163
{
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
145
168
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 ;
148
188
tol = tol * 2 ;
149
189
}
150
190
}
151
191
found = false ;
152
192
int requiredCnt = (isLine ? 2 : 4 ); // 4 for polygon is correct because first and last points are the same
153
193
bool bottomFound = false ;
154
194
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
156
196
while (!found)
157
197
{
158
198
159
199
int foundVertexes = QgsSimplifyFeature::simplifyPoints (pts, tol).size ();
160
200
if (foundVertexes < requiredCnt + 1 )
161
- {
201
+ { // requred or lower number of verticies found
162
202
if (foundVertexes == requiredCnt)
163
203
{
164
204
found = true ;
165
205
maxTolerance = tol;
166
206
}
167
207
else
168
- {
208
+ { // solving problem that polygon would have less than minimum alowed vertexes
169
209
bottomFound = true ;
170
210
highTol = tol;
171
211
tol = (highTol + lowTol) /2 ;
172
212
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
174
215
found = true ;
175
216
maxTolerance = lowTol;
176
217
}
@@ -181,19 +222,20 @@ bool QgsMapToolSimplify::calculateSliderBoudaries()
181
222
lowTol = tol;
182
223
tol = (highTol + lowTol) /2 ;
183
224
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
185
227
found = true ;
186
228
maxTolerance = lowTol;
187
229
}
188
230
}
189
231
else
190
- {
232
+ { // still too much verticies left so we need to increase tolerance
191
233
lowTol = tol;
192
234
tol = tol * 2 ;
193
235
}
194
236
}
195
237
}
196
- toleranceDivider = calculateDivider (minTolerance);
238
+ toleranceDivider = calculateDivider (minTolerance, maxTolerance );
197
239
// set min and max
198
240
mSimplifyDialog ->setRange ( int (minTolerance * toleranceDivider),
199
241
int (maxTolerance * toleranceDivider) );
0 commit comments