diff --git a/resources/graphs/basic_graph/graph.py b/resources/graphs/basic_graph/graph.py
index 474209a33dc6fd02d2e06221d880a7e96a439dfb..fb6473e8f188912b99b6a9b19e443b051918fc26 100644
--- a/resources/graphs/basic_graph/graph.py
+++ b/resources/graphs/basic_graph/graph.py
@@ -216,14 +216,36 @@ class BasicGraphDisplay():
         """
         Assigns Graph mapping coordinates for all nodes.
         Accomplishes this with random assignment, on a grid of 100 by 100, such that no nodes should overlap.
+
+        If graph is of type that has "start" or "end" nodes, then it's modified to be slightly more organized.
+        Accomplishes this by putting initial/start nodes on the far left, and final nodes on far right.
+        All other node coordinates are randomly assigned to the center.
         """
+        # Get "start" and "end" node lists.
+        start_node_list, end_node_list = self._get_start_and_end_node_lists()
+
+        # Get all possible node position coordinates.
         max_direction = 100
         possible_positions = []
 
-        # Create list of "possible_positions". Should be a list of every possible (x,y) coordinate pairing.
-        for x_index in range(int(max_direction)):
-            for y_index in range(int(max_direction)):
-                possible_positions.append((x_index, y_index))
+        # If start or end node lists exist, we want to limit coordinate positioning slightly.
+        if len(start_node_list) != 0 or len(end_node_list) != 0:
+            logger.info('start or end node lists is greater than length 0.')
+
+            # Create list of "possible_positions". Should exclude far left or far right coordinates.
+            for x_index in range(int(max_direction)):
+                # We want to limit x-coords, preventing random assignment to x-coords less than 10 or greater than 90.
+                if x_index > 10 and x_index < 90:
+                    # Given x-coord is between values we want. Proceed.
+                    for y_index in range(int(max_direction)):
+                        possible_positions.append((x_index, y_index))
+
+        else:
+            logger.info('Start or end node lists is length 0.')
+            # Create list of "possible_positions". Should be a list of every possible (x,y) coordinate pairing.
+            for x_index in range(int(max_direction)):
+                for y_index in range(int(max_direction)):
+                    possible_positions.append((x_index, y_index))
 
         # Values to remember extreme coord values, as well as associated nodes.
         farthest_x = (0, None)
@@ -231,24 +253,84 @@ class BasicGraphDisplay():
         shortest_x = (100, None)
         shortest_y = (100, None)
 
-        # Now go through all nodes, assigning one to a random position.
-        # As long as there are less than 1000 nodes, this should work without issues.
+        # Loop through all "end" states, assigning y-coords based on a divided grid setup.
+        # Grids are from top to bottom, to evenly distribute space to all final nodes.
+        # Final states are done first, in case a node is both final and initial. In this case, we want it on the left.
+        # Going first means that the initial state logic will override the final state logic, putting it left like we
+        # want.
+        end_node_count = len(end_node_list)
+        if end_node_count > 0:
+            state_index = 1
+            grid_length = max_direction / end_node_count
+            for end_state in end_node_list:
+                # Get grid values.
+                current_grid_end = grid_length * state_index
+                current_grid_start = current_grid_end - grid_length
+                state_index += 1
+
+                # Assign node to calculated grid.
+                x_coord = 95
+                y_coord = int((current_grid_start + current_grid_end) / 2)
+                self._parent._nodes[end_state.get_name()].x_coord = x_coord
+                self._parent._nodes[end_state.get_name()].y_coord = y_coord
+
+                # Record extreme positions.
+                if x_coord > farthest_x[0]:
+                    farthest_x = (x_coord, end_state)
+                if x_coord < shortest_x[0]:
+                    shortest_x = (x_coord, end_state)
+                if y_coord > farthest_y[0]:
+                    farthest_y = (y_coord, end_state)
+                if y_coord < shortest_y[0]:
+                    shortest_y = (y_coord, end_state)
+
+        # Loop through all initial states, assigning y-coords based on a divided grid setup.
+        # Grids are from top to bottom, to evenly distribute space to all start nodes.
+        start_node_count = len(start_node_list)
+        if start_node_count > 0:
+            state_index = 1
+            grid_length = max_direction / start_node_count
+            for start_node in start_node_list:
+                # Get grid values.
+                current_grid_end = grid_length * state_index
+                current_grid_start = current_grid_end - grid_length
+                state_index += 1
+
+                # Assign node to calculated grid.
+                x_coord = 5
+                y_coord = int((current_grid_start + current_grid_end) / 2)
+                self._parent._nodes[start_node.get_name()].x_coord = x_coord
+                self._parent._nodes[start_node.get_name()].y_coord = y_coord
+
+                # Record extreme positions.
+                if x_coord > farthest_x[0]:
+                    farthest_x = (x_coord, start_node)
+                if x_coord < shortest_x[0]:
+                    shortest_x = (x_coord, start_node)
+                if y_coord > farthest_y[0]:
+                    farthest_y = (y_coord, start_node)
+                if y_coord < shortest_y[0]:
+                    shortest_y = (y_coord, start_node)
+
+        # Loop through all currently unassigned nodes and assign coordinates.
         for node in self._parent.nodes.all().values():
