Exemplo n.º 1
0
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
Exemplo n.º 2
0
Arquivo: moves.py Projeto: raylee/CDT
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
Exemplo n.º 3
0
Arquivo: moves.py Projeto: raylee/CDT
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