Skip to content

Add generic remapping & interpolation via MappableRange protocol #61

Description

@pockerhead

Implement a reusable protocol MappableRange for handling normalized interpolation (lerp) and range remapping (value -> % -> value).

✅ Goals:
Abstract start, end, and length of any scalar range.

Provide readable methods:

normalizedPosition(for:) (aka inverse lerp)

interpolatedValue(at:) (aka lerp)

remap(_:from:) (range-to-range mapping)

📦 Includes:
Default implementation in protocol extension.

Support for:

Custom struct Distance

Native ClosedRange<T: FloatingPoint>

import Foundation
import CoreGraphics

// MARK: - Протокол

protocol MappableRange {
    associatedtype Scalar: BinaryFloatingPoint
    var start: Scalar { get }
    var end: Scalar { get }

    func contains(_ value: Scalar) -> Bool
    func length() -> Scalar
    func normalizedPosition(for value: Scalar) -> Scalar
    func interpolatedValue(at normalizedPosition: Scalar) -> Scalar
    func remap(_ value: Scalar, from source: Self) -> Scalar
}

// MARK: - Default Implementation

extension MappableRange {
    func contains(_ value: Scalar) -> Bool {
        value >= start && value <= end
    }

    func length() -> Scalar {
        end - start
    }

    func normalizedPosition(for value: Scalar) -> Scalar {
        (value - start) / length()
    }

    func interpolatedValue(at normalizedPosition: Scalar) -> Scalar {
        start + normalizedPosition * length()
    }

    func remap(_ value: Scalar, from source: Self) -> Scalar {
        let position = source.normalizedPosition(for: value)
        return interpolatedValue(at: position)
    }
}

// MARK: - Distance Struct

struct Distance<T: BinaryFloatingPoint>: MappableRange {
    var x1: T
    var x2: T

    var start: T { x1 }
    var end: T { x2 }

    init(_ x1: T, _ x2: T) {
        self.x1 = x1
        self.x2 = x2
    }
}

// MARK: - ClosedRange поддержка

extension ClosedRange: MappableRange where Bound: BinaryFloatingPoint {
    var start: Bound { lowerBound }
    var end: Bound { upperBound }
} 

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions