@@ -161,32 +161,98 @@ std::unique_ptr< QgsCompoundCurve > QgsArcGisRestUtils::convertCompoundCurve( co
161
161
{
162
162
// [[6,3],[5,3],{"b":[[3,2],[6,1],[2,4]]},[1,2],{"c": [[3,3],[1,4]]}]
163
163
std::unique_ptr< QgsCompoundCurve > compoundCurve = std::make_unique< QgsCompoundCurve >();
164
- std::unique_ptr< QgsLineString > lineString;
164
+
165
+ QVector< double > lineX;
166
+ QVector< double > lineY;
167
+ QVector< double > lineZ;
168
+ QVector< double > lineM;
169
+ int maxCurveListSize = curvesList.size ();
170
+ lineX.resize ( maxCurveListSize );
171
+ lineY.resize ( maxCurveListSize );
172
+
173
+ const bool hasZ = QgsWkbTypes::hasZ ( pointType );
174
+ if ( hasZ )
175
+ lineZ.resize ( maxCurveListSize );
176
+ const bool hasM = QgsWkbTypes::hasM ( pointType );
177
+ if ( hasM )
178
+ lineM.resize ( maxCurveListSize );
179
+
180
+ double *outLineX = lineX.data ();
181
+ double *outLineY = lineY.data ();
182
+ double *outLineZ = lineZ.data ();
183
+ double *outLineM = lineM.data ();
184
+ int actualLineSize = 0 ;
185
+
186
+ bool xok = false ;
187
+ bool yok = false ;
188
+
189
+ int curveListIndex = 0 ;
165
190
for ( const QVariant &curveData : curvesList )
166
191
{
167
192
if ( curveData.type () == QVariant::List )
168
193
{
169
- std::unique_ptr< QgsPoint > point ( convertPoint ( curveData.toList (), pointType ) );
170
- if ( !point )
171
- {
194
+ const QVariantList coordList = curveData.toList ();
195
+ const int nCoords = coordList.size ();
196
+ if ( nCoords < 2 )
197
+ return nullptr ;
198
+
199
+ const double x = coordList[0 ].toDouble ( &xok );
200
+ const double y = coordList[1 ].toDouble ( &yok );
201
+ if ( !xok || !yok )
172
202
return nullptr ;
203
+
204
+ actualLineSize++;
205
+ *outLineX++ = x;
206
+ *outLineY++ = y;
207
+ if ( hasZ )
208
+ {
209
+ *outLineZ++ = nCoords >= 3 ? coordList[2 ].toDouble () : std::numeric_limits< double >::quiet_NaN ();
173
210
}
174
- if ( !lineString )
175
- lineString = std::make_unique< QgsLineString >();
176
211
177
- lineString->addVertex ( *point );
212
+ if ( hasM )
213
+ {
214
+ // if point has just M but not Z, then the point dimension list will only have X, Y, M, otherwise it will have X, Y, Z, M
215
+ *outLineM++ = ( ( hasZ && nCoords >= 4 ) || ( !hasZ && nCoords >= 3 ) ) ? coordList[ hasZ ? 3 : 2 ].toDouble () : std::numeric_limits< double >::quiet_NaN ();
216
+ }
178
217
}
179
218
else if ( curveData.type () == QVariant::Map )
180
219
{
181
220
// The last point of the linestring is the start point of this circular string
182
- std::unique_ptr< QgsCircularString > circularString ( convertCircularString ( curveData.toMap (), pointType, lineString ? lineString->endPoint () : QgsPoint () ) );
221
+ QgsPoint lastLineStringPoint;
222
+ if ( actualLineSize > 0 )
223
+ {
224
+ lastLineStringPoint = QgsPoint ( lineX.at ( actualLineSize - 1 ),
225
+ lineY.at ( actualLineSize - 1 ),
226
+ hasZ ? lineZ.at ( actualLineSize - 1 ) : std::numeric_limits< double >::quiet_NaN (),
227
+ hasM ? lineM.at ( actualLineSize - 1 ) : std::numeric_limits< double >::quiet_NaN () );
228
+ }
229
+ std::unique_ptr< QgsCircularString > circularString ( convertCircularString ( curveData.toMap (), pointType, lastLineStringPoint ) );
183
230
if ( !circularString )
184
231
{
185
232
return nullptr ;
186
233
}
187
234
188
- if ( lineString )
189
- compoundCurve->addCurve ( lineString.release () );
235
+ if ( actualLineSize > 0 )
236
+ {
237
+ lineX.resize ( actualLineSize );
238
+ lineY.resize ( actualLineSize );
239
+ if ( hasZ )
240
+ lineZ.resize ( actualLineSize );
241
+ if ( hasM )
242
+ lineM.resize ( actualLineSize );
243
+
244
+ compoundCurve->addCurve ( new QgsLineString ( lineX, lineY, lineZ, lineM ) );
245
+ lineX.resize ( maxCurveListSize - curveListIndex );
246
+ lineY.resize ( maxCurveListSize - curveListIndex );
247
+ if ( hasZ )
248
+ lineZ.resize ( maxCurveListSize - curveListIndex );
249
+ if ( hasM )
250
+ lineM.resize ( maxCurveListSize - curveListIndex );
251
+ outLineX = lineX.data ();
252
+ outLineY = lineY.data ();
253
+ outLineZ = lineZ.data ();
254
+ outLineM = lineM.data ();
255
+ }
190
256
191
257
// If the previous curve had less than two points, remove it
192
258
if ( compoundCurve->curveAt ( compoundCurve->nCurves () - 1 )->nCoordinates () < 2 )
@@ -196,20 +262,40 @@ std::unique_ptr< QgsCompoundCurve > QgsArcGisRestUtils::convertCompoundCurve( co
196
262
compoundCurve->addCurve ( circularString.release () );
197
263
198
264
// Prepare a new line string
199
- lineString = std::make_unique< QgsLineString >();
200
- lineString->addVertex ( endPointCircularString );
265
+ actualLineSize = 1 ;
266
+ *outLineX++ = endPointCircularString.x ();
267
+ *outLineY++ = endPointCircularString.y ();
268
+ if ( hasZ )
269
+ *outLineZ++ = endPointCircularString.z ();
270
+ if ( hasM )
271
+ *outLineM++ = endPointCircularString.m ();
201
272
}
273
+ curveListIndex++;
202
274
}
203
275
204
- if ( lineString && lineString-> numPoints () == 1 && compoundCurve->nCurves () > 0 )
276
+ if ( actualLineSize == 1 && compoundCurve->nCurves () > 0 )
205
277
{
206
278
const QgsCurve *finalCurve = compoundCurve->curveAt ( compoundCurve->nCurves () - 1 );
207
- if ( finalCurve->endPoint () == lineString->startPoint () )
208
- lineString.reset (); // redundant final curve containing a duplicate vertex
279
+ const QgsPoint finalCurveEndPoint = finalCurve->endPoint ();
280
+ if ( qgsDoubleNear ( finalCurveEndPoint.x (), lineX.at ( 0 ) )
281
+ && qgsDoubleNear ( finalCurveEndPoint.y (), lineY.at ( 0 ) )
282
+ && ( !hasZ || qgsDoubleNear ( finalCurveEndPoint.z (), lineZ.at ( 0 ) ) )
283
+ && ( !hasM || qgsDoubleNear ( finalCurveEndPoint.m (), lineM.at ( 0 ) ) ) )
284
+ {
285
+ actualLineSize = 0 ; // redundant final curve containing a duplicate vertex
286
+ }
209
287
}
210
288
211
- if ( lineString )
212
- compoundCurve->addCurve ( lineString.release () );
289
+ if ( actualLineSize > 0 )
290
+ {
291
+ lineX.resize ( actualLineSize );
292
+ lineY.resize ( actualLineSize );
293
+ if ( hasZ )
294
+ lineZ.resize ( actualLineSize );
295
+ if ( hasM )
296
+ lineM.resize ( actualLineSize );
297
+ compoundCurve->addCurve ( new QgsLineString ( lineX, lineY, lineZ, lineM ) );
298
+ }
213
299
214
300
return compoundCurve;
215
301
}
0 commit comments