I have a std::vector<QVector3D>, which contains some 3D coordinates. I want to sort the vector by the z value.
I push four 3D points into the vector in a loop:
/* points
29.3116 -192.771 -103.172
2.50764 -190.652 -194.383
24.1295 -181.255 -179.553
6.22275 -176.747 -189.578
*/
// Find the points and push in vector
...
std::vector<QVector3D> pointVector;
pointVector.push_back(QVector3D(point[0], point[1], point[2]));
// iterate through vector
for(int i= 0; i< pointVector.size(); i++)
{
qDebug()<<"Vector: " << pointVector[i].x() << pointVector[i].y() << pointVector[i].z();
}
The output should looks like, if I sort the vector by its z coordinate:
2.50764 -190.652 -194.383
6.22275 -176.747 -189.578
24.1295 -181.255 -179.553
29.3116 -192.771 -103.172
The std::sort
#include <iostream>
#include <vector>
#include <algorithm>
struct vec3
{
float x;
float y;
float z;
};
bool MysortFunc(const vec3& i, const vec3& j) { return (i.z > j.z); }
int main() {
std::vector<vec3> vertices;
vertices.push_back({ 29.3116 , 192.771 , 103.172 });
vertices.push_back({ 2.50764 , 190.652 , 194.383 });
vertices.push_back({ 24.1295 , 181.255 , 179.553 });
vertices.push_back({ 6.22275 , 176.747 , 189.578 });
std::sort (vertices.begin(), vertices.end(), MysortFunc);
for (auto vertex : vertices)
{
std::cout << vertex.x << ' ' << vertex.y << ' ' << vertex.z << std::endl;
}
}
The sort function gets two vertices from the vector array to compare. The function will return true or false depending on the values of i.z and j.z . The sort function will make use of that and sort your vector array for you. You can also sort by y using i.y and j.y in the MysortFunc.
My output:
2.50764 190.652 194.383
6.22275 176.747 189.578
24.1295 181.255 179.553
29.3116 192.771 103.172
I want to sort the vector by the z value.
Use the overload of std::sort that takes a custom comparator:
std::sort(pointVector.begin(), pointVector.end(),
[](auto&& e1, auto&& e2) { return e1.z() < e2.z(); });
I want to efficiently create a list of the vertex number of a polygon that intersects. This in order to check if I move the polygons slightly I can check whether it is the same intersection or a completely different one. Presumably if at least one vertex number remains in the list it is the same intersection.
So I have polygon P and Q at t=0 intersecting, this should give me vertex number [1,2,3] for P and [2] for polygon Q, see image for clarification. At t=1 I would get [1,2] for P and [2] for Q.
Currently I first retrieve the intersection and than for both polygons loop through the vertices and use the has_on_boundary function to determine if it is part of the intersection and store the vertex number. See code:
//Standard Includes
#include <iostream>
using std::cout;
using std::endl;
//Include CGAL options
#define CGAL_HEADER_ONLY 1 //Defining to use the CGAL library as header only
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Boolean_set_operations_2.h>
#include <CGAL/Constrained_Delaunay_triangulation_2.h>
//Typedefs for CGAL Uses.
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
typedef Kernel::Point_2 Point_2;
typedef CGAL::Polygon_2<Kernel> Polygon_2;
typedef CGAL::Polygon_with_holes_2<Kernel> Polygon_with_holes_2;
typedef std::vector<Polygon_with_holes_2> Pwh_list_2;
int main() {
Polygon_2 P;
P.push_back(Point_2(-1, 1));
P.push_back(Point_2(-0.01, -1));
P.push_back(Point_2(0, -1));
P.push_back(Point_2(0.01, -1));
P.push_back(Point_2(1, 1));
Polygon_2 Q;
Q.push_back(Point_2(-1, -1));
Q.push_back(Point_2(1, -1));
Q.push_back(Point_2(0, 1));
Pwh_list_2 polygon_intersections;
CGAL::intersection(P, Q, std::back_inserter(polygon_intersections));
//For ease now only assume one intersection
Polygon_2 intersection = polygon_intersections[0].outer_boundary();
//Get vertex number of P in intersection
int vertex_nr = 0;
std::set<int> overlapping_vertices_P;
cout << "Find intersection vertices of Polygon P" << endl;
for (auto it = P.vertices_begin(); it != P.vertices_end(); ++it, ++vertex_nr) {
if (intersection.has_on_boundary(*it)) {
overlapping_vertices_P.insert(vertex_nr);
cout << vertex_nr << endl;
}
}
//Get vertex number of Q in intersection
vertex_nr = 0;
std::set<int> overlapping_vertices_Q;
cout << "Find intersection vertices of Polygon Q" << endl;
for (auto it = Q.vertices_begin(); it != Q.vertices_end(); ++it, ++vertex_nr) {
if (intersection.has_on_boundary(*it)) {
overlapping_vertices_Q.insert(vertex_nr);
cout << vertex_nr << endl;
}
}
return 0;
}
Question: It works but seems very inefficient to me. Is there a better way to do this?
Any help or suggestions are highly appreciated.
I'm currently learning to perform 3D triangulation using CGAL, and so far I've managed to create a regular tetrahedron by inserting and triangulating 4 vertices. But when I try to loop over the edges of the tetrahedron and obtain the vertices corresponding to that edge, I get the origin as a vertex or duplicates of previous edges. In 2D it all works fine, but in 3D things go wrong. I think this is related to an infinite/undefined vertex being included, but I don't know how to deal with this. Any help would be appreciated.
My code (modified from this question):
#include <vector>
#include <iostream>
#include <cmath>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Delaunay_triangulation_3.h>
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef CGAL::Delaunay_triangulation_3<K> Delaunay;
typedef K::Point_3 Point;
void load_points(std::vector<Point>& rPoints)
{
rPoints.push_back(Point(1.0, 0.0, -1.0/sqrt(2))); // first point
rPoints.push_back(Point(-1.0, 0.0, -1.0/sqrt(2))); // second point
rPoints.push_back(Point(0.0, 1.0, 1.0/sqrt(2))); // third point
rPoints.push_back(Point(0.0, -1.0, 1.0/sqrt(2))); // fourth point
}
int main()
{
std::vector<Point> points;
load_points(points);
Delaunay dt;
dt.insert(points.begin(),points.end());
for(Delaunay::Finite_edges_iterator it = dt.finite_edges_begin(); it != dt.finite_edges_end(); ++it)
{
Point i1= it->first->vertex( (it->second+1)%3 )->point();
Point i2= it->first->vertex( (it->second+2)%3 )->point();
std::cout << "i1: " << i1 << "\t i2: " << i2 << "\n";
}
return 0;
}
The documentation for an edge indicates that it's a triple: (c,i,j) is the edge of cell c whose vertices indices are i and j.
So in your code you should write:
Point i1= it->first->vertex( it->second )->point();
Point i2= it->first->vertex( it->third )->point();
So in my code I got a vector of multidimensional arrays. In this vector I store the coordinates of points of a contour. Before I can restore the contour, based on the points, I have to erase the duplicates to reduce the data. So I found that I can use std::unique, if the vector is sorted. But sorting isn't needed, so I want to erase the duplicates from the unsorted vector. So I have to use std::set to remove the duplicates
std::vector<std::array<double, 3>> matrix;
rows = 2*lss.size();
matrix.resize(rows);
int j=0;
for(size_t i = 0;i<lss.size();i++) {
int k = j+1;
matrix[j][0]=lss[i].v[0].x;
matrix[j][1]=lss[i].v[0].y;
matrix[j][2]=lss[i].v[0].z;
matrix[k][0]=lss[i].v[1].x;
matrix[k][1]=lss[i].v[1].y;
matrix[k][2]=lss[i].v[1].z;
j=j+2;
}
std::set<double> set(matrix.begin(), matrix.end());
matrix.erase(std::remove_if(matrix.begin(), matrix.end(), [&set] (double item) {return !set.erase(item); }), matrix.end());
But for the line std::set<double> set(matrix.begin(), matrix.end()); I get this error message: 'std::pair<_Ty1,_Ty2> std::set<_Kty>::insert(double &&) : cannot convert parameter 1 from std::array<_Ty,_Size> to 'double &&'.
For the following line I also receive an error message: 'bool export::<lambda_c894aac2078f37151750793b2c6d0417>::operator ()(double) const' : cannot convert parameter 1 from 'std::array<_Ty,_Size>' to 'double'
If you require your container holds unique items only and you do not care about these being sorted then you can always just use std::unordered_set to hold your coordinates.
Simple example:
#include <iostream>
#include <unordered_set>
struct Point
{
double x, y, z;
bool operator==(const Point& other) const
{
return (x == other.x) && (y == other.y) && (z == other.z);
}
};
Hash function taken from this answer:
struct Hash
{
size_t operator() (const Point &point) const
{
return ((std::hash<double>()(point.x)
^ (std::hash<double>()(point.y) << 1)) >> 1)
^ (std::hash<double>()(point.z) << 1);
}
};
int main()
{
std::unordered_set<Point, Hash> uset;
uset.insert({ 100, 100, 200 });
uset.insert({ 100, 100, 200 });
uset.insert({ 100, 100, 200 });
std::cout << uset.size() << '\n'; // prints 1
return 0;
}
You should change the line
std::set<double> set(matrix.begin(), matrix.end());
to:
std::set<std::array<double, 3>> set(matrix.begin(), matrix.end());
You're building a set of matrices, not doubles. The template parameter to your set should be the same as to your vector.
I wanted to get a vector of distances between adjacent points in a vector:
struct Point { double x, y, z; }
vector<double> adjacent_distances( vector<Point> points ) {
...
}
I thought that stl::adjacent_difference() would do the trick for me if I simply provided a function that finds the distance between 2 points:
double point_distance( Point a, Point b ) {
return magnitude(a-b); // implementation details are unimportant
}
Thus, I was hoping that this would work,
vector<double> adjacent_distances( vector<Point> points )
{
vector<double> distances;
std::adjacent_difference( points.begin(), points.end(),
std::back_inserter(distances),
ptr_fun( point_distance ) );
return distances;
}
only to find that input and output vectors had to be of (practically) the same type because adjacent_difference() calls
output[0] = input[0]; // forces input and output to be of same value_type
output[1] = op( input[1], input[0] );
output[2] = op( input[2], input[1] );
....
which, sadly, is inconsistent with respect to how std::adjacent_find() works.
So, I had to convert my code to
double magnitude( Point pt );
Point difference( Point a, Point b ); // implements b-a
vector<double> adjacent_distances( vector<Point> points )
{
vector<Point> differences;
std::adjacent_difference( points.begin(), points.end(),
std::back_inserter(differences),
ptr_fun( point_difference ) );
vector<double> distances;
std::transform( differences.begin(), differences.end(),
std::back_inserter(distances),
ptr_fun( magnitude ) );
return distances;
}
NB: the first element of differences had to be removed for the function to behave correctly, but I skipped the implementation details, for brevity.
Question: is there a way I could achieve some transformation implicitly, so that I don't have to create the extra vector, and achieve a call to adjacent_difference() with input_iterator and output_iterator of different value_types ?
Probably this isn't so neat though, in this specific case, std::transform
with 2 input sequences might meet the purpose.
For example:
vector<double> adjacent_distances( vector<Point> points ) {
if ( points.empty() ) return vector<double>();
vector<double> distances(
1, point_distance( *points.begin(), *points.begin() ) );
std::transform( points.begin(), points.end() - 1,
points.begin() + 1,
std::back_inserter(distances),
ptr_fun( point_distance ) );
return distances;
}
Hope this helps
Indeed that adjacent_difference algorithm is logically broken (why should be the difference of the same time of the elements? Why is the first output element equal to the first one instead of getting an output sequence one item shorter than the input one (way more logical)?
Anyway I don't understand why you are punishing yourself by using a functional approach with C++ where clearly the code is going to be harder to write, harder to read, slower to compile and not faster to execute. Oh.. and let's not talk about the kind of joke error message you are going to face if there is any error in what you type.
What is the bad part of
std::vector<double> distances;
for (int i=1,n=points.size(); i<n; i++)
distances.push_back(magnitude(points[i] - points[i-1]));
?
This is shorter, more readable, faster to compile and may be even faster to execute.
EDIT
I wanted to check my subjective "shorter, more readable, faster to compile and may be faster to execute". Here the results:
~/x$ time for i in {1..10}
> do
> g++ -Wall -O2 -o algtest algtest.cpp
> done
real 0m2.001s
user 0m1.680s
sys 0m0.150s
~/x$ time ./algtest
real 0m1.121s
user 0m1.100s
sys 0m0.010s
~/x$ time for i in {1..10}
> do
> g++ -Wall -O2 -o algtest2 algtest2.cpp
> done
real 0m1.651s
user 0m1.230s
sys 0m0.190s
~/x$ time ./algtest2
real 0m0.941s
user 0m0.930s
sys 0m0.000s
~/x$ ls -latr algtest*.cpp
-rw-r--r-- 1 agriffini agriffini 932 2011-11-25 21:44 algtest2.cpp
-rw-r--r-- 1 agriffini agriffini 1231 2011-11-25 21:45 algtest.cpp
~/x$
The following is the accepted solution (I fixed what is clearly a brainfart of passing the vector of points by value).
// ---------------- algtest.cpp -------------
#include <stdio.h>
#include <math.h>
#include <functional>
#include <algorithm>
#include <vector>
using std::vector;
using std::ptr_fun;
struct Point
{
double x, y;
Point(double x, double y) : x(x), y(y)
{
}
Point operator-(const Point& other) const
{
return Point(x - other.x, y - other.y);
}
};
double magnitude(const Point& a)
{
return sqrt(a.x*a.x + a.y*a.y);
}
double point_distance(const Point& a, const Point& b)
{
return magnitude(b - a);
}
vector<double> adjacent_distances( const vector<Point>& points ) {
if ( points.empty() ) return vector<double>();
vector<double> distances(
1, point_distance( *points.begin(), *points.begin() ) );
std::transform( points.begin(), points.end() - 1,
points.begin() + 1,
std::back_inserter(distances),
ptr_fun( point_distance ) );
return distances;
}
int main()
{
std::vector<Point> points;
for (int i=0; i<1000; i++)
points.push_back(Point(100*cos(i*2*3.141592654/1000),
100*sin(i*2*3.141592654/1000)));
for (int i=0; i<100000; i++)
{
adjacent_distances(points);
}
return 0;
}
Here is instead the explicit loop solution; it requires two include less, one function definition less and the function body is also shorter.
// ----------------------- algtest2.cpp -----------------------
#include <stdio.h>
#include <math.h>
#include <vector>
struct Point
{
double x, y;
Point(double x, double y) : x(x), y(y)
{
}
Point operator-(const Point& other) const
{
return Point(x - other.x, y - other.y);
}
};
double magnitude(const Point& a)
{
return sqrt(a.x*a.x + a.y*a.y);
}
std::vector<double> adjacent_distances(const std::vector<Point>& points)
{
std::vector<double> distances;
if (points.size()) distances.reserve(points.size()-1);
for (int i=1,n=points.size(); i<n; i++)
distances.push_back(magnitude(points[i] - points[i-1]));
return distances;
}
int main()
{
std::vector<Point> points;
for (int i=0; i<1000; i++)
points.push_back(Point(100*cos(i*2*3.141592654/1000),
100*sin(i*2*3.141592654/1000)));
for (int i=0; i<100000; i++)
{
adjacent_distances(points);
}
return 0;
}
Summary:
code size is shorter (algtest2.cpp is less than 76% of algtest.cpp)
compile time is better (algtest2.cpp requires less than 83% of algtest.cpp)
execution time is better (algtest2.cpp runs in less than 85% of algtest.cpp)
So apparently on my system (not hand-picked) I was right on all points except execution speed (the one with "maybe") where to get from slightly slower to substantially faster I had to call reserve on the result array. Even with this optimization the code is of course shorter.
I also think that the fact that this version is more readable is also objective and not an opinion... but I'd be happy to be proven wrong by meeting someone that can understand what the functional thing is doing and that cannot understand what the explicit one is doing instead.
Yes, this can be done, but not easily. I don't think it's worth the effort, unless you really need to avoid the copy.
If you really want to do this, you can try creating your own iterator that iterates over the vector<Point> and a wrapper around Point.
The iterator class will dereference to an instance of the wrapper class. The wrapper class should support operator - or your distance function, and it should store the distance. You should then implement an operator for implicit conversion to double, which will be invoked when adjacent_difference attempts to assign the wrapper to the vector<double>.
I don't have time to go into detail, so if anything is unclear, I'll check back later or someone else can try to explain better. Below is an example of a wrapper that does this.
struct Foo {
Foo(double value) { d = value; }
operator double() { return d; }
double d;
};
Foo sub(const Foo& a, const Foo& b) {
return Foo(a.d - b.d);
}
vector<Foo> values = {1, 2, 3, 5, 8};
vector<double> dist;
adjacent_difference(values.begin(), values.end(), back_inserter(dist), sub);
// dist = {1, 1, 1, 2, 3}
This is maybe a bit dirty, but you could simply add
struct Point {
double x,y,z;
operator double() { return 0.0; }
};
or perhaps
struct Point {
double x,y,z;
operator double() { return sqrt(x*x + y*y + z*z); } // or whatever metric you are using
};
The effect being to set the first distance to 0, or the distance of the first point from the origin. However, I could imagine that you wouldn't want to pollute your Point struct with a rather arbitrary definition for conversion to double - in which case dauphic's wrapper is a cleaner solution.
Since you have no use for the first element returned by adjacent_difference, which is precisely the one giving trouble, you can write your own version of the algorithm, skipping that initial assignment:
template <class InputIterator, class OutputIterator, class BinaryOperation>
OutputIterator my_adjacent_difference(InputIterator first, InputIterator last,
OutputIterator result,
BinaryOperation binary_op)
{
if (first != last)
{
InputIterator prev = first++; // To start
while (first != last)
{
InputIterator val = first++;
*result++ = binary_op(*val, *prev);
prev = val;
}
}
return result;
}
This should work, though you will be missing some STL optimisations.
I like the a) formulation of the problem, b) comparison of the execution times, c) my_adjacent_difference, d) self-comment that my_adjacent_difference may lack built-in optimizations. I agree that the Standard C++ adjacent_difference logic limits the algorithm's application and that the three lines loop-code is a solution, which many would go with. I reuse the idea to apply the algorithm transform and present the version in C++ 11 illustrating lambdas. Regards.
#include <iostream> /* Standard C++ cout, cerr */
#include <vector> /* Standard C++ vector */
#include <algorithm> /* Standard C++ transform */
#include <iterator> /* Standard C++ back_inserter */
#include <cmath> /* Standard C++ sqrt */
#include <stdexcept> /* Standard C++ exception */
using namespace std; /* Standard C++ namespace */
struct Point {double x, y, z;}; // I would define this differently.
int main(int, char*[])
{
try {
const Point points[] = {{0, 0, 0}, {1, 0, 0}, {1, 0, 3}};
vector<double> distances;
transform(points + 1, points + sizeof(points) / sizeof(Point),
points, back_inserter(distances),
[](const Point& p1, const Point& p2)
{
double dx = p2.x - p1.x;
double dy = p2.y - p1.y;
double dz = p2.z - p1.z;
return sqrt(dx * dx + dy * dy + dz * dz);
});
copy(distances.begin(), distances.end(),
ostream_iterator<double>(cout, "\n"));
}
catch(const exception& e) {
cerr << e.what() << endl;
return -1;
}
catch(...) {
cerr << "Unknown exception" << endl;
return -2;
}
return 0;
}
The output:
1
3