1///////////////////////////////////////////////////////////////////////////
2//
3// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
4// Digital Ltd. LLC
5//
6// All rights reserved.
7//
8// Redistribution and use in source and binary forms, with or without
9// modification, are permitted provided that the following conditions are
10// met:
11// *       Redistributions of source code must retain the above copyright
12// notice, this list of conditions and the following disclaimer.
13// *       Redistributions in binary form must reproduce the above
14// copyright notice, this list of conditions and the following disclaimer
15// in the documentation and/or other materials provided with the
16// distribution.
17// *       Neither the name of Industrial Light & Magic nor the names of
18// its contributors may be used to endorse or promote products derived
19// from this software without specific prior written permission.
20//
21// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32//
33///////////////////////////////////////////////////////////////////////////
34
35
36
37//----------------------------------------------------------------------------
38//
39//	Specializations of the Vec2<T> and Vec3<T> templates.
40//
41//----------------------------------------------------------------------------
42
43#include "ImathVec.h"
44
45#if (defined _WIN32 || defined _WIN64) && defined _MSC_VER
46// suppress exception specification warnings
47#pragma warning(disable:4290)
48#endif
49
50
51namespace Imath {
52
53namespace
54{
55
56template<class T>
57bool
58normalizeOrThrow(Vec2<T> &v)
59{
60    int axis = -1;
61    for (int i = 0; i < 2; i ++)
62    {
63	if (v[i] != 0)
64	{
65	    if (axis != -1)
66	    {
67		throw IntVecNormalizeExc ("Cannot normalize an integer "
68					  "vector unless it is parallel "
69					  "to a principal axis");
70	    }
71	    axis = i;
72	}
73    }
74    v[axis] = (v[axis] > 0) ? 1 : -1;
75    return true;
76}
77
78
79template<class T>
80bool
81normalizeOrThrow(Vec3<T> &v)
82{
83    int axis = -1;
84    for (int i = 0; i < 3; i ++)
85    {
86	if (v[i] != 0)
87	{
88	    if (axis != -1)
89	    {
90		throw IntVecNormalizeExc ("Cannot normalize an integer "
91					  "vector unless it is parallel "
92					  "to a principal axis");
93	    }
94	    axis = i;
95	}
96    }
97    v[axis] = (v[axis] > 0) ? 1 : -1;
98    return true;
99}
100
101}
102
103
104// Vec2<short>
105
106template <>
107short
108Vec2<short>::length () const
109{
110    float lenF = Math<float>::sqrt (dot (*this));
111    short lenS = (short) (lenF + 0.5f);
112    return lenS;
113}
114
115template <>
116const Vec2<short> &
117Vec2<short>::normalize ()
118{
119    normalizeOrThrow<short>(*this);
120    return *this;
121}
122
123template <>
124const Vec2<short> &
125Vec2<short>::normalizeExc () throw (Iex::MathExc)
126{
127    if ((x == 0) && (y == 0))
128	throw NullVecExc ("Cannot normalize null vector.");
129
130    normalizeOrThrow<short>(*this);
131    return *this;
132}
133
134template <>
135const Vec2<short> &
136Vec2<short>::normalizeNonNull ()
137{
138    normalizeOrThrow<short>(*this);
139    return *this;
140}
141
142template <>
143Vec2<short>
144Vec2<short>::normalized () const
145{
146    Vec2<short> v(*this);
147    normalizeOrThrow<short>(v);
148    return v;
149}
150
151template <>
152Vec2<short>
153Vec2<short>::normalizedExc () const throw (Iex::MathExc)
154{
155    if ((x == 0) && (y == 0))
156	throw NullVecExc ("Cannot normalize null vector.");
157
158    Vec2<short> v(*this);
159    normalizeOrThrow<short>(v);
160    return v;
161}
162
163template <>
164Vec2<short>
165Vec2<short>::normalizedNonNull () const
166{
167    Vec2<short> v(*this);
168    normalizeOrThrow<short>(v);
169    return v;
170}
171
172
173// Vec2<int>
174
175template <>
176int
177Vec2<int>::length () const
178{
179    float lenF = Math<float>::sqrt (dot (*this));
180    int lenI = (int) (lenF + 0.5f);
181    return lenI;
182}
183
184template <>
185const Vec2<int> &
186Vec2<int>::normalize ()
187{
188    normalizeOrThrow<int>(*this);
189    return *this;
190}
191
192template <>
193const Vec2<int> &
194Vec2<int>::normalizeExc () throw (Iex::MathExc)
195{
196    if ((x == 0) && (y == 0))
197	throw NullVecExc ("Cannot normalize null vector.");
198
199    normalizeOrThrow<int>(*this);
200    return *this;
201}
202
203template <>
204const Vec2<int> &
205Vec2<int>::normalizeNonNull ()
206{
207    normalizeOrThrow<int>(*this);
208    return *this;
209}
210
211template <>
212Vec2<int>
213Vec2<int>::normalized () const
214{
215    Vec2<int> v(*this);
216    normalizeOrThrow<int>(v);
217    return v;
218}
219
220template <>
221Vec2<int>
222Vec2<int>::normalizedExc () const throw (Iex::MathExc)
223{
224    if ((x == 0) && (y == 0))
225	throw NullVecExc ("Cannot normalize null vector.");
226
227    Vec2<int> v(*this);
228    normalizeOrThrow<int>(v);
229    return v;
230}
231
232template <>
233Vec2<int>
234Vec2<int>::normalizedNonNull () const
235{
236    Vec2<int> v(*this);
237    normalizeOrThrow<int>(v);
238    return v;
239}
240
241
242// Vec3<short>
243
244template <>
245short
246Vec3<short>::length () const
247{
248    float lenF = Math<float>::sqrt (dot (*this));
249    short lenS = (short) (lenF + 0.5f);
250    return lenS;
251}
252
253template <>
254const Vec3<short> &
255Vec3<short>::normalize ()
256{
257    normalizeOrThrow<short>(*this);
258    return *this;
259}
260
261template <>
262const Vec3<short> &
263Vec3<short>::normalizeExc () throw (Iex::MathExc)
264{
265    if ((x == 0) && (y == 0) && (z == 0))
266	throw NullVecExc ("Cannot normalize null vector.");
267
268    normalizeOrThrow<short>(*this);
269    return *this;
270}
271
272template <>
273const Vec3<short> &
274Vec3<short>::normalizeNonNull ()
275{
276    normalizeOrThrow<short>(*this);
277    return *this;
278}
279
280template <>
281Vec3<short>
282Vec3<short>::normalized () const
283{
284    Vec3<short> v(*this);
285    normalizeOrThrow<short>(v);
286    return v;
287}
288
289template <>
290Vec3<short>
291Vec3<short>::normalizedExc () const throw (Iex::MathExc)
292{
293    if ((x == 0) && (y == 0) && (z == 0))
294	throw NullVecExc ("Cannot normalize null vector.");
295
296    Vec3<short> v(*this);
297    normalizeOrThrow<short>(v);
298    return v;
299}
300
301template <>
302Vec3<short>
303Vec3<short>::normalizedNonNull () const
304{
305    Vec3<short> v(*this);
306    normalizeOrThrow<short>(v);
307    return v;
308}
309
310
311// Vec3<int>
312
313template <>
314int
315Vec3<int>::length () const
316{
317    float lenF = Math<float>::sqrt (dot (*this));
318    int lenI = (int) (lenF + 0.5f);
319    return lenI;
320}
321
322template <>
323const Vec3<int> &
324Vec3<int>::normalize ()
325{
326    normalizeOrThrow<int>(*this);
327    return *this;
328}
329
330template <>
331const Vec3<int> &
332Vec3<int>::normalizeExc () throw (Iex::MathExc)
333{
334    if ((x == 0) && (y == 0) && (z == 0))
335	throw NullVecExc ("Cannot normalize null vector.");
336
337    normalizeOrThrow<int>(*this);
338    return *this;
339}
340
341template <>
342const Vec3<int> &
343Vec3<int>::normalizeNonNull ()
344{
345    normalizeOrThrow<int>(*this);
346    return *this;
347}
348
349template <>
350Vec3<int>
351Vec3<int>::normalized () const
352{
353    Vec3<int> v(*this);
354    normalizeOrThrow<int>(v);
355    return v;
356}
357
358template <>
359Vec3<int>
360Vec3<int>::normalizedExc () const throw (Iex::MathExc)
361{
362    if ((x == 0) && (y == 0) && (z == 0))
363	throw NullVecExc ("Cannot normalize null vector.");
364
365    Vec3<int> v(*this);
366    normalizeOrThrow<int>(v);
367    return v;
368}
369
370template <>
371Vec3<int>
372Vec3<int>::normalizedNonNull () const
373{
374    Vec3<int> v(*this);
375    normalizeOrThrow<int>(v);
376    return v;
377}
378
379
380} // namespace Imath
381