File:Instant centre of rotation of a rolling wheel broken down into points (smaller image size).gif

Page contents not supported in other languages.
This is a file from the Wikimedia Commons
From Wikipedia, the free encyclopedia

Instant_centre_of_rotation_of_a_rolling_wheel_broken_down_into_points_(smaller_image_size).gif(320 × 214 pixels, file size: 657 KB, MIME type: image/gif, looped, 388 frames, 34 s)

Summary

Description
English: By breaking down the rolling wheel into several points, it can be more easily seen how all points of the wheel rotate around a single point at each instant. This point is the instant centre of rotation, shown in black.
Date
Source Own work
Author Rodrigo Castro Freibott

Licensing

I, the copyright holder of this work, hereby publish it under the following license:
w:en:Creative Commons
attribution share alike
This file is licensed under the Creative Commons Attribution-Share Alike 4.0 International license.
You are free:
  • to share – to copy, distribute and transmit the work
  • to remix – to adapt the work
Under the following conditions:
  • attribution – You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use.
  • share alike – If you remix, transform, or build upon the material, you must distribute your contributions under the same or compatible license as the original.


Summary

Description
English: By breaking down the rolling wheel into several points, it can be more easily seen how all points of the wheel rotate around a single point at each instant. This point is the instant centre of rotation, shown in black.
Date
Source Own work
Author Rodrigo Castro Freibott

Licensing

I, the copyright holder of this work, hereby publish it under the following license:
w:en:Creative Commons
attribution share alike
This file is licensed under the Creative Commons Attribution-Share Alike 4.0 International license.
You are free:
  • to share – to copy, distribute and transmit the work
  • to remix – to adapt the work
Under the following conditions:
  • attribution – You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use.
  • share alike – If you remix, transform, or build upon the material, you must distribute your contributions under the same or compatible license as the original.


The following program, written in Processing 4.0.1, will create the frames of the animation for a particular number of layers of dots.

Processing 4.0.1 code

class Dot {
  
  // position in polar coordinates (with an arbitrary pole)
  PVector pole;
  float distance;
  float angle;
  
  // position in cartesian coordinates
  PVector pos;
  
  // angular velocity (around pole)
  float avel;
  
  // diameter (for display)
  float diameter;
  
  Dot(PVector pole, float distance, float initial_angle, float avel, float diameter) {
    this.pole = pole;
    this.distance = distance;
    this.angle = initial_angle;
    this.avel = avel;
    this.diameter = diameter;
    pos = new PVector(distance*cos(angle), distance*sin(angle));
    pos.add(pole);
  }
  
  void update() {
    /**
    Update the angle and position of the dot
    */
    angle += avel * 1/frameRate;
    pos = new PVector(distance*cos(angle), distance*sin(angle));
    pos.add(pole);
  }
  
  void show() {
    ellipse(pos.x, pos.y, diameter, diameter);
  }
  
  void change_pole(PVector new_pole) {
    
    /**
    Change the point around which the dot rotates
    This method changes the properties distance, angle (which should now be from the new pole) and pole
    */
    
    PVector distance_vector = new PVector();  // vector from new pole to current position
    distance_vector = pos.copy();
    distance_vector.sub(new_pole);
    
    distance = distance_vector.mag();
    angle = atan2(distance_vector.y, distance_vector.x);
    pole = new_pole.copy();
    
  }
  
}

class Wheel {
  
  Dot[] dots;
  float radius;
  int num_layers;
  PVector centre;  // central dot (used when creating the wheel)
  PVector pole;  // point in plane around which all the dots of the wheel rotate
  float avel;
  float dot_diameter;
  