-            # Get a random position.
-            index = randint(0, len(possible_positions) - 1)
-            position = possible_positions.pop(index)
-            self._parent._nodes[node.get_name()].x_coord = position[0]
-            self._parent._nodes[node.get_name()].y_coord = position[1]
-
-            # Record extreme positions.
-            if position[0] > farthest_x[0]:
-                farthest_x = (position[0], node)
-            if position[0] < shortest_x[0]:
-                shortest_x = (position[0], node)
-            if position[1] > farthest_y[0]:
-                farthest_y = (position[1], node)
-            if position[1] < shortest_y[0]:
-                shortest_y = (position[1], node)
+            # Make sure node is not already assigned coordinates.
+            if node.x_coord is None or node.y_coord is None:
+                # Get a random position.
+                index = randint(0, len(possible_positions))
+                position = possible_positions.pop(index)
+                self._parent._nodes[node.get_name()].x_coord = position[0]
+                self._parent._nodes[node.get_name()].y_coord = position[1]
+
+                # Record extreme positions.
+                if position[0] > farthest_x[0]:
+                    farthest_x = (position[0], node)
+                if position[0] < shortest_x[0]:
+                    shortest_x = (position[0], node)
+                if position[1] > farthest_y[0]:
+                    farthest_y = (position[1], node)
+                if position[1] < shortest_y[0]:
+                    shortest_y = (position[1], node)
 
         # Now that all nodes are mapped, adjust extreme node coords, so that all graphs will be roughly the same size.
         if shortest_x[0] > 10:
@@ -279,6 +361,14 @@ class BasicGraphDisplay():
             self._parent._edges[edge.get_name()].y1_coord = node_1.y_coord
             self._parent._edges[edge.get_name()].y2_coord = node_2.y_coord
 
