/*! */ Vector2D Segment2D::intersection( const Segment2D & other, const bool allow_end_point ) const { Vector2D sol = this->line().intersection( other.line() ); if ( ! sol.isValid() || ! this->contains( sol ) || ! other.contains( sol ) ) { return Vector2D::INVALIDATED; } if ( ! allow_end_point && ! existIntersectionExceptEndpoint( other ) ) { return Vector2D::INVALIDATED; } return sol; #if 0 // Following algorithm seems faster ther above. // In fact, the following algorithm slower... Vector2D ab = terminal() - origin(); Vector2D dc = other.origin() - other.terminal(); Vector2D ad = other.terminal() - origin(); double det = dc.outerProduct( ab ); if ( std::fabs( det ) < 1.0e-9 ) { // area size is 0. // segments has same slope. std::cerr << "Segment2D::intersection()" << " ***ERROR*** parallel segments" << std::endl; return Vector2D::INVALIDATED; } double s = ( dc.x * ad.y - dc.y * ad.x ) / det; double t = ( ab.x * ad.y - ab.y * ad.x ) / det; if ( s < 0.0 || 1.0 < s || t < 0.0 || 1.0 < t ) { return Vector2D::INVALIDATED; } return Vector2D( origin().x + ab.x * s, origin().y + ab.y * s ); #endif }
/*! */ void ConvexHull::computeDirectMethod() { clearResults(); const size_t point_size = M_input_points.size(); if ( point_size < 3 ) { return; } for ( size_t i = 0; i < point_size - 1; ++i ) { const Vector2D & p = M_input_points[i]; for ( size_t j = i + 1; j < point_size; ++j ) { const Vector2D & q = M_input_points[j]; const Vector2D rel = q - p; bool valid = true; double last_value = 0.0; for ( size_t k = 0; k < point_size; ++k ) { if ( k == i || k == j ) continue; const Vector2D & r = M_input_points[k]; double outer_prod = rel.outerProduct( r - p ); if ( std::fabs( outer_prod ) < 1.0e-6 ) { // point is on the line if ( ( r - p ).r2() < rel.r2() ) { // point is on the segment valid = false; break; } } if ( ( outer_prod > 0.0 && last_value < 0.0 ) || ( outer_prod < 0.0 && last_value > 0.0 ) ) { // point exists in the opposite side valid = false; break; } last_value = outer_prod; } if ( valid ) { M_vertices.push_back( p ); M_vertices.push_back( q ); if ( last_value < 0.0 ) { M_edges.push_back( Segment2D( p, q ) ); } else { M_edges.push_back( Segment2D( q, p ) ); } } } } // sort vertices by counter clockwise order if ( ! M_vertices.empty() ) { std::sort( M_vertices.begin() + 1, M_vertices.end(), AngleSortPredicate( M_vertices.front() ) ); M_vertices.erase( std::unique( M_vertices.begin(), M_vertices.end(), Vector2D::Equal() ), M_vertices.end() ); } }