qhull / qhull

Qhull development for www.qhull.org -- Qhull 2020.2 (8.1-alpha1) at https://github.com/qhull/qhull/wiki
Other
716 stars 191 forks source link

Constructing `std::vector` from `QhullPoints`' iterators gives unexpected results #133

Open griloHBG opened 1 year ago

griloHBG commented 1 year ago

Hi all!

From a Qhull object, I know it is possible to get a std::vector<QhullPoint> by using qhull.points().toStdVector().

But I am failing to construct a valild std::vector<QhullPoint> from QhullPoints' begin() and end() iterators.

Please consider the following code:

#include <iostream>
#include <vector>

#include "libqhullcpp/Qhull.h"
#include "libqhullcpp/QhullPoints.h"

// helper to print vector of something
template <typename T>
std::ostream& operator<<(std::ostream& os, std::vector<T> vec) {
    std::for_each(std::cbegin(vec), std::cend(vec), [&](const auto& e){os << e;});
    return os;
}

int main() {
    // 2-D problem
    constexpr int dim_size = 2;

    // 4 points to have a quadrilateral geometry
    constexpr int num_points = 4;

    // points of our quadrilateral
    std::array<std::array<coordT ,dim_size>,num_points> points = {{{1,2},{3,-4},{-5,6},{-7,-8}}};

    // array to store our "flattened" coordinates
    std::array<coordT , dim_size*num_points> input_vertices{};

    // flattening our coordinates
    for(int point_index=0; point_index < num_points; point_index++) {
        for(int dim_index=0; dim_index < dim_size; dim_index++) {
            input_vertices[point_index*dim_size + dim_index] = points[point_index][dim_index];
        }
    }

    // creating our Qhull
    orgQhull::Qhull qhull{inputComments, dim_size, num_points, input_vertices.data(), qhullCommands};
    std::cout << "qhull.points()" << std::endl;
    std::cout << qhull.points();
    std::cout << "qhull.points().size() = " << qhull.points().size() << std::endl << std::endl;

    // getting a vector using QhullPoints' toStdVector (this works as expected)
    auto toStdVector = qhull.points().toStdVector();
    // printing (using the helper function) toStdVector shows the expected size and coordinates
    std::cout << "toStdVector" << std::endl;
    std::cout << toStdVector;
    std::cout << "toStdVector.size() = " << toStdVector.size() << std::endl << std::endl;

    std::cout << "printing using QhullPoints' iterators" << std::endl;
    std::for_each(qhull.points().begin(), qhull.points().end(), [&](const auto& e){std::cout << e;});

    // constructing our vectorFromIterators out of the Qhull's points thought its iterators to QhullPoint (this doesn't work as expected)
    std::vector<orgQhull::QhullPoint> vectorFromIterators{qhull.points().begin(), qhull.points().end()};

    // this is another possibility, but the final result is the same as using the option above
    //std::vector<orgQhull::QhullPoint> vectorFromIterators{std::begin(qhull.points()), std::end(qhull.points())};

    // printing (using the helper function) vectorFromIterators doesn't show the expected size and coordinates
    std::cout << "vectorFromIterators from iterators of qhull.points():" << std::endl;
    std::cout << vectorFromIterators;
    std::cout << "vectorFromIterators.size() = " << vectorFromIterators.size() << std::endl << std::endl;

    // this assert will fail
    assert(qhull.points().size() == vectorFromIterators.size());

    return 0;
}

I get the following output:

qhull.points()
 1 2
 3 -4
 -5 6
 -7 -8
qhull.points().size() = 4

toStdVector
 1 2
 3 -4
 -5 6
 -7 -8
toStdVector.size() = 4

printing using QhullPoints' iterators
 1 2
 3 -4
 -5 6
 -7 -8
vectorFromIterators from iterators of qhull.points():
 1 2
 4.26873e-321 6.94734e-310
vectorFromIterators.size() = 2

[[ommited]]: int main(): Assertion `qhull.points().size() == vectorFromIterators.size()' failed.

I am using the latest commit from master:

$ git --no-pager log -1
commit c2ef2209c28dc61ccfd22514971236587e820121 (HEAD -> master, tag: v8.1-alpha3, origin/master, origin/HEAD)
Author: Brad Barber <bradb@shore.net>
Date:   Mon Jan 2 17:02:40 2023 -0500

    Qhull 8.1-alpha3 GitHub 2023/01/02
    - user_r.h, user.h: Fix header comment for REALmax,REALmin,REALepsilon
    - global_r.c, global.c: Update qh_version2 and new date for qh_version
    - CMakeLists.txt: Update qhull_VERSION and qhull_SOVERSION
    - README.txt: CMakeCache.txt is in the build/ directory
    - Update Perforce

I actually can use the toStdVector function to get the std::vector<QhullPoint> that I need, but I just wanted to report this strange behavior.

cbbarber commented 8 months ago

Can you explain what the problem is? Is the definition of begin() and end() incorrect? Perhaps compare your code to 'toStdVector'.