Color wheel

Revision as of 09:35, 11 September 2022 by Simonjsaunders (talk | contribs) (Uploaded Rust output file)

Write a function to draw a HSV color wheel completely with code.

Task
Color wheel
You are encouraged to solve this task according to the task description, using any language you may know.
Task

This is strictly for learning purposes only. It's highly recommended that you use an image in an actual application to actually draw the color wheel   (as procedurally drawing is super slow). This does help you understand how color wheels work and this can easily be used to determine a color value based on a position within a circle.


Applesoft BASIC

The lo-resolution GRaphics screen is limited to 16 colors. Ordered dithering is used for the saturation. Pink is mixed with violet and magenta, and aqua is mixed with light blue and green. These lighter colors are randomly mixed with the saturation dither. Note that the four Apple II colors can be seen at the 90 degree marks: orange at 30 degrees, green at 120 degrees, cyan (blue) at 120 degrees, and violet at 300 degrees.

 100  LET R = 3.1415926535 / 180
 110  LET YO = 20
 120  LET XO = YO
 130  LET MS =  INT (YO * 7 / 8)
 140  LET O$ = "1111111111.1111111110.1111011110.1101110110.1101010110.1010101010.0010101001.0010001001.0000100001.0000000001.0000000000"
 150  GR 
 160  FOR S = 0 TO MS
 170      LET D = S / MS
 180      LET P$ =  MID$ (O$, INT (D * 10) * 11 + 1,11)
 190      LET SY = S
 200      LET SX = S * 4 / 7
 210      LET P = 0
 220      FOR I = 0 TO 360
 230          LET X = XO +  SIN (I * R) * SX
 240          LET Y = YO +  COS (I * R) * SY
 250          LET W = 15
 260          IF I >  = 30 - 22.4 AND I < 30 + 22.5 THEN  COLOR= 9
 270          IF I >  = 75 - 22.5 AND I < 75 + 22.5 THEN  COLOR= 13
 280          IF I >  = 120 - 22.5 AND I < 120 + 22.5 THEN  COLOR= 12:W = 14
 290          IF I >  = 165 - 22.5 AND I < 165 + 22.5 THEN  COLOR= 7:W = 14
 300          IF I >  = 210 - 22.5 AND I < 210 + 22.5 THEN  COLOR= 6
 310          IF I >  = 255 - 22.5 AND I < 255 + 22.5 THEN  COLOR= 2
 320          IF I >  = 300 - 22.5 AND I < 300 + 22.5 THEN  COLOR= 3:W = 11
 330          IF I >  = 345 - 22.5 OR I < 345 + 22.5 - 360 THEN  COLOR= 1:W = 11
 340          IF D < .2 THEN W = 15
 350          IF  RND (1) < D THEN W = 15
 360          IF  VAL ( MID$ (P$,P + 1,1)) THEN  COLOR= W
 370          IF  SCRN( X,Y) = 0 THEN  PLOT X,Y:P = P + 1: IF P >  = 9 THEN P = 0
 380  NEXT I,S

AppleScript

 
choose color default color {0, 0, 0, 0}

C++

Library: Qt

This program draws an HSV color wheel in a window.

// colorwheelwidget.cpp
#include "colorwheelwidget.h"
#include <QPainter>
#include <QPaintEvent>
#include <cmath>

namespace {

QColor hsvToRgb(int h, double s, double v) {
    double hp = h/60.0;
    double c = s * v;
    double x = c * (1 - std::abs(std::fmod(hp, 2) - 1));
    double m = v - c;
    double r = 0, g = 0, b = 0;
    if (hp <= 1) {
        r = c;
        g = x;
    } else if (hp <= 2) {
        r = x;
        g = c;
    } else if (hp <= 3) {
        g = c;
        b = x;
    } else if (hp <= 4) {
        g = x;
        b = c;
    } else if (hp <= 5) {
        r = x;
        b = c;
    } else {
        r = c;
        b = x;
    }
    r += m;
    g += m;
    b += m;
    return QColor(r * 255, g * 255, b * 255);
}

}

ColorWheelWidget::ColorWheelWidget(QWidget *parent)
    : QWidget(parent) {
    setWindowTitle(tr("Color Wheel"));
    resize(400, 400);
}

void ColorWheelWidget::paintEvent(QPaintEvent *event) {
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    const QColor backgroundColor(0, 0, 0);
    const QColor white(255, 255, 255);
    painter.fillRect(event->rect(), backgroundColor);
    const int margin = 10;
    const double diameter = std::min(width(), height()) - 2*margin;
    QPointF center(width()/2.0, height()/2.0);
    QRectF rect(center.x() - diameter/2.0, center.y() - diameter/2.0,
                diameter, diameter);
    for (int angle = 0; angle < 360; ++angle) {
        QColor color(hsvToRgb(angle, 1.0, 1.0));
        QRadialGradient gradient(center, diameter/2.0);
        gradient.setColorAt(0, white);
        gradient.setColorAt(1, color);
        QBrush brush(gradient);
        QPen pen(brush, 1.0);
        painter.setPen(pen);
        painter.setBrush(brush);
        painter.drawPie(rect, angle * 16, 16);
    }
}
// colorwheelwidget.h
#ifndef COLORWHEELWIDGET_H
#define COLORWHEELWIDGET_H

#include <QWidget>

class ColorWheelWidget : public QWidget {
    Q_OBJECT
public:
    ColorWheelWidget(QWidget *parent = nullptr);
protected:
    void paintEvent(QPaintEvent *event) override;
};

#endif // COLORWHEELWIDGET_H
// main.cpp
#include "colorwheelwidget.h"
#include <QApplication>

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    ColorWheelWidget widget;
    widget.show();
    return app.exec();
}
Output:

Media:Colorwheel cpp.png

Delphi

Library: System.Math
Translation of: Kotlin
program Color_wheel;

{$APPTYPE CONSOLE}

uses
  Winapi.Windows,
  System.SysUtils,
  Vcl.Graphics,
  System.Math,
  Vcl.Imaging.pngimage;

const
  TAU = 2 * PI;

function HSBtoColor(hue, sat, bri: Double): TColor;
var
  f, h: Double;
  u, p, q, t: Byte;
begin
  u := Trunc(bri * 255 + 0.5);
  if sat = 0 then
    Exit(rgb(u, u, u));

  h := (hue - Floor(hue)) * 6;
  f := h - Floor(h);
  p := Trunc(bri * (1 - sat) * 255 + 0.5);
  q := Trunc(bri * (1 - sat * f) * 255 + 0.5);
  t := Trunc(bri * (1 - sat * (1 - f)) * 255 + 0.5);

  case Trunc(h) of
    0:
      result := rgb(u, t, p);
    1:
      result := rgb(q, u, p);
    2:
      result := rgb(p, u, t);
    3:
      result := rgb(p, q, u);
    4:
      result := rgb(t, p, u);
    5:
      result := rgb(u, p, q);
  else
    result := clwhite;
  end;

end;

function ColorWheel(Width, Height: Integer): TPngImage;
var
  Center: TPoint;
  Radius: Integer;
  x, y: Integer;
  Hue, dy, dx, dist, theta: Double;
  Bmp: TBitmap;
begin
  Bmp := TBitmap.Create;
  Bmp.SetSize(Width, Height);
  with Bmp.Canvas do
  begin
    Brush.Color := clWhite;
    FillRect(ClipRect);
    Center := ClipRect.CenterPoint;
    Radius := Center.X;
    if Center.Y < Radius then
      Radius := Center.Y;
    for y := 0 to Height - 1 do
    begin
      dy := y - Center.y;
      for x := 0 to Width - 1 do
      begin
        dx := x - Center.x;
        dist := Sqrt(Sqr(dx) + Sqr(dy));
        if dist <= Radius then
        begin
          theta := ArcTan2(dy, dx);
          Hue := (theta + PI) / TAU;
          Pixels[x, y] := HSBtoColor(Hue, 1, 1);
        end;
      end;
    end;
  end;

  Result := TPngImage.Create;
  Result.Assign(Bmp);
  Bmp.Free;
end;

begin
  with ColorWheel(500, 500) do
  begin
    SaveToFile('ColorWheel.png');
    Free;
  end;
end.
Output:

Png Image [1].

Fōrmulæ

Fōrmulæ programs are not textual, visualization/edition of programs is done showing/manipulating structures but not text. Moreover, there can be multiple visual representations of the same program. Even though it is possible to have textual representation —i.e. XML, JSON— they are intended for storage and transfer purposes more than visualization and edition.

Programs in Fōrmulæ are created/edited online in its website, However they run on execution servers. By default remote servers are used, but they are limited in memory and processing power, since they are intended for demonstration and casual use. A local server can be downloaded and installed, it has no limitations (it runs in your own computer). Because of that, example programs can be fully visualized and edited, but some of them will not run if they require a moderate or heavy computation/memory resources, and no local server is being used.

In this page you can see the program(s) related to this task and their results.


FreeBASIC

#include "fbgfx.bi"

Sub HSVtoRGB(h As Single, s As Integer, v As Integer, Byref r As Integer, Byref g As Integer, Byref b As Integer)
    If s = 0 Then
        r = v
        g = v
        b = v
        Return
    End If
    
    h = h Mod 360
    Dim As Single hue = h
    
    Select Case h
    Case 0f To 51.5f
        hue = ((hue         ) * (30f / (51.5f          )))
    Case 51.5f To 122f
        hue = ((hue -  51.5f) * (30f / (122f   -  51.5f))) + 30
    Case 122f To 142.5f
        hue = ((hue -   122f) * (30f / (142.5f -   122f))) + 60
    Case 142.5f To 165.5f
        hue = ((hue - 142.5f) * (30f / (165.5f - 142.5f))) + 90
    Case 165.5f To 192f
        hue = ((hue - 165.5f) * (30f / (192f   - 165.5f))) + 120
    Case 192f To 218.5f
        hue = ((hue -   192f) * (30f / (218.5f -   192f))) + 150
    Case 218.5f To 247f
        hue = ((hue - 218.5f) * (30f / (247f   - 218.5f))) + 180
    Case 247f To 275.5f
        hue = ((hue -   247f) * (30f / (275.5f -   247f))) + 210
    Case 275.5f To 302.5f
        hue = ((hue - 275.5f) * (30f / (302.5f - 275.5f))) + 240
    Case 302.5f To 330f
        hue = ((hue - 302.5f) * (30f / (330f   - 302.5f))) + 270
    Case 330f To 344.5f
        hue = ((hue -   330f) * (30f / (344.5f -   330f))) + 300
    Case 344.5f To 360f
        hue = ((hue - 344.5f) * (30f / (360f   - 344.5f))) + 330
    End Select
    h = hue
    
    h = h Mod 360
    
    Dim As Single h1 = h / 60         
    Dim As Integer i = Int(h1)
    Dim As Single f = h1 - i
    Dim As Integer p = v * (255 - s) / 256
    Dim As Integer q = v * (255 - f * s) / 256
    Dim As Integer t = v * (255 - (1 - f) * s) / 256
    
    Select Case As Const i
    Case 0
        r = v
        g = t
        b = p
        Return
    Case 1
        r = q
        g = v
        b = p
        Return
    Case 2
        r = p
        g = v
        b = t
        Return
    Case 3
        r = p
        g = q
        b = v
        Return
    Case 4
        r = t
        g = p
        b = v
        Return
    Case 5
        r = v
        g = p
        b = q
        Return
    End Select
End Sub

Const pi As Single = 4 * Atn(1)
Const radius = 160
Const xres = (radius * 2) + 1, yres = xres

Screenres xres, yres, 32
Windowtitle "Color wheel"

Dim As Integer r,g,b
Dim As Single dx, dy, dist, angle

Do
    Screenlock
    Cls
    For x As Integer = 0 To (radius * 2) - 1
        For y As Integer = 0 To (radius * 2) - 1
            dx = x - radius
            dy = radius - y
            dist = Sqr(dx * dx + dy * dy)
            If dist < radius Then
                angle = Atan2(dy, dx) * (180/pi)
                If angle <   0 Then angle += 360
                If angle > 360 Then angle -= 360
                HSVtoRGB(angle, (dist / radius) * 255, 255, r, g, b)
                Pset(x, y), Rgb(r, g, b)
            End If
        Next y
    Next x
    
    Screenunlock
Loop Until Inkey = Chr(27)


GML

 
for (var i = 1; i <= 360; i++) {
    for (var j = 0; j < 255; j++) {

        var hue = 255*(i/360);
        var saturation = j;
        var value = 255;

        var c = make_colour_hsv(hue,saturation,value);
        
        //size of circle determined by how far from the center it is
        //if you just draw them too small the circle won't be full. 
        //it will have patches inside it that didn't get filled in with color
        var r = max(1,3*(j/255));

        //Math for built-in GMS functions
        //lengthdir_x(len,dir) = +cos(degtorad(direction))*length;
        //lengthdir_y(len,dir) = -sin(degtorad(direction))*length;
        draw_circle_colour(x+lengthdir_x(m_radius*(j/255),i),y+lengthdir_y(m_radius*(j/255),i),r,c,c,false);
    }
}

Go

Library: Go Graphics
Translation of: Kotlin
package main

import (
    "github.com/fogleman/gg"
    "math"
)

const tau = 2 * math.Pi

func hsb2rgb(hue, sat, bri float64) (r, g, b int) {
    u := int(bri*255 + 0.5)
    if sat == 0 {
        r, g, b = u, u, u
    } else {
        h := (hue - math.Floor(hue)) * 6
        f := h - math.Floor(h)
        p := int(bri*(1-sat)*255 + 0.5)
        q := int(bri*(1-sat*f)*255 + 0.5)
        t := int(bri*(1-sat*(1-f))*255 + 0.5)
        switch int(h) {
        case 0:
            r, g, b = u, t, p
        case 1:
            r, g, b = q, u, p
        case 2:
            r, g, b = p, u, t
        case 3:
            r, g, b = p, q, u
        case 4:
            r, g, b = t, p, u
        case 5:
            r, g, b = u, p, q
        }
    }
    return
}

func colorWheel(dc *gg.Context) {
    width, height := dc.Width(), dc.Height()
    centerX, centerY := width/2, height/2
    radius := centerX
    if centerY < radius {
        radius = centerY
    }
    for y := 0; y < height; y++ {
        dy := float64(y - centerY)
        for x := 0; x < width; x++ {
            dx := float64(x - centerX)
            dist := math.Sqrt(dx*dx + dy*dy)
            if dist <= float64(radius) {
                theta := math.Atan2(dy, dx)
                hue := (theta + math.Pi) / tau
                r, g, b := hsb2rgb(hue, 1, 1)
                dc.SetRGB255(r, g, b)
                dc.SetPixel(x, y)
            }
        }
    }
}

func main() {
    const width, height = 480, 480
    dc := gg.NewContext(width, height)
    dc.SetRGB(1, 1, 1) // set background color to white
    dc.Clear()
    colorWheel(dc)
    dc.SavePNG("color_wheel.png")
}
Output:
Image is same as Kotlin entry

J

rgbc=: {{1-x*0>.1<.(<.4&-)6|m+y%60}}
hsv=: 5 rgbc(,"0 1) 3 rgbc(,"0) 1 rgbc
degrees=: {{180p_1*{:"1+.^.y}}
wheel=: {{((1>:|)*|hsv degrees)j./~y%~i:y}}
require'viewmat'
'rgb' viewmat 256#.<.255*wheel 400

The right argument to wheel determines the radius (in pixels) of the color wheel (with a white pixel in the center), so the diameter of the above color wheel is 801 pixels.

Here's a representation of wheel 5:


           
           
           
           
           
           
           
           
           
           
           
           

Here's an online implementation for wheel 80 (hit "Run" in the upper right corner).

Java

This program draws a color wheel in a window.

import java.awt.*;
import javax.swing.*;

public class ColorWheel {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                ColorWheelFrame frame = new ColorWheelFrame();
                frame.setVisible(true);
            }
        });
    }

    private static class ColorWheelFrame extends JFrame {
        private ColorWheelFrame() {
            super("Color Wheel");
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            getContentPane().add(new ColorWheelPanel());
            pack();
        }
    }

    private static class ColorWheelPanel extends JComponent {
        private ColorWheelPanel() {
            setPreferredSize(new Dimension(400, 400));
        }
        public void paint(Graphics g) {
            Graphics2D g2 = (Graphics2D)g;
            int w = getWidth();
            int h = getHeight();
            int margin = 10;
            int radius = (Math.min(w, h) - 2 * margin)/2;
            int cx = w/2;
            int cy = h/2;
            float[] dist = {0.F, 1.0F};
            g2.setColor(Color.BLACK);
            g2.fillRect(0, 0, w, h);
            for (int angle = 0; angle < 360; ++angle) {
                Color color = hsvToRgb(angle, 1.0, 1.0);
                Color[] colors = {Color.WHITE, color};
                RadialGradientPaint paint = new RadialGradientPaint(cx, cy,
                        radius, dist, colors);
                g2.setPaint(paint);
                g2.fillArc(cx - radius, cy - radius, radius*2, radius*2,
                        angle, 1);
            }
        }
    }

    private static Color hsvToRgb(int h, double s, double v) {
        double hp = h/60.0;
        double c = s * v;
        double x = c * (1 - Math.abs(hp % 2.0 - 1));
        double m = v - c;
        double r = 0, g = 0, b = 0;
        if (hp <= 1) {
            r = c;
            g = x;
        } else if (hp <= 2) {
            r = x;
            g = c;
        } else if (hp <= 3) {
            g = c;
            b = x;
        } else if (hp <= 4) {
            g = x;
            b = c;
        } else if (hp <= 5) {
            r = x;
            b = c;
        } else {
            r = c;
            b = x;
        }
        r += m;
        g += m;
        b += m;
        return new Color((int)(r * 255), (int)(g * 255), (int)(b * 255));
    }
}
Output:

Media:Color_wheel_java.png

Julia

using Gtk, Graphics, Colors

const win = GtkWindow("Color Wheel", 450, 450) |> (const can = @GtkCanvas())
set_gtk_property!(can, :expand, true)

@guarded draw(can) do widget
    ctx = getgc(can)
    h = height(can)
    w = width(can)
    center = (x = w / 2, y = h / 2)
    anglestep = 1/w
    for θ in 0:0.1:360
        rgb = RGB(HSV(θ, 1, 1))
        set_source_rgb(ctx, rgb.r, rgb.g, rgb.b)
        line_to(ctx, center...)
        arc(ctx, center.x, center.y, w/2.2, 2π * θ / 360, anglestep)
        line_to(ctx, center...)
        stroke(ctx)
    end
end

show(can)
const condition = Condition()
endit(w) = notify(condition)
signal_connect(endit, win, :destroy)
wait(condition)

Kotlin

We reuse the class in the Bitmap task for this and add a member function to draw the color wheel. To give a more 'wheel-like' image, a constant 'saturation' of 1.0 has been used rather than one which varies in line with distance from the center.

// Version 1.2.41

import java.awt.Color
import java.awt.Graphics
import java.awt.image.BufferedImage
import java.io.File
import javax.imageio.ImageIO
import kotlin.math.*

class BasicBitmapStorage(width: Int, height: Int) {
    val image = BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR)

    fun fill(c: Color) {
        val g = image.graphics
        g.color = c
        g.fillRect(0, 0, image.width, image.height)
    }

    fun setPixel(x: Int, y: Int, c: Color) = image.setRGB(x, y, c.getRGB())

    fun getPixel(x: Int, y: Int) = Color(image.getRGB(x, y))

    fun colorWheel() {
        val centerX = image.width / 2
        val centerY = image.height / 2
        val radius = minOf(centerX, centerY)
        for (y in 0 until image.height) {
            val dy = (y - centerY).toDouble()
            for (x in 0 until image.width) {
                val dx = (x - centerX).toDouble()
                val dist = sqrt(dx * dx + dy * dy)
                if (dist <= radius) {
                    val theta = atan2(dy, dx)
                    val hue = (theta + PI) / (2.0 * PI)
                    val rgb = Color.HSBtoRGB(hue.toFloat(), 1.0f, 1.0f)
                    setPixel(x, y, Color(rgb))
                }
            }
        }
    }
}

fun main(args: Array<String>) {
    val bbs = BasicBitmapStorage(480, 480)
    with (bbs) {
        fill(Color.white)
        colorWheel()
        val cwFile = File("Color_wheel.png")
        ImageIO.write(image, "png", cwFile)
    }
}
Output:
Looks like mirror image of Smart BASIC entry 


Lua

Library: LÖVE
local function hsv_to_rgb (h, s, v)  -- values in ranges: [0, 360], [0, 1], [0, 1]
	local r = math.min (math.max (3*math.abs (((h	    )/180)%2-1)-1, 0), 1)
	local g = math.min (math.max (3*math.abs (((h	-120)/180)%2-1)-1, 0), 1)
	local b = math.min (math.max (3*math.abs (((h	+120)/180)%2-1)-1, 0), 1)
	local k1 = v*(1-s)
	local k2 = v - k1
	return k1+k2*r, k1+k2*g, k1+k2*b -- values in ranges: [0, 1], [0, 1], [0, 1]
end

function love.load()
	local w, h, r = 256, 256, 128-0.5
	local cx, cy = w/2, h/2
	canvas = love.graphics.newCanvas ()
	love.graphics.setCanvas(canvas)
		for x = 0, w do
			for y = 0, h do
				local dx, dy = x-cx, y-cy
				if dx*dx + dy*dy <= r*r then
					local h = math.deg(math.atan2(dy, dx))
					local s = (dx*dx + dy*dy)^0.5/r
					local v = 1
					love.graphics.setColor (hsv_to_rgb (h, s, v))
					love.graphics.points (x, y)
				end
			end
		end
	love.graphics.setCanvas()
end

function love.draw()
	love.graphics.setColor (1,1,1)
	love.graphics.draw (canvas)
end

M2000 Interpreter

Module Check {
      \\ we use an internal object for Math functions (here for Atan2)
      Declare Math Math
      Const tau=2*Pi, Center=2
      \\ change console size,  and center it ( using ;) to current monitor      
      Window 12, 800*twipsX,600*twipsY;
      \\ actual size maybe less (so can fit text exactly)
      Double  ' Double height characters
      Report Center, "Color wheel"
      Normal  ' restore to normal
      Atan2=Lambda Math (a, b) ->{
            Method Math, "Atan2", a, b As ret
            =ret
      }
      \\ brightness=1 for this program
      hsb2rgb=Lambda (hue, sat) ->{
            If sat == 0 Then {
                = 255, 255, 255
           } Else {
                  h=frac(hue+1)*6
                  f = frac(h)  
                  p = Int((1-sat)*255 + 0.5)
                  q = Int((1-sat*f)*255 + 0.5)
                  t = Int((1-sat*(1-f))*255 + 0.5)
                  Select Case Int(h)
                  Case 1
                      = q, 255, p
                  Case 2
                      = p, 255, t
                  Case 3
                     = p, q, 255
                  Case 4
                      = t, p, 255
                  Case 5
                      = 255, p, q
                  Else Case
                      = 255, t, p
                  End Select
          }
      }
      Let OffsetX=X.twips/2-128*TwipsX, OffsetY=Y.twips/2-128*TwipsY
      \\ a pixel has a size of TwipsX x TwipsY
      OffsetX=(OffsetX div TwipsX)*TwipsX
      OffsetY=(OffsetY div TwipsY)*TwipsY
      \\ We set hsb2rgb, OffsetX, OffsetY as closures to PrintPixel
      \\ We send to stack the R G B values using Stack ! array
      \\ hsb2rgb() return an array of values
      \\ we pop these values using Number
      PrintPixel = Lambda  hsb2rgb, OffsetX, OffsetY (x,y, theta, sat)  -> {
            Stack ! hsb2rgb(theta,sat)  
            PSet Color(number, number, number), x*TwipsX+offsetX, y*TwipsY+offsetY
      }
      \\ set Atan2, tau as closures to HueCircle
      \\ we can rotate/flip the wheel by changing signs in Atan2() and
      \\ by changing order of arguments (dx,dy) or (dy,dx). 8 combinations
      HueCircle= Lambda Atan2, tau (PrintPixel) -> {
            Let  c_width=256, c_height=256
            Let  cx=c_width/2, cy=c_height/2
            Let  radius=If(cx<=cy->cx, cy)
            c_width--
            c_height--
            dy=-cy
            For y=0 To c_height {
                  dy++ : dy2=dy*dy : dx=-cx
                  For x=0 To c_width {
                        dx++ : dist=Sqrt(dx^2+dy2)
                        If dist>radius Then continue
                        Call PrintPixel(x,y, Atan2(dx, -dy)/tau, dist/radius)
                  }
            }
      }
      Call HueCircle(PrintPixel)
      Scr$=""  ' we use this string  to load an image
      Move 0,0
      \\ scale.x, scale.y are twips height and width, of current layer
      Copy scale.x, scale.y to Scr$
      Clipboard Scr$  ' save window to clipboard
}
Check
Output:

see this image

Mathematica/Wolfram Language

r = 100;
Image[Table[
  If[x^2 + y^2 <= r^2,
   angle = Mod[ArcTan[N@x, y]/(2 Pi), 1];
   List @@ RGBColor[Hue[angle, Sqrt[x^2 + y^2]/N[r], 1.0]]
   ,
   {1, 1, 1}
   ], {x, -r, r}, {y, -r, r}]
 ]
Output:

Outputs an image.

Nim

Translation of: Rust
Library: imageman

As Rust code does, we store the color wheel in a PNG image.

import math

import imageman

#---------------------------------------------------------------------------------------------------

func hsvToRgb(h, s, v: float): ColorRGBU =
  ## Convert HSV values to RGB values.

  let hp = h / 60
  let c = s * v
  let x = c * (1 - abs(hp mod 2 - 1))
  let m = v - c
  var r, g, b = 0.0
  if hp <= 1:
    r = c
    g = x
  elif hp <= 2:
    r = x
    g = c
  elif hp <= 3:
    g = c
    b = x
  elif hp <= 4:
    g = x
    b= c
  elif hp <= 5:
    r = x
    b = c
  else:
    r = c
    b = x
  r += m
  g += m
  b += m
  result = ColorRGBU [byte(r * 255), byte(g * 255), byte(b * 255)]

#---------------------------------------------------------------------------------------------------

func buildColorWheel(image: var Image) =
  ## Build a color wheel into the image.

  const Margin = 10
  let diameter = min(image.w, image.h) - 2 * Margin
  let xOffset = (image.w - diameter) div 2
  let yOffset = (image.h - diameter) div 2
  let radius = diameter / 2

  for x in 0..diameter:
    let rx = x.toFloat - radius
    for y in 0..diameter:
      let ry = y.toFloat - radius
      let r = hypot(rx, ry) / radius
      if r > 1: continue
      let a = 180 + arctan2(ry, -rx).radToDeg()
      image[x + xOffset, y + yOffset] = hsvToRgb(a, r, 1)

#———————————————————————————————————————————————————————————————————————————————————————————————————

const
  Side = 400
  Output = "color_wheel.png"

var image = initImage[ColorRGBU](Side, Side)
image.buildColorWheel()

image.savePNG(Output, compression = 9)

Perl

Translation of: Sidef
use Imager;
use Math::Complex qw(cplx i pi);

my ($width, $height) = (300, 300);
my $center = cplx($width/2, $height/2);

my $img = Imager->new(xsize => $width,
                      ysize => $height);

foreach my $y (0 .. $height - 1) {
    foreach my $x (0 .. $width - 1) {

        my $vec = $center - $x - $y * i;
        my $mag = 2 * abs($vec) / $width;
        my $dir = (pi + atan2($vec->Re, $vec->Im)) / (2 * pi);

        $img->setpixel(x => $x, y => $y,
            color => {hsv => [360 * $dir, $mag, $mag < 1 ? 1 : 0]});
    }
}

$img->write(file => 'color_wheel.png');

Phix

Library: Phix/pGUI
Library: Phix/online

You can run this online here.

--
-- demo\rosetta\Colour_wheel.exw
-- =============================
--
--  Note: Made non-resizeable since maximising this is far too slow.
--
with javascript_semantics
include pGUI.e

constant title = "Colour wheel"
Ihandle dlg, canvas
cdCanvas cddbuffer, cdcanvas

function redraw_cb(Ihandle /*ih*/, integer /*posx*/, /*posy*/)
    integer {w, h} = IupGetIntInt(canvas, "DRAWSIZE")
    cdCanvasActivate(cddbuffer)
    integer radius = floor(min(w,h)/2)
    integer cx = floor(w/2),
            cy = floor(h/2)

    for x=1 to w do
        for y=1 to h do
            integer rx = x - cx,
                    ry = y - cy
            atom s = sqrt(rx*rx+ry*ry) / radius
            if s <= 1.0 then
                atom hue = ((atan2(ry, rx) / PI) + 1.0) / 2.0
                cdCanvasPixel(cddbuffer, x, h-y, hsv_to_rgb(hue, s, 1)) 
            end if 
        end for
    end for
    cdCanvasFlush(cddbuffer)
    return IUP_DEFAULT
end function

function map_cb(Ihandle ih)
    cdcanvas = cdCreateCanvas(CD_IUP, ih)
    cddbuffer = cdCreateCanvas(CD_DBUFFER, cdcanvas)
    cdCanvasSetBackground(cddbuffer, CD_WHITE)
    cdCanvasSetForeground(cddbuffer, CD_MAGENTA)
    return IUP_DEFAULT
end function

procedure main()
    IupOpen()
    canvas = IupCanvas(NULL)
    IupSetAttribute(canvas, "RASTERSIZE", "300x300")
    IupSetCallback(canvas, "MAP_CB", Icallback("map_cb"))
    dlg = IupDialog(canvas,`TITLE="%s",RESIZE=NO`,{title})
    IupSetCallback(canvas, "ACTION", Icallback("redraw_cb"))
    IupShowXY(dlg,IUP_CENTER,IUP_CENTER)
    if platform()!=JS then
        IupMainLoop()
        IupClose()
    end if
end procedure

main()

Processing

size(300, 300);
background(0);
float radius = min(width, height) / 2.0;
float cx = width / 2;
float cy = width / 2;
for (int x = 0; x < width; x++) {
  for (int y = 0; y < width; y++) {
    float rx = x - cx;
    float ry = y - cy;
    float s = sqrt(sq(rx) + sq(ry)) / radius;
    if (s <= 1.0) {
      float h = ((atan2(ry, rx) / PI) + 1.0) / 2.0;
      colorMode(HSB);
      color c = color(int(h * 255), int(s * 255), 255);
      set(x, y, c);
    }
  }
}

Processing Python mode

size(300, 300)
background(0)
radius = min(width, height) / 2.0
cx, cy = width / 2, width / 2
for x in range(width):
        for y in range(height):
            rx = x - cx
            ry = y - cy
            s = sqrt(rx ** 2 + ry ** 2) / radius
            if s <= 1.0:
                h = ((atan2(ry, rx) / PI) + 1.0) / 2.0
                colorMode(HSB)
                c = color(int(h * 255), int(s * 255), 255)
                set(x, y, c) # note set() used as Processing set() not as Python set()

Python

from PIL import Image
import colorsys
import math

if __name__ == "__main__":

    im = Image.new("RGB", (300,300))
    radius = min(im.size)/2.0
    cx, cy = im.size[0]/2, im.size[1]/2
    pix = im.load()
 
    for x in range(im.width):
        for y in range(im.height):
            rx = x - cx
            ry = y - cy
            s = (rx ** 2.0 + ry ** 2.0) ** 0.5 / radius
            if s <= 1.0:
                h = ((math.atan2(ry, rx) / math.pi) + 1.0) / 2.0
                rgb = colorsys.hsv_to_rgb(h, s, 1.0)
                pix[x,y] = tuple([int(round(c*255.0)) for c in rgb])

    im.show()

Racket

With the colors package

#lang racket

(require racket/draw
         colors)

(define DIM 500)
(define target (make-bitmap DIM DIM))
(define dc (new bitmap-dc% [bitmap target]))
(define radius 200)
(define center (/ DIM 2))

(define (atan2 y x) (if (= 0 y x) 0 (atan y x)))

