00001
00006 #ifdef HAVE_CONFIG_H
00007 #include <tumble-conf.h>
00008 #endif
00009
00010 #include "epswrite.h"
00011
00012 #include "beziermesh.h"
00013 #include "boundarymesh.h"
00014
00015 #include <cstdio>
00016 #include <cstdlib>
00017 #include <iostream>
00018
00019 using namespace std;
00020
00021 #define INCH_TO_PT( inch ) (unsigned)(inch * 72.0 + 0.5)
00022
00023
00024 EPSWrite::EPSWrite(BezierMesh *_bezier_mesh, BoundaryMesh *_bdry_mesh )
00025 {
00026 if(!_bezier_mesh || !_bdry_mesh){
00027 cout<<"EPSWrite --- given bad mesh!"<<endl;
00028 return;
00029 }
00030
00031
00032 bdry_mesh = _bdry_mesh;
00033 bezier_mesh = _bezier_mesh;
00034
00035
00036 default_eps_rgb_map(rgb_map);
00037 default_eps_grayscale_map(grayscale_map);
00038
00039
00040
00041 Point2D top, bot;
00042 double height, width;
00043 bdry_mesh->bbox(top, bot);
00044 height = top.y() - bot.y();
00045 width = top.x() - bot.x();
00046
00047 top.coords[0] += width * 0.01;
00048 bot.coords[0] -= width * 0.01;
00049 top.coords[1] += height * 0.01;
00050 bot.coords[1] -= height * 0.01;
00051
00052 set_world_view(bot, top);
00053
00054
00055 set_page_dim(0,0,790,610,5);
00056 set_border_ink(1, 1.0);
00057 set_edge_ink(1, 1.0);
00058 set_bdry_draw(DRAW_OFF);
00059 set_face_draw(DRAW_OFF);
00060 }
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081 int EPSWrite::map_rgbcolor(int idx, const Color &color)
00082 {
00083 if( !color.is_valid() ) return -1;
00084 rgb_map[idx] = color;
00085 return 0;
00086 }
00087
00088 int EPSWrite::map_grayscale(int idx, float scale)
00089 {
00090 if( scale < 0.0 || scale > 1.0 ) return -1;
00091 grayscale_map[idx] = scale;
00092 return 0;
00093 }
00094
00095 int EPSWrite::set_border_draw(int mode)
00096 {
00097 if( (mode != DRAW_OFF) &&
00098 (mode != DRAW_GRAYSCALE) &&
00099 (mode != DRAW_RGB) ) return -1;
00100 border.mode = mode;
00101 return 0;
00102 }
00103
00104 int EPSWrite::set_border_ink(unsigned linewidth, float shade)
00105 {
00106 if(( shade < 0.0 ) || ( shade > 1.0)) return -1;
00107 border.mode = DRAW_GRAYSCALE;
00108 border.linewidth = linewidth;
00109 border.grayscale = shade;
00110 return 0;
00111 }
00112
00113 int EPSWrite::set_border_ink(unsigned linewidth, const Color &rgbcolor)
00114 {
00115 if( !rgbcolor.is_valid() ) return -1;
00116 border.mode = DRAW_RGB;
00117 border.linewidth = linewidth;
00118 border.rgbcolor = rgbcolor;
00119 return 0;
00120 }
00121
00122 int EPSWrite::set_bdry_draw(int mode)
00123 {
00124 if( (mode != DRAW_OFF) &&
00125 (mode != DRAW_GRAYSCALE) &&
00126 (mode != DRAW_RGB) ) return -1;
00127 bdry.mode = mode;
00128 return 0;
00129 }
00130
00131 int EPSWrite::set_bdry_ink(unsigned linewidth, float shade)
00132 {
00133 if(( shade < 0.0 ) || ( shade > 1.0)) return -1;
00134 bdry.mode = DRAW_GRAYSCALE;
00135 bdry.linewidth = linewidth;
00136 bdry.grayscale = shade;
00137 return 0;
00138 }
00139
00140 int EPSWrite::set_bdry_ink(unsigned linewidth, const Color &rgbcolor)
00141 {
00142 if( !rgbcolor.is_valid() ) return -1;
00143 bdry.mode = DRAW_RGB;
00144 bdry.linewidth = linewidth;
00145 bdry.rgbcolor = rgbcolor;
00146 return 0;
00147 }
00148
00149 int EPSWrite::set_edge_draw(int mode)
00150 {
00151 if( (mode != DRAW_OFF) &&
00152 (mode != DRAW_GRAYSCALE) &&
00153 (mode != DRAW_RGB) ) return -1;
00154 edges.mode = mode;
00155 return 0;
00156 }
00157
00158 int EPSWrite::set_edge_ink(unsigned linewidth, float shade)
00159 {
00160 if(( shade < 0.0 ) || ( shade > 1.0)) return -1;
00161 edges.mode = DRAW_GRAYSCALE;
00162 edges.linewidth = linewidth;
00163 edges.grayscale = shade;
00164 return 0;
00165 }
00166
00167 int EPSWrite::set_edge_ink(unsigned linewidth, const Color &rgbcolor)
00168 {
00169 if( !rgbcolor.is_valid() ) return -1;
00170 edges.mode = DRAW_RGB;
00171 edges.linewidth = linewidth;
00172 edges.rgbcolor = rgbcolor;
00173 return 0;
00174 }
00175
00176 int EPSWrite::set_face_draw(int mode)
00177 {
00178 if( (mode != DRAW_OFF) &&
00179 (mode != DRAW_GRAYSCALE) &&
00180 (mode != DRAW_RGB) ) return -1;
00181 shade_face_mode = mode;
00182 return 0;
00183 }
00184
00185 int EPSWrite::set_page_dim(unsigned xmin, unsigned ymin, unsigned xmax, unsigned ymax, unsigned margin)
00186 {
00187 if( ( xmin >= xmax ) || ( ymin >= ymax ) ) return -1;
00188 if( (2*margin >= xmax - xmin) || (2*margin >= ymax - ymin) ) return -1;
00189
00190 page_bot.x = xmin;
00191 page_bot.y = ymin;
00192 page_top.x = xmax;
00193 page_top.y = ymax;
00194 page_width = xmax - xmin;
00195 page_height = ymax - ymin;
00196 margin_width = margin;
00197
00198 canvas_bot.x = xmin + margin;
00199 canvas_bot.y = ymin + margin;
00200 canvas_top.x = xmax - margin;
00201 canvas_top.y = ymax - margin;
00202 canvas_width = canvas_top.x - canvas_bot.x;
00203 canvas_height = canvas_top.y - canvas_bot.y;
00204 project_to_canvas();
00205 return 0;
00206 }
00207
00208 int EPSWrite::set_page_dim_inch(float xmin, float ymin, float xmax, float ymax, float margin)
00209 {
00210 if( (xmin < 0.0) || (ymin < 0.0) ||(xmax < 0.0) || (ymax < 0.0) || (margin < 0.0) ) return -1;
00211 return set_page_dim(INCH_TO_PT(xmin), INCH_TO_PT(ymin), INCH_TO_PT(xmax), INCH_TO_PT(ymax), INCH_TO_PT(margin));
00212 }
00213
00214 int EPSWrite::set_world_view(const Point2D &bot, const Point2D &top)
00215 {
00216 if((bot.x() >= top.x()) || (bot.y() >= top.y())) return -1;
00217 world_bot = bot;
00218 world_top = top;
00219 world_width = world_top.x() - world_bot.x();
00220 world_height = world_top.y() - world_bot.y();
00221 project_to_canvas();
00222 return 0;
00223 }
00224
00225 void EPSWrite::project_to_canvas()
00226 {
00227 Point2D world_center;
00228 double world_ratio = world_width / world_height;
00229 double canvas_ratio = (double)canvas_width / (double)canvas_height;
00230 double ny, nx;
00231 world_center.coords[0] = world_bot.x() + world_width * 0.5;
00232 world_center.coords[1] = world_bot.y() + world_height * 0.5;
00233
00234
00235
00236 if(world_ratio > canvas_ratio){
00237 ny = world_width * (1.0 / canvas_ratio) * 0.5;
00238 view_top.assign(world_top.x(), world_center.y() + ny);
00239 view_bot.assign(world_bot.x(), world_center.y() - ny);
00240 }
00241 else{
00242 nx = world_height * canvas_ratio * 0.5;
00243 view_top.assign(world_center.x() + nx, world_top.y());
00244 view_bot.assign(world_center.x() - nx, world_bot.y());
00245 }
00246 view_width = view_top.x() - view_bot.x();
00247 view_height = view_top.y() - view_bot.y();
00248
00249 }
00250
00251 int EPSWrite::write(char *epsfilename)
00252 {
00253 if(!bdry_mesh || !bezier_mesh) return -1;
00254 if(!epsfilename) return -1;
00255
00256 epsfile = fopen( epsfilename, "w" );
00257 if(!epsfile) return -1;
00258
00259
00260 print_header();
00261 set_options();
00262 set_clip();
00263
00264 cout<<"World Top:"<<world_top<<" World Bot:"<<world_bot<<endl;
00265 cout<<"World Width:"<<world_width<<" World Height:"<<world_height<<endl;
00266 cout<<"Page Width:"<<page_width<< " Page Height:"<<page_height<<endl;
00267 cout<<"Canvas Width:"<<canvas_width<<" Canvas Height:"<<canvas_height<<endl;
00268
00269
00270 if(shade_face_mode != DRAW_OFF) draw_faces();
00271 if(edges.mode != DRAW_OFF) draw_edges();
00272 if(bdry.mode != DRAW_OFF) draw_bdry();
00273 if(border.mode != DRAW_OFF) draw_border();
00274
00275
00276 if( !fclose( epsfile ) ) return -1;
00277 return 0;
00278 }
00279
00280 void EPSWrite::draw_bdry()
00281 {
00282 set_ink(bdry);
00283 BezierMesh::Bezier_Edge_Hash_T::const_iterator i;
00284 for(i = bezier_mesh->get_edges_begin();
00285 i != bezier_mesh->get_edges_end(); ++i) {
00286 if( (*i)->is_boundary() ) draw_edge(*i);
00287 }
00288 }
00289
00290 void EPSWrite::draw_faces()
00291 {
00292 BezierMesh::Bezier_Face_Hash_T::const_iterator i;
00293 for(i = bezier_mesh->get_faces_begin();
00294 i != bezier_mesh->get_faces_end(); ++i) {
00295 shade_triangle(*i);
00296 }
00297 }
00298
00299 void EPSWrite::draw_edges()
00300 {
00301 set_ink(edges);
00302 BezierMesh::Bezier_Edge_Hash_T::const_iterator i;
00303 for(i = bezier_mesh->get_edges_begin();
00304 i != bezier_mesh->get_edges_end(); ++i) {
00305 draw_edge(*i);
00306 }
00307 }
00308
00309 PSCoord EPSWrite::convert_coords(const Point2D &p)
00310 {
00311 PSCoord q;
00312 q.x = canvas_bot.x + (unsigned)( ( (double)canvas_width * (p.x() - view_bot.x()) / view_width ) + 0.5);
00313 q.y = canvas_bot.y + (unsigned)( ( (double)canvas_height * (p.y() - view_bot.y()) / view_height ) + 0.5);
00314 return q;
00315 }
00316
00317 void EPSWrite::print_header()
00318 {
00319
00320 fprintf(epsfile,"%%!PS-Adobe-3.0 EPSF-3.0\n");
00321 fprintf(epsfile,"%%%%Pages: 0\n");
00322 fprintf(epsfile,"%%%%BoundingBox: %u %u %u %u\n", page_bot.x, page_bot.y, page_top.x, page_top.y);
00323 fprintf(epsfile,"%%%%Creator: TUMBLE\n");
00324 fprintf(epsfile,"%%%%EndComments\n");
00325 }
00326
00327 void EPSWrite::set_options()
00328 {
00329 fprintf(epsfile,"%% setting global options\n");
00330 fprintf(epsfile,"1 setlinecap\n");
00331 fprintf(epsfile,"1 setlinejoin\n\n");
00332 }
00333
00334 void EPSWrite::set_clip()
00335 {
00336 fprintf(epsfile,"%%clip the bounding box\n");
00337 fprintf(epsfile,"newpath\n");
00338 fprintf(epsfile,"%u %u moveto\n", canvas_bot.x, canvas_bot.y);
00339 fprintf(epsfile,"%u %u lineto\n", canvas_top.x, canvas_bot.y);
00340 fprintf(epsfile,"%u %u lineto\n", canvas_top.x, canvas_top.y);
00341 fprintf(epsfile,"%u %u lineto\n", canvas_bot.x, canvas_top.y);
00342 fprintf(epsfile,"closepath\n");
00343 fprintf(epsfile,"clip\n\n");
00344 }
00345
00346
00347 void EPSWrite::set_ink(const PSDrawMode &mode)
00348 {
00349 fprintf(epsfile,"%%set ink style\n");
00350 fprintf(epsfile,"%u setlinewidth\n",mode.linewidth);
00351 if(mode.mode == DRAW_GRAYSCALE) {
00352 fprintf(epsfile,"/DeviceGray setcolorspace\n");
00353 fprintf(epsfile,"%f setgray\n", mode.grayscale);
00354 }
00355 else if(mode.mode == DRAW_RGB) {
00356 fprintf(epsfile,"/DeviceRGB setcolorspace\n");
00357 fprintf(epsfile,"%f %f %f setrgbcolor\n", mode.rgbcolor.R(), mode.rgbcolor.G(), mode.rgbcolor.B());
00358 }
00359 }
00360
00361 void EPSWrite::draw_border()
00362 {
00363 unsigned a = (unsigned) ((double)border.linewidth / 2.0);
00364 set_ink(border);
00365 fprintf(epsfile,"%%draw the border\n");
00366 fprintf(epsfile,"newpath\n");
00367 fprintf(epsfile,"%u %u moveto\n", canvas_bot.x + a, canvas_bot.y + a);
00368 fprintf(epsfile,"%u %u lineto\n", canvas_top.x - a, canvas_bot.y + a);
00369 fprintf(epsfile,"%u %u lineto\n", canvas_top.x - a, canvas_top.y - a);
00370 fprintf(epsfile,"%u %u lineto\n", canvas_bot.x + a, canvas_top.y - a);
00371 fprintf(epsfile,"closepath\n");
00372 fprintf(epsfile,"stroke\n\n");
00373 }
00374
00375 void EPSWrite::draw_edge(BezierEdge *e)
00376 {
00377 PSCoord p0, p1, p2, p3;
00378
00379 p0 = convert_coords( e->get_cp(0) );
00380 p1 = convert_coords( e->get_cp(0) * 1.0/3.0 + e->get_cp(1) * 2.0/3.0);
00381 p2 = convert_coords( e->get_cp(2) * 1.0/3.0 + e->get_cp(1) * 2.0/3.0);
00382 p3 = convert_coords( e->get_cp(2) );
00383
00384 fprintf(epsfile,"%%draw edge\n");
00385 fprintf(epsfile,"newpath\n");
00386 fprintf(epsfile,"%u %u moveto\n",p0.x, p0.y);
00387 fprintf(epsfile,"%u %u %u %u %u %u curveto\n",p1.x, p1.y, p2.x, p2.y, p3.x, p3.y);
00388 fprintf(epsfile,"closepath\n");
00389 fprintf(epsfile,"stroke\n\n");
00390 }
00391
00392 void EPSWrite::shade_triangle(BezierTriangle *t)
00393 {
00394 PSDrawMode mode;
00395 PSCoord p0, p1, p2, p3;
00396 BezierEdge *e;
00397 BezierVertex *v, *vold;
00398 BezierTuple tup = bezier_mesh->get_tuple(t);
00399
00400 mode.mode = shade_face_mode;
00401 mode.linewidth = 1;
00402 mode.grayscale = grayscale_map[ t->get_color() ];
00403 mode.rgbcolor = rgb_map[ t->get_color() ];
00404 set_ink( mode );
00405
00406 fprintf(epsfile,"%%shade triangle\n");
00407 fprintf(epsfile,"newpath\n");
00408 p0 = convert_coords( tup.e->get_cp(0) );
00409 fprintf(epsfile,"%u %u moveto\n",p0.x, p0.y);
00410
00411 for(int i =0; i < 3; i++){
00412 e = tup.e;
00413 vold = tup.v;
00414 tup = bezier_mesh->Switch(0, tup);
00415 v = tup.v;
00416 p1 = convert_coords( vold->get_cp() * 1.0/3.0 + e->get_cp(1) * 2.0/3.0 );
00417 p2 = convert_coords( v->get_cp() * 1.0/3.0 + e->get_cp(1) * 2.0/3.0 );
00418 p3 = convert_coords( v->get_cp() );
00419
00420 fprintf(epsfile,"%u %u %u %u %u %u curveto\n", p1.x, p1.y, p2.x, p2.y, p3.x, p3.y);
00421 tup = bezier_mesh->Switch( 1, tup );
00422 }
00423 fprintf(epsfile,"closepath\n");
00424
00425
00426 if( edges.mode == DRAW_OFF ){
00427 fprintf(epsfile,"gsave\n");
00428 fprintf(epsfile,"stroke\n");
00429 fprintf(epsfile,"grestore\n");
00430 }
00431 fprintf(epsfile,"fill\n\n");
00432 }
00433
00434