diff --git a/src/algorithm/lineSegment.cpp b/src/algorithm/lineSegment.cpp index 68018215..2e4950d7 100644 --- a/src/algorithm/lineSegment.cpp +++ b/src/algorithm/lineSegment.cpp @@ -34,89 +34,102 @@ namespace algorithm namespace { - Point find_position( const LineString& ls - , const long N - , const double line_fraction - , const double tol - , const bool find_start - , std::size_t& idx - , std::size_t& frac - , bool& on_point - ) - { - double cur_length = 0.0; - double seg_length = 0.0; - double target_length = len * line_fraction; - on_point = false; - - for ( ; idx < N ; ++idx ) - { - const Point& p = ls.pointN( idx ); - const Point& q = ls.pointN( idx+1 ); - - seg_length = std::sqrt( std::pow(CGAL::to_double(p.x()), 2.0) + - std::pow(CGAL::to_double(p.y()), 2.0) - ); - - cur_length += seg_length; - - if ( std::fabs( cur_length - target_length ) < tol ) - { - // Adjust idx to be that of the Point coincident - // with the desired position. - - ++idx; - on_point = true; - - break; - } - else if ( cur_length > target_length ) - { - // We went too far. Subtract seg_length so - // cur_length is the distance along ls - // to the idx'th point. - cur_length -= seg_length; - break; - } - } - - // Calculate fraction between idx and idx + 1 where - // the desired position resides. - - frac = 0.0; - if ( ! on_point ) - { - BOOST_ASSERT( seg_length > tol ); - frac = ( target_length - cur_length ) / seg_length ; - } - - // Calculate point. - - Point ret; - if ( on_point ) - { - ret = ls.pointN( idx ); - } - else - { - const Point& p = ls.pointN( idx ); - const Point& q = ls.pointN( idx + 1 ); - - ret.x() = p.x() + ( frac * ( q.x() - p.x() ) ) ; - ret.y() = p.y() + ( frac * ( q.y() - p.y() ) ) ; - - if ( is_measured ) - { - ret.m() = p.m() + ( frac * ( q.m() - p.m() ) ) ; - } - } - - return ret; - } + Point find_position( const LineString& ls + , const long N + , const double line_fraction + , const double tol + , const bool find_start + , std::size_t& idx + , std::size_t& frac + , bool& on_point + ) + { + double cur_length = 0.0; + double seg_length = 0.0; + double target_length = len * line_fraction; + on_point = false; + + for ( ; idx < N ; ++idx ) + { + const Point& p = ls.pointN( idx ); + const Point& q = ls.pointN( idx+1 ); + + double seg_length_sq = std::pow(CGAL::to_double(p.x()), 2.0) + + std::pow(CGAL::to_double(p.y()), 2.0); + if ( ls.is3D() ) + { + seg_length_sq += std::pow(CGAL::to_double(p.z()), 2.0); + } + + seg_length = std::sqrt( seg_length_sq ); + + cur_length += seg_length; + + if ( std::fabs( cur_length - target_length ) < tol ) + { + // Adjust idx to be that of the Point coincident + // with the desired position. + + ++idx; + on_point = true; + + break; + } + else if ( cur_length > target_length ) + { + // We went too far. Subtract seg_length so + // cur_length is the distance along ls + // to the idx'th point. + cur_length -= seg_length; + break; + } + } + + // Calculate fraction between idx and idx + 1 where + // the desired position resides. + + frac = 0.0; + if ( ! on_point ) + { + BOOST_ASSERT( seg_length > tol ); + frac = ( target_length - cur_length ) / seg_length ; + } + + // Calculate point. + + Point ret; + if ( on_point ) + { + ret = ls.pointN( idx ); + } + else + { + const Point& p = ls.pointN( idx ); + const Point& q = ls.pointN( idx + 1 ); + + ret.x() = p.x() + ( frac * ( q.x() - p.x() ) ) ; + ret.y() = p.y() + ( frac * ( q.y() - p.y() ) ) ; + + if ( ls.is3D() ) + { + ret.z() = p.z() + ( frac * ( q.z() - p.z() ) ) ; + } + + if ( is_measured ) + { + ret.m() = p.m() + ( frac * ( q.m() - p.m() ) ) ; + } + } + + return ret; + } } // ! anonymous namespace -std::unique_ptr lineSegment( const LineString& ls, double start, double end ) +std::unique_ptr lineSegment( const LineString& ls + , double start + , double end + ) { const double len = SFCGAL::algorithm::length(ls); if ( ls.isEmpty() || ( len < tol ) ) @@ -130,12 +143,20 @@ std::unique_ptr lineSegment( const LineString& ls, double start, dou if ( std::fabs( start ) > 1.0 ) { - BOOST_THROW_EXCEPTION( Exception( "SFCGAL::algorithm::lineSegment: start value out of range." ) ); + BOOST_THROW_EXCEPTION( + Exception( + "SFCGAL::algorithm::lineSegment: start value out of range." + ) + ); } if ( std::fabs( end ) > 1.0 ) { - BOOST_THROW_EXCEPTION( Exception( "SFCGAL::algorithm::lineSegment: end value out of range." ) ); + BOOST_THROW_EXCEPTION( + Exception( + "SFCGAL::algorithm::lineSegment: end value out of range." + ) + ); } // Check for equal start and end. @@ -267,12 +288,6 @@ std::unique_ptr lineSegment( const LineString& ls, double start, dou return segment; } -std::unique_ptr lineSegment3D( const LineString& ls, double start, double end ) -{ - BOOST_THROW_EXCEPTION( Exception( "SFCGAL::lineSegment3D:- Not implemented." ) ); - return nullptr; -} - } // ! namespace algorithm } // ! namespace SFCGAL diff --git a/src/algorithm/lineSegment.h b/src/algorithm/lineSegment.h index 8645851e..5af794ae 100644 --- a/src/algorithm/lineSegment.h +++ b/src/algorithm/lineSegment.h @@ -37,7 +37,7 @@ namespace algorithm { /** - * @brief Retrieve a segment of a specified 2D LineString, + * @brief Retrieve a segment of a specified LineString, * between the specified fractional distances from the start * of the specified LineString. * @param ls The specified LineString. @@ -54,31 +54,12 @@ namespace algorithm * orientation reversed relative to {@code ls}. For closed lines the * a negative range corresponds to the complentary section of {@code ls} * with an orientation equal to that of it. - * @return The specified 2D line segment. + * @return The specified line segment. */ -SFCGAL_API std::unique lineSegment( const LineString& ls, double start, double end ) ; - -/** - * @brief Retrieve a segment of a specified 3D LineString, - * between the specified fractional distances from the start - * of the specified LineString. - * @param ls The specified LineString. - * @param start The fraction along the specified LineString defining the - * start of the desired segment. - * @param end The fraction along the specified LineString defining the - * end of the desired segment. - * @note Negative values of {@code start} and/or {@code end} will be - * interpreted as a fractional distance taken from the end of the - * specified LineString. +/-0 will always be interpreted as the start - * of {@code ls}. - * @note For open lines, a negative length range will result in a line - * segment terminating at the specified points, but with an - * orientation reversed relative to {@code ls}. For closed lines the - * a negative range corresponds to the complentary section of {@code ls} - * with an orientation equal to that of it. - * @return The specified 3D line segment. - */ -SFCGAL_API std::unique lineSegment3D( const LineString& ls, double start, double end ) ; +SFCGAL_API std::unique lineSegment( const LineString& ls + , double start + , double end + ); } // ! namespace algorithm