1 /*
2  * Sline.cc -- ePiX::Sline class (spherical arc)
3  *
4  * This file is part of ePiX, a preprocessor for creating high-quality
5  * line figures in LaTeX
6  *
7  * Version 1.2.17
8  * Last Change: June 30, 2017
9  */
10 
11 /*
12  * Copyright (C) 2017
13  * Andrew D. Hwang <rot 13 nujnat at 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 <cmath>
36 #include "constants.h"
37 #include "errors.h"
38 
39 #include "triples.h"
40 #include "geometry.h"
41 
42 #include "Sline.h"
43 
44 namespace ePiX {
Sline(const P & tail,const P & head)45   Sline::Sline(const P& tail, const P& head)
46     : m_tail(tail), m_head(head), m_malformed(false)
47   {
48     double mt(norm(tail)), mh(norm(head));
49     if (fabs(mt - 1) > EPIX_EPSILON)
50       {
51 	epix_warning("First argument of Sline is not a unit vector");
52 	if (EPIX_EPSILON < mt && mt < EPIX_INFTY)
53 	  m_tail *= 1.0/mt;
54 	else
55 	  m_malformed = true;
56       }
57 
58     if (fabs(mh - 1) > EPIX_EPSILON)
59       {
60 	epix_warning("Second argument of Sline is not a unit vector");
61 	if (EPIX_EPSILON < mh && mh < EPIX_INFTY)
62 	  m_head *= 1.0/mh;
63 	else
64 	  m_malformed = true;
65       }
66 
67     m_pole = m_tail * m_head;
68     double mp(norm(m_pole));
69     if (mp < EPIX_EPSILON)
70       {
71 	epix_warning("Collinear arguments in Sline");
72 	m_pole = P(0,0,0);
73 	m_malformed = true;
74       }
75 
76     else // well-formed; normalize pole
77       m_pole *= 1.0/mp;
78   } // end of Sline::Sline
79 
malformed() const80   bool Sline::malformed() const
81   {
82     return m_malformed;
83   }
84 
pole() const85   P Sline::pole() const
86   {
87     if (m_malformed)
88       epix_warning("Pole of malformed Sline requested");
89 
90     return m_pole;
91   }
92 
cosine() const93   double Sline::cosine() const
94   {
95     return (m_tail | m_head);
96   }
97 
operator *(const Sline & arg) const98   P Sline::operator * (const Sline& arg) const
99   {
100     if (m_malformed || arg.m_malformed)
101       {
102 	epix_warning("Malformed argument(s) in Sline intersection");
103 	return P(0,0,0);
104       }
105     else if (this -> collinear(arg))
106       {
107 	epix_warning("Collinear argument(s) in Sline intersection");
108 	return P(0,0,0);
109       }
110 
111     // else
112     P val(m_pole * arg.m_pole);
113     val *= 1.0/norm(val);
114 
115     if (0 < (m_tail | val))
116       return val;
117 
118     else
119       return -val;
120   }
121 
reflect(const P & arg) const122   P Sline::reflect(const P& arg) const
123   {
124     return arg - 2*(m_pole | arg)*m_pole;
125   }
126 
reflect(const Sline & arg) const127   Sline Sline::reflect(const Sline& arg) const
128   {
129     return Sline(this -> reflect(arg.m_tail), this -> reflect(arg.m_head));
130   }
131 
collinear(const Sline & arg) const132   bool Sline::collinear(const Sline& arg) const
133   {
134     return m_malformed ||
135       arg.m_malformed ||
136       norm(m_pole * arg.m_pole) < EPIX_EPSILON;
137   }
138 
cuts(const Sline & arg) const139   bool Sline::cuts(const Sline& arg) const // we and arg cross
140   {
141     return ((m_tail | arg.m_pole)*(m_head | arg.m_pole) < 0 &&
142 	    (m_pole | arg.m_tail)*(m_pole | arg.m_head) < 0);
143   }
144 
draw() const145   void Sline::draw() const
146   {
147     this -> draw_front();
148     this -> draw_back();
149   }
150 
draw_front() const151   void Sline::draw_front() const // front arc
152   {
153     front_arc(m_tail, m_head);
154   }
155 
draw_back() const156   void Sline::draw_back() const // back arc
157   {
158     back_arc(m_tail, m_head);
159   }
160 
draw_line() const161   void Sline::draw_line() const
162   {
163     this -> line_back();
164     this -> line_front();
165   }
166 
line_front() const167   void Sline::line_front() const
168   {
169     front_line(m_tail, m_head);
170   }
171 
line_back() const172   void Sline::line_back() const // back line
173   {
174     back_line(m_tail, m_head);
175   }
176 } // end of namespace
177