Skip to content

Instantly share code, notes, and snippets.

@theoknock
Created May 27, 2024 01:05
Show Gist options
  • Save theoknock/37933ba56fb07f57cc7c13b5ebe0594c to your computer and use it in GitHub Desktop.
Save theoknock/37933ba56fb07f57cc7c13b5ebe0594c to your computer and use it in GitHub Desktop.
A circular distribution or polar distribution is a probability distribution of a random variable whose values are angles, usually taken to be in the range [0, 2π). A circular distribution is often a continuous probability distribution, and hence has a probability density, but such distributions can also be discrete, in which case they are called…
/*
A circular distribution or polar distribution is a probability distribution of a random variable whose values are angles, usually taken to be in the range [0, 2π). A circular distribution is often a continuous probability distribution, and hence has a probability density, but such distributions can also be discrete, in which case they are called circular lattice distributions. Circular distributions can be used even when the variables concerned are not explicitly angles: the main consideration is that there is not usually any real distinction between events occurring at the opposite ends of the range, and the division of the range could notionally be made at any point.
*/
// https://en.wikipedia.org/wiki/Circular_distribution
import SwiftUI
func scale(oldMin: Double, oldMax: Double, value: Double, newMin: Double, newMax: Double) -> Double {
return ((value - oldMin) / (oldMax - oldMin)) * (newMax - newMin) + newMin
}
struct ContentView: View {
@State private var firstAngles: [Double] = []
@State private var secondAngles: [Double] = []
@State private var minusThresholdAngles: [Double] = []
@State private var plusThresholdAngles: [Double] = []
@State private var differences: [Double] = []
let threshold: Double = 45.0
var body: some View {
VStack {
Button(action: generateAngles) {
Text("Generate Angles")
}
List(0 ..< firstAngles.count, id: \.self) { index in
VStack(alignment: .leading) {
Text("\(Int(minusThresholdAngles[index]))° < \(Int(firstAngles[index]))° < \(Int(plusThresholdAngles[index]))° = \(Int(differences[index]))°")
Text("\(scale(oldMin: 0.0, oldMax: 360.0, value: firstAngles[index], newMin: 0.0, newMax: 1.0))")
Text("\(scale(oldMin: 0.0, oldMax: 360.0, value: differences[index], newMin: 0.0, newMax: 1.0))")
}
}
}
.padding()
}
private func generateAngles() {
firstAngles = (0 ..< 10).map { _ in generateRandomAngle(max: 360.0) }
secondAngles = (0 ..< 10).map { i in generateRandomAngle(max: firstAngles[i]) }
minusThresholdAngles = firstAngles.map { wrapAngle($0 - threshold) }
plusThresholdAngles = firstAngles.map { wrapAngle($0 + threshold) }
differences = zip(secondAngles, zip(minusThresholdAngles, plusThresholdAngles)).map { calculateShortestDifference($0, $1.0, $1.1) }
differences = (0 ..< 10).map { i in wrapAngle(differences[i] + firstAngles[i]) }
}
private func generateRandomAngle(max: Double) -> Double {
return Double.random(in: 0 ... max)
}
private func calculateShortestDifference(_ angle2: Double, _ minusThreshold: Double, _ plusThreshold: Double) -> Double {
let diffMinusThreshold = calculateShortestDistance(angle2, minusThreshold)
let diffPlusThreshold = calculateShortestDistance(angle2, plusThreshold)
return max(diffMinusThreshold, diffPlusThreshold)
}
private func calculateShortestDistance(_ angle1: Double, _ angle2: Double) -> Double {
let diff = abs(angle1 - angle2)
return min(diff, 360 - diff)
}
private func wrapAngle(_ angle: Double) -> Double {
let wrapped = angle.truncatingRemainder(dividingBy: 360)
return wrapped >= 0 ? wrapped : wrapped + 360
}
}
#Preview {
ContentView()
.preferredColorScheme(.dark)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment