示例#1
0
def signedDistance(f, box=None, parallel=False):
    if box is not None:
        adapt_box_to(f, box)
    else:
        create_box(f)
    ncpus = mp.cpu_count() if parallel else 1
    lib_exe.execute( lib_exe.mshdist + "-ncpu " + str(ncpus) + " -noscale box.1.o.mesh " + f + " > /dev/null 2>&1")
    if os.path.exists("box.mesh"): os.remove("box.mesh")
    if os.path.exists("box.1.mesh"): os.remove("box.1.mesh")
示例#2
0
def create_box(f):
    mesh = lib_msh.Mesh(f)
    cube = lib_msh.Mesh(cube=[mesh.xmin, mesh.xmax, mesh.ymin, mesh.ymax, mesh.zmin, mesh.zmax])
    cube.verts[:,:3] -= mesh.center
    cube.verts[:,:3] *= 1.25
    cube.verts[:,:3] += mesh.center
    cube.write("box.mesh")
    lib_exe.execute( lib_exe.tetgen + "-pgANEF box.mesh > /dev/null 2>&1" )
    hausd = 0.02 * np.max(mesh.dims)
    lib_exe.execute( lib_exe.mmg3d + "box.1.mesh -hausd %f -hmax %f > /dev/null 2>&1" % (hausd, hausd) )
示例#3
0
def intersects(f):
    lib_exe.execute(lib_exe.tetgen + "-d %s > log.txt" % (f))
    res = True
    with open("log.txt", "r") as f:
        lines = f.readlines()
        if "No faces are intersecting" in "".join(lines):
            res = False
        else:
            res = True
    os.remove("log.txt")
    return res
示例#4
0
 def morph(f):
     IN = os.path.join(directories["signed"], f)
     OUT = os.path.join(directories["morphed"], f)
     TMP = templates["morphing_skull"] if "Skull" in f else templates[
         "morphing_face"]
     REFS = [10, 2, 0] if "Skull" in f else [10, 2, 3]
     with tempfile.TemporaryDirectory() as tmp:
         os.chdir(tmp)
         lib_exe.execute(
             lib_exe.python_cmd("morph.py") +
             "-t %s -s %s -o %s --icotris %d --icotets %d --fixtris %d -n %d"
             % (TMP, IN, OUT, REFS[0], REFS[1], REFS[2], 250))
示例#5
0
def adapt_box_to(f, box, maxNb=20000):
    shutil.copyfile(box,"box.mesh")
    cube = lib_msh.Mesh("box.mesh")
    mesh = lib_msh.Mesh(f)
    step = 1 if len(mesh.verts)<maxNb else int(len(mesh.verts)/maxNb)+1
    dists, _ = nearest_neighbor(cube.verts[:,:3], mesh.verts[::step,:3])
    cube.scalars = np.array(dists)
    ABS = np.absolute(cube.scalars)
    mini, maxi = 0.005*np.max(cube.dims), 0.5*np.max(cube.dims)
    cube.scalars = mini + (maxi-mini) * (ABS - np.min(ABS)) / (np.max(ABS) - np.min(ABS))
    cube.write("box.1.mesh")
    cube.writeSol("box.1.sol")
    lib_exe.execute(lib_exe.mmg3d + "box.1.mesh -hgrad 1.5  > /dev/null 2>&1")
示例#6
0
def to_mesh(f, output):

    #Convert a stl to mesh with meshlabserver
    meshlabScript = os.path.join(os.path.dirname(os.path.abspath(__file__)),
                                 "meshlab_scripts", "cleanSTL.mlx")
    tmp = f.replace(".stl", ".obj")
    lib_exe.execute(lib_exe.meshlabserver +
                    "-i %s -o %s -s %s > /dev/null 2>&1" %
                    (f, tmp, meshlabScript))
    f = tmp

    #Convert a .obj to .mesh
    with open(f, "r") as _f:
        LINES = _f.readlines()
        mesh = lib_msh.Mesh()
        mesh.verts = np.array([[float(x) for x in l.split()[1:]] for l in LINES
                               if l[0] == "v"])
        mesh.tris = np.array([[int(x) - 1 for x in l.split()[1:]]
                              for l in LINES if l[0] == "f"])
        mesh.verts = np.insert(mesh.verts, 3, 0, axis=1)
        mesh.tris = np.insert(mesh.tris, 3, 0, axis=1)
        mesh.computeBBox()
        mesh.write(output)
