diff --git a/src/ccstruct/blobs.h b/src/ccstruct/blobs.h index e7993ffc3b..fd2eb2a338 100644 --- a/src/ccstruct/blobs.h +++ b/src/ccstruct/blobs.h @@ -81,8 +81,8 @@ struct TPOINT { return x * other.x + y * other.y; } - // Calculate length of vector. - int length() const { + // Calculate square of vector length. + int length2() const { return x * x + y * y; } diff --git a/src/ccstruct/polyaprx.cpp b/src/ccstruct/polyaprx.cpp index 10753cbcc8..9492304c5b 100644 --- a/src/ccstruct/polyaprx.cpp +++ b/src/ccstruct/polyaprx.cpp @@ -108,7 +108,7 @@ static void cutline( // recursive refine edge = edge->next; } while (edge != last); // test all line - perp = vecsum.length(); + perp = vecsum.length2(); ASSERT_HOST(perp != 0); if (maxperp < 256 * INT16_MAX) { @@ -389,7 +389,7 @@ static void fix2( // polygonal approx break; // already too few } d12vec.diff(edgefix1->pos, edgefix2->pos); - d12 = d12vec.length(); + d12 = d12vec.length2(); // TODO(rays) investigate this change: // Only unfix a point if it is part of a low-curvature section // of outline and the total angle change of the outlines is @@ -397,9 +397,9 @@ static void fix2( // polygonal approx // if (d12 <= gapmin && edgefix0->vec.dot(edgefix2->vec) > 0) { if (d12 <= gapmin) { d01vec.diff(edgefix0->pos, edgefix1->pos); - d01 = d01vec.length(); + d01 = d01vec.length2(); d23vec.diff(edgefix2->pos, edgefix3->pos); - d23 = d23vec.length(); + d23 = d23vec.length2(); if (d01 > d23) { edgefix2->fixed = false; fixed_count--; diff --git a/src/wordrec/chop.cpp b/src/wordrec/chop.cpp index 64db4a29bb..5ee4799413 100644 --- a/src/wordrec/chop.cpp +++ b/src/wordrec/chop.cpp @@ -107,24 +107,31 @@ int Wordrec::angle_change(EDGEPT *point1, EDGEPT *point2, EDGEPT *point3) { vector2.x = point3->pos.x - point2->pos.x; vector2.y = point3->pos.y - point2->pos.y; /* Use cross product */ - float length = std::sqrt(static_cast(vector1.length()) * vector2.length()); + float length = std::sqrt(static_cast(vector1.length2()) * vector2.length2()); if (static_cast(length) == 0) { return (0); } - angle = static_cast(floor(std::asin(vector1.cross(vector2) / length) / M_PI * 180.0 + 0.5)); - - /* Use dot product */ - if (vector1.dot(vector2) < 0) { - angle = 180 - angle; - } - /* Adjust angle */ - if (angle > 180) { - angle -= 360; - } - if (angle <= -180) { - angle += 360; + auto f = vector1.cross(vector2) / length; + // Avoid FP exception in std::asin caused by illegal values of f + // (caused by rounding errors). + if (f <= -1.0f) { + angle = -90; + } else if (f >= 1.0f) { + angle = 90; + } else { + angle = static_cast(floor(std::asin(f) / M_PI * 180.0 + 0.5)); + // Use dot product. + if (vector1.dot(vector2) < 0) { + angle = 180 - angle; + } + // Adjust angle. + if (angle > 180) { + angle -= 360; + } else if (angle <= -180) { + angle += 360; + } } - return (angle); + return angle; } /**