PI Angle to turn DJ Disk as the song plays

Hi everyone,

I’m trying to create the effect of the DJ Disk turning when the music is playing however I believe my angles are all wrong and I cannot fully understand how to implement it to spin as the music player.

Also, I have plans to create a waveform that would go from 0 to getTotalLength(), but this would be drawing an arc beside the DJ Disk, just like in the attached screenshot.

Any help will be much appreciated.

void Wheel::paint(juce::Graphics& g)
{
    g.setColour(juce::Colours::blue);
    
    const float radius = jmin(getWidth()/ 2, getHeight() / 2);
    float cx = getWidth()/2;
    float cy = getHeight()/2;
    float rx = cx - radius;
    float ry = cy - radius;
    
    float angle = position * 360 * (audioThumb.getTotalLength() * 0.2);
    float piAngle = angle * M_PI / 360 ;

    g.drawImage(wheel, (int) rx, (int) ry,  2 * (int)radius, 2 * (int)radius, 0, 0, rx * std::cos(piAngle),ry * std::sin(piAngle));

}

I think angle should be M_PI / 180 ( a complete circle is 2 * PI )
I’m not quite clear on the intention of the drawImage call. The normal way to rotate an image is to apply an ‘AffineTransform’ via the ‘drawImageTransformed’ method.

I don’t see why drawing an image is necessary at all. The entire wheel can easily be drawn procedurally.

1 Like

The image might be the record label, which might be supplied as image in addition to the line (I am no DJ, don’t know how it is called).

  • To convert angles don’t mess with PI and stuff, even though it is trivial. There is juce::DegreeToRadians() for that job. The other direction also exists, have a look around in the API docs.
  • Same goes for points etc. It can be written using functions which shows intent (self-documenting)
// assuming float degrees is from 0..360
const auto centre   = getLocalBounds().getCentre().toFloat();
const auto radians  = juce::degreeToRadians (degrees);
const auto inner    = centre.getPointOnCircumference (10.0f, radians);
const auto outer    = centre.getPointOnCircumference (50.0f, radians);

const auto diameter = float (std::min (getWidth(), getHeight())); // make it round
const auto circle   = juce::Rectangle (diameter, diameter).withCentre (centre); // circles are specified by enclosing rectangle

// the actual drawing
g.setColour (juce::Colours::white);
g.fillEllipse (circle);
g.setColour (juce::Colours::black);
g.drawLine (juce::Line (inner, outer), 4.0f);

This is an example with no magic numbers except the ones you choose, like the inner and outer radius and the thickness of the line.

If you want to draw an image rotated, the AffineTransform @JeffMcClintock mentioned does the trick:

// the transform moves the image centre to the centre of the bounds, then it rotates around the centre
auto transform = juce::AffineTransform::translation (centre - image.getBounds().getCentre().toFloat())
                .rotated (radians, centre);
g.drawImage (image, transform);

Just do this instead of the fillEllipse.

Hope that helps

2 Likes

Thanks @daniel! I have been able to draw everything and have the DJ disk image following your code.