[orx-math] Add demo and readme texts.
This commit is contained in:
@@ -11,12 +11,12 @@ import kotlin.math.cos
|
||||
import kotlin.random.Random
|
||||
|
||||
/**
|
||||
* Demonstrate least squares method to find a regression line through noisy points
|
||||
* Line drawn in red is the estimated line, in green is the ground-truth line
|
||||
* Demonstrate least squares method to find a regression line through noisy points.
|
||||
* The line drawn in red is the estimated line. The green one is the ground-truth.
|
||||
*
|
||||
* Ax = b => x = A⁻¹b
|
||||
* because A is likely inconsistent, we look for an approximate x based on AᵀA, which is consistent.
|
||||
* x̂ = (AᵀA)⁻¹ Aᵀb
|
||||
* `Ax = b => x = A⁻¹b`
|
||||
* because `A` is likely inconsistent, we look for an approximate `x` based on `AᵀA`, which is consistent.
|
||||
* `x̂ = (AᵀA)⁻¹ Aᵀb`
|
||||
*/
|
||||
fun main() {
|
||||
application {
|
||||
@@ -26,23 +26,23 @@ fun main() {
|
||||
}
|
||||
program {
|
||||
extend {
|
||||
val ls = drawer.bounds.horizontal(0.5).rotateBy(cos(seconds)*45.0)
|
||||
val groundTruth = drawer.bounds.horizontal(0.5).rotateBy(cos(seconds) * 45.0)
|
||||
|
||||
val r = Random((seconds*10).toInt())
|
||||
val r = Random((seconds * 10).toInt())
|
||||
|
||||
val pointCount = 100
|
||||
val A = Matrix(pointCount, 2)
|
||||
val b = Matrix(pointCount, 1)
|
||||
for (i in 0 until pointCount) {
|
||||
|
||||
val p = ls.position(Double.uniform(0.0, 1.0, r))
|
||||
val pr = p + Vector2.uniformRing(0.0, 130.0, r)
|
||||
val point = groundTruth.position(Double.uniform(0.0, 1.0, r))
|
||||
val pointRandomized = point + Vector2.uniformRing(0.0, 130.0, r)
|
||||
|
||||
A[i, 0] = 1.0
|
||||
A[i, 1] = pr.x
|
||||
b[i, 0] = pr.y
|
||||
A[i, 1] = pointRandomized.x
|
||||
b[i, 0] = pointRandomized.y
|
||||
|
||||
drawer.circle(pr, 5.0)
|
||||
drawer.circle(pointRandomized, 5.0)
|
||||
}
|
||||
val At = A.transposed()
|
||||
val AtA = At * A
|
||||
@@ -58,7 +58,7 @@ fun main() {
|
||||
drawer.lineSegment(p0, p1)
|
||||
|
||||
drawer.stroke = ColorRGBa.GREEN
|
||||
drawer.lineSegment(ls)
|
||||
drawer.lineSegment(groundTruth)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,17 @@ import kotlin.math.pow
|
||||
import kotlin.random.Random
|
||||
|
||||
/**
|
||||
* Demonstrate least squares method to fit a cubic bezier to noisy points
|
||||
* Demonstrate how to use the `least squares` method to fit a cubic bezier to noisy points.
|
||||
*
|
||||
* On every animation frame, 10 concentric circles are created centered on the window and converted to contours.
|
||||
* In OPENRNDR, circular contours are made ouf of 4 cubic-Bezier curves. Each of those curves is considered
|
||||
* one by one as the ground truth, then 5 points are sampled near those curves.
|
||||
* Finally, two matrices are constructed using those points and math operations are applied to
|
||||
* revert the randomization attempting to reconstruct the original curves.
|
||||
*
|
||||
* The result is drawn on every animation frame, revealing concentric circles that are more or less similar
|
||||
* to the ground truth depending on the random values used.
|
||||
*
|
||||
*/
|
||||
fun main() {
|
||||
application {
|
||||
@@ -34,8 +44,8 @@ fun main() {
|
||||
}
|
||||
extend {
|
||||
for (z in 0 until 10) {
|
||||
val c = Circle(drawer.bounds.center, 300.0- z*30.0).contour
|
||||
for (ls in c.segments) {
|
||||
val c = Circle(drawer.bounds.center, 300.0 - z * 30.0).contour
|
||||
for (groundTruth in c.segments) {
|
||||
|
||||
val pointCount = 5
|
||||
val A = Matrix(pointCount, 4)
|
||||
@@ -46,15 +56,15 @@ fun main() {
|
||||
pointCount - 1 -> 1.0
|
||||
else -> Double.uniform(0.0, 1.0, r)
|
||||
}
|
||||
val p = ls.position(t)
|
||||
val pr = p + Vector2.uniformRing(0.0, 0.5, r)
|
||||
val point = groundTruth.position(t)
|
||||
val pointRandomized = point + Vector2.uniformRing(0.0, 0.5, r)
|
||||
|
||||
A[i, 0] = bernstein(3, 0, t)
|
||||
A[i, 1] = bernstein(3, 1, t)
|
||||
A[i, 2] = bernstein(3, 2, t)
|
||||
A[i, 3] = bernstein(3, 3, t)
|
||||
b[i, 0] = pr.x
|
||||
b[i, 1] = pr.y
|
||||
b[i, 0] = pointRandomized.x
|
||||
b[i, 1] = pointRandomized.y
|
||||
}
|
||||
val At = A.transposed()
|
||||
val AtA = At * A
|
||||
@@ -64,11 +74,9 @@ fun main() {
|
||||
val x = AtAI * Atb
|
||||
|
||||
val segment = Segment2D(
|
||||
//ls.start,
|
||||
Vector2(x[0, 0], x[0, 1]),
|
||||
Vector2(x[1, 0], x[1, 1]),
|
||||
Vector2(x[2, 0], x[2, 1]),
|
||||
//ls.end
|
||||
Vector2(x[3, 0], x[3, 1])
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user