diff --git a/src/PythonicAPI.md b/src/PythonicAPI.md
index 116e87d58abe65d1223f68aef03e0c33a30f9a98..57018e166021b6372fbc5ffd4c4c8a6ac158cd72 100644
--- a/src/PythonicAPI.md
+++ b/src/PythonicAPI.md
@@ -168,6 +168,8 @@ This Python script, [SelectExamples](../PythonicAPI/Utilities/SelectExamples), w
 | -------------- | ------------- | ------- |
 [AlignTwoPolyDatas](/PythonicAPI/PolyData/AlignTwoPolyDatas) | Align two vtkPolyData's.
 [BooleanPolyDataFilters](/PythonicAPI/PolyData/BooleanPolyDataFilters) | This example performs a boolean operation (intersection, union or difference) of two PolyData using either a vtkBooleanOperationPolyDataFilter or a vtkLoopBooleanPolyDataFilter
+[Bottle](/PythonicAPI/Modelling/Bottle) | Model a rotationally symmetric object.
+[CappedSphere](/PythonicAPI/Modelling/CappedSphere) | Rotate an arc to create a capped sphere.
 [CellsInsideObject](/PythonicAPI/PolyData/CellsInsideObject) | Extract cells inside a closed surface.
 [ConnectivityFilter](/PythonicAPI/Filtering/ConnectivityFilter) | Color any dataset type based on connectivity.
 [Curvatures](/PythonicAPI/PolyData/Curvatures) | Compute Gaussian, and Mean Curvatures.
@@ -186,6 +188,7 @@ This Python script, [SelectExamples](../PythonicAPI/Utilities/SelectExamples), w
 [PolyDataToImageDataStencil](/PythonicAPI/PolyData/PolyDataToImageDataStencil) |
 [RuledSurfaceFilter](/PythonicAPI/PolyData/RuledSurfaceFilter) |
 [SmoothMeshGrid](/PythonicAPI/PolyData/SmoothMeshGrid) | Create a terrain with regularly spaced points and smooth it with ?vtkLoopSubdivisionFilter? and ?vtkButterflySubdivisionFilter?.
+[Spring](/PythonicAPI/Modelling/Spring) | Rotation in combination with linear displacement and radius variation.
 [WarpTo](/PythonicAPI/Filtering/WarpTo) | Deform geometry by warping towards a point.
 [WarpVector](/PythonicAPI/PolyData/WarpVector) | This example warps/deflects a line.
 
