Un petit framework

psychoh13psychoh13 Mothership DeveloperMembre
Bonjour à  tous, je vous poste aujourd'hui un petit projet de développement que je fais pour m'occuper. Il s'agit d'un ensemble de classes ou de méthodes de bases utilisables à  peu prés partout, des ajouts aux frameworks de base d'Apple.

Pour l'instant il n'y a pas grand chose, mais si vous avez des suggestions, ou des commentaires à  apporter, je serai ravi de les lire et de les prendre en compte.

Pour l'instant j'ignore s'il marche autre part que sur mon ordi, une chose est sûre c'est qu'il n'est que pour Leopard.

Ce framework comprend :
  • 1 méthode ajoutée à  NSBezierPath pour créer un CGPath à  partir du receveur, c'est une méthode simple donnée par Apple, mais comme j'en avais moi-même besoin dans mon framework, j'en ai fait une méthode publique.
  • 2 méthodes ajoutées à  NSAffineTransform et qui permettent de faire une rotation centrée sur un point donné.
  • La classe PSYVector permettant de gérer des vecteurs géométriques sur deux dimensions... Là  aussi, j'en avais besoin dans mon framework.
  • Et pour finir la classe principale : PSYShading, qui est en fait une version "améliorée" (ça dépend du point de vue :D) de la classe NSGradient d'Apple, pour les parties communes, les deux classes se comportent exactement de la même manière (quoiqu'on pourrait voir quelques différences lors de l'affichage avec beaucoup de couleurs...), ce que j'ai ajouté c'est en fait la possibilité de modifier le dégradé après sa création, il permet donc d'ajouter des couleurs, d'en enlever, d'en supprimer, ou de modifier leur position.


Bon, c'est vraiment pas grand chose pour l'instant, c'est pour ça que si vous avez des suggestion d'ajouts, je serai content de tenter de les développer. :D


