How to draw a circle in 3D when i have an array of n points that lay on the circle

Hello everyone!
I am working on a project where I want to visualize the Hopf Fibration using the stereographic projection from 4D onto 3D.
The maths part is working fine, but I have problems plotting the circles in 3D space.
My idea was to have an array of points which lay on the circle and using curveVertex() to plot a circle with it. The problem is, that with equidistant point this method worked fine using only a few points, but now i have points that are not equally distributed on the circle and then the forms I plot do not look like circles anymore. It does work if i choose very many points (like 100 or something like that). I would like to solve it in a nicer way, which takes less computing time…
Is there an easy way to do it? I tried playing around with curveTightness(), but did not get better results (only with equidistant points it worked out nicely)

So the core of my problem is that i have to draw circles in 3D and with the circle() or ellipse() function i have to find out the rotations around the 3 axes which seems too difficult…
Using the method I use now seems not like a clean solution because I need a lot of points to draw each circle.
Is there another method that makes more sense than these?

Here is the relevant part of the code:

//library for complex numbers: QScript
import org.qscript.*;
import org.qscript.editor.*;
import org.qscript.errors.*;
import org.qscript.events.*;
import org.qscript.eventsonfire.*;
import org.qscript.operator.*;

Complex i = new Complex(0,1); //initialize i

//SETUP ARRAY OF CIRCLE POINTS
int noPoints = 100; //how many points will be used to draw 1 circle; must be >=3
int noCircles = 2; //how many circles do you want to plot?
Vector[][]circlePoints = new Vector[noCircles][noPoints];

//SETUP ARRAY OF POINTS OF INTEREST IN C
Complex[] startingPoints = new Complex[noCircles]; //points on S^2 of which we want to find fibres



void setup() {
  size(800, 800, P3D);
  frameRate(10); //fix-bug-thing
  
  //FOR NOW:::::::SETUP STARTING POINTS (i will write a function that fills the array with useful points later)
  startingPoints[0] = new Complex(1,1);
  startingPoints[1] = new Complex(0,2);
}


void draw(){
  background(0);
  
  //CHOOSE CAMERA
  //camera(width/2, height/2, (height/2) / tan(PI/6), width/2, height/2, 0, 0, 1, 0); //centered camera
  camera(mouseX, height/2, (height/2) / tan(PI/6), width/2, height/2, 0, 0, 1, 0); //camera which rotates objects with MouseX
  
  //SETUP COORDINATE SYSTEM
  centerCoordinatesystem();
  drawAxes(300);
  nameAxes(300);
  
  //DRAW CIRCLES
  
  //CxComplex s_4D = new CxComplex(findFiberPoint(s));
  //println("point in fiber of s", s_4D.z_1, s_4D.z_2 );
  fillArray();
  //println(circlePoints[0], circlePoints[1], circlePoints[2], circlePoints[3]);
  drawCircle();
  
}

//__________________SETUP COORDINATE SYSTEM FUNCTIONS________
void centerCoordinatesystem(){
  translate(width/2-50, height/2+50, 0);
  scale(20);
  rotateX(3*PI/8);
  rotateZ(PI/8);
}

void drawAxes(float size){
  //X  - red
  stroke(192,0,0);
  strokeWeight(0.07);
  line(0,0,0,size,0,0);
  //Y - green
  stroke(0,192,0);
  line(0,0,0,0,size,0);
  //Z - blue
  stroke(0,0,192);
  line(0,0,0,0,0,size);
}

void nameAxes(float size){
  textSize(20);
  text("x",size+2,0,0);
  text("y",0,size+2,0);
  text("z",0,0,size+2);
}

//_______MATHEMATICAL ALGORITHM FUNCTIONS________________

CxComplex findFiberPoint(Complex p){ //put in complex number p and get one point on circle in S^3
//  (x_1,y_2,x_2,y_2) is coordinate in C^2
//  trick: set y_2 =0.
float x_1;
float x_2;
float y_1;
x_2 = sqrt(1/(1+ pow((float)p.real,2)+ pow((float)p.imag,2)));
x_1 = (float)p.real*x_2;
y_1 = (float)p.imag*x_2;
CxComplex p_fiber = new CxComplex(x_1,y_1,x_2,0);
return p_fiber;
}

CxComplex getNewPoint (CxComplex p){ //generate new point on same fiber
  //go fourth of orbit to find next point
  Complex t= new Complex(2*PI/noPoints);
  Complex z_1_second = p.z_1.mult(Complex.exp(i.mult(t)));
  Complex z_2_second = p.z_2.mult(Complex.exp(i.mult(t)));
  
  CxComplex p_2 = new CxComplex(z_1_second, z_2_second);
  return p_2;
}

Vector projectPoint(CxComplex p){//put in point in 4D get it projected into R^3 via stereographic projection with N=(0,0,0,1)
                                 //for projecting p, p', M
Vector p_projected = new Vector(p.z_1.real/(1-p.z_2.imag),p.z_1.imag/(1-p.z_2.imag),p.z_2.real/(1-p.z_2.imag));
return p_projected;
}

//_____________GRAPHICS FUNCTIONS___________
void fillArray(){ //gives #noPoints points on the circle in R3, (evenly spaced on the circle in C2)
  //CxComplex p_i = new CxComplex(findFiberPoint(complex)); //create copy of p to change throughout the loop
  
  CxComplex[] PointsInC2 = new CxComplex[noCircles]; //array of points in C2
  for(int i=0; i<noCircles; i++){
    PointsInC2[i] = findFiberPoint(startingPoints[i]); //fill that array up:
  }
  
  
  for (int j=0; j<noCircles; j++){ 
    circlePoints[j][0]= projectPoint(PointsInC2[j]); //put starting points' projections in first entry
    for(int i=1; i< noPoints; i++){
      circlePoints[j][i] = projectPoint(getNewPoint(PointsInC2[j]));
      PointsInC2[j] = getNewPoint(PointsInC2[j]);
    }
  }
}

void drawCircle(){
  stroke(255);
  strokeWeight(0.1);
  noFill();
  curveTightness(1);
  beginShape();
  for(int j=0; j<noCircles; j++){
    for(int i=0; i<noPoints; i++){
      curveVertex((float)circlePoints[j][i].x,(float)circlePoints[j][i].y,(float)circlePoints[j][i].z); 
     }
  curveVertex((float)circlePoints[j][0].x,(float)circlePoints[j][0].y,(float)circlePoints[j][0].z); //1
  curveVertex((float)circlePoints[j][1].x,(float)circlePoints[j][1].y,(float)circlePoints[j][1].z); //2 
  curveVertex((float)circlePoints[j][1].x,(float)circlePoints[j][2].y,(float)circlePoints[j][2].z); //3 - need those three for anchor point in beginning and end
  endShape();
  }
}
//_____________CLASS CxComplex_____________
class CxComplex { //Complex x Complex -> 4D!

 Complex z_1;
 Complex z_2;
 
 //CONSTRUCTOR
 
   CxComplex(CxComplex z){
     this.z_1 = z.z_1;
     this.z_2 = z.z_2;
   }
   
 
   CxComplex(Complex x, Complex y) {
    this.z_1 = x;
    this.z_2 = y;
   }
 
   CxComplex(double x_1, double y_1, double x_2, double y_2) {
    this.z_1 = new Complex(x_1, y_1);
    this.z_2 = new Complex(x_2, y_2);
   }
}

note: CxComplex is a class I wrote for the points in CxC - so its basically an array of two complex numbers.

1 Like

Hi! Welcome to the forum :dumpling:

First please format your code like this:

1 Like

we can’t run your code, this part is missing

also missing: centerCoordinatesystem()

please make a runable version.