Obtenir les différents objets finaux par ExecuteMacro

Lieu d'échange sur les pratiques et les réalisations de scripts
User avatar
Dibs
Posts: 112
Joined: Tue Apr 24, 2012 2:15 am
Location: Pau

Obtenir les différents objets finaux par ExecuteMacro

Post by Dibs » Fri Dec 21, 2012 7:50 pm

Bonjour,

Si on crée une macro qui renvoie plusieurs objets finaux, comment obtenir ces différents objets via ExecuteMacro ?
En effet, il semblerait que ExecuteMacro renvoie le dernier objet final créé, ce qui limite considérablement son efficacité.
Selon moi, ExecuteMacro devrait logiquement s'appliquer ainsi :
ExecuteMacro("macro", "initiaux")[0],
ExecuteMacro("macro", "initiaux")[1],...

Y a-t-il une syntaxe que je connais pas ?

monique31
Posts: 373
Joined: Sat Nov 03, 2007 3:33 pm
Location: Toulouse

Post by monique31 » Sun Dec 23, 2012 3:34 pm

Je viens de tester, en créant une macro toute bête "orthocentre" : celle qui à partir de 3 points donne les 3 hauteurs du triangle formé ainsi que l'orthocentre. Un CarScript avec :
ExecuteMacro("orthocentre","E,F,G");
me donne bien les 4 objets finaux.
On peut connaître cette macro qui semble poser problème ?

Hesperion
Posts: 260
Joined: Sun Nov 11, 2007 2:14 pm
Location: Blois

Post by Hesperion » Tue Dec 25, 2012 8:22 pm

Bonjour,

Alors effectivement, de la manière dont a été écrite la fonction ExecuteMacro, elle ne retourne que le nom du dernier objet créé.

Je suppose que tu voudrais quelque chose qui fonctionnerait comme dans la capture suivante.
Ça a donc l'air d'être faisable, tests en cours...
Attachments
macro_finaux.png
(47.21 KiB) Downloaded 1293 times

User avatar
Dibs
Posts: 112
Joined: Tue Apr 24, 2012 2:15 am
Location: Pau

Post by Dibs » Wed Dec 26, 2012 2:56 pm

Oui, c'est exactement ce que je voulais dire. Merci.

Et je vais donner un problème concret pour fixer les idées (voir fichiers joints) :

Imaginons que l'on veuille construire simplement (pour des élèves de collège) un arbre de Pythagore...
Comment faire ?

Niveau 1 : on crée une macro sur un bipoint. Cette macro (nommée totale dans le fichier de macros joint) crée le triangle (polygone), les deux carrés (polygones) et les deux nouveaux bipoints.
On applique cette macro à la main.

Niveau 2 : on applique la macro récursivement avec ExecuteMacro.
1er problème : ce n'est pas possible si on ne peut pas obtenir le nom des objets finaux...

On crée donc 4 nouvelles macro, qui renvoient chacune le nom d'un point.
La première (ptggEtPoly) a un statut particulier, c'est elle qui est chargée en passant de créer les polygones.
Puis on applique le script :

a=Point(-2,-2);
b=Point(2,-2);
function arbre(u,v,n) {
if (n<2) {
arbre(ExecuteMacro("DibsArbre/ptggEtPoly",u+","+v),ExecuteMacro("DibsArbre/ptgd",u+","+v),n+1);
arbre(ExecuteMacro("DibsArbre/ptdg",u+","+v),ExecuteMacro("DibsArbre/ptdd",u+","+v),n+1);
}
}
arbre(a,b,0);

2e problème : ça ne marche pas. Le script ne crée qu'une partie de l'arbre et certains points ne sont pas construits. Bizarre...
On crée donc la macro ptgg simple (sans création au passage des polygones, un seul objet final) et on substitue ptggEtPoly par ptgg.
Cette fois, ça marche : tous les points sont construits (!)
Il reste alors à créer une macro (polygones) pour créer les trois polygones. Ce qui donne :

a=Point(-2,-2);
b=Point(2,-2);

function arbre(u,v,n) {
if (n<5) {
ExecuteMacro("DibsArbre/polygones",u+","+v);
arbre(ExecuteMacro("DibsArbre/ptgg",u+","+v),ExecuteMacro("DibsArbre/ptgd",u+","+v),n+1);
arbre(ExecuteMacro("DibsArbre/ptdg",u+","+v),ExecuteMacro("DibsArbre/ptdd",u+","+v),n+1);
}
}

arbre(a,b,0);

