1 /** \file
2 * Implements NR::Point::normalize()
3 */
5 #include <libnr/nr-types.h>
7 #include "2geom/isnan.h"
9 /** Scales this vector to make it a unit vector (within rounding error).
10 *
11 * The current version tries to handle infinite coordinates gracefully,
12 * but it's not clear that any callers need that.
13 *
14 * \pre *this != Point(0, 0).
15 * \pre Neither coordinate is NaN.
16 * \post L2(*this) very near 1.0.
17 */
18 void NR::Point::normalize() {
19 double len = hypot(_pt[0], _pt[1]);
20 g_return_if_fail(len != 0);
21 g_return_if_fail(!IS_NAN(len));
22 static double const inf = 1e400;
23 if(len != inf) {
24 *this /= len;
25 } else {
26 unsigned n_inf_coords = 0;
27 /* Delay updating pt in case neither coord is infinite. */
28 NR::Point tmp;
29 for ( unsigned i = 0 ; i < 2 ; ++i ) {
30 if ( _pt[i] == inf ) {
31 ++n_inf_coords;
32 tmp[i] = 1.0;
33 } else if ( _pt[i] == -inf ) {
34 ++n_inf_coords;
35 tmp[i] = -1.0;
36 } else {
37 tmp[i] = 0.0;
38 }
39 }
40 switch (n_inf_coords) {
41 case 0:
42 /* Can happen if both coords are near +/-DBL_MAX. */
43 *this /= 4.0;
44 len = hypot(_pt[0], _pt[1]);
45 g_assert(len != inf);
46 *this /= len;
47 break;
49 case 1:
50 *this = tmp;
51 break;
53 case 2:
54 *this = sqrt(0.5) * tmp;
55 break;
56 }
57 }
58 }
59 /*
60 Local Variables:
61 mode:c++
62 c-file-style:"stroustrup"
63 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
64 indent-tabs-mode:nil
65 fill-column:99
66 End:
67 */
68 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :