I propose a solution using PyQGIS. It should work both for Linestring and MultiLineString layers. This solution is based on the creation of semicircular rings, so you need to set a value for the diameter (i.e. the `step` variable in the code below). The step you choose won't be the real step used because it is *adjusted* on the basis of the line length (but it would be really similar to the value initially set). You need to do some attempts before finding the best value for the `step` variable. The code also requires a second (optional) parameter (called `crv_angle`), which helps for decreasing or increasing the curvature for the rings (I performed a few tests for it, so I suggest leaving 45 degrees as default angle since it would lead to real circular rings). You only need to run this code from the Python Console: <!-- language-all: lang-py --> from math import sin, cos, radians step = 0.5 # they are meters in this case, but choose the correct value with reference to the CRS used crv_angle = 45 # degrees def segment(polyline): for x in range(0, len(polyline) - 1): first_point = polyline[x] second_point = polyline[x +1] seg = QgsGeometry.fromPolyline([first_point, second_point]) tmp_azim = first_point.azimuth(second_point) len_feat = seg.length() print len_feat parts = int(len_feat/step) real_step = len_feat/parts # this is the real step applied current = 0 points = [] while current <= len_feat: first = seg.interpolate(current) p1=QgsPointV2(first.asPoint().x(), first.asPoint().y()) angle_1 = radians(90 - (tmp_azim - crv_angle)) dist_x, dist_y = ((real_step*sin(radians(crv_angle)))* cos(angle_1), (real_step*sin(radians(crv_angle))) * sin(angle_1)) p2 = QgsPointV2(first.asPoint().x() + dist_x, first.asPoint().y() + dist_y) second = seg.interpolate(current + real_step) p3=QgsPointV2(second.asPoint().x(), second.asPoint().y()) angle_2 = radians(90 - (tmp_azim + crv_angle)) dist_x, dist_y = ((real_step*sin(radians(crv_angle)))* cos(angle_2), (real_step*sin(radians(crv_angle))) * sin(angle_2)) p4 = QgsPointV2(second.asPoint().x() + dist_x, second.asPoint().y() + dist_y) points.extend([p1, p2, p3, p4]) current += 2*real_step circularRing = QgsCircularStringV2() circularRing.setPoints(points) # set points for circular rings fet = QgsFeature() fet.setGeometry(QgsGeometry(circularRing)) prov.addFeatures([fet]) layer = iface.activeLayer() # load the input layer as you want crs = layer.crs().toWkt() # Create the output layer outLayer = QgsVectorLayer('Linestring?crs='+ crs, 'wiggly_line' , 'memory') prov = outLayer.dataProvider() fields = layer.pendingFields() prov.addAttributes(fields) # Add input layer fields to the outLayer outLayer.updateFields() for feat in layer.getFeatures(): geom = feat.geometry() polyline = geom.asPolyline() segment(polyline) # Add the layer to the Layers panel QgsMapLayerRegistry.instance().addMapLayer(outLayer) and it will create a new line memory layer with the expected result: [![enter image description here][1]][1] [1]: https://i.sstatic.net/eisUP.png