Skip to content

CeresArchitecturalDslSmoke.kt

src/jvmMain/kotlin/afield/examples/ceres/CeresArchitecturalDslSmoke.kt · 105 lines

package afield.examples.ceres

import afield.math.optimization.ceres.AxisSet
import afield.math.optimization.ceres.EqualDistance
import afield.math.optimization.ceres.PointId
import afield.math.optimization.ceres.FfmCeresBackend
import afield.math.optimization.ceres.PointRef
import afield.math.optimization.ceres.SolveOptions
import afield.math.optimization.ceres.Vec3
import afield.math.optimization.ceres.geometryModel
import kotlin.math.abs
import afield.math.linalg.Vector3f

fun main()

body — 59 lines, from line 14
fun main() {
    lateinit var liftedCorner: PointRef
    lateinit var vectorCorner: PointRef

    val model = geometryModel {
        val a = point("a", 0.0, 0.0, 0.0)
        val b = point("b", 1.0, 0.0, 0.0)
        val c = point("c", 0.0, 1.0, 0.0)
        val d = point("d", 1.0, 1.0, 0.4)
        val vp = point("vp", 3.0, 1.0, 0.0)
        val rawCorner = Vector3f(0.5f, 0.5f, 0.0f)
        val midpoint = point("midpoint", rawCorner)
        liftedCorner = d

        val floor = plane(a, b, c, "floor")
        val panel = panel(a, b, d, c, "adventurous panel")
        val leadingEdge = line(a, b, "leading edge")
        val recedingEdge = b lineTo d
        val reusedEdge = line(rawCorner, d, "vector backed edge")
        vectorCorner = reusedEdge.a

        constraints {
            check(rawCorner.c == vectorCorner) { "Vector3f.c did not reuse the point created by line(Vector3f, ...)" }
            lock(listOf(a, b, c, vp), AxisSet.XYZ)
            weakAll(weight = 1e-2)

            floor.normal(Vec3(0.0, 0.0, 1.0), weight = 10.0)
            panel.planar(weight = 80.0)
            panel.area(target = 1.0, weight = 5.0)
            d.inside(floor, minSignedDistance = 0.0, weight = 10.0)
            (a + b * 0.5) ceq midpoint

            leadingEdge.direction(Vec3(1.0, 0.0, 0.0), weight = 20.0)
            recedingEdge.vanishesAt(vp, weight = 4.0)
            (leadingEdge dot (a lineTo rawCorner)) ceq 1.0
        }
    }

    val session = model.openSession(
        backend = FfmCeresBackend(),
        baselinePrior = 1e-2,
    )
    try {
        check(session.solve(SolveOptions(maxIterations = 40, metrics = true, metricGroupCapacity = 128))) {
            "initial solve failed"
        }
        check(abs(session.get(liftedCorner).z) < 2e-2) {
            "panel did not settle toward the floor plane: ${session.get(liftedCorner)}"
        }

        session.drag(liftedCorner, Vec3(1.0, 1.0, 0.25), strength = 1e3)
        session.release(liftedCorner)

        println("ok lifted=${session.get(liftedCorner)} top=${session.report.top(6)}")
    } finally {
        session.close()
    }
    sharedCornerSameLength()
}

Two walls meeting at a corner, made the same length. Before the re-encoding this aborted the JVM inside Ceres ("Duplicate parameter blocks in a residual"), taking a house host down with it.

private fun sharedCornerSameLength() {
    lateinit var end1: PointRef
    lateinit var end2: PointRef
    val model = geometryModel {
        val corner = point("corner", 0.0, 0.0, 0.0)
        end1 = point("east", 4.0, 0.0, 0.0)
        end2 = point("north", 0.0, 2.5, 0.0)
        constraints {
            corner.lock(AxisSet.XYZ, 1e9)
            listOf(end1, end2).forEach { it.lock(AxisSet.Z, 1e8) }
            same(listOf(corner, end1), AxisSet.Y, 1e8)
            same(listOf(corner, end2), AxisSet.X, 1e8)
            line(corner, end1).sameLengthAs(line(corner, end2), 1e6)
        }
    }
    val session = model.openSession(backend = FfmCeresBackend())
    try {
        check(session.solve(SolveOptions(maxIterations = 60))) { "shared-corner solve failed" }
        val east = session.get(end1).x
        val north = session.get(end2).y
        check(abs(east - north) < 1e-4) { "shared-corner walls did not reach one length: $east vs $north" }
        println("ok shared corner same length: $east $north")
    } finally {
        session.close()
    }
    val refused = runCatching { EqualDistance(PointId(0), PointId(1), PointId(0), PointId(2)) }.exceptionOrNull()
    check(refused is IllegalArgumentException) { "EqualDistance with a repeated point was not refused: $refused" }
    println("ok EqualDistance refuses a repeated point")
}