Пример #1
0
	def solve_triangular_faces(self):
		"""Modify the decomposition mesh from polylines to make it a quad mesh by converting the degenerated quad faces that appear as triangular faces.

		"""

		mesh = self.mesh

		for fkey in list(mesh.faces()):
			if len(mesh.face_vertices(fkey)) == 3:

				boundary_vertices = [vkey for vkey in mesh.face_vertices(fkey) if mesh.is_vertex_on_boundary(vkey)]
				case = sum(mesh.is_vertex_on_boundary(vkey) for vkey in mesh.face_vertices(fkey))

				if case == 1:
					#convert triangular face to quad by duplicating the boundary vertex
					#due to compas_singular face vertices at the same location
					u = boundary_vertices[0]
					v = mesh.add_vertex(attr_dict = {attr: xyz for attr, xyz in zip(['x', 'y', 'z'], mesh.vertex_coordinates(u))})

					# modify adjacent faces
					vertex_faces = mesh.vertex_faces(u, ordered = True)
					mesh_substitute_vertex_in_faces(mesh, u, v, vertex_faces[: vertex_faces.index(fkey)])

					# modify triangular face
					mesh_insert_vertex_on_edge(mesh, u, mesh.face_vertex_ancestor(fkey, u), v)

				elif case == 2:
					# remove triangular face and merge the two boundary vertices
					# due to singularities at the same location
					polyline = Polyline(self.decomposition_polyline(*map(lambda x: geometric_key(mesh.vertex_coordinates(x)), boundary_vertices)))
					point = polyline.point(t = .5, snap = True)
					new_vkey = mesh.add_vertex(attr_dict = {'x': point.x, 'y': point.y , 'z': point.z})

					# modify triangular face
					mesh.delete_face(fkey)

					# modify adjacent faces
					for old_vkey in boundary_vertices:
						mesh_substitute_vertex_in_faces(mesh, old_vkey, new_vkey, mesh.vertex_faces(old_vkey))
						mesh.delete_vertex(old_vkey)

		to_move = {}
		# give some length to the new edge
		for edge in mesh.edges():
			threshold = 1e-6
			if mesh.edge_length(*edge) < threshold:
				for vkey in edge:
					xyz = centroid_points([mesh.vertex_coordinates(nbr) for nbr in mesh.vertex_neighbors(vkey)])
					xyz0 = mesh.vertex_coordinates(vkey)
					to_move[vkey] = [0.1 * (a - a0) for a, a0 in zip(xyz, xyz0)]

		for vkey, xyz in to_move.items():
			attr = mesh.vertex[vkey]
			attr['x'] += xyz[0]
			attr['y'] += xyz[1]
			attr['z'] += xyz[2]
Пример #2
0
def test_mesh_substitute_vertex_in_faces(mesh_0):
    mesh_substitute_vertex_in_faces(mesh_0, 0, 4)
    assert 4 in mesh_0.face_vertices(0)
    assert 0 not in mesh_0.face_vertices(0)
    assert 4 in mesh_0.face_vertices(1)
    assert 0 not in mesh_0.face_vertices(1)
    mesh_substitute_vertex_in_faces(mesh_0, 4, 0, [1])
    assert 4 in mesh_0.face_vertices(0)
    assert 0 not in mesh_0.face_vertices(0)
    assert 0 in mesh_0.face_vertices(1)
    assert 4 not in mesh_0.face_vertices(1)
Пример #3
0
def delete_strip(mesh, skey, update_data=True):
    """Delete a strip.

	Parameters
	----------
	mesh : QuadMesh
		A quad mesh.
	skey : hashable
		A strip key.
	update_data : bool, optional
		Update strip data. Default is True.
 
	Returns
	-------
	skey_to_skeys : dict, None
		If strip splits were applied to preserve boundaries, a dictionary of the initial strip key to the refining strip keys. None otherwise.

	"""

    # build network between vertices of the edges of the strip to delete to get the disconnect parts of vertices to merge
    network = strip_edge_network(mesh, skey)
    disc_vertices = network_disconnected_vertices(network)

    # delete strip faces
    for fkey in mesh.strip_faces(skey):
        mesh.delete_face(fkey)

    old_vkeys_to_new_vkeys = {}

    # merge strip edge vertices that are connected
    for vertices in disc_vertices:

        # new vertex
        x, y, z = centroid_points(
            [mesh.vertex_coordinates(vkey) for vkey in vertices])
        new_vkey = mesh.add_vertex(attr_dict={'x': x, 'y': y, 'z': z})
        old_vkeys_to_new_vkeys.update(
            {old_vkey: new_vkey
             for old_vkey in vertices})

        # replace the old vertices
        for old_vkey in vertices:
            new_faces = mesh_substitute_vertex_in_faces(
                mesh, old_vkey, new_vkey, mesh.vertex_faces(old_vkey))

        # delete the old vertices
        for old_vkey in vertices:
            mesh.delete_vertex(old_vkey)

    # update strip data
    if update_data:
        update_strip_data(mesh, old_vkeys_to_new_vkeys)

    return old_vkeys_to_new_vkeys
