Code

fix nodetype determination. more stable now. (lost symmetry detection, nobody is...
authorjohanengelen <johanengelen@users.sourceforge.net>
Wed, 23 Jul 2008 19:56:43 +0000 (19:56 +0000)
committerjohanengelen <johanengelen@users.sourceforge.net>
Wed, 23 Jul 2008 19:56:43 +0000 (19:56 +0000)
src/helper/geom-nodetype.cpp

index 4bd5d4643d8ad83575ef19f913765113ee7a5023..54c4e4e889eba64b0bb9dc211e8e6e3d2c491da9 100644 (file)
 namespace Geom {
 
 /*
+ * NOTE: THIS METHOD NEVER RETURNS "NODE_SYMM".
  * Returns the nodetype between c_incoming and c_outgoing. Location of the node is
  * at c_incoming.pointAt(1) == c_outgoing.pointAt(0). If these two are unequal, 
  * the returned type is NODE_NONE.
- * If one of the curves has zero length, but the other doesn't, then the returned type
- * is NODE_SMOOTH. If both have zero length, the returned type is NODE_SYMM. There is no
- * good reason for this. Feel free to change, but check all uses of this method such
- * that it doesn't break anything!
- * This method uses exact floating point comparison, so the final and initial points of
- * the two input curves should match exactly!
+ * Comparison is based on the unitTangent, does not work for NODE_SYMM!
  */
 NodeType get_nodetype(Curve const &c_incoming, Curve const &c_outgoing)
 {
-    // FIXME: this should be exact floating point match, not are_near!
     if ( !are_near(c_incoming.pointAt(1), c_outgoing.pointAt(0)) )
         return NODE_NONE;
 
-    Curve * c1_reverse = c_incoming.reverse();
-    std::vector<Point> deriv1 = c1_reverse->pointAndDerivatives(0, 3);
-    delete c1_reverse;
-    std::vector<Point> deriv2 = c_outgoing.pointAndDerivatives(0, 3);
-
-    // Determine lowest derivative that is non-zero
-    int n1 = 1;
-    while ( (deriv1[n1] == Point(0.,0.)) && (n1 <= 3) ) {
-        n1++;
-    }
-    int n2 = 1;
-    while ( (deriv2[n2] == Point(0.,0.)) && (n2 <= 3) ) {
-        n2++;
-    }
-
-    // if one of the paths still has zero derivative
-    if ( (n1 > 3) || (n2 > 3) ) {
-        if (n1 == n2)
-            return NODE_SYMM;
-        else
-            return NODE_SMOOTH;
-    }
-
-    // get unit derivatives, so the errors do not depend on absolute lengths of derivatives
-    Geom::Point const d1 = - deriv1[n1] / deriv1[n1].length(); // reverse sign because it is taken in "wrong direction"
-    Geom::Point const d2 = deriv2[n2]  / deriv2[n2].length();
-
-    double crossproduct = Geom::cross(d1, d2);
-    if ( are_near( crossproduct , 0.) && (Geom::dot(d1, d2) > 0.) ) {
-        // Apparently, the derivatives are colinear and in same direction but do they match exactly?
-        if ( (n1 == n2) && (Geom::are_near(-deriv1[n1], deriv2[n2])) )
-            return NODE_SYMM;
-        else
-            return NODE_SMOOTH;
+    Geom::Point deriv_1 = c_incoming.unitTangentAt(1);
+    Geom::Point deriv_2 = c_outgoing.unitTangentAt(0);
+    double this_angle_L2 = Geom::L2(deriv_1);
+    double next_angle_L2 = Geom::L2(deriv_2);
+    double both_angles_L2 = Geom::L2(deriv_1 + deriv_2);
+    if ( (this_angle_L2 > 1e-6) &&
+         (next_angle_L2 > 1e-6) &&
+         ((this_angle_L2 + next_angle_L2 - both_angles_L2) < 1e-3) )
+    {
+        return NODE_SMOOTH;
     }
 
     return NODE_CUSP;
 }
 
-}
+} // end namespace Geom
 
 /*
   Local Variables: