LCOV - code coverage report
Current view: top level - ugbase/lib_grid/file_io - file_io_tikz.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 97 0
Test Date: 2025-09-21 23:31:46 Functions: 0.0 % 4 0

            Line data    Source code
       1              : /*
       2              :  * Copyright (c) 2014-2015:  G-CSC, Goethe University Frankfurt
       3              :  * Author: Sebastian Reiter
       4              :  * 
       5              :  * This file is part of UG4.
       6              :  * 
       7              :  * UG4 is free software: you can redistribute it and/or modify it under the
       8              :  * terms of the GNU Lesser General Public License version 3 (as published by the
       9              :  * Free Software Foundation) with the following additional attribution
      10              :  * requirements (according to LGPL/GPL v3 §7):
      11              :  * 
      12              :  * (1) The following notice must be displayed in the Appropriate Legal Notices
      13              :  * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
      14              :  * 
      15              :  * (2) The following notice must be displayed at a prominent place in the
      16              :  * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
      17              :  * 
      18              :  * (3) The following bibliography is recommended for citation and must be
      19              :  * preserved in all covered files:
      20              :  * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
      21              :  *   parallel geometric multigrid solver on hierarchically distributed grids.
      22              :  *   Computing and visualization in science 16, 4 (2013), 151-164"
      23              :  * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
      24              :  *   flexible software system for simulating pde based models on high performance
      25              :  *   computers. Computing and visualization in science 16, 4 (2013), 165-179"
      26              :  * 
      27              :  * This program is distributed in the hope that it will be useful,
      28              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      29              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
      30              :  * GNU Lesser General Public License for more details.
      31              :  */
      32              : 
      33              : #include <algorithm>
      34              : #include <cmath>
      35              : #include <fstream>
      36              : #include <vector>
      37              : #include "file_io_tikz.h"
      38              : #include "common/util/string_util.h"
      39              : #include "lib_grid/algorithms/geom_obj_util/geom_obj_util.h"
      40              : #include "lib_grid/algorithms/bounding_box_util.h"
      41              : #include "lib_grid/iterators/lg_for_each.h"
      42              : 
      43              : using namespace std;
      44              : 
      45              : namespace ug{
      46              : 
      47            0 : TikzExportDesc::
      48            0 : TikzExportDesc() :
      49            0 :         vrtRadius(0.1),
      50            0 :         vrtRimWidth(0.02),
      51              :         vrtColor(0.65, 0.65, 0.65),
      52            0 :         edgeWidth(0.025),
      53              :         edgeColor(0, 0, 0),
      54            0 :         faceRimWidth(0.015),
      55              :         faceColor(0.85, 0.85, 0.85),
      56            0 :         smallestVal(0.001)
      57            0 : {}
      58              : 
      59            0 : static vector2 trunk(const vector2& v, number smallestVal)
      60              : {
      61              :         vector2 t;
      62            0 :         t.x() = smallestVal * round(v.x() / smallestVal);
      63            0 :         t.y() = smallestVal * round(v.y() / smallestVal);
      64            0 :         return t;
      65              : }
      66              : 
      67              : 
      68              : struct TIKZElem{
      69              :         GridObject* elem;
      70              :         float zmin;
      71              :         float zmax;
      72              :         int elemId;
      73              :         int subsetId;
      74              : 
      75              :         template <class vector_t>
      76            0 :         TIKZElem(GridObject* _e, int _si, const AABox<vector_t>& bbox) :
      77            0 :                 elem(_e),
      78            0 :                 elemId(_e->base_object_id()),
      79            0 :                 subsetId(_si)
      80              :                 {
      81              :                         if(vector_t::Size == 3){
      82            0 :                                 zmin = bbox.min[2];
      83            0 :                                 zmax = bbox.max[2];
      84              :                         }
      85              :                         else
      86              :                                 zmin = zmax = 0;
      87              :                 }
      88              : 
      89              : //      if x < y, x will be rendered before y
      90            0 :         bool operator <(const TIKZElem& e) const{
      91            0 :                 if(zmin - e.zmin > SMALL)                    return false;
      92            0 :                 else if(e.zmin - zmin > SMALL)       return true;
      93              :                 
      94            0 :                 if(e.elemId > elemId)                return false;
      95            0 :                 else if(e.elemId < elemId)   return true;
      96              : 
      97            0 :                 if(zmax - e.zmax > SMALL)                    return false;
      98            0 :                 else if(e.zmax - zmax > SMALL)       return true;
      99              : 
     100            0 :                 if(e.subsetId < subsetId)            return false;
     101            0 :                 else if(e.subsetId > subsetId)       return true;
     102              : 
     103              :                 return false;   
     104              :         }
     105              : };
     106              : 
     107              : 
     108              : 
     109            0 : bool ExportGridToTIKZ(Grid& grid, const char* filename, const ISubsetHandler* psh,
     110              :                                           APosition aPos, TikzExportDesc desc)  
     111              : {
     112            0 :         UG_COND_THROW(!psh, "A subset handler is required to write a tikz file!\n");
     113              : 
     114            0 :         ofstream out(filename);
     115            0 :         UG_COND_THROW(!out, "Couldn't load file " << filename << "\n");
     116              : 
     117              : 
     118              :         vector<string>    subsetIdentifyer;
     119              :         vector<bool>      subsetNameIsDuplicate;
     120            0 :         for(int si = 0; si < psh->num_subsets(); ++si){
     121            0 :                 string sname = psh->get_subset_name(si);
     122            0 :                 for(size_t i = 0; i < sname.size(); ++i){
     123            0 :                         char c = sname[i];
     124            0 :                         if(!(isalnum(c) || c == '_'))
     125            0 :                                 sname[i] = '_';
     126              :                 }
     127              : 
     128              :         //      check if the string is already contained in subsetIdentifyers and mark it
     129              :         //      as a duplicate if that's the case
     130              :                 bool isDuplicate = false;
     131            0 :                 for(size_t i = 0; i < subsetIdentifyer.size(); ++i){
     132            0 :                         if(subsetIdentifyer[i] == sname){
     133              :                                 isDuplicate = true;
     134              :                                 break;
     135              :                         }
     136              :                 }
     137            0 :                 subsetIdentifyer.push_back(sname);
     138            0 :                 subsetNameIsDuplicate.push_back(isDuplicate);
     139              :         }
     140              : 
     141            0 :         number sml = max(SMALL, desc.smallestVal);
     142              : 
     143              :         Grid::VertexAttachmentAccessor<APosition> aaPos(grid, aPos);
     144              : 
     145              :         out << "% This tex-file was exported from ProMesh (www.promesh3d.com)" << endl << endl;
     146              :         out << "% Call 'pdflatex' with this script to generate a .pdf file from it." << endl << endl;
     147              :         out << "% By placing a file 'custom_promesh_style.tex' in the same folder as this" << endl;
     148              :         out << "% script, you may override all local style definitions with custom definitions." << endl << endl;
     149              : 
     150              :         out << "\\documentclass[tikz]{standalone}" << endl;
     151              :         out << "\\begin{document}" << endl;
     152              :         out << "\\begin{tikzpicture}" << endl;
     153              : 
     154              :         out << endl;
     155            0 :         out << "\\definecolor{vertexColor}{rgb}{" << desc.vrtColor.x() << ", "
     156            0 :                 << desc.vrtColor.y() << ", " << desc.vrtColor.z() << "}" << endl;
     157            0 :         out << "\\definecolor{edgeColor}{rgb}{" << desc.edgeColor.x() << ", "
     158            0 :                 << desc.edgeColor.y() << ", " << desc.edgeColor.z() << "}" << endl;
     159            0 :         out << "\\definecolor{faceColor}{rgb}{" << desc.faceColor.x() << ", "
     160            0 :                 << desc.faceColor.y() << ", " << desc.faceColor.z() << "}" << endl;
     161              :         out << endl;
     162              : 
     163            0 :         out << "\\tikzset{vertexBase/.style={circle,draw=black,fill=vertexColor,line width=" << desc.vrtRimWidth << "cm,\n"
     164            0 :                 << "                        inner sep=0,minimum size=" << desc.vrtRadius << "cm}}\n";
     165            0 :         out << "\\tikzset{edgeBase/.style={draw=edgeColor, line width=" << desc.edgeWidth << "cm}}\n";
     166            0 :         out << "\\tikzset{faceBase/.style={draw=black, fill=faceColor, line width=" << desc.faceRimWidth <<"cm}}\n";
     167              :         
     168              :         out << endl;
     169              : 
     170            0 :         for(int si = 0; si < psh->num_subsets(); ++si){
     171            0 :                 if(!subsetNameIsDuplicate[si]){
     172            0 :                         const std::string& subsetName = subsetIdentifyer[si];
     173              :                         out << "% '" << subsetName << "' subset styles" <<endl;
     174            0 :                         out << "\\tikzset{vertex_" << subsetName << "/.style={vertexBase}}\n";
     175            0 :                         out << "\\tikzset{edge_" << subsetName << "/.style={edgeBase}}\n";
     176            0 :                         out << "\\tikzset{face_" << subsetName << "/.style={faceBase}}\n";
     177              :                 }
     178              :         }
     179              :         
     180              :         out << endl;
     181              :         out << "\\InputIfFileExists{./custom_promesh_style.tex}{}{}" << endl;
     182              :         out << endl;
     183              : 
     184              : 
     185              : //      create a vector which contains all objects that shall be rendered and sort it
     186              :         vector<TIKZElem>  elems;
     187            0 :         lg_for_each(Vertex, v, grid){
     188            0 :                 if(psh->get_subset_index(v) != -1)
     189            0 :                         elems.push_back(TIKZElem(v, psh->get_subset_index(v),
     190              :                                                                          CalculateBoundingBox(v, aaPos)));
     191              :         }lg_end_for;
     192              : 
     193            0 :         lg_for_each(Edge, e, grid){
     194            0 :                 if(psh->get_subset_index(e) != -1)
     195            0 :                         elems.push_back(TIKZElem(e, psh->get_subset_index(e),
     196            0 :                                                                          CalculateBoundingBox(e, aaPos)));
     197              :         }lg_end_for;
     198              : 
     199            0 :         lg_for_each(Face, f, grid){
     200            0 :                 if(psh->get_subset_index(f) != -1)
     201            0 :                         elems.push_back(TIKZElem(f, psh->get_subset_index(f),
     202            0 :                                                                          CalculateBoundingBox(f, aaPos)));
     203              :         }lg_end_for;
     204              : 
     205            0 :         sort(elems.begin(), elems.end());
     206              : 
     207              :         out << "\\begin{scope}" << endl;
     208            0 :         for_each_in_vec(TIKZElem& tikzElem, elems){
     209            0 :                 const std::string& subsetName = subsetIdentifyer[tikzElem.subsetId];
     210            0 :                 switch(tikzElem.elemId){
     211            0 :                         case VERTEX:{
     212            0 :                                 Vertex* vrt = static_cast<Vertex*>(tikzElem.elem);
     213            0 :                                 vector2 p = trunk(vector2(aaPos[vrt].x(), aaPos[vrt].y()), sml);
     214            0 :                                 out << "\\node[vertex_" << subsetName << "] at (" << p.x() << "cm, " << p.y() << "cm) {};" << endl;
     215            0 :                         }break;
     216              : 
     217            0 :                         case EDGE:{
     218            0 :                                 Edge* e = static_cast<Edge*>(tikzElem.elem);
     219            0 :                                 out << "\\draw[edge_" << subsetName << "]";
     220            0 :                                 for(size_t i = 0; i < e->num_vertices(); ++i){
     221            0 :                                         Vertex* vrt = e->vertex(i);
     222            0 :                                         vector2 p = trunk(vector2(aaPos[vrt].x(), aaPos[vrt].y()), sml);
     223            0 :                                         out << " (" << p.x() << "cm, " << p.y() << "cm)";
     224            0 :                                         if(i+1 != e->num_vertices())
     225            0 :                                                 out << " --";
     226              :                                 }
     227              :                                 out << ";" << endl;
     228              :                         }break;
     229              : 
     230            0 :                         case FACE:{
     231            0 :                                 Face* f = static_cast<Face*>(tikzElem.elem);
     232            0 :                                 out << "\\filldraw[face_" << subsetName << "]";
     233            0 :                                 for(size_t i = 0; i < f->num_vertices(); ++i){
     234            0 :                                         Vertex* vrt = f->vertex(i);
     235            0 :                                         vector2 p = trunk(vector2(aaPos[vrt].x(), aaPos[vrt].y()), sml);
     236            0 :                                         out << " (" << p.x() << "cm, " << p.y() << "cm) --";
     237              :                                 }
     238              :                                 out << " cycle;" << endl;
     239              :                         }break;
     240              : 
     241              :                 }
     242              : 
     243              :         }end_for;
     244              :         
     245              : 
     246              :         // for(int si = 0; si < psh->num_subsets(); ++si){
     247              :         // //   draw all faces which are in a subset
     248              :         //      for(FaceIterator iter = grid.begin<Face>();
     249              :         //              iter != grid.end<Face>(); ++iter)
     250              :         //      {
     251              :         //              Face* f = *iter;
     252              :         //              if(psh->get_subset_index(f) != si)   // THIS IS NASTY! One should iterate over subset-elements directly instead
     253              :         //                      continue;
     254              :         //              out << "\\filldraw[face" << si << "]";
     255              :         //              for(size_t i = 0; i < f->num_vertices(); ++i){
     256              :         //                      Vertex* vrt = f->vertex(i);
     257              :         //                      vector2 p = trunk(vector2(aaPos[vrt].x(), aaPos[vrt].y()), sml);
     258              :         //                      out << " (" << p.x() << "cm, " << p.y() << "cm) --";
     259              :         //              }
     260              :         //              out << " cycle;" << endl;
     261              :         //      }
     262              :         // }
     263              : 
     264              :         // for(int si = 0; si < psh->num_subsets(); ++si){
     265              :         // //   draw all edges which are in a subset
     266              :         //      for(EdgeIterator iter = grid.begin<Edge>();
     267              :         //              iter != grid.end<Edge>(); ++iter)
     268              :         //      {
     269              :         //              Edge* e = *iter;
     270              :         //              if(psh->get_subset_index(e) != si)   // THIS IS NASTY! One should iterate over subset-elements directly instead
     271              :         //                      continue;
     272              :         //              out << "\\draw[edge" << si << "]";
     273              :         //              for(size_t i = 0; i < e->num_vertices(); ++i){
     274              :         //                      Vertex* vrt = e->vertex(i);
     275              :         //                      vector2 p = trunk(vector2(aaPos[vrt].x(), aaPos[vrt].y()), sml);
     276              :         //                      out << " (" << p.x() << "cm, " << p.y() << "cm)";
     277              :         //                      if(i+1 != e->num_vertices())
     278              :         //                              out << " --";
     279              :         //              }
     280              :         //              out << ";" << endl;
     281              :         //      }
     282              :         // }
     283              : 
     284              :         // for(int si = 0; si < psh->num_subsets(); ++si){
     285              :         // //   draw all nodes which are in a subset
     286              :         //      for(VertexIterator iter = grid.begin<Vertex>();
     287              :         //              iter != grid.end<Vertex>(); ++iter)
     288              :         //      {
     289              :         //              Vertex* vrt = *iter;
     290              :         //              if(psh->get_subset_index(vrt) != si) // THIS IS NASTY! One should iterate over subset-elements directly instead
     291              :         //                      continue;
     292              :         //              vector2 p = trunk(vector2(aaPos[vrt].x(), aaPos[vrt].y()), sml);
     293              :         //              out << "\\node[vertex" << si << "] at (" << p.x() << "cm, " << p.y() << "cm) {};" << endl;
     294              :         //      }
     295              :         // }
     296              :         out << "\\end{scope}" << endl;
     297              : 
     298              :         out << "\\end{tikzpicture}" << endl;
     299              :         out << "\\end{document}" << endl;
     300              : 
     301            0 :         out.close();
     302            0 :         return true;
     303            0 : }
     304              : 
     305              : }//     end of namespace
        

Generated by: LCOV version 2.0-1