 import Foundation
 
 extension String {
+    /**
+     Parse a string of space-separated key=value pairs into a Dictionary.
+     Unrecognized elements are ignored.
+     - Returns: Dictionary like `["AAA": "1", "BBB": "2"]` for an input of `"FOO AAA=1 BBB=2"`
+     */
     func kvToDict() -> [String: String]? {
         let vals = self
             .split(separator: " ")

}

extension Double {
    func format(_ precision: Int) -> String {
        return String(format: "%.\(precision)f", self)
    }

        return (horiz, vert)
    }

    /**
     Move to photo index position (0..<number of photos)
     - Parameter to: linear cell index aka photo number
     - Returns: `(horizMove, vertMove)` as relative movement in degrees to reach the next cell in the pano sequence, or `(0.0, 0.0)` if the next cell is outside the pano bounds.
     */
    func moveTo(to targetPosition: Int) -> (Double, Double) {
        return moveTo(row: targetPosition / cols, col: targetPosition % cols);
    }

    /**
     Move to specified grid coordinates
     - Parameter row: requested row position 0..<rows
     - Parameter col: request column position 0..<col
     - Returns: `(horizMove, vertMove)` as relative movement in degrees to reach the requested grid location, or `(0.0, 0.0)` if the location is outside the pano bounds.
     */
    func moveTo(row: Int, col: Int) -> (Double, Double) {
        let currentRow = position / cols
        let currentCol = position % cols
