How can i extend a class in a library like Armadillo? - c++

I'm working with 3D vectors for 3d Graphics.
I created a class vec3 to add functions like getX, getY, getZ, setX, setY, setZ, setXYZ... and so on.
#include <armadillo>
using namespace arma;
// An extension to VEC class for Armadillo for 3D graphics.
class vec3 : public vec
{
public:
// Constructor inits vector to 0,0,0
vec3() : vec(3,fill::zeros) {}
~vec3(void){};
double getX() const { return at(0); }
double getY() const { return at(1); }
double getZ() const { return at(2); }
void setX(double x){ ?????? = x; }
};
I found myself lost in a very unusual situation i never found:
How do i use (i) access to elements... inside the class?
For the getter function, as you can see, it is easy since we have an "at" function, at least.
But how do i create a setX function, that inserts in the 0 position of the vector the given element...
I tried this(i) , obviously didn't work. I feel so newbie here...
Where is "vec" built over?. A std::vector?... Am i doing right by doing this simple stuff?

at(0) = x; should work if vec is derived from std::vector because at function can return non-constant reference.

Related

Difficulty getting barycentric_rational from c++ boost library to work how I need it to

I am using barycentric_rational from the C++ Boost library to interpolate on data stored in vectors. The vectors are populated inside a class, and I need the interpolation to be performed after the vectors have been populated, so I can write an access function to get the interpolated value at a specific point. Something like this:
class V{
public:
V(/* some arguments */){
//populate x and y
b=barycentric_rational<double>(x.data(),y.data(),x.size());
}
double psi(double r){
return b(r);
}
private:
std::vector<double> x,y;
barycentric_rational<double> b;
};
I get the error message:
error: no matching function for call to ‘boost::math::barycentric_rational<double>::barycentric_rational()
I think I get this message because b needs to be initialized in an initialiser list, but the code to populate x and y in my application is complicated. Setting x and y in a separate public method doesn't work for the same reason.
I have tried the following solution:
class V{
public:
V(/* some arguments */):b(nullptr){
//populate x and y
b=new barycentric_rational<double>(x.data(),y.data(),x.size());
}
~V(){
delete b;
}
double psi(double r){
return b->operator()(r);
}
private:
std::vector<double> x,y;
barycentric_rational<double> *b;
};
which seems to work. However, I don't like it for two reasons: a) I am using raw pointers, and eventually I need to be able to use copy and assignment operators which will get me into trouble, and b) I am sure there must be a neater way of doing this.
Please can someone suggest a way of doing what I need?
You can just init it in initialization list. If you need to use some special logic to populate x and y, you can do it in separate method.
class V{
public:
V(/* some arguments */)
: x(populateX()), y(populateY()), b(x.data(),y.data(),x.size())
{
}
std::vector<double> populateX() {
}
std::vector<double> populateY() {
}
double psi(double r){
return b(r);
}
private:
std::vector<double> x,y;
barycentric_rational<double> b;
};
If the code that populates x and y is too complecated, and initialization of x and y can not be done separately then you can move it to separate class:
struct XY {
XY(/* some args */) {
//init x and y
}
std::vector<double> x;
std::vector<double> y;
};
class V{
public:
V(/* some arguments */)
: xy(/*some args */), b(xy.x.data(),xy.y.data(),xy.x.size())
{
}
double psi(double r){
return b(r);
}
private:
XY xy;
barycentric_rational<double> b;
};
Another solution is just to initialize b with empty x and y, and then assign to it another correct value:
V(/* some arguments */) : b(x.data(),y.data(),x.size()){
//populate x and y
b=barycentric_rational<double>(x.data(),y.data(),x.size());
}

Using class member function as function pointer?

I am trying to pass a function pointer to a member function of a class to std::unique() and am getting some compiler errors that are impossible for me to decipher.
// So this will otherwise compile
class Vec2 {};
class Polygon {};
// ConvexHull.h:
#include <vector>
#include <algorithm>
class ConvexHull {
public:
// Used to sort an array of vectors so the bottom-right element is first:
bool bottomRight(const Vec2& a, const Vec2& b);
// Used to determine if coordinates are equivalent:
bool vecEqual(const Vec2& a, const Vec2& b);
Polygon chGrahamScan(std::vector<Vec2> points);
};
// ConvexHull.cpp:
bool ConvexHull::bottomRight(const Vec2& a, const Vec2& b) {
// implementation...
return false; // So this will otherwise compile
}
bool ConvexHull::vecEqual(const Vec2& a, const Vec2& b) {
// implementation...
return false; // So this will otherwise compile
}
Polygon ConvexHull::chGrahamScan(std::vector<Vec2> points) {
// Sort according to bottom right:
std::sort(points.begin(),points.end(),bottomRight); // !!!Does not compile!!!
std::vector<Vec2>::iterator it;
// Get rid of duplicate points:
it = std::unique(points.begin(),points.end(),vecEqual); // !!!Does not compile!!!
// rest of implementation...
Polygon poly; // So this will otherwise compile
return poly;
}
int main(){return 0;} // again, to allow this to otherwise compile
Ignoring the two broken lines, this is enough to compile something. Please help! I am not sure what I am doing wrong here. I know this test code says the members functions are public but my end goal here is to have them be private functions that are hidden from the user but still used internally in ConvexHull::chGrahamScan() by sort and unique. These aren't the only two comparison methods I intend to use. The others require referring to internal state data maintained by an instance of the ConvexHull class. My initial solution (which apparently totally worked) had methods that did not belong to any class. Instead all of the state data and comparison functions were in a global anonymous namespace, but this broke the thread-safeness of my project so I decided to go this route.
If you copy and paste this into an empty project you should see the errors I am getting. It says I need to use .* or ->* for a member function pointer. However trying to do this gives me other errors, saying these functions cannot be used as member functions as they are of type "unresolved overloaded function".
If it turns out that I cannot do something like this, how would I best go about implementing std::sort and std::unique in such a way that the comparison functions passed to them use state data external to the definition of the functions themselves without violating thread safety by using global variables? My previous solution did something like:
namespace {
Vec2 point0; // state data that other comparison functions like
// bottomRight and vecEqual need
bool bottomRight(/*...*/){/*...*/}
bool vecEqual(/*...*/){/*...*/}
}
// Accesses global data. Bad!
Polygon chGrahamScan(std::vector<Vec2> points) {
std::sort(points.begin(),points.end(),bottomRight);
std::vector<Vec2>::iterator it;
it = std::unique(points.begin(),points.end(),vecEqual);
// etc..
}
If you want to use the sort function with a comparator, write the comparator as a separate object rather putting the code in your ConvexHull class. Unless you need some private data within ConvexHull, your comparator does not need to be part of that class.
class ConvexHull
{
// ... rest of class as shown above ...
private:
// declare friend so comparator can use private data.
friend struct VectorComparator;
};
struct VectorComparator
{
explicit VectorComparator( ConvexHull * hull ) : hull_( hull ) {}
bool operator()( const Vec2& a, const Vec2& b ) const
{
// ... compare the two Vec2 objects here using private data from ConvexHull ...
}
ConvexHull * hull_;
};
Then you can use VectorComparator as a parameter into std::sort.
ConvexHull * hull = new ConvexHull;
std::sort(points.begin(),points.end(), VectorComparator(hull) );
You can make a separate comparator for the unique function.
struct UniqueVectorComparator
{
bool operator()( const Vec2& a, const Vec2& b ) const
{
// .. compare the two Vec2 objects here.
}
};
it = std::unique(points.begin(),points.end(), UniqueVectorComparator() );
As the compiler says, make your functions static and use scoping operator:
class ConvexHull {
public:
// Used to sort an array of vectors so the bottom-right element is first:
static bool bottomRight(const Vec2& a, const Vec2& b);
// Used to determine if coordinates are equivalent:
static bool vecEqual(const Vec2& a, const Vec2& b);
Polygon chGrahamScan(std::vector<Vec2> points);
};
...
std::sort(points.begin(),points.end(),ConvexHull::bottomRight); // !!!Does not compile!!!

How to chain multiple operator[]

