Categories
Fade2D Examples

Saving and Loading a Triangulation – Ex. 11

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);
}
  1. The above Step 1 calls the function createTestZones() to construct three demo-zones pEarthZone, pMarsZone and pDiffZone. The code in this function is easy to understand, you might review the previous examples, especially Polygon Clipping and Boolean Operations.
  2. 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”
  3. 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 the save...() commands accept both, filenames and objects of type std::ostream. This time we use a file of type std::ofstream.
  4. Step 4 saves an individual zone. Although we could push the zone into a vector<Zone2*> and use Fade_2D::saveZones() there is a shorter command, namely Zone2::save(). This time we a std::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;
}
  1. 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 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”
  1. 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)
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”
  1. Finally Step 7 reloads only pDiffZone from the stringstream that we used together with Zone2::save()
Only one reloaded zone
Reloaded “pDiffZone”

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.

Zone with additional triangles to complete the convex hull.
Zone plus additional triangles to complete its convex hull.

Leave a Reply

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