+    def _get_start_and_end_node_lists(self):
+        """
+        Returns lists of "start" and "end" nodes in graph.
+
+        "Basic" graphs do not have these node types so it returns empty lists.
+        """
+        return ([], [])
+
     def _create_node_mapping(self):
         """
         Maps graph nodes to values that the Visual Mapping can understand.
diff --git a/resources/graphs/directed_graph/graph.py b/resources/graphs/directed_graph/graph.py
index 130297829ff0c3129a7666d350232abda7820834..a70c9ca68dc69148a7299b566bffc36fe6c20db5 100644
--- a/resources/graphs/directed_graph/graph.py
+++ b/resources/graphs/directed_graph/graph.py
@@ -11,6 +11,7 @@ Parent structure containing various Nodes and Edges.
 
 # System Imports.
 import math
+from random import randint
 
 # User Class Imports.
 from .components import DirectedEdge, DirectedNode
@@ -63,6 +64,30 @@ class DirectedGraphDisplay(BasicGraphDisplay):
         # Get calling parent.
         self._parent = parent
 
+    def _get_start_and_end_node_lists(self):
+        """
+        Returns lists of "start" and "end" nodes in graph.
+
+        For a directed graph, "start" nodes are all nodes with only outgoing edges.
+        "End" nodes are all nodes with only incoming edges.
+        """
+        start_node_list = []
+        end_node_list = []
+
+        # Find all nodes that only have inward edges.
+        for node in self._parent._nodes.values():
+            # Check that node has at least 1 edge and no edges are outgoing.
+            if node.get_edge_count() > 0 and len(node.get_outgoing_nodes()) == 0:
+                end_node_list.append(node)
+
+        # Find all nodes that only have outward edges.
+        for node in self._parent._nodes.values():
+            # Check that node has at least 1 edge and no edges are incoming.
+            if node.get_edge_count() > 0 and len(node.get_incoming_nodes()) == 0:
+                start_node_list.append(node)
+
+        return (start_node_list, end_node_list)
+
     def _create_additional_edge_mappings(self):
         """
         Creates additional visual edge direction "pointer" mappings for all edge.
diff --git a/resources/graphs/state_machine/graph.py b/resources/graphs/state_machine/graph.py
index 3b7ad1c781c739e2f3416199c7a2d582459a5668..3ba6d4b086a02372f65e83685bcd7188722a734b 100644
--- a/resources/graphs/state_machine/graph.py
+++ b/resources/graphs/state_machine/graph.py
@@ -67,129 +67,14 @@ class StateMachineGraphDisplay(DirectedGraphDisplay):
         # Get calling parent.
         self._parent = parent
 
-    def _assign_node_coordinates(self):
+    def _get_start_and_end_node_lists(self):
         """
-        Assigns Graph mapping coordinates for all nodes.
-        Still mostly random coordinate assignment (just like the basic graph). However, slightly more organized.
-        Accomplishes this by putting initial/start nodes on the far left, and final nodes on far right.
-        All other node coordinates are randomly assigned to the center.
+        Returns lists of "start" and "end" nodes in graph.
+
+        For a State Machine graph, "start" nodes are all nodes marked with an "initial" state.
+        "End" nodes are all nodes marked with a "final" state.
         """
