diff --git a/pdt_tangent.py b/pdt_tangent.py
index 1f2a7ab93611193971cd6952b5b4e8371b283e53..a00be31381a0c9928acb605e7659ebbb19ca2686 100644
--- a/pdt_tangent.py
+++ b/pdt_tangent.py
@@ -23,96 +23,371 @@
 #
 import bpy
 import bmesh
-from math import sqrt
+from math import sqrt, floor, asin, sin, cos, pi
 from mathutils import Vector
 from bpy.types import Operator
 
 from .pdt_functions import (
     oops,
     arc_centre,
+    set_mode,
+    view_coords,
+    view_coords_i,
 )
 
 from .pdt_msg_strings import (
     PDT_OBJ_MODE_ERROR,
     PDT_ERR_NO_ACT_OBJ,
     PDT_ERR_SEL_3_VERTS,
+    PDT_ERR_SEL_1_VERT,
+    PDT_ERR_BADDISTANCE,
+    PDT_ERR_MATHSERROR,
+    PDT_ERR_SAMERADII,
+    PDT_ERR_VERT_MODE,
 )
 
 from . import pdt_exception
 PDT_ObjectModeError = pdt_exception.ObjectModeError
-PDT_NoObjectError = pdt_exception.NoObjectError
 PDT_SelectionError = pdt_exception.SelectionError
 
 
-def get_tangent_intersect_outer(xloc_0, yloc_0, xloc_1, yloc_1, radius_0, radius_1):
-    xloc_p = ((xloc_1 * radius_0) - (xloc_0 * radius_1)) / (radius_0 - radius_1)
-    yloc_p = ((yloc_1 * radius_0) - (yloc_0 * radius_1)) / (radius_0 - radius_1)
+def get_tangent_intersect_outer(hloc_0, vloc_0, hloc_1, vloc_1, radius_0, radius_1):
+    """Return Location in 2 Dimensions of the Intersect Point for Outer Tangents.
 
-    return xloc_p, yloc_p
+    Args:
+        hloc_0: Horizontal Coordinate of Centre of First Arc
+        vloc_0: Vertical Coordinate of Centre of First Arc
+        hloc_1: Horizontal Coordinate of Centre of Second Arc
+        vloc_1: Vertical Coordinate of Centre of Second Arc
+        radius_0: Radius of First Arc
+        radius_1: Radius of Second Arc
 
+    Returns:
+        hloc_p: Horizontal Coordinate of Centre of Intersection
+        vloc_p: Vertical Coordinate of Centre of Intersection.
+    """
 
-def get_tangent_intersect_inner(xloc_0, yloc_0, xloc_1, yloc_1, radius_0, radius_1):
-    xloc_p = ((xloc_1 * radius_0) + (xloc_0 * radius_1)) / (radius_0 + radius_1)
-    yloc_p = ((yloc_1 * radius_0) + (yloc_0 * radius_1)) / (radius_0 + radius_1)
+    hloc_p = ((hloc_1 * radius_0) - (hloc_0 * radius_1)) / (radius_0 - radius_1)
+    vloc_p = ((vloc_1 * radius_0) - (vloc_0 * radius_1)) / (radius_0 - radius_1)
 
