Creating clean array everytime function is run in Arduino code - c++

I'm writing a program which gets the distances from five ultrasonic sensors and uses a trilateration algorithm on every combination of distance values. It first outputs all the coordinates it recieves from the trilateration algorithm, then it filters out values which are too small or too large. However, it keeps outputting values from previous trilateration cycles as the array has not been reset.
#include "NewPing.h"
#include<stdio.h>
#include<stdlib.h>
#define TP0 11
#define EP0 13
#define TP1 3
#define EP1 4
#define TP2 6
#define EP2 2
#define TP3 5
#define EP3 7
#define TP4 10
#define EP4 8
#define MAX_DISTANCE 150
//sensor coordinates
int xcords [5] = {3, 45, 87, 87, 3};
int ycords [5] = {0, 16, 0, 58, 58};
int r = 3;
int n = 5;
float x = 0;
float y = 0;
int MAX_X = 85;
int MAX_Y = 62;
int sensor;
int count = 0;
int resultCount = 0;
bool reading = false;
void setup() {
Serial.begin (9600);
}
void
loop() {
while(count < 1){
count += 1;
int distances [3];
for (int r = 0; r<5; r++){
distances[r] = getValue(r);
if (distances[r] >= MAX_DISTANCE || distances[r] <= 2) {
getValue(r);
}
//Serial.print("Distance =");
//Serial.print(distances[r]);
//Serial.println(" cm ");
}
printCombination(distances, xcords, ycords, n, r);
//trilateration(distances[0], distances[1], distances[2]);
delay(5000);
}
}
int combinationUtil(int distances[], int data[], int dataCords[], int start, int end, int index, int r, float xresults[], float yresults[]);
// Needed for qsort. See http://w...content-available-to-author-only...s.com/reference/cstdlib/qsort/
int compare (const void * a, const void * b)
{ return ( *(int*)a - *(int*)b ); }
// The main function that prints all combinations of size r
// in arr[] of size n. This function mainly uses combinationUtil()
int printCombination(int distances[], int xcords[], int ycords[], int n, int r)
{
// A temporary array to store all combination one by one
int data[r];
int xdataCords[r];
int ydataCords[r];
float xresults[10];// the arrays causing the issue
float yresults[10];
// Sort array to handle duplicates
qsort (distances, n, sizeof(int), compare);
// Print all combination using temprary array 'data[]'
combinationUtil(distances, data, xdataCords, ydataCords, 0, n-1, 0, r, xresults, yresults);
sorting(xresults,yresults);
resultCount = 0;
Serial.print("\n");
}
/* distances[] ---> Input Array
data[] ---> Temporary array to store current combination
start & end ---> Staring and Ending indexes in distances[]
index ---> Current index in data[]
r ---> Size of a combination to be printed */
float* combinationUtil(int distances[], int data[], int xdataCords[], int ydataCords[], int start, int end, int index, int r, float xresults[], float yresults[])
{
// Current combination is ready to be printed, print it
if (index == r)
{
trilateration(data[0], data[1], data[2], xdataCords[0], xdataCords[1], xdataCords[2], ydataCords[0], ydataCords[1], ydataCords[2], xresults, yresults);
resultCount++;
}
// replace index with all possible elements. The condition
// "end-i+1 >= r-index" makes sure that including one element
// at index will make a combination with remaining elements
// at remaining positions
for (int i=start; i<=end && end-i+1 >= r-index; i++)
{
data[index] = distances[i];
xdataCords[index] = xcords[i];
ydataCords[index] = ycords[i];
combinationUtil(distances, data, xdataCords, ydataCords, i+1, end, index+1, r, xresults, yresults);
// Remove duplicates
while (distances[i] == distances[i+1])
i++;
}
}
float* trilateration(int d1,int d2, int d3, int x1, int x2, int x3, int y1, int y2, int y3, float xresults[], float yresults[]){
float va = ((sq(d2) - sq(d3)) - (sq(x2) - sq(x3)) - (sq(y2) - sq(y3))) / (2) ;
float vb = ((sq(d2) - sq(d1)) - (sq(x2) - sq(x1)) - (sq(y2) - sq(y1))) / (2) ;
y = ((vb*(x3-x2)) - (va*(x1-x2))) / (((y1-y2)*(x3-x2)) - ((y3-y2)*(x1-x2)));
x = (va - (y*(y3-y2))) / (x3-x2);
//Serial.print(d1);
//Serial.print(d2);
//Serial.print(d3);
Serial.print("The coordinates are: ");
Serial.print(abs(x));
xresults[resultCount] = abs(x);
Serial.print(", ");
Serial.println(abs(y));
yresults[resultCount] = abs(y);
//sorting(xresults, yresults);
return xresults, yresults;
}
void sorting(float xresults[], float yresults[]){
float xfinal[10];
float yfinal[10];
qsort (xresults, 10, sizeof(int), compare);
qsort (yresults, 10, sizeof(int), compare);
for (int i = 0; i<10; i++){
if (xresults[i] > 3 && xresults[i] < MAX_X){
xfinal[i] = xresults[i];
Serial.print("x=");
Serial.print(xresults[i]);
Serial.print("\n");
}
if (yresults[i] > 10 && yresults[i] < MAX_Y){
yfinal[i] = yresults[i];
Serial.print("y=");
Serial.print(yresults[i]);
Serial.print("\n");
}
}
}
float getValue(int sensor){
NewPing sonar0(TP0, EP0, MAX_DISTANCE);
NewPing sonar1(TP1, EP1, MAX_DISTANCE);
NewPing sonar2(TP2, EP2, MAX_DISTANCE);
NewPing sonar3(TP3, EP3, MAX_DISTANCE);
NewPing sonar4(TP4, EP4, MAX_DISTANCE);
switch(sensor){
case 0:
return sonar0.ping_cm();
case 1:
return sonar1.ping_cm();
case 2:
return sonar2.ping_cm();
case 3:
return sonar3.ping_cm();
case 4:
return sonar4.ping_cm();
}
}
the arrays "xresults and yresults" is the array causing the problem. You can see that I have redefined it every time printCombination is called so it should be cleared right?
This is my output:
The coordinates are: 40.33, 34.88
The coordinates are: 58.62, 8.00
The coordinates are: 42.09, 8.00
The coordinates are: nan, 7.74
The coordinates are: 59.14, 24.17
The coordinates are: 47.81, 13.41
The coordinates are: 47.81, 7.74
x=40.25
x=58.56
y=24.16
x=47.81
y=13.41
x=47.81
x=32.99
New distance call
The coordinates are: 40.65, 35.72
The coordinates are: 58.62, 8.00
The coordinates are: 42.09, 8.00
The coordinates are: nan, 7.28
The coordinates are: 60.07, 25.03
The coordinates are: 47.81, 13.41
The coordinates are: 47.81, 7.28
x=40.50
x=58.56
y=35.56
x=47.81
y=13.41
x=47.81
x=32.99
New distance call
The coordinates are: 24.98, 15.69
The coordinates are: 50.48, 8.00
The coordinates are: 112.35, 8.00
The coordinates are: nan, 25.91
The coordinates are: 14.66, 84.64
The coordinates are: 91.00, 12.26
The coordinates are: 91.00, 25.91
x=14.63
x=50.31
y=15.70
y=12.26
y=25.91
x=32.99
As you can see there are values which are not in the list of coordinates appearing in the print out after the coordinates.

