mirror of
https://github.com/OpenFOAM/ThirdParty-6.git
synced 2025-12-08 06:57:43 +00:00
552 lines
16 KiB
C++
552 lines
16 KiB
C++
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: vtkGeoJSONWriter.cxx
|
|
|
|
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
|
|
All rights reserved.
|
|
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
|
|
|
|
This software is distributed WITHOUT ANY WARRANTY; without even
|
|
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
PURPOSE. See the above copyright notice for more information.
|
|
|
|
=========================================================================*/
|
|
|
|
#include "vtkGeoJSONWriter.h"
|
|
|
|
#include "vtkCellArray.h"
|
|
#include "vtkInformation.h"
|
|
#include "vtkLookupTable.h"
|
|
#include "vtkMath.h"
|
|
#include "vtkObjectFactory.h"
|
|
#include "vtkPointData.h"
|
|
#include "vtkPolyData.h"
|
|
|
|
#include <sstream>
|
|
|
|
#if _MSC_VER
|
|
#define snprintf _snprintf
|
|
#endif
|
|
|
|
vtkStandardNewMacro(vtkGeoJSONWriter);
|
|
|
|
#define VTK_GJWRITER_MAXPOINTS 32000
|
|
|
|
class vtkGeoJSONWriter::Internals
|
|
{
|
|
public:
|
|
Internals()
|
|
{
|
|
this->MaxBufferSize = 128;
|
|
this->Buffer = new char[this->MaxBufferSize];
|
|
this->Top = this->Buffer;
|
|
};
|
|
~Internals()
|
|
{
|
|
delete[] this->Buffer;
|
|
}
|
|
inline size_t GetSize()
|
|
{
|
|
return this->Top-this->Buffer;
|
|
}
|
|
void Clear()
|
|
{
|
|
this->Top = this->Buffer;
|
|
}
|
|
inline void Grow()
|
|
{
|
|
this->MaxBufferSize*=2;
|
|
//cerr << "GROW " << this->MaxBufferSize << endl;
|
|
char *biggerBuffer = new char[this->MaxBufferSize];
|
|
size_t curSize = this->Top-this->Buffer;
|
|
memcpy(biggerBuffer, this->Buffer, curSize);
|
|
delete[] this->Buffer;
|
|
this->Buffer = biggerBuffer;
|
|
this->Top = this->Buffer+curSize;
|
|
}
|
|
inline void append(const char *newcontent)
|
|
{
|
|
while (this->Top+strlen(newcontent)>=this->Buffer+this->MaxBufferSize)
|
|
{
|
|
this->Grow();
|
|
}
|
|
int nchars = sprintf(this->Top, "%s", newcontent);
|
|
this->Top+=nchars;
|
|
}
|
|
inline void append(const double newcontent)
|
|
{
|
|
snprintf(this->NumBuffer, 64, "%g", newcontent);
|
|
while (this->Top+strlen(NumBuffer)>=this->Buffer+this->MaxBufferSize)
|
|
{
|
|
this->Grow();
|
|
}
|
|
int nchars = sprintf(this->Top, "%s", this->NumBuffer);
|
|
this->Top+=nchars;
|
|
}
|
|
char *Buffer;
|
|
char *Top;
|
|
size_t MaxBufferSize;
|
|
char NumBuffer[64];
|
|
};
|
|
|
|
//------------------------------------------------------------------------------
|
|
vtkGeoJSONWriter::vtkGeoJSONWriter()
|
|
{
|
|
this->FileName = NULL;
|
|
this->OutputString = NULL;
|
|
this->SetNumberOfOutputPorts(0);
|
|
this->WriteToOutputString = false;
|
|
this->ScalarFormat = 2;
|
|
this->LookupTable = NULL;
|
|
this->WriterHelper = new vtkGeoJSONWriter::Internals();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
vtkGeoJSONWriter::~vtkGeoJSONWriter()
|
|
{
|
|
this->SetFileName(NULL);
|
|
delete[] this->OutputString;
|
|
this->SetLookupTable(NULL);
|
|
delete this->WriterHelper;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void vtkGeoJSONWriter::PrintSelf(ostream & os, vtkIndent indent)
|
|
{
|
|
this->Superclass::PrintSelf(os, indent);
|
|
os << indent << "FileName: "
|
|
<< (this->FileName?this->FileName:"NONE") << endl;
|
|
os << indent << "WriteToOutputString: "
|
|
<< (this->WriteToOutputString?"True":"False") << endl;
|
|
os << indent << "ScalarFormat: " << this->ScalarFormat << endl;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
int vtkGeoJSONWriter::FillInputPortInformation(int port, vtkInformation *info)
|
|
{
|
|
if (port == 0)
|
|
{
|
|
info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkPolyData");
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
ostream *vtkGeoJSONWriter::OpenFile()
|
|
{
|
|
vtkDebugMacro(<<"Opening file\n");
|
|
|
|
ostream *fptr;
|
|
|
|
if (!this->WriteToOutputString)
|
|
{
|
|
if (!this->FileName)
|
|
{
|
|
vtkErrorMacro(<< "No FileName specified! Can't write!");
|
|
return NULL;
|
|
}
|
|
|
|
fptr = new ofstream(this->FileName, ios::out);
|
|
}
|
|
else
|
|
{
|
|
// Get rid of any old output string.
|
|
if (this->OutputString)
|
|
{
|
|
delete [] this->OutputString;
|
|
this->OutputString = NULL;
|
|
this->OutputStringLength = 0;
|
|
}
|
|
fptr = new std::ostringstream;
|
|
}
|
|
|
|
if (fptr->fail())
|
|
{
|
|
vtkErrorMacro(<< "Unable to open file: "<< this->FileName);
|
|
delete fptr;
|
|
return NULL;
|
|
}
|
|
|
|
return fptr;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void vtkGeoJSONWriter::CloseFile(ostream *fp)
|
|
{
|
|
vtkDebugMacro(<<"Closing file\n");
|
|
|
|
if ( fp != NULL )
|
|
{
|
|
if (this->WriteToOutputString)
|
|
{
|
|
std::ostringstream *ostr =
|
|
static_cast<std::ostringstream*>(fp);
|
|
|
|
delete [] this->OutputString;
|
|
this->OutputStringLength = static_cast<int>(ostr->str().size());
|
|
//+1's account for null terminator
|
|
this->OutputString = new char[ostr->str().size()+1];
|
|
memcpy(this->OutputString, ostr->str().c_str(),
|
|
this->OutputStringLength+1);
|
|
}
|
|
|
|
delete fp;
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void vtkGeoJSONWriter::ConditionalComma(
|
|
vtkIdType cnt, vtkIdType limit)
|
|
{
|
|
if (cnt+1 != limit)
|
|
{
|
|
this->WriterHelper->append(",");
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void vtkGeoJSONWriter::WriteScalar(
|
|
vtkDataArray *da, vtkIdType ptId)
|
|
{
|
|
if (this->ScalarFormat == 0)
|
|
{
|
|
return;
|
|
}
|
|
if (da)
|
|
{
|
|
double b = da->GetTuple1(ptId);
|
|
if (this->ScalarFormat == 1)
|
|
{
|
|
vtkLookupTable *lut = this->GetLookupTable();
|
|
if (!lut)
|
|
{
|
|
lut = vtkLookupTable::New();
|
|
lut->SetNumberOfColors(256);
|
|
lut->SetHueRange(0.0,0.667);
|
|
lut->SetRange(da->GetRange());
|
|
lut->Build();
|
|
this->SetLookupTable(lut);
|
|
lut->Delete();
|
|
}
|
|
unsigned char *color = lut->MapValue(b);
|
|
this->WriterHelper->append(",");
|
|
this->WriterHelper->append((double)color[0]/255.0);
|
|
this->WriterHelper->append(",");
|
|
this->WriterHelper->append((double)color[1]/255.0);
|
|
this->WriterHelper->append(",");
|
|
this->WriterHelper->append((double)color[2]/255.0);
|
|
}
|
|
else
|
|
{
|
|
if (vtkMath::IsNan(b))
|
|
{
|
|
this->WriterHelper->append(",null");
|
|
}
|
|
else
|
|
{
|
|
this->WriterHelper->append(",");
|
|
this->WriterHelper->append(b);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void vtkGeoJSONWriter::WriteData()
|
|
{
|
|
ostream *fp;
|
|
vtkPolyData *input = vtkPolyData::SafeDownCast(this->GetInput());
|
|
|
|
vtkDebugMacro(<<"Writing vtk polygonal data to geojson file...");
|
|
fp=this->OpenFile();
|
|
if ( !fp )
|
|
{
|
|
return;
|
|
}
|
|
|
|
this->WriterHelper->append("{\n");
|
|
this->WriterHelper->append("\"type\": \"Feature\",\n");
|
|
vtkDataArray *da = input->GetPointData()->GetScalars();
|
|
if (!da)
|
|
{
|
|
da = input->GetPointData()->GetArray(0);
|
|
}
|
|
if (da)
|
|
{
|
|
switch (this->ScalarFormat)
|
|
{
|
|
case 0:
|
|
this->WriterHelper->append("\"properties\": {\"ScalarFormat\": \"none\"},\n");
|
|
break;
|
|
case 1:
|
|
this->WriterHelper->append("\"properties\": {\"ScalarFormat\": \"rgb\"},\n");
|
|
break;
|
|
case 2:
|
|
double rng[2];
|
|
da->GetRange(rng);
|
|
this->WriterHelper->append("\"properties\": {\"ScalarFormat\": \"values\", \"ScalarRange\": [");
|
|
this->WriterHelper->append(rng[0]);
|
|
this->WriterHelper->append(",");
|
|
this->WriterHelper->append(rng[1]);
|
|
this->WriterHelper->append("] },\n");
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this->WriterHelper->append("\"properties\": {\"ScalarFormat\": \"none\"},\n");
|
|
}
|
|
this->WriterHelper->append("\"geometry\":\n");
|
|
this->WriterHelper->append("{\n");
|
|
this->WriterHelper->append("\"type\": \"GeometryCollection\",\n");
|
|
this->WriterHelper->append("\"geometries\":\n");
|
|
this->WriterHelper->append("[\n");
|
|
|
|
vtkIdType cellLoc = 0;
|
|
vtkIdType *cellPts = NULL;
|
|
vtkIdType cellSize = 0;
|
|
vtkIdType numlines, numpolys;
|
|
numlines = input->GetLines()->GetNumberOfCells();
|
|
numpolys = input->GetPolys()->GetNumberOfCells();
|
|
|
|
//VERTS
|
|
vtkCellArray *ca;
|
|
ca = input->GetVerts();
|
|
if (ca && ca->GetNumberOfCells())
|
|
{
|
|
bool done = false;
|
|
vtkIdType inCell = 0;
|
|
vtkIdType ptCnt = 0;
|
|
do //loop to break into sections with < VTK_GJWRITER_MAXPOINTS points
|
|
{
|
|
this->WriterHelper->append("{\n");
|
|
this->WriterHelper->append("\"type\": \"MultiPoint\",\n");
|
|
this->WriterHelper->append("\"coordinates\":\n");
|
|
this->WriterHelper->append("[\n");
|
|
for (; inCell < ca->GetNumberOfCells() && ptCnt < VTK_GJWRITER_MAXPOINTS; inCell++)
|
|
{
|
|
ca->GetCell(cellLoc, cellSize, cellPts);
|
|
cellLoc += cellSize+1;
|
|
ptCnt += cellSize;
|
|
vtkIdType inPt;
|
|
for (inPt = 0; inPt < cellSize; inPt++)
|
|
{
|
|
double coords[3];
|
|
input->GetPoint(cellPts[inPt], coords);
|
|
this->WriterHelper->append("[");
|
|
for (int i=0; i<3; i++)
|
|
{
|
|
if (vtkMath::IsNan(coords[i]))
|
|
{
|
|
this->WriterHelper->append("null");
|
|
}
|
|
else
|
|
{
|
|
this->WriterHelper->append(coords[i]);
|
|
}
|
|
if (i!=2)
|
|
{
|
|
this->WriterHelper->append(",");
|
|
}
|
|
}
|
|
this->WriteScalar(da, cellPts[inPt]);
|
|
this->WriterHelper->append("]");
|
|
this->ConditionalComma(inPt, cellSize);
|
|
}
|
|
if (ptCnt<VTK_GJWRITER_MAXPOINTS)
|
|
{
|
|
this->ConditionalComma(inCell, ca->GetNumberOfCells());
|
|
}
|
|
this->WriterHelper->append("\n");
|
|
}
|
|
this->WriterHelper->append("]"); //coordinates for this cell array
|
|
if (inCell < ca->GetNumberOfCells())
|
|
{
|
|
ptCnt = 0;
|
|
this->WriterHelper->append(",\n");
|
|
}
|
|
else
|
|
{
|
|
if (numlines || numpolys)
|
|
{
|
|
this->WriterHelper->append(",");
|
|
}
|
|
done = true;
|
|
}
|
|
} while (!done);
|
|
}
|
|
|
|
//lines
|
|
ca = input->GetLines();
|
|
if (ca && ca->GetNumberOfCells())
|
|
{
|
|
bool done = false;
|
|
vtkIdType inCell = 0;
|
|
vtkIdType ptCnt = 0;
|
|
do //loop to break into sections with < VTK_GJWRITER_MAXPOINTS points
|
|
{
|
|
this->WriterHelper->append("{\n");
|
|
this->WriterHelper->append("\"type\": \"MultiLineString\",\n");
|
|
this->WriterHelper->append("\"coordinates\":\n");
|
|
this->WriterHelper->append("[\n");
|
|
for (; inCell < ca->GetNumberOfCells() && ptCnt < VTK_GJWRITER_MAXPOINTS; inCell++)
|
|
{
|
|
this->WriterHelper->append("[ "); //one cell
|
|
ca->GetCell(cellLoc, cellSize, cellPts);
|
|
cellLoc += cellSize+1;
|
|
ptCnt += cellSize;
|
|
vtkIdType inPt;
|
|
for (inPt = 0; inPt < cellSize; inPt++)
|
|
{
|
|
double coords[3];
|
|
input->GetPoint(cellPts[inPt], coords);
|
|
this->WriterHelper->append("[");
|
|
for (int i =0; i<3; i++)
|
|
{
|
|
if (vtkMath::IsNan(coords[i]))
|
|
{
|
|
this->WriterHelper->append("null");
|
|
}
|
|
else
|
|
{
|
|
this->WriterHelper->append(coords[i]);
|
|
}
|
|
if (i!=2)
|
|
{
|
|
this->WriterHelper->append(",");
|
|
}
|
|
}
|
|
this->WriteScalar(da, cellPts[inPt]);
|
|
this->WriterHelper->append("]");
|
|
this->ConditionalComma(inPt, cellSize);
|
|
}
|
|
this->WriterHelper->append("]");//one cell
|
|
if (ptCnt<VTK_GJWRITER_MAXPOINTS)
|
|
{
|
|
this->ConditionalComma(inCell, ca->GetNumberOfCells());
|
|
}
|
|
this->WriterHelper->append("\n");
|
|
}
|
|
this->WriterHelper->append("]"); //coordinates for this cell array
|
|
this->WriterHelper->append("\n");
|
|
this->WriterHelper->append("}\n"); //this cell array
|
|
if (inCell < ca->GetNumberOfCells())
|
|
{
|
|
ptCnt = 0;
|
|
this->WriterHelper->append(",\n");
|
|
}
|
|
else
|
|
{
|
|
if (numpolys)
|
|
{
|
|
this->WriterHelper->append(",");
|
|
}
|
|
done = true;
|
|
}
|
|
} while (!done);
|
|
}
|
|
//polygons
|
|
ca = input->GetPolys();
|
|
if (ca && ca->GetNumberOfCells())
|
|
{
|
|
bool done = false;
|
|
vtkIdType inCell = 0;
|
|
vtkIdType ptCnt = 0;
|
|
do //loop to break into sections with < VTK_GJWRITER_MAXPOINTS points
|
|
{
|
|
this->WriterHelper->append("{\n");
|
|
this->WriterHelper->append("\"type\": \"MultiPolygon\",\n");
|
|
this->WriterHelper->append("\"coordinates\":\n");
|
|
this->WriterHelper->append("[\n");
|
|
for (; inCell < ca->GetNumberOfCells() && ptCnt < VTK_GJWRITER_MAXPOINTS; inCell++)
|
|
{
|
|
this->WriterHelper->append("[[ "); //one cell
|
|
ca->GetCell(cellLoc, cellSize, cellPts);
|
|
cellLoc += cellSize+1;
|
|
ptCnt += cellSize;
|
|
vtkIdType inPt;
|
|
for (inPt = 0; inPt < cellSize; inPt++)
|
|
{
|
|
double coords[3];
|
|
input->GetPoint(cellPts[inPt], coords);
|
|
this->WriterHelper->append("[");
|
|
for (int i =0; i<3; i++)
|
|
{
|
|
if (vtkMath::IsNan(coords[i]))
|
|
{
|
|
this->WriterHelper->append("null");
|
|
}
|
|
else
|
|
{
|
|
this->WriterHelper->append(coords[i]);
|
|
}
|
|
if (i!=2)
|
|
{
|
|
this->WriterHelper->append(",");
|
|
}
|
|
}
|
|
this->WriteScalar(da, cellPts[inPt]);
|
|
this->WriterHelper->append("]");
|
|
this->ConditionalComma(inPt, cellSize);
|
|
}
|
|
this->WriterHelper->append(" ]]");//one cell
|
|
if (ptCnt<VTK_GJWRITER_MAXPOINTS)
|
|
{
|
|
this->ConditionalComma(inCell, ca->GetNumberOfCells());
|
|
}
|
|
this->WriterHelper->append("\n");
|
|
}
|
|
this->WriterHelper->append("]"); //coordinates for this cell array
|
|
this->WriterHelper->append("\n");
|
|
this->WriterHelper->append("}\n"); //this cell array
|
|
if (inCell < ca->GetNumberOfCells())
|
|
{
|
|
ptCnt = 0;
|
|
this->WriterHelper->append(",\n");
|
|
}
|
|
else
|
|
{
|
|
done = true;
|
|
}
|
|
} while (!done);
|
|
}
|
|
|
|
this->WriterHelper->append("]\n");//feature.geometry.GeometryCollection.geometries
|
|
this->WriterHelper->append("}\n");//feature.geometry
|
|
this->WriterHelper->append("}\n");//feature
|
|
|
|
fp->write(this->WriterHelper->Buffer, this->WriterHelper->GetSize());
|
|
this->WriterHelper->Clear();
|
|
|
|
fp->flush();
|
|
if (fp->fail())
|
|
{
|
|
vtkErrorMacro("Problem writing result check disk space.");
|
|
delete fp;
|
|
fp = NULL;
|
|
}
|
|
|
|
this->CloseFile(fp);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
char *vtkGeoJSONWriter::RegisterAndGetOutputString()
|
|
{
|
|
char *tmp = this->OutputString;
|
|
|
|
this->OutputString = NULL;
|
|
this->OutputStringLength = 0;
|
|
|
|
return tmp;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
vtkStdString vtkGeoJSONWriter::GetOutputStdString()
|
|
{
|
|
return vtkStdString(this->OutputString, this->OutputStringLength);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
vtkCxxSetObjectMacro(vtkGeoJSONWriter, LookupTable, vtkLookupTable)
|