I am trying to create a class that use the operator [] like
MyClass[x][y]
and it should return a value based on what I call in the function that is defined within the class. What I have so far is:
MyClass.h
class MyClass{
public:
// return one value of the matrix
friend double operator[][] (const int x, const int y);
}
I don't even think my syntax for this is right, and how can I write this function in MyClass.cpp to define what value it should return?
Like is it:
MyClass::friend double operator[][] (const int x, const int y)
{
// insert code here
}
Tried it but it keeps saying errors. I believe it is a mess up there...
Many thanks,
Overloading operator() is definitely the cleanest approach.
However, remember that this is C++, and you can bend the syntax to your will :)
In particular, if you insist on wanting to use myclass[][], you can do so by declaring an "intermediate class", here's an example:
Run It Online
#include <iostream>
using std::cout;
using std::endl;
class MyClass {
public:
using IndexType = int;
using ReturnType = double;
// intermediate structure
struct YClass {
MyClass& myclass;
IndexType x;
YClass (MyClass& c, IndexType x_) : myclass(c), x(x_) {}
ReturnType operator[](IndexType y_) { return myclass.compute(x, y_); }
};
// return an intermediate structure on which you can use opearator[]
YClass operator[](IndexType x) { return {*this, x}; }
// actual computation, called by the last "intremediate" class
ReturnType compute(IndexType x, IndexType y) {
return x * y;
}
};
int main()
{
MyClass myclass;
cout << myclass[2][3] << endl; // same as: cout << myclass.compute(2, 3) << endl;
}
You need to return a proxy object for the row. This is a very simplified example just to get you going. I have not tried compiling it.
class Matrix {
int data[4][4];
class Row {
Matrix* matrix;
int row;
int operator[](int index){
return matrix->data[row][index]; // Probably you want to check the index is in range here.
}
}
Row operator[](int row){
Row which_row;
which_row.matrix = this;
which_row.row = row; // beware that if the user passes the row around it might point to invalid memory if Matrix is deleted.
return which_row;
}
}
You could also just return the row directly from operator[] and leave the second [] to be a direct array access. IMHO it is nice with the proxy object as it can do some checking on the index and possibly have other nice member functions.
There is no operator[][]. But you can declare operator()(int, int) instead.
class Foo {
public:
double operator()(int a, int b) {
//...
}
};
If you're trying to create 4x4 Matrix class, the way I did it and the way its done in the D3DX library is to have a member variable in the class:
class Matrix
{
public:
// publicly accessible member 4x4 array
float m[4][4];
// also accessible via () operator. E.G. float value = mtx(3,2);
float operator()(int column, int row);
}

What is the scope of a class inside of a class in C++?

I've written a class that looks like
class Mesh {
public:
vector<Vertex> vs;
}
where Vertex is
class Vertex {
public:
const double x, y, z;
}
I have a function which loads a Mesh from a file:
shared_ptr<Mesh> load_mesh(string filename) {
//....
vector<Vertex> vs;
Vertex v(1, 2, 3);
vs.push_back(v);
return shared_ptr<Mesh>(Mesh(vs));
}
My questions are concerning the scope of the Vertex and the vector.
Will one or both go out of scope?
Which (if any) of the alternatives are preferred?
class Mesh1 {
public:
vector<shared_ptr<Vertex>> vs;
}
class Mesh2 {
public:
shared_ptr<vector<Vertex>> vs;
}
class Mesh3 {
public:
shared_ptr<vector<shared_ptr<Vertex>>> vs;
}
Or is there a better / easier way of handling this?
Your basic structure looks right to me. You are copying the Vertex into the vector and then copying the vector into the Mesh. The local copies in the load_mesh() function will go out of scope but because you have made a copy that is ok.
At the risk of being accused of premature optimization I would say that unless the vector is small all that copying is a little inefficient. There are a number of ways it could be optimized. With C++11, and move semantics, you can keep your current structure and just move the data:
#include <vector>
struct Vertex {
const double x, y, z;
Vertex(double _x, double _y, double _z) : x(_x), y(_y), z(_z) {}
};
struct Mesh {
std::vector<Vertex> vs;
Mesh(std::vector<Vertex> _vs) : vs(std::move(_vs)) {}
Mesh(Mesh&& other) noexcept : vs(std::move(other.vs)) {} // Move constructor
};
Mesh
loadMesh() {
//....
std::vector<Vertex> vs;
vs.emplace_back(1,2,3);
return Mesh{std::move(vs)};
}
int main() {
auto mesh = loadMesh();
}
I'm using emplace_back instead of push_back to construct the Vertex in the vector in-place and using std::move to move the vector into Mesh.
Returning a shared_ptr<Mesh> would be fine but I wanted to show you can also return the Mesh by value. The compiler should perform RVO and there will be no copy (see this question).

sorting vector with 3D points by a coordinate value -- syntax

