[Paraview] Writing XML VTK Binary files from C++

Mark Olesen Mark.Olesen at esi-group.com
Tue Dec 5 05:28:13 EST 2017


Hi Nicholas,

The ostream 'write' method is indeed normally just used for writing a block of binary data, however for your case you can simply wrap things. In fact, you will pretty much have to wrap things to achieve what you want.

For the sake of discussion, we'll call these wrappers NicholasA (ASCII) and NicholasB (BINARY).
The funny names are just to show that there is no special magic involved, just your own logic.

The classes would be contructed with a reference to an ostream, which you'll use inside.
Eg,

class NicholasA
{
    std::ostream& os_;

public:
    NicholasA(std::ostream& os) : os_(os) {}

    void write (double val)
    {
        os_ << val;
    }

....
}

In the binary version

class NicholasB
{
    std::ostream& os_;

public:
    NicholasB(std::ostream& os) : os_(os) {}

    void write (double val)
    {
        os_.write(reinterpret_cast<const char*>(val), sizeof(val));
    }
....
}

You follow the same type of thing for all the data types you want to support.
Finally, you need to fix the binary example to use the base64 layer instead of
a direct write, but now you have the place to intercept the output. To switch between ASCII and BINARY output you choose different classes. This is what is going on behind the scenes in the OpenFOAM code. Of course, by the time you add in additional bells and whistles the purpose gets a bit obfuscated.

I hope this (terse) explanation helps make things a bit clearer.
/mark

________________________________________
From: Stegmeier, Nicholas <Nicholas.Stegmeier at sdstate.edu>
Sent: Monday, December 4, 2017 12:46:26 AM
To: Mark Olesen; paraview at paraview.org
Subject: Re: [Paraview] Writing XML VTK Binary files from C++

Hello again Mark,

I have been working on implementing the binary "inline" option for my VTK XML files. I looked through the OpenFOAM code that you suggested and am having trouble interpreting it.

Would you be able to give me a hint as to where I should be looking in foamVtkBase64Layer? For example, in my current code I write the array data like this:

  int i,j;
  ofstream lfile;

  lfile << "\t\t\t\t<DataArray type=\"Float32\" Name=\"rho\" format=\"ascii\">\n";
  lfile << "\t\t\t\t\t";
    for (j = firsty-1; j <= lasty+1; j++){
    for (i = firstx-1; i <= lastx+1; i++){
      lfile << rho[j][i][t] << " ";
    }
    }
  lfile << "\n";
  lfile << "\t\t\t\t</DataArray>\n";

 I have not used the write function in C++ before. Is there a quick way to explain how the above code would be modified (with the contents of "rho" being written to the file)? I wonder if I will run into a problem because of how I have set up the array with the 't' index last.

Thank you so much for your help so far.

Nicholas Stegmeier
Graduate Student
Mathematics and Statistics
South Dakota State University


________________________________
From: Mark Olesen <Mark.Olesen at esi-group.com>
Sent: Friday, December 1, 2017 1:34:58 AM
To: Stegmeier, Nicholas; paraview at paraview.org
Subject: Re: [Paraview] Writing XML VTK Binary files from C++

When you say "writing binary", you need to distinguish between three
possibilities.
1) writing binary "inline" (actually base64 encoded)
2) writing binary "append" (actually base64 encoded)
3) writing raw binary "append" (really raw binary)

Since you already have ASCII writing working and its content is
"inline", it won't take much more to get binary inline working.
By "inline", I mean when the output is placed between the <xxx> </xxx>
markers. Eg,
     <DataArray ...>
         content
     </DataArray>

For the binary case, the content is written as base64-encoded data,
which means that your output writer for these sections needs to pass the
content through a base64 layer to do the encoding for you.

If it helps as reference, we have the same thing in OpenFOAM, except
that we only write vtu and vtp files (we don't have rectilinear meshes).

In the repo https://develop.openfoam.com/Development/OpenFOAM-plus
we have a foamVtkBase64Formatter and a foamVtkBase64Layer (both under
src/fileFormats/vtk/format/) that add a base64Layer to encode and output
as base64 (src/OpenFOAM/db/IOstreams/hashes/base64Layer.[CH]).

You'll see that the foamVtkBase64Layer and base64Layer are quite low
level means of adding an tiny encoding buffer (3 chars size) to
intercept output prior to sending through to a std::ostream. It take
very little effort to adopt for your output and thus quite easy to drop
in instead of your current ASCII outputter.  For it too work easily,
however, you should make sure that you need to generate your output
content with a write() method instead of using '<<'. This allows
somewhat easy switching between something like a foamVtkAsciiFormatter
and the binary version, but more importantly it makes it easier to track
the output state.

When browsing through the code, you may also notice that we have support
for writing in appended format (raw and base64). However, I would not
advise you to tackle that immediately. There are a few more things to
watch out for here, but more importantly it will change many more things
on the calling side.

I hope this information helps you.
/mark

--
Dr Mark OLESEN
Principal Engineer, ESI-OpenCFD
ESI GmbH | Einsteinring 24 | 85609 Munich | GERMANY
www.openfoam.com<http://www.openfoam.com> | www.esi-group.com<http://www.esi-group.com> | mark.olesen at esi-group.com


On 11/30/17 18:00, Stegmeier, Nicholas wrote:
> Hello,
>
> I am new to Paraview and C++ coming from a mostly mathematics
> background. I am emailing to get resources or help on writing binary XML
> VTK files from C++.
>
> I have finally succeeded in using the ASCII XML VTK format for a 2D
> rectilinear CFD application. My ".pvtr" file is shown below.
>
> How can I write this file and my other XML VTK files in binary from C++?
> Do I need a special C++ library?


More information about the ParaView mailing list