2020-03-09 05:59:51 +01:00
|
|
|
/*
|
|
|
|
MDAL - Mesh Data Abstraction Library (MIT License)
|
|
|
|
Copyright (C) 2020 Lutra Consulting Ltd.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stddef.h>
|
|
|
|
#include <iosfwd>
|
|
|
|
#include <iostream>
|
|
|
|
#include <fstream>
|
|
|
|
#include <sstream>
|
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
|
|
|
#include <map>
|
|
|
|
#include <cassert>
|
|
|
|
#include <limits>
|
|
|
|
#include <algorithm>
|
|
|
|
|
|
|
|
#include "mdal_xms_tin.hpp"
|
|
|
|
#include "mdal.h"
|
|
|
|
#include "mdal_utils.hpp"
|
|
|
|
#include "mdal_logger.hpp"
|
|
|
|
|
|
|
|
#define DRIVER_NAME "XMS_TIN"
|
|
|
|
|
|
|
|
MDAL::DriverXmsTin::DriverXmsTin():
|
|
|
|
Driver( DRIVER_NAME,
|
|
|
|
"XMS Tin Mesh File",
|
|
|
|
"*.tin",
|
|
|
|
Capability::ReadMesh
|
|
|
|
)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
MDAL::DriverXmsTin *MDAL::DriverXmsTin::create()
|
|
|
|
{
|
|
|
|
return new DriverXmsTin();
|
|
|
|
}
|
|
|
|
|
|
|
|
int MDAL::DriverXmsTin::faceVerticesMaximumCount() const
|
|
|
|
{
|
|
|
|
return MAX_VERTICES_PER_FACE_TIN;
|
|
|
|
}
|
|
|
|
|
|
|
|
MDAL::DriverXmsTin::~DriverXmsTin() = default;
|
|
|
|
|
|
|
|
bool MDAL::DriverXmsTin::canReadMesh( const std::string &uri )
|
|
|
|
{
|
|
|
|
std::ifstream in( uri, std::ifstream::in );
|
|
|
|
std::string line;
|
|
|
|
if ( !MDAL::getHeaderLine( in, line ) || !startsWith( line, "TIN" ) )
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-04-14 02:17:15 -04:00
|
|
|
std::unique_ptr<MDAL::Mesh> MDAL::DriverXmsTin::load( const std::string &meshFile, const std::string & )
|
2020-03-09 05:59:51 +01:00
|
|
|
{
|
|
|
|
MDAL::Log::resetLastStatus();
|
|
|
|
|
|
|
|
std::ifstream in( meshFile, std::ifstream::in );
|
|
|
|
std::string line;
|
|
|
|
// skip first line with "TIN" already checked in the canReadMesh
|
|
|
|
std::getline( in, line );
|
|
|
|
|
|
|
|
// Read vertices
|
|
|
|
if ( !std::getline( in, line ) || !startsWith( line, "BEGT" ) )
|
|
|
|
{
|
|
|
|
MDAL::Log::error( MDAL_Status::Err_UnknownFormat, name(), meshFile + " second line does not start with BEGT keyword" );
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
if ( !std::getline( in, line ) )
|
|
|
|
{
|
|
|
|
MDAL::Log::error( MDAL_Status::Err_IncompatibleMesh, name(), meshFile + " does not contain 3rd line" );
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
std::vector<std::string> chunks = split( line, ' ' );
|
|
|
|
if ( ( chunks.size() != 2 ) || ( chunks[0] != "VERT" ) )
|
|
|
|
{
|
|
|
|
MDAL::Log::error( MDAL_Status::Err_IncompatibleMesh, name(), meshFile + " 4th line does not contain VERT keyword with number of vertices" );
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
size_t vertexCount = MDAL::toSizeT( chunks[1] );
|
|
|
|
Vertices vertices( vertexCount );
|
|
|
|
for ( size_t i = 0; i < vertexCount; ++i )
|
|
|
|
{
|
|
|
|
if ( !std::getline( in, line ) )
|
|
|
|
{
|
|
|
|
MDAL::Log::error( MDAL_Status::Err_IncompatibleMesh, name(), meshFile + " does not contain enough vertex definitions" );
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
chunks = split( line, ' ' );
|
|
|
|
if ( chunks.size() != 4 )
|
|
|
|
{
|
|
|
|
MDAL::Log::error( MDAL_Status::Err_IncompatibleMesh, name(), meshFile + " does not contain valid vertex definition" );
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
Vertex &vertex = vertices[i];
|
|
|
|
vertex.x = MDAL::toDouble( chunks[0] );
|
|
|
|
vertex.y = MDAL::toDouble( chunks[1] );
|
|
|
|
vertex.z = MDAL::toDouble( chunks[2] );
|
|
|
|
}
|
|
|
|
|
|
|
|
// Read triangles
|
|
|
|
if ( !std::getline( in, line ) )
|
|
|
|
{
|
2020-05-11 01:19:22 -04:00
|
|
|
MDAL::Log::error( MDAL_Status::Err_IncompatibleMesh, name(), meshFile + " does not contain valid triangle definition" );
|
2020-03-09 05:59:51 +01:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
chunks = split( line, ' ' );
|
|
|
|
if ( ( chunks.size() != 2 ) || ( chunks[0] != "TRI" ) )
|
|
|
|
{
|
|
|
|
MDAL::Log::error( MDAL_Status::Err_IncompatibleMesh, name(), meshFile + " does not contain TRI keyword" );
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
size_t faceCount = MDAL::toSizeT( chunks[1] );
|
|
|
|
Faces faces( faceCount );
|
|
|
|
for ( size_t i = 0; i < faceCount; ++i )
|
|
|
|
{
|
|
|
|
if ( !std::getline( in, line ) )
|
|
|
|
{
|
|
|
|
MDAL::Log::error( MDAL_Status::Err_IncompatibleMesh, name(), meshFile + " does not contain enough triangle definitions" );
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
chunks = split( line, ' ' );
|
|
|
|
if ( chunks.size() != 3 )
|
|
|
|
{
|
|
|
|
// should have 3 indexes
|
2020-05-11 01:19:22 -04:00
|
|
|
MDAL::Log::error( MDAL_Status::Err_IncompatibleMesh, name(), meshFile + " does not contain valid triangle defintion" );
|
2020-03-09 05:59:51 +01:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
Face &face = faces[i];
|
|
|
|
face.resize( MAX_VERTICES_PER_FACE_TIN );
|
|
|
|
face[0] = MDAL::toSizeT( chunks[0] ) - 1;
|
|
|
|
face[1] = MDAL::toSizeT( chunks[1] ) - 1;
|
|
|
|
face[2] = MDAL::toSizeT( chunks[2] ) - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Final keyword
|
|
|
|
if ( !std::getline( in, line ) || !startsWith( line, "ENDT" ) )
|
|
|
|
{
|
|
|
|
MDAL::Log::error( MDAL_Status::Err_IncompatibleMesh, name(), meshFile + " does not end with ENDT keyword" );
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::unique_ptr< MemoryMesh > mesh(
|
|
|
|
new MemoryMesh(
|
|
|
|
DRIVER_NAME,
|
|
|
|
vertices.size(),
|
|
|
|
0,
|
|
|
|
faces.size(),
|
|
|
|
MAX_VERTICES_PER_FACE_TIN,
|
|
|
|
computeExtent( vertices ),
|
|
|
|
meshFile
|
|
|
|
)
|
|
|
|
);
|
|
|
|
mesh->faces = faces;
|
|
|
|
mesh->vertices = vertices;
|
|
|
|
|
|
|
|
// Add Bed Elevation
|
|
|
|
MDAL::addBedElevationDatasetGroup( mesh.get(), vertices );
|
|
|
|
|
|
|
|
return std::unique_ptr<Mesh>( mesh.release() );
|
|
|
|
}
|