From: johanengelen Date: Wed, 23 Jul 2008 19:56:43 +0000 (+0000) Subject: fix nodetype determination. more stable now. (lost symmetry detection, nobody is... X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=13b2057922920384c8b51f3f944971f4ceab382b;p=inkscape.git fix nodetype determination. more stable now. (lost symmetry detection, nobody is using it yet). fixes lpe-spiro. --- diff --git a/src/helper/geom-nodetype.cpp b/src/helper/geom-nodetype.cpp index 4bd5d4643..54c4e4e88 100644 --- a/src/helper/geom-nodetype.cpp +++ b/src/helper/geom-nodetype.cpp @@ -20,62 +20,33 @@ 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 deriv1 = c1_reverse->pointAndDerivatives(0, 3); - delete c1_reverse; - std::vector 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: