// 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 #include #include #include #include #include #include #include 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) .v (vertex list) * (2) .plt (Gnuplot script), This script will read * .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 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 , to , * ... * * 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 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: * * * * ... * * @param g A boost::adjacency_list graph with Point_2 as the vertex property to be plotted * @return The vertex list string. */ template 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 struct Gnuplot_edges_2; // IMPLEMENTATIONS // exported functions template 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 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 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::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 struct Gnuplot_edges_2 { // 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 struct Gnuplot_edges_2 : public Gnuplot_edges_2 {}; // Undirected graphs /** Writing edge list to the gnuplot script for undirected graphs */ template struct Gnuplot_edges_2 { 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