Code

add comment and implementation of get_nodetype where both curves are zero_length...
[inkscape.git] / src / helper / geom-nodetype.cpp
1 #define INKSCAPE_HELPER_GEOM_NODETYPE_CPP
3 /**
4  * Specific nodetype geometry functions for Inkscape, not provided my lib2geom.
5  *
6  * Author:
7  *   Johan Engelen <goejendaagh@zonnet.nl>
8  *
9  * Copyright (C) 2008 Johan Engelen
10  *
11  * Released under GNU GPL
12  */
14 #include "helper/geom-nodetype.h"
16 #include <2geom/curve.h>
17 #include <2geom/point.h>
18 #include <vector>
20 namespace Geom {
22 /*
23  * Returns the nodetype between c_incoming and c_outgoing. Location of the node is
24  * at c_incoming.pointAt(1) == c_outgoing.pointAt(0). If these two are unequal, 
25  * the returned type is NODE_NONE.
26  * If one of the curves has zero length, but the other doesn't, then the returned type
27  * is NODE_SMOOTH. If both have zero length, the returned type is NODE_SYMM. There is no
28  * good reason for this. Feel free to change, but check all uses of this method such
29  * that it doesn't break anything!
30  * This method uses exact floating point comparison, so the final and initial points of
31  * the two input curves should match exactly!
32  */
33 NodeType get_nodetype(Curve const &c_incoming, Curve const &c_outgoing)
34 {
35     // FIXME: this should be exact floating point match, not are_near!
36     if ( !are_near(c_incoming.pointAt(1), c_outgoing.pointAt(0)) )
37         return NODE_NONE;
39     Curve * c1_reverse = c_incoming.reverse();
40     std::vector<Point> deriv1 = c1_reverse->pointAndDerivatives(0, 3);
41     delete c1_reverse;
42     std::vector<Point> deriv2 = c_outgoing.pointAndDerivatives(0, 3);
44     // Determine lowest derivative that is non-zero
45     int n1 = 1;
46     while ( (deriv1[n1] == Point(0,0)) && (n1 <= 3) ) {
47         n1++;
48     }
49     int n2 = 1;
50     while ( (deriv2[n2] == Point(0,0)) && (n2 <= 3) ) {
51         n2++;
52     }
54     // if one of the paths still has zero derivative
55     if ( (n1 > 3) || (n2 > 3) ) {
56         if (n1 == n2)
57             return NODE_SYMM;
58         else
59             return NODE_SMOOTH;
60     }
62     double const angle1 = Geom::atan2(-deriv1[n1]);
63     double const angle2 = Geom::atan2(deriv2[n2]);
65     if ( !are_near(angle1, angle2) )
66         return NODE_CUSP;   // derivatives are not colinear
68     // Apparently, the derivatives are colinear but does the order of the derivatives match?
69     if (n1 != n2)
70         return NODE_SMOOTH;
71     else
72         return NODE_SYMM;
73 }
75 }
77 /*
78   Local Variables:
79   mode:c++
80   c-file-style:"stroustrup"
81   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
82   indent-tabs-mode:nil
83   fill-column:99
84   End:
85 */
86 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :