elrnv / vtkio

Visualization ToolKit (VTK) file parser and writer
Apache License 2.0
57 stars 13 forks source link

Request an example of constructing a VTK object containing point/cell data in Legacy style #33

Closed hunter1992 closed 1 year ago

hunter1992 commented 1 year ago

Hello elrnv!

Thank you three contributors for your work!I'm learning to use vtkio and it feels great!

After studying the examples in the readme, I already know how to construct a VTK object(with default attributes) using vtkio, and bufferd write it into a .vtk file. Here is my Rust file:

test_vtkio.rs :

use std::io::{BufWriter, Write};
use vtkio::model::*;

// The whole idea:
//    1. Construct a String to store the vtk object;
//    2. Construct a VTK object containing data;
//    2. Write VTK object into String;
//    3. Write the String into the .vtk file.

fn main() {
    // Prepare a file for loading vtk content
    let file_path = "./test2.vtk";
    let vtk_file = std::fs::File::create(file_path).unwrap();
    let mut vtk_writer = BufWriter::new(vtk_file);

    // Prepare a String to hold vtk file information
    let mut vtk_strings = String::new();

    // Construct the content of the vtk file
    let tri2 = make_triangle_legacy();

    // Write the content of the vtk file into String
    tri2.write_legacy_ascii(&mut vtk_strings)
        .expect("Write vtk info into bytes failed!");

    // Print out the written string
    println!("{}", vtk_strings.as_str());

    // Write the String into the .vtk file
    write!(vtk_writer, "{}", vtk_strings.as_str()).expect("Write VTK error!");
}

fn make_triangle_legacy() -> Vtk {
    Vtk {
        version: Version { major: 4, minor: 2 },
        title: String::from("Rust vtk io crate test."),
        byte_order: ByteOrder::BigEndian,
        file_path: None,
        data: DataSet::inline(UnstructuredGridPiece {
            points: IOBuffer::F64(vec![
                0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0,
            ]),
            cells: Cells {
                cell_verts: VertexNumbers::Legacy {
                    num_cells: 2,
                    vertices: vec![3, 0, 1, 2, 3, 3, 2, 1],
                },
                types: vec![CellType::Triangle; 2],
            },
            data: Attributes {
                ..Default::default()
            },
        }),
    }
}

And the above code will generate a vtk file: test2.vtk. Its contents are:

test2.vtk:

# vtk DataFile Version 4.2
Rust vtk io crate test.
ASCII

DATASET UNSTRUCTURED_GRID
POINTS 4 double
0 0 0 1 0 0 0 1 0 1 1 0

CELLS 2 8
3 0 1 2 3 3 2 1

CELL_TYPES 2
5
5

POINT_DATA 4

CELL_DATA 2

The test2.vtk file can be well loaded and visualized by paraview without any data:

Screenshot_20230623_232416

However I'm having trouble writing Dataset attributes to a .vtk file in Legacy style using vtkio. I don't know how to write the following point_data into the test2.vtk file in Legacy style,

POINT_DATA 4
VECTORS displacement float
0 0 0
0.5 0 0
0 0 0
0.5 0 0

Please teach me how to construct a VTK object containing point/cell data, thanks a lot!

hunter1992 commented 1 year ago

Come on folks! any help?

elrnv commented 1 year ago

Hi @hunter1992, You just need to add a non-default Attributes struct. In your example, this will be something like

...
            data: Attributes {
                point: vec![
                    Attribute::vectors("displacement")
                       .with_data(vec![0.0f32, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0]),
                ],
                ..Default::default()
            },
...

There is more documentation about how to create attributes here: https://docs.rs/vtkio/latest/vtkio/model/enum.Attribute.html .

The best place to see examples of how to create vtk files take a look at the tests subdirectory. For instance, there is an example of how to create a vector attribute here.

Hope this helps!