I want to sort points_vec vector as shown in the pseudocode below. I want to sort this vector, by a coordinate value like x or y or z
class A{
std:vector<double*> points_vec;
void doSomething();
}
Then, in method A::doSomething, I want sort this vector:
void A::doSomething() {
std::sort(points_vec.begin(), points_vec.end(), sortPoints());
}
Can someone please show me syntax for the sortPoints() method.. Preferably I want it to be a method of class A. this post creates a struct to do this, not sure if I should create a similar struct within the class. Is there another way to handle this?
thanks
The simplest way is to provide a functor which is used by the sort algorithm to compare two values. You can write like this:
struct Compare
{
bool operator()(double* first, double* second) const
{
//Compare points here
}
};
And use like:
std::sort(p.begin(), p.end(), Compare());
EDIT for comment by OP: Yes, this sample code compiles fine:
class A
{
public:
struct c
{
bool operator()(int a, int b) const
{
return a < b;
}
};
};
int main()
{
std::vector<int> a1;
a1.push_back(2);
a1.push_back(1);
std::sort(a1.begin(), a1.end(), A::c());
return 0;
}
You have two options for sorting: either pass a function/functor to sort or define the operator< for your class. Now, your class A seems to be more of a wrapper for a set of coordinates. So, create another class for your co-ordinates.
struct Point {
double x_, y_, z_;
Point(double x, double y, double z) : x_(x), y_(y), z_(z) {}
// just an example, you can refine the following as much as you need
bool operator<(Point const& other) {
return x < other.x;
}
};
bool sortOnY(Point const& l, Point const& r) const {
return l.y < r.y;
}
class A {
std::vector<Point> pts_;
void doSomething() {
sort(pts_.begin(), pts_.end());
}
// if sorting on y is also required, you will need
// to use a custom comparator which can be either
// a functor or a function
void doSomeOtherThing() {
sort(pts_.begin(), pts_.end(), sortOnY);
}
};
First of all - what you have will break all your points - as you'll sort by single doubles not by "points consisting of 3 doubles".
The best way to do this I think is:
Store the points as some Point3D class not a couple doubles
Define the less then operator for Point3D
Just call std::sort(points_vec.begin(), points_vec.end() );
If you'd want to sort them by in different ways that's when you'd use the sort functor and create different functors with operators() for different purposes.
I don't think this thread would be complete without a mention of Boost.Bind:
struct Point3D {
double x, y;
Point3D(double x=0., double y=0.) : x(x), y(y) {
}
};
int main() {
std::vector<Point3D> points;
points.push_back(Point3D(-1., 2.));
points.push_back(Point3D( 2., -1.));
points.push_back(Point3D(-2., 0.));
using boost::bind;
std::sort(points.begin(), points.end(),
bind(&Point3D::x, _1) < bind(&Point3D::x, _2));
// points sorted by x coord
std::sort(points.begin(), points.end(),
bind(&Point3D::y, _1) < bind(&Point3D::y, _2));
// points sorted by y coord
}
What a shame std::tr1::bind does not support that. But of course, with a C++0x compiler you'll be able to do this:
std::sort(points.begin(), points.end(),
[](Point3D const & a, Point3D const & b) { return a.x < b.x; });
If you want to sort by x or y or z, those are three different functionalities. Which coordinate to sort by is extra information which doesn't really come from std::sort. You need have an object to pass it on.
struct coord_comparison {
int coord_id; // <= critical information
bool operator()( double (*l)[3], double (*r)[3] ) {
return (*l)[ coord_id ] < (*r)[ coord_id ];
}
coord_comparison( int id ) { coord_id = id; }
};
Create this struct inside your class or outside, but it needs to be a structure and not a free function, and operator() cannot be static. Call:
std::sort(points_vec.begin(), points_vec.end(), compare_points( 1 /*for y*/) );
Sorting by all 3 coords at once:
You have
std:vector<double*> points_vec;
I'm going to presume that the double* points to an array of 3 coordinates. This is cleaner:
std:vector<double(*)[3]> points_vec;
std::sort's third argument is a functor which compares two sequence objects:
bool compare_coords( double(*l)[3], double(*r)[3] ) {
Fortunately, comparing two sequences is already coded for you by std::less:
return std::less( *l, *l + ( sizeof *l/sizeof **l ), r );
(perhaps I did more work than necessary to get the size of the array)
return std::less( *l, *l + 3, r );
}
This function may be useful outside the class, so I'd make it a free function. You need to make it static if it's going to stay inside the class.
Finally, leave off the parens when passing the function to std::sort:
std::sort(points_vec.begin(), points_vec.end(), compare_points );