  Wheel(float radius, int num_layers, PVector centre, float avel) {
    
    this.radius = radius;
    this.num_layers = num_layers;
    this.centre = centre;
    this.avel = avel;
    
    dots = new Dot[0];
    dot_diameter = radius/num_layers;
    
    // Creating the wheel ...
    
    for(int layer_index = 0; layer_index < num_layers; layer_index++) {
      
      float distance = radius/num_layers*layer_index;  // equally spaced distances between the dots of different layers
      int num_dots_of_layer = floor(2*PI*num_layers*distance/radius);
      /*
      Calculation of the number of dots each layer must have to fill the whole circumference:
      2*PI*layer_radius = ¿? * dot_diameter
      2*PI*layer_radius = ¿? * radius/num_layers
      ¿? = 2*PI*layer_radius*num_layers/radius
      ¿? = 2*PI*num_layers*layer_radius/radius
      */
      if (num_dots_of_layer == 0) num_dots_of_layer = 1;  // central dot
      
      for(int dot_index = 0; dot_index < num_dots_of_layer; dot_index++) {
        
        float angle = 2*PI/num_dots_of_layer*dot_index;  // equally spaced angles between the dots of the same layer
        angle += PI/num_dots_of_layer*layer_index;  // add offset according to layer to use more space
        dots = (Dot[]) append(dots, new Dot(centre, distance, angle, 0, dot_diameter));
        
      }
      
    }
    
    // Giving the wheel a first pole, which will be its lowest dot (the one with the highest y coordinate) ...
    
    float max_y = 0;
    int max_y_index = 0;
    for(int i = 0; i < dots.length; i++) {
      if (dots[i].pos.y > max_y) {
        max_y = dots[i].pos.y;
        max_y_index = i;
      }
    }
    this.set_pole(dots[max_y_index].pos);
    
  }
  
  void set_pole(PVector pole) {
    
    this.pole = pole.copy();
    
    for(int i = 0; i < dots.length; i++) {
      dots[i].change_pole(pole);
      dots[i].avel = avel;
    }
    
  }
  
  void show() {
    for(int i = 0; i < dots.length; i++) {
      
      if (dots[i].pos.equals(pole)) {  // '==' doesn't work: checking 'dots[i].pos == pole' gives 'false', for some reason
        fill(0);  // black
      } else {
        fill(255);  // white
      }
      
      dots[i].show();
      
    }
  }
  
  void update() {
    for(int i = 0; i < dots.length; i++) {
      
      dots[i].update();
      
      if (dots[i].pos.y + dot_diameter/2 >= FLOOR_HEIGHT) {
        this.set_pole(dots[i].pos);
      }
      // With this, the wheel will gradually go down, but this isn't noticeable
      
    }
  }
  
}

Wheel wheel;
float WHEEL_CENTRE_HEIGHT;
float WHEEL_RADIUS;
int NUM_LAYERS;
float FLOOR_HEIGHT;

void setup() {
  
  size(600, 400);
  WHEEL_CENTRE_HEIGHT = height/2;
  WHEEL_RADIUS = height/4;
  NUM_LAYERS = 10;
  FLOOR_HEIGHT = WHEEL_CENTRE_HEIGHT + WHEEL_RADIUS - 0.5*WHEEL_RADIUS/NUM_LAYERS;
  wheel = new Wheel(WHEEL_RADIUS, NUM_LAYERS, new PVector(-WHEEL_RADIUS, height/2), 1);
  
}

void draw() {
  
  background(255);
  line(0, FLOOR_HEIGHT, width, FLOOR_HEIGHT);
  wheel.update();
  wheel.show();
  
  saveFrame("#####.png");
  
}

This second program, which is written in Python and uses ImageMagick, will join the generated frames into a GIF. After this, it is still necessary to do further editing with a tool like https://ezgif.com/speed to increase the GIF's animation speed.

Python code

import os

# CHANGE THIS ACCORDING TO THE IMAGES GENERATED BY PROCESSING 4.0.1!
NUM_LAYERS = 10
NUM_FRAMES = 310

FILENAME = f"wheel_{NUM_LAYERS}layers"
FPS = 200  # Any value greater than 100 will simply give a delay of 0 (speeding the resulting GIF with https://ezgif.com/speed is necessary)

images = [f"{i:05n}.png" for i in range(1, NUM_FRAMES+1)]
# You may need to filter some images to avoid a command line that is too long
# One way to do this is: filtered_images = [f"{i:05n}.png" for i in range(1, NUM_FRAMES+1) if i % 2 == 0]

os.system('convert -delay {} +dither +remap -layers Optimize {} "{}"'.
          format(100//FPS, ' '.join(['"' + img + '"' for img in images]), FILENAME + '.gif'))


# Delete the images
for img in images:
    if os.path.exists(img):
        os.remove(img)



Captions

Add a one-line explanation of what this file represents

Items portrayed in this file

depicts

23 August 2022

File history

Click on a date/time to view the file as it appeared at that time.

Date/TimeThumbnailDimensionsUserComment
current08:08, 23 August 2022Thumbnail for version as of 08:08, 23 August 2022320 × 214 (657 KB)Rodrigo Castro FreibottUploaded while editing "Instant centre of rotation" on en.wikipedia.org
The following pages on the English Wikipedia use this file (pages on other projects are not listed):

Global file usage

The following other wikis use this file:

Metadata