Skip to content

Instantly share code, notes, and snippets.

@theoknock
Last active June 5, 2024 10:03
Show Gist options
  • Save theoknock/0bf6b2ccaba4d463524fc985f428d549 to your computer and use it in GitHub Desktop.
Save theoknock/0bf6b2ccaba4d463524fc985f428d549 to your computer and use it in GitHub Desktop.
"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_distribu…
import Foundation
import SwiftUI
import Combine
import Observation
struct ContentView: View {
@State private var randoms: LatticeCircularDistributor = LatticeCircularDistributor(boundLower: 0.3125, boundUpper: 0.3125, threshholdLeft: 0.25, threshholdRight: 0.25)
var body: some View {
Spacer()
VStack {
Spacer()
Text("\(randoms.description())")
.font(.body).monospacedDigit()
Spacer()
Button(action: {
randoms.distributeRandoms(randoms: &randoms.randoms)
}, label: {
Text("Generate randoms")
.padding()
.border(.blue, width: 1.0)
})
Spacer()
}
.onAppear {
randoms.distributeRandoms(randoms: &randoms.randoms)
}
Spacer()
}
}
#Preview {
ContentView()
.preferredColorScheme(.dark)
}
import Foundation
import SwiftUI
import Combine
import Observation
@Observable class LatticeCircularDistributor {
var boundLower: Float64
var boundUpper: Float64
var randoms: [Float64] = [Float64.zero, Float64.zero]
var threshholdLeft: Float64
var threshholdRight: Float64
func scaledAngle(scale: Float64) -> Float64 {
return Float64(abs(360.0 * scale))
}
func offsetByDegrees(startAngle: Float64, offsetDegrees: Float64) -> Float64 {
return Float64((startAngle + offsetDegrees).truncatingRemainder(dividingBy: 360.0))
}
// func offsetAngle(startAngle: Float64, offsetDegrees: Float64) -> Float64 {
// let radians = (startAngle + offsetDegrees) * .pi / 180.0
// let sinValue = sin(radians)
// let cosValue = cos(radians)
// let angle = atan2(sinValue, cosValue) * 180.0 / .pi
// return angle
// }
func offsetAngle(startAngle: Float64, offsetDegrees: Float64) -> Float64 {
let radians = (startAngle + offsetDegrees) * .pi / 180.0
let sinValue = sin(radians)
let cosValue = cos(radians)
let angle = atan2(sinValue, cosValue) * 180.0 / .pi
let wrappedAngle = angle + 360.0 * floor((360.0 - angle) / 360.0)
return wrappedAngle
}
private func wrapAngle(_ angle: Double) -> Double {
let wrapped = angle.truncatingRemainder(dividingBy: 360)
return wrapped >= 0 ? wrapped : wrapped + 360
}
func description() -> String {
return String("\(randoms[0])°\t\t\(randoms[1])°")
}
func distributeRandoms(randoms: inout [Float64]) -> (Void) {
let lowerRangeBoundary: Float64 = scaledAngle(scale: 0.0625)
let upperRangeBoundary: Float64 = scaledAngle(scale: 0.9375)
print("lowerRangeBoundary == \(lowerRangeBoundary)")
print("upperRangeBoundary == \(upperRangeBoundary)")
let firstRandom: Float64 = Float64.random(in: lowerRangeBoundary ... upperRangeBoundary)
print("firstRandom == \(firstRandom)")
let lowerRandomThreshold: Float64 = scaledAngle(scale: 0.0625)
let upperRandomThreshold: Float64 = scaledAngle(scale: 0.0625)
print("lowerRandomThreshold == \(lowerRandomThreshold)")
print("upperRandomThreshold == \(upperRandomThreshold)")
// get the actual lowerRangeBoundary and the relative lowerRandomThreshold and use offset func to calculate new lower bounds
let secondRandomLowerRange: Float64 = Float64(offsetAngle(startAngle: lowerRangeBoundary, offsetDegrees: lowerRandomThreshold))
let secondRandomUpperRange: Float64 = Float64(offsetAngle(startAngle: upperRangeBoundary, offsetDegrees: -upperRandomThreshold))
print("secondRandomLowerRange == \(secondRandomLowerRange)")
print("secondRandomUpperRange == \(secondRandomUpperRange)")
let nextRandom: Float64 = Float64.random(in: secondRandomLowerRange ... secondRandomUpperRange)
print("nextRandom == \(nextRandom)")
let adjustedSecondRandom: Float64 = Float64(offsetAngle(startAngle: nextRandom, offsetDegrees: firstRandom))
print("adjustedSecondRandom == \(adjustedSecondRandom)")
randoms = [firstRandom, nextRandom]
}
init(boundLower: Float64, boundUpper: Float64, threshholdLeft: Float64, threshholdRight: Float64) {
self.boundLower = boundLower
self.boundUpper = boundUpper
self.threshholdLeft = threshholdLeft
self.threshholdRight = threshholdRight
distributeRandoms(randoms: &self.randoms)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment