Task #7: draw a circle on your square

It’s time for Task #7

It’s a basic one, aka hard for beginners to grasp, trivial for more advanced users, and well suited to the middle ground playing to see what they can do with it.

If you find this easy: golf it, make it as short as possible.
If you find this hard, some pointers would be:

You should have a center point of 0,0… You’ll want to adjust your math for this.
A squared + B squared equals C squared is a big hint.

Polar coordinates make this trivial. Learning how they work will help you in many ways.

Good luck!

I’ve had the idea of radar kind of stuck in my head since task #4. The classic radar screen is circular, right? And just to make sure it qualifies, I added another circle to this week’s pattern. Here 's the code:

var dishAngle;
export var beamWidth = 0.225;

export function sliderRadarWidth(v) {
  beamWidth = .02+0.5*v;
}

export function beforeRender(delta) {
  // create a position for our spinning "radar dish" with
  // angle that revolves from 0 to 1.
  dishAngle = time(.03)
  
  // use another timer for the current radius of an
  // expanding circle.
  circleRadius = time(0.015);
}

export function render2D(index, x, y) {
  // center coordinates in matrix
  x -= 0.5; y -=0.5;             
  
  // calculate angle to (x,y) and convert radians to 0..1 percentage
  // of full circle
  v = (PI + atan2(x, y))/PI2;
  
  // calculate absolute distance between angle to (x,y) and
  // the "dish angle" currently indicated by the sawtooth
  // wave we made in beforeRender
  d =  0.5-abs(0.5 - abs(dishAngle - v));
  
  // use the angular distance to mask off the parts of the
  // display we don't need
  v = (d < beamWidth) ? 1-(d/beamWidth) : 0;
  
  // calculate radius at this point, and use it
  // to set the pixel hue
  h = sqrt(x*x + y*y);  

  // if radius is near our expanding circle radius,
  // desaturate the point so it's white, and allow
  // it to be drawn around the entire circle.
  if (abs(h-circleRadius) < 0.05) {
    s = 0;
    v = 0.8
  }
  else {
    s = 1;
  }

  hsv(h, s, v*v*v*v)
}
2 Likes

From the moment I thought of radar blips for #4, I was wishing for the 2D matrix versions.

Well, here’s a simpler version of code for a circle on a square matrix. I’ve added sliders to vary circle radius and "thickness’. Seems to work OK.

// WHITE CIRCLE IN RED SQUARE
// AS IN “I LIKE SLIDERS”

export var CycleTime
var timer

export var CircleThickness

export var circleRadius

export function sliderCycleTime(v) { // has little discernable effect
CycleTime = 50 + (1500 * v) // but beforerender makes it behave nicely
}

export function slidercircleRadius(v) {
circleRadius = 0.12 + (0.37 * v)
}
export function sliderCircleThickness(v) {
CircleThickness = 0.01 + (0.05 * v)
}

export function beforeRender(delta) {
timer += delta

if (timer >= CycleTime) {
timer = 0
}

}

export function render2D(index, x, y) {

x -= 0.5; y -=0.5;

r = sqrt(xx + yy);

if (abs(r-circleRadius) < CircleThickness) {
h=
s = 0;
v = 1
}
else {
s = 1;
}

hsv(h, s, v)
}

2 Likes

Works great, @JustPete! I like that you limit slider inputs to reasonable values - this is a very good practice.

My only suggestion is to initialize your control variables when you declare them. Something like this:

// set control variables to whatever you think is the best looking
// default value
export var CircleThickness = 0.04; 
export var CircleRadius = 0.35;

When you first install or load a pattern, the Pixelblaze hasn’t yet saved the controls, so they wind up defaulting to zero, which in this case means nothing gets displayed 'till you play with the controls a bit. Initializing your variables means that the first thing the user sees can always be something that you think shows the pattern off well.

1 Like

I wondered about that. I guessed that the sliders did all the work. Now I know its otherwise. Thanks!

Also the use of semicolons, is that of some significance/utility, one that presently eludes me?

Regarding input limits, I do like how the circle representation distills down to limited geometry at low "thickness " and radius levels.

Not sure what cycle time does. It does not appear to affect frame rate. I put the slider in for possible future mods/enhancement. Just possibly.

Semicolons are for readability mostly. They separate lines.

Great to know! Thanks.
Commas, on the other hand, appear to separate strings of things like variables…
e.g. var x1, y1, z1 etc.

1 Like