示例#7
0
    if not os.path.splitext(args.input)[1] == ".mesh":
        print(args.input + " is not a .mesh file")
        sys.exit()
    if not os.path.splitext(args.output)[1] == ".mesh":
        print("Output file must be in the .mesh format")
        sys.exit()
    if intersects(args.input):
        print(args.input + " has intersecting facets")
        sys.exit()

    mesh = lib_msh.Mesh(args.input)
    ico = lib_msh.Mesh(ico=[args.center, args.radius])
    ico.tris[:, -1] = 10
    mesh.fondre(ico)
    mesh.write("out.mesh")
    lib_exe.execute(lib_exe.tetgen + "-pgANEYF out.mesh")
    lib_exe.execute(lib_exe.mmg3d + "out.1.mesh -nosurf -o " + args.output)
    os.remove(args.output.replace(".mesh", ".sol"))

    #Make the same references in args.output than in out.mesh
    def distance(a, b):
        return ((a[0] - b[0])**2 + (a[1] - b[1])**2 + (a[2] - b[2])**2)**0.5

    final = lib_msh.Mesh(args.output)
    for i, t in enumerate(final.tris):
        vert1 = final.verts[t[0]]
        if distance(vert1, [0.5, 0.5, 0.65]) < 0.12:
            final.tris[i, -1] = 10
    final.write(args.output)

    os.remove("out.mesh")
示例#8
0
                        "--directory",
                        type=str,
                        help="directory containing the data to test",
                        required=True)
    parser.add_argument("-m",
                        "--medit",
                        action="store_true",
                        help="visualize each result with medit")
    args = parser.parse_args()
    args.directory = os.path.abspath(args.directory)

    # 1 - Carve a .mesh object
    print("Testing carve.py")
    IN = os.path.join(args.directory, "buddha.mesh")
    OUT = os.path.join(args.directory, "buddha.carved.mesh")
    lib_exe.execute(
        lib_exe.python_cmd("carve.py") + "-i %s -o %s -r %d" % (IN, OUT, 31))
    if args.medit: lib_exe.execute(lib_exe.medit + "%s" % (OUT))
    os.remove(OUT)

    # 2 - convert .obj and .stl objects to .mesh
    print("Testing convert.py")
    IN1 = os.path.join(args.directory, "buddha.obj")
    OUT1 = os.path.join(args.directory, "buddha1.mesh")
    lib_exe.execute(
        lib_exe.python_cmd("convert.py") + "-i %s -o %s" % (IN1, OUT1))
    IN2 = os.path.join(args.directory, "buddha.stl")
    OUT2 = os.path.join(args.directory, "buddha2.mesh")
    lib_exe.execute(
        lib_exe.python_cmd("convert.py") + "-i %s -o %s" % (IN2, OUT2))
    if args.medit: lib_exe.execute(lib_exe.medit + "%s %s" % (OUT1, OUT2))
    buddha1 = lib_msh.Mesh(OUT1)
示例#9
0
    parser = argparse.ArgumentParser(description="Warps a mesh with a baloon-like object")
    parser.add_argument("-i", "--input",      type=str, help="Mesh to wrap", required=True)
    parser.add_argument("-o", "--output",     type=str, help="Output mesh", required=True)
    parser.add_argument("-t", "--template",   type=str, help="Template to wrap", required=True)
    args = parser.parse_args(sys.argv[1:])

    #checks
    args.template = os.path.abspath(args.template) if args.template else None
    args.input    = os.path.abspath(args.input)
    args.output   = os.path.abspath(args.output)

    #Copy the template to warp
    shutil.copyfile(args.template, "sphere.mesh")

    #Warp
    lib_exe.execute(lib_paths.wrapping + " %s -p -nit %d -load %f > /dev/null 2>&1" % (args.input, 150, 40) )

    #Clean the mesh and extract the surface
    final = None
    try:
        number_max=-1
        for f in [x for x in os.listdir(".") if "sphere.d." in x and ".mesh" in x]:
            number = int(f.split(".")[2])
            if number>number_max:
                final = f
    except:
        final = "sphere.d.mesh"

    warped = lib_msh.Mesh(final)
    warped.tris = warped.tris[warped.tris[:,-1] != 2]
    warped.tets = np.array([])