Пример #4
0
def add_strip(mesh, polyedge):

	full_updated_polyedge = []
	# store data
	left_polyedge = []
	right_polyedge = []
	new_faces = []

	# exception if closed
	is_closed = polyedge[0] == polyedge[-1]
	if is_closed:
		polyedge.pop()

	k = -1
	count = len(polyedge) * 2
	while count and len(polyedge) > 0:
		k += 1
		count -= 1
		
		# select u, v, w if not closed
		if not is_closed:
			# u
			if len(new_faces) != 0:
				u1, u2 = left_polyedge[-1], right_polyedge[-1]
			else:
				u1, u2 = None, None
			# v
			v = polyedge.pop(0)
			full_updated_polyedge.append(v)
			# w
			if len(polyedge) != 0:
				w = polyedge[0]
			else:
				w = None
		
		# select u, v, w if closed
		else:
			# u
			if len(new_faces) != 0:
				u1, u2 = left_polyedge[-1], right_polyedge[-1]
			else:
				u1 = polyedge[-1] # artificial u1
			# v
			v = polyedge.pop(0)
			# w
			if len(polyedge) != 0:
				w = polyedge[0]
			else:
				w = left_polyedge[0]

		# add new vertices
		faces = sort_faces(mesh, u1, v, w)
		v1, v2 = mesh.add_vertex(attr_dict=mesh.vertex[v]), mesh.add_vertex(attr_dict=mesh.vertex[v])
		
		if type(faces[0]) == list:
			faces_1, faces_2 = faces
		else:
			# exception necessary for U-turns
			if faces[0] in mesh.vertex_faces(left_polyedge[-2]):
				faces_1 = faces
				faces_2 = []
			else:
				faces_1 = []
				faces_2 = faces
		mesh_substitute_vertex_in_faces(mesh, v, v1, faces_1)
		mesh_substitute_vertex_in_faces(mesh, v, v2, faces_2)
		mesh.delete_vertex(v)
		left_polyedge.append(v1)
		right_polyedge.append(v2)

		# add new faces, different if at the start, end or main part of the polyedge
		if len(new_faces) == 0:
			if not is_closed:
				new_faces.append(mesh.add_face([v1, w, v2]))
			else:
				new_faces.append(mesh.add_face([v1, v2, u1]))
				new_faces.append(mesh.add_face([v1, w, v2]))
		elif len(polyedge) == 0:
			if not is_closed:
				u1, u2 = left_polyedge[-2], right_polyedge[-2]
				face = new_faces.pop()
				mesh.delete_face(face)
				new_faces.append(mesh.add_face([u1, v1, v2, u2]))
			else:
				u1, u2 = left_polyedge[-2], right_polyedge[-2]
				face = new_faces.pop()
				mesh.delete_face(face)
				new_faces.append(mesh.add_face([v1, u1, u2, v2]))
				face = new_faces.pop(0)
				mesh.delete_face(face)
				u1, u2 = left_polyedge[0], right_polyedge[0]
				new_faces.append(mesh.add_face([v1, u1, u2, v2]))

				mesh_substitute_vertex_in_faces(mesh, v, v1)
				mesh_substitute_vertex_in_faces(mesh, v, v2)
		else:
			face = new_faces.pop()
			mesh.delete_face(face)
			new_faces.append(mesh.add_face([u1, v1, v2, u2]))
			new_faces.append(mesh.add_face([v1, w, v2]))

		# update
		updated_polyedge = []
		via_vkeys = [v1, v2]
		for i, vkey in enumerate(polyedge):
			if vkey != v:
				updated_polyedge.append(vkey)
			else:
				from_vkey = polyedge[i - 1]
				to_vkey = polyedge[i + 1]
				updated_polyedge += polyedge_from_to_via_vertices(mesh, from_vkey, to_vkey, via_vkeys)[1:-1]
		polyedge = updated_polyedge

	# include pseudo closed polyedges


	
	old_vkeys_to_new_vkeys = {u0: (u1, u2) for u0, u1, u2 in zip(full_updated_polyedge, left_polyedge, right_polyedge)}
	
	#for fkey in mesh.faces():
	#	print(mesh.face_vertices(fkey))
	n = update_strip_data(mesh, full_updated_polyedge, old_vkeys_to_new_vkeys)
	#print(left_polyedge, right_polyedge)
	return n, old_vkeys_to_new_vkeys
