nicklockwood / Euclid

A Swift library for creating and manipulating 3D geometry
MIT License
644 stars 53 forks source link

Vector semantics: vertex.position and Plane(normal:pointOnPlane) (6+7/7) #70

Closed jkalias closed 3 years ago

jkalias commented 3 years ago

Overview of remaining refactoring steps from #37:

line.origin -> Position [done] lineSegment.start/end -> Position [done] pathPoint.position -> Position [done] transform.offset -> Distance [done] transform.scale -> Distance [done] vertex.position -> Position [this PR] Plane(normal: Direction, pointOnPlane: Vector) -> pointOnPlane should be Position [this PR]

codecov-commenter commented 3 years ago

Codecov Report

Merging #70 (30c25dd) into develop (20206fa) will increase coverage by 0.15%. The diff coverage is 82.00%.

Impacted file tree graph

@@             Coverage Diff             @@
##           develop      #70      +/-   ##
===========================================
+ Coverage    71.80%   71.96%   +0.15%     
===========================================
  Files           27       27              
  Lines         3536     3531       -5     
===========================================
+ Hits          2539     2541       +2     
+ Misses         997      990       -7     
Impacted Files Coverage Δ
Sources/CSG.swift 51.88% <0.00%> (ø)
Sources/Euclid+SceneKit.swift 9.09% <0.00%> (ø)
Sources/Transforms.swift 56.62% <80.00%> (ø)
Sources/Paths.swift 86.06% <83.33%> (+0.23%) :arrow_up:
Sources/Polygon.swift 91.40% <92.85%> (ø)
Sources/Bounds.swift 71.08% <100.00%> (ø)
Sources/Plane.swift 93.58% <100.00%> (ø)
Sources/Position.swift 93.18% <100.00%> (+7.46%) :arrow_up:
Sources/Shapes.swift 68.97% <100.00%> (ø)
Sources/Utilities.swift 89.90% <100.00%> (ø)
... and 5 more

Continue to review full report at Codecov.

Legend - Click here to learn more Δ = absolute <relative> (impact), ø = not affected, ? = missing data Powered by Codecov. Last update 20206fa...30c25dd. Read the comment docs.

jkalias commented 3 years ago

@nicklockwood I think the next and final step would be to eliminate all instances of Vector, agree? What do you propose we do for vertex.texcoor?

nicklockwood commented 3 years ago

@jkalias I think texcoord is fairly simple, as it's just a Position. More problematic is cases like size/scale which represent a magnitude and don't seem to fit well with any of the existing Direction/Position/Distance classifications.

jkalias commented 3 years ago

@nicklockwood how about something like this?

public struct Size {
    let x: Double
    let y: Double
    let z: Double
}

public extension Size {
    static func * (_ size: Size, _ factor: Double) -> Size {
        Size(size.x * factor, size.y * factor, size.z * factor)
    }

 static func / (_ size: Size, _ factor: Double) -> Size? {
        guard factor != 0 else {
           return nil
        }
        return Size(size.x / factor, size.y / factor, size.z / factor)
    }
}

public struct Scale {
    let x: Double
    let y: Double
    let z: Double
}

public extension Scale {
    static func * (_ scale: Scale, _ factor: Double) -> Scale {
        Scale(scale.x * factor, scale.y * factor, scale.z * factor)
    }

 static func / (_ scale: Scale, _ factor: Double) -> Scale? {
        guard factor != 0 else {
           return nil
        }
        return Scale(scale.x / factor, scale.y / factor, scale.z / factor)
    }
}
jkalias commented 3 years ago

@nicklockwood any ideas or objections to the previous proposal?

nicklockwood commented 3 years ago

@jkalias it seems a little bit like overkill to have separate size and scale structs as they're semantically quite similar. Can you think of any differences in how you'd implement them?

jkalias commented 3 years ago

@nicklockwood what about this?

protocol Scalable {
    var x: Double { get }
    var y: Double { get }
    var z: Double { get }
    init(x: Double, y: Double, z: Double)
}

extension Scalable {
    static func * (_ scalable: Scalable, _ factor: Double) -> Self {
        Self(x: scalable.x * factor, y: scalable.y * factor, z: scalable.z * factor)
    }

    static func * (_ factor: Double, _ scalable: Scalable) -> Self {
        scalable * factor
    }

    static func / (_ scalable: Scalable, _ factor: Double) -> Scalable? {
        guard factor != 0 else {
            return nil
        }
        return Self(x: scalable.x / factor, y: scalable.y / factor, z: scalable.z / factor)
    }
}

public struct Size: Scalable {
    let x: Double
    let y: Double
    let z: Double
}

public struct Scale: Scalable {
    let x: Double
    let y: Double
    let z: Double
}
jkalias commented 3 years ago

@nicklockwood Any feedback would be welcome 😄