def build_sub_edges_of_triangle(point_list_or_triangle_object): """ Takes either a triangle class instance or a set of three points as input and makes the edges that a triangle defined this way would contain. Checks for redundancies. """ if type(point_list_or_triangle_object) == list: vertices = set(point_list_or_triangle_object) elif type(point_list_or_triangle_object) == tuple: vertices = set(point_list_or_triangle_object) elif type(point_list_or_triangle_object) == set: vertices = point_list_or_triangle_object elif isinstance(point_list_or_triangle_object,triangle): vertices = set(point_list_or_triangle_object.vertices) else: # This is a way to give more verbose error messages print "ERROR: You have passed the function" print "'build_sub_edges_of_triangle'" print "an object that is not a list, a set, a tuple," + \ "or a triangle class instance." print "The object was: {}".format(point_list_or_triangle_object) assert isinstance(point_list_or_triangle_object,triangle) \ or type(point_list_or_triangle_object) == list \ or type(point_list_or_triangle_object) == tuple \ or type(point_list_or_triangle_object) == set # A triangle should only have 3 vertices assert error_checking.check_length(vertices,3,'triangle', 'build_sub_edges_of_triangle') # Now calculate the points the subsimplices contain ordered_pairs = ut.k_combinations(vertices,2) # The ids of our subsimplices. This will be a return value. edge_ids = set([]) # For each edge, check to see if it exists. If it does not, make it. for pair in ordered_pairs: duplicates = edge.find_duplicates(pair) # If there are no duplicates, then we need to make this edge if len(duplicates) == 0: # And tell our triangle it exists new_edge = edge(pair) edge_ids.add(new_edge.id) # And add it to the edge instances hash table edge.add(new_edge) # If there is exactly one duplicate, then we simply add its id # to the triangle's edge ID list elif len(duplicates) == 1: edge_ids.add(duplicates[0]) else: # If there is more than one duplicate, something went # very wrong. error_checking.too_many_duplicates('edge',pair,duplicates,1, 'build_sub_edges_of_triangle') # There should be exactly 3 edge ids. assert error_checking.check_length(edge_ids,3,'edge_ids', 'build_sub_edges_of_triangle') return edge_ids
def move_3_to_1(cmpx): "Applies a 3->1 move to the input complex, cmpx." # Extract the complex, which contains three triangles. if len(cmpx.get_triangles()) == 3: original_triangles = [sd.triangle.instances[i] \ for i in cmpx.get_triangles()] else: raise ValueError("There should be exactly 3 triangles for the " + "3->1 complex.") # Extract the boundary vertices original_vertices = [set(t.get_vertices()) for t in original_triangles] central_vertex = list(ut.set_intersection(original_vertices))[0] boundary_vertices = ut.set_union(original_vertices) \ - set([central_vertex]) boundary_vertex_ids = [v.get_id() for v in boundary_vertices] # Extract the edges to be removed (there are 3) # Lambda functions for clarity get_edges = lambda i: set(sd.triangle.instances[i].get_edges()) intersected_element = lambda L: ut.only_element(ut.set_intersection(L)) # Nested list comprehensions: take the intersection of the set of # edges associated with pairs of the triangles we care # about. These edges are flagged for deleteion. shared_edges = [intersected_element([get_edges(i) for i in c]) \ for c in ut.k_combinations(cmpx.get_triangles())] # There should only be 3 shared edges. If there are more, we messed up. assert len(shared_edges) == 3 # Make the new triangle new_triangle = sm.build_triangle_and_edges(boundary_vertex_ids) # Clean up for t in original_triangles: # Delete the old triangles: sm.remove_triangle(t) for e in shared_edges: # Delete the old edges. sm.remove_edge(e) sd.vertex.delete(central_vertex) # Delete the old vertex # Set triangles, neihgbors, and check topology set_neighbors_and_triangles(boundary_vertices,[new_triangle]) return True
def complex_2_to_2(simplex_id_or_simplex): """ Takes a simplex or simplex id as input and calculates what, if any, complices are topologically acceptable to operate on. If there's more than one, return one at random. If there are none, return False. The 2->2 move equires that the new edge not already exist (there are cases when it does) and that the endpoints of the deleted edge each have >=4 triangles attached to them before the move is applied. """ # Declare local constants pair_length = 2 # The length of a pair neighbor_length = 3 # The number of vertices a triangle must have. # Extract data for the first triangle # Extract triangle t1 = extract_triangle(simplex_id_or_simplex) # Extract neighbors t1_neighbors = t1.get_neighbors() # Extract vertices t1_vertices = t1.get_vertices() # If we can find a pair of vertices of t1 that each have >=4 # triangles attached, then these vertices might be good choices of # endpoints for the edge we will delete. possible_endpoints = [v for v in t1_vertices if len(v) >= 4] # If there are fewer than two possible endpoints, no acceptable # edge exists, so me might as well give up. if len(possible_endpoints) < 2: return False else: # If >=2 possible endpoints exist, get all possible pairs: possible_endpoint_pairs = ut.k_combinations(possible_endpoints,2) # The other triangle in the complex will be the neighbor that # shares the chosen pair of of endpoint vertices. We want to keep # track of which pair this is associated with. acceptable_neighbors = [(p,n) for p in possible_endpoint_pairs \ for n in t1_neighbors \ if p.issubset(n.get_vertices())] # We will be making an edge between the unshared vertices of the # two neighboring triangles. We have to make sure that this edge # does not yet exist. # A function to calculate the unshared vertices as a pair. Just # syntactic sugar. unshared_v = lambda p,n: ut.set_union([set(t1.get_vertices()), set(n.get_vertices())]) - set(p) # An acceptable complex has a pair of shared points, a neighbor, # and a pair of unshared points which are not the endpoints of an # existing edge. acceptable_cmpxs = [(p,n,unshared_v(p,n))\ for (p,n) in acceptable_neighbors \ if not sd.edge.exists(unshared_v(p,n))] # Double check to make sure we have what we expect. acceptable_cmpxs = [(p,n,u) for (p,n,u) in acceptable_cmpxs \ if len(p) == pair_length\ and len(n) == neighbor_length\ and len(u) == pair_length] # We have everything. If it exists, stick it in a complex and # return it. Otherwise, return false. if acceptable_cmpxs: chosen_complex = random.choice(acceptable_cmpxs) triangles = [t1,chosen_complex[1]] shared_vertices = chosen_complex[0] unshared_vertices = chosen_complex[2] cmpx = complex22(triangles) cmpx.set_shared_vertices(shared_vertices) cmpx.set_unshared_vertices(unshared_vertices) return cmpx else: return False