-        max_direction = 100
-        possible_positions = []
-
-        # Create list of "possible_positions". Should be a list of every possible (x,y) coordinate pairing.
-        for x_index in range(int(max_direction)):
-            # We want to limit x-coords, preventing random assignment to x-coords less than 10 or greater than 90.
-            if x_index > 10 and x_index < 90:
-                # Given x-coord is between values we want. Proceed.
-                for y_index in range(int(max_direction)):
-                    possible_positions.append((x_index, y_index))
-
-        # Values to remember extreme coord values, as well as associated nodes.
-        farthest_x = (0, None)
-        farthest_y = (0, None)
-        shortest_x = (100, None)
-        shortest_y = (100, None)
-
-        # Loop through all final states, assigning y-coords based on a divided grid setup.
-        # Grids are from top to bottom, to evenly distribute space to all final nodes.
-        # Final states are done first, in case a node is both final and initial. In this case, we want it on the left.
-        # Going first means that the intial state logic will override the final state logic, putting it left like we
-        # want.
-        final_state_count = len(self._parent._final_states)
-        state_index = 1
-        grid_length = max_direction / final_state_count
-        for final_state in self._parent._final_states.values():
-            # Get grid values.
-            current_grid_end = grid_length * state_index
-            current_grid_start = current_grid_end - grid_length
-            state_index += 1
-
-            # Assign node to calculated grid.
-            x_coord = 95
-            y_coord = int((current_grid_start + current_grid_end) / 2)
-            self._parent._nodes[final_state.get_name()].x_coord = x_coord
-            self._parent._nodes[final_state.get_name()].y_coord = y_coord
-
-            # Record extreme positions.
-            if x_coord > farthest_x[0]:
-                farthest_x = (x_coord, final_state)
-            if x_coord < shortest_x[0]:
-                shortest_x = (x_coord, final_state)
-            if y_coord > farthest_y[0]:
-                farthest_y = (y_coord, final_state)
-            if y_coord < shortest_y[0]:
-                shortest_y = (y_coord, final_state)
-
-        # Loop through all initial states, assigning y-coords based on a divided grid setup.
-        # Grids are from top to bottom, to evenly distribute space to all start nodes.
-        initial_state_count = len(self._parent._initial_states)
-        state_index = 1
-        grid_length = max_direction / initial_state_count
-        for initial_state in self._parent._initial_states.values():
-            # Get grid values.
-            current_grid_end = grid_length * state_index
-            current_grid_start = current_grid_end - grid_length
-            state_index += 1
-
-            # Assign node to calculated grid.
-            x_coord = 5
-            y_coord = int((current_grid_start + current_grid_end) / 2)
-            self._parent._nodes[initial_state.get_name()].x_coord = x_coord
-            self._parent._nodes[initial_state.get_name()].y_coord = y_coord
-
-            # Record extreme positions.
-            if x_coord > farthest_x[0]:
-                farthest_x = (x_coord, initial_state)
-            if x_coord < shortest_x[0]:
-                shortest_x = (x_coord, initial_state)
-            if y_coord > farthest_y[0]:
-                farthest_y = (y_coord, initial_state)
-            if y_coord < shortest_y[0]:
-                shortest_y = (y_coord, initial_state)
-
-        # Now loop through all other nodes and assign coordinates.
-        for node in self._parent.nodes.all().values():
-            # Make sure node is not already assigned coordinates.
-            if node.x_coord is None or node.y_coord is None:
-                # Get a random position.
-                index = randint(0, len(possible_positions))
-                position = possible_positions.pop(index)
-                self._parent._nodes[node.get_name()].x_coord = position[0]
-                self._parent._nodes[node.get_name()].y_coord = position[1]
-
-                # Record extreme positions.
-                if position[0] > farthest_x[0]:
-                    farthest_x = (position[0], node)
-                if position[0] < shortest_x[0]:
-                    shortest_x = (position[0], node)
-                if position[1] > farthest_y[0]:
-                    farthest_y = (position[1], node)
-                if position[1] < shortest_y[0]:
-                    shortest_y = (position[1], node)
-
-        # Now that all nodes are mapped, adjust extreme node coords, so that all graphs will be roughly the same size.
-        if shortest_x[0] > 10:
-            shortest_x[1].x_coord = 10
-        if shortest_y[0] > 10:
-            shortest_y[1].y_coord = 10
-        if farthest_x[0] < 90:
-            farthest_x[1].x_coord = 90
-        if farthest_y[0] < 90:
-            farthest_y[1].y_coord = 90
-
-        # Now go through all edges and do similar.
-        for edge in self._parent.edges.all().values():
-            node_list = edge.get_nodes()
-
-            node_1 = node_list['tail_node']
-            node_2 = node_list['head_node']
-
-            # Assign edge coordinates.
-            self._parent._edges[edge.get_name()].x1_coord = node_1.x_coord
-            self._parent._edges[edge.get_name()].x2_coord = node_2.x_coord
-            self._parent._edges[edge.get_name()].y1_coord = node_1.y_coord
-            self._parent._edges[edge.get_name()].y2_coord = node_2.y_coord
+        return (self._parent._initial_states.values(), self._parent._final_states.values())
 
     def _create_node_hover_text(self):
         """