(for* ([x (in-range DIM)]
       [y (in-range DIM)]
       [rx (in-value (- x center))]
       [ry (in-value (- y center))]
       [s (in-value (/ (sqrt (+ (sqr rx) (sqr ry))) radius))]
       #:when (<= s 1))
  (define h (* 0.5 (+ 1 (/ (atan2 ry rx) pi))))
  (send dc set-pen (hsv->color (hsv (if (= 1 h) 0 h) s 1)) 1 'solid)
  (send dc draw-point x y))

target

Raku

(formerly Perl 6)

Works with: Rakudo version 2016.08
use Image::PNG::Portable;

my ($w, $h) = 300, 300;

my $out = Image::PNG::Portable.new: :width($w), :height($h);

my $center = $w/2 + $h/2*i;

color-wheel($out);

$out.write: 'Color-wheel-perl6.png';

sub color-wheel ( $png ) {
    ^$w .race.map: -> $x {
        for ^$h -> $y {
            my $vector    = $center - $x - $y*i;
            my $magnitude = $vector.abs * 2 / $w;
            my $direction = ( π + atan2( |$vector.reals ) ) / τ;
            $png.set: $x, $y, |hsv2rgb( $direction, $magnitude, $magnitude < 1 );
        }
    }
}

sub hsv2rgb ( $h, $s, $v ){
    my $c = $v * $s;
    my $x = $c * (1 - abs( (($h*6) % 2) - 1 ) );
    my $m = $v - $c;
    (do given $h {
        when   0..^1/6 { $c, $x, 0 }
        when 1/6..^1/3 { $x, $c, 0 }
        when 1/3..^1/2 { 0, $c, $x }
        when 1/2..^2/3 { 0, $x, $c }
        when 2/3..^5/6 { $x, 0, $c }
        when 5/6..1    { $c, 0, $x }
    } ).map: ((*+$m) * 255).Int
}

Until local image uploading is re-enabled, see Color-wheel-perl6.png

Ring

Color wheel - image

#===================================================================#
#  Sample: Color Wheel 
#  Author: Gal Zsolt, Bert Mariani, Ilir Liburn & Mahmoud Fayed
#===================================================================#

load "guilib.ring"
 
xWidth  = 400
yHeight = 400
 
MyApp = new qapp 
{
   win1 = new qwidget() 
   {  setwindowtitle("ColorWheel-FastDraw")
      setgeometry(500,150,xWidth,yHeight)
      
      Canvas = new qlabel(win1)
      {  ### daVinci paints the MonaLisa on the Canvas
         MonaLisa  = new qPixMap2( xWidth, yHeight)
             color = new qcolor(){ setrgb(255,255,255,0) }
              pen  = new qpen()  { setwidth(1) }  
         MonaLisa.fill(color)

         daVinci = new qpainter()
         {  begin(MonaLisa)
            #endpaint()           ### This will Stop the Painting. For Animation comment it out
         }
         
         setPixMap(MonaLisa)
      }
      
      show()
   }
         
   ColorWheel()
   exec()
}
 
//=====================
 
Func colorWheel

   #=====================================================================#
   ? "Start Processing..."
   t1 = clock()
   ? "Clock : " + t1
   #=====================================================================#

   aList = []
   pi       = 3.14159265359
   diameter = pi * 2
   radius   = yHeight / 2
   v        = 1                    // value/brightness  1 to 100  1=bright 0=dark

   for i = 1 to xWidth
      iradius = i - radius
            p = pow( iradius, 2)

      for j = 1 to yHeight

          h = (atan2( iradius, j-radius ) + pi ) / diameter   // hue/color  1 to 360 
          s =   sqrt( p + pow( j-radius, 2)) / radius         // saturation/intensity 1 to 100
        
         if s <= 1 and h <= 1 
            aList + [i,j,h,s,v,1]
         ok
         
      next 
   next  

   #=====================================================================#
   ? "Start drawing..." 
   t2 = clock()
   ? "Clock : " + t2
   #=====================================================================#

   daVinci.drawHSVFList(aList)
   Canvas.setPixMap(MonaLisa)

   #=====================================================================#
   ? "Done..."
   t3 = clock()
   ? "Clock : " + t3
   #=====================================================================#
   ? "Processing Time: " + ( (t2-t1)/ClocksPerSecond() ) + " seconds "
   ? "Drawing Time: " + ( (t3-t2)/ClocksPerSecond() ) + " seconds "
   ? "Total Time: " + ( (t3-t1)/ClocksPerSecond() ) + " seconds "
   #=====================================================================#
   
 return  
   
//==================

Ruby

Library: RubyGems
Library: JRubyArt
def settings
  size(300, 300)
end

def setup
  sketch_title 'Color Wheel'
  background(0)
  radius = width / 2.0
  center = width / 2
  grid(width, height) do |x, y|
    rx = x - center
    ry = y - center
    sat = Math.hypot(rx, ry) / radius
    if sat <= 1.0
      hue = ((Math.atan2(ry, rx) / PI) + 1) / 2.0
      color_mode(HSB)
      col = color((hue * 255).to_i, (sat * 255).to_i, 255)
      set(x, y, col)
    end
  end
end

Run BASIC

' -----------------------------------
' color wheel
' -----------------------------------
global pi
pi	= 22 / 7
steps	= 1

graphic #g, 525, 525


for x =0 to 525 step steps
	for y =0 to 525 step steps
		angle   = atan2(y - 250, x - 250) * 360 / 2 / pi      '  full degrees....
		sector  = int(angle / 60)                             '    60 degree sectors (0 to 5)
		slope   = (angle mod 60) /60 * 255                    '     1 degree sectors.
		
		if  sector = 0 then  col$    = "255 ";                    str$( int( slope));      "   0"
		if  sector = 1 then  col$    = str$(int(256 - slope)); " 255                          0"
		if  sector = 2 then  col$    = "0                         255 ";                     str$( int( slope))
		if  sector = 3 then  col$    = "0 ";                      str$( int( 256 -slope)); " 255"
		if  sector = 4 then  col$    = str$(int(slope));    "     0                        255"
		if  sector = 5 then  col$    = "255                         0 ";                     str$( int( 256 -slope))
		
		red	= val( word$( col$, 1))
		grn	= val( word$( col$, 2))
		blu	= val( word$( col$, 3))
		p	= ((x -270)^2 +(y -270)^2)^0.5 / 250
		r	= min(255,p * red)
		g	= min(255,p * grn)
		b	= min(255,p * blu)
		if p > 1 then  #g "color white" else #g color(r,g,b)
		#g "set "; x; " "; y
	next y
next x
render #g
end

function atan2(y,x)
if (x = 0) and (y <> 0) then
	r$ = "Y"
	if y > 0 then atan2 = pi /2
	if y < 0 then atan2 = 3 * pi /2
end if

if y = 0 and (x <> 0) then
	r$ = "Y"
	if x > 0 then atan2 = 0
	if x < 0 then atan2 = pi
end if

If r$ <> "Y" then
	if x = 0 and y = 0 then
		atan2	= 0
		else
		baseAngle = atn(abs(y) / abs(x))
		if x > 0 then
			if y > 0 then atan2 = baseAngle
			If y < 0 then atan2 = 2 * pi - baseAngle
		end if
		if x < 0 then
			If y > 0 then atan2 = pi - baseAngle
			If y < 0 then atan2 = pi + baseAngle
		end if
	end if
end if
end function

Rust

Output is a file in PNG format.

// [dependencies]
// image = "0.23"

use image::error::ImageResult;
use image::{Rgb, RgbImage};

fn hsv_to_rgb(h: f64, s: f64, v: f64) -> Rgb<u8> {
    let hp = h / 60.0;
    let c = s * v;
    let x = c * (1.0 - (hp % 2.0 - 1.0).abs());
    let m = v - c;
    let mut r = 0.0;
    let mut g = 0.0;
    let mut b = 0.0;
    if hp <= 1.0 {
        r = c;
        g = x;
    } else if hp <= 2.0 {
        r = x;
        g = c;
    } else if hp <= 3.0 {
        g = c;
        b = x;
    } else if hp <= 4.0 {
        g = x;
        b = c;
    } else if hp <= 5.0 {
        r = x;
        b = c;
    } else {
        r = c;
        b = x;
    }
    r += m;
    g += m;
    b += m;
    Rgb([(r * 255.0) as u8, (g * 255.0) as u8, (b * 255.0) as u8])
}

fn write_color_wheel(filename: &str, width: u32, height: u32) -> ImageResult<()> {
    let mut image = RgbImage::new(width, height);
    let margin = 10;
    let diameter = std::cmp::min(width, height) - 2 * margin;
    let xoffset = (width - diameter) / 2;
    let yoffset = (height - diameter) / 2;
    let radius = diameter as f64 / 2.0;
    for x in 0..=diameter {
        let rx = x as f64 - radius;
        for y in 0..=diameter {
            let ry = y as f64 - radius;
            let r = ry.hypot(rx) / radius;
            if r > 1.0 {
                continue;
            }
            let a = 180.0 + ry.atan2(-rx).to_degrees();
            image.put_pixel(x + xoffset, y + yoffset, hsv_to_rgb(a, r, 1.0));
        }
    }
    image.save(filename)
}

fn main() {
    match write_color_wheel("color_wheel.png", 400, 400) {
        Ok(()) => {}
        Err(error) => eprintln!("{}", error),
    }
}
Output:

Media:Color_wheel_rust.png

Sidef

Translation of: Raku
require('Imager')

var (width, height) = (300, 300)
var center = Complex(width/2 , height/2)

var img = %O<Imager>.new(xsize => width, ysize => height)

for y=(^height), x=(^width) {
    var vector    = (center - x - y.i)
    var magnitude = (vector.abs * 2 / width)
    var direction = ((Num.pi + atan2(vector.real, vector.imag)) / Num.tau)
    img.setpixel(x => x, y => y,
        color => Hash(hsv => [360*direction, magnitude, magnitude < 1 ? 1 : 0])
    )
}

img.write(file => 'color_wheel.png')

Output image: Color wheel

Smart BASIC

' Runs on iOS
GET SCREEN SIZE sw,sh
xmax=0.45*3/7*(sw+sh)
x0=sw/2!y0=sh/2
twopi=2*3.1415926
GRAPHICS
GRAPHICS CLEAR
DIM triX(1000), triY(1000)
triX(0)=x0 ! triY(0)=y0
steps=INT(1^2*360)+1
dAngle=twopi/steps
dAngle2=dAngle/2
REFRESH OFF
FOR i=0 TO steps-1
  pal(i/steps+TintOffset)
  ANGLE=i*dAngle
  FILL COLOR pal.r,pal.g,pal.b
  DRAW COLOR pal.r,pal.g,pal.b
  x=x0+(xmax-radius)*COS(ANGLE)
  y=y0-(xmax-radius)*SIN(ANGLE)
  k=0
  FOR j=-dAngle2 TO dAngle2 STEP 0.02
    k+=1
    triX(k)=x0+xmax*COS(ANGLE+j)
    triY(k)=y0-xmax*SIN(ANGLE+j)
  NEXT j
  k+=1
  triX(k)=x0+xmax*COS(ANGLE+dAngle2)
  triY(k)=y0-xmax*SIN(ANGLE+dAngle2)
  DRAW POLY triX,triY COUNT k+1
  FILL POLY triX,triY COUNT k+1
NEXT i
REFRESH ON
END

DEF pal(tint)
tint=tint*360
h=(tint%360)/60 ! f=FRACT(h) ! z=1-f ! ic=FLOOR(h)+1
ON ic GOTO s1,s2,s3,s4,s5,s6
  s1: r=1 ! g=f ! b=0 ! GOTO done
  s2: r=z ! g=1 ! b=0 ! GOTO done
  s3: r=0 ! g=1 ! b=f ! GOTO done
  s4: r=0 ! g=z ! b=1 ! GOTO done
  s5: r=f ! g=0 ! b=1 ! GOTO done
  s6: r=1 ! g=0 ! b=z ! done:
END DEF

View the output on Dropbox https://www.dropbox.com/s/g3l5rbywo34bnp6/IMG_4600.PNG?dl=0 This file is no longer there!!! 10 Sep 2021

VBScript

Building a BMP file and opening it with the default viewer. It takes 5 seconds in my 5 years old notebook. Run with Cscript if you don want to be clicking at annoying message boxes.

option explicit

Class ImgClass
  Private ImgL,ImgH,ImgDepth,bkclr,nclr,tt
  private xmini,xmaxi,ymini,ymaxi
  dim ImgArray()  'rgb in 24 bit mode, indexes to palette in 8 bits
  private filename   
  private Palette
  
public property get xmin():xmin=xmini:end property  
public property get ymin():ymin=ymini:end property  
public property get xmax():xmax=xmaxi:end property  
public property get ymax():ymax=ymaxi:end property  
public property let depth(x)
     if x<>8 and x<>32 then err.raise 9
     Imgdepth=x
end property     
  
  public sub set0 (x0,y0) 'sets the new origin (default tlc)
    if x0<0 or x0>=imgl or y0<0 or y0>imgh then err.raise 9 
    xmini=-x0
    ymini=-y0
    xmaxi=xmini+imgl-1
    ymaxi=ymini+imgh-1    
  end sub
  
  'constructor
  Public Default Function Init(name,w,h,dep,bkg,pal)
     dim i,j
     ImgL=w
     ImgH=h
  
     tt=timer
     depth=dep
     if dep<>8 and dep <>32 then err.raise 9
     set0 0,0  'tlc
     redim imgArray(ImgL-1,ImgH-1)
     bkclr=bkg
     if bkg<>0 then 
       for i=0 to ImgL-1 
         for j=0 to ImgH-1 
            imgarray(i,j)=bkg
         next
       next  
    end if   
     filename=name
 
     'load user palette if provided  
     if imgdepth=8 then 
       if isarray(pal) then
        if ubound(pal)=255 then
            palette=pal
        else
           mypalette          
        end if
      else
        mypalette
      end if 
     end if       
     set init=me
  end function

  
  'class termination writes it to a BMP file and displays it 
  'if an error happens VBS terminates the class before exiting so the BMP is displayed the same
  Private Sub Class_Terminate
    
    if err<>0 then wscript.echo "Error " & err.number
    wscript.echo "copying image to bmp file"
    savebmp
    wscript.echo "opening " & filename & " with uour default viewer"
    CreateObject("Shell.Application").ShellExecute filename
    wscript.echo timer-tt & " milliseconds"
  End Sub


   function long2str(byval k)
        Dim s
        s= chr(k and &hff)
        k=k\&h100
        s=s& chr(k and &hff)
        k=k\&h100
        s=s& chr(k and &hff)
        k=k\&h100
        s=s& chr(k and &hff)
        long2str=s
    End function
  
    function int2str(byval k)
        Dim s
        s= chr(k and &hff)
        k=k\&h100
        s=s& chr(k and &hff)
        int2str=s
    End function
 
  Public Sub SaveBMP
    'Save the picture to a bmp file
    Dim s,ostream, x,y,loc
    dim bpp:bpp=imgdepth\8
    const hdrs=54 '14+40 
    dim bms:bms=ImgH* 4*(((ImgL*bpp)+3)\4)  'bitmap size including padding
    dim pals:if (imgdepth=8) then pals=(ubound(Palette)+1)*4 else pals=0
    loc=getlocale
    setlocale "us"

    with  CreateObject("ADODB.Stream") 'auxiliary ostream, it creates an UNICODE with bomb stream in memory
      .Charset = "Windows-1252"  
      .Type =  2' adTypeText  
      .open 
      
      'build a header
      'bmp header: VBSCript does'nt have records nor writes binary values to files, so we use strings of unicode chars!! 
      'BMP head  0 "BM" 'Type  2 size            6            10                   14
      .writetext "BM" & long2str(hdrs+pals+bms)& long2str(0) &long2str (hdrs+pals) 

      'InfoHeader 14  hdr sz   18 length      22 width         26 pla       28 clr depth        30 NOCOMPR   34 
      .writetext long2str(40) &long2str(Imgl)&long2str(imgh) & int2str(1) & int2str(imgdepth)& long2str(&H0)
      
       '         34 nosize     38 bpp           42 bpp           46  cls pal     50 imp clrs   54
      .writetext long2str(bms)&long2str(&Hc4e)& long2str(&hc43)& long2str(&H0) & long2str(&H0)

      'add palette if exists
      If (imgdepth=8) Then
        s=""
        For x=0 to ubound(palette)
          s=s& long2str(palette(x))
        Next
        .writetext s
      End If
      
      'write bitmap
      Select Case ImgDepth
      Case 32
      'wscript.echo imgdepth
        For y=ImgH-1 to 0 step-1  'Origin of bitmap: bottom left
          s=""
          For x=0 To ImgL-1
           'writelong fic, Pixel(x,y) 
           s=s & long2str(Imgarray(x,y))
          Next
          .writetext s
        Next
      Case 8
        dim xx:xx=ImgL mod 4
        For y=ImgH-1 to 0 step-1
          s=""
          For x=0 To ImgL-1 step 2
               s=s & chrw((ImgArray(x,y) and 255 )+ 256*(ImgArray(x+1,y) and 255))
          Next
          if xx and 1 then s=s &chrw(ImgArray(Imgl-1,y))
          if xx >1 then s=s & chrw(0)
          .writetext s 
        Next
      Case Else
        WScript.Echo "ColorDepth not supported : " & ImgDepth & " bits"
      End Select

      'save to file
      .position=0              'using single byte chars, no bom
      .savetofile filename,2   'adSaveCreateOverWrite
      .close
    end with
    setlocale loc
  End Sub
end class
 

function hsv2rgb( Hue, Sat, Value) 'hue 0-360   0-ro 120-ver 240-az ,sat 0-100,value 0-100
  dim Angle, Radius,Ur,Vr,Wr,Rdim
  dim r,g,b, rgb
  Angle = (Hue-150) *0.01745329251994329576923690768489
  Ur = Value * 2.55
  Radius = Ur * tan(Sat *0.01183199)
  Vr = Radius * cos(Angle) *0.70710678  'sqrt(1/2)
  Wr = Radius * sin(Angle) *0.40824829  'sqrt(1/6)
  r = (Ur - Vr - Wr)  
  g = (Ur + Vr - Wr) 
  b = (Ur + Wr + Wr) 
  
  'clamp values 
 if r >255 then 
   Rdim = (Ur - 255) / (Vr + Wr)
   r = 255
   g = Ur + (Vr - Wr) * Rdim
   b = Ur + 2 * Wr * Rdim 
 elseif r < 0 then
   Rdim = Ur / (Vr + Wr)
   r = 0
   g = Ur + (Vr - Wr) * Rdim
   b = Ur + 2 * Wr * Rdim 
 end if 

 if g >255 then 
   Rdim = (255 - Ur) / (Vr - Wr)
   r = Ur - (Vr + Wr) * Rdim
   g = 255
   b = Ur + 2 * Wr * Rdim
 elseif g<0 then   
   Rdim = -Ur / (Vr - Wr)
   r = Ur - (Vr + Wr) * Rdim
   g = 0
   b = Ur + 2 * Wr * Rdim   
 end if 
 if b>255 then
   Rdim = (255 - Ur) / (Wr + Wr)
   r = Ur - (Vr + Wr) * Rdim
   g = Ur + (Vr - Wr) * Rdim
   b = 255
 elseif b<0 then
   Rdim = -Ur / (Wr + Wr)
   r = Ur - (Vr + Wr) * Rdim
   g = Ur + (Vr - Wr) * Rdim
   b = 0
 end if
 hsv2rgb= ((b and &hff)+256*((g and &hff)+256*(r and &hff))and &hffffff)

end function

function ang(col,row)
    'if col =0 then  if row>0 then ang=0 else ang=180:exit function 
    if col =0 then  
      if row<0 then ang=90 else ang=270 end if
    else  
   if col>0 then
      ang=atn(-row/col)*57.2957795130
   else
     ang=(atn(row/-col)*57.2957795130)+180
  end if
  end if
   ang=(ang+360) mod 360  
end function 


Dim X,row,col,fn,tt,hr,sat,row2
const h=160
const w=160
const rad=159
const r2=25500
tt=timer
fn=CreateObject("Scripting.FileSystemObject").GetSpecialFolder(2)& "\test.bmp"
Set X = (New ImgClass)(fn,w*2,h*2,32,0,0)

x.set0 w,h
'wscript.echo x.xmax, x.xmin

for row=x.xmin+1 to x.xmax
   row2=row*row
   hr=int(sqr(r2-row2))
   for col=-hr to hr
     sat=100-sqr(row2+col*col)/rad *50
    ' wscript.echo c,r
     x.imgArray(col+160,row+160)=hsv2rgb(ang(row,col)+90,100,sat)
    next
    'script.echo row
  next  

Set X = Nothing

Wren

Library: DOME
import "graphics" for Canvas, Color
import "dome" for Window
import "random" for Random

class Game {
    static init() {
        Window.title = "Color Wheel"
        __width = 640
        __height = 640
        Window.resize(__width, __height)
        Canvas.resize(__width, __height)
        colorWheel()
    }

    static colorWheel() {
        var cx = (__width/2).floor
        var cy = (__height/2).floor
        var r = (cx < cy) ? cx : cy
        for (y in 0...__height) {
            var dy = y - cy
            for (x in 0...__width) {
                var dx = x - cx
                var dist = (dx*dx + dy*dy).sqrt
                if (dist <= r) {
                    var theta = dy.atan(dx)
                    var h = (theta + Num.pi) / Num.pi * 180
                    var col = Color.hsv(h, dist/r, 1)
                    Canvas.pset(x, y, col)
                }
            }
        }
    }

    static update() {}

    static draw(alpha) {}
}

XPL0

Algorithm is from "Computer Graphics ..." by Foley et al. The output is the same as Zkl.

def  Radius = 480/2;
real Hue, Sat, Dist, I, F, P, Q, T;
real XX, YY, RR, GG, BB;
int  X, Y, R, G, B;
def  Pi = 3.141592654;
def  V = 1.;            \Value
[SetVid($112);          \640x480x24 graphics
for Y:= -Radius to Radius do
    for X:= -Radius to Radius do
        [XX:= float(X);
         YY:= float(Y);
         Dist:= sqrt(XX*XX + YY*YY);
         if Dist <= float(Radius) then
                [Sat:= Dist/float(Radius);      \0 >= Sat <= 1
                Hue:= ATan2(YY, XX);            \-Pi >= Hue <= Pi
                if Hue < 0. then Hue:= Hue + 2.*Pi;
                Hue:= Hue * 180./Pi;            \radians to degrees
                Hue:= Hue / 60.;                \0 >= Hue < 6
                I:= Floor(Hue);                 \integer part of Hue
                F:= Hue - I;                    \fractional part of Hue
                P:= 1. - Sat;
                Q:= 1. - Sat*F;
                T:= 1. - Sat*(1.-F);
                case fix(I) of
                  0:    [RR:= V;  GG:= T;  BB:= P];
                  1:    [RR:= Q;  GG:= V;  BB:= P];
                  2:    [RR:= P;  GG:= V;  BB:= T];
                  3:    [RR:= P;  GG:= Q;  BB:= V];
                  4:    [RR:= T;  GG:= P;  BB:= V];
                  5:    [RR:= V;  GG:= P;  BB:= Q]
                other   [exit 1];
                R:= fix(RR*255.);
                G:= fix(GG*255.);
                B:= fix(BB*255.);
                Point(X+Radius, Radius-Y, R<<16+G<<8+B);
                ];
        ];
]

zkl

Uses Image Magick and the PPM class from http://rosettacode.org/wiki/Bitmap/Bresenham%27s_line_algorithm#zkl

var w=300,h=300,out=PPM(w,h);
colorWheel(out);
out.writeJPGFile("colorWheel.zkl.jpg");

fcn colorWheel(ppm){
   zero,R:=ppm.w/2, zero;
   foreach x,y in (w,h){
      v,hue:=(x - zero).toFloat().toPolar(y - zero); 
      if(v<=R){    // only render in the circle
	 if((hue = hue.toDeg())<0) hue+=360;  // (-pi..pi] to [0..2pi)
	 s:=v/R;  // scale saturation zero at center to 1 at edge
	 ppm[x,y]=hsv2rgb(hue,1.0,s);
      }
   }
}

fcn hsv2rgb(hue,v,s){  //  0<=H<360, 0<=v(brightness)<=1, 0<=saturation<=1
		       // --> 24 bit RGB each R,G,B in [0..255]
   to24bit:=fcn(r,g,b,m){
      r,g,b=((r+m)*255).toInt(),((g+m)*255).toInt(),((b+m)*255).toInt();
      r*0x10000 + g*0x100 + b
   };
   c:=v*s;
   x:=c*(1.0 - (hue.toFloat()/60%2 - 1).abs());
   m:=v - c;
   if     (0  <=hue< 60) return(to24bit(c,  x,  0.0,m));
   else if(60 <=hue<120) return(to24bit(x,  c,  0.0,m));
   else if(120<=hue<180) return(to24bit(0.0,c,  x,  m));
   else if(180<=hue<240) return(to24bit(0.0,x,  c,  m));
   else if(240<=hue<300) return(to24bit(x,  0.0,c,  m));
   else			 return(to24bit(c,  0.0,x,  m));
}
Output:

See this image