-    return xloc_p, yloc_p
+    return hloc_p, vloc_p
 
 
-def get_tangent_points(xloc_0, yloc_0, radius_0, xloc_p, yloc_p):
-    numerator = (radius_0 ** 2 * (xloc_p - xloc_0)) + (
+def get_tangent_intersect_inner(hloc_0, vloc_0, hloc_1, vloc_1, radius_0, radius_1):
+    """Return Location in 2 Dimensions of the Intersect Point for Inner Tangents.
+
+    Args:
+        hloc_0: Horizontal Coordinate of Centre of First Arc
+        vloc_0: Vertical Coordinate of Centre of First Arc
+        hloc_1: Horizontal Coordinate of Centre of Second Arc
+        vloc_1: Vertical Coordinate of Centre of Second Arc
+        radius_0: Radius of First Arc
+        radius_1: Radius of Second Arc
+
+    Returns:
+        hloc_p: Horizontal Coordinate of Centre of Intersection
+        vloc_p: Vertical Coordinate of Centre of Intersection.
+    """
+
+    hloc_p = ((hloc_1 * radius_0) + (hloc_0 * radius_1)) / (radius_0 + radius_1)
+    vloc_p = ((vloc_1 * radius_0) + (vloc_0 * radius_1)) / (radius_0 + radius_1)
+
+    return hloc_p, vloc_p
+
+
+def get_tangent_points(context, hloc_0, vloc_0, radius_0, hloc_p, vloc_p):
+    """Return Location in 2 Dimensions of the Tangent Points.
+
+    Args:
+        context: Blender bpy.context instance
+        hloc_0: Horizontal Coordinate of Centre of First Arc
+        vloc_0: Vertical Coordinate of Centre of First Arc
+        radius_0: Radius of First Arc
+        hloc_p: Horizontal Coordinate of Intersection
+        vloc_p: Vertical Coordinate of Intersection
+
+    Returns:
+        hloc_t1: Horizontal Location of First Tangent Point
+        hloc_t2: Horizontal Location of Second Tangent Point
+        vloc_t1: Vertical Location of First Tangent Point
+        vloc_t2: Vertical Location of Second Tangent Point
+    """
+    numerator = (radius_0 ** 2 * (hloc_p - hloc_0)) + (
         radius_0
-        * (yloc_p - yloc_0)
-        * sqrt((xloc_p - xloc_0) ** 2 + (yloc_p - yloc_0) ** 2 - radius_0 ** 2)
+        * (vloc_p - vloc_0)
+        * sqrt((hloc_p - hloc_0) ** 2 + (vloc_p - vloc_0) ** 2 - radius_0 ** 2)
     )
-    denominator = (xloc_p - xloc_0) ** 2 + (yloc_p - yloc_0) ** 2
-    xloc_t1 = round((numerator / denominator) + xloc_0, 5)
+    denominator = (hloc_p - hloc_0) ** 2 + (vloc_p - vloc_0) ** 2
+    hloc_t1 = round((numerator / denominator) + hloc_0, 5)
 
-    numerator = (radius_0 ** 2 * (xloc_p - xloc_0)) - (
+    numerator = (radius_0 ** 2 * (hloc_p - hloc_0)) - (
         radius_0
-        * (yloc_p - yloc_0)
-        * sqrt((xloc_p - xloc_0) ** 2 + (yloc_p - yloc_0) ** 2 - radius_0 ** 2)
+        * (vloc_p - vloc_0)
+        * sqrt((hloc_p - hloc_0) ** 2 + (vloc_p - vloc_0) ** 2 - radius_0 ** 2)
     )
-    denominator = (xloc_p - xloc_0) ** 2 + (yloc_p - yloc_0) ** 2
-    xloc_t2 = round((numerator / denominator) + xloc_0, 5)
+    denominator = (hloc_p - hloc_0) ** 2 + (vloc_p - vloc_0) ** 2
+    hloc_t2 = round((numerator / denominator) + hloc_0, 5)
 
     # Get Y values
-    numerator = (radius_0 ** 2 * (yloc_p - yloc_0)) - (
+    numerator = (radius_0 ** 2 * (vloc_p - vloc_0)) - (
         radius_0
-        * (xloc_p - xloc_0)
-        * sqrt((xloc_p - xloc_0) ** 2 + (yloc_p - yloc_0) ** 2 - radius_0 ** 2)
+        * (hloc_p - hloc_0)
+        * sqrt((hloc_p - hloc_0) ** 2 + (vloc_p - vloc_0) ** 2 - radius_0 ** 2)
     )
-    denominator = (xloc_p - xloc_0) ** 2 + (yloc_p - yloc_0) ** 2
-    yloc_t1 = round((numerator / denominator) + yloc_0, 5)
+    denominator = (hloc_p - hloc_0) ** 2 + (vloc_p - vloc_0) ** 2
+    vloc_t1 = round((numerator / denominator) + vloc_0, 5)
 
-    numerator = (radius_0 ** 2 * (yloc_p - yloc_0)) + (
+    numerator = (radius_0 ** 2 * (vloc_p - vloc_0)) + (
         radius_0
-        * (xloc_p - xloc_0)
-        * sqrt((xloc_p - xloc_0) ** 2 + (yloc_p - yloc_0) ** 2 - radius_0 ** 2)
+        * (hloc_p - hloc_0)
+        * sqrt((hloc_p - hloc_0) ** 2 + (vloc_p - vloc_0) ** 2 - radius_0 ** 2)
     )
-    denominator = (xloc_p - xloc_0) ** 2 + (yloc_p - yloc_0) ** 2
-    yloc_t2 = round((numerator / denominator) + yloc_0, 5)
-
-    return xloc_t1, xloc_t2, yloc_t1, yloc_t2
-
-
-def draw_tangents(
-    xloc_to1, xloc_to2, yloc_to1, yloc_to2, xloc_to3, xloc_to4, yloc_to3, yloc_to4, bm, obj, obj_loc
-):
-    tangent_vector_o1 = Vector((xloc_to1, 0, yloc_to1))
-    tangent_vertex_o1 = bm.verts.new(tangent_vector_o1 - obj_loc)
-    tangent_vector_o2 = Vector((xloc_to2, 0, yloc_to2))
-    tangent_vertex_o2 = bm.verts.new(tangent_vector_o2 - obj_loc)
-    tangent_vector_o3 = Vector((xloc_to3, 0, yloc_to3))
-    tangent_vertex_o3 = bm.verts.new(tangent_vector_o3 - obj_loc)
-    tangent_vector_o4 = Vector((xloc_to4, 0, yloc_to4))
-    tangent_vertex_o4 = bm.verts.new(tangent_vector_o4 - obj_loc)
-    # Add Edges
-    bm.edges.new([tangent_vertex_o1, tangent_vertex_o3])
-    bm.edges.new([tangent_vertex_o2, tangent_vertex_o4])
+    denominator = (hloc_p - hloc_0) ** 2 + (vloc_p - vloc_0) ** 2
+    vloc_t2 = round((numerator / denominator) + vloc_0, 5)
+
+    return hloc_t1, hloc_t2, vloc_t1, vloc_t2
+
+
+def make_vectors(coords, a1, a2, a3, pg):
+    """Return Vectors of the Tangent Points.
+
+    Args:
+        coords: A List of Coordinates in 2D space of the tangent points
+                & a third dimension for the vectors
+        a1: Index of horizontal axis
+        a2: Index of vertical axis
+        a3: Index of depth axis
+        pg: PDT Parameters Group - our variables
+
+    Returns:
+        tangent_vector_o1: Location of First Tangent Point
+        tangent_vector_o2: Location of Second Tangent Point
+        tangent_vector_o3: Location of First Tangent Point
+        tangent_vector_o4: Location of Second Tangent Point
+    """
+
+    tangent_vector_o1 = Vector((0, 0, 0))
+    tangent_vector_o1[a1] = coords[0]
+    tangent_vector_o1[a2] = coords[1]
+    tangent_vector_o1[a3] = coords[8]
+    tangent_vector_o2 = Vector((0, 0, 0))
+    tangent_vector_o2[a1] = coords[2]
+    tangent_vector_o2[a2] = coords[3]
+    tangent_vector_o2[a3] = coords[8]
+    tangent_vector_o3 = Vector((0, 0, 0))
+    tangent_vector_o3[a1] = coords[4]
+    tangent_vector_o3[a2] = coords[5]
+    tangent_vector_o3[a3] = coords[8]
+    tangent_vector_o4 = Vector((0, 0, 0))
+    tangent_vector_o4[a1] = coords[6]
+    tangent_vector_o4[a2] = coords[7]
+    tangent_vector_o4[a3] = coords[8]
+
+    if pg.plane == "LO":
+        tangent_vector_o1 = view_coords(tangent_vector_o1[a1], tangent_vector_o1[a2],
+        tangent_vector_o1[a3])
+        tangent_vector_o2 = view_coords(tangent_vector_o2[a1], tangent_vector_o2[a2],
+        tangent_vector_o2[a3])
+        tangent_vector_o3 = view_coords(tangent_vector_o3[a1], tangent_vector_o3[a2],
+        tangent_vector_o3[a3])
+        tangent_vector_o4 = view_coords(tangent_vector_o4[a1], tangent_vector_o4[a2],
+        tangent_vector_o4[a3])
+
+    return ((tangent_vector_o1, tangent_vector_o2, tangent_vector_o3, tangent_vector_o4))
+
+def tangent_setup(context, pg, plane, obj_data, centre_0, centre_1, centre_2, radius_0, radius_1):
+    # Depth is a3
+    a1, a2, a3 = set_mode(plane)
+    if plane == "LO":
+        centre_0 = view_coords_i(centre_0[a1], centre_0[a2], centre_0[a3])
+        centre_1 = view_coords_i(centre_1[a1], centre_1[a2], centre_1[a3])
+        centre_2 = view_coords_i(centre_2[a1], centre_2[a2], centre_2[a3])
+    if pg.tangent_from_point:
+        vector_difference = centre_2 - centre_0
+        distance = sqrt(vector_difference[a1] ** 2 + vector_difference[a2] ** 2)
+    else:
+        vector_difference = centre_1 - centre_0
+        distance = sqrt(vector_difference[a1] ** 2 + vector_difference[a2] ** 2)
+    if distance > radius_0 + radius_1 and not pg.tangent_from_point:
+        mode = "inner"
+    elif distance > radius_0 and distance > radius_1 and not pg.tangent_from_point:
+        mode = "outer"
+    elif distance > radius_1 and pg.tangent_from_point:
+        mode = "point"
+    else:
+        # Cannot execute, centres are too close.
+        pg.error = f"{PDT_ERR_BADDISTANCE}"
+        context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
+        return {"FINISHED"}
+
+    if mode == "point":
+        if (
+            ((centre_2[a1] - centre_0[a1]) ** 2 +
+            (centre_2[a2] - centre_0[a2]) ** 2 -
+            radius_0 ** 2) > 0
+            ):
+            hloc_to1, hloc_to2, vloc_to1, vloc_to2 = get_tangent_points(context,
+                centre_0[a1], centre_0[a2], radius_0, centre_2[a1], centre_2[a2]
+            )
+        else:
+            pg.error = PDT_ERR_MATHSERROR
+            context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
+            return {"FINISHED"}
+        # Point Tangents
+        tangent_vector_o1 = Vector((0, 0, 0))
+        tangent_vector_o1[a1] = hloc_to1
+        tangent_vector_o1[a2] = vloc_to1
+        tangent_vector_o1[a3] = centre_2[a3]
+        tangent_vector_o2 = Vector((0, 0, 0))
+        tangent_vector_o2[a1] = hloc_to2
+        tangent_vector_o2[a2] = vloc_to2
+        tangent_vector_o2[a3] = centre_2[a3]
+        if pg.plane == "LO":
+            centre_2 = view_coords(centre_2[a1], centre_2[a2], centre_2[a3])
+            tangent_vector_o1 = view_coords(tangent_vector_o1[a1], tangent_vector_o1[a2],
+            tangent_vector_o1[a3])
+            tangent_vector_o2 = view_coords(tangent_vector_o2[a1], tangent_vector_o2[a2],
+            tangent_vector_o2[a3])
+        tangent_vectors = ((centre_2, tangent_vector_o1, tangent_vector_o2))
+        draw_tangents(tangent_vectors, obj_data)
+
+        return {"FINISHED"}
+
+    if mode in {"outer", "inner"}:
+        # Outer Tangents
+        if radius_0 == radius_1:
+            # No intersection point for outer tangents
+            sin_angle = (centre_1[a2] - centre_0[a2]) / distance
+            cos_angle = (centre_1[a1] - centre_0[a1]) / distance
+            hloc_to1 = centre_0[a1] + (radius_0 * sin_angle)
+            hloc_to2 = centre_0[a1] - (radius_0 * sin_angle)
+            hloc_to3 = centre_1[a1] + (radius_0 * sin_angle)
+            hloc_to4 = centre_1[a1] - (radius_0 * sin_angle)
+            vloc_to1 = centre_0[a2] - (radius_0 * cos_angle)
+            vloc_to2 = centre_0[a2] + (radius_0 * cos_angle)
+            vloc_to3 = centre_1[a2] - (radius_0 * cos_angle)
+            vloc_to4 = centre_1[a2] + (radius_0 * cos_angle)
+        else:
+            hloc_po, vloc_po = get_tangent_intersect_outer(
+                centre_0[a1], centre_0[a2], centre_1[a1], centre_1[a2], radius_0, radius_1
+            )
+
+            if (
+                ((hloc_po - centre_0[a1]) ** 2 +
+                (vloc_po - centre_0[a2]) ** 2 -
+                radius_0 ** 2) > 0
+                ):
+                hloc_to1, hloc_to2, vloc_to1, vloc_to2 = get_tangent_points(context,
+                    centre_0[a1], centre_0[a2], radius_0, hloc_po, vloc_po
+                )
+            else:
+                pg.error = PDT_ERR_MATHSERROR
+                context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
+                return {"FINISHED"}
+            if (
+                ((hloc_po - centre_0[a1]) ** 2 +
+                (vloc_po - centre_0[a2]) ** 2 -
+                radius_1 ** 2) > 0
+                ):
+                hloc_to3, hloc_to4, vloc_to3, vloc_to4 = get_tangent_points(context,
+                    centre_1[a1], centre_1[a2], radius_1, hloc_po, vloc_po
+                )
+            else:
+                pg.error = PDT_ERR_MATHSERROR
+                context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
+                return {"FINISHED"}
+
+        dloc_p = centre_0[a3]
+        coords_in = ((hloc_to1, vloc_to1, hloc_to2, vloc_to2, hloc_to3, vloc_to3,
+                    hloc_to4, vloc_to4, dloc_p))
+        tangent_vectors = make_vectors(coords_in, a1, a2, a3, pg)
+        draw_tangents(tangent_vectors, obj_data)
+
+    if mode == "inner":
+        # Inner Tangents
+        hloc_pi, vloc_pi = get_tangent_intersect_inner(
+            centre_0[a1], centre_0[a2], centre_1[a1], centre_1[a2], radius_0, radius_1
+        )
+        if (
+            ((hloc_pi - centre_0[a1]) ** 2 +
+            (vloc_pi - centre_0[a2]) ** 2 -
+            radius_0 ** 2) > 0
+            ):
+            hloc_to1, hloc_to2, vloc_to1, vloc_to2 = get_tangent_points(context,
+                centre_0[a1], centre_0[a2], radius_0, hloc_pi, vloc_pi
+            )
+        else:
+            pg.error = PDT_ERR_MATHSERROR
+            context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
+            return {"FINISHED"}
+        if (
+            ((hloc_pi - centre_0[a1]) ** 2 +
+            (vloc_pi - centre_0[a2]) ** 2 -
+            radius_0 ** 2) > 0
+            ):
+            hloc_to3, hloc_to4, vloc_to3, vloc_to4 = get_tangent_points(context,
+                centre_1[a1], centre_1[a2], radius_1, hloc_pi, vloc_pi
+            )
+        else:
+            pg.error = PDT_ERR_MATHSERROR
+            context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
+            return {"FINISHED"}
+
+        dloc_p = centre_0[a3]
+        coords_in = ((hloc_to1, vloc_to1, hloc_to2, vloc_to2, hloc_to3, vloc_to3,
+                    hloc_to4, vloc_to4, dloc_p))
+        tangent_vectors = make_vectors(coords_in, a1, a2, a3, pg)
+        draw_tangents(tangent_vectors, obj_data)
+
+
+def draw_tangents(tangent_vectors, obj_data):
+    """Add Edges Representing the Tangents.
+
+    Note:
+        The length of the tanget_vectors determins whcih tangents will be
+        drawn, 3 gives Point Tangents, 4 gives Inner/Outer tangents
+
+    Args:
+        tangent_vectors: A list of vectores representing the tangents
+        obj_data: A list giving Object, Object Location and Object Bmesh
+
+    Returns:
+        Nothing.
+    """
+    obj = obj_data[0]
+    obj_loc = obj_data[1]
+    bm = obj_data[2]
+    if len(tangent_vectors) == 3:
+        point_vertex_outer = bm.verts.new(tangent_vectors[0] - obj_loc)
+        tangent_vertex_o1 = bm.verts.new(tangent_vectors[1] - obj_loc)
+        tangent_vertex_o2 = bm.verts.new(tangent_vectors[2] - obj_loc)
+        bm.edges.new([tangent_vertex_o1, point_vertex_outer])
+        bm.edges.new([tangent_vertex_o2, point_vertex_outer])
+    else:
+        tangent_vertex_o1 = bm.verts.new(tangent_vectors[0] - obj_loc)
+        tangent_vertex_o2 = bm.verts.new(tangent_vectors[2] - obj_loc)
+        tangent_vertex_o3 = bm.verts.new(tangent_vectors[1] - obj_loc)
+        tangent_vertex_o4 = bm.verts.new(tangent_vectors[3] - obj_loc)
+        bm.edges.new([tangent_vertex_o1, tangent_vertex_o2])
+        bm.edges.new([tangent_vertex_o3, tangent_vertex_o4])
     bmesh.update_edit_mesh(obj.data)
 
 
 def analyse_arc(context, pg):
+    """Analyses an Arc inferred from Selected Vertices.
+
+    Note:
+        Will work if more than 3 vertices are selected, taking the
+        first, the nearest to the middle and the last.
+
+    Args:
+        context: Blender bpy.context instance
+        pg: PDT Parameters Group - our variables
+
+    Returns:
+        vector_delta: Location of Arc Centre
+        radius: Radius of Arc.
+    """
     obj = context.view_layer.objects.active
     if obj is None:
         pg.error = PDT_ERR_NO_ACT_OBJ
@@ -122,17 +397,17 @@ def analyse_arc(context, pg):
         obj_loc = obj.matrix_world.decompose()[0]
         bm = bmesh.from_edit_mesh(obj.data)
         verts = [v for v in bm.verts if v.select]
-        if len(verts) != 3:
+        if len(verts) < 3:
             pg.error = f"{PDT_ERR_SEL_3_VERTS} {len(verts)})"
             context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
             raise PDT_SelectionError
         vector_a = verts[0].co
-        vector_b = verts[1].co
-        vector_c = verts[2].co
+        vector_b = verts[int(floor(len(verts)/2))].co
+        vector_c = verts[-1].co
         vector_delta, radius = arc_centre(vector_a, vector_b, vector_c)
 
         return vector_delta, radius
-        
+
 
 class PDT_OT_TangentOperate(Operator):
     """Calculate Tangents."""
@@ -150,108 +425,146 @@ class PDT_OT_TangentOperate(Operator):
         return all([bool(ob), ob.type == "MESH", ob.mode == "EDIT"])
 
     def execute(self, context):
+        """Repeat Current Command Line Input.
+
+        Note:
+            Uses pg.plane, pg.tangent_point0, pg.tangent_radius0, pg.tangent_point1
+            pg.tangent_radius1, pg.tangent_point2 to place tangents.
+
+            Analyses distance between arc centres, or arc centre and tangent point
+            to determine which mode is possible (Inner, Outer, or Point). If centres are
+            both contianed within 1 inferred circle, Inner tangents are not possible.
+
+            Arcs of same radius will have no intersection for outer tangents so these
+            are calculated differently.
+
+        Args:
+            context: Blender bpy.context instance.
+
+        Returns:
+            Nothing.
+        """
+
         scene = context.scene
         pg = scene.pdt_pg
-        centre_0 = pg.tangent_point0
+        plane = pg.plane
+        # Get Object
+        obj = context.view_layer.objects.active
+        if obj is not None:
+            if obj.mode not in {"EDIT"} or obj.type != "MESH":
+                pg.error = PDT_OBJ_MODE_ERROR
+                context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
+                return {"FINISHED"}
+        else:
+            pg.error = PDT_ERR_NO_ACT_OBJ
+            context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
+            return {"FINISHED"}
+        bm = bmesh.from_edit_mesh(obj.data)
+        obj_loc = obj.matrix_world.decompose()[0]
+        obj_data = ((obj, obj_loc, bm))
+
         radius_0 = pg.tangent_radius0
-        centre_1 = pg.tangent_point1
         radius_1 = pg.tangent_radius1
+        centre_0 = pg.tangent_point0
+        centre_1 = pg.tangent_point1
         centre_2 = pg.tangent_point2
-        distance = (centre_0 - centre_1).length
-        if distance > radius_0 + radius_1:
-            mode = "inner"
-        elif distance > radius_0 and distance > radius_1:
-            mode = "outer"
-        else:
-            # Cannot execute, centres are too close.
-            print("Execution Error")
-            return {"FINISHED"}
 
+        tangent_setup(context, pg, plane, obj_data, centre_0, centre_1,
+            centre_2, radius_0, radius_1)
+
+        return {"FINISHED"}
+
+
+class PDT_OT_TangentOperateSel(Operator):
+    """Calculate Tangents."""
+
+    bl_idname = "pdt.tangentoperatesel"
+    bl_label = "Calculate Tangents"
+    bl_options = {"REGISTER", "UNDO"}
+    bl_description = "Calculate Tangents to Arcs from 2 Selected Vertices, or 1 & Point"
+
+    @classmethod
+    def poll(cls, context):
+        ob = context.object
+        if ob is None:
+            return False
+        return all([bool(ob), ob.type == "MESH", ob.mode == "EDIT"])
+
+    def execute(self, context):
+        """Repeat Current Command Line Input.
+
+        Note:
+            Uses pg.plane & 2 or more selected Vertices to place tangents.
+            One vertex must be on each arc.
+
+            Analyses distance between arc centres, or arc centre and tangent point
+            to determine which mode is possible (Inner, Outer, or Point). If centres are
+            both contianed within 1 inferred circle, Inner tangents are not possible.
+
+            Arcs of same radius will have no intersection for outer tangents so these
+            are calculated differently.
+
+        Args:
+            context: Blender bpy.context instance.
+
+        Returns:
+            Nothing.
+        """
+
+        scene = context.scene
+        pg = scene.pdt_pg
+        plane = pg.plane
         # Get Object
         obj = context.view_layer.objects.active
         if obj is not None:
             if obj.mode not in {"EDIT"} or obj.type != "MESH":
                 pg.error = PDT_OBJ_MODE_ERROR
                 context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
-                raise PDT_ObjectModeError
+                return {"FINISHED"}
         else:
             pg.error = PDT_ERR_NO_ACT_OBJ
             context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
-            raise PDT_NoObjectError
+            return {"FINISHED"}
         bm = bmesh.from_edit_mesh(obj.data)
         obj_loc = obj.matrix_world.decompose()[0]
+        obj_data = ((obj, obj_loc, bm))
 
-        if pg.tangent_from_point:
-            # FIXME Get Proper Axes Values
-            xloc_to1, xloc_to2, yloc_to1, yloc_to2 = get_tangent_points(
-                centre_0.x, centre_0.z, radius_0, centre_2.x, centre_2.z
-            )
-            # Point Tangents
-            point_vector_outer = Vector((centre_2.x, 0, centre_2.z))
-            point_vertex_outer = bm.verts.new(point_vector_outer - obj_loc)
-            tangent_vector_o1 = Vector((xloc_to1, 0, yloc_to1))
-            tangent_vertex_o1 = bm.verts.new(tangent_vector_o1 - obj_loc)
-            tangent_vector_o2 = Vector((xloc_to2, 0, yloc_to2))
-            tangent_vertex_o2 = bm.verts.new(tangent_vector_o2 - obj_loc)
-            bm.edges.new([tangent_vertex_o1, point_vertex_outer])
-            bm.edges.new([tangent_vertex_o2, point_vertex_outer])
-            bmesh.update_edit_mesh(obj.data)
+        # Get All Values from Selected Vertices
+        verts = [v for v in bm.verts if v.select]
+        v1 = verts[0]
+        vn = verts[-1]
+        for v in bm.verts:
+            v.select_set(False)
+        for e in bm.edges:
+            e.select_set(False)
+        v1.select_set(True)
+        bpy.ops.mesh.select_linked()
+        verts1 = [v for v in bm.verts if v.select].copy()
+        if len(verts1) < 3:
+            pg.error = f"{PDT_ERR_VERT_MODE}"
+            context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
             return {"FINISHED"}
+        for v in bm.verts:
+            v.select_set(False)
+        for e in bm.edges:
+            e.select_set(False)
+        vn.select_set(True)
+        bpy.ops.mesh.select_linked()
+        vertsn = [v for v in bm.verts if v.select].copy()
+        for v in bm.verts:
+            v.select_set(False)
+        for e in bm.edges:
+            e.select_set(False)
+        bmesh.update_edit_mesh(obj.data)
+        bm.select_history.clear()
+        verts1 = [verts1[0].co, verts1[int(floor(len(verts1)/2))].co, verts1[-1].co]
+        vertsn = [vertsn[0].co, vertsn[int(floor(len(vertsn)/2))].co, vertsn[-1].co]
+        centre_0, radius_0 = arc_centre(verts1[0], verts1[1], verts1[2])
+        centre_1, radius_1 = arc_centre(vertsn[0], vertsn[1], vertsn[2])
+        centre_2 = pg.tangent_point2
 
-        if mode in {"outer", "inner"}:
-            # FIXME Get Proper Axes Values
-            xloc_po, yloc_po = get_tangent_intersect_outer(
-                centre_0.x, centre_0.z, centre_1.x, centre_1.z, radius_0, radius_1
-            )
-            # Outer Tangents
-            xloc_to1, xloc_to2, yloc_to1, yloc_to2 = get_tangent_points(
-                centre_0.x, centre_0.z, radius_0, xloc_po, yloc_po
-            )
-            xloc_to3, xloc_to4, yloc_to3, yloc_to4 = get_tangent_points(
-                centre_1.x, centre_1.z, radius_1, xloc_po, yloc_po
-            )
-
-            # Add Outer Tangent Vertices
-            draw_tangents(
-                xloc_to1,
-                xloc_to2,
-                yloc_to1,
-                yloc_to2,
-                xloc_to3,
-                xloc_to4,
-                yloc_to3,
-                yloc_to4,
-                bm,
-                obj,
-                obj_loc,
-            )
-
-        if mode == "inner":
-            # FIXME Get Proper Axes Values
-            xloc_pi, yloc_pi = get_tangent_intersect_inner(
-                centre_0.x, centre_0.z, centre_1.x, centre_1.z, radius_0, radius_1
-            )
-            # Inner Tangents
-            xloc_to1, xloc_to2, yloc_to1, yloc_to2 = get_tangent_points(
-                centre_0.x, centre_0.z, radius_0, xloc_pi, yloc_pi
-            )
-            xloc_to3, xloc_to4, yloc_to3, yloc_to4 = get_tangent_points(
-                centre_1.x, centre_1.z, radius_1, xloc_pi, yloc_pi
-            )
-            # Add Inner Tangent Vertices
-            draw_tangents(
-                xloc_to1,
-                xloc_to2,
-                yloc_to1,
-                yloc_to2,
-                xloc_to3,
-                xloc_to4,
-                yloc_to3,
-                yloc_to4,
-                bm,
-                obj,
-                obj_loc,
-            )
+        tangent_setup(context, pg, plane, obj_data, centre_0, centre_1, centre_2,
+            radius_0, radius_1)
 
         return {"FINISHED"}
 
@@ -290,10 +603,10 @@ class PDT_OT_TangentSet2(Operator):
 
     @classmethod
     def poll(cls, context):
-        ob = context.object
-        if ob is None:
+        obj = context.object
+        if obj is None:
             return False
-        return all([bool(ob), ob.type == "MESH", ob.mode == "EDIT"])
+        return all([bool(obj), obj.type == "MESH", obj.mode == "EDIT"])
 
     def execute(self, context):
         scene = context.scene
@@ -302,3 +615,80 @@ class PDT_OT_TangentSet2(Operator):
         pg.tangent_point1 = vector_delta
         pg.tangent_radius1 = radius
         return {"FINISHED"}
+
+
+class PDT_OT_TangentSet3(Operator):
+    """Set Tangent Origin Point from Cursor."""
+
+    bl_idname = "pdt.tangentset3"
+    bl_label = "Set Tangent Origin Point from Cursor"
+    bl_options = {"REGISTER", "UNDO"}
+    bl_description = "Set Tangent Origin Point from Cursor"
+
+    @classmethod
+    def poll(cls, context):
+        obj = context.object
+        if obj is None:
+            return False
+        return all([bool(obj), obj.type == "MESH", obj.mode == "EDIT"])
+
+    def execute(self, context):
+        scene = context.scene
+        pg = scene.pdt_pg
+        pg.tangent_point2 = scene.cursor.location
+        return {"FINISHED"}
+
+
+class PDT_OT_TangentSet4(Operator):
+    """Set Tangent Origin Point from Cursor."""
+
+    bl_idname = "pdt.tangentset4"
+    bl_label = "Set Tangent Origin Point from Vertex"
+    bl_options = {"REGISTER", "UNDO"}
+    bl_description = "Set Tangent Origin Point from Vertex"
+
+    @classmethod
+    def poll(cls, context):
+        obj = context.object
+        if obj is None:
+            return False
+        return all([bool(obj), obj.type == "MESH", obj.mode == "EDIT"])
+
+    def execute(self, context):
+        scene = context.scene
+        pg = scene.pdt_pg
+        obj = context.object
+        bm = bmesh.from_edit_mesh(obj.data)
+        verts = [v for v in bm.verts if v.select]
+        if len(verts) != 1:
+            pg.error = f"{PDT_ERR_SEL_1_VERT} {len(verts)})"
+            context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
+            raise PDT_SelectionError
+        pg.tangent_point2 = verts[0].co
+        return {"FINISHED"}
+
+
+class PDT_OT_TangentExpandMenu(Operator):
+    """Expand/Collapse Tangent Menu."""
+
+    bl_idname = "pdt.tangentexpandmenu"
+    bl_label = "Expand/Collapse Tangent Menu"
+    bl_options = {"REGISTER", "UNDO"}
+    bl_description = "Expand/Collapse Tangent Menu to Show/Hide Input Options"
+
+    def execute(self,context):
+        """Expand Menu.
+
+        Args:
+            context: Blender bpy.context instance.
+
+        Returns:
+            Nothing.
+        """
+        scene = context.scene
+        pg = scene.pdt_pg
+        if pg.menu_expand:
+            pg.menu_expand = False
+        else:
+            pg.menu_expand = True
+        return {"FINISHED"}
diff --git a/precision_drawing_tools/__init__.py b/precision_drawing_tools/__init__.py
index 298b2d9ce0e12eeb05c758b379d74b2c6c5d23f8..4aeecd26090c3a7ead235efb9e05d080e7315fa3 100644
--- a/precision_drawing_tools/__init__.py
+++ b/precision_drawing_tools/__init__.py
@@ -413,6 +413,9 @@ class PDTSceneProperties(PropertyGroup):
         name="Coordst3", default=(0.0, 0.0, 0.0), subtype="XYZ", description=PDT_DES_TANCEN3
     )
     tangent_from_point: BoolProperty(name="From Point", default=False, description=PDT_DES_TPOINT)
+    menu_expand: BoolProperty(
+        name="Expand", default=False, description="Expand/Collapse Menu",
+    )
 
 
 class PDTPreferences(AddonPreferences):
@@ -502,8 +505,12 @@ classes = (
     pdt_pivot_point.PDT_OT_PivotWrite,
     pdt_pivot_point.PDT_OT_PivotRead,
     pdt_tangent.PDT_OT_TangentOperate,
+    pdt_tangent.PDT_OT_TangentOperateSel,
     pdt_tangent.PDT_OT_TangentSet1,
     pdt_tangent.PDT_OT_TangentSet2,
+    pdt_tangent.PDT_OT_TangentSet3,
+    pdt_tangent.PDT_OT_TangentSet4,
+    pdt_tangent.PDT_OT_TangentExpandMenu,
     pdt_view.PDT_OT_ViewRot,
     pdt_view.PDT_OT_ViewRotL,
     pdt_view.PDT_OT_ViewRotR,
diff --git a/precision_drawing_tools/pdt_exception.py b/precision_drawing_tools/pdt_exception.py
index d0dc157a93a7a22322dbcc61edcca8e65e7d7d4f..601f51413eedef1895b2f2b389c7ed967841625e 100644
--- a/precision_drawing_tools/pdt_exception.py
+++ b/precision_drawing_tools/pdt_exception.py
@@ -85,3 +85,7 @@ class ShaderError(Exception):
 class FeatureError(Exception):
     """Wrong Feature Type Error Exception."""
     pass
+
+class DistanceError(Exception):
+    """Invalid Distance (Separation) Error."""
+    pass
diff --git a/precision_drawing_tools/pdt_functions.py b/precision_drawing_tools/pdt_functions.py
index 3d12c4f99b6581cd92274597f239b89bce7d0339..38879618f713891ab4f780ef569afe78e0b3fc21 100644
--- a/precision_drawing_tools/pdt_functions.py
+++ b/precision_drawing_tools/pdt_functions.py
@@ -111,6 +111,7 @@ def set_mode(mode_pl):
 
     Note:
         Sets indices of axes for locational vectors:
+        a3 is normal to screen, or depth
         "XY": a1 = x, a2 = y, a3 = z
         "XZ": a1 = x, a2 = z, a3 = y
         "YZ": a1 = y, a2 = z, a3 = x
@@ -126,6 +127,7 @@ def set_mode(mode_pl):
         "XY": (0, 1, 2),
         "XZ": (0, 2, 1),
         "YZ": (1, 2, 0),
+        "LO": (0, 1, 2),
     }
     return order[mode_pl]
 
diff --git a/precision_drawing_tools/pdt_menus.py b/precision_drawing_tools/pdt_menus.py
index 1632730c16315d1b00e7f29b7012f215d5f0a48d..649b2b962af9da336d4137cf5b55676145ff8283 100644
--- a/precision_drawing_tools/pdt_menus.py
+++ b/precision_drawing_tools/pdt_menus.py
@@ -426,30 +426,50 @@ class PDT_PT_PanelTangent(Panel):
     def draw(self,context):
         layout = self.layout
         pdt_pg = context.scene.pdt_pg
-        # First Centre & Radius
-        row = layout.row()
-        split = row.split(factor=0.35, align=True)
-        split.label(text="Centre 1")
-        split.prop(pdt_pg, "tangent_point0", text="")
-        row = layout.row()
-        split = row.split(factor=0.45, align=False)
-        split.operator("pdt.tangentset1", text="Set From Arc")
-        split.prop(pdt_pg, "tangent_radius0", text="")
 
-        # Second Centre & Radius
+        if pdt_pg.menu_expand:
+            icon_e = "EVENT_C"
+        else:
+            icon_e = "EVENT_E"
         row = layout.row()
-        split = row.split(factor=0.35, align=True)
-        split.label(text="Centre 2")
-        split.prop(pdt_pg, "tangent_point1", text="")
+        row.label(text=f"Working {PDT_LAB_PLANE}:")
+        row.prop(pdt_pg, "plane", text="")
         row = layout.row()
-        split = row.split(factor=0.45, align=False)
-        split.operator("pdt.tangentset2", text="Set From Arc")
-        split.prop(pdt_pg, "tangent_radius1", text="")
-
+        row.operator("pdt.tangentoperatesel", text="Tangents from Selection", icon="NONE")
         row = layout.row()
-        row.operator("pdt.tangentoperate", text="Execute", icon="NONE")
+        row.label(text="Or Use Tangents From Inputs")
+        row.operator("pdt.tangentexpandmenu", text="", icon=icon_e)
+
+        box = layout.box()
+        row = box.row()
         row.prop(pdt_pg, "tangent_from_point", text="From Point")
-        row = layout.row()
+        row = box.row()
         split = row.split(factor=0.35, align=True)
         split.label(text="Tan Point")
         split.prop(pdt_pg, "tangent_point2", text="")
+        row = box.row()
+        row.operator("pdt.tangentset3", text="from Cursor")
+        row.operator("pdt.tangentset4", text="from Vertex")
+
+        if pdt_pg.menu_expand:
+            box = layout.box()
+            row = box.row()
+            split = row.split(factor=0.35, align=True)
+            split.label(text="Centre 1")
+            split.prop(pdt_pg, "tangent_point0", text="")
+            row = box.row()
+            split = row.split(factor=0.45, align=False)
+            split.operator("pdt.tangentset1", text="Set From Arc")
+            split.prop(pdt_pg, "tangent_radius0", text="")
+
+            # Second Centre & Radius
+            row = box.row()
+            split = row.split(factor=0.35, align=True)
+            split.label(text="Centre 2")
+            split.prop(pdt_pg, "tangent_point1", text="")
+            row = box.row()
+            split = row.split(factor=0.45, align=False)
+            split.operator("pdt.tangentset2", text="Set From Arc")
+            split.prop(pdt_pg, "tangent_radius1", text="")
+            row = box.row()
+            row.operator("pdt.tangentoperate", text="Tangents From Inputs", icon="NONE")
diff --git a/precision_drawing_tools/pdt_msg_strings.py b/precision_drawing_tools/pdt_msg_strings.py
index 9eeb08f17b125b6abd18f01216ac2abeece8fb28..0233a8c1fdb93e222d59f5f5271b5f8d850c8034 100644
--- a/precision_drawing_tools/pdt_msg_strings.py
+++ b/precision_drawing_tools/pdt_msg_strings.py
@@ -151,6 +151,9 @@ PDT_ERR_2CPNPE = "Select 2 Co-Planar Non-Parallel Edges"
 PDT_ERR_NCEDGES = "Edges must be Co-Planar Non-Parallel Edges, Selected Edges aren't"
 PDT_ERR_1EDGE1FACE = "Select 1 face and 1 Detached Edge"
 PDT_ERR_NOINT = "No Intersection Found"
+PDT_ERR_BADDISTANCE = "Invalid Distance (Separtion) Error; Chosen Points too Close"
+PDT_ERR_MATHSERROR = "Maths Error - Check Working Plane"
+PDT_ERR_SAMERADII = "Circles have the same radius - Just offset the Edge between centres"
 
 # Info messages
 #