1 /* 2 * eepic.cc -- ePiX's eepic output format 3 * 4 * This file is part of ePiX, a C++ library for creating high-quality 5 * figures in LaTeX 6 * 7 * Version 1.2.0-2 8 * Last Change: September 26, 2007 9 */ 10 11 /* 12 * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007 13 * Andrew D. Hwang <rot 13 nujnat at zngupf dot ubylpebff dot rqh> 14 * Department of Mathematics and Computer Science 15 * College of the Holy Cross 16 * Worcester, MA, 01610-2395, USA 17 */ 18 19 /* 20 * ePiX is free software; you can redistribute it and/or modify it 21 * under the terms of the GNU General Public License as published by 22 * the Free Software Foundation; either version 2 of the License, or 23 * (at your option) any later version. 24 * 25 * ePiX is distributed in the hope that it will be useful, but WITHOUT 26 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 27 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 28 * License for more details. 29 * 30 * You should have received a copy of the GNU General Public License 31 * along with ePiX; if not, write to the Free Software Foundation, Inc., 32 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 33 */ 34 #include <cmath> 35 #include <list> 36 37 #include <string> 38 #include <sstream> 39 40 #include <set> // for palette 41 42 #include "constants.h" 43 44 #include "functions.h" 45 46 #include "pairs.h" 47 #include "edge_data.h" 48 49 #include "Color.h" 50 51 #include "path_style.h" 52 #include "pen_data.h" 53 54 #include "hatching.h" 55 56 #include "format.h" 57 #include "eepic.h" 58 59 namespace ePiX { 60 61 // rotate successive hatches this much to avoid parallelity 62 const double d_hatch_theta(111.24612); // ~90*(sqrt(5)-1) 63 eepic()64 eepic::eepic() 65 : m_ink(Black()), m_nib(PLAIN_WIDTH), m_hatch(0) { } 66 clone() const67 eepic* eepic::clone() const 68 { 69 return new eepic(*this); 70 } 71 72 // Filled region with specified Cartesian edges, offset, and color print_fill(const std::list<edge2d> & edges,const pair & offset,const Color & fc,const pen_data & line,const std::string & len) const73 std::string eepic::print_fill(const std::list<edge2d>& edges, 74 const pair& offset, 75 const Color& fc, 76 const pen_data& line, 77 const std::string& len) const 78 { 79 std::stringstream obuf; 80 81 // set angle 82 const double hatch_angle(m_hatch); 83 m_hatch += d_hatch_theta; 84 85 // draw hatch lines separated by pen.width(), actual line width 86 // scaled by density 87 double dens(fc.alpha()); // transparency 88 if (dens < EPIX_EPSILON) 89 return ""; 90 91 // else 92 length hatch_width(length(PLAIN_WIDTH).to(len)); 93 94 path_state style; // solid 95 96 if (EPIX_EPSILON < dens*hatch_width.magnitude()) 97 { 98 // Use fill color, draw thin lines to simulate transparency. 99 // Area covered by double-hatching is (supposed to be) dens. 100 pen_data fill_pen(fc, (1-sqrt(1-dens))*hatch_width); 101 102 // draw hatch-filled edges 103 hatch_data bd1(hatch_angle, hatch_width.magnitude(), edges); 104 for (unsigned int i=0; i < bd1.data().size(); ++i) 105 obuf << format::print_line(bd1.data().at(i), offset, 106 fill_pen, style, std::string(""), len); 107 108 // re-draw hatch lines at right angles... 109 hatch_data bd2(hatch_angle+90, hatch_width.magnitude(), edges); 110 for (unsigned int i=0; i < bd2.data().size(); ++i) 111 obuf << format::print_line(bd2.data().at(i), offset, 112 fill_pen, style, "", len); 113 } 114 115 obuf << set_pen_state(line); 116 obuf << print_paths(edges, offset, "", len); 117 118 return obuf.str(); 119 } // end of eepic::print_fill() 120 121 122 // may assume line is visible print_line(const std::list<edge2d> & edges,const pair & offset,const pen_data & line,const pen_data & base,const path_state & style,const std::string & len) const123 std::string eepic::print_line(const std::list<edge2d>& edges, 124 const pair& offset, 125 const pen_data& line, 126 const pen_data& base, 127 const path_state& style, 128 const std::string& len) const 129 { 130 std::string value; 131 132 // draw *solid* base first if necessary 133 if (line.width() < base.width() && !base.color().is_unset()) 134 value += format::print_line(edges, offset, base, path_state(), "", len); 135 136 return value += format::print_line(edges, offset, line, style, "", len); 137 } 138 139 print_color(const std::string & model,const std::string & name,double d1,double d2,double d3) const140 std::string eepic::print_color(const std::string& model, 141 const std::string& name, 142 double d1, double d2, double d3) const 143 { 144 return format::xdefinecolor(model, name, d1, d2, d3); 145 } 146 print_color(const std::string & model,const std::string & name,double d1,double d2,double d3,double d4) const147 std::string eepic::print_color(const std::string& model, 148 const std::string& name, 149 double d1, double d2, 150 double d3, double d4) const 151 { 152 return format::xdefinecolor(model, name, d1, d2, d3, d4); 153 } 154 155 // one-line comment print_comment(const std::string & msg) const156 std::string eepic::print_comment(const std::string& msg) const 157 { 158 std::stringstream obuf; 159 obuf << "%% " << msg << std::endl; 160 161 return obuf.str(); 162 } 163 164 // verbatim string, newline protected print_verbatim(const std::string & msg) const165 std::string eepic::print_verbatim(const std::string& msg) const 166 { 167 std::stringstream obuf; 168 obuf << msg << "%" << std::endl; 169 170 return obuf.str(); 171 } 172 reset_state() const173 void eepic::reset_state() const 174 { 175 m_ink = Neutral(); 176 m_nib = length(0); 177 } 178 179 180 //// private member functions //// start_picture(const pair & sz,const pair & offset) const181 std::string eepic::start_picture(const pair& sz, const pair& offset) const 182 { 183 std::stringstream obuf; 184 obuf << "\\begin{picture}" 185 << format::print(sz) << format::print(-offset) << "%" << std::endl; 186 187 return obuf.str(); 188 } 189 end_picture() const190 std::string eepic::end_picture() const 191 { 192 std::stringstream obuf; 193 obuf << "\\end{picture}%" << std::endl; 194 return obuf.str(); 195 } 196 set_unitlength(const std::string & len) const197 std::string eepic::set_unitlength(const std::string& len) const 198 { 199 std::stringstream obuf; 200 201 obuf << "\\setlength{\\unitlength}{1" << len << "}%" << std::endl; 202 203 return obuf.str(); 204 } 205 206 usepackages() const207 std::string eepic::usepackages() const 208 { 209 return "usepackages epic,eepic,xcolor"; 210 } 211 212 // string argument for passing attributes local to this path/loop start_open_path(const std::string & attribs) const213 std::string eepic::start_open_path(const std::string& attribs) const 214 { 215 return "\\path"; 216 } 217 end_open_path(const std::string & attribs) const218 std::string eepic::end_open_path(const std::string& attribs) const 219 { 220 std::stringstream obuf; 221 obuf << std::endl; 222 return obuf.str(); 223 } 224 start_closed_path(const std::string & attribs) const225 std::string eepic::start_closed_path(const std::string& attribs) const 226 { 227 return "\\path"; 228 } 229 end_closed_path(const std::string & attribs) const230 std::string eepic::end_closed_path(const std::string& attribs) const 231 { 232 std::stringstream obuf; 233 obuf << std::endl; 234 return obuf.str(); 235 } 236 set_fill_state(const Color & col) const237 std::string eepic::set_fill_state(const Color& col) const // unused 238 { 239 std::stringstream obuf; 240 241 if (m_ink != col) 242 { 243 m_ink = col; 244 obuf << "\\color{" << m_ink.name() << "}%" << std::endl; 245 } 246 247 return obuf.str(); 248 } 249 set_pen_state(const pen_data & pen) const250 std::string eepic::set_pen_state(const pen_data& pen) const 251 { 252 std::stringstream obuf; 253 254 if (m_nib != pen.width()) 255 { 256 m_nib = pen.width(); 257 obuf << "\\allinethickness{" << m_nib.name() << "}%" << std::endl; 258 } 259 260 if (m_ink != pen.color()) 261 { 262 m_ink = pen.color(); 263 obuf << "\\color{" << m_ink.name() << "}%" << std::endl; 264 } 265 266 return obuf.str(); 267 } 268 269 // place a LaTeX box of width zero (containing string) at location (pair) put_box(const pair & loc,const std::string & msg) const270 std::string eepic::put_box(const pair& loc, const std::string& msg) const 271 { 272 std::stringstream obuf; 273 obuf << "\\put" << print(loc) << "{" << msg << "}" << std::endl; 274 275 return obuf.str(); 276 } 277 print_circle_marker(const pair & here,double diam,bool fill,const Color & color,const std::string & len) const278 std::string eepic::print_circle_marker(const pair& here, double diam, 279 bool fill, const Color& color, 280 const std::string& len) const 281 { 282 std::stringstream obuf; 283 obuf << "\\put" << print(here) 284 << "{\\color{" << print(color) << "}$"; 285 286 if (fill) 287 obuf << "\\allinethickness{" << 0.5*diam << len << "}" 288 << "\\circle{" << 0.5*diam << "}"; 289 290 else 291 obuf << "\\circle{" << diam << "}"; 292 293 obuf << "$}%" << std::endl; 294 295 return obuf.str(); 296 } 297 } // end of namespace 298