示例#10
0
            os.path.join(args.templates, d + ".mesh"))

    return args, templates


if __name__ == "__main__":

    #Get the templates and arguments
    args, templates = init()
    NAME = "reconstruction"

    # 1 - If needed, convert the .obj or .stl objects to .mesh
    for i, f in enumerate(args.input):
        if f.endswith(".obj") or f.endswith(".stl"):
            lib_exe.execute(
                lib_exe.python_cmd("convert.py") + "-i %s -o %s" %
                (f, f.replace(f[-3:], "mesh")))
            args.input[i] = f.replace(f[-3:], "mesh")

    # 2 - If needed, merge everything together
    if len(args.input) > 1:
        lib_exe.execute(
            lib_exe.python_cmd("merge.py") + "-i %s -o %s" %
            (" ".join(args.input), NAME + ".mesh"))
    else:
        shutil.copyfile(args.input[0], NAME + ".mesh")

    # 3 - Transform to an object between 0.1 and 0.9
    mesh = lib_msh.Mesh(NAME + ".mesh")
    S = 0.8 / np.max(mesh.dims)
    C = mesh.center
示例#11
0
    parser.add_argument("-d", "--icotris",  type=int, help="Icosphere triangles reference", required=True)
    parser.add_argument("-e", "--icotets",     type=int, help="Icosphere tetrahedra reference", required=True)
    parser.add_argument("-b", "--fixtris",      type=int, help="Fixed triangles reference", required=True)

    args = parser.parse_args(sys.argv[1:])

    #checks
    args.template = os.path.abspath(args.template)
    args.signed   = os.path.abspath(args.signed)
    args.output   = os.path.abspath(args.output)

    # dref: Fixed surface inside the template (number + ref)
    # elref: Elements inside the fixed surface
    # bref: Follower elements
    shutil.copyfile(args.template, "template.mesh")
    cmd = lib_exe.morphing + " %s %s -nit %d -dref 1 %d -elref 1 %d -bref 1 %d  > /dev/null 2>&1" % (args.signed, "template.mesh", args.iterations, args.icotris, args.icotets, args.fixtris)
    lib_exe.execute(cmd)

    #Clean the mesh
    mesh = lib_msh.Mesh(args.signed[:-5] + ".1.mesh")
    mesh.readSol(   args.signed[:-5] + ".1.depl.sol")
    mesh.tets = np.array([])
    mesh.tris = mesh.tris[mesh.tris[:,-1]!=10]
    mesh.discardUnused()
    mesh.write(args.output)
    mesh.writeSol(args.output.replace("mesh", "sol"))

    #Remove the temporary files
    os.remove(args.signed[:-5] + ".1.mesh")
    os.remove(args.signed[:-5] + ".1.depl.sol")
示例#12
0
                        help="Hausdorff distance",
                        default=0.01)
    parser.add_argument("-r",
                        "--reference",
                        type=int,
                        help="New surface reference",
                        default=0)
    parser.add_argument("-l",
                        "--levelset",
                        type=float,
                        help="Levelset value",
                        default=0)
    args = parser.parse_args(sys.argv[1:])

    #checks
    args.input = os.path.abspath(args.input)
    args.output = os.path.abspath(args.output)

    lib_exe.execute(lib_exe.mmg3d + "%s -ls %f -hausd %f -o tmp.mesh" %
                    (args.input, args.levelset, args.distance))

    mesh = lib_msh.Mesh("tmp.mesh")
    mesh.tets = np.array([])
    mesh.tris = mesh.tris[mesh.tris[:, -1] == 10]
    mesh.discardUnused()
    mesh.tris[:, -1] = args.reference
    mesh.write(args.output)

    os.remove("tmp.mesh")
    os.remove("tmp.sol")
示例#13
0
    lib_exe.execute( lib_exe.mmg3d + "box.1.mesh -hausd %f -hmax %f > /dev/null 2>&1" % (hausd, hausd) )

