1 /*
2  MDAL - Mesh Data Abstraction Library (MIT License)
3  Copyright (C) 2018 Peter Petrik (zilolv at gmail dot com)
4 */
5 
6 #include "gtest/gtest.h"
7 
8 #include "mdal_testutils.hpp"
9 #include "mdal_config.hpp"
10 #include "mdal_utils.hpp"
11 #include <vector>
12 #include <math.h>
13 #include <assert.h>
14 #include <fstream>
15 #include <stdio.h>
16 
data_path()17 const char *data_path()
18 {
19   return TESTDATA;
20 }
21 
drivers_path()22 const char *drivers_path()
23 {
24   return DRIVERS_PATH;
25 }
26 
27 
test_file(std::string basename)28 std::string test_file( std::string basename )
29 {
30   std::string path( data_path() );
31   path += basename;
32   return path;
33 }
34 
tmp_file(std::string basename)35 std::string tmp_file( std::string basename )
36 {
37   std::string path( data_path() + std::string( "/tmp" ) );
38   path += basename;
39   return path;
40 }
41 
copy(const std::string & src,const std::string & dest)42 void copy( const std::string &src, const std::string &dest )
43 {
44   std::ifstream srcS;
45   std::ofstream dstS;
46 
47   srcS.open( src, std::ios::in | std::ios::binary );
48   dstS.open( dest, std::ios::out | std::ios::binary );
49   dstS << srcS.rdbuf();
50 }
51 
deleteFile(const std::string & path)52 void deleteFile( const std::string &path )
53 {
54   if ( fileExists( path ) )
55     remove( path.c_str() );
56 }
57 
fileExists(const std::string & filename)58 bool fileExists( const std::string &filename )
59 {
60   std::ifstream in( filename );
61   return in.good();
62 }
63 
getActive(MDAL_DatasetH dataset,int index)64 int getActive( MDAL_DatasetH dataset, int index )
65 {
66   bool hasFlag = MDAL_D_hasActiveFlagCapability( dataset );
67   if ( hasFlag )
68   {
69     int active;
70     int nValuesRead = MDAL_D_data( dataset, index, 1, MDAL_DataType::ACTIVE_INTEGER, &active );
71     if ( nValuesRead != 1 )
72       return -2;
73     return static_cast<bool>( active );
74   }
75   else
76   {
77     return -1;
78   }
79 }
80 
getValue(MDAL_DatasetH dataset,int index)81 double getValue( MDAL_DatasetH dataset, int index )
82 {
83   double val;
84   int nValuesRead = MDAL_D_data( dataset, index, 1, MDAL_DataType::SCALAR_DOUBLE, &val );
85   if ( nValuesRead != 1 )
86     return 0;
87 
88   return val;
89 }
90 
getValueX(MDAL_DatasetH dataset,int index)91 double getValueX( MDAL_DatasetH dataset, int index )
92 {
93   double val[2];
94   int nValuesRead = MDAL_D_data( dataset, index, 1, MDAL_DataType::VECTOR_2D_DOUBLE, &val );
95   if ( nValuesRead != 1 )
96     return 0;
97 
98   return val[0];
99 }
100 
getValueY(MDAL_DatasetH dataset,int index)101 double getValueY( MDAL_DatasetH dataset, int index )
102 {
103   double val[2];
104   int nValuesRead = MDAL_D_data( dataset, index, 1, MDAL_DataType::VECTOR_2D_DOUBLE, &val );
105   if ( nValuesRead != 1 )
106     return 0;
107 
108   return val[1];
109 }
110 
getLevelsCount3D(MDAL_DatasetH dataset,int index)111 int getLevelsCount3D( MDAL_DatasetH dataset, int index )
112 {
113   int count;
114   int nValuesRead = MDAL_D_data( dataset, index, 1, MDAL_DataType::VERTICAL_LEVEL_COUNT_INTEGER, &count );
115   if ( nValuesRead != 1 )
116     return -1;
117 
118   return count;
119 }
120 
getLevelZ3D(MDAL_DatasetH dataset,int index)121 double getLevelZ3D( MDAL_DatasetH dataset, int index )
122 {
123   double z;
124   int nValuesRead = MDAL_D_data( dataset, index, 1, MDAL_DataType::VERTICAL_LEVEL_DOUBLE, &z );
125   if ( nValuesRead != 1 )
126     return -1;
127 
128   return z;
129 }
130 
getValue3D(MDAL_DatasetH dataset,int index)131 double getValue3D( MDAL_DatasetH dataset, int index )
132 {
133   double val;
134   int nValuesRead = MDAL_D_data( dataset, index, 1, MDAL_DataType::SCALAR_VOLUMES_DOUBLE, &val );
135   if ( nValuesRead != 1 )
136     return 0;
137 
138   return val;
139 }
140 
getValue3DX(MDAL_DatasetH dataset,int index)141 double getValue3DX( MDAL_DatasetH dataset, int index )
142 {
143   double val[2];
144   int nValuesRead = MDAL_D_data( dataset, index, 1, MDAL_DataType::VECTOR_2D_VOLUMES_DOUBLE, &val );
145   if ( nValuesRead != 1 )
146     return 0;
147 
148   return val[0];
149 }
150 
getValue3DY(MDAL_DatasetH dataset,int index)151 double getValue3DY( MDAL_DatasetH dataset, int index )
152 {
153   double val[2];
154   int nValuesRead = MDAL_D_data( dataset, index, 1, MDAL_DataType::VECTOR_2D_VOLUMES_DOUBLE, &val );
155   if ( nValuesRead != 1 )
156     return 0;
157 
158   return val[1];
159 }
160 
get3DFrom2D(MDAL_DatasetH dataset,int index)161 int get3DFrom2D( MDAL_DatasetH dataset, int index )
162 {
163   int index3d;
164   int nValuesRead = MDAL_D_data( dataset, index, 1, MDAL_DataType::FACE_INDEX_TO_VOLUME_INDEX_INTEGER, &index3d );
165   if ( nValuesRead != 1 )
166     return -1;
167 
168   return index3d;
169 }
170 
compareVectors(const std::vector<int> & a,const std::vector<int> & b)171 bool compareVectors( const std::vector<int> &a, const std::vector<int> &b )
172 {
173   if ( a.size() != b.size() )
174     return false;
175 
176   for ( size_t i = 0; i < a.size(); ++i )
177     if ( a[i] != b[i] )
178       return false;
179 
180   return true;
181 }
182 
compareVectors(const std::vector<double> & a,const std::vector<double> & b)183 bool compareVectors( const std::vector<double> &a, const std::vector<double> &b )
184 {
185   double eps = 1e-4;
186   if ( a.size() != b.size() )
187     return false;
188 
189   for ( size_t i = 0; i < a.size(); ++i )
190     if ( fabs( a[i] - b[i] ) > eps )
191       return false;
192 
193   return true;
194 }
195 
compareMeshFrames(MDAL_MeshH meshA,MDAL_MeshH meshB)196 void compareMeshFrames( MDAL_MeshH meshA, MDAL_MeshH meshB )
197 {
198   // Vertices
199   int orignal_v_count = MDAL_M_vertexCount( meshA );
200   int saved_v_count = MDAL_M_vertexCount( meshB );
201   EXPECT_EQ( orignal_v_count, saved_v_count );
202 
203   std::vector<double> coordsA = getCoordinates( meshA, orignal_v_count );
204   std::vector<double> coordsB = getCoordinates( meshB, saved_v_count );
205   EXPECT_TRUE( compareVectors( coordsA, coordsB ) );
206 
207   // Edges
208   int orignal_e_count = MDAL_M_edgeCount( meshA );
209   int saved_e_count = MDAL_M_edgeCount( meshB );
210   EXPECT_EQ( orignal_e_count, saved_e_count );
211 
212   std::vector<int> original_start;
213   std::vector<int> original_end;
214   std::vector<int> saved_start;
215   std::vector<int> saved_end;
216 
217   getEdgeVertexIndices( meshA, orignal_e_count, original_start, original_end );
218   getEdgeVertexIndices( meshB, saved_e_count, saved_start, saved_end );
219 
220   EXPECT_TRUE( compareVectors( original_start, saved_start ) );
221   EXPECT_TRUE( compareVectors( original_end, saved_end ) );
222 
223   // Faces
224   int orignal_f_count = MDAL_M_faceCount( meshA );
225   int saved_f_count = MDAL_M_faceCount( meshB );
226   EXPECT_EQ( orignal_f_count, saved_f_count );
227 
228   std::vector<int> verticesA = faceVertexIndices( meshA, orignal_f_count );
229   std::vector<int> verticesB = faceVertexIndices( meshB, saved_f_count );
230   EXPECT_TRUE( compareVectors( verticesA, verticesB ) );
231 }
232 
getCoordinates(MDAL_MeshH mesh,int verticesCount)233 std::vector<double> getCoordinates( MDAL_MeshH mesh, int verticesCount )
234 {
235   MDAL_MeshVertexIteratorH iterator = MDAL_M_vertexIterator( mesh );
236   std::vector<double> coordinates( static_cast<size_t>( 3 * verticesCount ) );
237   MDAL_VI_next( iterator, verticesCount, coordinates.data() );
238   MDAL_VI_close( iterator );
239   return coordinates;
240 }
241 
getEdgeVertexIndices(MDAL_MeshH mesh,int edgesCount,std::vector<int> & start,std::vector<int> & end)242 void getEdgeVertexIndices( MDAL_MeshH mesh, int edgesCount, std::vector<int> &start, std::vector<int> &end )
243 {
244   MDAL_MeshEdgeIteratorH iterator = MDAL_M_edgeIterator( mesh );
245   start.clear();
246   start.resize( static_cast<size_t>( edgesCount ) );
247   end.clear();
248   end.resize( static_cast<size_t>( edgesCount ) );
249   MDAL_EI_next( iterator, edgesCount, start.data(), end.data() );
250   MDAL_EI_close( iterator );
251 }
252 
_getVertexCoordinatesAt(MDAL_MeshH mesh,int index,int coordIndex)253 double _getVertexCoordinatesAt( MDAL_MeshH mesh, int index, int coordIndex )
254 {
255   // coordIndex = 0 x
256   // coordIndex = 1 y
257   // coordIndex = 2 z
258   std::vector<double> coordinates = getCoordinates( mesh, index + 1 );
259   double val = coordinates[static_cast<size_t>( index * 3 + coordIndex )];
260   return val;
261 }
262 
getVertexXCoordinatesAt(MDAL_MeshH mesh,int index)263 double getVertexXCoordinatesAt( MDAL_MeshH mesh, int index )
264 {
265   return _getVertexCoordinatesAt( mesh, index, 0 );
266 }
267 
getVertexYCoordinatesAt(MDAL_MeshH mesh,int index)268 double getVertexYCoordinatesAt( MDAL_MeshH mesh, int index )
269 {
270   return _getVertexCoordinatesAt( mesh, index, 1 );
271 }
272 
getVertexZCoordinatesAt(MDAL_MeshH mesh,int index)273 double getVertexZCoordinatesAt( MDAL_MeshH mesh, int index )
274 {
275   return _getVertexCoordinatesAt( mesh, index, 2 );
276 }
277 
faceVertexIndices(MDAL_MeshH mesh,int faceCount)278 std::vector<int> faceVertexIndices( MDAL_MeshH mesh, int faceCount )
279 {
280   MDAL_MeshFaceIteratorH iterator = MDAL_M_faceIterator( mesh );
281   int faceOffsetsBufferLen = faceCount + 1;
282   int vertexIndicesBufferLen = faceOffsetsBufferLen * MDAL_M_faceVerticesMaximumCount( mesh );
283   std::vector<int> faceOffsetsBuffer( static_cast<size_t>( faceOffsetsBufferLen ) );
284   std::vector<int> vertexIndicesBuffer( static_cast<size_t>( vertexIndicesBufferLen ) );
285   MDAL_FI_next( iterator, faceOffsetsBufferLen, faceOffsetsBuffer.data(),
286                 vertexIndicesBufferLen, vertexIndicesBuffer.data() );
287   MDAL_FI_close( iterator );
288   return vertexIndicesBuffer;
289 }
290 
getFaceVerticesCountAt(MDAL_MeshH mesh,int faceIndex)291 int getFaceVerticesCountAt( MDAL_MeshH mesh, int faceIndex )
292 {
293   MDAL_MeshFaceIteratorH iterator = MDAL_M_faceIterator( mesh );
294   int faceOffsetsBufferLen = faceIndex + 1;
295   int vertexIndicesBufferLen = faceOffsetsBufferLen * MDAL_M_faceVerticesMaximumCount( mesh );
296   std::vector<int> faceOffsetsBuffer( static_cast<size_t>( faceOffsetsBufferLen ) );
297   std::vector<int> vertexIndicesBuffer( static_cast<size_t>( vertexIndicesBufferLen ) );
298   MDAL_FI_next( iterator, faceOffsetsBufferLen, faceOffsetsBuffer.data(),
299                 vertexIndicesBufferLen, vertexIndicesBuffer.data() );
300   MDAL_FI_close( iterator );
301   int count;
302   if ( faceIndex == 0 )
303   {
304     count = faceOffsetsBuffer[static_cast<size_t>( faceIndex )];
305   }
306   else
307   {
308     count = faceOffsetsBuffer[static_cast<size_t>( faceIndex )] - faceOffsetsBuffer[static_cast<size_t>( faceIndex - 1 )];
309   }
310   return count;
311 }
312 
getFaceVerticesIndexAt(MDAL_MeshH mesh,int faceIndex,int index)313 int getFaceVerticesIndexAt( MDAL_MeshH mesh, int faceIndex, int index )
314 {
315   MDAL_MeshFaceIteratorH iterator = MDAL_M_faceIterator( mesh );
316   int faceOffsetsBufferLen = faceIndex + 1;
317   int vertexIndicesBufferLen = faceOffsetsBufferLen * MDAL_M_faceVerticesMaximumCount( mesh );
318   std::vector<int> faceOffsetsBuffer( static_cast<size_t>( faceOffsetsBufferLen ) );
319   std::vector<int> vertexIndicesBuffer( static_cast<size_t>( vertexIndicesBufferLen ) );
320   MDAL_FI_next( iterator, faceOffsetsBufferLen, faceOffsetsBuffer.data(),
321                 vertexIndicesBufferLen, vertexIndicesBuffer.data() );
322   MDAL_FI_close( iterator );
323   int id;
324   if ( faceIndex == 0 )
325   {
326     id = index;
327   }
328   else
329   {
330     id = faceOffsetsBuffer[static_cast<size_t>( faceIndex - 1 )] + index;
331   }
332 
333   int faceVertexIndex = vertexIndicesBuffer[static_cast<size_t>( id )];
334   return faceVertexIndex;
335 }
336 
set_mdal_driver_path(const std::string & dirname)337 void set_mdal_driver_path( const std::string &dirname )
338 {
339   std::string fullPath = std::string( drivers_path() ) +  "/" + dirname;
340 #ifdef WIN32
341   size_t requiredSize = 0;
342   getenv_s( &requiredSize, NULL, 0, "MDAL_DRIVER_PATH" );
343   if ( requiredSize == 0 )
344   {
345     _putenv_s( "MDAL_DRIVER_PATH", fullPath.c_str() );
346   }
347 #endif
348 
349 #ifndef WIN32
350   setenv( "MDAL_DRIVER_PATH", fullPath.c_str(), 0 );
351 #endif
352 }
353 
init_test()354 void init_test()
355 {
356 }
357 
finalize_test()358 void finalize_test()
359 {
360 }
361 
compareDurationInHours(double h1,double h2)362 bool compareDurationInHours( double h1, double h2 )
363 {
364   return fabs( h1 - h2 ) < 1.0 / 3600 / 1000;
365 }
366 
hasReferenceTime(MDAL_DatasetGroupH group)367 bool hasReferenceTime( MDAL_DatasetGroupH group )
368 {
369   return std::strcmp( MDAL_G_referenceTime( group ), "" ) != 0;
370 }
371 
compareReferenceTime(MDAL_DatasetGroupH group,const char * referenceTime)372 bool compareReferenceTime( MDAL_DatasetGroupH group, const char *referenceTime )
373 {
374   return std::strcmp( MDAL_G_referenceTime( group ), referenceTime ) == 0;
375 }
376 
saveAndCompareMesh(const std::string & filename,const std::string & savedFile,const std::string & driver,const std::string & meshName)377 void saveAndCompareMesh( const std::string &filename, const std::string &savedFile, const std::string &driver, const std::string &meshName )
378 {
379   //test driver capability
380   EXPECT_TRUE( MDAL_DR_saveMeshCapability( MDAL_driverFromName( driver.c_str() ) ) );
381 
382   std::string uri( filename );
383 
384   std::string savedUri = driver + ":\"" + savedFile + "\"";
385 
386   if ( !meshName.empty() )
387   {
388     uri = "\"" + uri + "\":" + meshName;
389     savedUri = savedUri + ":" + meshName;
390   }
391 
392   // Open mesh
393   MDAL_MeshH meshToSave = MDAL_LoadMesh( uri.c_str() );
394   EXPECT_NE( meshToSave, nullptr );
395   MDAL_Status s = MDAL_LastStatus();
396   ASSERT_EQ( MDAL_Status::None, s );
397 
398   // Save the mesh
399   MDAL_SaveMeshWithUri( meshToSave, savedUri.c_str() );
400   s = MDAL_LastStatus();
401   ASSERT_EQ( MDAL_Status::None, s );
402 
403   // Load saved mesh
404   MDAL_MeshH savedMesh = MDAL_LoadMesh( savedFile.c_str() );
405   EXPECT_NE( savedMesh, nullptr );
406   s = MDAL_LastStatus();
407   ASSERT_EQ( MDAL_Status::None, s );
408 
409   // Compare saved with the original mesh
410   compareMeshFrames( meshToSave, savedMesh );
411 
412   MDAL_CloseMesh( savedMesh );
413 
414   // Again but with other API method
415   MDAL_SaveMesh( meshToSave,  savedFile.c_str(), driver.c_str() );
416   s = MDAL_LastStatus();
417   ASSERT_EQ( MDAL_Status::None, s );
418 
419   // Load saved mesh
420   savedMesh = MDAL_LoadMesh( savedFile.c_str() );
421   EXPECT_NE( savedMesh, nullptr );
422   s = MDAL_LastStatus();
423   ASSERT_EQ( MDAL_Status::None, s );
424 
425   // Close meshed and delete all the files
426   MDAL_CloseMesh( meshToSave );
427   MDAL_CloseMesh( savedMesh );
428   std::remove( savedFile.c_str() );
429 }
430