Related

How can I make my c++ code run faster with eigen library?

I have written a parallelized c++ code, which functions as follows :
There are 75 'w' points, and each of them is sent to one processor.
For each 'w' point, I am defining a matrix. Then I am diagonalizing it. I am using the eigenvectors to compute a particular quantity by summing over the fourth power of each of the matrix elements. And then I average this quantity over 300 iterations of the matrix.
So I am using Eigen package for this calculation, and I compile the code with mpiCC -I eigen -Ofast filename.cpp. For a 512 x 512 matrix, the whole procedure takes 2.5 hours. Currently I need to do the same for a 2748 x 2748 matrix, and it's still going on after approx. 12:30 hrs. Is there anyway I can make the code run faster?
The code is given here for reference :
#include <iostream>
#include <complex>
#include <cmath>
#include<math.h>
#include<stdlib.h>
#include<time.h>
#include<Eigen/Dense>
#include<fstream>
#include<random>
#include "mpi.h"
#define pi 3.14159
using namespace std;
using namespace Eigen;
#define no_of_processor 75 // no of processors used for computing
#define no_of_disorder_av 300 //300 iterations for each w
#define A_ratio 1 //aspect ratio Ly/Lx
#define Lx 8
#define w_init 0.1 // initial value of potential strength
#define del_w 0.036 // increment of w in each loop
#define w_loop 75 // no of different w
#define alpha (sqrt(5.0)-1.0)/(double)2.0
double onsite_pot(int x,int y, int z, double phi, double alpha_0){
double B11=alpha;
double B12=alpha;
double B13=alpha;
double b1= (double)B11*x+(double)B12*y+(double)B13*z;
double c11= 1.0-cos(2*M_PI*b1+phi); //printf("%f\n",c1);
double c12= 1.0+(alpha_0*cos(2*M_PI*b1+phi));
double c1=c11/c12;
return c1;
}
int main(int argc, char *argv[])
{
clock_t begin = clock();
/*golden ratio----------------------------*/
char filename[200];
double t=1.0;
int i,j,k,l,m;//for loops
double alpha_0=0;
int Ly=A_ratio*Lx;
int Lz= A_ratio*Lx;
int A=Lx*Ly;
int V=A*Lz; //size of the matrix
int numtasks,rank,RC;
RC=MPI_Init(&argc,&argv);
if (RC != 0) {
printf ("Error starting MPI program. Terminating.\n");
MPI_Abort(MPI_COMM_WORLD, RC);
}
MPI_Comm_size(MPI_COMM_WORLD,&numtasks);
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
sprintf(filename,"IPR3D%dalpha%g.dat",rank+1,alpha_0);
ofstream myfile;
myfile.open(filename, ios::app); //preparing file to write in
int n = w_loop/no_of_processor;
double w=w_init+(double)(n*rank*del_w);
int var_w_loop = 0;
MatrixXcd H(V,V); // matrix getting defined here
MatrixXcd evec(V,V); // matrix for eigenvector
VectorXcd temp(V); // vector for a temporary space used later in calculation
double IPR[V], E_levels[V]; // for average value of the quantity and eigen values.
do{
for(i=0;i<V;i++)
{
IPR[i]=E_levels[i]=0.0;
}
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
/*----loop for disorder average---------------------------*/
for (l=0;l<no_of_disorder_av;l++){
for (i=V; i<V; i++)
{
for (j=V; j<V; j++)
H(i,j)=0;
}
double phi=(2*M_PI*(double)l)/(double)no_of_disorder_av;
//matrix assignment starts
int z=0;
for (int plane=0; plane<Lz; plane++)
{
z += 1 ;
int y=0;
int indx1= plane*A ; //initial index of each plane
int indx2= indx1+A-1; // last index of each plane
for (int linchain=0; linchain<Ly; linchain++){
y += 1;
int x=0;
int indx3= indx1 + linchain*Lx ; //initial index of each chain
int indx4= indx3 + Lx-1 ; //last index of each chain
for (int latpoint=0; latpoint<Lx; latpoint++){
x += 1;
int indx5= indx3 +latpoint; //index of each lattice point
H(indx5,indx5)= 2*w*onsite_pot(x,y,z,phi,alpha_0); //onsite potential
if (indx5<indx4){ //hopping inside a chain
H(indx5,(indx5+1))= t; //printf("%d %d\n",indx5,indx5+1);
H((indx5+1),indx5)= t;
}
if (indx5<=(indx2-Lx)){ //hopping between different chain
H(indx5,(indx5+Lx))= t; //printf("%d %d\n",indx5,indx5+Lx);
H((indx5+Lx),indx5)= t;
printf("%d\n",indx5);
}
if (indx5<(V-A)){
H(indx5,(indx5+A))= t; //printf("%d %d\n",indx5,indx5+A);// hopping between different plane
H((indx5+A),indx5)= t;
}
} //latpoint loop
}//linchain loop
}//plane loop
//PB..............................................
for (int plane=0; plane<Lz; plane++){
int indx1= plane*A; //initial index of each plane
int indx2 = indx1+A-1 ;//last indx of each plane
//periodic boundary condition x
for (int linchain=0; linchain<Ly; linchain++){
int indx3 = indx1 + linchain*Lx; // initital index of each chain
int indx4=indx3+ Lx-1; //last index of each chain
H(indx3,indx4)= t; //printf("%d %d\n",indx3,indx4);
H(indx4,indx3)= t;
}//linchain loop
//periodic boundary condition y
for (int i=0; i<Lx; i++){
int indx5 = indx1+i;
int indx6 = indx5+(Ly-1)*Lx; //printf("%d %d\n",indx5,indx6);
H(indx5,indx6)=t;
H(indx6,indx5)=t;
}
}//plane loop
//periodic boundary condition in z
for (int i=0; i<A; i++){
int indx1=i ;
int indx2=(Lz-1)*A+i ;
H(indx1,indx2)= t; //printf("%d %d\n",indx1,indx2);
H(indx2,indx1)= t ;
}
//matrix assignment ends
/**-------------------------------------------------------*/
double Tr = abs(H.trace());
for(i=0;i<V;i++)
{
for(j=0;j<V;j++)
{
if(i==j)
{
H(i,j) = H(i,j)-(Tr/(double)V);
}
}
}
SelfAdjointEigenSolver<MatrixXcd> es(H); //defining the diagonalizing function
double *E = NULL;
E = new double[V]; // for the eigenvalues
for(i=0;i<V;i++)
{
E[i]=es.eigenvalues()[i];
//cout<<"original eigenvalues "<<E[i]<<"\n";
}
evec=es.eigenvectors();
double bandwidth = E[V-1] - E[0];
for(i=0;i<V;i++)
E[i]=E[i]/bandwidth;
for(i=0;i<V;i++)
{
E_levels[i] = E_levels[i]+E[i]; //summing over energies for each iteration
}
delete[] E;
E=NULL;
//main calculation process
for(i=0;i<V;i++)
{
temp = evec.col(i);
double num=0.0,denom=0.0;
for(j=0;j<V;j++)
{
num=num+pow(abs(temp(j)),4);
denom=denom+pow(abs(temp(j)),2);
}
IPR[i] = IPR[i]+(num/(denom*denom));
} //calculation ends
}//no_of_disorder_av loop (l)
for(i=0; i<V; i++)
{
myfile<<w<<"\t"<<(E_levels[i]/(double)no_of_disorder_av)<<"\t"
<<(IPR[i]/(double)no_of_disorder_av)<<"\n"; //taking output in file
}
var_w_loop++; // counts number of w loop
w+= del_w; // proceeds to next w
}while(var_w_loop<n) ; // w varying do while loop
MPI_Finalize();
clock_t end = clock();
double time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
printf("time spent %f s\n\n",time_spent);
return 0;
}

