unsigned short PointFacePosition:: getPointFacePosition ( const Point3DCartesian <T> * q, const Face <T> *face ) { /*Returns position of the point to the Face 0: q is strictly interior 1: q is strictly exterior 2: q is on the edge but not an endpoint 3: q is a vertex */ //There is a valid Face if ( face != NULL ) { unsigned short l_inters = 0, r_inters = 0; HalfEdge <T> *e = face->getHalfEdge(); const HalfEdge <T> *e_start = e; //Get point P[i-1] const Node3DCartesian <T> *pi1 = e->getPreviousEdge()->getPoint(); //Process all edges do { //Get point P[i] const Node3DCartesian <T> *pi = e->getPoint(); //Test point is identical with end points: d(q, pi) < POSITION_ROUND_ERROR if ( ( q->getX() - pi->getX() ) * ( q->getX() - pi->getX() ) + ( q->getY() - pi->getY() ) * ( q->getY() - pi->getY() ) < POSITION_ROUND_ERROR * POSITION_ROUND_ERROR ) { return 3; } //Perform tests: different position of segment end points to ray bool t1 = ( pi->getY() > q->getY() + POSITION_ROUND_ERROR ) != ( pi1->getY() > q->getY() + POSITION_ROUND_ERROR ); bool t2 = ( pi->getY() < q->getY() - POSITION_ROUND_ERROR ) != ( pi1->getY() < q->getY() - POSITION_ROUND_ERROR ); //Segment intersects left or ray if ( t1 || t2 ) { //Compute intersection T x = ( ( pi->getX() - q->getX() ) * ( pi1->getY() - q->getY() ) - ( pi1->getX() - q->getX() ) * ( pi->getY() - q->getY() ) ) / double ( ( pi1->getY() - pi->getY() ) ); //Aditional test to avoid roundness error: point too close to edge if ( PointLineDistance::getPointLineSegmentDistance2D ( q, pi, pi1 ) < POSITION_ROUND_ERROR ) { return 2; } //Increment number of right intersections if ( t1 && x > 0 ) { r_inters ++; } //Increment number of left intersections if ( t2 && x < 0 ) { l_inters ++; } } //Assign point pi1 = pi; //Increment edge e = e->getNextEdge(); } while ( e != e_start ); //Point lies on the edge, but not at endpoints if ( ( l_inters % 2 ) != ( r_inters % 2 ) ) { return 2; } //Points is strictly interior if ( l_inters % 2 == 1 ) { return 0; } //Point is strictly exterior return 1; } //Throw exception else { throw ErrorBadData ( "ErrorBadData: no face incident to edge, ", "can not test point vs. face position" ); } }
void TangentFunction::computeTangentFunctionFace ( const Face <T> *face, typename TTangentFunction <T>::Type & tf, T & rotation, const TTangentFunctionRotationMethod & rotation_method, const TTangentFunctionScaleMethod & scale_method ) { //Compute normalized tangent function for the Face given by HalfEdge T turning_angle_sum = 0, normalize_length_sum = 0; const HalfEdge <T> *e_start = face->getHalfEdge(); HalfEdge <T> *e = const_cast <HalfEdge <T> *> ( e_start ) ; //Get triplet of points Node3DCartesian <T> *pi, *piii = NULL; Node3DCartesian <T> *pii = e_start->getPoint(); //Jump short segments for ( pi = e->getPreviousEdge()->getPoint(); EuclDistance::getEuclDistance2D ( pi, pii ) < MIN_POSITION_DIFF ; e = e->getPreviousEdge(), pi = e->getPreviousEdge()->getPoint() ) {} //Get third point for initial edge for ( piii = e->getNextEdge()->getPoint(); EuclDistance::getEuclDistance2D ( pii, piii ) < MIN_POSITION_DIFF ; e = e->getNextEdge(), piii = e->getNextEdge()->getPoint() ) {} //Compute perimeter of the Face const T face_perimeter = FacePerimeter::getFacePerimeter ( e_start ); //Throw exception if ( face_perimeter == 0 ) { throw ErrorMathZeroDevision <T> ( "ErrorMathZeroDevision: tangent function, can not normalize function (1 / perimeter), ", "perimeter = 0." ); } //Compute initial angle: rotation invariant if ( rotation_method == RotationInvariant ) { turning_angle_sum += 180 - Angle3Points::getAngle3Points ( pi, pii, piii ); } //Compute initial angle: rotation dependent (do not compute the sum) else { turning_angle_sum = 360 - Angle3Points::getAngle3Points ( &Node3DCartesian <T> ( pii->getX() - 1, pii->getY() ), pii, piii ); } //Add turning angle computed for normalized length of initial edge to map tf[normalize_length_sum] = turning_angle_sum; //Assign points from initial edge pi = pii; pii = piii; //Increment initial edge e = e_start->getNextEdge(); //Process all edges of the Face (2, n-1) do { //Get third point piii = e->getNextEdge()->getPoint(); //Segment is too short if ( EuclDistance::getEuclDistance2D ( pii, piii ) > MIN_POSITION_DIFF ) { //Compute angle: rotation invariant if ( rotation_method == RotationInvariant ) { turning_angle_sum += 180 - Angle3Points::getAngle3Points ( pi, pii, piii ); } //Compute initial angle: rotation dependent (do not compute the sum) else { turning_angle_sum = 360 - Angle3Points::getAngle3Points ( &Node3DCartesian <T> ( pii->getX() - 1, pii->getY() ), pii, piii ); } //Compute normalized length sum normalize_length_sum += ( scale_method == ScaleDependent ? EuclDistance::getEuclDistance2D ( pi, pii ) / face_perimeter : EuclDistance::getEuclDistance2D ( pi, pii ) ); //Add turning angle computed for normalized length to map tf[normalize_length_sum] = turning_angle_sum; //Assign points pi = pii; pii = piii; } //Increment edge e = e->getNextEdge(); } while ( e != e_start ); //Add last value: we visit first point again const T last = ( scale_method == ScaleDependent ? 1.0 : face_perimeter ); if ( rotation_method == RotationInvariant ) { tf[ last] = turning_angle_sum + tf.begin()->second; } else { tf[last] = tf.begin()->second; } }
void TurningFunction::computeTurningFunctionFace ( const Face <T> *face, typename TTurningFunction <T>::Type & tf, T & rotation, const TTurningFunctionRotationMethod & rotation_method, const TTurningFunctionScaleMethod & scale_method ) { //Compute normalized turning function for the Face given by HalfEdge T turning_angle_sum = 0, normalize_length_sum = 0; const HalfEdge <T> *e_start = face->getHalfEdge(); HalfEdge <T> *e = const_cast <HalfEdge <T> *> ( e_start ) ; //Get triplet of points Node3DCartesian <T> *pi, *piii = NULL; Node3DCartesian <T> *pii = e_start->getPoint(); //Jump short segments for ( pi = e->getPreviousEdge()->getPoint(); EuclDistance::getEuclDistance2D ( pi->getX(), pi->getY(), pii->getX(), pii->getY() ) < MIN_POSITION_DIFF ; e = e->getPreviousEdge(), pi = e->getPreviousEdge()->getPoint() ); //Get third point for initial edge for ( piii = e->getNextEdge()->getPoint(); EuclDistance::getEuclDistance2D ( pii->getX(), pii->getY(), piii->getX(), piii->getY() ) < MIN_POSITION_DIFF ; e = e->getNextEdge(), piii = e->getNextEdge()->getPoint() ); //Compute perimeter of the Face const T face_perimeter = FacePerimeter::getFacePerimeter ( e_start ); //Throw exception if ( fabs ( face_perimeter ) < MIN_FLOAT ) { throw MathZeroDevisionException <T> ( "MathZeroDevisionException: turning function, can not normalize function (1 / perimeter), ", "perimeter = 0.", face_perimeter ); } //Compute initial angle: rotation invariant if ( rotation_method == RotationInvariant ) { turning_angle_sum += 180 - Angle3Points::getAngle3Points ( pi, pii, piii ); } //Compute initial angle: rotation dependent (do not compute the sum) else { //Create temporary point P (x_temp, y_temp) on x axis const T dx = std::max ( fabs ( piii->getX() - pii->getX() ), fabs ( piii->getY() - pii->getY() ) ); Node3DCartesian <T> n_temp ( pii->getX() - 2 * dx , pii->getY() ); turning_angle_sum += Bearing::getBearing ( pii, &n_temp ); } //Add turning angle computed for normalized length of initial edge to map tf[normalize_length_sum] = turning_angle_sum; //Assign points from initial edge pi = pii; pii = piii; //Increment initial edge e = e_start->getNextEdge(); //Process all edges of the Face (2, n-1) do { //Get third point piii = e->getNextEdge()->getPoint(); //Segment is too short if ( EuclDistance::getEuclDistance2D ( pii->getX(), pii->getY(), piii->getX(), piii->getY() ) > MIN_POSITION_DIFF ) { //Compute angle: rotation invariant turning_angle_sum += 180.0 - Angle3Points::getAngle3Points ( pi, pii, piii ); //Compute normalized length sum normalize_length_sum += ( scale_method == ScaleInvariant ? EuclDistance::getEuclDistance2D ( pi->getX(), pi->getY(), pii->getX(), pii->getY() ) / face_perimeter : EuclDistance::getEuclDistance2D ( pi->getX(), pi->getY(), pii->getX(), pii->getY() ) ); //Add turning angle computed for normalized length to map tf[normalize_length_sum] = turning_angle_sum; //Assign points pi = pii; pii = piii; } //Increment edge e = e->getNextEdge(); } while ( e != e_start ); //Add last value: we visit first point again const T last_key = ( scale_method == ScaleInvariant ? 1.0 : face_perimeter ); tf[last_key] = ( rotation_method == RotationInvariant ? turning_angle_sum + tf.begin()->second : tf.begin()->second ); }