Пример #5
0
def add_strip(mesh, polyedge):
    """Add a strip along a mesh polyedge.

    Parameters
    ----------
    mesh : Mesh
        A mesh.
    polyedge : list
        List of vertex keys forming path.

    Returns
    -------
    new_skey, left_polyedge, right_polyedge : tuple
        The key of the new strip, the new strip vertices on the left, the new strip vertices on the right.

    """

    kinks_xyz = [
        mesh.vertex_coordinates(vkey) for vkey in mesh.boundary_kinks(pi / 12)
    ]

    # close or open status
    closed = polyedge[0] == polyedge[-1]

    # store transversal strips to update later
    update = {
        mesh.edge_strip(edge): i
        for i, edge in enumerate(pairwise(polyedge))
    }
    transverse_strips = set(update.keys())

    # list faces on the left and right of the polyedge
    left_faces = [mesh.halfedge[u][v] for u, v in pairwise(polyedge)]
    right_faces = [mesh.halfedge[v][u] for u, v in pairwise(polyedge)]

    # add extremities for looping on data
    if closed:
        left_faces = [left_faces[-1]] + left_faces + [left_faces[0]]
        right_faces = [right_faces[-1]] + right_faces + [right_faces[0]]
    else:
        left_faces = [None] + left_faces + [None]
        right_faces = [None] + right_faces + [None]

    # remove duplicat extremity
    if closed:
        polyedge.pop()

    # duplicate polyedge
    left_polyedge = [
        mesh.add_vertex(attr_dict=mesh.vertex[vkey]) for vkey in polyedge
    ]
    right_polyedge = [
        mesh.add_vertex(attr_dict=mesh.vertex[vkey]) for vkey in polyedge
    ]

    # store changes to apply all at once later
    to_substitute = {vkey: [] for vkey in polyedge}

    all_left_faces = []
    all_right_faces = []
    # collect all faces to update along polyedge with corresponding new vertex
    for i, vkey in enumerate(polyedge):
        vertex_faces = mesh.vertex_faces(vkey, ordered=True, include_none=True)
        # on the left
        faces = sublist_from_to_items_in_closed_list(vertex_faces,
                                                     left_faces[i],
                                                     left_faces[i + 1])
        all_left_faces += faces
        to_substitute[vkey].append((left_polyedge[i], faces))
        # on the right
        faces = sublist_from_to_items_in_closed_list(vertex_faces,
                                                     right_faces[i + 1],
                                                     right_faces[i])
        all_right_faces += faces
        to_substitute[vkey].append((right_polyedge[i], faces))

    all_left_faces = list(set(all_left_faces))
    all_right_faces = list(set(all_right_faces))
    left_strips = list(
        set([
            skey for fkey in all_left_faces if fkey is not None
            for skey in mesh.face_strips(fkey) if skey not in transverse_strips
        ]))
    right_strips = list(
        set([
            skey for fkey in all_right_faces if fkey is not None
            for skey in mesh.face_strips(fkey) if skey not in transverse_strips
        ]))

    # apply changes
    for key, substitutions in to_substitute.items():
        for substitution in substitutions:
            new_key, faces = substitution
            mesh_substitute_vertex_in_faces(
                mesh, key, new_key,
                [face for face in faces if face is not None])

    # delete old vertices
    for vkey in polyedge:
        mesh.delete_vertex(vkey)

    # add strip faces
    if closed:
        polyedge.append(polyedge[0])
        left_polyedge.append(left_polyedge[0])
        right_polyedge.append(right_polyedge[0])
    for i in range(len(polyedge) - 1):
        mesh.add_face([
            right_polyedge[i], right_polyedge[i + 1], left_polyedge[i + 1],
            left_polyedge[i]
        ])

    # update transverse strip data
    for skey, i in update.items():
        mesh.data['attributes']['strips'][skey] = mesh.collect_strip(
            *list(pairwise(left_polyedge))[i])

    # add new strip data
    new_skey = list(mesh.strips())[-1] + 1
    mesh.data['attributes']['strips'][new_skey] = mesh.collect_strip(
        left_polyedge[0], right_polyedge[0])

    # update adjacent strips
    for i in range(len(polyedge)):
        old, left, right = polyedge[i], left_polyedge[i], right_polyedge[i]
        mesh.substitute_vertex_in_strips(old, left, left_strips)
        mesh.substitute_vertex_in_strips(old, right, right_strips)

    func_1(mesh, kinks_xyz, 20, 0.5)

    return new_skey, left_polyedge, right_polyedge