def signedDistance(f, box=None, parallel=False):
    if box is not None:
        adapt_box_to(f, box)
    else:
        create_box(f)
    ncpus = mp.cpu_count() if parallel else 1
    lib_exe.execute( lib_exe.mshdist + "-ncpu " + str(ncpus) + " -noscale box.1.o.mesh " + f + " > /dev/null 2>&1")
    if os.path.exists("box.mesh"): os.remove("box.mesh")
    if os.path.exists("box.1.mesh"): os.remove("box.1.mesh")

if __name__ == "__main__":

    #arguments
    parser = argparse.ArgumentParser(description="Computes the signed distance to a .mesh file")
    parser.add_argument("-i", "--input",  type=str, help="Input mesh", required=True)
    parser.add_argument("-o", "--output", type=str, help="Output mesh", required=True)
    parser.add_argument("-v", "--volume", type=str, help="Volume mesh to adapt")
    parser.add_argument("-p", action="store_true",  help="Run in parallel", default=False)
    args = parser.parse_args(sys.argv[1:])

    #checks
    args.input  = os.path.abspath(args.input)
    args.output = os.path.abspath(args.output)
    args.volume = os.path.abspath(args.volume) if args.volume is not None else None

    signedDistance(args.input, box=args.volume, parallel=args.p)
    lib_exe.execute("mv box.1.o.mesh " + args.output)
    lib_exe.execute("mv box.1.o.sol  " + args.output.replace(".mesh",".sol"))
示例#14
0
    #Merge the meshes and run tetgen
    exterior, interior = lib_msh.Mesh(args.exterior), lib_msh.Mesh(
        args.interior)
    #exterior.tris = exterior.tris[exterior.tris[:,-1]!=2]
    exterior.tris[:, -1] = 2
    exterior.discardUnused()
    interior.tris[:, -1] = 1
    interior.fondre(exterior)
    interior.write("mask.mesh")

    if intersects("mask.mesh"):
        print("mask is self-intersecting")
        sys.exit(3)

    #Run tetgen
    lib_exe.execute(lib_exe.tetgen + "-pgaANEFY mask.mesh")
    for f in os.listdir("."):
        if 'mask' in f and ".mesh" not in f and ".py" not in f:
            os.remove(f)

    lib_exe.execute(
        lib_exe.mmg3d +
        "-nosurf -nr -hgrad 1.75 mask.1.mesh -out mask.1.o.mesh"
    )  #Because the number of triangles is not good, therefore tetrahedra re not read!!
    os.remove("mask.1.o.sol")
    os.remove("mask.mesh")
    os.remove("mask.1.mesh")

    #Remove the inside of the mask
    mesh = lib_msh.Mesh("mask.1.o.mesh")
    ext_point_ind = np.argmin(mesh.verts[:, :3], axis=0)[0]
示例#15
0
        sys.exit()
    if not os.path.splitext(args.output)[1] == ".mesh":
        print("Output file must be in the .mesh format")
        sys.exit()
    if args.interiorIsovalue < args.exteriorIsovalue:
        print("The inner shell must be closer than the outer shell")
        sys.exit()
    if args.interiorIsovalue < 5 or args.exteriorIsovalue < 5:
        print("The shell must be closer than maxDim/5")
        sys.exit()
    args.input = os.path.abspath(args.input)
    args.output = os.path.abspath(args.output)

    #Carve the input mesh
    lib_exe.execute(
        lib_exe.python_cmd("carve.py") + "-i %s -o %s -r %d" %
        (args.input, args.output.replace(".mesh", ".carved.mesh"), 31))

    #Create a box and mesh it to compute the signed distance on
    mesh = lib_msh.Mesh(args.input)
    c = np.max(mesh.dims) / 8
    cube = lib_msh.Mesh(cube=[
        mesh.xmin - c, mesh.xmax + c, mesh.ymin - c, mesh.ymax + c, mesh.zmin -
        c, mesh.zmax + c
    ])
    cube.write("box.mesh")
    lib_exe.execute(lib_exe.tetgen + "-pgANEF %s" % ("box.mesh"))
    lib_exe.execute(
        lib_exe.mmg3d + "%s -hausd %f -hmax %f" %
        ("box.1.mesh", np.max(mesh.dims) / 50, np.max(mesh.dims) / 25))