|
@@ -34,7 +34,7 @@ MDAL::Mesh2dm::Mesh2dm( size_t faceVerticesMaximumCount, |
|
|
|
|
|
MDAL::Mesh2dm::~Mesh2dm() = default; |
|
|
|
|
|
bool _parse_vertex_id_gaps( std::map<size_t, size_t> &vertexIDtoIndex, size_t vertexIndex, size_t vertexID ) |
|
|
static bool _parse_vertex_id_gaps( std::map<size_t, size_t> &vertexIDtoIndex, size_t vertexIndex, size_t vertexID ) |
|
|
{ |
|
|
if ( vertexIndex == vertexID ) |
|
|
return false; |
|
@@ -50,6 +50,21 @@ bool _parse_vertex_id_gaps( std::map<size_t, size_t> &vertexIDtoIndex, size_t ve |
|
|
return false; |
|
|
} |
|
|
|
|
|
static void _persist_native_index( std::vector<double> &arr, size_t nativeID, size_t ourId, size_t maxOurId ) |
|
|
{ |
|
|
if ( !arr.empty() || ( nativeID != ourId + 1 ) ) |
|
|
{ |
|
|
// we have gaps in face indexing |
|
|
if ( arr.empty() ) |
|
|
{ |
|
|
arr.resize( maxOurId ); |
|
|
for ( size_t i = 0; i < ourId; ++i ) |
|
|
arr[i] = static_cast<double>( i + 1 ); |
|
|
} |
|
|
arr[ourId] = static_cast<double>( nativeID ); |
|
|
} |
|
|
} |
|
|
|
|
|
size_t MDAL::Mesh2dm::vertexIndex( size_t vertexID ) const |
|
|
{ |
|
|
auto ni2i = mVertexIDtoIndex.find( vertexID ); |
|
@@ -120,11 +135,16 @@ std::unique_ptr<MDAL::Mesh> MDAL::Driver2dm::load( const std::string &meshFile, |
|
|
size_t materialCount = 0; |
|
|
bool hasMaterialsDefinitionsForElements = false; |
|
|
|
|
|
std::vector<double> nativeVertexIds; |
|
|
std::vector<double> nativeFaceIds; |
|
|
std::vector<double> nativeEdgeIds; |
|
|
|
|
|
// Find out how many nodes and elements are contained in the .2dm mesh file |
|
|
while ( std::getline( in, line ) ) |
|
|
{ |
|
|
if ( startsWith( line, "E4Q" ) || |
|
|
startsWith( line, "E3T" ) ) |
|
|
startsWith( line, "E3T" ) || |
|
|
startsWith( line, "E6T" ) ) |
|
|
{ |
|
|
faceCount++; |
|
|
} |
|
@@ -137,7 +157,6 @@ std::unique_ptr<MDAL::Mesh> MDAL::Driver2dm::load( const std::string &meshFile, |
|
|
edgesCount++; |
|
|
} |
|
|
else if ( startsWith( line, "E3L" ) || |
|
|
startsWith( line, "E6T" ) || |
|
|
startsWith( line, "E8Q" ) || |
|
|
startsWith( line, "E9Q" ) ) |
|
|
{ |
|
@@ -156,6 +175,7 @@ std::unique_ptr<MDAL::Mesh> MDAL::Driver2dm::load( const std::string &meshFile, |
|
|
Vertices vertices( vertexCount ); |
|
|
Edges edges( edgesCount ); |
|
|
Faces faces( faceCount ); |
|
|
size_t maxVerticesPerFace = 2; |
|
|
|
|
|
// .2dm mesh files may have any number of material ID columns |
|
|
std::vector<std::vector<double>> faceMaterials; |
|
@@ -174,24 +194,31 @@ std::unique_ptr<MDAL::Mesh> MDAL::Driver2dm::load( const std::string &meshFile, |
|
|
while ( std::getline( in, line ) ) |
|
|
{ |
|
|
if ( startsWith( line, "E4Q" ) || |
|
|
startsWith( line, "E3T" ) |
|
|
startsWith( line, "E3T" ) || |
|
|
startsWith( line, "E6T" ) |
|
|
) |
|
|
{ |
|
|
chunks = split( line, ' ' ); |
|
|
assert( faceIndex < faceCount ); |
|
|
|
|
|
const size_t faceVertexCount = MDAL::toSizeT( line[1] ); |
|
|
assert( ( faceVertexCount == 3 ) || ( faceVertexCount == 4 ) ); |
|
|
assert( ( faceVertexCount == 3 ) || ( faceVertexCount == 4 ) || ( faceVertexCount == 6 ) ); |
|
|
if ( maxVerticesPerFace < faceVertexCount ) |
|
|
maxVerticesPerFace = faceVertexCount; |
|
|
|
|
|
Face &face = faces[faceIndex]; |
|
|
face.resize( faceVertexCount ); |
|
|
|
|
|
// chunks format here |
|
|
// E** id vertex_id1, vertex_id2, vertex_id3, material_id [, aux_column_1, aux_column_2, ...] |
|
|
// E** id vertex_id1, vertex_id2, vertex_id3, ..., material_id [, aux_column_1, aux_column_2, ...] |
|
|
// vertex ids are numbered from 1 |
|
|
// Right now we just store node IDs here - we will convert them to node indices afterwards |
|
|
assert( chunks.size() > faceVertexCount + 1 ); |
|
|
|
|
|
// in case we have gaps/reorders in native indexes, store it |
|
|
size_t nativeID = MDAL::toSizeT( chunks[1] ); |
|
|
_persist_native_index( nativeFaceIds, nativeID, faceIndex, faceCount ); |
|
|
|
|
|
for ( size_t i = 0; i < faceVertexCount; ++i ) |
|
|
face[i] = MDAL::toSizeT( chunks[i + 2] ) - 1; // 2dm is numbered from 1 |
|
|
|
|
@@ -237,6 +264,10 @@ std::unique_ptr<MDAL::Mesh> MDAL::Driver2dm::load( const std::string &meshFile, |
|
|
chunks = split( line, ' ' ); |
|
|
assert( edgeIndex < edgesCount ); |
|
|
assert( chunks.size() > 4 ); |
|
|
// in case we have gaps/reorders in native indexes, store it |
|
|
size_t nativeID = MDAL::toSizeT( chunks[1] ); |
|
|
_persist_native_index( nativeEdgeIds, nativeID, edgeIndex, edgesCount ); |
|
|
|
|
|
size_t startVertexIndex = MDAL::toSizeT( chunks[2] ) - 1; // 2dm is numbered from 1 |
|
|
size_t endVertexIndex = MDAL::toSizeT( chunks[3] ) - 1; // 2dm is numbered from 1 |
|
|
Edge &edge = edges[edgeIndex]; |
|
@@ -261,9 +292,11 @@ std::unique_ptr<MDAL::Mesh> MDAL::Driver2dm::load( const std::string &meshFile, |
|
|
} |
|
|
lastVertexID = nodeID; |
|
|
} |
|
|
nodeID -= 1; // 2dm is numbered from 1 |
|
|
|
|
|
_parse_vertex_id_gaps( vertexIDtoIndex, vertexIndex, nodeID ); |
|
|
// in case we have gaps/reorders in native indexes, store it |
|
|
_persist_native_index( nativeVertexIds, nodeID, vertexIndex, vertexCount ); |
|
|
_parse_vertex_id_gaps( vertexIDtoIndex, vertexIndex, nodeID - 1 ); |
|
|
|
|
|
assert( vertexIndex < vertexCount ); |
|
|
Vertex &vertex = vertices[vertexIndex]; |
|
|
vertex.x = toDouble( chunks[2] ); |
|
@@ -296,7 +329,7 @@ std::unique_ptr<MDAL::Mesh> MDAL::Driver2dm::load( const std::string &meshFile, |
|
|
|
|
|
std::unique_ptr< Mesh2dm > mesh( |
|
|
new Mesh2dm( |
|
|
MAX_VERTICES_PER_FACE_2DM, |
|
|
maxVerticesPerFace, |
|
|
mMeshFile, |
|
|
vertexIDtoIndex |
|
|
) |
|
@@ -308,6 +341,13 @@ std::unique_ptr<MDAL::Mesh> MDAL::Driver2dm::load( const std::string &meshFile, |
|
|
// Add Bed Elevation |
|
|
MDAL::addBedElevationDatasetGroup( mesh.get(), mesh->vertices() ); |
|
|
|
|
|
if ( !nativeFaceIds.empty() ) |
|
|
MDAL::addFaceScalarDatasetGroup( mesh.get(), nativeFaceIds, "NativeFaceIds" ); |
|
|
if ( !nativeVertexIds.empty() ) |
|
|
MDAL::addVertexScalarDatasetGroup( mesh.get(), nativeVertexIds, "NativeVertexIds" ); |
|
|
if ( !nativeEdgeIds.empty() ) |
|
|
MDAL::addEdgeScalarDatasetGroup( mesh.get(), nativeEdgeIds, "NativeEdgeIds" ); |
|
|
|
|
|
// Add material IDs |
|
|
if ( hasMaterialsDefinitionsForElements ) |
|
|
{ |
|
@@ -367,19 +407,21 @@ void MDAL::Driver2dm::save( const std::string &uri, MDAL::Mesh *mesh ) |
|
|
} |
|
|
|
|
|
// write faces |
|
|
std::vector<int> vertexIndices( mesh->faceVerticesMaximumCount() ); |
|
|
std::unique_ptr<MDAL::MeshFaceIterator> faceIterator = mesh->readFaces(); |
|
|
for ( size_t i = 0; i < mesh->facesCount(); ++i ) |
|
|
{ |
|
|
int faceOffsets[1]; |
|
|
int vertexIndices[MAX_VERTICES_PER_FACE_2DM]; |
|
|
faceIterator->next( 1, faceOffsets, 4, vertexIndices ); |
|
|
faceIterator->next( 1, faceOffsets, 4, vertexIndices.data() ); |
|
|
|
|
|
if ( faceOffsets[0] > 2 && faceOffsets[0] < 5 ) |
|
|
{ |
|
|
if ( faceOffsets[0] == 3 ) |
|
|
line = "E3T "; |
|
|
if ( faceOffsets[0] == 4 ) |
|
|
line = "E4Q "; |
|
|
if ( faceOffsets[0] == 6 ) |
|
|
line = "E6T "; |
|
|
|
|
|
line.append( std::to_string( i + 1 ) ); |
|
|
|
|
|