diff options
Diffstat (limited to 'graphics/epix/markers.cc')
-rw-r--r-- | graphics/epix/markers.cc | 308 |
1 files changed, 308 insertions, 0 deletions
diff --git a/graphics/epix/markers.cc b/graphics/epix/markers.cc new file mode 100644 index 0000000000..ac418f8e1f --- /dev/null +++ b/graphics/epix/markers.cc @@ -0,0 +1,308 @@ +/* + * markers.cc -- ePiX axes, grids, markers, and labels + * + * This file is part of ePiX, a C++ library for creating high-quality + * figures in LaTeX + * + * Version 1.1.19 + * Last Change: September 17, 2007 + */ + +/* + * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007 + * Andrew D. Hwang <rot 13 nujnat at zngupf dot ubylpebff dot rqh> + * Department of Mathematics and Computer Science + * College of the Holy Cross + * Worcester, MA, 01610-2395, USA + */ + +/* + * ePiX is free software; 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 2 of the License, or + * (at your option) any later version. + * + * ePiX is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ePiX; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "constants.h" + +#include "triples.h" +#include "length.h" + +#include "functions.h" + +#include "path.h" +#include "curves.h" +#include "screen.h" +#include "picture.h" + +#include "label_data.h" +#include "markers.h" + +namespace ePiX { + + static void __epix_label(const P& base, const P& offset, + const std::string& lbl, + epix_label_posn POSN, bool masked) + { + label_data val(base, offset, lbl); + + if (masked) + { + // get mask color + Color my_mask(the_label_style().mask_color()); + + if (my_mask.is_unset()) + my_mask = White(); + + val.mask_color(my_mask); + } + + else // !masked + val.mask_color(Neutral()); + + val.align_to(POSN).draw(); + } + + // label -- put POSN-aligned string <label_text> + // at Cartesian position <base> translated by <offset> true points. + void label(const P& base, const P& offset, const std::string& lbl, + epix_label_posn POSN) + { + __epix_label(base, offset, lbl, POSN, the_label_style().is_masked()); + } + + // mask color comes from global style, falls back to White() + void masklabel(const P& base, const P& offset, const std::string& lbl, + epix_label_posn POSN) + { + __epix_label(base, offset, lbl, POSN, true); + } + + void label(const P& base, const P& offset, const std::string& lbl) + { + __epix_label(base, offset, lbl, none, the_label_style().is_masked()); + } + + void masklabel(const P& base, const P& offset, const std::string& lbl) + { + __epix_label(base, offset, lbl, none, true); + } + + // centered labels + void label(const P& base, const std::string& lbl) + { + __epix_label(base, P(0,0), lbl, c, the_label_style().is_masked()); + } + + void masklabel(const P& base, const std::string& lbl) + { + __epix_label(base, P(0,0), lbl, c, true); + } + + // Marker aliases + void marker(const P& arg, epix_mark_type TYPE) + { + label_data(arg, TYPE).draw(); + } + + // Markers with labels + void circ(const P& posn, const P& offset, const std::string& label_text, + epix_label_posn POSN) + { + if (label_text != "") + label(posn, offset, label_text, POSN); + label_data mk(posn, CIRC); + mk.draw(); + } + + void ring(const P& posn, const P& offset, const std::string& label_text, + epix_label_posn POSN) + { + if (label_text != "") + label(posn, offset, label_text, POSN); + label_data mk(posn, RING); + mk.draw(); + } + + void spot(const P& posn, const P& offset, const std::string& label_text, + epix_label_posn POSN) + { + if (label_text != "") + label(posn, offset, label_text, POSN); + label_data mk(posn, SPOT); + mk.draw(); + } + + void dot(const P& posn, const P& offset, const std::string& label_text, + epix_label_posn POSN) + { + if (label_text != "") + label(posn, offset, label_text, POSN); + label_data mk(posn, DOT); + mk.draw(); + } + + void ddot(const P& posn, const P& offset, const std::string& label_text, + epix_label_posn POSN) + { + if (label_text != "") + label(posn, offset, label_text, POSN); + label_data mk(posn, DDOT); + mk.draw(); + } + + void box(const P& posn, const P& offset, const std::string& label_text, + epix_label_posn POSN) + { + if (label_text != "") + label(posn, offset, label_text, POSN); + label_data mk(posn, BOX); + mk.draw(); + } + + void bbox(const P& posn, const P& offset, const std::string& label_text, + epix_label_posn POSN) + { + if (label_text != "") + label(posn, offset, label_text, POSN); + label_data mk(posn, BBOX); + mk.draw(); + } + + // Axis ticks (h_tick = tall, thin rectangle, for a *horizontal* axis) + void h_axis_tick(const P& arg, epix_label_posn POSN) + { + label_data mk(arg, HTICK, POSN); + mk.draw(); + } + + void v_axis_tick(const P& arg, epix_label_posn POSN) + { + label_data mk(arg, VTICK, POSN); + mk.draw(); + } + + + //// Curve-like elements + // arrow with label + void arrow(const P& tail, const P& head, const P& offset, + const std::string& label_text, + epix_label_posn POSN, double scale) + { + arrow(tail, head, scale); + label(tail, offset, label_text, POSN); + } + + // fixed-size elements + void right_angle(const P& loc, P leg1, P leg2, double scale) + { + const double norm1(norm(leg1)); + const double norm2(norm(leg2)); + + if (norm1 < EPIX_EPSILON || norm2 < EPIX_EPSILON) + return; + + //else + const double mult(pt_to_screen(scale)); + leg1 *= mult/norm1; + leg2 *= mult/norm2; + + path bd; + bd.pt(loc + leg1).pt(loc + leg1 + leg2).pt(loc + leg2); + bd.draw(); + } + + // the *acute* angle + void arc_measure(const P& loc, P leg1, P leg2, const P& offset, + const std::string& text, epix_label_posn align, + double scale) + { + const double norm1(norm(leg1)); + const double norm2(norm(leg2)); + + if (norm1 < EPIX_EPSILON || norm2 < EPIX_EPSILON) + return; + + //else normalize + leg1 *= 1.0/norm1; + leg2 *= 1.0/norm2; + + // check for parllelity + P perp(leg1*leg2); + const double norm3(norm(perp)); + + if (norm3 < EPIX_EPSILON) + return; + + // else get small angle + const double th(Acos(leg1|leg2)); + + perp *= 1.0/norm3; + leg1 *= pt_to_screen(scale); + + perp *= leg1; // perp to leg1 in plane of legs + + ellipse(loc, leg1, perp, 0, th); + + if (text != "") + label(loc + Cos(0.5*th)*leg1 + Sin(0.5*th)*perp, offset, + text, align); + } + + void arc_measure(const P& loc, P leg1, P leg2, double scale) + { + arc_measure(loc, leg1, leg2, P(0,0), "", none, scale); + } + + void axis_break(const P& tail, const P& head, double scale) + { + const P midpt(0.5*(head+tail)); + + P dir((head-tail)%E_3); // project to (x1,x2)-plane + + if (norm(dir) < EPIX_EPSILON) + return; + + // else + dir *= pt_to_screen(0.25*scale)/norm(dir); // zag is scale pt long + + path bd; + bd.pt(tail).pt(midpt-2*dir).pt(midpt-dir+1.5*J(dir)) + .pt(midpt+dir-1.5*J(dir)).pt(midpt+2*dir).pt(head); + + bd.draw(); + } + + void h_error_bar(const P& loc, double err, epix_mark_type mk, double ht) + { + const P dy(0, pt_to_screen(0.5*ht)); + const P bot(loc - P(err,0)); + const P top(loc + P(err,0)); + + line(bot, top); + line(bot - dy, bot + dy); + line(top - dy, top + dy); + marker(loc, mk); + } + + void v_error_bar(const P& loc, double err, epix_mark_type mk, double wd) + { + const P dx(pt_to_screen(0.5*wd), 0); + const P bot(loc - P(0,err)); + const P top(loc + P(0,err)); + + line(bot, top); + line(bot - dx, bot + dx); + line(top - dx, top + dx); + marker(loc, mk); + } +} // end of namespace |