Find and list all char clusters in the string C++

I'm looking for some help finding all clusters of chars in the string in C++. The exact task is:
Given the following “2D string” (in C++ expression):
string text =
"#################aa##a###c######\n" +
"####bbbbaaaabbbbbaaaaa###ccc##cc\n" +
"#o##bbbbaaaabbbbbaaaaa###c#c##cc\n" +
"#oo#bbbbaeeabbbbbbbbaa##cc#ccccc\n" +
"#o##bbbbaeeabbbbbaaaaaa#cc#####c\n" +
"#o##bbbbaaaabbbbbaaaaaa#cc#####c\n";
Write a program computing the area of each contiguous region of the same >symbols. Two equal symbols belong to the same area if they are neighbors either >in a row or in a column. Don’t count the newline (\n) symbols, they are just to >form the 2D string.
The main function should be recursive.
Hint: use an extra 2D array to mark each symbol in the 2D string if it is >already counted or not. Scan the array row-wise until a not counted yet symbol >is found. Then, run the recursive area-computing function starting from this >symbol. Continue until all symbols are marked as counted.
The program output should look (more or less) like:
Region of symbols #, area …
Region of symbols a, area …
Region of symbols #, area …
Region of symbols c, area …
My current code looks like this:
#include <iostream>
#include <string>
using namespace std;
int cords (string str, int x, int y) {
int length, i, position, lines = 0, x_max, y_max;
char symbol;
length = str.length();
for (i = 0; i < length; i++) {
symbol = str[i];
if (symbol == '\n')
lines++;
}
length -= lines;
x_max = length / lines;
y_max = length / x_max;
position = x - 1 + (y - 1) * x_max + y - 1;
if (x <= x_max && y <= y_max)
return position;
}
int clusterMiner (char symbol, string str, int x, int y, int counter, int last) {
if (x > 32 || y > 6) {
return counter;
} else {
if (str[cords(str, x++, y)] == symbol) {
counter++;
return clusterMiner(symbol, str, x++, y, counter, x);
} else if (str[cords(str, 1, y++)] == symbol) {
return clusterMiner(symbol, str, 1, y++, counter, x);
}
}
}
int main () {
int length, lines, i, j, k, l, counter;
string text = // 32 elements per line
"#################aa##a###c######\n" // 32
"####bbbbaaaabbbbbaaaaa###ccc##cc\n" // 64
"#o##bbbbaaaabbbbbaaaaa###c#c##cc\n" // 96
"#oo#bbbbaeeabbbbbbbbaa##cc#ccccc\n" // 128
"#o##bbbbaeeabbbbbaaaaaa#cc#####c\n" // 160
"#o##bbbbaaaabbbbbaaaaaa#cc#####c\n"; // 192
counter = clusterMiner('#', text, 1, 1, 0, 0);
cout << counter;
return 0;
}
Cords function is just for easier interaction with the two dimensions of the string.
I'm not sure what to do next. Right now the program counts only some of the symbols as it stops at the first different one ignoring these which are connected to further nodes.
Thanks!
First, do not calculate x_max and y_max all the time newly, just do it once and store it in a variable. Then, you will have to iterate over the whole field:
char get(int x, int y)
{
// + 1: the newline!!!
return field[x + y * (x_max + 1)];
}
void countAll()
{
calculateMaxima();
// created your visited array now
for(unsigned int y = 0; y <= y_max; ++y)
{
for(int x = 0; x <= x_max; ++x)
{
if(!visited[x, y])
{
count = 0;
search(get(x, y), x, y);
// output count here...
}
}
}
}
Each time we hit a character not yet visited, i. e. a new one, we start a new search. For each search, we have to consider four neighbours for each current position {x, y}:{x +/- 1, y} and {x, y +/- (x_max + 1} (apart from the positions at the edges, which have less). So your search might look like this:
void visit(char symbol, int x, int y)
{
if(!visited[x][y] && get(x, y) == symbol)
{
++count;
++visited[x][y] = true;
}
search(symbol, x, y);
}
void search(char symbol, int x, int y)
{
if(x > 0)
visit(x - 1, y);
if(x < max_x)
visit(x + 1, y);
if(y > 0)
visit(x, y - 1);
if(y < max_y)
visit(x, y + 1);
}
For now, I am assuming count, visited and x/y_max being some global variables. Cleaner, as we are C++, would be writing a separate class for this purpose:
class ClusterMiner
{
unsigned int count;
std::string field;
// ...
void visit(char symbol, int x, int y);
void search(char symbol, int x, int y);
// ...
public:
void countAll();
};
Code is untested and incomplete, it shall only give you the necessary hints to find your way...
Side note: If you have unconnected regions of the same character, these will be detected as such. If this is not desired, you might sum up the results e. g. in a std::map<char, unsigned int> and iterate over this one after you finished counting...

Explain working of compareX in qsort() library function

I was searching for the closest pair code and i found this which has used qsort() library function. I basically didn't get the concept of how it's compare parameter works. Explanation related to this particular code will be more appreciated. Thanks.
#include <iostream>
#include <float.h>
#include <stdlib.h>
#include <math.h>
using namespace std;
// A structure to represent a Point in 2D plane
struct Point
{
int x, y;
};
/* Following two functions are needed for library function qsort().
Refer: http://www.cplusplus.com/reference/clibrary/cstdlib/qsort/ */
// Needed to sort array of points according to X coordinate
int compareX(const void* a, const void* b)
{
Point *p1 = (Point *)a, *p2 = (Point *)b;
return (p1->x - p2->x);
}
// Needed to sort array of points according to Y coordinate
int compareY(const void* a, const void* b)
{
Point *p1 = (Point *)a, *p2 = (Point *)b;
return (p1->y - p2->y);
}
// A utility function to find the distance between two points
float dist(Point p1, Point p2)
{
return sqrt( (p1.x - p2.x)*(p1.x - p2.x) +
(p1.y - p2.y)*(p1.y - p2.y)
);
}
// A Brute Force method to return the smallest distance between two points
// in P[] of size n
float bruteForce(Point P[], int n)
{
float min = FLT_MAX;
for (int i = 0; i < n; ++i)
for (int j = i+1; j < n; ++j)
if (dist(P[i], P[j]) < min)
min = dist(P[i], P[j]);
return min;
}
// A utility function to find minimum of two float values
float min(float x, float y)
{
return (x < y)? x : y;
}
// A utility function to find the distance beween the closest points of
// strip of given size. All points in strip[] are sorted accordint to
// y coordinate. They all have an upper bound on minimum distance as d.
// Note that this method seems to be a O(n^2) method, but it's a O(n)
// method as the inner loop runs at most 6 times
float stripClosest(Point strip[], int size, float d)
{
float min = d; // Initialize the minimum distance as d
// Pick all points one by one and try the next points till the difference
// between y coordinates is smaller than d.
// This is a proven fact that this loop runs at most 6 times
for (int i = 0; i < size; ++i)
for (int j = i+1; j < size && (strip[j].y - strip[i].y) < min; ++j)
if (dist(strip[i],strip[j]) < min)
min = dist(strip[i], strip[j]);
return min;
}
// A recursive function to find the smallest distance. The array Px contains
// all points sorted according to x coordinates and Py contains all points
// sorted according to y coordinates
float closestUtil(Point Px[], Point Py[], int n)
{
// If there are 2 or 3 points, then use brute force
if (n <= 3)
return bruteForce(Px, n);
// Find the middle point
int mid = n/2;
Point midPoint = Px[mid];
// Divide points in y sorted array around the vertical line.
// Assumption: All x coordinates are distinct.
Point Pyl[mid+1]; // y sorted points on left of vertical line
Point Pyr[n-mid-1]; // y sorted points on right of vertical line
int li = 0, ri = 0; // indexes of left and right subarrays
for (int i = 0; i < n; i++)
{
if (Py[i].x <= midPoint.x)
Pyl[li++] = Py[i];
else
Pyr[ri++] = Py[i];
}
// Consider the vertical line passing through the middle point
// calculate the smallest distance dl on left of middle point and
// dr on right side
float dl = closestUtil(Px, Pyl, mid);
float dr = closestUtil(Px + mid, Pyr, n-mid);
// Find the smaller of two distances
float d = min(dl, dr);
// Build an array strip[] that contains points close (closer than d)
// to the line passing through the middle point
Point strip[n];
int j = 0;
for (int i = 0; i < n; i++)
if (abs(Py[i].x - midPoint.x) < d)
strip[j] = Py[i], j++;
// Find the closest points in strip. Return the minimum of d and closest
// distance is strip[]
return min(d, stripClosest(strip, j, d) );
}
// The main functin that finds the smallest distance
// This method mainly uses closestUtil()
float closest(Point P[], int n)
{
Point Px[n];
Point Py[n];
for (int i = 0; i < n; i++)
{
Px[i] = P[i];
Py[i] = P[i];
}
qsort(Px, n, sizeof(Point), compareX);
qsort(Py, n, sizeof(Point), compareY);
// Use recursive function closestUtil() to find the smallest distance
return closestUtil(Px, Py, n);
}
// Driver program to test above functions
int main()
{
Point P[] = {{2, 3}, {12, 30}, {40, 50}, {5, 1}, {12, 10}, {3, 4}};
int n = sizeof(P) / sizeof(P[0]);
cout << "The smallest distance is " << closest(P, n);
return 0;
}
The last parameter of qsort is a pointer to a function with a specific signature: it must take two void* pointers, and return an int that indicates which of the two passed items is smaller or if the two items are the same. The specifics are here, but generally a positive result indicates that the second item is smaller, a negative indicates that the first item is smaller, and zero indicates the equaliity.
The implementation of compareX
int compareX(const void* a, const void* b)
{
Point *p1 = (Point *)a, *p2 = (Point *)b;
return (p1->x - p2->x);
}
follows the general pattern for comparison functions. First, it converts the void* pointer to the Point type, because it "knows" that it is used together with an array of Point structures. Then it subtracts the x coordinates of the two points:
p1->x - p2->x
Note that the result of the subtraction is going to be positive if the second point's x is smaller, negative when the second point's x is greater, and zero when the two xs are the same. This is precisely what qsort wants the cmp function to do, so the subtraction operation fulfills the contract of the comparison function.

Given a 2D array, convert to Z-Order

Having trouble wrapping my head around this conversion. I want to recursively convert a 2D NxN matrix into its z-order version.
For example given array:
[ 1 2 ]
[ 3 4 ]
The Z-order is
[ 1 2 3 4]
What are the steps recursively for the z-order conversion?
The recursive way is simple:
visit top-left
visit top-right
visit bottom-left
visit bottom-right
In code
#include <iostream>
template<typename M, typename CBACK>
void zorder(const M& m, int y0, int x0, int size,
CBACK cback)
{
if (size == 1) {
// Base case, just one cell
cback(m[y0][x0]);
} else {
// Recurse in Z-order
int h = size/2;
zorder(m, y0, x0, h, cback); // top-left
zorder(m, y0, x0+h, h, cback); // top-right
zorder(m, y0+h, x0, h, cback); // bottom-left
zorder(m, y0+h, x0+h, h, cback); // bottom-right
}
}
void print(int x) {
std::cout << x << " ";
}
int main(int argc, const char *argv[]) {
int x[][4] = {{ 1, 2, 3, 4},
{ 5, 6, 7, 8},
{ 9, 10, 11, 12},
{13, 14, 15, 16}};
zorder(x, 0, 0, 4, print);
std::cout << std::endl;
return 0;
}
Output of this program is
1 2 5 6 3 4 7 8 9 10 13 14 11 12 15 16
Note that there is also another non-recursive approach: to visit the elements in z-order you can just iterate over a counter and take odd-bits as y and even-bits as x (counting bits from 0):
int zorder_x_of(int index) {
int x = 0;
for (int b=0,k=0; (1<<b) <= index; b+=2,k++) {
x += ((index & (1<<b)) != 0) << k;
}
return x;
}
int zorder_y_of(int index) {
return zorder_x_of(index>>1);
}
template<typename M, typename CBACK>
void zorder2(const M& m, int size, CBACK cback)
{
for (int i=0; i<size*size; i++) {
cback(m[zorder_y_of(i)][zorder_x_of(i)]);
}
}
Note:
In the above code samples I created a function that accepts a "callback" (named cback) that is something that will be called with the elements of the matrix, one at a time, in z-order.
To allow using both as matrix and as callback anything that supports double [] indexing and anything that can be called I used a C++ template.
In the main program as matrix I've used a bi-dimensional array of integers and a function, but the code would have compiled even for example with an std::vector< std::vector< double > > as matrix and an object instance of a class providing operator()(double) as callback.
A 2D matrix behaves internally as an 1D array i.e. it is already in "Z order".
Just iterate across the pointer that points to the first element up to NxM where N is the number of columns and M the number of rows.
example:
int arr[2][2] = {{2,4},{3,5}};
for (int i=0; i<2 * 2; ++i){
std::cout << *(&arr[0][0] + i); // or *(arr + i)
}

How to add/subtract to value rather than just be that value

Using the Openframeworks library in C++, I have the radius of a glow (max_distance) that is determined by the stretch of the mouse dragging across the screen (mouseDragX). It works fine.
But rather than every time I resize it (by dragging the mouse), I want it not to start at 0 and follow the mouse drag directly.
max_distance = mouseDragX/2;
But rather, if I have already dragged the mouse to the right to say 200 on a previous drag, that the next time I drag the mouse, and go into the opposite direction (negative numbers) that the value of max_distance decreases by that amount, instead of just being that amount.
I thought it would be
max_distance += mouseDragX/2;
but that seems to kill it altogether
Can you help me?
#include "testApp.h"
//--------------------------------------------------------------
void testApp::setup(){
ofSetWindowShape(700,700);
max_distance = 700; // ofDist didn't work(?) // ofDist(0,0,700,700);
ofEnableSmoothing();
ofEnableAlphaBlending();
}
//--------------------------------------------------------------
void testApp::update(){
max_distance = mouseDragX/2;
if (max_distance < 0) max_distance = 0;
}
//--------------------------------------------------------------
void testApp::draw(){
string str = "mouseDragX: ";
str += ofToString(mouseDragX)+" ";
ofSetWindowTitle(str);
int i,j;
int height = ofGetHeight();
int width = ofGetWidth();
for(i = 0; i <= height; i += 20) {
for(j = 0; j <= width; j += 20) {
float dist_color = getDistance(mouseX, mouseY, i, j); // for definition of getDistance, look below!
dist_color = dist_color/max_distance * 100;
// to get the colors into the range between 0 and 255, multiply the values by 5.
ofSetColor(dist_color*5,dist_color*5,dist_color*5, 123);
ofEllipse(i, j, 20, 20);
}
}
}
//--------------------------------------------------------------
void testApp::keyPressed (int key){
}
//--------------------------------------------------------------
void testApp::keyReleased (int key){
}
//--------------------------------------------------------------
void testApp::mouseMoved(int x, int y ){
// shift values down
for (int i = 0; i < 1; /*<<- length of array*/ i++) {
pmouseX[i] = pmouseX[i+1];
pmouseY[i] = pmouseY[i+1];
}
// make pmouseX/Y[0] be the previous mouse position. [1] = current
pmouseX[1] = mouseX;
pmouseY[1] = mouseY;
}
//--------------------------------------------------------------
void testApp::mouseDragged(int x, int y, int button){
mouseDragX = (mouseX - pmouseX[0]);
}
//--------------------------------------------------------------
void testApp::mousePressed(int x, int y, int button){
// mouseDragX = mouseDragY = 0; // The drag starts here
}
//--------------------------------------------------------------
void testApp::mouseReleased(){
}
float testApp::getDistance(int startX, int startY, int endX, int endY){
return sqrt((endX-startX)*(endX-startX) + (endY-startY)*(endY-startY));
}
Thank you so much.
If I understand correctly, you want todo something like this.
// Every time the mouse *stops* moving, (say on mouse-up
// message) save previous max_distance
int base = max_distance;
// when mouse moves
max_distance = base + mouseDragX/2;
If max_distance and mouseDragX are int values, the division by 2 results in an integer division that can induce losses.
This is especially true if mouseDragX value's is 1 at some time. This will result in 1 / 2 (integer division) and returns 0.
Example:
Lets consider that mouseDragX takes 3 different values (3 cycles):
3, 1, -4
One would expect that max_distance will be increased by (3 / 2) + (1 / 2) - (4 / 2) = 0.
But due to integer truncation, this will infact result to 1 + 0 - 2 = -1.
What if you use floats instead of int, and just round max_distance to an int when you really need it's value ?