Polar/Radar & Spider Plots

Polar, Radar, and Spider plots are different names for essentially the same thing: two-dimensional plots using a polar coodrinate system. In a 2-d polar coordinate system one axis is radial, measuring distance from the center of the graph, and the second axis is angular, measuring angle around a circle.

Polar Graph

Analogous to the XYGraph for 2-d Cartesian plots, there is PolarGraph for creating the surface onto which polar plots can be composed. The below example illustrates a PolarGraph with mostly default configuration:

1
2
3
4
5
    PolarGraph(
        rememberFloatRadialAxisModel(List(6) { it.toFloat() }),
        rememberAngularValueAxisModel(),
        angularAxisLabelText = { "${it.toDegrees().value}\u00B0" }
    ) { }
/examples/src/jvmMain/kotlin/io/github/koalaplot/example/Polar1.kt

Polar Graph

In this example the radial axis uses Float values, and the angular axis uses AngularValues, a sealed type that represents angular coordinates in degrees or radians and can transform between the two scales. The defaultAngularValueAxisModel produces ticks at every 45-degrees.

The angular axis can be any type that implements the AngularAxisModel interface. Koala Plot provides an implementation that uses a List of elements of an arbitrary type, CategoryAngularAxisModel, that places its elements evenly spaced around the circumfrence of the plot.

Below is an example using String as the category objects:

1
2
3
4
    PolarGraph(
        rememberFloatRadialAxisModel(List(6) { it.toFloat() }),
        rememberCategoryAngularAxisModel(listOf("A", "B", "C", "D", "E")),
    ) { }
/examples/src/jvmMain/kotlin/io/github/koalaplot/example/Polar4.kt

Polar Graph

Polar Graph Styling

The above examples draw the radial grid lines as concentric circles. An alternative is to draw them as straight lines between angular grid lines, as illustrated in the below example:

1
2
3
4
5
6
    PolarGraph(
        rememberFloatRadialAxisModel(List(6) { it.toFloat() }),
        rememberAngularValueAxisModel(),
        angularAxisLabelText = { "${it.toDegrees().value}\u00B0" },
        polarGraphProperties = PolarGraphDefaults.PolarGraphPropertyDefaults().copy(RadialGridType.LINES)
    ) { }
/examples/src/jvmMain/kotlin/io/github/koalaplot/example/Polar2.kt

Spider Graph

This cosmetic alternative is often referred to as a Spider Chart because of its resemblance to a spider web, but functionally it is identical to the polar graph from the first example.

Other key elements of the PolarGraph that can be styled include the axis lines and the background, as shown in the below example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
    PolarGraph(
        rememberFloatRadialAxisModel(List(6) { it.toFloat() }),
        rememberAngularValueAxisModel(),
        angularAxisLabelText = { "${it.toDegrees().value}\u00B0" },
        polarGraphProperties = PolarGraphDefaults.PolarGraphPropertyDefaults().copy(
            radialAxisGridLineStyle = LineStyle(SolidColor(Color.DarkGray)),
            angularAxisGridLineStyle = LineStyle(SolidColor(Color.Blue)),
            background = AreaStyle(SolidColor(Color.LightGray))
        )
    ) { }
/examples/src/jvmMain/kotlin/io/github/koalaplot/example/Polar3.kt

Polar Graph

Polar Plots

PolarPlotSeries is used within the PolarGraph to plot lines, symbols, areas, or any combination of the three. The below example demonstrates using symbols to create polar scatter plots of two data sets:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
    val data1: List<PolarPoint<Float, AngularValue>> = buildList {
        for (i in 1..20) {
            add(PolarPoint(random.nextFloat() * 5f, (15.2f + random.nextFloat() * 15f).toDegrees()))
        }
    }
    val data2: List<PolarPoint<Float, AngularValue>> = buildList {
        for (i in 1..20) {
            add(PolarPoint(random.nextFloat() * 5f, (95f + random.nextFloat() * 35f).toDegrees()))
        }
    }

    PolarGraph(
        rememberFloatRadialAxisModel(List(6) { it.toFloat() }),
        rememberAngularValueAxisModel(),
        angularAxisLabelText = { "${it.toDegrees().value}\u00B0" }
    ) {
        PolarPlotSeries(data1, symbols = { Symbol(shape = CircleShape, fillBrush = SolidColor(Color.Blue)) })
        PolarPlotSeries(data2, symbols = { Symbol(shape = CircleShape, fillBrush = SolidColor(Color.Red)) })
    }
/examples/src/jvmMain/kotlin/io/github/koalaplot/example/Polar5.kt

Polar Scatter Plot

To plot lines and/or areas, specify the styling for each as parameters to the PolarPlotSeries as shown in the below example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
    fun cardioid(theta: Double): Double = 2F * (1F + cos(theta))

    val data1: List<PolarPoint<Float, AngularValue>> = buildList {
        for (theta in 0..360) {
            add(PolarPoint(cardioid(theta * PI / 180F).toFloat(), theta.toFloat().toDegrees()))
        }
    }

    PolarGraph(
        rememberFloatRadialAxisModel(List(6) { it.toFloat() }),
        rememberAngularValueAxisModel(),
        angularAxisLabelText = { "${it.toDegrees().value}\u00B0" }
    ) {
        PolarPlotSeries(
            data1,
            lineStyle = LineStyle(SolidColor(Color.Blue), strokeWidth = 2.dp),
            areaStyle = AreaStyle(SolidColor(Color.Blue.copy(alpha = 0.2f)))
        )
    }
/examples/src/jvmMain/kotlin/io/github/koalaplot/example/Polar6.kt

Cardioid Plot


Last modified November 26, 2023: Add polar graphs section. (58710d1)