Et ça marche. Mais d'un point de vue pédagogique, c'est pas génial.
Bref.
Je suis perplexe concernant le 2e problème
Je pense qu'ExecuteMacro devrait donner accès à tous les objets finaux.
Si on veut garder une certaine « symétrie », la solution proposée par Hesperion semble logique. Mais je serais plutôt partisan de surcharger la fonction ExecuteMacro par un 3e paramètre correspondant à l'indice de l'objet final.
Voire même par un 4e paramètre(!) qui déterminerait si les objets finaux doivent être construits en passant ou pas :
0 pour objets finaux pas construits
1 pour objets finaux construits jusqu'à l'indice du 3e paramètre ( ! Hum hum...)
2 pour tous les objets finaux construits

Ce qui donnerait « idéalement » (guillemets importants) le script suivant :

a=Point(-2,-2);
b=Point(2,-2);
function arbre(u,v,n) {
if (n<2) {
arbre(ExecuteMacro("DibsArbre/totale",u+","+v,3,1),ExecuteMacro("DibsArbre/totale",u+","+v,4,0),n+1);
arbre(ExecuteMacro("DibsArbre/totale",u+","+v,5,0),ExecuteMacro("DibsArbre/totale",u+","+v,6,0),n+1);
}
}
arbre(a,b,0);

Euh... oui, je suis obligé de reconnaître... que c'est abominable !! (-> "Je sors !")

Merci pour votre patience. Je joins les macros et le classeur.
Attachments
arbre_Pythagore.zirs
(5.44 KiB) Downloaded 83 times
macro-Dibs-arbre.mcr
(15.25 KiB) Downloaded 96 times

Hesperion
Posts: 260
Joined: Sun Nov 11, 2007 2:14 pm
Location: Blois

Post by Hesperion » Thu Dec 27, 2012 12:04 am

J'ai pas exactement lu ton post en entier (je le ferai demain), mais si ton problème est de récupérer les noms des objets finaux, il est peut-être plus simple de les passer en paramètres, avec des noms choisis.

La commande suivante permet (déjà) de donner le nom que l'on souhaite aux 4+3=7 objets finaux de ta macro "totale".

Code: Select all

ExecuteMacro("a,b,c,d,e,f,g","DibsArbre/totale","A,B");
Dans ce que je proposais, on avait aussi les noms des objets intermédiaires, en général non utiles...
C'est peut-être plus simple ainsi, non ?

User avatar
Dibs
Posts: 112
Joined: Tue Apr 24, 2012 2:15 am
Location: Pau

Post by Dibs » Thu Dec 27, 2012 12:06 pm

