@@ -1178,6 +1178,75 @@ QgsCircularString *QgsCircularString::reversed() const
1178
1178
return copy;
1179
1179
}
1180
1180
1181
+ QgsPoint *QgsCircularString::interpolatePoint ( const double distance ) const
1182
+ {
1183
+ if ( distance < 0 )
1184
+ return nullptr ;
1185
+
1186
+ double distanceTraversed = 0 ;
1187
+ const int totalPoints = numPoints ();
1188
+ if ( totalPoints == 0 )
1189
+ return nullptr ;
1190
+
1191
+ QgsWkbTypes::Type pointType = QgsWkbTypes::Point ;
1192
+ if ( is3D () )
1193
+ pointType = QgsWkbTypes::PointZ;
1194
+ if ( isMeasure () )
1195
+ pointType = QgsWkbTypes::addM ( pointType );
1196
+
1197
+ const double *x = mX .constData ();
1198
+ const double *y = mY .constData ();
1199
+ const double *z = is3D () ? mZ .constData () : nullptr ;
1200
+ const double *m = isMeasure () ? mM .constData () : nullptr ;
1201
+
1202
+ double prevX = *x++;
1203
+ double prevY = *y++;
1204
+ double prevZ = z ? *z++ : 0.0 ;
1205
+ double prevM = m ? *m++ : 0.0 ;
1206
+
1207
+ if ( qgsDoubleNear ( distance, 0.0 ) )
1208
+ {
1209
+ return new QgsPoint ( pointType, prevX, prevY, prevZ, prevM );
1210
+ }
1211
+
1212
+ for ( int i = 0 ; i < ( totalPoints - 2 ) ; i += 2 )
1213
+ {
1214
+ double x1 = prevX;
1215
+ double y1 = prevY;
1216
+ double z1 = prevZ;
1217
+ double m1 = prevM;
1218
+
1219
+ double x2 = *x++;
1220
+ double y2 = *y++;
1221
+ double z2 = z ? *z++ : 0.0 ;
1222
+ double m2 = m ? *m++ : 0.0 ;
1223
+
1224
+ double x3 = *x++;
1225
+ double y3 = *y++;
1226
+ double z3 = z ? *z++ : 0.0 ;
1227
+ double m3 = m ? *m++ : 0.0 ;
1228
+
1229
+ const double segmentLength = QgsGeometryUtils::circleLength ( x1, y1 , x2, y2, x3, y3 );
1230
+ if ( distance < distanceTraversed + segmentLength || qgsDoubleNear ( distance, distanceTraversed + segmentLength ) )
1231
+ {
1232
+ // point falls on this segment - truncate to segment length if qgsDoubleNear test was actually > segment length
1233
+ const double distanceToPoint = std::min ( distance - distanceTraversed, segmentLength );
1234
+ return new QgsPoint ( QgsGeometryUtils::interpolatePointOnArc ( QgsPoint ( pointType, x1, y1 , z1, m1 ),
1235
+ QgsPoint ( pointType, x2, y2, z2, m2 ),
1236
+ QgsPoint ( pointType, x3, y3, z3, m3 ), distanceToPoint ) );
1237
+ }
1238
+
1239
+ distanceTraversed += segmentLength;
1240
+
1241
+ prevX = x3;
1242
+ prevY = y3;
1243
+ prevZ = z3;
1244
+ prevM = m3;
1245
+ }
1246
+
1247
+ return nullptr ;
1248
+ }
1249
+
1181
1250
QgsCircularString *QgsCircularString::curveSubstring ( double startDistance, double endDistance ) const
1182
1251
{
1183
1252
if ( startDistance < 0 && endDistance < 0 )
0 commit comments