1 /*
2  * arrow_data.cc -- ePiX arrow class
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 
35 #include <list>
36 #include <cmath>
37 
38 #include "triples.h"
39 #include "functions.h"
40 
41 #include "camera.h"
42 
43 #include "edge_data.h"
44 #include "path_data.h"
45 #include "clipping.h"
46 
47 #include "arrow_style.h"
48 #include "pen_data.h"
49 #include "paint_style.h"
50 
51 #include "halfspace.h"
52 #include "pen_line.h"
53 #include "pen_arrow.h"
54 
55 #include "screen_data.h"
56 #include "screen.h"
57 #include "active_screen.h"
58 
59 #include "arrow_data.h"
60 
61 namespace ePiX {
62 
arrow_data(const std::vector<P> & pv,const P & base,const P & tip,double scale)63   arrow_data::arrow_data(const std::vector<P>& pv, const P& base, const P& tip,
64 			 double scale)
65     : m_base(base), m_tip(tip), m_scale(scale),
66       m_head_seen(!the_clip_box().clips(m_tip))
67   {
68     for (unsigned int i=0; i<pv.size()-1; ++i)
69       m_shaft.push_back(edge3d(pv.at(i), pv.at(i+1), true));
70 
71     the_clip_box().clip_path(m_shaft);
72   }
73 
clip_to(const halfspace & knife)74   arrow_data& arrow_data::clip_to(const halfspace& knife)
75   {
76     knife.clip_path(m_shaft);
77     if (knife.clips(m_tip))
78       m_head_seen = false;
79 
80     return *this;
81   }
82 
83 
photo(screen & scr,const Camera & mycam,const pen_data & line,const pen_data & under) const84   void arrow_data::photo(screen& scr, const Camera& mycam,
85 			 const pen_data& line, const pen_data& under) const
86   {
87     arrow_data tmp_data(*this);
88     if (mycam.needs_clip())
89       tmp_data.clip_to(mycam.clip_plane());
90 
91     std::list<edge2d> edges;
92     for (std::list<edge3d>::const_iterator p=tmp_data.m_shaft.begin();
93 	 p != tmp_data.m_shaft.end(); ++p)
94       {
95 	edge2d tmp(mycam((*p).tail()), mycam((*p).head()), (*p).is_seen());
96 
97 	if (!tmp.is_null()) // endpoints not equal
98 	  edges.push_back(tmp);
99       }
100 
101     // draw shaft
102     scr.m_screen->add_tile(pen_line(line.seen_through(mycam),
103 				    under.seen_through(mycam), edges));
104 
105     // and arrowhead
106     if (m_head_seen)
107       {
108 	const P dir(m_tip-m_base);
109 	const P to_cam(mycam.viewpt()-m_base);
110 
111 	const double sin_th(norm(dir*to_cam)/(norm(dir)*norm(to_cam)));
112 
113 	scr.m_screen->add_tile(pen_arrow(mycam(m_base), mycam(m_tip),
114 					 line.seen_through(mycam),
115 					 under.seen_through(mycam),
116 					 m_scale, sin_th, m_head_seen));
117       }
118   }
119 
draw() const120   void arrow_data::draw() const
121   {
122     photo(*active_screen(), cam(),
123 	  the_paint_style().line_pen(), the_paint_style().base_pen());
124   }
125 
draw(const pen_data & p1,const pen_data & p2) const126   void arrow_data::draw(const pen_data& p1, const pen_data& p2) const
127   {
128     photo(*active_screen(), cam(), p1, p2);
129   }
130 } // end of namespace
131