Manually saving and loading a triangulation is difficult. This is especially true when there are millions of elements and it must be fast. For this reason, there are functions in Fade to support you in saving and loading a triangulation, it’s zones and constraint edges. The contained file “examples_2D/ex11_save_and_load.cpp” provides simple demo source code for this purpose. Let’s discuss it:
Saving a triangulation
The below C++ code first creates a triangulation with zones, then it saves them.
int ex11_save_and_load_main() { // * 1 * Create 3 test zones for this demo and draw // the triangulation with pDiffZone highlighted. Fade_2D dt; Zone2* pEarthZone(NULL); // large circle Zone2* pMarsZone(NULL); // small circle Zone2* pDiffZone(NULL); // difference: large-small createTestZones(dt,pEarthZone,pMarsZone,pDiffZone); std::cout<<" triangulation, numT="<<dt.numberOfTriangles()<<std::endl; std::cout<<" pEarthZone, numT="<<pEarthZone->getNumberOfTriangles()<<std::endl; std::cout<<" pMarsZone, numT="<<pMarsZone->getNumberOfTriangles()<<std::endl; std::cout<<" pDiffZone, numT="<<pDiffZone->getNumberOfTriangles()<<std::endl; std::vector<Zone2*> vSaveZones; // Below we use this vector to save these zones vSaveZones.push_back(pEarthZone); vSaveZones.push_back(pMarsZone); vSaveZones.push_back(pDiffZone); pEarthZone->show("ex11_orgTriangulation_and_pEarthZone.ps",true,true); pMarsZone->show("ex11_orgTriangulation_and_pMarsZone.ps",true,true); pDiffZone->show("ex11_orgTriangulation_and_pDiffZone.ps",true,true); // * 2 * Save all triangles and vSaveZones (filename provided) std::cout<<"saveTriangulation()..."<<std::endl; dt.saveTriangulation("ex11_saveTriangulation.fade",vSaveZones); // * 3 * Save only vSaveZones (ofstream provided) std::cout<<"saveZones()..."<<std::endl; std::ofstream file("ex11_saveZones.fade",std::ios::binary); if(file.is_open()) { bool bOK=dt.saveZones(file,vSaveZones); file.close(); GASSEX(bOK); // End this demo if false } else { GASSEX(false); // End this demo } // * 4 * Save an individual zone (stringstream provided) std::cout<<"Zone2::save()..."<<std::endl; std::stringstream sstr; pDiffZone->save(sstr); }
- The above Step 1 calls the function
createTestZones()
to construct three demo-zonespEarthZone
,pMarsZone
andpDiffZone
. The code in this function is easy to understand, you might review the previous examples, especially Polygon Clipping and Boolean Operations. - The second step calls
Fade_2D::saveTriangulation()
to save the whole triangulation and the specified zones to a binary file with the name “ex11_saveTriangulation.fade” - The third step is a call to
Fade_2D::saveZones()
to save only the specified zones (plus a few fill-triangles as described further below). Notice that thesave...()
commands accept both, filenames and objects of typestd::ostream
. This time we use a file of typestd::ofstream
. - Step 4 saves an individual zone. Although we could push the zone into a
vector<Zone2*>
and useFade_2D::saveZones()
there is a shorter command, namelyZone2::save()
. This time we astd::stringstream
as target.
Loading a triangulation
No matter how a triangulation was saved, you can always use the Fade_2D::load()
command for loading. It accepts a filename or a std::istream
, see the listing below:
int ex11_save_and_load_main() { ... // * 5 * Reload the full triangulation with all zones std::cout<<"\nReloading...\n"<<std::endl; std::cout<<"Loading the full triangulation and the 3 zones..."<<std::endl; std::cout<<" ...first argument is the filename, \"ex11_saveTriangulation.fade\""<<std::endl; Fade_2D loadDt1; std::vector<Zone2*> vLoadZones1; bool bOK1=loadDt1.load("ex11_saveTriangulation.fade",vLoadZones1); GASSEX(bOK1); // End this demo if false std::cout<<" triangulation, numT="<<loadDt1.numberOfTriangles()<<std::endl; std::cout<<" pEarthZone, numT="<<vLoadZones1[0]->getNumberOfTriangles()<<std::endl; std::cout<<" pMarsZone, numT="<<vLoadZones1[1]->getNumberOfTriangles()<<std::endl; std::cout<<" pDiffZone, numT="<<vLoadZones1[2]->getNumberOfTriangles()<<std::endl; vLoadZones1[2]->show("ex11_allTriangles_reloaded_pDiffZone_highlighted.ps",true,true); // * 6 * Reload only the zones std::cout<<std::endl<<"\nLoading just the 3 zones"<<std::endl; std::cout<<" ...first argument is ifstream(\"ex11_saveZones.fade\")"<<std::endl; Fade_2D loadDt2; std::vector<Zone2*> vLoadZones2; std::ifstream inFile("ex11_saveZones.fade",std::ios::binary); bool bOK2(false); if(inFile.is_open()) { bOK2=loadDt2.load(inFile,vLoadZones2); inFile.close(); } GASSEX(bOK2); // End this demo if false std::cout<<" triangulation, numT="<<loadDt2.numberOfTriangles()<<std::endl; std::cout<<" pEarthZone, numT="<<vLoadZones2[0]->getNumberOfTriangles()<<std::endl; std::cout<<" pMarsZone, numT="<<vLoadZones2[1]->getNumberOfTriangles()<<std::endl; std::cout<<" pDiffZone, numT="<<vLoadZones2[2]->getNumberOfTriangles()<<std::endl; vLoadZones2[2]->show("ex11_zones_reloaded_pDiffZone_highlighted.ps",true,true); // * 7 * Reload one zone from stringstream std::cout<<std::endl<<"\nLoading only one zone"<<std::endl; std::cout<<" ...first argument is a stringstream"<<std::endl; Fade_2D loadDt3; std::vector<Zone2*> vLoadZones3; bool bOK3=loadDt3.load(sstr,vLoadZones3); GASSEX(bOK3); // End this demo if false std::cout<<" triangulation, numT="<<loadDt3.numberOfTriangles()<<std::endl; std::cout<<" pDiffZone, numT="<<vLoadZones3[0]->getNumberOfTriangles()<<std::endl; vLoadZones3[0]->show("ex11_one_zone_reloaded_and_highlighted.ps",true,true); return 0; }
- Step 5 calls
Fade_2D::load(filename,vZones)
to reload the whole triangulation plus the zones. The below three images show the triangulation and highlight the three zones as reloaded from the file “ex11_saveTriangulation.fade”: All triangles are contained because we created this file usingFade_2D::saveTriangulation()
.



- In contrast the sixth step loads a reduced triangulation from the file “ex11_saveZones.fade” that we created with
Fade_2D::saveZones()
: The file contains only the highlighted zone triangles (plus a few additional triangles to complete the convex hull)



- Finally Step 7 reloads only pDiffZone from the stringstream that we used together with Zone2::save()

Saved triangulations are always convex
A Delaunay triangulation is always convex and this property is also a technical requirement in Fade. In contrast the area that you save may have concave locations. In this case the saveZones()
command creates additional fill-triangles to complete the convex hull of the area to be saved, see the image below. These fill-triangles then belong to the triangulation, but not to any of the saved zones.

2 replies on “Saving and Loading a Triangulation – Ex. 11”
how could I construct a Fade_2D object by a list of points and indices ?
Well, you have a triangulation and you want to import it into a Fade_2D object? Then use importTriangles:
https://www.geom.at/fade25d/html/classGEOM__FADE25D_1_1Fade__2D.html#a97fc39010cbb1bd5ef55b003c3d9f1eb