def zip_hulls(base, triang): """ Given a triangulation containing two seperate hulls and the base edge connecting the hulls, triangulate the space between the hulls. This is refered to as 'zipping' the hulls together. Parameters ---------- base : int index of base edge triang : TriangulationEdges Incomplete triangulation, with known base edge Returns ------- d_triang : TriangulationEdges Instance of TriangulationEdges class object containing the finished Delaunay triangulation of the input triangulation. """ while True: # Make variables for commonly used base edge points base1 = triang.points[triang.edges[base].org] base2 = triang.points[triang.edges[base].dest] # Find the first candidate edges for triangulation from each subset rcand = triang.edges[triang.edges[base].sym].onext pt1 = triang.points[triang.edges[rcand].dest] rcand_valid = linalg.on_right(base1, base2, pt1) lcand = triang.edges[base].oprev pt2 = triang.points[triang.edges[lcand].dest] lcand_valid = linalg.on_right(base1, base2, pt2) # If neither candidate is valid, hull merge is complete if not rcand_valid and not lcand_valid: break if rcand_valid: triang, rcand = rcand_func(triang, rcand, base1, base2) if lcand_valid: triang, lcand = lcand_func(triang, lcand, base1, base2) lcand_strong_valid = candidate_decider(rcand, lcand, lcand_valid, triang) if not rcand_valid or lcand_strong_valid: base = triang.connect(lcand, triang.edges[base].sym) else: base = triang.connect(triang.edges[base].sym, triang.edges[rcand].sym) return triang
def triangle_primitive(pts_subset): """ This function takes a list of three points and forms three edges to create a single triangle. This triangle has the property that the origin of one edge is connected to the destination of the next edge in a CCW orientation. Parameters ---------- pts_index : list List of the indices of the three points pts_subset : lists of lists A set of three points with the form [ [x1, y1], [x2, y2] , [x3, y3] ] Returns ------- out1 : int Index of edge with the left most point ou2 : int Index of the edge with the right most point edges : TriangulationEdges The resulting triangulation of three points """ p1, p2, p3 = 0, 1, 2 triang = edge_topology.TriangulationEdges(pts_subset) # Create the first two edges of the triangle edge1, edge1_sym = edge_topology.setup_edge(p1, p2, 0) triang.push_back(edge1) triang.push_back(edge1_sym) edge2, edge2_sym = edge_topology.setup_edge(p2, p3, 2) triang.push_back(edge2) triang.push_back(edge2_sym) triang.splice(edge1_sym.index, edge2.index) # To maintain the counter-clockwise orientation of the edges in the # triangle, we determine where p3 is in relation to the two existing edges. pt1 = pts_subset[triang.edges[edge1.index].org] pt2 = pts_subset[triang.edges[edge1.index].dest] pt3 = pts_subset[p3] if linalg.on_right(pt1, pt2, pt3): # Points are in CCW orientiaton c = triang.connect(edge2.index, edge1.index) triang.set_extreme_edges(edge1.index, edge2_sym.index) return triang if linalg.on_left(pt1, pt2, pt3): # Points are in CW orientiaton c = triang.connect(edge2.index, edge1.index) triang.set_extreme_edges(triang.edges[c].sym, c) return triang # Points are collinear triang.set_extreme_edges(edge1.index, edge2_sym.index) return triang
def lowest_common_tangent(h_left, h_right): """ Given two fully triangulated sets of points, this function finds an edge connecting the two triangulations. Each triangulation forms a convex hull of edges. The edge to be found by this function is the edge with the lowest y-value point which is still tangential to both hulls. This is known as the 'base' edge, as it is the first edge connecting two separately triangulated point sets. Parameters ---------- h_left : TriangulationEdges h_right : TriangulationEdges Returns ------- left_e : int The index of the edge in the right hull which forms one end of the base edge right_e : int The index of the edge in the left hull which forms the other end of the base edge """ left_e = h_left.outer right_e = h_right.inner pts_left = h_left.points pts_right = h_right.points p1 = pts_left[h_left.edges[left_e].org] p2 = pts_left[h_left.edges[left_e].dest] p4 = pts_right[h_right.edges[right_e].org] p5 = pts_right[h_right.edges[right_e].dest] while True: if linalg.on_right(p1, p2, pts_right[h_right.edges[right_e].org]): left_e = h_left.edges[h_left.edges[left_e].sym].onext p1 = pts_left[h_left.edges[left_e].org] p2 = pts_left[h_left.edges[left_e].dest] elif linalg.on_left(p4, p5, pts_left[h_left.edges[left_e].org]): right_e = h_right.edges[h_right.edges[right_e].sym].oprev p4 = pts_right[h_right.edges[right_e].org] p5 = pts_right[h_right.edges[right_e].dest] else: return left_e, right_e
def lcand_func(lhull, lcand, b1, b2): """ This function performs the same task as the above 'rcand_func' but testing for the left candidate edge. """ completed = False while not completed: lcand_oprev_dest = lhull.edges[lhull.edges[lcand].oprev].dest lcand_dest = lhull.edges[lcand].dest ccw_test = linalg.on_right(b1, b2, lhull.points[lcand_oprev_dest]) next_cand_invalid = linalg.in_circle(b2, b1, lhull.points[lcand_dest], lhull.points[lcand_oprev_dest]) if ccw_test and next_cand_invalid: t = lhull.edges[lcand].oprev lhull.kill_edge(lcand) lcand = t else: completed = True return lhull, lcand
def rcand_func(rhull, rcand, b1, b2): """ This function finds the candidate edge from the right hull triangulation. An initial candidate 'rcand' is given. This candidate is tested. If the candidate fails it is deleted from the triangulation and the next potential candiate is considered. While a valid candidate has not been found this process continues until a valid candidate is found. Parameters ---------- rhull : TriangulationEdges The triangulation of edges on the right hand side rcand : TYPE DESCRIPTION. b1 : list DESCRIPTION. b2 : list DESCRIPTION. Returns ------- rhull : TriangulationEdges DESCRIPTION. rcand : TYPE DESCRIPTION. """ completed = False while not completed: rcand_onext_dest = rhull.edges[rhull.edges[rcand].onext].dest rcand_dest = rhull.edges[rcand].dest ccw_test = linalg.on_right(b1, b2, rhull.points[rcand_onext_dest]) next_cand_invalid = linalg.in_circle(b2, b1, rhull.points[rcand_dest], rhull.points[rcand_onext_dest]) if ccw_test and next_cand_invalid: t = rhull.edges[rcand].onext rhull.kill_edge(rcand) rcand = t else: completed = True return rhull, rcand