Categories
2D Delaunay Triangulation Examples in C++

Saving and Loading a Triangulation – Example 11

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 and pDiffZone. 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 the save...() commands can accept both, filenames and objects of type std::ostream. In this case we use a file of type std::ofstream.
  • In Step 4, we save an individual zone. Although we could add the zone to a vector<Zone2*> and use Fade_2D::saveZones(), there is a shorter command available, namely Zone2::save(). This time, we use a std::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 using Fade_2D::saveTriangulation().
Zone 3 "pEarthZone" reloaded from file "ex11_saveTriangulation.fade"
Reloaded Zone0 “pEarthZone”
Zone 1 "pMarsZone" reloaded from file "ex11_saveTriangulation.fade"
Reloaded Zone1 “pMarsZone”
Zone 2 "pDiffZone" reloaded from file "ex11_saveTriangulation.fade"
Reloaded Zone2 “pDiffZone”
  • 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.
Zone0 "pEarthZone" reloaded from file "ex11_saveZones.fade"
Reloaded Zone0 “pEarthZone”
Zone1 "pMarsZone" reloaded from file "ex11_saveZones.fade"
Reloaded Zone1 “pMarsZone”
Zone2 "pDiffZone" reloaded from file "ex11_saveZones.fade"
Reloaded Zone2 “pDiffZone”
  • Finally, in Step 7, we reload only pDiffZone from the std::stringstream that we used for Zone2::save()
Only one reloaded zone
Reloaded “pDiffZone”

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.

Zone with additional triangles to complete the convex hull.
Zone with Additional Triangles to Complete its Convex Hull

2 replies on “Saving and Loading a Triangulation – Example 11”

Leave a Reply

Your email address will not be published. Required fields are marked *