cgal/Cone_spanners_2/include/CGAL/Gnuplot_output_2.h

244 lines
7.5 KiB
C++

// Copyright (c) 2013-2014 The University of Western Sydney, Australia.
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
// You can redistribute it and/or modify it under the terms of the GNU
// General Public License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
//
//
// Author(s) : Quincy Tse, Weisheng Si
/** @file gnuplot_output_2.h
*
* This header implements the function that can generate data and script files for plotting
* graphs by Gnuplot. This function requires that graphs be represented by boost::adjacency_list
* with vertex property Point_2.
*/
#ifndef GNUPLOT_OUTPUT_2_H
#define GNUPLOT_OUTPUT_2_H
#include <CGAL/Cone_spanners_2/_cxx0x_hack.h>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <stdexcept>
#include <boost/config.hpp>
#include <boost/graph/adjacency_list.hpp>
namespace CGAL {
// Declarations go first, then implementations follow.
/**
* @brief Output a set of files that plots %g using Gnuplot.
* Compiles a set of data and script files that plot %g using Gnuplot.
*
* The files that are generated are:
* (1) <prefix>.v (vertex list)
* (2) <prefix>.plt (Gnuplot script), This script will read
* <prefix>.v as input to plot the vertex list. The edge list is also
* included in this script.
*
* Notes:
* (1) If these files already exists, this function will overwrite these
* files.
* (2) Parallel and self-edges cannot be plotted.
*
* @param g A boost::adjacency_list graph with Point_2 as the vertex property to be plotted
* @param prefix The prefix of the output files
* @return The Gnuplot script.
*/
template <typename Graph>
void gnuplot_output_2 (const Graph& g, const std::string& prefix);
/**
* @brief Compiles a multi-lined %string to draw the edges in %g by Gnuplot.
* Compiles an edge list of %g in the following format:
*
* set arrow from <start x>, <start y> to <end x>, <end y>
* ...
*
* NOTE: For undirected graphs, use "set style arrow nohead"; for directed graphs,
* use "set style arrow head"
*
* @param g A boost::adjacency_list graph with Point_2 as the vertex property to be plotted
* @return The edge list string.
*/
template <typename Graph> std::string gnuplot_edge_list (const Graph& g);
/**
* @brief Compiles a multi-lined %string representing the vertices in %g.
* Compiles a vertex list of %g in the following format:
*
* <x> <y>
* <x> <y>
* ...
*
* @param g A boost::adjacency_list graph with Point_2 as the vertex property to be plotted
* @return The vertex list string.
*/
template <typename Graph> std::string gnuplot_vertex_list (const Graph& g);
/** This struct is defined to use partial specialization to generate arrow styles differently for
* directed and undirected graphs.
* Note: Need to use structs because C++ before 11 doesn't allow partial specialisation
* for functions
*/
template <typename Graph, typename Directedness=typename Graph::directed_selector>
struct Gnuplot_edges_2;
// IMPLEMENTATIONS
// exported functions
template <typename Graph>
std::string gnuplot_edge_list (const Graph& g)
{
std::stringstream ss;
ss.precision(3);
ss << std::fixed; // Use fixed floating-point notation
typename Graph::edge_iterator eit, ee;
for (boost::tie(eit, ee) = boost::edges(g); eit != ee; ++eit) {
typename Graph::vertex_descriptor src = boost::source(*eit, g);
typename Graph::vertex_descriptor end = boost::target(*eit, g);
ss << "set arrow from ";
ss << to_double(g[src].x()) << "," << to_double(g[src].y());
ss << " to ";
ss << to_double(g[end].x()) << "," << to_double(g[end].y());
ss << " as 1" << std::endl;
}
return ss.str();
}
// Common regardless of whether g is directed.
template <typename Graph>
std::string gnuplot_vertex_list(const Graph& g) {
std::stringstream ss;
ss.precision(3);
ss << std::fixed;
typename Graph::vertex_iterator vit, ve;
for (boost::tie(vit, ve) = boost::vertices(g); vit != ve; ++vit) {
ss << to_double(g[*vit].x()) << " " << to_double(g[*vit].y()) << std::endl;
}
return ss.str();
}
template <typename Graph>
void gnuplot_output_2 (const Graph& g, const std::string& prefix)
{
// Generate the vertex list to the .v file
std::ofstream fs((prefix + ".v").c_str(),
std::ofstream::out | std::ofstream::trunc);
fs << gnuplot_vertex_list(g);
fs.close();
std::cout << prefix << ".v" << " is generated. " << std::endl;
// Generate the Gnuplot Script to the .plt file
fs.open((prefix + ".plt").c_str(),
std::ofstream::out | std::ofstream::trunc);
fs << "set term ";
// Choose one:
fs << "wxt ";
// fs << "postscript eps ";
fs << "font \", 9\" enhanced" << std::endl;
// Uncomment if eps:
// fs << "set output \"" << prefix << ".eps\"" << std::endl;
fs << "set title" << std::endl;
fs << "set xlabel # when no options, clear the xlabel" << std::endl;
fs << "set ylabel" << std::endl;
fs << "unset key" << std::endl;
fs << "set size square" << std::endl;
fs << "unset xtics" << std::endl;
fs << "unset ytics" << std::endl;
fs << "unset border" << std::endl;
/*
ss << "set xtics" << std::endl;
ss << "set ytics" << std::endl;
ss << "set border" << std::endl;
ss << "set grid xtics ytics" << std::endl;
*/
fs << std::endl;
// Specific part that depends on whether g is directed
fs << Gnuplot_edges_2<Graph>::gnuplot_edge_script(g);
fs << std::endl;
// plot the vertices
fs << "plot \"" << prefix << ".v\" with points pt 7 ps 0.8 lt rgb \"blue\"" << std::endl;
// Uncomment if wxt and also want eps output:
// fs << "set term postscript eps " << std::endl;
// fs << "set output \"" << prefix << ".eps\"" << std::endl;
// fs << "replot" << std::endl;
fs.close();
std::cout << prefix << ".plt" << " is generated. " << std::endl;
}
// directed graphs
/** Writing edge list to the gnuplot script for directed graphs */
template <typename Graph>
struct Gnuplot_edges_2<Graph, boost::directedS> {
// Uses "set style arrow 1 head" to draw directed edges
// Edges are written directly into the script file.
static std::string gnuplot_edge_script(const Graph& g)
{
std::stringstream ss;
ss << "set style arrow 1 head filled lc rgb \"black\"" << std::endl;
ss << std::endl;
ss << "# edges" << std::endl;
ss << gnuplot_edge_list(g);
ss << "# end of edges" << std::endl;
return ss.str();
}
};
// Bidirectional graph, the same as the directed graph.
/** Writing edge list to the gnuplot script for bidirectional graphs */
template <typename Graph>
struct Gnuplot_edges_2<Graph, boost::bidirectionalS> : public Gnuplot_edges_2<Graph, boost::directedS> {};
// Undirected graphs
/** Writing edge list to the gnuplot script for undirected graphs */
template <typename Graph>
struct Gnuplot_edges_2<Graph, boost::undirectedS> {
static std::string gnuplot_edge_script(const Graph& g)
{
std::stringstream ss;
ss << "set style arrow 1 nohead lc rgb \"black\"" << std::endl;
ss << std::endl;
ss << "# edges" << std::endl;
ss << gnuplot_edge_list(g);
ss << "# end of edges" << std::endl;
return ss.str();
}
};
} // namespace CGAL
#endif