Réponses

  • Philippe49Philippe49 Membre
    14:50 modifié #2
    Pour les méthodes sur NSAffineTransform, tu choisis des NSPoint .

    - (void)rotateByDegrees:(CGFloat)angle withCenterPoint:(NSPoint)center;
    - (void)rotateByRadians:(CGFloat)angle withCenterPoint:(NSPoint)center;

    Les méthodes de translations (translateXBy: yBy:) se faisant avec des CGFloat, ne serait-il pas plus logique de prendre  CGPoint ?
    ou alors de faire deux signatures différentes ?


  • AliGatorAliGator Membre, Modérateur
    14:50 modifié #3
    Et histoire de pinailler parce que sinon c'est pas drôle  :)beta: moi j'aurais nommé le paramètre "aroundCenterPoint:" et non "withCenterPoint:"  ;)
  • psychoh13psychoh13 Mothership Developer Membre
    14:50 modifié #4
    Pour le pinaillage, j'ai mis du temps à  trouver le "bon" nom pour ces deux méthodes. :)

    spinAroundPoint:byDegrees:
    rotateByDegrees:aroundCenter:
    etc.

    J'ai finalement choisis "withCenterPoint:" parce que je trouvais ça plus Objective-C-like : on fait une rotation de x degrés avec pour centre le point p. Personnellement je trouve ça plus Objective-C. :D


    Sinon, Philippe je ne suis pas sûr de comprendre la question, mais je vais tenter d'y répondre. À mon avis, si la translation se fait avec deux CGFloat séparés (x et y), c'est au nom de la cohérence (si vous n'êtes pas déjà  habitué à  me voir écrire ce mot, vous devriez commencer à  vous y faire parce que je le répète tout le temps :D).

    Faire une rotation autour d'un point est tout à  fait logique et normal, n'est-ce pas ? Tu poses ton doigt sur le dit-point sur une feuille et tu fais tourner la feuille autour, ton doit a des coordonnées c'est donc logique qu'on le représente par un point.

    Mais là , dans le cas de la translation, on déplace la figure d'une certaine valeur sur X et sur Y, on ne dit pas qu'on va amener la figure à  un point précis, mais on va la déplacer d'une certaine distance sur X et sur Y, bien sûr on pourrait dire qu'un point représente un vecteur, et comme ça déplacer une figure selon un vecteur c'est beaucoup plus logique et surtout mathématique, et dans ce cas on pourrait créer un type comme ça :
    typedef NSPoint NSVector;
    


    Là  ce serait logique, mais bon quel intérêt de créer un type complet pour cette seule alors qu'on peut simplement dire qu'on va déplacer la figure sur X et sur Y. À mona vis, c'est donc le choix de la cohérence et de la simplicité que Apple a fait.
  • Philippe49Philippe49 Membre
    14:50 modifié #5
    Pour moi, je vois cela ainsi :

    On peut décomposer la rotation autour d'un point en une translation suivie d'un rotation.
    Comme la translation se fait avec des CGFloat,il me semble plus normal que ta méthode utilise des CGFloat, regroupés dans un CGPoint.
    Certes, ton nouveau centre n'est pas exactement le vecteur de translation, mais on peut établir des formules de passage entre ces coordonnées.
    vous avez dit cohérence ?  ;)
  • Philippe49Philippe49 Membre
    14:50 modifié #6
    A ce sujet entre NSPoint et CGPoint, j'ai trouvé joli la fonction

    NSPointToCGPoint
    Returns a CGPoint typecast from an NSPoint.

    CGPoint NSPointToCGPoint(NSPoint nspoint) {
      return (*(CGPoint *)&(nspoint));
    }

    Un bel item de QCM sur le langage C, non ?
    Cela va faire des heureux ...  ;D

  • Philippe49Philippe49 Membre
    14:50 modifié #7
    dans 1198890663:

    si vous avez des suggestion d'ajouts, je serai content de tenter de les développer. :D


    Dans les NSBezierPath, il y a le tracé des ellipses, mais il manque cruellement le tracé des paraboles et des hyperboles.
  • psychoh13psychoh13 Mothership Developer Membre
    décembre 2007 modifié #8
    Je parle de la cohérence à  l'extérieur de la méthode, en interne on s'en fout un peu comment ça marche c'est le principe de la programmation objet. :D

    Sinon, je dirais que le nouveau n'est pas du tout le vecteur de translation je le considère réellement comme le point central de la rotation. Le principe c'est que je fais d'abord la rotation du point autour du NSZeroPoint normal et je calcule la translation en faisant la soustraction des coordonnées des deux points :

    - (void)rotateByRadians:(CGFloat)angle withCenterPoint:(NSPoint)center<br />{<br />	NSAffineTransformStruct *transformStruct = (NSAffineTransformStruct*)((id)self + 1);<br />	NSAffineTransformStruct append, new, old;<br />	old = *transformStruct;<br /><br />	// Calcul de la rotation<br />	append.m11 = cos(angle);<br />	append.m12 = sin(angle);<br />	append.m21 = -append.m12;<br />	append.m22 = append.m11;<br /><br />	// Rotation du centre puis calcul de la translation de l&#39;ancien centre au nouveau<br />	append.tX = -((center.x * append.m11 + center.y * append.m21) - center.x);<br />	append.tY = -((center.x * append.m12 + center.y * append.m22) - center.y);<br /><br />	// Application proprement dite de la transformation<br />	new.m11 = old.m11 * append.m11 + old.m12 * append.m21;<br />	new.m12 = old.m11 * append.m12 + old.m12 * append.m22;<br />	new.m21 = old.m21 * append.m11 + old.m22 * append.m21;<br />	new.m22 = old.m21 * append.m12 + old.m22 * append.m22;<br />	new.tX = old.tX * append.m11 + old.tY * append.m21 + append.tX;<br />	new.tY = old.tX * append.m12 + old.tY * append.m22 + append.tY;<br />	<br />	*transformStruct = new;<br />}
    


    Donc pour commencer, le point central ne représente pas le vecteur de translation, et ensuite, une rotation, en mathématique, se fait autour d'un point, et non pas d'un déplacement, alors qu'un déplacement se faire par une certaine valeur sur X et une autre sur Y, et non pas par un point.

    dans 1198930341:

    A ce sujet entre NSPoint et CGPoint, j'ai trouvé joli la fonction

    NSPointToCGPoint
    Returns a CGPoint typecast from an NSPoint.

    CGPoint NSPointToCGPoint(NSPoint nspoint) {
       return (*(CGPoint *)&(nspoint));
    }

    Un bel item de QCM sur le langage C, non ?
    Cela va faire des heureux ...  ;D




    Oui on peut utiliser cette technique, mais sous Leopard tu peux compiler de façon à  ce que les NSPoint, NSSize et NSRect soit considérer comme des CGPoint, CGSize et CGRect. ;D

    Soit tu compiles en 64 bits, soit tu compiles avec le flag : -DNS_BUILD_32_LIKE_64 :D

    dans 1198930758:

    dans 1198890663:

    si vous avez des suggestion d'ajouts, je serai content de tenter de les développer. :D


    Dans les NSBezierPath, il y a le tracé des ellipses, mais il manque cruellement le tracé des paraboles et des hyperboles.



    Tu veux dire le tracer de fonctions mathématiques ?
  • Philippe49Philippe49 Membre
    14:50 modifié #9
    dans 1198930817:


    Donc pour commencer, le point central ne représente pas le vecteur de translation, et ensuite, une rotation, en mathématique, se fait autour d'un point


    Mais si, à  un calcul près c'est la même chose.
    translation(vecteur u) composée avec rotation(centre O) = rotation de centre (O')
    avec O' calculé à  partir du vecteur u, de l'ancien centre O et de l'angle de la rotation.

    Ok, le calcul est un peu plus compliqué qu'une simple translation, mais il faut que celui qui calcule par composition la nouvelle rotation trouve le même résultat que celui qui utilise ta méthode.


    dans 1198930817:

    Dans les NSBezierPath, il y a le tracé des ellipses, mais il manque cruellement le tracé des paraboles et des hyperboles.

    Tu veux dire le tracer de fonctions mathématiques ?


    Non non seulement les hyperboles et les paraboles qui sont de la même nature que les ellipses.
    (prends un cône et coupe-le selon différents plans, tu trouves  des ellipses, des hyperboles, ou des paraboles).
    Il existe des courbes de Bezier rationnelles qui font ces tracés particuliers. D'ailleurs l'appli geodes  (de Fouf il me semble) propose ces tracés.
  • psychoh13psychoh13 Mothership Developer Membre
    14:50 modifié #10
    J'ai regardé un ce qu'il avait comme code puisque c'est OpenSource... Mais c'est super violent... Lui n'utilise pas du tout les NSBezierPath, ses courbes sont en fait des centaines de lignes droites très courtes les unes à  la suite des autres, c'est, je pense, beaucoup plus difficile de transformer une courbe comme ça en courbe de Bézier cubique...  :-\\
  • Philippe49Philippe49 Membre
    14:50 modifié #11
    Ah dommage. Il faudrait faire une recherche poussée, je ne sais pas si cela existe déjà  développé. 

    courbes Bezier rationnelles

    Laisse tomber.
  • AliGatorAliGator Membre, Modérateur
    14:50 modifié #12
    Dommage, il aurait été plus joli de faire des splines, au moins la courbe serait continue y compris au points de raccordement (même tangeante) alors qu'en faisant des lignes par morceaux ça "casse" la courbe en une ligne brisée moins "fluide"... Mais bon c'est au nom de la rapidité de calcul j'imagine
  • fouffouf Membre
    14:50 modifié #13
    Tadammm....
    Je vois qu'on parle de moi :o

    En effet, comme le dis Philippe, Geodes sait tracer des coniques à  partir de cinq points (en faisant un petit pivot de Gauss et après en calculant un certain nombre de points), mais il s'agit bien d'une série de points qui sont ensuite reliés entre eux.

    Il se trouve (le hasard fait bien les choses) qu'un développeur français m'a envoyé du code pour transformé une suite de points en courbe de bezier (après, je ne sais pas si il s'agit de courbes cubiques ou quadratiques - connais pas la différence ::) ).
    Donc, je lui demande si ca ne le gêne pas de vous donner le code et je le poste après.
  • Philippe49Philippe49 Membre
    14:50 modifié #14
    dans 1198934900:

    Non non seulement les hyperboles et les paraboles qui sont de la même nature que les ellipses.
    prends un cône et coupe-le selon différents plans, tu trouves  des ellipses, des hyperboles, ou des paraboles.


    A la main, je chercherais à  creuser cette idée : on passe d'une ellipse à  une parabole ou hyperbole par une rotation dans l'espace du plan de coupe d'un cône de révolution.
    En très gros :
    Prendre la représentation de Bezier d'une ellipse, et reporter sur les points de contrôle la rotation en 3D.
  • psychoh13psychoh13 Mothership Developer Membre
    14:50 modifié #15
    dans 1198942635:

    Tadammm....
    Je vois qu'on parle de moi :o

    En effet, comme le dis Philippe, Geodes sait tracer des coniques à  partir de cinq points (en faisant un petit pivot de Gauss et après en calculant un certain nombre de points), mais il s'agit bien d'une série de points qui sont ensuite reliés entre eux.

    Il se trouve (le hasard fait bien les choses) qu'un développeur français m'a envoyé du code pour transformé une suite de points en courbe de bezier (après, je ne sais pas si il s'agit de courbes cubiques ou quadratiques - connais pas la différence ::) ).
    Donc, je lui demande si ca ne le gêne pas de vous donner le code et je le poste après.


    Une courbe de Bézier quadratique, dite aussi de "degré 2" est une courbe définie par 3 points, c'est-à -dire 1 point de départ, un point d'arrivé et 1 point de contrôle, une courbe de bézier cubique est une courbe de degré 3, c'est-à -dire avec 1 point d'arrivé, 1 point de départ et 2 points de contrôle, il existe aussi les "courbes" de degré 1 (1 point d'arrivé, un point de départ) qui sont simplement des lignes droites.

    On les appelle quadratique, ou cubique parce que la fonction qui permet de les définir sont des polynômes de degré 2 (c'est-à -dire avec un x au carré) ou de degré 3 (avec x au cube).

    Les NSBezierPath ne connaissent que les courbes cubiques ou les degré 1, tandis que les CGPath connaissent aussi les quadratiques.
  • psychoh13psychoh13 Mothership Developer Membre
    14:50 modifié #16
    Voilà  une petite application pour montrer la puissance des courbes de bézier.
    Elle vous présentera sous forme d'animation la construction d'une courbe de bézier quadratique et d'une courbe de bézier cubique.

    Pour Leopard uniquement désolé pour les autres.
  • Philippe49Philippe49 Membre
    14:50 modifié #17
    dans 1198942635:

    Tadammm....
    Je vois qu'on parle de moi :o

    En effet, comme le dis Philippe, Geodes sait tracer des coniques à  partir de cinq points (en faisant un petit pivot de Gauss et après en calculant un certain nombre de points), mais il s'agit bien d'une série de points qui sont ensuite reliés entre eux.


    Le pivot de gauss est inutile. On peut à  partir de 5 points trouver explicitement l'équation cartésienne de la conique sans résoudre de système.

    Equation de la conique (cas dégénérés compris) passant par cinq points A,B,C,D,E , ABCD quadrilatère.
    a.|MBA|.|MDC|=b.|MBC|.|MDA|
    avec a=|EBC|.|EDA| , b=|EBA|.|EDC|

    |ABC| est le déterminant (3,3) de la matrice (xA,yA,1)(xB,yB,1)(xC,yC,1)
Connectez-vous ou Inscrivez-vous pour répondre.