Getting a point on a sphere to sit at the north pole with all other points rotating the same amount

Say I have 10 points all on a sphere (randomly distributed) and I want to rotate the entire system to make sure one point sits at the north pole. How would I do this?

I went about it by looking at 3D rotation matrices:

http://en.wikipedia.org/wiki/Rotation_matrix

I rotate my point around the x-axis until the y component is zero and then rotate around the y-axis until the x component is zero. This should leave the point in question at either the north or south pole right?

My code looks like so:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#include <stdio.h> 
#include <string.h>
#include <math.h>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <time.h>
#include <stdlib.h>
#include <sstream>
using namespace std;
#define PI 3.14159265358979323846

int main()
{

  int a,b,c,f,i,j,k,m,n,s;
  double p,Time,Averagetime,Energy,energy,Distance,Length,DotProdForce,Forcemagnitude,
         ForceMagnitude[101],Force[101][4],E[1000001],En[501],x[101][4],y[101][4],
         Dist[101][101],Epsilon,z[101],theta,phi;

    /*  set the number of points */
    n=10;

    /* check that there are no more than 100 points */
    if(n>100){
      cout << n << " is too many points for me :-( \n";
      exit(0);
    }
  
    /* reset the random number generator */
    srand((unsigned)time(0));  
  
    for (i=1;i<=n;i++){
      x[i][1]=((rand()*1.0)/(1.0*RAND_MAX)-0.5)*2.0;
      x[i][2]=((rand()*1.0)/(1.0*RAND_MAX)-0.5)*2.0;
      x[i][3]=((rand()*1.0)/(1.0*RAND_MAX)-0.5)*2.0;
    
      Length=sqrt(pow(x[i][1],2)+pow(x[i][2],2)+pow(x[i][3],2));
    
      for (k=1;k<=3;k++){
        x[i][k]=x[i][k]/Length;
      }
    }

    /* calculate the energy */
    Energy=0.0;
  
    for(i=1;i<=n;i++){
      for(j=i+1;j<=n;j++){
        Distance=sqrt(pow(x[i][1]-x[j][1],2)+pow(x[i][2]-x[j][2],2)
		            +pow(x[i][3]-x[j][3],2));
      
        Energy=Energy+1.0/Distance;
      }
    }
  
   cout << fixed << setprecision(10) << "energy=" << Energy << "\n";  
  
  /* Save Values so far */
  
  for(i=1;i<=n;i++){
    for(j=1;j<=3;j++){
      y[i][j]=x[i][j];
    }
  }
 
  /* Choose each point in turn and make it the north pole note this is what the while loop os for, but have set it to a<2 to just look at first point */
  
  a=1;
  b=0;
  c=0;
  
  while(a<2){
  
  /* Find theta and phi to rotate points by */
  
  cout << fixed << setprecision(5) << "x[" << a << "][1]=" << x[a][1] << 
  " x[" << a << "][2]=" << x[a][2] << " x[" << a << "][3]=" << x[a][3] << "\n";
  
  theta=x[a][2]/x[a][3];
  theta=b*PI+atan(theta);
 
  /* Rotate Points by theta around x axis and then by phi around y axis */
  
  for(i=1;i<=n;i++){
    x[i][1]=x[i][1];
    x[i][2]=x[i][2]*cos(theta)-x[i][3]*sin(theta);
    x[i][3]=x[i][2]*sin(theta)+x[i][3]*cos(theta);
  }
 
  phi=x[a][1]/x[a][3];
  phi=c*PI+atan(phi);
  
  for(i=1;i<=n;i++){
    x[i][1]=x[i][1]*cos(phi)-x[i][3]*sin(phi);
    x[i][2]=x[i][2];
    x[i][3]=x[i][1]*sin(phi)+x[i][3]*cos(phi);
  }
  
  cout << fixed << setprecision(5) << "x[" << a << "][1]=" << x[a][1] << 
  " x[" << a << "][2]=" << x[a][2] << " x[" << a << "][3]=" << x[a][3] << "\n";
    
   if(x[a][3]==1.0 && x[a][2]==x[a][3]==0)
    a=a+1;
  else if(b==0 && c==0)
    for(i=1;i<=n;i++){
      for(j=1;j<=3;j++){
        x[i][j]=y[i][j];
        c=1;
      }
    }
  else if(b==0 && c==1)
    for(i=1;i<=n;i++){
      for(j=1;j<=3;j++){
        x[i][j]=y[i][j];
        b=1;
        c=0;
      }
    }
  else if(b==1 && c==0)
    for(i=1;i<=n;i++){
      for(j=1;j<=3;j++){
        x[i][j]=y[i][j];
        c=1;
      }
    }
  else if(b==1 && c==1)
    break;
 
  }
 
  energy=0.0;
  
  for(i=1;i<=n;i++){
    for(j=i+1;j<=n;j++){
      
      Distance=sqrt(pow(x[i][1]-x[j][1],2)+pow(x[i][2]-x[j][2],2)
                    +pow(x[i][3]-x[j][3],2));
      energy=energy+1.0/Distance;
    }
  }  
    
  cout << fixed << setprecision(10) << "ENERGY=" << energy << "\n";  
  cout << fixed << setprecision(5) << "x[" << a << "][1]=" << x[a][1] << 
  " x[" << a << "][2]=" << x[a][2] << " x[" << a << "][3]=" << x[a][3] << "\n";
  
  /* Output to help with gnuin.txt */
  ofstream File4 ("mypoints");
  for(i=1;i<=n;i++){
    File4 << x[i][1] << " " <<   x[i][2] << " " << x[i][3] << "\n";
  }
  File4.close(); 
  
  return 0;

}


Ok, so there are loads of issues here, like the if statement (line 103) shouldn't really have a condition for equal to a double as it will never work, but I can sort that out later using indirect comparison (some epsilon stuff). My real query is why does the rotation even though it is acting on all the points take the points off the sphere?

(As you can see the values have been normalised to make them all on the unit sphere in line 38).

I am not sure sure if this a maths issue or a c++ issue, but I find that most c++ users understand maths, but not necessarily the other way around which is why I have asked here. (Note: the energy of the system should not change by just rotating points around the sphere as a whole).

Thanks, A.
Last edited on
So I screwed up on line 85 by using the same variable. Should look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 for(i=1;i<=n;i++){
    new_x[i][1]=x[i][1];
    new_x[i][2]=x[i][2]*cos(theta)-x[i][3]*sin(theta);
    new_x[i][3]=x[i][2]*sin(theta)+x[i][3]*cos(theta);
  }
 
  phi=new_x[a][1]/new_x[a][3];
  phi=c*PI+atan(phi);
  
  for(i=1;i<=n;i++){
    x[i][1]=new_x[i][1]*cos(phi)-new_x[i][3]*sin(phi);
    x[i][2]=new_x[i][2];
    x[i][3]=new_x[i][1]*sin(phi)+new_x[i][3]*cos(phi);
  }
  


My bad.
Topic archived. No new replies allowed.