def densification(self):
        """Generate a denser quad mesh from the coarse quad mesh and its strip densities.
		"""
        import time
        t0 = time.time()

        edge_strip = {}
        for skey, edges in self.strips(data=True):
            for edge in edges:
                edge_strip[edge] = skey
                edge_strip[tuple(reversed(edge))] = skey

        t1 = time.time()

        face_meshes = {}
        for fkey in self.faces():
            ab, bc, cd, da = [[
                self.edge_point(
                    u, v,
                    float(i) /
                    float(self.get_strip_density(edge_strip[(u, v)])))
                for i in range(0,
                               self.get_strip_density(edge_strip[(u, v)]) + 1)
            ] for u, v in self.face_halfedges(fkey)]
            vertices, faces = discrete_coons_patch(ab, bc, list(reversed(cd)),
                                                   list(reversed(da)))
            face_meshes[fkey] = QuadMesh.from_vertices_and_faces(
                vertices, faces)

        t2 = time.time()

        self.set_quad_mesh(meshes_join_and_weld(face_meshes.values()))
        #mesh = join_mesh(meshes)
        # for u, v in self.edges():
        # 	if not self.is_edge_on_boundary(u, v):
        # 		fkey_0 = self.halfedge[u][v]
        # 		fkey_1 = self.halfedge[v][u]

        t3 = time.time()

        print((t1 - t0) / (t3 - t0), (t2 - t1) / (t3 - t0),
              (t3 - t2) / (t3 - t0))
    import compas
    from compas_singular.datastructures.mesh_quad.mesh_quad import QuadMesh
    from compas_singular.datastructures.mesh_quad_coarse.coloring import dense_quad_mesh_polyedge_2_coloring
    from compas.geometry import scale_vector
    from compas_plotters.meshplotter import MeshPlotter

    def func0(mesh, vkey):
        normal = mesh.vertex_normal(vkey)
        return scale_vector(normal, 1)

    def func1(mesh, vkey):
        normal = mesh.vertex_normal(vkey)
        return scale_vector(normal, -1)

    mesh = QuadMesh.from_json('/Users/Robin/Desktop/json/debug.json')
    mesh.collect_strips()
    mesh.collect_polyedges()

    polyedge_key_to_colour = dense_quad_mesh_polyedge_2_coloring(mesh)
    polyedges_0 = [mesh.data['attributes']['polyedges'][key] for key, colour in polyedge_key_to_colour.items() if colour == 0]
    polyedges_1 = [mesh.data['attributes']['polyedges'][key] for key, colour in polyedge_key_to_colour.items() if colour == 1]

    vkey_to_group = fold_vertex_group(mesh, polyedges_1)
    #fold(mesh, vkey_to_group, func0, func1)

    plotter = MeshPlotter(mesh, figsize=(20, 20))
    plotter.draw_vertices(radius=0.4, text=vkey_to_group)
    plotter.draw_edges()
    plotter.draw_faces()
    plotter.show()
    -------
    dict
        A dictionary with polyedge keys pointing to colors.
    """

    vertices, edges = quad_mesh.polyedge_graph()
    return vertex_coloring(adjacency_from_edges(edges))


# ==============================================================================
# Main
# ==============================================================================

if __name__ == '__main__':

    import time
    import compas
    from compas_singular.datastructures.mesh_quad.mesh_quad import QuadMesh

    mesh = QuadMesh.from_json('/Users/Robin/Desktop/cnit2.json')

    mesh.collect_strips()
    mesh.collect_polyedges()
    t0 = time.time()
    result = quad_mesh_strip_2_coloring(mesh)
    t1 = time.time()
    print(t1 - t0, result)
    #print(quad_mesh_strip_n_coloring(mesh))
    #print(quad_mesh_polyedge_2_coloring(mesh))
    #print(quad_mesh_polyedge_n_coloring(mesh))
    #     [1, 2, 5, 4],
    #     [3, 4, 7, 6],
    #     [4, 5, 8, 7]
    # ]

    # mesh = QuadMesh.from_vertices_and_faces(vertices, faces)
    # add_strip_wip(mesh, [3, 4, 5])

    # plotter = MeshPlotter(mesh, figsize=(5.0, 5.0))
    # plotter.draw_vertices(text='key')
    # plotter.draw_edges()
    # plotter.draw_faces()
    # plotter.show()

    vertices = [
        [0.0, 0.0, 0.0],
        [1.0, 0.0, 0.0],
        [1.0, 1.0, 0.0],
        [0.0, 1.0, 0.0],
    ]

    faces = [
        [0, 1, 2, 3],
    ]

    mesh = QuadMesh.from_vertices_and_faces(vertices, faces)
    mesh.collect_strips()

    print(total_boundary_deletions(mesh, [0, 1]))
    print(collateral_strip_deletions(mesh, [0]))
# ==============================================================================

if __name__ == '__main__':

    import compas
    from compas_singular.datastructures.mesh_quad.mesh_quad import QuadMesh
    from compas.datastructures.mesh import mesh_smooth_centroid
    from compas_plotters.meshplotter import MeshPlotter

    #mesh = QuadMesh.from_obj(compas.get('faces.obj'))
    # mesh = QuadMesh.from_json('/Users/Robin/Desktop/json/debug.json')
    # mesh.collect_strips()
    # mesh.collect_polyedges()

    mesh_0 = CoarseQuadMesh.from_quad_mesh(
        QuadMesh.from_obj(compas.get('faces.obj')))
    mesh_0.collect_strips()
    # mesh_0.collect_polyedges()
    # print(mesh_0.is_quadmesh())
    # print(mesh_0.number_of_strips())

    # vertices = [[12.97441577911377, 24.33094596862793, 0.0], [18.310085296630859, 8.467333793640137, 0.0], [30.052173614501953, 18.846050262451172, 0.0], [17.135400772094727, 16.750551223754883, 0.0], [16.661802291870117, 22.973459243774414, 0.0], [14.180665969848633, 26.949295043945313, 0.0], [36.052761077880859, 26.372636795043945, 0.0], [26.180931091308594, 21.778648376464844, 0.0], [19.647378921508789, 12.288106918334961, 0.0], [9.355668067932129, 16.475896835327148, 0.0], [18.929227828979492, 16.271940231323242, 0.0], [7.34525203704834, 12.111981391906738, 0.0], [13.31309986114502, 14.699410438537598, 0.0], [18.699434280395508, 19.613750457763672, 0.0], [11.913931846618652, 10.593378067016602, 0.0], [17.163223266601563, 26.870658874511719, 0.0], [26.110898971557617, 26.634754180908203, 0.0], [22.851469039916992, 9.81414794921875, 0.0], [21.051292419433594, 7.556171894073486, 0.0], [22.1370792388916, 19.089054107666016, 0.0]]
    # faces = [[15, 5, 0, 4], [0, 9, 12, 4], [9, 11, 14, 12], [14, 1, 8, 12], [1, 18, 17, 8], [17, 2, 7, 8], [2, 6, 16, 7], [16, 15, 4, 7], [13, 19, 7, 4], [19, 10, 8, 7], [10, 3, 12, 8], [3, 13, 4, 12]]
    # mesh = QuadMesh.from_vertices_and_faces(vertices, faces)
    # mesh.collect_strips()
    # mesh.collect_polyedges()

    # mesh_0 = CoarseQuadMesh.from_quad_mesh(mesh)
    # mesh_0.collect_strips()
    # mesh_0.collect_polyedges()