l'opération Bitwise Inversion
ou invert(a)
Tous les bits à 0 passent à 1 et inversement. Pratique pour avoir l'inverse d'une matrice pour passer de coordonnées local à globale et ... inversement.
C'est un des opérateurs de python.
http://docs.python.org/library/operator.html
Dernière modification par valkaari ; 03/03/2012 à 03h31.
Mais alors, ~5 devrait donner 2, vu que 5 est 101 et 2 est 010, non ?
Or ~5 donne -4.
sur 8 bits 5 -> 00000101
L'inverse donne donc 11111010
Le bit de poids le plus fort (celui à gauche) détermine le signe (sur un entier signé). Du coup on sait qu'on a un chiffre négatif et ça change tout.
00000000 -> 0
11111111 -> -1
11111110 -> -2
11111101 -> -3
11111100 -> -4
11111011 -> -5
11111010 -> -6
si tu fais un print ~5 il te donne -6.
en fait tu prends les 0 pour avoir le nombre en base 10 et t'enlève 1
par contre 11111111 si on stocke une valeur non signé celà donne 255 et pas -1
Dernière modification par valkaari ; 03/03/2012 à 03h28.
hmm je vois ... faut quand même une petite révision en math Merci valkaari!
j'ai essayé avec des matrices,
Code:import c4d def main(): obj = doc.GetActiveObject() a = obj.GetMg() print a.off #Vector(200,200,200) b = ~a print b.off #Vector(-200,-200,-200) if __name__=='__main__': main()
Donc, si je ne dis pas de bêtises,
local coord * (M) = global coord.
global coord * ~(M) = local coord.
Ah d'accord, je pige mieux. Merci Val !
J'avoue que je fais toujours un test rapidos pour vérifier s'il faut multiplier par la matrice ou par son inverse. ( y a des trucs con comme ça qui n'entrent pas dans mon crâne de piaf)
Mais oui c'est bien ça.
Je précise que c'est bien une coordonné que l'on multiplie par une matrice.
VecteurA * MatriceB = VecteurC
Ne pas confondre avec le produit scalaire (dot product) qui sert à avoir l'angle entre deux vecteurs ou le produit vectoriel (cross product) qui sert à avoir le vecteur perpendiculaire.
(et je dois aussi vérifier à chaque fois qui fait quoi aussi pour ces trucs là, ça rentre pas, qu'est ce que vous voulez )
Mais je sais qu'il faut pas les confondre ^^
Miam miam… que du bon!
Justement en parlant de matrices, y a-t-il un lien entre la matrice de la vue c.a.d :
et la position d’un point par exemple ?Code:bd = doc.GetActiveBaseDraw() M = bd.GetMg()
Aucune, les positions dans c4d sont définie en fonction de l'origine du monde ou du parent (global ou local).
Elles sont stocké sous forme de matrice composé de 4 vecteurs. Un pour la position et 3 pour l'orientation/échelle.
Chaque vue possède une camera et une méthode de projection (perspective/orthogonal etc) que l'on ajoute un objet camera ou non.
Comme chaque objet dans un espace 3D, la camera possède des coordonées. C'est ce que tu récupères avec le GetMg d'un baseDraw.
Je n'ai jamais utilisé les fonctions pour jouer avec les informations projeté sur la vue, mais la class BaseDraw est hérité de BaseView qui elle possède des fonctions pour ce genre de choses à priori.
BaseView.WS(p)
World to screen conversion. Converts p from world space to screen space (pixels relative to the view), and returns the conversion. The orthogonal distance to the world point is stored in world units in the Z axis of the result.
Mais encore une fois, je n'ai jamais utilisé ces fonctions.
Val a tout juste, il y a un bon exemple dans la doc dans le Py-LiquidPainter qui passe de la vue à la scène avec bd.SW(point).
ça me rassure c'est la même chose pour moi ...(et je dois aussi vérifier à chaque fois qui fait quoi aussi pour ces trucs là, ça rentre pas, qu'est ce que vous voulez )
Dernière modification par oli_d ; 05/03/2012 à 20h16.
Au sujet de la classe BaseSelect et sa fonction SelectAll(min, max), ses deux arguments semblent inversés.
D'après la doc, min est le premier élément à sélectionner, et max le dernier.
Or pour que la cela fonctionne, il faut intervertir min et max :
Pourrait-on me confirmer cela ?Code PHP:
import c4d
def main():
if not op: return
bs = op.GetPolygonS()
nbp = op.GetPolygonCount()
bs.SelectAll(nbp-1, 2) # Sélectionne tous les polygones à partir du second.
#bs.SelectAll(2, nbp-1) # Ne sélectionne rien.
c4d.EventAdd()
if __name__=='__main__':
main()
yep! pareil chez moi
malheureusement la doc de python et incomplète et contient quelques erreurs
J'ai un petit soucis concernant un calcul d'angle à partir de vecteurs, voici le problème :
J'ai un vecteur v absolu (donc défini sur les axes x, y, z du monte).
J'ai une matrice Mr = ((0;0;0), Xr, Yr, Zr).
Je cherche à calculer l'angle A entre Yr et v', v' étant une sorte de projection du vecteur v sur le plan XrZr.
J'ai passé la matinée dessus, en jouant avec MulV, GetAngle et compagnie... mais sans succès.
J'aimerais éviter les sinus et cosinus car le vecteur v peut-être orienté dans n'importe quel sens.
Je pense qu'il faudrait trouver les nouvelles coordonnées du vecteur v par rapport à Mr, mais je vois pas comment.
C'est sûrement simple, mais j'ai la tête comme dans une machine à laver.
Dernière modification par César Vonc ; 30/06/2012 à 19h53.
pas spécialement tout compris (quand on est pas dedans c'est parfois un peu flou).
Par contre pour avoir un angle entre deux vecteurs, il suffit de faire un dot product. v1.dot(v2)
Par contre, je ne sais plus s'il donne l'angle en radian directement ou s'il donne le cos de l'angle. Auquel cas il faut faire un inverse cos.
edit :
évidement si le résultat est 0 c'est donc que les deux vecteurs sont parallèle (attention aux approximation de python ou de ciname4D 0.0001 != 0))
Il me semble aussi que tu peux déterminer si l'angle est aigu ou obtu si le résultat est négatif ou positif.
Ah ben, tu m'as donné une idée, pas avec le produit scalaire mais avec le produit vectoriel !
Si je calcule le produit vectoriel entre v et Zr, je pourrai calculer son angle par rapport à Yr, qui vaudrait A + 90°
Donc :
A = c4d.utils.VectorAngle(v.Cross(Mr.v3), Mr.v2) - math.pi / 2
Et ça marche ! ^^
Et le dot product entre v et Yr te donne pas le cos de l'angle ?
Si, mais l'angle entre Yr et v est différent de celui entre Yr et v'.
Heu ...
Je n'ai peut-être pas tout compris mais c'est très curieux que ça marche.
Petit rappel d'ordre général.
Le produit scalaire ne donne pas un angle. Pour faire simple, c'est le "produit" de deux vecteurs qui donne un scalaire. Bref, un nombre.
Mais ce nombre (scalaire) dépend effectivement de l'angle entre les vecteurs.
Si A est la norme du premier vecteur (sa longueur) et B la norme du second. x l'angle entre les deux:
Le produit scalaire vaudra: A.B cos x.
Si les vecteurs sont unitaires (A=1 et B=1) on a bien effectivement la valeur du cosinus de l'angle. (Compris entre -1 et 1)
Le cosinus n'est ni en radian ni en degré. C'est uniquement avec le cos-1 qu'on devra se soucier de l'unité de l'angle.
Mais le plus intéressant c'est la signification "physique" possible de ce produit scalaire. C'est comme si on multipliait la norme du premier vecteur par la projection du deuxième vecteur sur ce même premier vecteur. Ou inversement puisque le produit est symétrique.
vecteur A scalaire vecteur B = A * projection de B sur A = B * projection de A sur B.
Du coup on comprend facilement et intuitivement que si le produit scalaire est nul c'est que la projection d'un vecteur sur l'autre est nul, et qu'ils sont à 90°.
Si l'angle est aigu il est positif, s'il est obtus négatif.
Pour le produit vectoriel. C'est le produit de deux vecteur qui donne un troisième vecteur perpendiculaire aux deux autres et dont la norme est équivalente à la surface du parallélogramme formé par les deux premiers vecteurs.
La norme du produit vectoriel vaut donc: A.B sin x avec les notations précédentes.
Et de la même manière qu'un produit scalaire permet de remonter au cosinus, un produit vectoriel permettra d'obtenir le sinus. Ainsi que la direction perpendiculaire aux deux vecteurs de départ.
Là encore, de manière intuitive on voit que le produit vectoriel est maximal si les deux vecteurs sont à 90° l'un de l'autre. (Aire d'un rectangle) et vaut 0 si ils sont colinéaires.
Là où je suis très sceptique c'est quand tu fais le produit vectoriel de v et Zr. Le résultat n'a aucune raison de se trouver dans le plan XrYr.
Ce ne sera le cas que si v est lui-même dans le plan XrYr.
Du coup je ne comprends pas bien ton calcul de A+90.
Tu peux facilement avoir les projections de v sur Yr et Xr avec le produit scalaire.
(v scalaire Yr)/(norme Yr) par exemple donne celle sur Yr. Si Yr est unitaire c'est encore plus simple.
Puis à partir des projections l'angle A se déduit facilement.
(projection sur Xr/projection sur Yr) = tan (A)
Il y a sans doute plus simple aussi. Peut-être ton A+90 il faut que je regarde plus en détail, mais j'ai un gros doute.
SMC fan.
Merci pour ces précisions, Jean-Laurent.
En fait j'en ai justement déduis que si, dans tous les cas. Si on imagine une plaque en équilibre sur l'axe Zr, sa normale sera toujours dans le plan XrYr, donc si cette plaque s'appuie également sur le vecteur v, sa normale sera le produit vectoriel de v et Zr.Là où je suis très sceptique c'est quand tu fais le produit vectoriel de v et Zr. Le résultat n'a aucune raison de se trouver dans le plan XrYr.
Et vu qu'elle est perpendiculaire, en calculant son angle avec Yr je tombe sur v' en virant 90°.
Tu as parfaitement raison.
Tous les vecteurs perpendiculaires à Zr (ce qui est le cas du produit vectoriel) sont contenus dans Xr, Yr.
C'est logique maintenant que tu le dis.
C'est moi qui suis à côté de la plaque.
SMC fan.
J'ai un petit soucis pour créer un tableau à trois dimensions.
Avec la première méthode, je fais :
tab1 = [[[False]*(zmax)]*(ymax)]*(xmax)
Avec la seconde méthode, je fais trois boucles initialisant la case à chaque fois.
Jusqu' là tout va bien, le résultat est le même, mes deux tableaux sont identiques lorsque je les compare :Code PHP:
import c4d
def main():
xmax = 2
zmax = 2
ymax = 2
tab1 = [[[False]*(zmax)]*(ymax)]*(xmax)
tab2 = []
for x in xrange(xmax) :
tab2.append([])
for y in xrange(ymax) :
tab2[x].append([])
for z in xrange(zmax) :
tab2[x][y].append(False)
print tab1 == tab2 # Vrai
tab2[1][1][1] = True
tab1[1][1][1] = True
print tab1 == tab2 # Faux
print tab1
print tab2
if __name__=='__main__':
main()
tab1 = [[[False, False], [False, False]], [[False, False], [False, False]]]
tab2 = [[[False, False], [False, False]], [[False, False], [False, False]]]
Mais dès que je veux modifier une valeur, plus rien ne va !
tab1[1][1][1] = True
tab2[1][1][1] = True
tab1 = [[[False, True], [False, True]], [[False, True], [False, True]]]
tab2 = [[[False, False], [False, False]], [[False, False], [False, True]]]
tab1 ne me modifie pas la bonne case. Comment cela se fait ?
à mon avis c'est une histoire de label quand tu multiplies le tableau
problème identique que quand tu fais lista = listb cela crée une sorte de pointeur (en vrai un label, j'ai jamais vraiment essayé de comprendre la différence)
http://forum.hardware.fr/hfr/Programmation/Python/copie-liste-sujet_119386_1.htm
Salut,
oli_d a raison, la multiplication de la liste créée une référence, pour obtenir une copie il faudra soit faire appel au constructeur "list()" soit avec "[:]"
Quelques pistes :
Code PHP:
tab1 = [[x[:] for x in [[False]*xmax]*ymax] for x in xrange(zmax)]
------
tab1 = [[[False for i in xrange(xmax)] for j in xrange(ymax)] for k in xrange(zmax)]
------
tab1 = {}
tab1[(1, 2, 3)] = True
print tab1[(1, 2, 3)]
try:
print tab1[(1, 1, 1)]
except KeyError:
pass
Dernière modification par xs_yann ; 29/09/2012 à 13h42.