Nan nan. Je ne souhaite pas nommer les objets mais récupérer leur nom (= l'objet lui-même). Je suis plus en phase avec ta première réponse.
Les « objets intermédiaires », kesako ?
Selon moi (et c'est tout le problème), il y a les initiaux et les finaux. ExecuteMacro a la syntaxe d'un CaRScript ordinaire, ce qui est pratique. Mais par nature, ce n'est pas un CaRScript ordinaire, c'est une fonction qui renvoie plusieurs objets. Sa syntaxe doit donc nécessairement être différente.

Hesperion
Posts: 260
Joined: Sun Nov 11, 2007 2:14 pm
Location: Blois

Post by Hesperion » Thu Dec 27, 2012 1:36 pm

Dans la capture qui suit :
* les initiaux sont les points A et B ;
* les finaux sont les objets a, b, c, d, e, f et g (que j'ai choisi de nommer pour bien voir, mais on peut ne pas le faire)

Les autres objets listés (aussi construis par la macro) sont des intermédiaires.
Le problème dans cette capture est que la macro renvoie le nom de tous les objets construits, ce qui n'est pas hyper élégant à mon gout.
Attachments
macro_totale.png
(46.52 KiB) Downloaded 1274 times

User avatar
Dibs
Posts: 112
Joined: Tue Apr 24, 2012 2:15 am
Location: Pau

Post by Dibs » Thu Dec 27, 2012 2:58 pm

En voyant ta capture d'écran, j'ai bondi sur ma chaise : ça marche, ce script ? !!!
si r contient le nom du dernier objet créé, comment peut-on le « spliter » ?!
J'ai testé. Dieu merci, ça ne marche pas (= ça se comporte normalement !).

OK. Si j'ai bien compris, tu testes en java des variantes à ExecuteMacro. D'où cette mystérieuse fenêtre java (à ne pas confondre avec la pop up javascript !).

Autre remarque : je trouve que ce serait bien si on pouvait voir les finaux et leur ordre dans les propriétés de la macro (l'ordre des finaux dans ma macro totale ne semble pas cohérent avec ce que j'ai écrit, dsl, et je ne peux pas vérifier...).

Bref. C'est la semoule...
En résumé, voici le défi que je lance :
Utiliser la seule macro totale pour créer récursivement l'arbre de Pythagore.

La macro contient tout ce qu'il faut. Elle doit donc suffire.

Hesperion
Posts: 260
Joined: Sun Nov 11, 2007 2:14 pm
Location: Blois

Post by Hesperion » Fri Dec 28, 2012 11:26 am

Alors pour être précis, ce script ne fonctionne qu'avec une version que j'ai modifiée, donc pas avec la version officielle.

Dans cette version, ExecuteMacro renvoie les noms des objets créés par la macro.

Je pense que finalement, sans avoir à modifier la fonction ExecuteMacro, on peut faire l'arbre de Pythagore que tu attends.
Je vais essayer.

Hesperion
Posts: 260
Joined: Sun Nov 11, 2007 2:14 pm
Location: Blois

Post by Hesperion » Fri Dec 28, 2012 2:24 pm

Alors, voici une première version du code qui fonctionne sans que la fonction ExecuteMacro n'ait besoin de retourner le noms des objets créés. Les points de base se nomment P{0} et P{1}.
Par contre, la syntaxe "P{_j},P{_m},P{_k},P{_l},e_i,f_i,g_i" n'est pas encore comprise par l'actuelle version 3.7.6, mais elle le sera dans la prochaine.

Code: Select all

Arbre = function(a, b, nb_iteration){
	var nbPoints;
	aa = a;
	bb = b;
	
	nb_iteration--;
	if(nb_iteration>=0){
		j = 4*i;
		k = 4*i+1;
		l = 4*i+2;
		m = 4*i+3;
		ExecuteMacro("P{_j},P{_m},P{_k},P{_l},e_i,f_i,g_i","DibsArbre/totale","P{_aa},P{_bb}");
		
		nbPoints = i++; //on sauve les indices des points créés avant de s'enfoncer dans la récursion
		Arbre(4*nbPoints, 4*nbPoints+1, nb_iteration);
		Arbre(4*nbPoints+2, 4*nbPoints+3, nb_iteration);
	}
}

i = 1;
Arbre(0,1,4);
Sinon, j'ai aussi écrit le même script, mais en utilisant les noms des objets créés par la macro, un peu plus simple évidemment puisqu'il n'y a aucun effet à fournir concernant le nommage des points créés, il suffit juste de connaitre, dans le tableau t, les indices des points qui nous intéresse.

Code: Select all

Arbre = function(a, b, nb_iteration){
	var t;
	aa = a;
	bb = b;
	
	nb_iteration--;
	if(nb_iteration>=0){
		t = ExecuteMacro("DibsArbre/totale","_aa,_bb");
		t = t.split(",");
		Arbre(t[8],t[15],nb_iteration);
		Arbre(t[16],t[9],nb_iteration);
	}
}

Arbre("P{0}","P{1}",5);
Je ne fournis pas les fichiers et les scripts, car, comme dit au début du post, ils ne fonctionneraient pas avec l'actuelle version 3.7.6.

User avatar
Dibs
Posts: 112
Joined: Tue Apr 24, 2012 2:15 am
Location: Pau

Post by Dibs » Fri Dec 28, 2012 6:28 pm

Merci. C'est vraiment très très intéressant.
Le script 2 montre que ton implémentation est meilleure que celle que je suggérais. Car elle évite tous les effets de bord parasites. Je me rallie désormais à cette approche.

Le script 1 est très astucieux et montre l'intérêt de la nouvelle notation : le nommage prend une force procédurale. Ton script 1 est très parlant.

Juste un petit truc : j'ai un réticence sur la gestion des indices de points dans ce script 1 :
J'aurais plutôt vu ça :

...
ExecuteMacro("P{_j},P{_m},P{_k},P{_l},e_i,f_i,g_i","DibsArbre/totale","P{_aa},P{_bb}");

nbPoint = i ; i *=2; //on sauve les indices des points créés avant de s'enfoncer dans la récursion
Arbre(4*nbPoints, 4*nbPoints+1, nb_iteration);

i++ ;
Arbre(4*nbPoints+2, 4*nbPoints+3, nb_iteration);
}
}
...

Comme de la base 2, en fait. J'espère que je ne dis pas de bêtise...

Lettre au père Noël :
  • Ta nouvelle ExecuteMacro (ExecuteMacro2 ?) dans la prochaîne version de CaRMetal ;
    la version de luxe ExecuteMacro3 qui renverrait la chaîne des finaux seulement ;
    une nouvelle fenêtre propriétés d'une macro qui donnerait une place aux finaux.
Merci encore pour ton aide éclairée.

User avatar
alain974
Posts: 150
Joined: Sat Jun 13, 2009 9:08 am
Location: Réunion

Post by alain974 » Fri Dec 28, 2012 6:55 pm

Pour cet exercice, on n'a pas besoin de macros, on peut tout faire en JavaScript (mais avec des tableaux de points comme bipoints):

Code: Select all

function carré(b){
	p=b[0];
	q=b[1];
	r=Point(X(p)-Y(q)+Y(p),Y(p)+X(q)-X(p));
	s=Point(X(q)-Y(q)+Y(p),Y(q)+X(q)-X(p));
	SetHide("_r,_s",true);
	Polygon(p+","+q+","+s+","+r);
	return [r,s];
}

function triangle(a,b){
	m=MidPoint(a,b);
	d=PerpendicularBisector(a,b);
	c=FixedAngle(b,a,45);
	i=Intersection(c,d);
	SetHide("_m,_d,_c,_i",true);
	return i;
}

function arbre(bipoint,n){
	if (n<5){
		var tr=carré(bipoint);
		var r=triangle(tr[0],tr[1]);
		arbre([tr[0],r],n+1);
		arbre([r,tr[1]],n+1);
	} else {
		carré(bipoint);
	}
}

a=Point(-2,-2);
b=Point(0,-2);
arbre([a,b],0);
La fonction triangle retourne le troisième sommet du triangle; la fonction carré trace le carré et retourne le bipoint translaté (celui sur lequel la construction du triangle se fera). Elle utilise de la géométrie repérée mais on peut faire comme dans la fonction triangle avec des angles droits et des intersections...

En nommant les objets construits et en dérécursifiant on peut aller jusqu'à l'ordre 8 voire plus...

Ordre 6 ci-dessous
Attachments
arbreP1.png
ordre 6
(24.79 KiB) Downloaded 1251 times

Hesperion
Posts: 260
Joined: Sun Nov 11, 2007 2:14 pm
Location: Blois

Post by Hesperion » Fri Dec 28, 2012 8:13 pm

@Dibs
Je ne suis pas sûr que cette modif concernant la variable i fonctionne.
Je te laisse l'essayer lors de la prochaine mise à jour.

Et concernant ExecuteMacro, la nouvelle version contiendra l'ancienne, c'est juste un ajout de ParseVariable, autant dire rien !
Pour le retour de la chaine contenant les finaux, faudra voir exactement...

@Alain
L'algorithme s'adressait peut-être plus à des élèves de collège (voir 4eme post), donc peut-être qu'une solution totalement JS serait trop compliquée, même pour les plus aguerris et curieux d'entre eux (j'ai moi même commencé la programmation au collège, avec mon prof de techno, lors d'ateliers organisés après les cours, alors je me dis que ça doit rester très abordable dans un premier temps...)

User avatar
Dibs
Posts: 112
Joined: Tue Apr 24, 2012 2:15 am
Location: Pau

Post by Dibs » Fri Dec 28, 2012 9:43 pm

@alain :
Au départ, c'est effectivement par souci pédagogique pour mes élèves de 5°.
Cela dit, je considère que cet exemple a une portée générale  : l'utilisation d'une macro apporte une souplesse, une efficacité, et une simplicité sans égale. On suit un processus de pensée naturelle :
1) la macro (aucun effort)
2) son application récursive (avec un script réduit au minimum)

C'est un problème fondamental, qui justifie selon moi le besoin d'un CaRScript ExecuteMacro plus évolué.

@Hesperion :
Je suis déçu du Père Noël. :)
Si je comprends bien, avec tout ça il va falloir que j'explique le script 1 à mes élèves de 5° ?... Hum hum... :?
Je sens que mon régiment de macros DibsArbre/ n'est pas encore au placard.

@tous :
Si ExecuteMacro3() existait, on pourrait même faire un assistant de récursivité pour appliquer récursivement n'importe qu'elle macro. Avec aucune ligne de code.

Hesperion
Posts: 260
Joined: Sun Nov 11, 2007 2:14 pm
Location: Blois

Post by Hesperion » Fri Dec 28, 2012 10:07 pm

Ah je me suis mal exprimé en fait.

Le fait d'avoir cette possibilité d'avoir en retour la liste des objets construits par la macro est très importante pour avoir un script réduit au minimum (comme tu dis), mais sous quelle forme exactement :
* implémentée dans la version actuelle, mais quid de la rétrocompatibilité ?
* création d'un ExecuteMacro2 ?

Pour cela, il faudra attendre la prochaine mise à jour.

Post Reply