diff --git a/src/PythonicAPI/Modelling/Bottle.py b/src/PythonicAPI/Modelling/Bottle.py
new file mode 100755
index 0000000000000000000000000000000000000000..787839c51342f3448d70de1e765d90e352f60e72
--- /dev/null
+++ b/src/PythonicAPI/Modelling/Bottle.py
@@ -0,0 +1,98 @@
+#!/usr/bin/env python3
+
+# noinspection PyUnresolvedReferences
+import vtkmodules.vtkInteractionStyle
+# noinspection PyUnresolvedReferences
+import vtkmodules.vtkRenderingOpenGL2
+from vtkmodules.vtkCommonColor import vtkNamedColors
+from vtkmodules.vtkCommonCore import vtkPoints
+from vtkmodules.vtkCommonDataModel import (
+    vtkCellArray,
+    vtkPolyData
+)
+from vtkmodules.vtkFiltersCore import (
+    vtkStripper,
+    vtkTubeFilter
+)
+from vtkmodules.vtkFiltersModeling import vtkRotationalExtrusionFilter
+from vtkmodules.vtkRenderingCore import (
+    vtkActor,
+    vtkPolyDataMapper,
+    vtkRenderWindow,
+    vtkRenderWindowInteractor,
+    vtkRenderer
+)
+
+
+def main():
+    colors = vtkNamedColors()
+
+    # Create the RenderWindow, Renderer and Interactor.
+    renderer = vtkRenderer(background=colors.GetColor3d('Burlywood'))
+    ren_win = vtkRenderWindow(size=(640, 480), window_name='Bottle')
+    ren_win.AddRenderer(renderer)
+    iren = vtkRenderWindowInteractor()
+    iren.render_window = ren_win
+
+    # Create the bottle profile.
+    points = vtkPoints()
+    points.InsertPoint(0, 0.01, 0.0, 0.0)
+    points.InsertPoint(1, 1.5, 0.0, 0.0)
+    points.InsertPoint(2, 1.5, 0.0, 3.5)
+    points.InsertPoint(3, 1.25, 0.0, 3.75)
+    points.InsertPoint(4, 0.75, 0.0, 4.00)
+    points.InsertPoint(5, 0.6, 0.0, 4.35)
+    points.InsertPoint(6, 0.7, 0.0, 4.65)
+    points.InsertPoint(7, 1.0, 0.0, 4.75)
+    points.InsertPoint(8, 1.0, 0.0, 5.0)
+    points.InsertPoint(9, 0.2, 0.0, 5.0)
+
+    lines = vtkCellArray()
+    lines.InsertNextCell(10)  # The number of points.
+    for i in range(0, 10):
+        lines.InsertCellPoint(i)
+
+    profile = vtkPolyData(points=points, lines=lines)
+
+    # Extrude the profile to make the bottle.
+    extrude = vtkRotationalExtrusionFilter(input_data=profile, resolution=60)
+
+    mapper = vtkPolyDataMapper()
+    extrude >> mapper
+
+    bottle = vtkActor(mapper=mapper)
+    bottle.property.color = colors.GetColor3d('Mint')
+
+    # Display the profile.
+    stripper = vtkStripper(input_data=profile)
+
+    tubes = vtkTubeFilter(number_of_sides=11, radius=0.05)
+
+    profile_mapper = vtkPolyDataMapper()
+    stripper >> tubes >> profile_mapper
+
+    profile_actor = vtkActor()
+    profile_actor.SetMapper(profile_mapper)
+    profile_actor.property.color = colors.GetColor3d('Tomato')
+
+    # Add the actors to the renderer, set the background and size.
+    renderer.AddActor(bottle)
+    renderer.AddActor(profile_actor)
+    renderer.SetBackground(colors.GetColor3d('Burlywood'))
+
+    ren_win.Render()
+
+    renderer.active_camera.position = (1, 0, 0)
+    renderer.active_camera.focal_point = (0, 0, 0)
+    renderer.active_camera.view_up = (0, 0, 1)
+    renderer.ResetCamera()
+    renderer.active_camera.Azimuth(30)
+    renderer.active_camera.Elevation(30)
+
+    # Render the image.
+    ren_win.Render()
+    iren.Start()
+
+
+if __name__ == '__main__':
+    main()
diff --git a/src/PythonicAPI/Modelling/CappedSphere.md b/src/PythonicAPI/Modelling/CappedSphere.md
new file mode 100644
index 0000000000000000000000000000000000000000..f3beea299675e8c5e8573c076d2dad67ca80c844
--- /dev/null
+++ b/src/PythonicAPI/Modelling/CappedSphere.md
@@ -0,0 +1,26 @@
+### Description
+
+Demonstrates how to create a capped sphere.
+
+Firstly a line is created in the x-z plane corresponding to an arc from +z to -z in the +x direction in the x-z plane, the length of the arc is specified in degrees.
+
+Then the line is extended by dropping a perpendicular to the x-axis.
+
+The points generated are then converted to a line and passed through to the vtkRotationalExtrusionFilter to generate the resultant 3D surface.
+
+The parameters are:
+
+- angle - the arc length in degrees default 90° (a hemisphere)
+- step -the step size of the arc in degrees, default 1°
+- radius - the radius of the arc default 1
+
+Options are provided to:
+
+- Uncap the sphere (**-u, --uncapped**)
+- Display the line that was rotationally extruded (**-s, --show_line**)
+
+!!! Note
+    The coordinate system for specifying the arc is left-handed with 0° aligned with the positive z-axis, 90° aligned with the positive x-axis.
+
+!!! Note
+    You can substitute different parametric equations for x and z in the line generating function to get other shapes.
diff --git a/src/PythonicAPI/Modelling/CappedSphere.py b/src/PythonicAPI/Modelling/CappedSphere.py
new file mode 100755
index 0000000000000000000000000000000000000000..d2dca9e275eaf61fbc80e7ea29e72490b83c7aad
--- /dev/null
+++ b/src/PythonicAPI/Modelling/CappedSphere.py
@@ -0,0 +1,163 @@
+#!/usr/bin/env python3
+
+import math
+
+# noinspection PyUnresolvedReferences
+import vtkmodules.vtkInteractionStyle
+# noinspection PyUnresolvedReferences
+import vtkmodules.vtkRenderingOpenGL2
+from vtkmodules.vtkCommonColor import vtkNamedColors
+from vtkmodules.vtkCommonCore import vtkPoints
+from vtkmodules.vtkCommonDataModel import (
+    vtkCellArray,
+    vtkLine,
+    vtkPolyData
+)
+from vtkmodules.vtkFiltersModeling import vtkRotationalExtrusionFilter
+from vtkmodules.vtkRenderingCore import (
+    vtkActor,
+    vtkPolyDataMapper,
+    vtkRenderWindow,
+    vtkRenderWindowInteractor,
+    vtkRenderer
+)
+
+
+def get_program_parameters():
+    import argparse
+    description = 'Display a capped sphere.'
+    epilogue = '''
+   '''
+    parser = argparse.ArgumentParser(description=description, epilog=epilogue,
+                                     formatter_class=argparse.RawDescriptionHelpFormatter)
+    parser.add_argument('angle', default=90, type=float, nargs='?',
+                        help='The length of the arc in degrees from +z to -z in the +x direction in the x-z plane.')
+    parser.add_argument('step', default=1, type=float, nargs='?', help='Step size in degrees.')
+    parser.add_argument('radius', default=1, type=float, nargs='?', help='Radius of the arc.')
+    parser.add_argument('-u', '--uncapped', action='store_true', help='Uncap the sphere.')
+    parser.add_argument('-s', '--show_line', action='store_true',
+                        help='Show the line that is rotationally extruded to make the surface.')
+    args = parser.parse_args()
+    return args.angle, args.step, args.radius, args.uncapped, args.show_line
+
+
+def main():
+    angle, step, radius, uncapped, show_line = get_program_parameters()
+    angle = math.radians(abs(angle))
+    step = math.radians(abs(step))
+    radius = abs(radius)
+    # With the default settings, if you set this to 45°,
+    # you get a bowl with a flat bottom.
+    start = math.radians(90)
+
+    pts = get_line_points(angle, step, radius, uncapped, start)
+
+    # Setup points and lines
+    points = vtkPoints()
+    lines = vtkCellArray()
+    for pt in pts:
+        pt_id = points.InsertNextPoint(pt)
+        if pt_id < len(pts) - 1:
+            line = vtkLine()
+            line.GetPointIds().SetId(0, pt_id)
+            line.GetPointIds().SetId(1, pt_id + 1)
+            lines.InsertNextCell(line)
+
+    polydata = vtkPolyData(points=points, lines=lines)
+
+    # Extrude the profile to make the capped sphere
+    extrude = vtkRotationalExtrusionFilter(input_data=polydata, resolution=60)
+
+    #  Visualize
+    colors = vtkNamedColors()
+
+    # To see the line.
+    line_mapper = vtkPolyDataMapper(input_data=polydata)
+
+    line_actor = vtkActor(mapper=line_mapper)
+    line_actor.property.line_width = 4
+    line_actor.property.color = colors.GetColor3d('Red')
+
+    # To see the surface.
+    surface_mapper = vtkPolyDataMapper()
+    extrude >> surface_mapper
+
+    surface_actor = vtkActor(mapper=surface_mapper)
+    surface_actor.property.color = colors.GetColor3d('Khaki')
+
+    ren = vtkRenderer(background=colors.GetColor3d('LightSlateGray'))
+    ren_win = vtkRenderWindow(size=(600, 600), window_name='CappedSphere')
+    ren_win.AddRenderer(ren)
+    iren = vtkRenderWindowInteractor()
+    iren.render_window = ren_win
+
+    ren.AddActor(surface_actor)
+    if show_line:
+        ren.AddActor(line_actor)
+
+    ren.ResetCamera()
+    if show_line:
+        ren.active_camera.Roll(90)
+    ren.active_camera.Elevation(60)
+
+    ren.ResetCameraClippingRange()
+
+    ren_win.Render()
+    iren.Start()
+
+
+def get_line_points(angle, step, radius, uncapped, start):
+    """
+    Get the points for a line.
+
+    :param angle: Length of the arc in degrees.
+    :param step: Step size in degrees.
+    :param radius: Radius of the arc.
+    :param uncapped: True if uncapped.
+    :param start: Starting angle.
+    :return: A vector of points.
+    """
+    precision = 1.0e-6
+    pts = list()
+    # Do the curved line
+    theta = 0.0
+    while theta <= angle:
+        x = radius * math.cos(start - theta)
+        z = radius * math.sin(theta - start)
+        if x < 0:
+            x = 0
+            pts.append((x, 0, z))
+            break
+        if abs(x) < precision:
+            x = 0
+        if abs(z) < precision:
+            z = 0
+        pts.append((x, 0, z))
+        theta += step
+
+    if not uncapped:
+        # Drop a perpendicular from the last point to the x-axis.
+        if len(pts) > 1:
+            if pts[-1][0] > 0:
+                last_point = pts[-1]
+                num_pts = 10
+                interval = float(num_pts) / radius
+                for i in range(1, num_pts):
+                    x = last_point[0] - i / interval
+                    z = last_point[2]
+                    if x < 0:
+                        x = 0
+                        pts.append((x, 0, z))
+                        break
+                    if abs(x) < precision:
+                        x = 0
+                    if abs(z) < precision:
+                        z = 0
+                    pts.append((x, 0, z))
+            if pts[-1][0] > precision:
+                pts.append((0, 0, pts[-1][2]))
+    return pts
+
+
+if __name__ == '__main__':
+    main()
diff --git a/src/PythonicAPI/Modelling/Spring.py b/src/PythonicAPI/Modelling/Spring.py
new file mode 100755
index 0000000000000000000000000000000000000000..c4eaefded2dbf9190b3e466e46afc2a4d1e91236
--- /dev/null
+++ b/src/PythonicAPI/Modelling/Spring.py
@@ -0,0 +1,83 @@
+#!/usr/bin/env python3
+
+# noinspection PyUnresolvedReferences
+import vtkmodules.vtkInteractionStyle
+# noinspection PyUnresolvedReferences
+import vtkmodules.vtkRenderingOpenGL2
+from vtkmodules.vtkCommonColor import vtkNamedColors
+from vtkmodules.vtkCommonCore import vtkPoints
+from vtkmodules.vtkCommonDataModel import (
+    vtkCellArray,
+    vtkPolyData
+)
+from vtkmodules.vtkFiltersCore import vtkPolyDataNormals
+from vtkmodules.vtkFiltersModeling import vtkRotationalExtrusionFilter
+from vtkmodules.vtkRenderingCore import (
+    vtkActor,
+    vtkPolyDataMapper,
+    vtkRenderWindow,
+    vtkRenderWindowInteractor,
+    vtkRenderer
+)
+
+
+def main():
+    colors = vtkNamedColors()
+
+    # Create the RenderWindow, Renderer and Interactor.
+
+    ren = vtkRenderer(background=colors.GetColor3d('Burlywood'))
+    ren_win = vtkRenderWindow(size=(640, 512), window_name='Spring')
+    ren_win.AddRenderer(ren)
+    iren = vtkRenderWindowInteractor()
+    iren.render_window = ren_win
+
+    # Create the spring profile (a circle).
+    points = vtkPoints()
+    points.InsertPoint(0, 1.0, 0.0, 0.0)
+    points.InsertPoint(1, 1.0732, 0.0, -0.1768)
+    points.InsertPoint(2, 1.25, 0.0, -0.25)
+    points.InsertPoint(3, 1.4268, 0.0, -0.1768)
+    points.InsertPoint(4, 1.5, 0.0, 0.00)
+    points.InsertPoint(5, 1.4268, 0.0, 0.1768)
+    points.InsertPoint(6, 1.25, 0.0, 0.25)
+    points.InsertPoint(7, 1.0732, 0.0, 0.1768)
+
+    poly = vtkCellArray()
+    poly.InsertNextCell(8)  # The number of points.
+    for i in range(0, 8):
+        poly.InsertCellPoint(i)
+
+    profile = vtkPolyData(points=points, polys=poly)
+
+    # Extrude the profile to make a spring.
+    # Note: angle=360 * 6 corresponds to six revolutions.
+    extrude = vtkRotationalExtrusionFilter(input_data=profile, resolution=360,
+                                           translation=6, delta_radius=1.0,
+                                           angle=360 * 6)
+
+    normals = vtkPolyDataNormals(feature_angle=60)
+
+    mapper = vtkPolyDataMapper()
+    extrude >> normals >> mapper
+
+    spring = vtkActor(mapper=mapper)
+    spring.property.color = colors.GetColor3d("PowderBlue")
+    spring.property.diffuse = 0.7
+    spring.property.specular = 0.4
+    spring.property.specular_power = 20
+    spring.property.backface_culling = True
+
+    # Add the actor to the renderer, set the background and size.
+    ren.AddActor(spring)
+
+    ren.ResetCamera()
+    ren.active_camera.Azimuth(90)
+
+    # Render the image.
+    ren_win.Render()
+    iren.Start()
+
+
+if __name__ == '__main__':
+    main()
diff --git a/src/Testing/Baseline/PythonicAPI/Modelling/TestBottle.png b/src/Testing/Baseline/PythonicAPI/Modelling/TestBottle.png
new file mode 100644
index 0000000000000000000000000000000000000000..e6d492a5fbb52961d93cadef6f139304aab3f1bf
--- /dev/null
+++ b/src/Testing/Baseline/PythonicAPI/Modelling/TestBottle.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:9bcc5918e6acbe9d0ff66090eafd9de76513cf316b7665ff08559afd184d1669
+size 30279
diff --git a/src/Testing/Baseline/PythonicAPI/Modelling/TestCappedSphere.png b/src/Testing/Baseline/PythonicAPI/Modelling/TestCappedSphere.png
new file mode 100644
index 0000000000000000000000000000000000000000..79b1c2d9f7173b9e12de6cccdc8a0fe3a44a0a3d
--- /dev/null
+++ b/src/Testing/Baseline/PythonicAPI/Modelling/TestCappedSphere.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:d8eb76da7971c0e685d75415c8b8339400b19fc261410301da29c2e9dd2aa350
+size 29164
diff --git a/src/Testing/Baseline/PythonicAPI/Modelling/TestSpring.png b/src/Testing/Baseline/PythonicAPI/Modelling/TestSpring.png
new file mode 100644
index 0000000000000000000000000000000000000000..d5b624c2163e180e7c0e311da710ee1ce950ca6a
--- /dev/null
+++ b/src/Testing/Baseline/PythonicAPI/Modelling/TestSpring.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:e1c1eefcb00ff7eb5dfed0713df09c096db0946575fd0bca096e2e7cfb2c9b7f
+size 60821