Proplem using vtkPLYWriter with WriteToOutputString = true

Hi,

I am trying to use the vtkPLYWriter to write to a std::string. This is an extraction of my code:

vtkNew<vtkPLYWriter> vtkWriter;
vtkWriter->WriteToOutputStringOn();
vtkWriter->SetFileTypeToBinary();
vtkWriter->SetInputData(polyDataModel);
int ret = vtkWriter->Write();
std::string dataString = vtkWriter->GetOutputString();

The dataString is always empty after execution.

I went looking in the VTK code and it looks like the vtkPLYWriter member OutputString does not get assigned properly.

This is the code found in VTK 9.1 (vtkPLY.cxx):

PlyFile* vtkPLY::ply_open_for_writing_to_string(
  std::string& output, int nelems, const char** elem_names, int file_type)
{
  PlyFile* plyfile;
  // memory leaks
  plyInitialize();
  std::ostringstream* oss = new std::ostringstream;
  oss->str(output);

  /* create the actual PlyFile structure */
  plyfile = vtkPLY::ply_write(oss, nelems, elem_names, file_type);
  if (plyfile == nullptr)
  {
    delete oss;
    return (nullptr);
  }

  /* return pointer to the file descriptor */
  return (plyfile);
}

As you can see it looks like oss gets initialised with OutputString but that’s it. By adding a very simple hack to the vtkPLYWriter::WriteData method it seemed to fix the problem.

My modification in file vtkPLYWriter.cxx:

void vtkPLYWriter::WriteData()
{
...
...
...
  //Added this to fix write to string
  if (this->WriteToOutputString)
  {
    std::ostringstream* ofs = dynamic_cast< std::ostringstream* >(ply->os);
    if (ofs)
      this->OutputString = ofs->str();
  }
  // close the PLY file
  vtkPLY::ply_close(ply);
}

My code is probably not ideal as I am no expert in the VTK code. Should someone add something similar to fix the problem?

Cheers
Daniel

Thank you, it seems you have found a bug and a solution, too. To make it easier for VTK developers to review and integrate your proposed change, I would recommend to submit a merge request. See details here:

https://vtk.org/contributing-code/

I think the problem here is that
vtkPLY::ply_open_for_writing_to_string(std::string& output)
should be
vtkPLY::ply_open_for_writing_to_stream(std::ostream& output)

  std::ostringstream* stringstream = nullptr;
  if (this->WriteToOutputString)
  {
    stringstream = new std::ostringstream;
    ply = vtkPLY::ply_open_for_writing_to_stream(&stringstream, ...)
  }

Then there is no need for the dynamic cast later just

  if (this->WriteToOutputString)
  {
    this->OutputString = stringstream->str();
    delete stringstream;
  }

I agree with Todd’s recommendation. Seems unnecessary to pass the string output to ply_open_for_writing_to_string if it is not going to be used.

Todd, will you do the honour of submitting a merge request?