Пример #6
0
def delete_strip(mesh, skey, preserve_boundaries=False):
    """Delete a strip.

    Parameters
    ----------
    mesh : QuadMesh
        A quad mesh.
    skey : hashable
        A strip key.
    preserve_boundaries : bool
        A boolean whether to preserve boundaries that would be collapsed by refining strips without adding singularities.

    Returns
    -------
    skey_to_skeys : dict, None
        If strip splits were applied to preserve boundaries, a dictionary of the initial strip key to the refining strip keys. None otherwise.

    """

    if skey not in list(mesh.strips()):
        return 0

    if preserve_boundaries:
        skey_to_skeys = split_strips(mesh,
                                     boundary_strip_preserve(mesh, [skey]))

    old_boundary_vertices = list(mesh.vertices_on_boundary())

    # get strip data
    strip_edges = mesh.strip_edges(skey)
    strip_faces = mesh.strip_faces(skey)

    # collateral strip deletions
    collateral_deleted_strips = []
    #print('strip_faces: ', strip_faces)
    for skey_2 in mesh.strips():
        if skey_2 == skey:
            continue
        #print('strip_faces_2: ', mesh.strip_faces(skey_2), [mesh.strip_faces(skey_2) in strip_faces])
        if all([fkey in strip_faces for fkey in mesh.strip_faces(skey_2)]):
            collateral_deleted_strips.append(skey_2)
    #print('collateral_deleted_strips: ', collateral_deleted_strips)

    # build network between vertices of the edges of the strip to delete to
    # get the disconnect parts of vertices to merge
    vertices = set([i for edge in strip_edges for i in edge])
    # maps between old and new indices
    old_to_new = {vkey: i for i, vkey in enumerate(vertices)}
    new_to_old = {i: vkey for i, vkey in enumerate(vertices)}
    # network
    vertex_coordinates = [mesh.vertex_coordinates(vkey) for vkey in vertices]
    edges = [(old_to_new[u], old_to_new[v]) for u, v in strip_edges]
    network = Network.from_vertices_and_edges(vertex_coordinates, edges)
    # disconnected parts
    parts = network_disconnected_vertices(network)

    # delete strip faces
    for fkey in strip_faces:
        mesh.delete_face_in_strips(fkey)
    for fkey in strip_faces:
        mesh.delete_face(fkey)

    old_vkeys_to_new_vkeys = {}

    # merge strip edge vertices that are connected
    for part in parts:

        # move back from network vertices to mesh vertices
        vertices = [new_to_old[vkey] for vkey in part]

        # skip adding a vertex if all vertices of the part are disconnected
        if any(mesh.is_vertex_connected(vkey) for vkey in vertices):

            # get position based on disconnected vertices that used to be on
            # the boundary if any
            if any(not mesh.is_vertex_connected(vkey) for vkey in vertices):
                points = [
                    mesh.vertex_coordinates(vkey) for vkey in vertices
                    if not mesh.is_vertex_connected(vkey)
                ]
            # or based on old boundary vertices if any
            elif any(vkey in old_boundary_vertices for vkey in vertices):
                points = [
                    mesh.vertex_coordinates(vkey) for vkey in vertices
                    if vkey in old_boundary_vertices
                ]
            else:
                points = [mesh.vertex_coordinates(vkey) for vkey in vertices]

            # new vertex
            x, y, z = centroid_points(points)
            new_vkey = mesh.add_vertex(attr_dict={'x': x, 'y': y, 'z': z})
            old_vkeys_to_new_vkeys.update(
                {old_vkey: new_vkey
                 for old_vkey in vertices})

            # replace the old vertices
            for old_vkey in vertices:
                mesh.substitute_vertex_in_strips(old_vkey, new_vkey)
                mesh_substitute_vertex_in_faces(mesh, old_vkey, new_vkey,
                                                mesh.vertex_faces(old_vkey))

        # delete the old vertices
        for old_vkey in vertices:
            mesh.delete_vertex(old_vkey)

    # delete data of deleted strip and collateral deleted strips
    del mesh.data['attributes']['strips'][skey]
    for skey_2 in collateral_deleted_strips:
        del mesh.data['attributes']['strips'][skey_2]
    #print(old_vkeys_to_new_vkeys)
    #print(mesh.data['attributes']['face_pole'])
    if 'face_pole' in mesh.data['attributes']:
        for fkey, pole in mesh.data['attributes']['face_pole'].items():
            if fkey in mesh.data['attributes']['face_pole']:
                #print(fkey, pole, mesh.data['attributes']['face_pole'])
                if pole == mesh.data['attributes']['face_pole'][fkey]:
                    if pole in old_vkeys_to_new_vkeys:
                        mesh.data['attributes']['face_pole'][
                            fkey] = old_vkeys_to_new_vkeys[pole]

    return old_vkeys_to_new_vkeys