Gaëtan
Gaëtan

Reputation: 198

Change vtk DataFile version

When I use vtkPolyDataWriter to create a vtk legacy file, I obtain the new version of the data file (5.1) with connectivities and offsets. Is it possible to change that and get the 'legacy' old format?

It seems gmsh is not able to read vtk file with the new format version..

(I work with python 3.8 and vtk package version 9.0.1)

Upvotes: 3

Views: 1445

Answers (2)

Gaëtan
Gaëtan

Reputation: 198

For those interested, I post the code I used to convert new to old format. It works for polydata and unstructured grid vtk meshes.

import math
import re


def convert_to_old_format(mesh_fname: str, save_fname: str, copy_lines: bool = False):
    conv = Converter(mesh_fname, save_fname, copy_lines)
    conv.read()
    conv.replace()
    conv.write()


def change_vtk_version(filename: str, v: float = 5.1):
    with open(filename, "r") as f:
        x = f.read()
    x = re.sub(r"(# vtk DataFile Version) (.+)", f"\\1 {v}", x)
    with open(filename, "w") as f:
        f.write(x)


class Converter:
    def __init__(self, inp, out=None, copy_lines=False):
        if out is None:
            out = inp
        self.inp = inp
        self.out = out
        self.copy_lines = copy_lines  # if line cells should be copied
        self.original = None
        self.lines = None
        self.polys = None
        self.cells = None

    def read(self):
        with open(self.inp, "r") as f:
            self.original = f.read().split("\n")
        lines_original = list(map(lambda x: x.strip().split(), self.original))

        for i, l in enumerate(self.original):
            if "LINES" in l:
                self.lines = NewContent("LINES", lines_original, i)
            elif "POLYGONS" in l:
                self.polys = NewContent("POLYGONS", lines_original, i)
            elif "CELLS" in l:
                self.cells = NewContent("CELLS", lines_original, i)

    def replace(self):
        if self.polys is not None:
            self.original = self.polys.replace(self.original)
        if self.cells is not None:
            self.original = self.cells.replace(self.original)
        if self.lines is not None:
            self.original = self.lines.replace(self.original, replace=self.copy_lines)

    def write(self):
        with open(self.out, "w") as f:
            f.write("\n".join(self.original))

        change_vtk_version(self.out, 4.2)


class NewContent:
    def __init__(self, kw, content, ln):
        self.kw = kw
        self.ln = ln
        self.name = content[ln][0]
        self.no = int(content[ln][1])
        self.nc = int(content[ln][2])

        flat_list = [item for line in content[ln + 2 :] for item in line]
        flat_list = list(filter("".__ne__, flat_list))

        self.offsets = list(map(int, flat_list[0 : self.no]))
        self.connectivity = list(
            map(int, flat_list[self.no + 2 : self.no + 2 + self.nc])
        )

    @property
    def remove(self):
        return self.ln, self.ln + math.ceil(self.no / 9) + math.ceil(self.nc / 9) + 3

    def replace(self, lines, replace=True):
        nb_cells = self.no - 1
        new_content = []
        if replace:
            new_content = [f"{self.kw} {nb_cells} {nb_cells + self.nc}"]
            for i in range(nb_cells):
                nb_points = self.offsets[i + 1] - self.offsets[i]
                ids = self.connectivity[self.offsets[i] : self.offsets[i + 1]]
                new_content.append(f"{nb_points} {' '.join(map(str, ids))}")

        lines_to_keep = lines
        a, b = self.remove
        del lines_to_keep[a:b]
        lines_to_keep[a:a] = new_content
        lines_to_keep = list(filter("".__ne__, lines_to_keep))
        return lines_to_keep


if __name__ == "__main__":
    convert_to_old_format("mesh.vtk", "mesh_old_format.vtk")

    # change_vtk_version("mesh.vtk", 8.6)

Upvotes: 0

Nico Vuaille
Nico Vuaille

Reputation: 2488

Nope, you cannot programmatically choose the version. The only way to write with an old format is to downgrade vtk to the desired version.

Upvotes: 3

Related Questions