I have a simple DLL doing some calculations with Boost Geometry polygons. (Mostly intersections and differences.) Since the DLL will be most likely called from C# code, and from Delphi and who knows from where else, I should convert the result into arrays that everything can handle.
UPDATE:
I had simplified and somewhat corrected my code. The new code looks completely different, uses a completely different approach (for_each_point), and somehow still doesn't compile.
My new code:
#include <vector>
#include <boost/range.hpp>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/polygon.hpp>
using namespace boost::geometry;
typedef boost::geometry::model::point
<
double, 2, boost::geometry::cs::spherical_equatorial<boost::geometry::degree>
> spherical_point;
class PointAggregator {
private :
double *x, *y;
int count;
public :
PointAggregator(int size) {
x = (double*) malloc(sizeof(double) * size);
y = (double*) malloc(sizeof(double) * size);
count = 0;
}
~PointAggregator() {
free(x);
free(y);
}
inline void operator()(spherical_point& p) {
x[count] = get<0>(p);
y[count] = get<1>(p);
count++;
}
void GetResult(double *resultX, double *resultY) {
resultX = x;
resultY = y;
}
};
void VectorToArray(std::vector<model::polygon<spherical_point>> resultVector, double x[], double y[], int *count) {
int i = 0;
for (std::vector<model::polygon<spherical_point>>::iterator it = resultVector.begin(); it != resultVector.end(); ++it) {
if (boost::size(*it) >= 2) {
*count = boost::size(*it);
PointAggregator* pa = new PointAggregator(*count);
boost::geometry::for_each_point(*it, *pa);
pa->GetResult(x, y);
delete(pa);
break;
}
}
}
The current compilation errors are:
error C2039: 'type' : is not a member of 'boost::mpl::eval_if_c' iterator.hpp 63
error C3203: 'type' : unspecialized class template can't be used as a template argument for template parameter 'Iterator', expected a real type difference_type.hpp 25
error C2955: 'boost::type' : use of class template requires template argument list difference_type.hpp 25
error C2955: 'boost::iterator_difference' : use of class template requires template argument list difference_type.hpp 26
Which ones don't look like they have anything to do with this part of code (my filename is geometry.cpp), but everything else that uses Boost Geometry is commented out and I still get these errors, so...
Here is my bad code that I had previously (edited by sehe)
(I'm new to C++ and Boost so I might have missed some basic concept while putting code from the internet together.)
I assume that I can just not iterate through a polygon that easily and I missed the non-trivial part, or that a polygon can not be used as a ring, or iterations are just not the way I thought they are, or I have no idea what else can be wrong. What did I do wrong?
Ok, I think I've got what you're looking for here.
I still don't quite understand why you're looking for this range of what I assume to be points greater than or equal to 2, but I figured out how to get it to compile when using boost::size() at least.
First off, realize that the first parameter of the function
void VectorToArray(std::vector<model::polygon<spherical_point> > resultVector, double x[], double y[], int *count)
{
...
}
is a std::vector containing instances of type model::polygon.
This means that when you dereference your iterator ...defined as
std::vector<model::polygon<spherical_point> >::iterator it
the rvalue is a model::polygon.
boost::model::polygon is NOT in and of itself Boost.Range compatible.
boost::model::polygon is a type containing 5 member functions ....
inline ring_type const& outer() const { return m_outer; }
inline inner_container_type const& inners() const { return m_inners; }
inline ring_type& outer() { return m_outer; }
inline inner_container_type & inners() { return m_inners; }
inline void clear()
{
m_outer.clear();
m_inners.clear();
}
This means that your *it (ie, a model::polygon) is limited to calling only those functions.
What it looks like you want to do is grab either the outer ring or one of the inner rings of each polygon in the vector (not sure which , inner or outer), and see if the range of whatever in that ring is greater than or equal to 2.
To do this, we must do some more mpl and typedef.
typedef boost::geometry::model::point<double, 2, boost::geometry::cs::spherical_equatorial<boost::geometry::degree> > spherical_point; // your definition of a spherical_point
typedef boost::geometry::model::polygon<spherical_point> polygon; //consolidation of template args for a polygon
typedef boost::geometry::ring_type<polygon>::type ring_type; // define a ring_type that can handle your spherical_point by way of the polygon typedef.
typedef boost::geometry::interior_type<polygon>::type int_type; //define a interior_type that can handle your spherical_point
To complete this and just up and get it "working" I decided to assume you wanted the "outer" ring for your range limit conditional.
Here is, to me, compiling code, on gcc 4.1.1 with boost 1.48.
I leave whether the logic is correct up to someone else.
using namespace boost::geometry;
typedef boost::geometry::model::point<double, 2, boost::geometry::cs::spherical_equatorial<boost::geometry::degree> > spherical_point;
typedef boost::geometry::model::polygon<spherical_point> polygon;
typedef boost::geometry::ring_type<polygon>::type ring_type;
typedef boost::geometry::interior_type<polygon>::type int_type;
class PointAggregator
{
private :
double *x, *y;
int count;
public :
PointAggregator(int size)
{
x = (double*) malloc(sizeof(double) * size);
y = (double*) malloc(sizeof(double) * size);
count = 0;
}
~PointAggregator()
{
free(x);
free(y);
}
inline void operator()(spherical_point& p)
{
x[count] = get<0>(p);
y[count] = get<1>(p);
count++;
}
void GetResult(double *resultX, double *resultY)
{
resultX = x;
resultY = y;
}
};
void VectorToArray(std::vector<model::polygon<spherical_point> > resultVector, double x[], double y[], int *count)
{
for (std::vector<model::polygon<spherical_point> >::iterator it = resultVector.begin(); it != resultVector.end(); ++it)
{
model::polygon<spherical_point> tmpPoly;
tmpPoly = (*it);
boost::geometry::ring_type<polygon>::type somering = tmpPoly.outer(); //typed it all out again instead of using ring_type since the complier was complaining and i didn't wanna get into it.
int ringsize = boost::size(somering);
if(ringsize >= 2)
{
*count = ringsize;
PointAggregator* pa = new PointAggregator(*count);
boost::geometry::for_each_point(*it, *pa);
pa->GetResult(x, y);
delete(pa);
break;
}
}
}
I found a few things that needed to be fixed:
One issue I see is in your templates. Be sure to put spaces!
boost range works on containers or ranges that hold begin, end pairs
Iterators represents something like a pointer to an object. Getting the size of the iterator will not do what you want. You need to either use boost::size of a whole container, or std::distance(begin_iterator,end_iterator).
Here is a version that compiles:
#include <vector>
#include <boost/range.hpp>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/polygon.hpp>
using namespace boost::geometry;
typedef boost::geometry::model::point
<
double, 2, boost::geometry::cs::spherical_equatorial<boost::geometry::degree>
> spherical_point;
class PointAggregator {
private :
double *x, *y;
int count;
public :
PointAggregator(int size) {
x = (double*) malloc(sizeof(double) * size);
y = (double*) malloc(sizeof(double) * size);
count = 0;
}
~PointAggregator() {
free(x);
free(y);
}
inline void operator()(spherical_point& p) {
x[count] = get<0>(p);
y[count] = get<1>(p);
count++;
}
void GetResult(double *resultX, double *resultY) {
resultX = x;
resultY = y;
}
};
// added spaces to the close brackets >> becomes > >
void VectorToArray(std::vector<model::polygon<spherical_point> > resultVector, double x[], double y[], int *count) {
for (std::vector<model::polygon<spherical_point> >::iterator it = resultVector.begin(); it != resultVector.end(); ++it) {
if (boost::size(resultVector) >= 2) {
// getting the size of the whole container
*count = boost::size(resultVector);
PointAggregator* pa = new PointAggregator(*count);
boost::geometry::for_each_point(*it, *pa);
pa->GetResult(x, y);
delete(pa);
break;
}
}
}
Related
The f() function in the class MapSquare works properly.. When I add the other class MapTriple, it is not working. f() function in the MapSquare should find the square of the elements in the vector and in the MapTriple should multiply 3 to all elements.
MapGeneric is the base class which contains the function map() which is a recursive function to access the vector elements and the f() function is a pure virtual function.
MapSquare and MapTriple are two derived classes overrides the f() function to find the square of vector elements and to multiply 3 with all the vector elements.
MapSquare works properly... but when I add MapTriple, segmentation fault occures. Please help to solve this.
#include<vector>
#include<iostream>
#include<cstdlib>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
class MapGeneric
{
public:
virtual int f(int){};
vector<int> map(vector<int>, int);
};
class MapSquare:public MapGeneric
{
public: int f(int);
};
class MapTriple:public MapGeneric
{
public: int f(int);
};
class MapAbsolute:public MapGeneric
{
public: int f(int);
};
vector<int> MapGeneric::map(vector<int> v, int index)
{
if(index>=1)
{
v[index]=f(v[index]);
return map(v,index-1);
}
return v;
}
int MapSquare::f(int x)
{
return x*x;
}
int MapTriple::f(int x)
{
return 3*x;
}
int MapAbsolute::f(int x)
{
return abs(x);
}
int main()
{
//mapping square
MapSquare ob;
vector<int> L,L1,L2;
for (int i = 1; i <= 5; i++)
L.push_back(i);
L1=ob.map(L,sizeof(L));
cout<<"Square = ";
for ( vector<int>::iterator i = L1.begin(); i != L1.end(); ++i)
cout << *i<<" ";
//mapping triple
MapTriple t;
L2=t.map(L,sizeof(L));
cout<<endl<<"Triple = ";
for(vector<int>::iterator i=L2.begin();i!=L2.end();++i)
cout<<*i<<" ";
return 0;
}
A number of problems here. It looks as though you think that C++ indices start at 1, rather than zero?
if(index>=1)
{
v[index]=f(v[index]);
return map(v,index-1);
}
To me that immediately looks wrong, surely you mean:
// use size_t for indices (which cannot be negative)
vector<int> MapGeneric::map(vector<int> v, size_t index)
{
// make sure the index is valid!
if(index < v.size())
{
v[index] = f(v[index]);
return map(v, index - 1);
}
return v;
}
Secondly, the sizeof() operator does not do what you expect!! It returns the size of std::vector (which is usually 24bytes on 64 bit systems - basically 3 pointers). You should use the size() method to determine the length of the array.
// remember that indices are zero based, and not 1 based!
L1=ob.map(L, L.size() - 1);
i have this code which uses a function pointer to point 3 functions sum, subtract, mul. it works well. but now the problem is that i have functions with different no.of parameters and different data types. how to implement this.
int add(int a, int b)
{
cout<<a+b;
}
int subtract(int a, int b)
{
cout<<a-b;
}
int mul(int a, int b)
{
cout<<a*b;
}
int main()
{
int (*fun_ptr_arr[])(int, int) = {add, subtract, mul};
unsigned int ch, a = 15, b = 10,c=9;
ch=2;
if (ch > 4) return 0;
(*fun_ptr_arr[ch])(a, b);
return 0;
}
The simple answer is that technically you can't do this. You could do some manipulations using an array as input for all these functions, but you will still have to know exactly what to pass to each function. From a software engineering perspective, you should not do this - I suggest you take a look at the nice answers here: C++ Function pointers with unknown number of arguments
A slightly different approach using objects to implement the required behavior. In order to have a truly generic kind of solution, we need to use Interfaces.
Dismantle the data and operation i.e keep them separately.
//Interface which describes any kind of data.
struct IData
{
virtual ~IData()
{
}
};
//Interface which desribes any kind of operation
struct IOperation
{
//actual operation which will be performed
virtual IData* Execute(IData *_pData) = 0;
virtual ~IOperation()
{
}
};
Now, every operation knows the kind of data it work on and will expect that kind of data only.
struct Operation_Add : public IOperation
{
//data for operation addition.
struct Data : public IData
{
int a;
int b;
int result;
};
IData* Execute(IData *_pData)
{
//expected data is "Operation_Add::Data_Add"
Operation_Add::Data *pData = dynamic_cast<Operation_Add::Data*>(_pData);
if(pData == NULL)
{
return NULL;
}
pData->result = pData->a + pData->b;
return pData;
}
};
struct Operation_Avg : public IOperation
{
//data for operation average of numbers.
struct Data : public IData
{
int a[5];
int total_numbers;
float result;
};
IData* Execute(IData *_pData)
{
//expected data is "Operation_Avg::Data_Avg"
Operation_Avg::Data *pData = dynamic_cast<Operation_Avg::Data*>(_pData);
if(pData == NULL)
{
return NULL;
}
pData->result = 0.0f;
for(int i = 0; i < pData->total_numbers; ++i)
{
pData->result += pData->a[i];
}
pData->result /= pData->total_numbers;
return pData;
}
};
Here, is the operation processor, the CPU.
struct CPU
{
enum OPERATION
{
ADDITION = 0,
AVERAGE
};
Operation_Add m_stAdditionOperation;
Operation_Avg m_stAverageOperation;
map<CPU::OPERATION, IOperation*> Operation;
CPU()
{
Operation[CPU::ADDITION] = &m_stAdditionOperation;
Operation[CPU::AVERAGE] = &m_stAverageOperation;
}
};
Sample:
CPU g_oCPU;
Operation_Add::Data stAdditionData;
stAdditionData.a = 10;
stAdditionData.b = 20;
Operation_Avg::Data stAverageData;
stAverageData.total_numbers = 5;
for(int i = 0; i < stAverageData.total_numbers; ++i)
{
stAverageData.a[i] = i*10;
}
Operation_Add::Data *pResultAdd = dynamic_cast<Operation_Add::Data*>(g_oCPU.Operation[CPU::ADDITION]->Execute(&stAdditionData));
if(pResultAdd != NULL)
{
printf("add = %d\n", pResultAdd->result);
}
Operation_Avg::Data *pResultAvg = dynamic_cast<Operation_Avg::Data*>(g_oCPU.Operation[CPU::AVERAGE]->Execute(&stAverageData));
if(pResultAvg != NULL)
{
printf("avg = %f\n", pResultAvg->result);
}
If you have the following functions
int f1(int i);
int f2(int i, int j);
You can define a generic function type like this
typedef int (*generic_fp)(void);
And then initialize your function array
generic_fp func_arr[2] = {
(generic_fp) f1,
(generic_fp) f2
};
But you will have to cast the functions back
int result_f1 = ((f1) func_arr[0]) (2);
int result_f2 = ((f2) func_arr[1]) (1, 2);
Obviously, it does not look like a good way to build a program
To make code look a little bit better you can define macros
#define F1(f, p1) ((f1)(f))(p1)
#define F2(f, p1, p2) ((f2)(f))(p1, p2)
int result_f1 = F1(func_arr[0], 2);
int result_f2 = F2(func_arr[1], 1, 2);
EDIT
Forgot to mention, you also have to define a type for every type of function
typedef int (*fi)(int); // type for function of one int param
typedef int (*fii)(int, int); // type for function of two int params
And to then cast stored pointers to those types
int result_f1 = ((fi) func_arr[0]) (2);
int result_f2 = ((fii) func_arr[1]) (1, 2);
Here is a complete example
#include <iostream>
typedef int (*generic_fp)(void);
typedef int (*fi)(int); // type for function of one int param
typedef int (*fii)(int, int); // type for function of two int params
#define F1(f, p1) ((fi)(f))(p1)
#define F2(f, p1, p2) ((fii)(f))(p1, p2)
int f1(int i);
int f2(int i, int j);
int main()
{
generic_fp func_arr[2] = {
(generic_fp) f1,
(generic_fp) f2
};
int result_f1_no_macro = ((fi) func_arr[0]) (2);
int result_f2_no_macro = ((fii) func_arr[1]) (1, 2);
int result_f1_macro = F1(func_arr[0], 2);
int result_f2_macro = F2(func_arr[1], 1, 2);
std::cout << result_f1_no_macro << ", " << result_f2_no_macro << std::endl;
std::cout << result_f1_macro << ", " << result_f2_macro << std::endl;
return 0;
}
int f1(int i)
{
return i * 2;
}
int f2(int i, int j)
{
return i + j;
}
The code above produces the following output
4, 3
4, 3
I'm trying to use in my implementation the fibonacci heap from boost but my program crashes, when I calling decrease function, this the example (W is a simple class):
struct heap_data
{
boost::heap::fibonacci_heap<heap_data>::handle_type handle;
W* payload;
heap_data(W* w)
{
payload = w;
}
bool operator<(heap_data const & rhs) const
{
return payload->get_key() < rhs.payload->get_key();
}
};
int main()
{
boost::heap::fibonacci_heap<heap_data> heap;
vector<heap_data> A;
for (int i = 0; i < 10; i++)
{
W* w = new W(i, i + 3);
heap_data f(w);
A.push_back(f);
boost::heap::fibonacci_heap<heap_data>::handle_type handle = heap.push(f);
(*handle).handle = handle; // store handle in node
}
A[5].payload->decr();
heap.decrease(A[5].handle);
return 0;
}
The problem is quite trivial.
You have two containers (vector A and heap heap).
The heap contains copies of the data in the vector:
A.push_back(f); // copies f!
handle_type handle = heap.push(f); // copies f again!
You set the handle only on the copy in the heap:
(*handle).handle = handle; // store handle in the heap node only
Hence, in the temporary f and the vector A's elements, the value of handle is indeterminate (you just didn't give it any value).
Therefore when you do
heap.decrease(A[5].handle);
you invoke Undefined Behaviour because you depend on the value of A[5].handle, which is uninitialized.
Simpler, correct, example:
Live On Coliru
#include <boost/heap/fibonacci_heap.hpp>
#include <boost/tuple/tuple_comparison.hpp>
struct W {
int a;
int b;
W(int a, int b) : a(a), b(b) { }
boost::tuple<int const&, int const&> get_key() const { return boost::tie(a, b); }
void decr() { b?a:--a, b?--b:b; }
};
struct heap_data;
using Heap = boost::heap::fibonacci_heap<heap_data>;
struct heap_data
{
W payload;
Heap::handle_type handle;
heap_data(W w) : payload(w), handle() {}
bool operator<(heap_data const & rhs) const {
return payload.get_key() < rhs.payload.get_key();
}
};
#include <vector>
#include <iostream>
int main()
{
Heap heap;
std::vector<Heap::handle_type> handles;
for (int i = 0; i < 10; i++)
{
Heap::handle_type h = heap.push(W { i, i + 3 });
handles.push_back(h);
(*h).handle = h;
}
(*handles[5]).payload.decr();
heap.decrease(handles[5]);
}
Since I cannot answer my own question in 8 hours after asking, I'm posting my solution here.
Made some mistakes in the incoming channel number and number of the vector element. Setting the value of channel-1 instead of channel fixed to problem.
My new function is as follows:
void input(long inlet, t_symbol *s, long ac, t_atom *av){
// GET VARIABLES
long channel = atom_getlong(av);
double value = atom_getfloat(av + 1);
long v_size = v_chan.size();
if(channel && v_size < channel){
for(int i = v_size; i < channel; i++){
v_chan.push_back(n_chan);
}
v_chan[channel - 1].value = value;
}
else if(channel){
v_chan[channel - 1].value = value;
}
}
I've got a vector containing structs, which I like to push_back with a new, empty struct.
Example code:
struct channels{
double value;
// eventually more variables
};
vector<channels> v_chan;
channels n_chan;
void push(){
v_chan.push_back(n_chan);
}
The problem is, if my vector contains elements, push_back add an element, but also overwrites the last element.
For example, if my vector size is 1 and element 0 has a value of 0.2, after push_back my vector size is 2, but element 0 and 1 have a value of 0.
What am I doing wrong here?
Real Code: (MAX/MSP external, function input is called in Max)
#include <maxcpp6.h>
#include <string>
#include <algorithm>
#include <vector>
using namespace std;
struct bind{
string param;
double* value;
int track;
double base;
double multiplier;
};
struct channels{
double value;
vector<int> bind;
};
vector<channels> v_chan;
vector<bind> v_bind(19);
channels n_chan;
class rec : public MaxCpp6<rec> {
public:
rec(t_symbol * sym, long ac, t_atom * av) {
setupIO(1, 1); // inlets / outlets
}
~rec() {}
// methods:
//SET BIND FUNCTION
void setBind(long inlet, t_symbol *s, long ac, t_atom *av){
}
void output(long track, long type){
}
void input(long inlet, t_symbol *s, long ac, t_atom *av){
// GET VARIABLES
long channel = atom_getlong(av);
double value = atom_getfloat(av + 1);
long v_size = v_chan.size();
if(v_size <= channel){
v_chan.push_back(n_chan);
}
else{
v_chan[channel].value = value;
}
}
void dump(long inlet){
for(int i = 1; i <= v_chan.size(); i++){
post("%d %.2f", i, v_chan[i].value);
}
}
void clearTrackBinds(long inlet){
}
void reset(long inlet){
clearTrackBinds(0);
}
};
C74_EXPORT int main(void) {
// create a class with the given name:
rec::makeMaxClass("solar_receiver");
REGISTER_METHOD_GIMME(rec, input);
REGISTER_METHOD_GIMME(rec, setBind);
REGISTER_METHOD(rec, dump);
REGISTER_METHOD(rec, clearTrackBinds);
REGISTER_METHOD(rec, reset);
}
I am trying to write a class and I finally got it to compile, but visual studio still shows there are errors (with a red line).
The problem is at (I wrote #problem here# around the places where visual studio draws a red line):
1. const priority_queue<int,vector<int>,greater<int> #># * CM::getHeavyHitters() {
2. return & #heavyHitters# ;
3. }
And it says:
"Error: expected an identifier" (at the first line)
"Error: identifier "heavyHitters" is undefined" (at the second line)
The first problem I don't understand at all. The second one I don't understand because heavyHitters is a a member of CM and I included CM.
BTW, I tried to build. It didn't fix the problem.
Thanks!!!
The whole code is here:
Count-Min Sketch.cpp
#include "Count-Min Sketch.h"
CM::CM(double eps, double del) {
}
void CM::update(int i, int long unsigned c) {
}
int long unsigned CM::point(int i) {
int min = count[0][calcHash(0,i)];
return min;
}
const priority_queue<int,vector<int>,greater<int>>* CM::getHeavyHitters() {
return &heavyHitters;
}
CM::CM(const CM &) {
}
CM::~CM() {
}
int CM::calcHash(int hashNum, int inpt) {
int a = hashFunc[hashNum][0];
int b = hashFunc[hashNum][1];
return ((a*inpt+b) %p) %w;
}
bool CM::isPrime(int a) {
bool boo = true;
return boo;
}
int CM::gePrime(int n) {
int ge = 2;
return ge;
}
Count-Min Sketch.h
#pragma once
#ifndef _CM_H
#define _CM_H
using namespace std;
#include <queue>
class CM {
private:
// d = ceiling(log(3,1/del)), w = ceiling(3/eps)
int d,w,p;
// [d][w]
int long unsigned *(*count);
// [d][2]
int *(hashFunc[2]);
// initialized to 0. norm = sum(ci)
int long unsigned norm;
// Min heap
priority_queue<int,vector<int>,greater<int>> heavyHitters;
// ((ax+b)mod p)mod w
int calcHash(int hashNum, int inpt);
// Is a a prime number
bool isPrime(int a);
// Find a prime >= n
int gePrime(int n);
public:
// Constructor
CM(double eps, double del);
// count[j,hj(i)]+=c for 0<=j<d, norm+=c, heap update & check
void update(int i, int long unsigned c);
// Point query ai = minjcount[j,hj(i)]
int long unsigned point(int i);
const priority_queue<int,vector<int>,greater<int>>* getHeavyHitters();
// Copy constructor
CM(const CM &);
// Destructor
~CM();
};
#endif // _CM_H
>> is a single token, the right-shift (or extraction) operator. Some compilers don't recognize it correctly in nested template specialization. You have to put a space between the two angle brackets like this:
Type<specType<nestedSpecType> > ident;
^^^