Manually saving and loading a triangulation is challenging. This is especially true when there are millions of elements, and speed is crucial. For this reason, there are functions in Fade2D to assist you in saving and loading a triangulation, its zones and constraint edges. The included file “examples_2D/ex11_save_and_load.cpp” provides simple demo source code for this purpose. Let’s discuss it:
Saving a triangulation
The following C++ code first creates a triangulation with zones, and 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 zones,pEarthZone
,pMarsZone
andpDiffZone
. The code within this function is easy to understand, and you might want to review the previous examples, especially Polygon Clipping and Boolean Operations. - Step 2 invokes
Fade_2D::saveTriangulation()
to save the entire triangulation including the specified zones, to a binary file named “ex11_saveTriangulation.fade” - The third step involves a call to
Fade_2D::saveZones()
to save only the specified zones along with a few additional fill-triangles, as described in more detail below. It’s important to note that thesave...()
commands can accept both, filenames and objects of typestd::ostream
. In this case we use a file of typestd::ofstream
. - In Step 4, we save an individual zone. Although we could add the zone to a
vector<Zone2*>
and useFade_2D::saveZones()
, there is a shorter command available, namelyZone2::save()
. This time, we use astd::stringstream
as target.
Loading a Triangulation
Regardless of how a triangulation was saved, you can always employ the Fade_2D::load()
command for loading purposes. This command is capable of accepting either a filename or a std::istream, as demonstrated in 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 entire triangulation along with the zones. The three images below illustrate the triangulation and highlight the three reloaded zones from the file “ex11_saveTriangulation.fade”: All triangles are included because we generated this file usingFade_2D::saveTriangulation()
.
- In contrast, the sixth step loads a reduced triangulation from the file “ex11_saveZones.fade” which we created using
Fade_2D::saveZones()
: The file contains solely the highlighted zone triangles, along with a few additional triangles needed to complete the convex hull.
- Finally, in Step 7, we reload only pDiffZone from the std::stringstream that we used for Zone2::save()
Saved Triangulations are Always Convex
A Delaunay triangulation is inherently convex, and this property is also a fundamental technical requirement in Fade2D. However, the area you intend to save may contain concave regions. In such cases, the saveZones()
command generates supplementary fill triangles to complete the convex hull of the area to be saved, as depicted in the image below. It’s important to note that these fill triangles become part of the overall triangulation but do not belong to any of the saved zones.
2 replies on “Saving and Loading a Triangulation – Example 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