Accès aux membres d'une struct par nom et par indice

2»

Réponses

  • CéroceCéroce Membre, Modérateur

    Si, comme Draken on ne veut pas tuer les poneys, on peut toujours utiliser un enum pour l'index :

    Je comprends ce que tu cherches à  faire, mais comment puis-je l'utiliser en principe ?
    Je ne peux plus écrire:


    let vec = Vector(x: 1, y: 2, z: 3)
    let component = vec[2] // Cannot convert value of type Int to type Vector.Index
  • Joanna CarterJoanna Carter Membre, Modérateur

    Une idée



    struct Vector
    {
    enum Index : Int
    {
    case x = 0
    case y
    case z

    static let allValues = [x, y, z]
    }

    var x: Float

    var y: Float

    var z: Float

    subscript(index: Index) -> Float
    {
    get
    {
    switch index
    {
    case .x : return self.x

    case .y : return self.y

    case .z : return self.z
    }
    }
    }
    }

    struct Ray
    {
    var origin = [Float]()

    var direction = [Float]()
    }

    struct BoundingBox
    {
    let minPoint: Vector

    let maxPoint: Vector

    func isHitBy(ray: Ray, distMin: Float, distMax: Float) -> Bool
    {
    var tmin = distMin

    var tmax = distMax

    for component in Vector.Index.allValues
    {
    let invD = Float(1.0) / ray.direction[component.rawValue]

    let t0 = (minPoint[component] - ray.origin[component.rawValue]) * invD

    let t1 = (maxPoint[component] - ray.origin[component.rawValue]) * invD

    tmin = max(tmin, min(t0, t1))

    tmax = min(tmax, max(t0, t1))

    if tmax <= tmin
    {
    return false
    }
    }

    return true
    }
    }
  • CéroceCéroce Membre, Modérateur
    Merci Joanna, je vois mieux.

    J'imagine que allValues renvoie une séquence est qu'on peut donc l'indicer si nécessaire. (J'imagine parce que j'ai énormément de mal à  trouver les informations dans la doc de Xcode).
  • Joanna CarterJoanna Carter Membre, Modérateur

    Ce ne devrait pas être nécessaire d'indicer allValues parce que chaque membre est de type Vector.Index, qui contient le rawValue de l'enum.


     


    Qu'est-ce que tu crois que tu manque ?


  • CéroceCéroce Membre, Modérateur
    février 2017 modifié #36
    Pour donner un (mauvais) exemple, si je voulais remplacer ça:
     
    for component in 1..<3 {
    (donc, seulement y et z)

    Ce qui me gêne dans la solution de l'enum, c'est le manque de flexibilité. Mon problème n'est pas de faire le code le plus robuste possible, mais le plus expressif possible.
  • Joanna CarterJoanna Carter Membre, Modérateur

    Ah! Je pige.


     


    Oui, on peut indicer allValues mais pour utiliser les Ints avec le code qui attend les Vector.Index, il faudrait utiliser Vector.Index(rawValue: component) pour convertir l'Int. Mais, là , on aurait le même problème que le rawValue pourrait dépasser les limites.


     


    Juste une idée mais, pour BoundingBox, as-tu pensé d'implémenter l'opérateur "Pattern Match" ( ~= ) pour déterminer si un vecteur se trouve là  dedans ou non ?




  • Pour donner un (mauvais) exemple, si je voulais remplacer ça:

     



    for component in 1..<3 {



     


    Cela me hérisse de voir cette syntaxe, avec une valeur finale-1. On dirais du C des années 80.


     


    Pourquoi est-ce que tu n'utilises pas la formulation moderne en Swift : 


    f



    for component in 0...2 {

  • Joanna CarterJoanna Carter Membre, Modérateur


     


    Cela me hérisse de voir cette syntaxe, avec une valeur finale-1. On dirais du C des années 80.


     


    Pourquoi est-ce que tu n'utilises pas la formulation moderne en Swift : 


    f



    for component in 0...2 {




     


    Car il veut utiliser :



    for component in 1...2

    ::)

  • DrakenDraken Membre
    février 2017 modifié #40

    Oui, il itére de 1 à  3-1 dans son (mauvais) exemple. Et de 0 à  3-1 dans son vrai code :



    struct BoundingBox {
    let minPoint: Vec3
    let maxPoint: Vec3

    func isHitBy(ray: Ray, distMin: Float, distMax: Float) -> Bool {
    var tmin = distMin
    var tmax = distMax

    for component in 0..<3 { // <= ICI, DE 0 à  (3-1)
    let invD = Float(1.0) / ray.direction[component]
    let t0 = (minPoint[component] - ray.origin[component]) * invD
    let t1 = (maxPoint[component] - ray.origin[component]) * invD
    tmin = max(tmin, min(t0, t1))
    tmax = min(tmax, max(t0, t1))

    if tmax <= tmin {
    return false
    }
    }

    return true
    }
    }

  • CéroceCéroce Membre, Modérateur
    ça se discute, mais je vois plus clairement qu'on énumère 3 composantes.
  • Oui, c'est une affaire de perception. Pour ma part, j'ai toujours détesté les boucles se terminant sur une valeur finale-1. 


  • CéroceCéroce Membre, Modérateur
    février 2017 modifié #43

    Juste une idée mais, pour BoundingBox, as-tu pensé d'implémenter l'opérateur "Pattern Match" ( ~= ) pour déterminer si un vecteur se trouve là  dedans ou non ?

    Non, et je découvre le ~=.
    Mais je t'avoue que je ne saisis pas ta question, n'ayant qu'un seul if dans la méthode isHitBy(). La méthode doit pouvoir renvoyer false le plus rapidement possible. Statistiquement, on s'attend à  avoir beaucoup plus de false que de true.
Connectez-vous ou Inscrivez-vous pour répondre.