00001 /* 00002 File: EPSPlot.cc 00003 00004 Function: Provides 2D plotter which outputs EPS files. 00005 00006 Author: Andrew Willmott 00007 00008 Notes: Some of this is originally from Paul Heckbert's libplo.a 00009 */ 00010 00011 #include "gcl/EPSPlot.h" 00012 #include "gcl/Geometry.h" 00013 #include <string.h> 00014 00015 // --- eps header ------------------------------------------------------------- 00016 00017 static Char header[] = 00018 "%%!PS-Adobe-3.0 EPSF-3.0\n" 00019 "%%%%BoundingBox: %d %d %d %d\n" 00020 "%%%%Title: %s\n" 00021 "%%%%Creator: PSPlot class\n"; 00022 00023 // --- little ps library ----------------------------------------------------- 00024 00025 static Char definitions[] = "\ 00026 /m {moveto} def\n\ 00027 /d {lineto} def\n\ 00028 /t {moveto show} def\n\ 00029 /p {stroke} def\n\ 00030 /dot {newpath 0 360 arc closepath fill} def\n\ 00031 /cir {newpath 0 360 arc closepath stroke} def\n\ 00032 \n\n"; 00033 00034 00035 // --- EPSPlot class ---------------------------------------------------------- 00036 00037 00038 EPSPlot::EPSPlot() : 00039 file(0), 00040 drawn(false), 00041 font("Helvetica"), 00042 width(1), 00043 scale(144), // default 2" x 2" 00044 level2(false) 00045 { 00046 } 00047 00048 Void EPSPlot::Open(const Char *filename) 00049 { 00050 if (strcmp(filename, ".") == 0) 00051 file = stdout; 00052 else if ((file = fopen(filename, "w")) == NULL) 00053 { 00054 fprintf(stderr, "(EPSPlot::Open) Can't write %s\n", filename); 00055 return; 00056 } 00057 00058 fprintf(file, header, 0, 0, (int) scale, (int) scale, "plot"); 00059 fputs(definitions, file); 00060 00061 if (level2) 00062 { 00063 // draw border 00064 fprintf(file, "0.1 setlinewidth\n"); 00065 fprintf(file, "%g %g %g %g rectstroke\n", 0.0, 0.0, scale, scale); 00066 00067 // make sure everything outside viewport is clipped. 00068 fprintf(file, "%g %g %g %g rectclip\n", 0.0, 0.0, scale, scale); 00069 } 00070 00071 // scale down so coord. sys. is [0,1]. 00072 00073 fprintf(file, "%g %g scale\n", scale, scale); 00074 } 00075 00076 Void EPSPlot::Close() 00077 { 00078 if (drawn) 00079 Stroke(); 00080 fprintf(file, "showpage\n"); 00081 fclose(file); 00082 } 00083 00084 // --- Drawing commands ------------------------------------------------------- 00085 00086 Void EPSPlot::MoveTo(GCLReal x, GCLReal y) 00087 { 00088 if (drawn) 00089 Stroke(); 00090 fprintf(file, "%.4g %.4g m\n", x, y); 00091 } 00092 00093 Void EPSPlot::LineTo(GCLReal x, GCLReal y) 00094 { 00095 drawn = 1; 00096 fprintf(file, "%.4g %.4g d\n", x, y); 00097 } 00098 00099 Void EPSPlot::Stroke() 00100 { 00101 fprintf(file, "p\n"); 00102 drawn = 0; 00103 } 00104 00105 Void EPSPlot::SetWidth(GCLReal width) 00106 { 00107 if (drawn) 00108 Stroke(); 00109 fprintf(file, "%g setlinewidth\n", width); 00110 } 00111 00112 Void EPSPlot::LineStyle(Int style) 00113 { 00114 if (drawn) 00115 Stroke(); 00116 switch (style) 00117 { 00118 case lineDashed: 00119 fprintf(file, "[.06 .04] 0 setdash\n"); 00120 break; 00121 case lineDotted: 00122 fprintf(file, "[.015 .03] 0 setdash\n"); 00123 break; 00124 default: 00125 fprintf(stderr, "(EPSPlot::LineStyle) don't know style %d\n", style); 00126 /* fall through */ 00127 case lineSolid: 00128 fprintf(file, "[] 0 setdash\n"); 00129 break; 00130 } 00131 } 00132 00133 Void EPSPlot::SetColour(const Colour &clr) 00134 { 00135 if (drawn) 00136 Stroke(); 00137 00138 if (level2) 00139 { 00140 fprintf(file, "%g %g %g setrgbcolor\n", 00141 Double(clr[0]), Double(clr[1]), Double(clr[2])); 00142 } 00143 else 00144 { 00145 Double level = dot(cRGBToLum, clr); 00146 fprintf(file, "%g setgray\n", level); 00147 } 00148 } 00149 00150 Void EPSPlot::Dot(GCLReal x, GCLReal y, GCLReal r) 00151 { 00152 if (drawn) 00153 Stroke(); 00154 fprintf(file, "%.4g %.4g %.4g dot\n", x, y, r); 00155 } 00156 00157 Void EPSPlot::Circle(GCLReal x, GCLReal y, GCLReal r) 00158 { 00159 if (drawn) 00160 Stroke(); 00161 fprintf(file, "%.4g %.4g %.4g cir\n", x, y, r); 00162 } 00163 00164 Void EPSPlot::DrawText(GCLReal x, GCLReal y, Char *string) 00165 { 00166 fprintf(file, "(%s) %.4g %.4g t\n", string, x, y); 00167 } 00168 00169 Void EPSPlot::SetOutputSize(GCLReal size) 00170 { 00171 scale = size; 00172 } 00173 00174 Void EPSPlot::SetPort(GCLReal left, GCLReal bottom, GCLReal right, GCLReal top, 00175 Bool centred) 00176 { 00177 Scale(1.0 / (right - left), 1.0 / (top - bottom)); 00178 if (centred) 00179 Translate((right - left) / 2.0, (top - bottom) / 2.0); 00180 else 00181 Translate(-left, -bottom); 00182 } 00183 00184 Void EPSPlot::Push() 00185 { 00186 if (drawn) 00187 Stroke(); 00188 fprintf(file, "gsave\n"); 00189 } 00190 00191 Void EPSPlot::Pop() 00192 { 00193 if (drawn) 00194 Stroke(); 00195 fprintf(file, "grestore\n"); 00196 } 00197 00198 Void EPSPlot::Translate(GCLReal tx, GCLReal ty) 00199 { 00200 fprintf(file, "%.4g %.4g translate\n", tx, ty); 00201 } 00202 00203 Void EPSPlot::Scale(GCLReal sx, GCLReal sy) 00204 { 00205 fprintf(file, "%.4g %.4g scale\n", sx, sy); 00206 } 00207 00208 Void EPSPlot::Rotate(GCLReal angle) 00209 { 00210 fprintf(file, "%.4g rotate\n", RadsToDegs(angle)); 00211 } 00212 00213 Void EPSPlot::Comment(StrConst string) 00214 { 00215 fprintf(file, "%% %s\n", string); 00216 } 00217 00218