22
22
#include " qgstolerance.h"
23
23
24
24
#include < QMouseEvent>
25
+ #include < QMessageBox>
25
26
26
27
#include < math.h>
27
28
@@ -81,15 +82,29 @@ void QgsMapToolSimplify::toleranceChanged(int tolerance)
81
82
82
83
// create a copy of selected feature and do the simplification
83
84
QgsFeature f = mSelectedFeature ;
84
- QgsSimplifyFeature::simplifyLine (f, mTolerance );
85
+ if ( mSelectedFeature .geometry ()->type () == QGis::Line )
86
+ {
87
+ QgsSimplifyFeature::simplifyLine (f, mTolerance );
88
+ }
89
+ else
90
+ {
91
+ QgsSimplifyFeature::simplifyPolygon (f, mTolerance );
92
+ }
85
93
mRubberBand ->setToGeometry (f.geometry (), false );
86
94
}
87
95
88
96
89
97
void QgsMapToolSimplify::storeSimplified ()
90
98
{
91
99
QgsVectorLayer * vlayer = currentVectorLayer ();
92
- QgsSimplifyFeature::simplifyLine (mSelectedFeature , mTolerance );
100
+ if ( mSelectedFeature .geometry ()->type () == QGis::Line )
101
+ {
102
+ QgsSimplifyFeature::simplifyLine (mSelectedFeature , mTolerance );
103
+ }
104
+ else
105
+ {
106
+ QgsSimplifyFeature::simplifyPolygon (mSelectedFeature , mTolerance );
107
+ }
93
108
94
109
vlayer->changeGeometry ( mSelectedFeature .id (), mSelectedFeature .geometry () );
95
110
@@ -99,7 +114,7 @@ void QgsMapToolSimplify::storeSimplified()
99
114
int QgsMapToolSimplify::calculateDivider (double num)
100
115
{
101
116
double tmp = num;
102
- int i = 1 ;
117
+ long i = 1 ;
103
118
while (tmp < 1 )
104
119
{
105
120
tmp = tmp*10 ;
@@ -108,7 +123,7 @@ int QgsMapToolSimplify::calculateDivider(double num)
108
123
return i;
109
124
}
110
125
111
- void QgsMapToolSimplify::calculateSliderBoudaries ()
126
+ bool QgsMapToolSimplify::calculateSliderBoudaries ()
112
127
{
113
128
double minTolerance, maxTolerance;
114
129
@@ -117,9 +132,9 @@ void QgsMapToolSimplify::calculateSliderBoudaries()
117
132
bool isLine = mSelectedFeature .geometry ()->type () == QGis::Line;
118
133
QVector<QgsPoint> pts = getPointList (mSelectedFeature );
119
134
int size = pts.size ();
120
- if (size == 0 || (isLine && size < 2 ) || (!isLine && size < 3 ) )
135
+ if (size == 0 || (isLine && size < 2 ) || (!isLine && size < 4 ) )
121
136
{
122
- return ;
137
+ return false ;
123
138
}
124
139
125
140
// calculate min
@@ -128,30 +143,61 @@ void QgsMapToolSimplify::calculateSliderBoudaries()
128
143
if (QgsSimplifyFeature::simplifyPoints (pts, tol).size () < size)
129
144
{
130
145
found = true ;
131
- minTolerance = tol/2 ;
146
+ minTolerance = tol/ 2 ;
132
147
} else {
133
148
tol = tol * 2 ;
134
149
}
135
150
}
136
-
137
151
found = false ;
138
- int requiredCnt = (isLine ? 2 : 3 );
152
+ int requiredCnt = (isLine ? 2 : 4 ); // 4 for polygon is correct because first and last points are the same
153
+ bool bottomFound = false ;
154
+ double highTol, lowTol;// two boundaries to be used when no directly correct solution is found
139
155
// calculate max
140
156
while (!found)
141
157
{
142
- if (QgsSimplifyFeature::simplifyPoints (pts, tol).size () < requiredCnt + 1 )
158
+
159
+ int foundVertexes = QgsSimplifyFeature::simplifyPoints (pts, tol).size ();
160
+ if (foundVertexes < requiredCnt + 1 )
143
161
{
144
- // TODO: fix for polygon
145
- found = true ;
146
- maxTolerance = tol;
162
+ if (foundVertexes == requiredCnt)
163
+ {
164
+ found = true ;
165
+ maxTolerance = tol;
166
+ }
167
+ else
168
+ {
169
+ bottomFound = true ;
170
+ highTol = tol;
171
+ tol = (highTol + lowTol) /2 ;
172
+ if (highTol/lowTol < 1.00000001 )
173
+ {
174
+ found = true ;
175
+ maxTolerance = lowTol;
176
+ }
177
+ }
147
178
} else {
148
- tol = tol * 2 ;
179
+ if (bottomFound)
180
+ {
181
+ lowTol = tol;
182
+ tol = (highTol + lowTol) /2 ;
183
+ if (highTol/lowTol < 1.00000001 )
184
+ {
185
+ found = true ;
186
+ maxTolerance = lowTol;
187
+ }
188
+ }
189
+ else
190
+ {
191
+ lowTol = tol;
192
+ tol = tol * 2 ;
193
+ }
149
194
}
150
195
}
151
196
toleranceDivider = calculateDivider (minTolerance);
152
197
// set min and max
153
198
mSimplifyDialog ->setRange ( int (minTolerance * toleranceDivider),
154
199
int (maxTolerance * toleranceDivider) );
200
+ return true ;
155
201
}
156
202
157
203
@@ -181,7 +227,11 @@ void QgsMapToolSimplify::canvasPressEvent( QMouseEvent * e )
181
227
mSelectedFeature = f;
182
228
}
183
229
}
184
-
230
+ if (mSelectedFeature .geometry ()->isMultipart ())
231
+ {
232
+ QMessageBox::critical ( 0 , tr ( " Unsupported operation" ), tr ( " Multipart features are not supported for simplification." ) );
233
+ return ;
234
+ }
185
235
// delete previous rubberband (if any)
186
236
removeRubberBand ();
187
237
@@ -193,10 +243,11 @@ void QgsMapToolSimplify::canvasPressEvent( QMouseEvent * e )
193
243
mRubberBand ->setWidth (2 );
194
244
mRubberBand ->show ();
195
245
// calculate boudaries for slidebar
196
- calculateSliderBoudaries ();
197
-
198
- // show dialog as a non-modal window
199
- mSimplifyDialog ->show ();
246
+ if (calculateSliderBoudaries ())
247
+ {
248
+ // show dialog as a non-modal window
249
+ mSimplifyDialog ->show ();
250
+ }
200
251
}
201
252
}
202
253
@@ -234,13 +285,10 @@ QVector<QgsPoint> QgsMapToolSimplify::getPointList(QgsFeature& f)
234
285
}
235
286
return line->asPolygon ()[0 ];
236
287
}
237
-
238
288
}
239
289
240
290
241
291
242
-
243
-
244
292
bool QgsSimplifyFeature::simplifyLine (QgsFeature& lineFeature, double tolerance)
245
293
{
246
294
QgsGeometry* line = lineFeature.geometry ();
@@ -254,23 +302,22 @@ bool QgsSimplifyFeature::simplifyLine(QgsFeature& lineFeature, double tolerance
254
302
return TRUE ;
255
303
}
256
304
257
-
258
- // TODO: change to correct structure after
259
- bool QgsSimplifyFeature::simplifyPartOfLine (QgsFeature& lineFeature, int fromVertexNr, int toVertexNr, double tolerance)
305
+ bool QgsSimplifyFeature::simplifyPolygon (QgsFeature& polygonFeature, double tolerance)
260
306
{
261
- QgsGeometry* line = lineFeature .geometry ();
262
- if (line ->type () != QGis::Line )
307
+ QgsGeometry* polygon = polygonFeature .geometry ();
308
+ if (polygon ->type () != QGis::Polygon )
263
309
{
264
310
return FALSE ;
265
311
}
266
-
267
- QVector<QgsPoint> resultPoints = simplifyPoints (line->asPolyline (), tolerance);
268
- lineFeature.setGeometry ( QgsGeometry::fromPolyline ( resultPoints ) );
312
+ QVector<QgsPoint> resultPoints = simplifyPoints (polygon->asPolygon ()[0 ], tolerance);
313
+ // resultPoints.push_back(resultPoints[0]);
314
+ QVector<QgsPolyline> poly;
315
+ poly.append (resultPoints);
316
+ polygonFeature.setGeometry ( QgsGeometry::fromPolygon ( poly ) );
269
317
return TRUE ;
270
318
}
271
319
272
320
273
-
274
321
QVector<QgsPoint> QgsSimplifyFeature::simplifyPoints (const QVector<QgsPoint>& pts, double tolerance)
275
322
{
276
323
// Douglas-Peucker simplification algorithm
0 commit comments