Commit 2bf36c31 authored by Ovidiu Parvu's avatar Ovidiu Parvu

Removed static variables which were not read-only and used more function parameters instead.

parent e324446c
...@@ -97,47 +97,16 @@ ...@@ -97,47 +97,16 @@
#define EPSILON 1E-5 #define EPSILON 1E-5
/////////////////////////////////// Global variables /////////////////////////////////////
namespace minEnclosingTriangle {
static unsigned int G_validationFlag;
static cv::Point2f G_vertexA;
static cv::Point2f G_vertexB;
static cv::Point2f G_vertexC;
static cv::Point2f G_sideAStartVertex;
static cv::Point2f G_sideAEndVertex;
static cv::Point2f G_sideBStartVertex;
static cv::Point2f G_sideBEndVertex;
static cv::Point2f G_sideCStartVertex;
static cv::Point2f G_sideCEndVertex;
static double G_triangleArea;
static unsigned int G_a;
static unsigned int G_b;
static unsigned int G_c;
static unsigned int G_nrOfPoints;
static std::vector<cv::Point2f> G_polygon;
};
////////////////////////////// Helper functions declarations ///////////////////////////// ////////////////////////////// Helper functions declarations /////////////////////////////
namespace minEnclosingTriangle { namespace minEnclosingTriangle {
static void advance(unsigned int &index); static void advance(unsigned int &index, unsigned int nrOfPoints);
static void advanceBToRightChain(); static void advanceBToRightChain(const std::vector<cv::Point2f> &polygon,
unsigned int nrOfPoints, unsigned int &b,
unsigned int c);
static bool almostEqual(double number1, double number2); static bool almostEqual(double number1, double number2);
...@@ -162,44 +131,64 @@ static double areaOfTriangle(const cv::Point2f &a, const cv::Point2f &b, const c ...@@ -162,44 +131,64 @@ static double areaOfTriangle(const cv::Point2f &a, const cv::Point2f &b, const c
static void copyResultingTriangle(const std::vector<cv::Point2f> &resultingTriangle, cv::OutputArray triangle); static void copyResultingTriangle(const std::vector<cv::Point2f> &resultingTriangle, cv::OutputArray triangle);
static void createConvexHull(cv::InputArray points); static void createConvexHull(cv::InputArray points, std::vector<cv::Point2f> &polygon);
static double distanceBtwPoints(const cv::Point2f &a, const cv::Point2f &b); static double distanceBtwPoints(const cv::Point2f &a, const cv::Point2f &b);
static double distanceFromPointToLine(const cv::Point2f &a, const cv::Point2f &linePointB, static double distanceFromPointToLine(const cv::Point2f &a, const cv::Point2f &linePointB,
const cv::Point2f &linePointC); const cv::Point2f &linePointC);
static bool findGammaIntersectionPoints(unsigned int polygonPointIndex, const cv::Point2f &side1StartVertex, static bool findGammaIntersectionPoints(const std::vector<cv::Point2f> &polygon, unsigned int nrOfPoints,
const cv::Point2f &side1EndVertex, const cv::Point2f &side2StartVertex, unsigned int c, unsigned int polygonPointIndex,
const cv::Point2f &side2EndVertex, cv::Point2f &intersectionPoint1, const cv::Point2f &side1StartVertex, const cv::Point2f &side1EndVertex,
cv::Point2f &intersectionPoint2); const cv::Point2f &side2StartVertex, const cv::Point2f &side2EndVertex,
cv::Point2f &intersectionPoint1, cv::Point2f &intersectionPoint2);
static void findMinEnclosingTriangle(cv::InputArray points, static void findMinEnclosingTriangle(cv::InputArray points,
CV_OUT cv::OutputArray triangle, CV_OUT double &area); CV_OUT cv::OutputArray triangle, CV_OUT double &area);
static void findMinEnclosingTriangle(std::vector<cv::Point2f> &triangle, double &area); static void findMinEnclosingTriangle(const std::vector<cv::Point2f> &polygon,
std::vector<cv::Point2f> &triangle, double &area);
static void findMinimumAreaEnclosingTriangle(std::vector<cv::Point2f> &triangle, double &area); static void findMinimumAreaEnclosingTriangle(const std::vector<cv::Point2f> &polygon,
std::vector<cv::Point2f> &triangle, double &area);
static cv::Point2f findVertexCOnSideB(); static cv::Point2f findVertexCOnSideB(const std::vector<cv::Point2f> &polygon, unsigned int nrOfPoints,
unsigned int a, unsigned int c,
const cv::Point2f &sideBStartVertex,
const cv::Point2f &sideBEndVertex,
const cv::Point2f &sideCStartVertex,
const cv::Point2f &sideCEndVertex);
static bool gamma(unsigned int polygonPointIndex, cv::Point2f &gammaPoint); static bool gamma(unsigned int polygonPointIndex, cv::Point2f &gammaPoint,
const std::vector<cv::Point2f> &polygon, unsigned int nrOfPoints,
unsigned int a, unsigned int c);
static bool greaterOrEqual(double number1, double number2); static bool greaterOrEqual(double number1, double number2);
static double height(const cv::Point2f &polygonPoint); static double height(const cv::Point2f &polygonPoint, const std::vector<cv::Point2f> &polygon,
unsigned int nrOfPoints, unsigned int c);
static double height(unsigned int polygonPointIndex); static double height(unsigned int polygonPointIndex, const std::vector<cv::Point2f> &polygon,
unsigned int nrOfPoints, unsigned int c);
static void initialise(std::vector<cv::Point2f> &triangle, double &area); static void initialise(std::vector<cv::Point2f> &triangle, double &area);
static unsigned int intersects(double angleGammaAndPoint, unsigned int polygonPointIndex); static unsigned int intersects(double angleGammaAndPoint, unsigned int polygonPointIndex,
const std::vector<cv::Point2f> &polygon, unsigned int nrOfPoints,
unsigned int c);
static bool intersectsAbove(const cv::Point2f &gammaPoint, unsigned int polygonPointIndex); static bool intersectsAbove(const cv::Point2f &gammaPoint, unsigned int polygonPointIndex,
const std::vector<cv::Point2f> &polygon, unsigned int nrOfPoints,
unsigned int c);
static unsigned int intersectsAboveOrBelow(unsigned int succPredIndex, unsigned int pointIndex); static unsigned int intersectsAboveOrBelow(unsigned int succPredIndex, unsigned int pointIndex,
const std::vector<cv::Point2f> &polygon,
unsigned int nrOfPoints, unsigned int c);
static bool intersectsBelow(const cv::Point2f &gammaPoint, unsigned int polygonPointIndex); static bool intersectsBelow(const cv::Point2f &gammaPoint, unsigned int polygonPointIndex,
const std::vector<cv::Point2f> &polygon, unsigned int nrOfPoints,
unsigned int c);
static bool isAngleBetween(double angle1, double angle2, double angle3); static bool isAngleBetween(double angle1, double angle2, double angle3);
...@@ -211,16 +200,30 @@ static bool isGammaAngleBtw(double &gammaAngle, double angle1, double angle2); ...@@ -211,16 +200,30 @@ static bool isGammaAngleBtw(double &gammaAngle, double angle1, double angle2);
static bool isGammaAngleEqualTo(double &gammaAngle, double angle); static bool isGammaAngleEqualTo(double &gammaAngle, double angle);
static bool isLocalMinimalTriangle(); static bool isLocalMinimalTriangle(cv::Point2f &vertexA, cv::Point2f &vertexB,
cv::Point2f &vertexC, const std::vector<cv::Point2f> &polygon,
unsigned int nrOfPoints, unsigned int a, unsigned int b,
unsigned int validationFlag, const cv::Point2f &sideAStartVertex,
const cv::Point2f &sideAEndVertex, const cv::Point2f &sideBStartVertex,
const cv::Point2f &sideBEndVertex, const cv::Point2f &sideCStartVertex,
const cv::Point2f &sideCEndVertex);
static bool isNotBTangency(); static bool isNotBTangency(const std::vector<cv::Point2f> &polygon,
unsigned int nrOfPoints, unsigned int a, unsigned int b,
unsigned int c);
static bool isOppositeAngleBetweenNonReflex(double angle1, double angle2, double angle3); static bool isOppositeAngleBetweenNonReflex(double angle1, double angle2, double angle3);
static bool isPointOnLineSegment(const cv::Point2f &point, const cv::Point2f &lineSegmentStart, static bool isPointOnLineSegment(const cv::Point2f &point, const cv::Point2f &lineSegmentStart,
const cv::Point2f &lineSegmentEnd); const cv::Point2f &lineSegmentEnd);
static bool isValidMinimalTriangle(); static bool isValidMinimalTriangle(const cv::Point2f &vertexA, const cv::Point2f &vertexB,
const cv::Point2f &vertexC, const std::vector<cv::Point2f> &polygon,
unsigned int nrOfPoints, unsigned int a, unsigned int b,
unsigned int validationFlag, const cv::Point2f &sideAStartVertex,
const cv::Point2f &sideAEndVertex, const cv::Point2f &sideBStartVertex,
const cv::Point2f &sideBEndVertex, const cv::Point2f &sideCStartVertex,
const cv::Point2f &sideCEndVertex);
static bool lessOrEqual(double number1, double number2); static bool lessOrEqual(double number1, double number2);
...@@ -239,29 +242,50 @@ static double maximum(double number1, double number2, double number3); ...@@ -239,29 +242,50 @@ static double maximum(double number1, double number2, double number3);
static cv::Point2f middlePoint(const cv::Point2f &a, const cv::Point2f &b); static cv::Point2f middlePoint(const cv::Point2f &a, const cv::Point2f &b);
static bool middlePointOfSideB(cv::Point2f& middlePointOfSideB); static bool middlePointOfSideB(cv::Point2f &middlePointOfSideB, const cv::Point2f &sideAStartVertex,
const cv::Point2f &sideAEndVertex, const cv::Point2f &sideBStartVertex,
const cv::Point2f &sideBEndVertex, const cv::Point2f &sideCStartVertex,
const cv::Point2f &sideCEndVertex);
static void moveAIfLowAndBIfHigh(); static void moveAIfLowAndBIfHigh(const std::vector<cv::Point2f> &polygon,
unsigned int nrOfPoints, unsigned int &a, unsigned int &b,
unsigned int c);
static double oppositeAngle(double angle); static double oppositeAngle(double angle);
static unsigned int predecessor(unsigned int index); static unsigned int predecessor(unsigned int index, unsigned int nrOfPoints);
static void returnMinimumAreaEnclosingTriangle(std::vector<cv::Point2f> &triangle, double &area); static void returnMinimumAreaEnclosingTriangle(const std::vector<cv::Point2f> &polygon,
std::vector<cv::Point2f> &triangle, double &area);
static void searchForBTangency(); static void searchForBTangency(const std::vector<cv::Point2f> &polygon,
unsigned int nrOfPoints, unsigned int a, unsigned int &b,
unsigned int c);
static int sign(double number); static int sign(double number);
static unsigned int successor(unsigned int index); static unsigned int successor(unsigned int index, unsigned int nrOfPoints);
static void updateMinimumAreaEnclosingTriangle(std::vector<cv::Point2f> &triangle, double &area); static void updateMinimumAreaEnclosingTriangle(std::vector<cv::Point2f> &triangle, double &area,
const cv::Point2f &vertexA, const cv::Point2f &vertexB,
const cv::Point2f &vertexC);
static void updateSideB(); static void updateSideB(const std::vector<cv::Point2f> &polygon,
unsigned int nrOfPoints, unsigned int a, unsigned int b,
unsigned int c, unsigned int &validationFlag,
cv::Point2f &sideBStartVertex, cv::Point2f &sideBEndVertex);
static void updateSidesBA(); static void updateSidesBA(const std::vector<cv::Point2f> &polygon,
unsigned int nrOfPoints, unsigned int a, unsigned int b,
unsigned int c, unsigned int &validationFlag,
cv::Point2f &sideAStartVertex, cv::Point2f &sideAEndVertex,
cv::Point2f &sideBStartVertex, cv::Point2f &sideBEndVertex,
const cv::Point2f &sideCStartVertex, const cv::Point2f &sideCEndVertex);
static void updateSidesCA(); static void updateSidesCA(const std::vector<cv::Point2f> &polygon,
unsigned int nrOfPoints, unsigned int a, unsigned int c,
cv::Point2f &sideAStartVertex, cv::Point2f &sideAEndVertex,
cv::Point2f &sideCStartVertex, cv::Point2f &sideCEndVertex);
}; };
...@@ -296,18 +320,19 @@ namespace minEnclosingTriangle { ...@@ -296,18 +320,19 @@ namespace minEnclosingTriangle {
*/ */
static void findMinEnclosingTriangle(cv::InputArray points, static void findMinEnclosingTriangle(cv::InputArray points,
CV_OUT cv::OutputArray triangle, CV_OUT double &area) { CV_OUT cv::OutputArray triangle, CV_OUT double &area) {
std::vector<cv::Point2f> resultingTriangle; std::vector<cv::Point2f> resultingTriangle, polygon;
createConvexHull(points); createConvexHull(points, polygon);
findMinEnclosingTriangle(resultingTriangle, area); findMinEnclosingTriangle(polygon, resultingTriangle, area);
copyResultingTriangle(resultingTriangle, triangle); copyResultingTriangle(resultingTriangle, triangle);
} }
//! Create the convex hull of the given set of points //! Create the convex hull of the given set of points
/*! /*!
* @param points The provided set of points * @param points The provided set of points
* @param polygon The polygon representing the convex hull of the points
*/ */
static void createConvexHull(cv::InputArray points) { static void createConvexHull(cv::InputArray points, std::vector<cv::Point2f> &polygon) {
cv::Mat pointsMat = points.getMat(); cv::Mat pointsMat = points.getMat();
std::vector<cv::Point2f> pointsVector; std::vector<cv::Point2f> pointsVector;
...@@ -316,7 +341,7 @@ static void createConvexHull(cv::InputArray points) { ...@@ -316,7 +341,7 @@ static void createConvexHull(cv::InputArray points) {
pointsMat.convertTo(pointsVector, CV_32F); pointsMat.convertTo(pointsVector, CV_32F);
convexHull(pointsVector, G_polygon, true, true); convexHull(pointsVector, polygon, true, true);
} }
//! Find the minimum enclosing triangle and its area //! Find the minimum enclosing triangle and its area
...@@ -324,16 +349,18 @@ static void createConvexHull(cv::InputArray points) { ...@@ -324,16 +349,18 @@ static void createConvexHull(cv::InputArray points) {
* The overall complexity of the algorithm is theta(n) where "n" represents the number * The overall complexity of the algorithm is theta(n) where "n" represents the number
* of vertices in the convex polygon * of vertices in the convex polygon
* *
* @param triangle Minimum area triangle enclosing the given polygon * @param polygon The polygon representing the convex hull of the points
* @param area Area of the minimum area enclosing triangle * @param triangle Minimum area triangle enclosing the given polygon
* @param area Area of the minimum area enclosing triangle
*/ */
static void findMinEnclosingTriangle(std::vector<cv::Point2f> &triangle, double &area) { static void findMinEnclosingTriangle(const std::vector<cv::Point2f> &polygon,
std::vector<cv::Point2f> &triangle, double &area) {
initialise(triangle, area); initialise(triangle, area);
if (G_polygon.size() > 3) { if (polygon.size() > 3) {
findMinimumAreaEnclosingTriangle(triangle, area); findMinimumAreaEnclosingTriangle(polygon, triangle, area);
} else { } else {
returnMinimumAreaEnclosingTriangle(triangle, area); returnMinimumAreaEnclosingTriangle(polygon, triangle, area);
} }
} }
...@@ -353,51 +380,81 @@ static void copyResultingTriangle(const std::vector<cv::Point2f> &resultingTrian ...@@ -353,51 +380,81 @@ static void copyResultingTriangle(const std::vector<cv::Point2f> &resultingTrian
* @param area Area of the minimum area enclosing triangle * @param area Area of the minimum area enclosing triangle
*/ */
static void initialise(std::vector<cv::Point2f> &triangle, double &area) { static void initialise(std::vector<cv::Point2f> &triangle, double &area) {
G_nrOfPoints = static_cast<unsigned int>(G_polygon.size());
area = std::numeric_limits<double>::max(); area = std::numeric_limits<double>::max();
// Clear all points previously stored in the vector // Clear all points previously stored in the vector
triangle.clear(); triangle.clear();
// Initialise the values of the indices for the algorithm
G_a = 1;
G_b = 2;
G_c = 0;
} }
//! Find the minimum area enclosing triangle for the given polygon //! Find the minimum area enclosing triangle for the given polygon
/*! /*!
* @param polygon The polygon representing the convex hull of the points
* @param triangle Minimum area triangle enclosing the given polygon * @param triangle Minimum area triangle enclosing the given polygon
* @param area Area of the minimum area enclosing triangle * @param area Area of the minimum area enclosing triangle
*/ */
static void findMinimumAreaEnclosingTriangle(std::vector<cv::Point2f> &triangle, double &area) { static void findMinimumAreaEnclosingTriangle(const std::vector<cv::Point2f> &polygon,
for (G_c = 0; G_c < G_nrOfPoints; G_c++) { std::vector<cv::Point2f> &triangle, double &area) {
advanceBToRightChain(); // Algorithm specific variables
moveAIfLowAndBIfHigh();
searchForBTangency(); unsigned int validationFlag;
cv::Point2f vertexA, vertexB, vertexC;
cv::Point2f sideAStartVertex, sideAEndVertex;
cv::Point2f sideBStartVertex, sideBEndVertex;
cv::Point2f sideCStartVertex, sideCEndVertex;
updateSidesCA(); unsigned int a, b, c;
unsigned int nrOfPoints;
if (isNotBTangency()) { // Variables initialisation
updateSidesBA();
nrOfPoints = static_cast<unsigned int>(polygon.size());
a = 1;
b = 2;
c = 0;
// Main algorithm steps
for (c = 0; c < nrOfPoints; c++) {
advanceBToRightChain(polygon, nrOfPoints, b, c);
moveAIfLowAndBIfHigh(polygon, nrOfPoints, a, b, c);
searchForBTangency(polygon, nrOfPoints, a ,b, c);
updateSidesCA(polygon, nrOfPoints, a, c, sideAStartVertex, sideAEndVertex,
sideCStartVertex, sideCEndVertex);
if (isNotBTangency(polygon, nrOfPoints, a, b, c)) {
updateSidesBA(polygon, nrOfPoints, a, b, c, validationFlag, sideAStartVertex,
sideAEndVertex, sideBStartVertex, sideBEndVertex,
sideCStartVertex, sideCEndVertex);
} else { } else {
updateSideB(); updateSideB(polygon, nrOfPoints, a, b, c, validationFlag,
sideBStartVertex, sideBEndVertex);
} }
if (isLocalMinimalTriangle()) { if (isLocalMinimalTriangle(vertexA, vertexB, vertexC, polygon, nrOfPoints, a, b,
updateMinimumAreaEnclosingTriangle(triangle, area); validationFlag, sideAStartVertex, sideAEndVertex,
sideBStartVertex, sideBEndVertex, sideCStartVertex,
sideCEndVertex)) {
updateMinimumAreaEnclosingTriangle(triangle, area, vertexA, vertexB, vertexC);
} }
} }
} }
//! Return the minimum area enclosing (pseudo-)triangle in case the convex polygon has at most three points //! Return the minimum area enclosing (pseudo-)triangle in case the convex polygon has at most three points
/*! /*!
* @param polygon The polygon representing the convex hull of the points
* @param triangle Minimum area triangle enclosing the given polygon * @param triangle Minimum area triangle enclosing the given polygon
* @param area Area of the minimum area enclosing triangle * @param area Area of the minimum area enclosing triangle
*/ */
static void returnMinimumAreaEnclosingTriangle(std::vector<cv::Point2f> &triangle, double &area) { static void returnMinimumAreaEnclosingTriangle(const std::vector<cv::Point2f> &polygon,
std::vector<cv::Point2f> &triangle, double &area) {
unsigned int nrOfPoints = static_cast<unsigned int>(polygon.size());
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
triangle.push_back(G_polygon[i % G_nrOfPoints]); triangle.push_back(polygon[i % nrOfPoints]);
} }
area = areaOfTriangle(triangle[0], triangle[1], triangle[2]); area = areaOfTriangle(triangle[0], triangle[1], triangle[2]);
...@@ -406,25 +463,41 @@ static void returnMinimumAreaEnclosingTriangle(std::vector<cv::Point2f> &triangl ...@@ -406,25 +463,41 @@ static void returnMinimumAreaEnclosingTriangle(std::vector<cv::Point2f> &triangl
//! Advance b to the right chain //! Advance b to the right chain
/*! /*!
* See paper [2] for more details * See paper [2] for more details
*
* @param polygon The polygon representing the convex hull of the points
* @param nrOfPoints Number of points defining the convex polygon
* @param b Index b
* @param c Index c
*/ */
static void advanceBToRightChain() { static void advanceBToRightChain(const std::vector<cv::Point2f> &polygon,
while (greaterOrEqual(height(successor(G_b)), height(G_b))) { unsigned int nrOfPoints, unsigned int &b,
advance(G_b); unsigned int c) {
while (greaterOrEqual(height(successor(b, nrOfPoints), polygon, nrOfPoints, c),
height(b, polygon, nrOfPoints, c))) {
advance(b, nrOfPoints);
} }
} }
//! Move "a" if it is low and "b" if it is high //! Move "a" if it is low and "b" if it is high
/*! /*!
* See paper [2] for more details * See paper [2] for more details
*
* @param polygon The polygon representing the convex hull of the points
* @param nrOfPoints Number of points defining the convex polygon
* @param a Index a
* @param b Index b
* @param c Index c
*/ */
static void moveAIfLowAndBIfHigh() { static void moveAIfLowAndBIfHigh(const std::vector<cv::Point2f> &polygon,
unsigned int nrOfPoints, unsigned int &a, unsigned int &b,
unsigned int c) {
cv::Point2f gammaOfA; cv::Point2f gammaOfA;
while(height(G_b) > height(G_a)) { while(height(b, polygon, nrOfPoints, c) > height(a, polygon, nrOfPoints, c)) {
if ((gamma(G_a, gammaOfA)) && (intersectsBelow(gammaOfA, G_b))) { if ((gamma(a, gammaOfA, polygon, nrOfPoints, a, c)) && (intersectsBelow(gammaOfA, b, polygon, nrOfPoints, c))) {
advance(G_b); advance(b, nrOfPoints);
} else { } else {
advance(G_a); advance(a, nrOfPoints);
} }
} }
} }
...@@ -432,25 +505,45 @@ static void moveAIfLowAndBIfHigh() { ...@@ -432,25 +505,45 @@ static void moveAIfLowAndBIfHigh() {
//! Search for the tangency of side B //! Search for the tangency of side B
/*! /*!
* See paper [2] for more details * See paper [2] for more details
*
* @param polygon The polygon representing the convex hull of the points
* @param nrOfPoints Number of points defining the convex polygon
* @param a Index a
* @param b Index b
* @param c Index c
*/ */
static void searchForBTangency() { static void searchForBTangency(const std::vector<cv::Point2f> &polygon,
unsigned int nrOfPoints, unsigned int a, unsigned int &b,
unsigned int c) {
cv::Point2f gammaOfB; cv::Point2f gammaOfB;
while (((gamma(G_b, gammaOfB)) && (intersectsBelow(gammaOfB, G_b))) && while (((gamma(b, gammaOfB, polygon, nrOfPoints, a, c)) &&
(greaterOrEqual(height(G_b), height(predecessor(G_a))))) { (intersectsBelow(gammaOfB, b, polygon, nrOfPoints, c))) &&
advance(G_b); (greaterOrEqual(height(b, polygon, nrOfPoints, c),
height(predecessor(a, nrOfPoints), polygon, nrOfPoints, c)))
) {
advance(b, nrOfPoints);
} }
} }
//! Check if tangency for side B was not obtained //! Check if tangency for side B was not obtained
/*! /*!
* See paper [2] for more details * See paper [2] for more details
*
* @param polygon The polygon representing the convex hull of the points
* @param nrOfPoints Number of points defining the convex polygon
* @param a Index a
* @param b Index b
* @param c Index c
*/ */
static bool isNotBTangency() { static bool isNotBTangency(const std::vector<cv::Point2f> &polygon,
unsigned int nrOfPoints, unsigned int a, unsigned int b,
unsigned int c) {
cv::Point2f gammaOfB; cv::Point2f gammaOfB;
if (((gamma(G_b, gammaOfB)) && (intersectsAbove(gammaOfB, G_b))) || if (((gamma(b, gammaOfB, polygon, nrOfPoints, a, c)) &&
(height(G_b) < height(predecessor(G_a)))) { (intersectsAbove(gammaOfB, b, polygon, nrOfPoints, c))) ||
(height(b, polygon, nrOfPoints, c) < height(predecessor(a, nrOfPoints), polygon, nrOfPoints, c))) {
return true; return true;
} }
...@@ -461,67 +554,137 @@ static bool isNotBTangency() { ...@@ -461,67 +554,137 @@ static bool isNotBTangency() {
/*! /*!
* Side C will have as start and end vertices the polygon points "c" and "c-1" * Side C will have as start and end vertices the polygon points "c" and "c-1"
* Side A will have as start and end vertices the polygon points "a" and "a-1" * Side A will have as start and end vertices the polygon points "a" and "a-1"
*
* @param polygon The polygon representing the convex hull of the points
* @param nrOfPoints Number of points defining the convex polygon
* @param a Index a
* @param c Index c
* @param sideAStartVertex Start vertex for defining side A
* @param sideAEndVertex End vertex for defining side A
* @param sideCStartVertex Start vertex for defining side C
* @param sideCEndVertex End vertex for defining side C
*/ */
static void updateSidesCA() { static void updateSidesCA(const std::vector<cv::Point2f> &polygon,
G_sideCStartVertex = G_polygon[predecessor(G_c)]; unsigned int nrOfPoints, unsigned int a, unsigned int c,
G_sideCEndVertex = G_polygon[G_c]; cv::Point2f &sideAStartVertex, cv::Point2f &sideAEndVertex,
cv::Point2f &sideCStartVertex, cv::Point2f &sideCEndVertex) {
G_sideAStartVertex = G_polygon[predecessor(G_a)]; sideCStartVertex = polygon[predecessor(c, nrOfPoints)];
G_sideAEndVertex = G_polygon[G_a]; sideCEndVertex = polygon[c];
sideAStartVertex = polygon[predecessor(a, nrOfPoints)];
sideAEndVertex = polygon[a];
} }
//! Update sides B and possibly A if tangency for side B was not obtained //! Update sides B and possibly A if tangency for side B was not obtained
/*! /*!
* See paper [2] for more details * See paper [2] for more details
*
* @param polygon The polygon representing the convex hull of the points
* @param nrOfPoints Number of points defining the convex polygon
* @param a Index a
* @param b Index b
* @param c Index c
* @param validationFlag Flag used for validation
* @param sideAStartVertex Start vertex for defining side A
* @param sideAEndVertex End vertex for defining side A
* @param sideBStartVertex Start vertex for defining side B
* @param sideBEndVertex End vertex for defining side B
* @param sideCStartVertex Start vertex for defining side C
* @param sideCEndVertex End vertex for defining side C
*/ */
static void updateSidesBA() { static void updateSidesBA(const std::vector<cv::Point2f> &polygon,
unsigned int nrOfPoints, unsigned int a, unsigned int b,
unsigned int c, unsigned int &validationFlag,
cv::Point2f &sideAStartVertex, cv::Point2f &sideAEndVertex,
cv::Point2f &sideBStartVertex, cv::Point2f &sideBEndVertex,
const cv::Point2f &sideCStartVertex, const cv::Point2f &sideCEndVertex) {
// Side B is flush with edge [b, b-1] // Side B is flush with edge [b, b-1]
G_sideBStartVertex = G_polygon[predecessor(G_b)]; sideBStartVertex = polygon[predecessor(b, nrOfPoints)];
G_sideBEndVertex = G_polygon[G_b]; sideBEndVertex = polygon[b];
// Find middle point of side B // Find middle point of side B
cv::Point2f sideBMiddlePoint; cv::Point2f sideBMiddlePoint;
if ((middlePointOfSideB(sideBMiddlePoint)) && if ((middlePointOfSideB(sideBMiddlePoint, sideAStartVertex, sideAEndVertex, sideBStartVertex,
(height(sideBMiddlePoint) < height(predecessor(G_a)))) { sideBEndVertex, sideCStartVertex, sideCEndVertex)) &&
G_sideAStartVertex = G_polygon[predecessor(G_a)]; (height(sideBMiddlePoint, polygon, nrOfPoints, c) <
G_sideAEndVertex = findVertexCOnSideB(); height(predecessor(a, nrOfPoints), polygon, nrOfPoints, c))) {
sideAStartVertex = polygon[predecessor(a, nrOfPoints)];
sideAEndVertex = findVertexCOnSideB(polygon, nrOfPoints, a, c,
sideBStartVertex, sideBEndVertex,
sideCStartVertex, sideCEndVertex);
G_validationFlag = VALIDATION_SIDE_A_TANGENT; validationFlag = VALIDATION_SIDE_A_TANGENT;
} else { } else {
G_validationFlag = VALIDATION_SIDES_FLUSH; validationFlag = VALIDATION_SIDES_FLUSH;
} }
} }
//! Set side B if tangency for side B was obtained //! Set side B if tangency for side B was obtained
/*! /*!
* See paper [2] for more details * See paper [2] for more details
*
* @param polygon The polygon representing the convex hull of the points
* @param nrOfPoints Number of points defining the convex polygon
* @param a Index a
* @param b Index b
* @param c Index c
* @param validationFlag Flag used for validation
* @param sideBStartVertex Start vertex for defining side B
* @param sideBEndVertex End vertex for defining side B
*/ */
static void updateSideB() { static void updateSideB(const std::vector<cv::Point2f> &polygon,
if (!gamma(G_b, G_sideBStartVertex)) { unsigned int nrOfPoints, unsigned int a, unsigned int b,
unsigned int c, unsigned int &validationFlag,
cv::Point2f &sideBStartVertex, cv::Point2f &sideBEndVertex) {
if (!gamma(b, sideBStartVertex, polygon, nrOfPoints, a, c)) {
CV_Error(cv::Error::StsInternal, ERR_SIDE_B_GAMMA); CV_Error(cv::Error::StsInternal, ERR_SIDE_B_GAMMA);
} }
G_sideBEndVertex = G_polygon[G_b]; sideBEndVertex = polygon[b];
G_validationFlag = VALIDATION_SIDE_B_TANGENT; validationFlag = VALIDATION_SIDE_B_TANGENT;
} }
//! Update the triangle vertices after all sides were set and check if a local minimal triangle was found or not //! Update the triangle vertices after all sides were set and check if a local minimal triangle was found or not
/*! /*!
* See paper [2] for more details * See paper [2] for more details
*
* @param vertexA Vertex A of the enclosing triangle
* @param vertexB Vertex B of the enclosing triangle
* @param vertexC Vertex C of the enclosing triangle
* @param polygon The polygon representing the convex hull of the points
* @param nrOfPoints Number of points defining the convex polygon
* @param a Index a
* @param b Index b
* @param validationFlag Flag used for validation
* @param sideAStartVertex Start vertex for defining side A
* @param sideAEndVertex End vertex for defining side A
* @param sideBStartVertex Start vertex for defining side B
* @param sideBEndVertex End vertex for defining side B
* @param sideCStartVertex Start vertex for defining side C
* @param sideCEndVertex End vertex for defining side C
*/ */
static bool isLocalMinimalTriangle() { static bool isLocalMinimalTriangle(cv::Point2f &vertexA, cv::Point2f &vertexB,
if ((!lineIntersection(G_sideAStartVertex, G_sideAEndVertex, cv::Point2f &vertexC, const std::vector<cv::Point2f> &polygon,
G_sideBStartVertex, G_sideBEndVertex, G_vertexC)) || unsigned int nrOfPoints, unsigned int a, unsigned int b,
(!lineIntersection(G_sideAStartVertex, G_sideAEndVertex, unsigned int validationFlag, const cv::Point2f &sideAStartVertex,
G_sideCStartVertex, G_sideCEndVertex, G_vertexB)) || const cv::Point2f &sideAEndVertex, const cv::Point2f &sideBStartVertex,
(!lineIntersection(G_sideBStartVertex, G_sideBEndVertex, const cv::Point2f &sideBEndVertex, const cv::Point2f &sideCStartVertex,
G_sideCStartVertex, G_sideCEndVertex, G_vertexA))) { const cv::Point2f &sideCEndVertex) {
if ((!lineIntersection(sideAStartVertex, sideAEndVertex,
sideBStartVertex, sideBEndVertex, vertexC)) ||
(!lineIntersection(sideAStartVertex, sideAEndVertex,
sideCStartVertex, sideCEndVertex, vertexB)) ||
(!lineIntersection(sideBStartVertex, sideBEndVertex,
sideCStartVertex, sideCEndVertex, vertexA))) {
return false; return false;
} }
return isValidMinimalTriangle(); return isValidMinimalTriangle(vertexA, vertexB, vertexC, polygon, nrOfPoints, a, b,
validationFlag, sideAStartVertex, sideAEndVertex,
sideBStartVertex, sideBEndVertex, sideCStartVertex,
sideCEndVertex);
} }
//! Check if the found minimal triangle is valid //! Check if the found minimal triangle is valid
...@@ -529,21 +692,42 @@ static bool isLocalMinimalTriangle() { ...@@ -529,21 +692,42 @@ static bool isLocalMinimalTriangle() {
* This means that all midpoints of the triangle should touch the polygon * This means that all midpoints of the triangle should touch the polygon
* *
* See paper [2] for more details * See paper [2] for more details
*
* @param vertexA Vertex A of the enclosing triangle
* @param vertexB Vertex B of the enclosing triangle
* @param vertexC Vertex C of the enclosing triangle
* @param polygon The polygon representing the convex hull of the points
* @param nrOfPoints Number of points defining the convex polygon
* @param a Index a
* @param b Index b
* @param validationFlag Flag used for validation
* @param sideAStartVertex Start vertex for defining side A
* @param sideAEndVertex End vertex for defining side A
* @param sideBStartVertex Start vertex for defining side B
* @param sideBEndVertex End vertex for defining side B
* @param sideCStartVertex Start vertex for defining side C
* @param sideCEndVertex End vertex for defining side C
*/ */
static bool isValidMinimalTriangle() { static bool isValidMinimalTriangle(const cv::Point2f &vertexA, const cv::Point2f &vertexB,
cv::Point2f midpointSideA = middlePoint(G_vertexB, G_vertexC); const cv::Point2f &vertexC, const std::vector<cv::Point2f> &polygon,
cv::Point2f midpointSideB = middlePoint(G_vertexA, G_vertexC); unsigned int nrOfPoints, unsigned int a, unsigned int b,
cv::Point2f midpointSideC = middlePoint(G_vertexA, G_vertexB); unsigned int validationFlag, const cv::Point2f &sideAStartVertex,
const cv::Point2f &sideAEndVertex, const cv::Point2f &sideBStartVertex,
bool sideAValid = (G_validationFlag == VALIDATION_SIDE_A_TANGENT) const cv::Point2f &sideBEndVertex, const cv::Point2f &sideCStartVertex,
? (areEqualPoints(midpointSideA, G_polygon[predecessor(G_a)])) const cv::Point2f &sideCEndVertex) {
: (isPointOnLineSegment(midpointSideA, G_sideAStartVertex, G_sideAEndVertex)); cv::Point2f midpointSideA = middlePoint(vertexB, vertexC);
cv::Point2f midpointSideB = middlePoint(vertexA, vertexC);
bool sideBValid = (G_validationFlag == VALIDATION_SIDE_B_TANGENT) cv::Point2f midpointSideC = middlePoint(vertexA, vertexB);
? (areEqualPoints(midpointSideB, G_polygon[G_b]))
: (isPointOnLineSegment(midpointSideB, G_sideBStartVertex, G_sideBEndVertex)); bool sideAValid = (validationFlag == VALIDATION_SIDE_A_TANGENT)
? (areEqualPoints(midpointSideA, polygon[predecessor(a, nrOfPoints)]))
bool sideCValid = isPointOnLineSegment(midpointSideC, G_sideCStartVertex, G_sideCEndVertex); : (isPointOnLineSegment(midpointSideA, sideAStartVertex, sideAEndVertex));
bool sideBValid = (validationFlag == VALIDATION_SIDE_B_TANGENT)
? (areEqualPoints(midpointSideB, polygon[b]))
: (isPointOnLineSegment(midpointSideB, sideBStartVertex, sideBEndVertex));
bool sideCValid = isPointOnLineSegment(midpointSideC, sideCStartVertex, sideCEndVertex);
return (sideAValid && sideBValid && sideCValid); return (sideAValid && sideBValid && sideCValid);
} }
...@@ -552,27 +736,44 @@ static bool isValidMinimalTriangle() { ...@@ -552,27 +736,44 @@ static bool isValidMinimalTriangle() {
/*! /*!
* @param triangle Minimum area triangle enclosing the given polygon * @param triangle Minimum area triangle enclosing the given polygon
* @param area Area of the minimum area triangle enclosing the given polygon * @param area Area of the minimum area triangle enclosing the given polygon
* @param vertexA Vertex A of the enclosing triangle
* @param vertexB Vertex B of the enclosing triangle
* @param vertexC Vertex C of the enclosing triangle
*/ */
static void updateMinimumAreaEnclosingTriangle(std::vector<cv::Point2f> &triangle, double &area) { static void updateMinimumAreaEnclosingTriangle(std::vector<cv::Point2f> &triangle, double &area,
G_triangleArea = areaOfTriangle(G_vertexA, G_vertexB, G_vertexC); const cv::Point2f &vertexA, const cv::Point2f &vertexB,
const cv::Point2f &vertexC) {
double triangleArea = areaOfTriangle(vertexA, vertexB, vertexC);
if (G_triangleArea < area) { if (triangleArea < area) {
triangle.clear(); triangle.clear();
triangle.push_back(G_vertexA); triangle.push_back(vertexA);
triangle.push_back(G_vertexB); triangle.push_back(vertexB);
triangle.push_back(G_vertexC); triangle.push_back(vertexC);
area = G_triangleArea; area = triangleArea;
} }
} }
//! Return the middle point of side B //! Return the middle point of side B
static bool middlePointOfSideB(cv::Point2f& middlePointOfSideB) { /*!
* @param middlePointOfSideB Middle point of side B
* @param sideAStartVertex Start vertex for defining side A
* @param sideAEndVertex End vertex for defining side A
* @param sideBStartVertex Start vertex for defining side B
* @param sideBEndVertex End vertex for defining side B
* @param sideCStartVertex Start vertex for defining side C
* @param sideCEndVertex End vertex for defining side C
*/
static bool middlePointOfSideB(cv::Point2f &middlePointOfSideB, const cv::Point2f &sideAStartVertex,
const cv::Point2f &sideAEndVertex, const cv::Point2f &sideBStartVertex,
const cv::Point2f &sideBEndVertex, const cv::Point2f &sideCStartVertex,
const cv::Point2f &sideCEndVertex) {
cv::Point2f vertexA, vertexC; cv::Point2f vertexA, vertexC;
if ((!lineIntersection(G_sideBStartVertex, G_sideBEndVertex, G_sideCStartVertex, G_sideCEndVertex, vertexA)) || if ((!lineIntersection(sideBStartVertex, sideBEndVertex, sideCStartVertex, sideCEndVertex, vertexA)) ||
(!lineIntersection(G_sideBStartVertex, G_sideBEndVertex, G_sideAStartVertex, G_sideAEndVertex, vertexC))) { (!lineIntersection(sideBStartVertex, sideBEndVertex, sideAStartVertex, sideAEndVertex, vertexC))) {
return false; return false;
} }
...@@ -586,13 +787,18 @@ static bool middlePointOfSideB(cv::Point2f& middlePointOfSideB) { ...@@ -586,13 +787,18 @@ static bool middlePointOfSideB(cv::Point2f& middlePointOfSideB) {
* Check if the line determined by gammaPoint and polygon[polygonPointIndex] intersects * Check if the line determined by gammaPoint and polygon[polygonPointIndex] intersects
* the polygon below the point polygon[polygonPointIndex] * the polygon below the point polygon[polygonPointIndex]
* *
* @param gammaPoint Gamma(p) * @param gammaPoint Gamma(p)
* @param polygonPointIndex Index of the polygon point which is considered when determining the line * @param polygonPointIndex Index of the polygon point which is considered when determining the line
* @param polygon The polygon representing the convex hull of the points
* @param nrOfPoints Number of points defining the convex polygon
* @param c Index c
*/ */
static bool intersectsBelow(const cv::Point2f &gammaPoint, unsigned int polygonPointIndex) { static bool intersectsBelow(const cv::Point2f &gammaPoint, unsigned int polygonPointIndex,
double angleOfGammaAndPoint = angleOfLineWrtOxAxis(G_polygon[polygonPointIndex], gammaPoint); const std::vector<cv::Point2f> &polygon, unsigned int nrOfPoints,
unsigned int c) {
double angleOfGammaAndPoint = angleOfLineWrtOxAxis(polygon[polygonPointIndex], gammaPoint);
return (intersects(angleOfGammaAndPoint, polygonPointIndex) == INTERSECTS_BELOW); return (intersects(angleOfGammaAndPoint, polygonPointIndex, polygon, nrOfPoints, c) == INTERSECTS_BELOW);
} }
//! Check if the line intersects above //! Check if the line intersects above
...@@ -600,35 +806,47 @@ static bool intersectsBelow(const cv::Point2f &gammaPoint, unsigned int polygonP ...@@ -600,35 +806,47 @@ static bool intersectsBelow(const cv::Point2f &gammaPoint, unsigned int polygonP
* Check if the line determined by gammaPoint and polygon[polygonPointIndex] intersects * Check if the line determined by gammaPoint and polygon[polygonPointIndex] intersects
* the polygon above the point polygon[polygonPointIndex] * the polygon above the point polygon[polygonPointIndex]
* *
* @param gammaPoint Gamma(p) * @param gammaPoint Gamma(p)
* @param polygonPointIndex Index of the polygon point which is considered when determining the line * @param polygonPointIndex Index of the polygon point which is considered when determining the line
* @param polygon The polygon representing the convex hull of the points
* @param nrOfPoints Number of points defining the convex polygon
* @param c Index c
*/ */
static bool intersectsAbove(const cv::Point2f &gammaPoint, unsigned int polygonPointIndex) { static bool intersectsAbove(const cv::Point2f &gammaPoint, unsigned int polygonPointIndex,
double angleOfGammaAndPoint = angleOfLineWrtOxAxis(gammaPoint, G_polygon[polygonPointIndex]); const std::vector<cv::Point2f> &polygon, unsigned int nrOfPoints,
unsigned int c) {
double angleOfGammaAndPoint = angleOfLineWrtOxAxis(gammaPoint, polygon[polygonPointIndex]);
return (intersects(angleOfGammaAndPoint, polygonPointIndex) == INTERSECTS_ABOVE); return (intersects(angleOfGammaAndPoint, polygonPointIndex, polygon, nrOfPoints, c) == INTERSECTS_ABOVE);
} }
//! Check if/where the line determined by gammaPoint and polygon[polygonPointIndex] intersects the polygon //! Check if/where the line determined by gammaPoint and polygon[polygonPointIndex] intersects the polygon
/*! /*!
* @param angleGammaAndPoint Angle determined by gammaPoint and polygon[polygonPointIndex] wrt Ox axis * @param angleGammaAndPoint Angle determined by gammaPoint and polygon[polygonPointIndex] wrt Ox axis
* @param polygonPointIndex Index of the polygon point which is considered when determining the line * @param polygonPointIndex Index of the polygon point which is considered when determining the line
* @param polygon The polygon representing the convex hull of the points
* @param nrOfPoints Number of points defining the convex polygon
* @param c Index c
*/ */
static unsigned int intersects(double angleGammaAndPoint, unsigned int polygonPointIndex) { static unsigned int intersects(double angleGammaAndPoint, unsigned int polygonPointIndex,
double anglePointPredecessor = angleOfLineWrtOxAxis(G_polygon[predecessor(polygonPointIndex)], const std::vector<cv::Point2f> &polygon, unsigned int nrOfPoints,
G_polygon[polygonPointIndex]); unsigned int c) {
double anglePointSuccessor = angleOfLineWrtOxAxis(G_polygon[successor(polygonPointIndex)], double anglePointPredecessor = angleOfLineWrtOxAxis(polygon[predecessor(polygonPointIndex, nrOfPoints)],
G_polygon[polygonPointIndex]); polygon[polygonPointIndex]);
double angleFlushEdge = angleOfLineWrtOxAxis(G_polygon[predecessor(G_c)], double anglePointSuccessor = angleOfLineWrtOxAxis(polygon[successor(polygonPointIndex, nrOfPoints)],
G_polygon[G_c]); polygon[polygonPointIndex]);
double angleFlushEdge = angleOfLineWrtOxAxis(polygon[predecessor(c, nrOfPoints)],
polygon[c]);
if (isFlushAngleBtwPredAndSucc(angleFlushEdge, anglePointPredecessor, anglePointSuccessor)) { if (isFlushAngleBtwPredAndSucc(angleFlushEdge, anglePointPredecessor, anglePointSuccessor)) {
if ((isGammaAngleBtw(angleGammaAndPoint, anglePointPredecessor, angleFlushEdge)) || if ((isGammaAngleBtw(angleGammaAndPoint, anglePointPredecessor, angleFlushEdge)) ||
(almostEqual(angleGammaAndPoint, anglePointPredecessor))) { (almostEqual(angleGammaAndPoint, anglePointPredecessor))) {
return intersectsAboveOrBelow(predecessor(polygonPointIndex), polygonPointIndex); return intersectsAboveOrBelow(predecessor(polygonPointIndex, nrOfPoints),
polygonPointIndex, polygon, nrOfPoints, c);
} else if ((isGammaAngleBtw(angleGammaAndPoint, anglePointSuccessor, angleFlushEdge)) || } else if ((isGammaAngleBtw(angleGammaAndPoint, anglePointSuccessor, angleFlushEdge)) ||
(almostEqual(angleGammaAndPoint, anglePointSuccessor))) { (almostEqual(angleGammaAndPoint, anglePointSuccessor))) {
return intersectsAboveOrBelow(successor(polygonPointIndex), polygonPointIndex); return intersectsAboveOrBelow(successor(polygonPointIndex, nrOfPoints),
polygonPointIndex, polygon, nrOfPoints, c);
} }
} else { } else {
if ( if (
...@@ -653,9 +871,14 @@ static unsigned int intersects(double angleGammaAndPoint, unsigned int polygonPo ...@@ -653,9 +871,14 @@ static unsigned int intersects(double angleGammaAndPoint, unsigned int polygonPo
/*! /*!
* @param succPredIndex Index of the successor or predecessor * @param succPredIndex Index of the successor or predecessor
* @param pointIndex Index of the point x in the polygon * @param pointIndex Index of the point x in the polygon
* @param polygon The polygon representing the convex hull of the points
* @param nrOfPoints Number of points defining the convex polygon
* @param c Index c
*/ */
static unsigned int intersectsAboveOrBelow(unsigned int succPredIndex, unsigned int pointIndex) { static unsigned int intersectsAboveOrBelow(unsigned int succPredIndex, unsigned int pointIndex,
if (height(succPredIndex) > height(pointIndex)) { const std::vector<cv::Point2f> &polygon,
unsigned int nrOfPoints, unsigned int c) {
if (height(succPredIndex, polygon, nrOfPoints, c) > height(pointIndex, polygon, nrOfPoints, c)) {
return INTERSECTS_ABOVE; return INTERSECTS_ABOVE;
} else { } else {
return INTERSECTS_BELOW; return INTERSECTS_BELOW;
...@@ -677,20 +900,27 @@ static unsigned int intersectsAboveOrBelow(unsigned int succPredIndex, unsigned ...@@ -677,20 +900,27 @@ static unsigned int intersectsAboveOrBelow(unsigned int succPredIndex, unsigned
* *
* @param polygonPointIndex Index of the polygon point * @param polygonPointIndex Index of the polygon point
* @param gammaPoint Point gamma(polygon[polygonPointIndex]) * @param gammaPoint Point gamma(polygon[polygonPointIndex])
* @param polygon The polygon representing the convex hull of the points
* @param nrOfPoints Number of points defining the convex polygon
* @param a Index a
* @param c Index c
*/ */
static bool gamma(unsigned int polygonPointIndex, cv::Point2f &gammaPoint) { static bool gamma(unsigned int polygonPointIndex, cv::Point2f &gammaPoint,
const std::vector<cv::Point2f> &polygon, unsigned int nrOfPoints,
unsigned int a, unsigned int c) {
cv::Point2f intersectionPoint1, intersectionPoint2; cv::Point2f intersectionPoint1, intersectionPoint2;
// Get intersection points if they exist // Get intersection points if they exist
if (!findGammaIntersectionPoints(polygonPointIndex, G_polygon[G_a], G_polygon[predecessor(G_a)], if (!findGammaIntersectionPoints(polygon, nrOfPoints, c, polygonPointIndex,
G_polygon[G_c], G_polygon[predecessor(G_c)], polygon[a], polygon[predecessor(a, nrOfPoints)],
polygon[c], polygon[predecessor(c, nrOfPoints)],
intersectionPoint1, intersectionPoint2)) { intersectionPoint1, intersectionPoint2)) {
return false; return false;
} }
// Select the point which is on the same side of line C as the polygon // Select the point which is on the same side of line C as the polygon
if (areOnTheSameSideOfLine(intersectionPoint1, G_polygon[successor(G_c)], if (areOnTheSameSideOfLine(intersectionPoint1, polygon[successor(c, nrOfPoints)],
G_polygon[G_c], G_polygon[predecessor(G_c)])) { polygon[c], polygon[predecessor(c, nrOfPoints)])) {
gammaPoint = intersectionPoint1; gammaPoint = intersectionPoint1;
} else { } else {
gammaPoint = intersectionPoint2; gammaPoint = intersectionPoint2;
...@@ -699,25 +929,73 @@ static bool gamma(unsigned int polygonPointIndex, cv::Point2f &gammaPoint) { ...@@ -699,25 +929,73 @@ static bool gamma(unsigned int polygonPointIndex, cv::Point2f &gammaPoint) {
return true; return true;
} }
//! Find vertex C which lies on side B at a distance = 2 * height(a-1) from side C
/*!
* Considering that line (x y) is a line parallel to (c c-1) and that the distance between the lines is equal
* to 2 * height(a-1), we can have two possible (x y) lines.
*
* Therefore, we will compute two intersection points between the lines (x y) and (b b-1) and take the
* point which is on the same side of line (c c-1) as the polygon.
*
* See paper [2] and formula for distance from point to a line for more details
*
* @param polygon The polygon representing the convex hull of the points
* @param nrOfPoints Number of points defining the convex polygon
* @param a Index a
* @param c Index c
* @param sideBStartVertex Start vertex for defining side B
* @param sideBEndVertex End vertex for defining side B
* @param sideCStartVertex Start vertex for defining side C
* @param sideCEndVertex End vertex for defining side C
*/
static cv::Point2f findVertexCOnSideB(const std::vector<cv::Point2f> &polygon, unsigned int nrOfPoints,
unsigned int a, unsigned int c,
const cv::Point2f &sideBStartVertex,
const cv::Point2f &sideBEndVertex,
const cv::Point2f &sideCStartVertex,
const cv::Point2f &sideCEndVertex) {
cv::Point2f intersectionPoint1, intersectionPoint2;
// Get intersection points if they exist
if (!findGammaIntersectionPoints(polygon, nrOfPoints, c, predecessor(a, nrOfPoints),
sideBStartVertex, sideBEndVertex,
sideCStartVertex, sideCEndVertex,
intersectionPoint1, intersectionPoint2)) {
CV_Error(cv::Error::StsInternal, ERR_VERTEX_C_ON_SIDE_B);
}
// Select the point which is on the same side of line C as the polygon
if (areOnTheSameSideOfLine(intersectionPoint1, polygon[successor(c, nrOfPoints)],
polygon[c], polygon[predecessor(c, nrOfPoints)])) {
return intersectionPoint1;
} else {
return intersectionPoint2;
}
}
//! Find the intersection points to compute gamma(point) //! Find the intersection points to compute gamma(point)
/*! /*!
* @param polygonPointIndex Index of the polygon point for which the distance is known * @param polygon The polygon representing the convex hull of the points
* @param side1StartVertex Start vertex for side 1 * @param nrOfPoints Number of points defining the convex polygon
* @param side1EndVertex End vertex for side 1 * @param c Index c
* @param side2StartVertex Start vertex for side 2 * @param polygonPointIndex Index of the polygon point for which the distance is known
* @param side2EndVertex End vertex for side 2 * @param side1StartVertex Start vertex for side 1
* @param intersectionPoint1 First intersection point between one pair of lines * @param side1EndVertex End vertex for side 1
* @param intersectionPoint2 Second intersection point between other pair of lines * @param side2StartVertex Start vertex for side 2
* @param side2EndVertex End vertex for side 2
* @param intersectionPoint1 First intersection point between one pair of lines
* @param intersectionPoint2 Second intersection point between other pair of lines
*/ */
static bool findGammaIntersectionPoints(unsigned int polygonPointIndex, const cv::Point2f &side1StartVertex, static bool findGammaIntersectionPoints(const std::vector<cv::Point2f> &polygon, unsigned int nrOfPoints,
const cv::Point2f &side1EndVertex, const cv::Point2f &side2StartVertex, unsigned int c, unsigned int polygonPointIndex,
const cv::Point2f &side2EndVertex, cv::Point2f &intersectionPoint1, const cv::Point2f &side1StartVertex, const cv::Point2f &side1EndVertex,
cv::Point2f &intersectionPoint2) { const cv::Point2f &side2StartVertex, const cv::Point2f &side2EndVertex,
cv::Point2f &intersectionPoint1, cv::Point2f &intersectionPoint2) {
std::vector<double> side1Params = lineEquationParameters(side1StartVertex, side1EndVertex); std::vector<double> side1Params = lineEquationParameters(side1StartVertex, side1EndVertex);
std::vector<double> side2Params = lineEquationParameters(side2StartVertex, side2EndVertex); std::vector<double> side2Params = lineEquationParameters(side2StartVertex, side2EndVertex);
// Compute side C extra parameter using the formula for distance from a point to a line // Compute side C extra parameter using the formula for distance from a point to a line
double polygonPointHeight = height(polygonPointIndex); double polygonPointHeight = height(polygonPointIndex, polygon, nrOfPoints, c);
double distFormulaDenom = sqrt((side2Params[0] * side2Params[0]) + (side2Params[1] * side2Params[1])); double distFormulaDenom = sqrt((side2Params[0] * side2Params[0]) + (side2Params[1] * side2Params[1]));
double sideCExtraParam = 2 * polygonPointHeight * distFormulaDenom; double sideCExtraParam = 2 * polygonPointHeight * distFormulaDenom;
...@@ -801,44 +1079,19 @@ static std::vector<double> lineEquationParameters(const cv::Point2f& p, const cv ...@@ -801,44 +1079,19 @@ static std::vector<double> lineEquationParameters(const cv::Point2f& p, const cv
return lineEquationParameters; return lineEquationParameters;
} }
//! Find vertex C which lies on side B at a distance = 2 * height(a-1) from side C
/*!
* Considering that line (x y) is a line parallel to (c c-1) and that the distance between the lines is equal
* to 2 * height(a-1), we can have two possible (x y) lines.
*
* Therefore, we will compute two intersection points between the lines (x y) and (b b-1) and take the
* point which is on the same side of line (c c-1) as the polygon.
*
* See paper [2] and formula for distance from point to a line for more details
*/
static cv::Point2f findVertexCOnSideB() {
cv::Point2f intersectionPoint1, intersectionPoint2;
// Get intersection points if they exist
if (!findGammaIntersectionPoints(predecessor(G_a), G_sideBStartVertex, G_sideBEndVertex,
G_sideCStartVertex, G_sideCEndVertex,
intersectionPoint1, intersectionPoint2)) {
CV_Error(cv::Error::StsInternal, ERR_VERTEX_C_ON_SIDE_B);
}
// Select the point which is on the same side of line C as the polygon
if (areOnTheSameSideOfLine(intersectionPoint1, G_polygon[successor(G_c)],
G_polygon[G_c], G_polygon[predecessor(G_c)])) {
return intersectionPoint1;
} else {
return intersectionPoint2;
}
}
//! Compute the height of the point //! Compute the height of the point
/*! /*!
* See paper [2] for more details * See paper [2] for more details
* *
* @param polygonPoint Polygon point * @param polygonPoint Polygon point
* @param polygon The polygon representing the convex hull of the points
* @param nrOfPoints Number of points defining the convex polygon
* @param c Index c
*/ */
static double height(const cv::Point2f &polygonPoint) { static double height(const cv::Point2f &polygonPoint, const std::vector<cv::Point2f> &polygon,
cv::Point2f pointC = G_polygon[G_c]; unsigned int nrOfPoints, unsigned int c) {
cv::Point2f pointCPredecessor = G_polygon[predecessor(G_c)]; cv::Point2f pointC = polygon[c];
cv::Point2f pointCPredecessor = polygon[predecessor(c, nrOfPoints)];
return distanceFromPointToLine(polygonPoint, pointC, pointCPredecessor); return distanceFromPointToLine(polygonPoint, pointC, pointCPredecessor);
} }
...@@ -847,23 +1100,28 @@ static double height(const cv::Point2f &polygonPoint) { ...@@ -847,23 +1100,28 @@ static double height(const cv::Point2f &polygonPoint) {
/*! /*!
* See paper [2] for more details * See paper [2] for more details
* *
* @param polygonPointIndex Index of the polygon point * @param polygonPointIndex Index of the polygon point
* @param polygon The polygon representing the convex hull of the points
* @param nrOfPoints Number of points defining the convex polygon
* @param c Index c
*/ */
static double height(unsigned int polygonPointIndex) { static double height(unsigned int polygonPointIndex, const std::vector<cv::Point2f> &polygon,
cv::Point2f pointC = G_polygon[G_c]; unsigned int nrOfPoints, unsigned int c) {
cv::Point2f pointCPredecessor = G_polygon[predecessor(G_c)]; cv::Point2f pointC = polygon[c];
cv::Point2f pointCPredecessor = polygon[predecessor(c, nrOfPoints)];
cv::Point2f polygonPoint = G_polygon[polygonPointIndex]; cv::Point2f polygonPoint = polygon[polygonPointIndex];
return distanceFromPointToLine(polygonPoint, pointC, pointCPredecessor); return distanceFromPointToLine(polygonPoint, pointC, pointCPredecessor);
} }
//! Advance the given index with one position //! Advance the given index with one position
/*! /*!
* @param index Index of the point * @param index Index of the point
* @param nrOfPoints Number of points defining the convex polygon
*/ */
static void advance(unsigned int &index) { static void advance(unsigned int &index, unsigned int nrOfPoints) {
index = successor(index); index = successor(index, nrOfPoints);
} }
//! Return the succesor of the provided point index //! Return the succesor of the provided point index
...@@ -871,10 +1129,11 @@ static void advance(unsigned int &index) { ...@@ -871,10 +1129,11 @@ static void advance(unsigned int &index) {
* The succesor of the last polygon point is the first polygon point * The succesor of the last polygon point is the first polygon point
* (circular referencing) * (circular referencing)
* *
* @param index Index of the point * @param index Index of the point
* @param nrOfPoints Number of points defining the convex polygon
*/ */
static unsigned int successor(unsigned int index) { static unsigned int successor(unsigned int index, unsigned int nrOfPoints) {
return ((index + 1) % G_nrOfPoints); return ((index + 1) % nrOfPoints);
} }
//! Return the predecessor of the provided point index //! Return the predecessor of the provided point index
...@@ -882,10 +1141,11 @@ static unsigned int successor(unsigned int index) { ...@@ -882,10 +1141,11 @@ static unsigned int successor(unsigned int index) {
* The predecessor of the first polygon point is the last polygon point * The predecessor of the first polygon point is the last polygon point
* (circular referencing) * (circular referencing)
* *
* @param index Index of the point * @param index Index of the point
* @param nrOfPoints Number of points defining the convex polygon
*/ */
static unsigned int predecessor(unsigned int index) { static unsigned int predecessor(unsigned int index, unsigned int nrOfPoints) {
return (index == 0) ? (G_nrOfPoints - 1) return (index == 0) ? (nrOfPoints - 1)
: (index - 1); : (index - 1);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment