How to draw linear (input) data points around circular shape

Sorry if the title is a little too abstract but this is a hard concept for me to put into words. The code is not too difficult but my main issue is the maths. It is based on receving OSC messages from TidalCycles, livecoding software for dealing with events and patterns.

I have been working on attempting to modify this Processing sketch for a few weeks now.

I want to modify the draw method of the Orbit class to draw a set of events I am receiving over time in a circular motion instead of linearly across the screen. Here is the part of the code I’m talking about:

class Orbit {
  Boolean state = false;
  ArrayList<Event> events = new ArrayList<Event>();
  
  void add (Event event) {
    events.add(0,event);
    state = !state;
  }
  
  void draw(float cycle) {
    Boolean state = this.state;
    noFill();
    beginShape();
    strokeWeight(3);
    stroke(255,255,255);
    vertex(width, state ? 0 : h);
    Iterator<Event> i = events.iterator();
    while (i.hasNext()) {
      Event event = i.next();
      float pos = (event.cycle-(cycle-showCycles))/showCycles;
      if (pos < 0) {
        i.remove();
      }
      else {
        vertex(width * pos, state ? 0 : h);
        vertex(width * pos, state ? h : 0);
        state = !state;
      }
    }  
    vertex(0, state ? 0 : h);
    endShape();
  }
}

i want the pattern produced by the events received to draw like this instead of in a line across the canvas:

MS Paint _ Microsoft Paint Online (1)

I know how to draw vertices in a circle but firstly, I don’t know how to express the condition i need to remove events from the events array when the pattern is represented in a cyclical way rather than the current linear way ( the if pos < 0 condition) and secondly I can’t get the pattern, including the binary states of the events, to join up conforming to the correct circular shape, they just join up as horizontal lines across the circle. After drawing out what I want the pattern to look like by hand, I believe I might need to use a different type of vertex.

Hopefully someone can understand what I’m talking about and point me in the right direction as this has become quite a frustrating stumbling block for me , who has neglected and forgotten most of their mathematical education! I appreciate that not many people will be familiar with TidalCycles and that this is a niche problem but maybe someone will enjoy a challenge.

Thank you for reading!

Hello,

A simple example I wrote in a few minutes.
I did not simplify or refactor it.

It may give you some ideas…

Example:

// Simple Gear
// v1.0.0
// GLV 2021-07-02

boolean toggle = false;

void setup() 
  {
  size(640, 360);
  background(0);
  stroke(255);
  translate(width/2, height/2);
  
  noFill();
  beginShape();
  for(int i = 0; i<=50; i++)
    {
    float r = 50;
    float angle = i*TAU/50;
      
    toggle = !toggle;
      
    if (toggle)
      {
      r = 100;       
      float x = r*cos(angle);
      float y = r*sin(angle);
      //point(x, y);
      vertex(x, y);
  
      r = 120;    
      x = r*cos(angle);
      y = r*sin(angle);
      //point(x, y);
      vertex(x, y);
      }
    else
      {
      r = 120;       
      float x = r*cos(angle);
      float y = r*sin(angle);
      //point(x, y);
      vertex(x, y);
  
      r = 100;    
      x = r*cos(angle);
      y = r*sin(angle);
      //point(x, y);
      vertex(x, y);
      }
    }
  endShape();   
  }

image

References:
Trigonometry Primer \ Processing.org

:)

Hello @domha91

Great question!

Since you mentioned at the top of your post:

For the purposes of as a search-engine-friendly searchable phrase within the forum data base (:grin:) perhaps a less abstract title would be:

"How to draw linear (input) data points around circular shape"??
Or something like that…

Just a humble suggestion :upside_down_face:
:nerd_face:

2 Likes

Thank you! that is the basic shape that I want and I got it working.

However I would like the spacing of the “teeth” of the gear to be determined by OSC input.

As represented by the line

float pos = (event.cycle-(cycle-showCycles))/showCycles;

Here is how this looks in the original:

You can see that each OSC event is triggering a state change at its corresponding position within a “cycle”, the unit of time that TidalCycles uses. There is one line for each sound source. Here is the code for that:

void drawTidalCycles(){
  float now = millis();
  float elapsed = now - lastTime;
  float cycle = ((elapsed * cps)/1000) + lastCycle;
   
   synchronized(orbits){
     pushMatrix();
     for(int i = 0; i < orbitn; ++i){
       Orbit o = orbits.get(i);
       translate(0, orbitHeight);
       o.draw(cycle);
     }
     popMatrix();
   }
}

I tried combining the original with your suggestions to write a new draw method:

class Orbit{
  Boolean state = false;
  ArrayList<Event> events = new ArrayList<Event>();
  
  void add(Event event){
    events.add(0,event);
    state = !state;
  }
  void draw(float cycle){
    Boolean state = this.state;
    
    noFill();
    beginShape();
    strokeWeight(2);
    //TODO: Change stroke colour based on audio and/or OSC
    stroke(0,0, 0);
    
    Iterator<Event> i = events.iterator();
    int count = 0;
    while(i.hasNext()){
      Event event = i.next();
      float pos = ((event.cycle-(cycle-showCycles))/showCycles);

        // TODO: Circular plot
      if (pos < 0)
      {
        i.remove();
      }
      else{
        float angle = count*TAU/60; 
        float posX = 0;
        float posY = 0;    
        
        if(state){
            r = 400;
            posX = pos * r * cos(angle);
            posY = pos * r * sin(angle);
            vertex(posX, posY);
            r += h;
            posX = pos * r * cos(angle);
            posY = pos * r * sin(angle);
            vertex(posX, posY);
        }
        else{
            r = 400 + h;
            posX = pos * r * cos(angle);
            posY = pos * r * sin(angle);
            vertex(posX,posY);
            r = 400;
            posX = pos * r * cos(angle);
            posY = pos * r * sin(angle);
            vertex(posX,posY);
        }
        state = !state;
        count++;
        println( "posX: " + posX, " posY: " + posY);
        println( "pos: " + pos);  
      }  
    }
    endShape();     
  }
}

Here is what i got when i tried this (The number represents the last cycle):

Not the correct shape! Any suggestions?

Thanks and i have used your kindly provided title suggestion :slight_smile:

1 Like