/*************************************************************************************************************************************/ /* */ /* G E N E R A T I O N D ' U N P A V A G E D U D I S Q U E D E P O I N C A R E : */ /* */ /* */ /* Author of '$xci/valeurs_DPoincare.01$K' : */ /* */ /* Jean-Francois COLONNA (LACTAMME, 20120522141653). */ /* */ /*************************************************************************************************************************************/ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* I N T E R F A C E ' listG ' : */ /* */ /* */ /* :Debut_listG: */ /* :Fin_listG: */ /* */ /*************************************************************************************************************************************/ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* D I R E C T I V E S S P E C I F I Q U E S D E C O M P I L A T I O N : */ /* */ /*************************************************************************************************************************************/ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* F I C H I E R S D ' I N C L U D E S : */ /* */ /*************************************************************************************************************************************/ #include INCLUDES_BASE /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* P A R A M E T R E S : */ /* */ /*************************************************************************************************************************************/ #define COMPATIBILITE_2012060510 \ FAUX \ /* Permet de generer des segments {A,B} identiques a celles qui auraient pu etre generes */ \ /* anterieurement au 20120605104020... */ #define COMPATIBILITE_2012060512 \ FAUX \ /* Permet de generer l'ensemble des polygones (meme redondants) identiques a ceux qui */ \ /* auraient pu etre generes anterieurement au 20120605121054... */ #define EDITER_LES_COORDONNEES_DES_POINTS \ VRAI #define EDITER_LES_COORDONNEES_NORMALISEES_DES_POINTS \ VRAI /* Faut-il editer les coordonnees des points ('VRAI') ou pas ('FAUX') et doivent-elles */ /* normalisees ('VRAI') ou denormalisees ('FAUX') ? */ #define EDITER_LES_POINTS_SOUS_LA_FORME_DE_SEGMENTS_AB \ VRAI \ /* Faut-il editer des segments 'AB' ('VRAI') ou des points isoles ('FAUX') ? */ #define SUPPRIMER_LES_SEGMENTS_AB_REDONDANTS \ VRAI \ /* Faut-il supprimer les segments 'AB' redondants ('VRAI') ou les conserver ('FAUX') ? Ceci */ \ /* fut introduit le 20120609093349... */ #define INTERPOLER_CIRCULAIREMENT_ENTRE_LES_SOMMETS \ FAUX #define FACTEUR_DE_CALCUL_DU_NOMBRE_DE_PAS_ANGULAIRES \ FLOT(VINGT) /* Dans le cas ou 'IL_NE_FAUT_PAS(editer_les_points_sous_la_forme_de_segments_AB)', doit-on */ /* interpoler circulairement entre les sommets ('VRAI') ou pas ('FAUX') ? */ #define AVERTIR_DANS_LE_CAS_DE_RAYONS_NEGATIFS_OU_NULS \ FAUX \ /* Faut-il avertir ('VRAI') ou pas lors en acs de rayons negatifs ou nuls ('FAUX') ? */ #define NOMBRE_DE_COTES_DU_POLYGONE_FONDAMENTAL \ SIX \ /* Nombre de cotes 'N' du polygone fondamental. */ #define ANGLE_AU_SOMMET_EN_FRACTION_DU_CERCLE_TRIGONOMETRIQUE \ QUATRE \ /* Mesure des angles au sommet du polygone fondamental exprimee en fraction 'P' de 2.pi. */ #define PROFONDEUR_DU_DISQUE_DE_POINCARE \ DEUX \ /* Profondeur de la generation... */ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* M A C R O S U T I L E S : */ /* */ /*************************************************************************************************************************************/ /* On notera que l'on ne peut pas mettre ici : */ /* */ /* #include xci/valeurs.02.I" */ /* */ /* a cause du message : */ /* */ /* error: initializer element is not constant */ /* */ /* provoque par la fonction 'Finitialisation_d_une_constante_chaine_de_caracteres(...)'. */ /* On notera que l'on ne met pas ici : */ /* */ /* #include xci/valeurs.03.I" */ /* */ /* parce que l'on ne peut inclure '$xci/valeurs.02$I' ci-avant... */ DEFV(Local,DEFV(Logical,INIT(editer_les_coordonnees_des_points,EDITER_LES_COORDONNEES_DES_POINTS))); DEFV(Local,DEFV(Logical,INIT(editer_les_coordonnees_normalisees_des_points,EDITER_LES_COORDONNEES_NORMALISEES_DES_POINTS))); /* Faut-il editer les coordonnees des points ('VRAI') ou pas ('FAUX') et doivent-elles */ /* normalisees ('VRAI') ou denormalisees ('FAUX') ? */ DEFV(Local,DEFV(Logical,INIT(editer_les_points_sous_la_forme_de_segments_AB,EDITER_LES_POINTS_SOUS_LA_FORME_DE_SEGMENTS_AB))); /* Faut-il editer des segments 'AB' ('VRAI') ou des points isoles ('FAUX') ? */ DEFV(Local,DEFV(Logical,INIT(supprimer_les_segments_AB_redondants,SUPPRIMER_LES_SEGMENTS_AB_REDONDANTS))); /* Faut-il supprimer les segments 'AB' redondants ('VRAI') ou les conserver ('FAUX') ? Ceci */ /* fut introduit le 20120609093349... */ DEFV(Local,DEFV(Logical,INIT(interpoler_circulairement_entre_les_sommets,INTERPOLER_CIRCULAIREMENT_ENTRE_LES_SOMMETS))); DEFV(Local,DEFV(Float,INIT(facteur_de_calcul_du_nombre_de_pas_angulaires,FACTEUR_DE_CALCUL_DU_NOMBRE_DE_PAS_ANGULAIRES))); /* Dans le cas ou 'IL_NE_FAUT_PAS(editer_les_points_sous_la_forme_de_segments_AB)', doit-on */ /* interpoler circulairement entre les sommets ('VRAI') ou pas ('FAUX') ? */ #define INCLINAISON_GENERALE_DU_POLYGONE_FONDAMENTAL \ FZERO \ /* Donne l'inclinaison par rapport a l'horizontale du centre du cercle du premier cote du */ \ /* polygone fondamental. */ #define EDITION_DES_COORDONNEES(coord_X,coord_Y,editer,format_XY_normalisees,format_XY_denormalisees,format_numero_polygone) \ Bblock \ Test(IL_FAUT(editer_les_coordonnees_des_points)) \ Bblock \ Test(IL_FAUT(editer)) \ Bblock \ Test(IL_FAUT(editer_les_coordonnees_normalisees_des_points)) \ Bblock \ CAL2(Prin2(format_XY_normalisees \ ,coord_X \ ,coord_Y \ ) \ ); \ /* On notera que l'on ne peut utiliser 'NOMBRE_DE_DECIMALES_EFFECTIF(...)' ou encore */ \ /* 'valeurs_signees' et 'format_d_edition' tels qu'il sont definis d'une part dans */ \ /* 'v $xci/valeurs.02$I' et d'autre part dans '$xci/valeurs.03$I' pour des problemes */ \ /* de references en avant... */ \ /* */ \ /* Grace a ce format d'edition, on peut assurer les conversions : */ \ /* */ \ /* {X,Y} <--> CoordonneeCurviligne */ \ /* */ \ /* si besoin est... */ \ Eblock \ ATes \ Bblock \ CAL2(Prin2(format_XY_denormalisees \ ,_cDENORMALISE_OX(coord_X) \ ,_cDENORMALISE_OY(coord_Y) \ ) \ ); \ Eblock \ ETes \ \ CAL2(Prin2(format_numero_polygone \ ,numero_du_polygone_courant \ ,profondeur_courante \ ) \ ); \ Eblock \ ATes \ Bblock \ Eblock \ ETes \ Eblock \ ATes \ Bblock \ Eblock \ ETes \ Eblock \ /* Edition des coordonnees. */ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* D E F I N I T I O N S G E N E R A L E S R E L A T I V E S A U X P O L Y G O N E S */ /* D ' U N P A V A G E D U D I S Q U E D E P O I N C A R E : */ /* */ /*************************************************************************************************************************************/ DEFV(Int,INIT(profondeur_du_disque_de_Poincare,PROFONDEUR_DU_DISQUE_DE_POINCARE)); /* Profondeur de la generation... */ DEFV(Local,DEFV(Int,INIT(nombre_de_cotes_du_polygone_fondamental,NOMBRE_DE_COTES_DU_POLYGONE_FONDAMENTAL))); /* Nombre de cotes 'N' du polygone fondamental. */ DEFV(Local,DEFV(Int,INIT(angle_au_sommet_en_fraction_du_cercle_trigonometrique,ANGLE_AU_SOMMET_EN_FRACTION_DU_CERCLE_TRIGONOMETRIQUE))); /* Mesure des angles au sommet du polygone fondamental exprimee en fraction 'P' de 2.pi. */ DEFV(Local,DEFV(Float,INIT(demi_angle_au_sommet_du_polygone_fondamental,FLOT__UNDEF))); DEFV(Local,DEFV(Float,INIT(demi_angle_au_centre_du_polygone_fondamental,FLOT__UNDEF))); /* Definition de deux angles tres utiles... */ #define PREMIER_COTE_D_UN_POLYGONE \ PREMIER_POINT #define sommet_de_reference_du_polygone_fondamental \ ACCES_SOMMET(polygone_fondamental,PREMIER_COTE_D_UN_POLYGONE) /* Premier sommet du polygone fondamental. */ #define C_EST_LE_POLYGONE_FONDAMENTAL \ IFEQ(profondeur,PRED(profondeur_du_disque_de_Poincare)) \ /* Introduit le 20120609093349 afin de savoir si l'on est sur le polygone fondamental... */ #define sITb0(vecteur,index,dimension) \ ITb0(vecteur,index) \ /* Introduit afin que 'sITb0(...)' ait le meme nombre d'arguments (trois) que 'IdTb1(...)', */ \ /* ce qui n'est pas le cas de 'ITb0(...)' qui n'en a que deux... */ #define ACCES_SOMMET(nom_du_polygone,numero_du_cote_courant_du_polygone,ACCES) \ ACCES(liste_des_sommets_du`nom_du_polygone \ ,INDX(numero_du_cote_courant_du_polygone,PREMIER_COTE_D_UN_POLYGONE) \ ,nombre_de_cotes_du_polygone_fondamental \ ) #define ACCES_CENTRE(nom_du_polygone,numero_du_cote_courant_du_polygone,ACCES) \ ACCES(liste_des_centres_des_cercles_des_cotes_du`nom_du_polygone \ ,INDX(numero_du_cote_courant_du_polygone,PREMIER_COTE_D_UN_POLYGONE) \ ,nombre_de_cotes_du_polygone_fondamental \ ) \ /* Procedure d'acces a un sommet du polygone fondamental. */ #define ACCES_RAYON_(nom_du_polygone,numero_du_cote_courant_du_polygone,ACCES) \ ACCES(liste_des_rayons_des_cercles_des_cotes_du`nom_du_polygone \ ,INDX(numero_du_cote_courant_du_polygone,PREMIER_COTE_D_UN_POLYGONE) \ ,nombre_de_cotes_du_polygone_fondamental \ ) #define DEBUT_DE_DEFINITION_D_UN_POLYGONE(nom_du_polygone) \ DEFV(pointF_2D,DdTb1(POINTERs \ ,liste_des_sommets_du`nom_du_polygone \ ,nombre_de_cotes_du_polygone_fondamental \ ,tMalo(MUL2(nombre_de_cotes_du_polygone_fondamental,SIZE(pointF_2D)),pointF_2D) \ ) \ ); \ DEFV(pointF_2D,DdTb1(POINTERs \ ,liste_des_centres_des_cercles_des_cotes_du`nom_du_polygone \ ,nombre_de_cotes_du_polygone_fondamental \ ,tMalo(MUL2(nombre_de_cotes_du_polygone_fondamental,SIZE(pointF_2D)),pointF_2D) \ ) \ ); \ DEFV(Float,DdTb1(POINTERf \ ,liste_des_rayons_des_cercles_des_cotes_du`nom_du_polygone \ ,nombre_de_cotes_du_polygone_fondamental \ ,fMalo(MUL2(nombre_de_cotes_du_polygone_fondamental,size_Float)) \ ) \ ); #define FIN_DE_DEFINITION_D_UN_POLYGONE(nom_du_polygone) \ FdTb1(liste_des_rayons_des_cercles_des_cotes_du`nom_du_polygone \ ,nombre_de_cotes_du_polygone_fondamental \ ,Float \ ,ADRESSE_PLUS_DEFINIE \ ); \ FdTb1(liste_des_centres_des_cercles_des_cotes_du`nom_du_polygone \ ,nombre_de_cotes_du_polygone_fondamental \ ,pointF_2D \ ,ADRESSE_PLUS_DEFINIE \ ); \ FdTb1(liste_des_sommets_du`nom_du_polygone \ ,nombre_de_cotes_du_polygone_fondamental \ ,pointF_2D \ ,ADRESSE_PLUS_DEFINIE \ ); /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* F O N C T I O N S R E C U R S I V E S D E G E N E R A T I O N */ /* D ' U N P A V A G E D U D I S Q U E D E P O I N C A R E : */ /* */ /*************************************************************************************************************************************/ #define INVERSION_D_UNE_COORDONNEE_D_UN_POINT(oordonnee_2,coordonnee_1,centre_inversion,rayon_inversion) \ EGAL(oordonnee_2 \ ,ADD2(centre_inversion \ ,SCAL(SOUS(coordonnee_1,centre_inversion),longueur_1_au_carre,EXP2(rayon_inversion)) \ ) \ ) \ /* Procedure d'inversion d'une coordonnee d'un point. */ #define INVERSION_D_UN_POINT(point_2,point_1,centre_inversion,rayon_inversion) \ Bblock \ DEFV(Float,INIT(longueur_1_au_carre,FLOT__UNDEF)); \ \ EGAL(longueur_1_au_carre \ ,pdisF2D(point_1,centre_inversion) \ ); \ \ INVERSION_D_UNE_COORDONNEE_D_UN_POINT(ASD1(point_2,x) \ ,ASD1(point_1,x) \ ,ASD1(centre_inversion,x) \ ,rayon_inversion \ ); \ INVERSION_D_UNE_COORDONNEE_D_UN_POINT(ASD1(point_2,y) \ ,ASD1(point_1,y) \ ,ASD1(centre_inversion,y) \ ,rayon_inversion \ ); \ \ Test(IFGE(Rho_2D(ASD1(point_2,x),ASD1(point_2,y)),RAYON_DU_CERCLE_TRIGONOMETRIQUE)) \ Bblock \ PRINT_ERREUR("apres inversion, un point est sur la frontiere ou est a l'exterieur du disque"); \ CAL1(Prer7("(CentreInversion={%f,%f} RayonInversion=%f PointAvant={%f,%f} PointApres={%f,%f})\n" \ ,ASD1(centre_inversion,x),ASD1(centre_inversion,y) \ ,rayon_inversion \ ,ASD1(point_1,x),ASD1(point_1,y) \ ,ASD1(point_2,x),ASD1(point_2,y) \ ) \ ); \ Eblock \ ATes \ Bblock \ Eblock \ ETes \ Eblock \ /* Procedure d'inversion d'un point suivant la definition : */ \ /* */ \ /* Soient : */ \ /* */ \ /* C : le centre d'inversion, */ \ /* R : la puissance d'inversion, */ \ /* P1 : un point quelconque, */ \ /* */ \ /* Le point P2 est l'inverse de P1 selon : */ \ /* */ \ /* ----> ----> 2 */ \ /* CP . CP = R */ \ /* 1 2 */ \ /* */ DEFV(Local,DEFV(Logical,INIT(avertir_dans_le_cas_de_rayons_negatifs_ou_nuls,AVERTIR_DANS_LE_CAS_DE_RAYONS_NEGATIFS_OU_NULS))); /* Faut-il avertir ('VRAI') ou pas lors en acs de rayons negatifs ou nuls ('FAUX') ? */ #define INVERSION_DU_RAYON_D_UN_CERCLE(rayon_2,centre_cercle_1,rayon_1,centre_inversion,rayon_inversion) \ Bblock \ EGAL(rayon_2 \ ,SCAL(rayon_1 \ ,SOUS(pdisF2D(centre_inversion,centre_cercle_1) \ ,EXP2(rayon_1) \ ) \ ,EXP2(rayon_inversion) \ ) \ ); \ /* Alors : 'SOUS(...)' ou 'SOUA(...)' ? En fait, il apparait qu'effectivement ce "rayon" */ \ /* ('rayon_2') peut etre negatif ! Il y a deux solutions : soit on utilise ici 'SOUA(...)', */ \ /* soit lorsque l'on utilise un rayon, on lui applique systematiquement 'ABSO(...)' comme */ \ /* cela est fait avec 'RAYON_DU_CERCLE' et 'RAYON_COURANT'. Enfin, on peut remplacer */ \ /* ci-apres 'NEUT(...)' par 'ABSO(...)'... */ \ \ Test(IZLE(rayon_2)) \ Bblock \ Test(IL_FAUT(avertir_dans_le_cas_de_rayons_negatifs_ou_nuls)) \ Bblock \ PRINT_ERREUR("apres inversion, un rayon est negatif ou nul"); \ CAL1(Prer7("(CentreInversion={%f,%f} RayonInversion=%f CentreCercle={%f,%f} Rayon1=%f Rayon2=%f)\n" \ ,ASD1(centre_inversion,x),ASD1(centre_inversion,y) \ ,rayon_inversion \ ,ASD1(centre_cercle_1,x),ASD1(centre_cercle_1,y) \ ,rayon_1 \ ,rayon_2 \ ) \ ); \ Eblock \ ATes \ Bblock \ Eblock \ ETes \ \ EGAL(rayon_2,NEUT(rayon_2)); \ /* On peut remplacer 'NEUT(...)' par 'ABSO(...)'... */ \ Eblock \ ATes \ Bblock \ Eblock \ ETes \ Eblock \ /* Procedure d'inversion du rayon d'un cercle. */ #define INVERSION_D_UNE_COORDONNEE_DU_CENTRE_D_UN_CERCLE(coordonnee_2,rayon_2,coordonnee_1,rayon_1,centre_inversion,rayon_inversion) \ EGAL(coordonnee_2 \ ,ADD2(centre_inversion \ ,SCAL(SOUS(coordonnee_1,centre_inversion),rayon_1,rayon_2) \ ) \ ) \ /* Procedure d'inversion d'une coordonnee du centre d'un cercle. */ #define INVERSION_DU_CENTRE_D_UN_CERCLE(centre_cercle_2,rayon_2,centre_cercle_1,rayon_1,centre_inversion,rayon_inversion) \ Bblock \ Test(IFET(IFEQ(ASD1(centre_cercle_1,x),ASD1(centre_inversion,x)) \ ,IFEQ(ASD1(centre_cercle_1,y),ASD1(centre_inversion,y)) \ ) \ ) \ Bblock \ EGAL(ASD1(centre_cercle_2,x),ASD1(centre_cercle_1,x)); \ EGAL(ASD1(centre_cercle_2,y),ASD1(centre_cercle_1,y)); \ EGAL(rayon_2,rayon_1); \ /* Cas ou le cercle a inverser est lui-meme le cercle d'inversion : on le conserve... */ \ Eblock \ ATes \ Bblock \ INVERSION_DU_RAYON_D_UN_CERCLE(rayon_2 \ ,centre_cercle_1 \ ,rayon_1 \ ,centre_inversion \ ,rayon_inversion \ ); \ INVERSION_D_UNE_COORDONNEE_DU_CENTRE_D_UN_CERCLE(ASD1(centre_cercle_2,x) \ ,rayon_2 \ ,ASD1(centre_cercle_1,x) \ ,rayon_1 \ ,ASD1(centre_inversion,x) \ ,rayon_inversion \ ); \ INVERSION_D_UNE_COORDONNEE_DU_CENTRE_D_UN_CERCLE(ASD1(centre_cercle_2,y) \ ,rayon_2 \ ,ASD1(centre_cercle_1,y) \ ,rayon_1 \ ,ASD1(centre_inversion,y) \ ,rayon_inversion \ ); \ Eblock \ ETes \ Eblock \ /* Procedure d'inversion du centre d'un cercle suivant la definition : */ \ /* */ \ /* Soient : */ \ /* */ \ /* C : le centre d'inversion, */ \ /* R : la puissance d'inversion, */ \ /* K1 : un cercle de rayon R1 et de centre C1, */ \ /* A1 : l'un des deux points de tangence a K1 d'une droite */ \ /* issue de 'C'. */ \ /* */ \ /* L'inverse K2 du cercle K1 est tel que : */ \ /* */ \ /* Soient : */ \ /* */ \ /* C2 : le centre de K2, */ \ /* R2 : le rayon de K2, */ \ /* A2 : le points de tangence a K2 de la droite CA1. */ \ /* */ \ /* Les triangles {C,C2,A2} et {C,C1,A1} sont semblables et donc : */ \ /* */ \ /* CC CA C A R */ \ /* 2 2 2 2 2 */ \ /* ----- = ----- = ------ = ---- */ \ /* CC CA C A R */ \ /* 1 1 1 1 1 */ \ /* */ \ /* Le point A2 etant l'inverse de A1 (par definition de K2 inverse de K1), on a : */ \ /* */ \ /* 2 */ \ /* |CA |.|CA | = R */ \ /* 1 2 */ \ /* */ \ /* On deduit alors les deux formules (via le theoreme de Pythagore) : */ \ /* */ \ /* 2 */ \ /* R */ \ /* R = R .---------- */ \ /* 2 1 2 2 */ \ /* CC - R */ \ /* 1 1 */ \ /* */ \ /* */ \ /* R */ \ /* 2 */ \ /* CC = CC .---- */ \ /* 2 1 R */ \ /* 1 */ \ /* */ \ /* On notera au passage que C2 (centre de K2) n'est pas l'inverse de C1 (centre de K1)... */ DEFV(Local,DEFV(Int,INIT(numero_du_polygone_courant,ZERO))); DEFV(Local,DEFV(Int,INIT(profondeur_courante,ZERO))); /* Afin de donner une identite au polygone courant et sa profondeur... */ DEFV(Local,DEFV(Logical,INIT(compatibilite_2012060510,COMPATIBILITE_2012060510))); /* Permet de generer des segments {A,B} identiques a celles qui auraient pu etre generes */ /* anterieurement au 20120605104020... */ DEFV(Local,DEFV(Logical,INIT(compatibilite_2012060512,COMPATIBILITE_2012060512))); /* Permet de generer l'ensemble des polygones (meme redondants) identiques a ceux qui */ /* auraient pu etre generes anterieurement au 20120605121054... */ BFonctionI DEFV(LoF,DEFV(FonctionI,InversionDUnPolygone(profondeur ,liste_des_centres_des_cercles_du_polygone_1 ,liste_des_rayons_des_cercles_du_polygone_1 ,liste_des_sommets_du_polygone_1 ) ) ) DEFV(Argument,DEFV(Int,profondeur)); /* Profondeur de la generation courante... */ DEFV(Argument,DEFV(pointF_2D,DTb0(liste_des_centres_des_cercles_des_cotes_du_polygone_1))); DEFV(Argument,DEFV(Float,DTb0(liste_des_rayons_des_cercles_des_cotes_du_polygone_1))); DEFV(Argument,DEFV(pointF_2D,DTb0(liste_des_sommets_du_polygone_1))); /* Definition du polygone a inverser. */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock DEFV(Int,INIT(numero_du_cote_courant_du_polygone_1,UNDEF)); DEFV(Float,INIT(longueur_du_plus_grand_cote_du_polygone_1,F_MOINS_L_INFINI)); INIT_ERROR; /*..............................................................................................................................*/ INCR(numero_du_polygone_courant,I); INCR(profondeur_courante,I); Test(IFOU(C_EST_LE_POLYGONE_FONDAMENTAL ,IL_NE_FAUT_PAS(supprimer_les_segments_AB_redondants) ) ) /* Test introduit le 20120609093349... */ Bblock /* Cas ou l'on est sur le polygone fondamental ou bien les segments redondants doivent */ /* etre conserves... */ Eblock ATes Bblock /* Cas ou les segments redondants peuvent etre elimines : */ DoIn(numero_du_cote_courant_du_polygone_1 ,PREMIER_COTE_D_UN_POLYGONE ,LSTX(PREMIER_COTE_D_UN_POLYGONE,nombre_de_cotes_du_polygone_fondamental) ,I ) Bblock DEFV(Int,INIT(numero_du_cote_suivant_du_polygone_1 ,MODU(SUCC(numero_du_cote_courant_du_polygone_1) ,PREMIER_COTE_D_UN_POLYGONE ,LSTX(PREMIER_COTE_D_UN_POLYGONE,nombre_de_cotes_du_polygone_fondamental) ) ) ); EGAL(longueur_du_plus_grand_cote_du_polygone_1 ,MAX2(RpdisF2D(ACCES_SOMMET(polygone_1,numero_du_cote_courant_du_polygone_1,IdTb1) ,ACCES_SOMMET(polygone_1,numero_du_cote_suivant_du_polygone_1,IdTb1) ) ,longueur_du_plus_grand_cote_du_polygone_1 ) ); /* Calcul introduit le 20120606183015... */ /* */ /* On notera que pour les polygones autres que le polygone fondamental, leur plus long cote */ /* (par le fait que l'inversion est ici une transformation "contractante") est aussi celui */ /* qui est commun avec leur polygone "pere" (de niveau superieur). Il est donc inutile de */ /* l'editer une seconde fois, d'ou ce test de longueur que l'on fera ci-apres pour */ /* l'eliminer (grace a 'longueur_du_plus_grand_cote_du_polygone_1'...). */ Eblock EDoI Eblock ETes DoIn(numero_du_cote_courant_du_polygone_1 ,PREMIER_COTE_D_UN_POLYGONE ,LSTX(PREMIER_COTE_D_UN_POLYGONE,nombre_de_cotes_du_polygone_fondamental) ,I ) Bblock Test(IL_NE_FAUT_PAS(interpoler_circulairement_entre_les_sommets)) Bblock DEFV(Float,INIT(X1,ASD1(ACCES_SOMMET(polygone_1,numero_du_cote_courant_du_polygone_1,sITb0),x))); DEFV(Float,INIT(Y1,ASD1(ACCES_SOMMET(polygone_1,numero_du_cote_courant_du_polygone_1,sITb0),y))); DEFV(Float,INIT(X1_effectif,FLOT__UNDEF)); DEFV(Float,INIT(Y1_effectif,FLOT__UNDEF)); EGAL(X1_effectif,X1); EGAL(Y1_effectif,Y1); Test(IL_NE_FAUT_PAS(editer_les_points_sous_la_forme_de_segments_AB)) Bblock EDITION_DES_COORDONNEES(X1_effectif ,Y1_effectif ,TOUJOURS_VRAI ,"xA=%+.^^^ yA=%+.^^^" ,"xA=%d yA=%d" ," NumeroPolygone=%d Profondeur=%d" ); CAL2(Prin0("\n")); Eblock ATes Bblock DEFV(Int,INIT(numero_du_cote_suivant_du_polygone_1 ,MODU(SUCC(numero_du_cote_courant_du_polygone_1) ,PREMIER_COTE_D_UN_POLYGONE ,LSTX(PREMIER_COTE_D_UN_POLYGONE,nombre_de_cotes_du_polygone_fondamental) ) ) ); DEFV(Float,INIT(X2,FLOT__UNDEF)); DEFV(Float,INIT(Y2,FLOT__UNDEF)); DEFV(Float,INIT(X2_effectif,FLOT__UNDEF)); DEFV(Float,INIT(Y2_effectif,FLOT__UNDEF)); EGAL(X2,ASD1(ACCES_SOMMET(polygone_1,numero_du_cote_suivant_du_polygone_1,sITb0),x)); EGAL(Y2,ASD1(ACCES_SOMMET(polygone_1,numero_du_cote_suivant_du_polygone_1,sITb0),y)); EGAL(X2_effectif,X2); EGAL(Y2_effectif,Y2); Test(IL_FAUT(compatibilite_2012060510)) Bblock Eblock ATes Bblock /* La sequence de tri qui suit a ete introduite le 20120605104020... */ Test(IFLT(X1,X2)) Bblock /* Dans le cas ou X1<X2, l'ordre {1,2} est conserve... */ Eblock ATes Bblock Test(IFGT(X1,X2)) Bblock EGAL(X1_effectif,X2); EGAL(Y1_effectif,Y2); EGAL(X2_effectif,X1); EGAL(Y2_effectif,Y1); /* Dans le cas ou X1>X2, l'ordre {1,2} est inverse... */ Eblock ATes Bblock Test(IFLT(Y1,Y2)) Bblock /* Dans le cas ou X1=X2 et Y1<Y2, l'ordre {1,2} est conserve... */ Eblock ATes Bblock Test(IFGT(Y1,Y2)) Bblock EGAL(X1_effectif,X2); EGAL(Y1_effectif,Y2); EGAL(X2_effectif,X1); EGAL(Y2_effectif,Y1); /* Dans le cas ou X1=X2 et Y1>Y2, l'ordre {1,2} est inverse... */ Eblock ATes Bblock Eblock ETes Eblock ETes Eblock ETes Eblock ETes Eblock ETes Test(I3OU(C_EST_LE_POLYGONE_FONDAMENTAL ,IL_NE_FAUT_PAS(supprimer_les_segments_AB_redondants) ,IFLT(RdisF2D(X1_effectif,Y1_effectif,X2_effectif,Y2_effectif) ,longueur_du_plus_grand_cote_du_polygone_1 ) ) ) /* Test introduit le 20120606183015... */ /* */ /* On regarde donc soit si nous sommes en train de traiter le polygone fondamental (via */ /* le test de 'profondeur'), soit pour les autres polygones s'il s'agit de cotes non */ /* encore edites (via le test de 'longueur_du_plus_grand_cote_du_polygone_1')... */ Bblock EDITION_DES_COORDONNEES(X1_effectif ,Y1_effectif ,TOUJOURS_VRAI ,"xA=%+.^^^ yA=%+.^^^" ,"xA=%d yA=%d" ," NumeroPolygone=%d Profondeur=%d" ); CAL2(Prin0(" ")); EDITION_DES_COORDONNEES(X2_effectif ,Y2_effectif ,TOUJOURS_VRAI ,"xB=%+.^^^ yB=%+.^^^" ,"xB=%d yB=%d" ," NumeroPolygone=%d Profondeur=%d" ); /* Edition du segment courant {{X1,Y1},{X2,Y2}} systematiquement lorsque l'on traite le */ /* polygone fondamental, ou pour les polygones suivants, si ce segment n'est pas le plus */ /* long de ce polygone (auquel cas, il a deja ete traite a un niveau superieur...). On */ /* notera que j'avais essaye au prealable un test plus "leger" consistant a tester la */ /* valeur de 'numero_du_cote_courant_du_polygone_1, mais malheureusement, contrairement */ /* a mon espoir, cet indice n'est pas le meme (le premier, le dernier,...) d'un polygone */ /* a l'autre ; il y a en fait une sorte de permutation circulaire d'un cran a chaque */ /* nouveau polygone... */ CAL2(Prin0("\n")); Eblock ATes Bblock Eblock ETes Eblock ETes Eblock ATes Bblock DEFV(Int,INIT(nombre_de_pas,UNDEF)); /* Nombre de pas d'interpolation circulaire... */ DEFV(pointF_2D,centre); DEFV(Float,INIT(rayon_du_cercle,FLOT__UNDEF)); /* Centre et rayon du cercle sur lequel se fait l'interpolation. */ DEFV(pointF_2D,sommet_1); DEFV(Float,INIT(Rho__relatif_au_centre_du_sommet_1,FLOT__UNDEF)); DEFV(Float,INIT(Theta_relatif_au_centre_du_sommet_1,FLOT__UNDEF)); /* Origine (1) de l'interpolation circulaire. */ DEFV(pointF_2D,sommet_2); DEFV(Float,INIT(Rho__relatif_au_centre_du_sommet_2,FLOT__UNDEF)); DEFV(Float,INIT(Theta_relatif_au_centre_du_sommet_2,FLOT__UNDEF)); /* Extremite (2) de l'interpolation circulaire. */ TRANSFERT_POINT_2D(centre,ACCES_CENTRE(polygone_1,NEUT(numero_du_cote_courant_du_polygone_1),sITb0)); EGAL(rayon_du_cercle,ACCES_RAYON_(polygone_1,numero_du_cote_courant_du_polygone_1,sITb0)); /* Definition du cercle sur lequel se fait l'interpolation. */ TRANSFERT_POINT_2D(sommet_1 ,ACCES_SOMMET(polygone_1 ,MODU(PRED(numero_du_cote_courant_du_polygone_1) ,PREMIER_COTE_D_UN_POLYGONE ,LSTX(PREMIER_COTE_D_UN_POLYGONE,nombre_de_cotes_du_polygone_fondamental) ) ,sITb0 ) ); /* Definition de l'origine (1) de l'interpolation circulaire. */ TRANSFERT_POINT_2D(sommet_2 ,ACCES_SOMMET(polygone_1,NEUT(numero_du_cote_courant_du_polygone_1),sITb0) ); /* Definition de l'extremite (2) de l'interpolation circulaire. */ EGAL(Rho__relatif_au_centre_du_sommet_1 ,Rho_2D(SOUS(ASD1(sommet_1,x),ASD1(centre,x)),SOUS(ASD1(sommet_1,y),ASD1(centre,y))) ); EGAL(Theta_relatif_au_centre_du_sommet_1 ,Theta_2D(SOUS(ASD1(sommet_1,x),ASD1(centre,x)),SOUS(ASD1(sommet_1,y),ASD1(centre,y))) ); EGAL(Rho__relatif_au_centre_du_sommet_2 ,Rho_2D(SOUS(ASD1(sommet_2,x),ASD1(centre,x)),SOUS(ASD1(sommet_2,y),ASD1(centre,y))) ); EGAL(Theta_relatif_au_centre_du_sommet_2 ,Theta_2D(SOUS(ASD1(sommet_2,x),ASD1(centre,x)),SOUS(ASD1(sommet_2,y),ASD1(centre,y))) ); /* Determination des deux bornes extremes de 'Rho' et de 'Theta' lors de l'interpolation... */ Test(IFGT(SOUA(Theta_relatif_au_centre_du_sommet_1,Theta_relatif_au_centre_du_sommet_2),PI)) Bblock /* Cas ou l'on passe par dessus '2.pi' : */ Test(IFLT(Theta_relatif_au_centre_du_sommet_1,Theta_relatif_au_centre_du_sommet_2)) Bblock INCR(Theta_relatif_au_centre_du_sommet_1,CERCLE_TRIGONOMETRIQUE); Eblock ATes Bblock INCR(Theta_relatif_au_centre_du_sommet_2,CERCLE_TRIGONOMETRIQUE); Eblock ETes Eblock ATes Bblock Eblock ETes #define RAYON_DU_CERCLE \ ABSO(rayon_du_cercle) Test(IFET(IFEQ_a_peu_pres_absolu(Rho__relatif_au_centre_du_sommet_1,RAYON_DU_CERCLE,igEPSILON) ,IFEQ_a_peu_pres_absolu(Rho__relatif_au_centre_du_sommet_2,RAYON_DU_CERCLE,igEPSILON) ) ) Bblock Eblock ATes Bblock PRINT_ERREUR("incompatibilite entre les rayons extremes d'interpolation et celui d'inversion en valeur absolue"); CAL1(Prer3("(Rayon=%f Rho1=%f Rho2=%f)\n" ,rayon_du_cercle ,Rho__relatif_au_centre_du_sommet_1 ,Rho__relatif_au_centre_du_sommet_2 ) ); Eblock ETes EGAL(nombre_de_pas ,INTE(MUL3(facteur_de_calcul_du_nombre_de_pas_angulaires ,RAYON_DU_CERCLE ,SOUA(Theta_relatif_au_centre_du_sommet_2,Theta_relatif_au_centre_du_sommet_1) ) ) ); /* Le nombre de pas est donc proportionnel a la longueur de l'arc de cercle sur lequel on */ /* doit interpoler... */ /* */ /* Le 20161115152426, je note que si 'facteur_de_calcul_du_nombre_de_pas_angulaires' est */ /* trop petit, les arcs de cercle ont une apparence polyonale et ce d'autant plus qu'ils */ /* sont petits ('v $xiirv/POIN.13' ou en effet, les points ici generes sont joints les */ /* uns aux autres : 'v $xiirv/.POIN.21.$U isoles=FAUX.chainer=FAUX' ce qui donne des */ /* segments de plus en plus visibles...). */ EGAL(nombre_de_pas,MAX2(nombre_de_pas,DEUX)); /* Afin d'eviter une division par zero dans le 'BARY(...)' a venir... */ Repe(nombre_de_pas) Bblock DEFV(Float,INIT(lambda ,DIVI(FLOT(SOUS(compteur_des_repetitions_du_Repe,PREMIERE_ITERATION_D_UN_Repe)) ,FLOT(SOUS(nombre_de_pas,PREMIERE_ITERATION_D_UN_Repe)) ) ) ); /* Parametre d'interpolation afin de balayer le cote du polygone du sommet 1 au sommet 2... */ DEFV(Float,INIT(Rho__courant,FLOT__UNDEF)); DEFV(Float,INIT(Theta_courant,FLOT__UNDEF)); DEFV(pointF_2D,point_intermediaire_interpole); EGAL(Rho__courant ,BARY(Rho__relatif_au_centre_du_sommet_1 ,Rho__relatif_au_centre_du_sommet_2 ,lambda ) ); EGAL(Theta_courant ,BARY(Theta_relatif_au_centre_du_sommet_1 ,Theta_relatif_au_centre_du_sommet_2 ,lambda ) ); Test(IFEQ_a_peu_pres_absolu(Rho__courant,RAYON_DU_CERCLE,mgEPSILON)) Bblock Eblock ATes Bblock PRINT_ERREUR("le rayon interpole est incorrect en valeur absolue"); CAL1(Prer2("(Rayon=%f RayonInterpole=%f)\n" ,rayon_du_cercle ,Rho__courant ) ); Eblock ETes #undef RAYON_DU_CERCLE INITIALISATION_POINT_2D(point_intermediaire_interpole ,ADD2(ASD1(centre,x),Xcartesienne_2D(Rho__courant,Theta_courant)) ,ADD2(ASD1(centre,y),Ycartesienne_2D(Rho__courant,Theta_courant)) ); Test(IFEQ(compteur_des_repetitions_du_Repe,PREMIERE_ITERATION_D_UN_Repe)) Bblock Test(IFET(IFEQ_a_peu_pres_absolu(ASD1(point_intermediaire_interpole,x),ASD1(sommet_1,x),gEPSILON) ,IFEQ_a_peu_pres_absolu(ASD1(point_intermediaire_interpole,y),ASD1(sommet_1,y),gEPSILON) ) ) Bblock Eblock ATes Bblock PRINT_ERREUR("le premier point d'une chaine d'interpolation est incorrect"); CAL1(Prer4("(Sommet1={%f,%f} PremierPoint={%f,%f})\n" ,ASD1(sommet_1,x),ASD1(sommet_1,y) ,ASD1(point_intermediaire_interpole,x),ASD1(point_intermediaire_interpole,y) ) ); Eblock ETes Eblock ATes Bblock Eblock ETes Test(IFEQ(compteur_des_repetitions_du_Repe,nombre_de_pas)) Bblock Test(IFET(IFEQ_a_peu_pres_absolu(ASD1(point_intermediaire_interpole,x),ASD1(sommet_2,x),gEPSILON) ,IFEQ_a_peu_pres_absolu(ASD1(point_intermediaire_interpole,y),ASD1(sommet_2,y),gEPSILON) ) ) Bblock Eblock ATes Bblock PRINT_ERREUR("le dernier point d'une chaine d'interpolation est incorrect"); CAL1(Prer4("(Sommet2={%f,%f} DernierPoint={%f,%f})\n" ,ASD1(sommet_2,x),ASD1(sommet_2,y) ,ASD1(point_intermediaire_interpole,x),ASD1(point_intermediaire_interpole,y) ) ); Eblock ETes Eblock ATes Bblock Eblock ETes Test(IL_FAUT(editer_les_points_sous_la_forme_de_segments_AB)) Bblock Test(IFGT(compteur_des_repetitions_du_Repe,PREMIERE_ITERATION_D_UN_Repe)) Bblock CAL2(Prin0(" ")); EDITION_DES_COORDONNEES(ASD1(point_intermediaire_interpole,x) ,ASD1(point_intermediaire_interpole,y) ,TOUJOURS_VRAI ,"xB=%+.^^^ yB=%+.^^^" ,"xB=%d yB=%d" ," NumeroPolygone=%d Profondeur=%d" ); CAL2(Prin0("\n")); Eblock ATes Bblock Eblock ETes Test(IFLT(compteur_des_repetitions_du_Repe,nombre_de_pas)) Bblock EDITION_DES_COORDONNEES(ASD1(point_intermediaire_interpole,x) ,ASD1(point_intermediaire_interpole,y) ,TOUJOURS_VRAI ,"xA=%+.^^^ yA=%+.^^^" ,"xA=%d yA=%d" ," NumeroPolygone=%d Profondeur=%d" ); Eblock ATes Bblock Eblock ETes Eblock ATes Bblock EDITION_DES_COORDONNEES(ASD1(point_intermediaire_interpole,x) ,ASD1(point_intermediaire_interpole,y) ,TOUJOURS_VRAI ,"xA=%+.^^^ yA=%+.^^^" ,"xA=%d yA=%d" ," NumeroPolygone=%d Profondeur=%d" ); CAL2(Prin0("\n")); Eblock ETes Eblock ERep Eblock ETes Eblock EDoI Test(IZGT(profondeur)) Bblock DEFV(Float,INIT(diametre_du_polygone_1,F_MOINS_L_INFINI)); Test(IL_FAUT(compatibilite_2012060512)) /* Test introduit le 20120605121054... */ Bblock Eblock ATes Bblock DEFV(Int,INIT(numero_du_cote_courant_1_du_polygone_1,UNDEF)); DEFV(Int,INIT(numero_du_cote_courant_2_du_polygone_1,UNDEF)); DoIn(numero_du_cote_courant_1_du_polygone_1 ,PREMIER_COTE_D_UN_POLYGONE ,LSTX(PREMIER_COTE_D_UN_POLYGONE,nombre_de_cotes_du_polygone_fondamental) ,I ) Bblock DoIn(numero_du_cote_courant_2_du_polygone_1 ,PREMIER_COTE_D_UN_POLYGONE ,LSTX(PREMIER_COTE_D_UN_POLYGONE,nombre_de_cotes_du_polygone_fondamental) ,I ) Bblock EGAL(diametre_du_polygone_1 ,MAX2(RpdisF2D(ACCES_SOMMET(polygone_1,numero_du_cote_courant_1_du_polygone_1,IdTb1) ,ACCES_SOMMET(polygone_1,numero_du_cote_courant_2_du_polygone_1,IdTb1) ) ,diametre_du_polygone_1 ) ); Eblock EDoI Eblock EDoI Eblock ETes DoIn(numero_du_cote_courant_du_polygone_1 ,PREMIER_COTE_D_UN_POLYGONE ,LSTX(PREMIER_COTE_D_UN_POLYGONE,nombre_de_cotes_du_polygone_fondamental) ,I ) Bblock DEFV(Int,INIT(numero_du_cote_courant_du_polygone_2,UNDEF)); DEBUT_DE_DEFINITION_D_UN_POLYGONE(polygone_2); DoIn(numero_du_cote_courant_du_polygone_2 ,PREMIER_COTE_D_UN_POLYGONE ,LSTX(PREMIER_COTE_D_UN_POLYGONE,nombre_de_cotes_du_polygone_fondamental) ,I ) Bblock INVERSION_DU_CENTRE_D_UN_CERCLE(ACCES_CENTRE(polygone_2,numero_du_cote_courant_du_polygone_2,IdTb1) ,ACCES_RAYON_(polygone_2,numero_du_cote_courant_du_polygone_2,IdTb1) ,ACCES_CENTRE(polygone_1,numero_du_cote_courant_du_polygone_2,sITb0) ,ACCES_RAYON_(polygone_1,numero_du_cote_courant_du_polygone_2,sITb0) ,ACCES_CENTRE(polygone_1,numero_du_cote_courant_du_polygone_1,sITb0) ,ACCES_RAYON_(polygone_1,numero_du_cote_courant_du_polygone_1,sITb0) ); INVERSION_D_UN_POINT(ACCES_SOMMET(polygone_2,numero_du_cote_courant_du_polygone_2,IdTb1) ,ACCES_SOMMET(polygone_1,numero_du_cote_courant_du_polygone_2,sITb0) ,ACCES_CENTRE(polygone_1,numero_du_cote_courant_du_polygone_1,sITb0) ,ACCES_RAYON_(polygone_1,numero_du_cote_courant_du_polygone_1,sITb0) ); /* Generation d'un "polygone_2" par inversion du "polygone_1" par rapport a l'un de ses */ /* cotes de numero 'numero_du_cote_courant_du_polygone_1'. */ /* */ /* On notera que l'un de ses polygones "polygone_2" a ete deja ete genere mais, a un */ /* niveau 'profondeur_courante' inferieur (d'une unite...). */ Eblock EDoI DoIn(numero_du_cote_courant_du_polygone_2 ,PREMIER_COTE_D_UN_POLYGONE ,LSTX(PREMIER_COTE_D_UN_POLYGONE,nombre_de_cotes_du_polygone_fondamental) ,I ) Bblock DEFV(Float,INIT(distance_au_centre ,RpdisF2D(ACCES_SOMMET(polygone_2,numero_du_cote_courant_du_polygone_2,IdTb1) ,ACCES_CENTRE(polygone_2,numero_du_cote_courant_du_polygone_2,IdTb1) ) ) ); #define RAYON_COURANT \ ABSO(rayon_courant) DEFV(Float,INIT(rayon_courant,ACCES_RAYON_(polygone_2,numero_du_cote_courant_du_polygone_2,IdTb1))); /* Afin de verifier que l'inversion des cercles et des sommets s'est bien passee... */ Test(IFEQ_a_peu_pres_absolu(distance_au_centre,RAYON_COURANT,mgEPSILON)) Bblock Eblock ATes Bblock PRINT_ERREUR("une inversion des cercles et des sommets est incoherente en valeur absolue"); CAL1(Prer6("(Centre=(%f,%f) Rayon=%f Sommet=(%f,%f) DistanceAuCentre=%f)\n" ,ASD1(ACCES_CENTRE(polygone_2,numero_du_cote_courant_du_polygone_2,IdTb1),x) ,ASD1(ACCES_CENTRE(polygone_2,numero_du_cote_courant_du_polygone_2,IdTb1),y) ,rayon_courant ,ASD1(ACCES_SOMMET(polygone_2,numero_du_cote_courant_du_polygone_2,IdTb1),x) ,ASD1(ACCES_SOMMET(polygone_2,numero_du_cote_courant_du_polygone_2,IdTb1),y) ,distance_au_centre ) ); Eblock ETes #undef RAYON_COURANT Eblock EDoI begin_nouveau_block Bblock DEFV(Float,INIT(diametre_du_polygone_2,F_MOINS_L_INFINI)); Test(IL_FAUT(compatibilite_2012060512)) /* Test introduit le 20120605121054... */ Bblock Eblock ATes Bblock DEFV(Int,INIT(numero_du_cote_courant_1_du_polygone_2,UNDEF)); DEFV(Int,INIT(numero_du_cote_courant_2_du_polygone_2,UNDEF)); DoIn(numero_du_cote_courant_1_du_polygone_2 ,PREMIER_COTE_D_UN_POLYGONE ,LSTX(PREMIER_COTE_D_UN_POLYGONE,nombre_de_cotes_du_polygone_fondamental) ,I ) Bblock DoIn(numero_du_cote_courant_2_du_polygone_2 ,PREMIER_COTE_D_UN_POLYGONE ,LSTX(PREMIER_COTE_D_UN_POLYGONE,nombre_de_cotes_du_polygone_fondamental) ,I ) Bblock EGAL(diametre_du_polygone_2 ,MAX2(RpdisF2D(ACCES_SOMMET(polygone_2,numero_du_cote_courant_1_du_polygone_2,IdTb1) ,ACCES_SOMMET(polygone_2,numero_du_cote_courant_2_du_polygone_2,IdTb1) ) ,diametre_du_polygone_2 ) ); Eblock EDoI Eblock EDoI Eblock ETes Test(IFOU(IL_FAUT(compatibilite_2012060512) ,IFLT(diametre_du_polygone_2,diametre_du_polygone_1) ) ) Bblock /* Cas ou le 'polygone_2' est plus petit que le 'polygone_1' : on va le traiter.. */ CALS(InversionDUnPolygone(PRED(profondeur) ,liste_des_centres_des_cercles_des_cotes_du_polygone_2 ,liste_des_rayons_des_cercles_des_cotes_du_polygone_2 ,liste_des_sommets_du_polygone_2 ) ); /* Et cette operation est repetee recursivement. */ Eblock ATes Bblock /* Cas ou le 'polygone_2' est plus grand que le 'polygone_1' : on va l'ignorer car, */ /* en effet, l'inversion que reduire les polygones sauf dans le cas d'un 'polygone_2' */ /* appartenant a la generation precedente (et donc deja traite...). */ Eblock ETes Eblock end_nouveau_block FIN_DE_DEFINITION_D_UN_POLYGONE(polygone_2); Eblock EDoI Eblock ATes Bblock Eblock ETes DECR(profondeur_courante,I); RETU_ERROR; Eblock EFonctionI /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* G E N E R A T I O N D ' U N P A V A G E D U D I S Q U E D E P O I N C A R E : */ /* */ /*************************************************************************************************************************************/ BCommande(nombre_d_arguments,arguments) /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock /*..............................................................................................................................*/ GET_ARGUMENTSi(nombre_d_arguments ,BLOC(GET_ARGUMENT_L("compatibilite_2012060510=",compatibilite_2012060510); GET_ARGUMENT_L("compatibilite_2012060512=",compatibilite_2012060512); GET_ARGUMENT_L("editer_coordonnees=""coordonnees=",editer_les_coordonnees_des_points); GET_ARGUMENT_L("coordonnees_normalisees=""normalisees=""norm=" ,editer_les_coordonnees_normalisees_des_points ); GET_ARGUMENT_N("coordonnees_denormalisees=""denormalisees=""denorm=" ,editer_les_coordonnees_normalisees_des_points ); GET_ARGUMENT_L("segments_AB=""segments=""AB=" ,editer_les_points_sous_la_forme_de_segments_AB ); GET_ARGUMENT_N("points_isoles=""points=" ,editer_les_points_sous_la_forme_de_segments_AB ); GET_ARGUMENT_L("supprimer_segments_AB_redondants=""supprimer_redondants=""sr=" ,supprimer_les_segments_AB_redondants ); GET_ARGUMENT_N("conserver_segments_AB_redondants=""conserver_redondants=""cr=" ,supprimer_les_segments_AB_redondants ); /* Arguments introduits le 20120609093349... */ GET_ARGUMENT_L("interpoler_circulairement=""circulaire=""ic=" ,interpoler_circulairement_entre_les_sommets ); GET_ARGUMENT_N("ne_pas_interpoler_circulairement=""nic=" ,interpoler_circulairement_entre_les_sommets ); GET_ARGUMENT_F("facteur_nombre_pas=""fnp=",facteur_de_calcul_du_nombre_de_pas_angulaires); GET_ARGUMENT_L("rayons_negatifs_ou_nuls=""negatifs=""rnn=",avertir_dans_le_cas_de_rayons_negatifs_ou_nuls); GET_ARGUMENT_I("nombre_cotes=""cotes=""nc=""N=",nombre_de_cotes_du_polygone_fondamental); GET_ARGUMENT_I("angle_sommet=""angle=""as=""P=",angle_au_sommet_en_fraction_du_cercle_trigonometrique); GET_ARGUMENT_I("profondeur=""recursivite=",profondeur_du_disque_de_Poincare); ) ); Test(IFET(IL_FAUT(supprimer_les_segments_AB_redondants) ,IL_FAUT(interpoler_circulairement_entre_les_sommets) ) ) /* Test introduit le 20120609095528... */ Bblock PRINT_ERREUR("la suppression des segments 'AB' redondants est incompatible avec l'interpolation circulaire"); Eblock ATes Bblock Eblock ETes Test(IFLT(ADD2(INVE(nombre_de_cotes_du_polygone_fondamental),INVE(angle_au_sommet_en_fraction_du_cercle_trigonometrique)),FDU)) /* Ce test provient de la contrainte suivante. Soient : */ /* */ /* O : l'origine du plan, */ /* A : le centre du cercle dont un arc est l'un des cotes du polygone */ /* fondamental, */ /* B : l'un des deux sommets du cote evoque ci-dessus. */ /* */ /* On a alors : */ /* */ /* / \ pi */ /* AOB = ---- */ /* N */ /* */ /* / \ pi pi */ /* ABO = ---- + ---- */ /* 2 P */ /* */ /* d'ou : */ /* */ /* / \ / \ / \ pi pi pi 1 1 1 */ /* OAB = pi - (AOB + ABO) = pi -(---- + ---- + ----) = pi.(--- - --- - ---) */ /* N 2 P 2 N P */ /* */ /* cet angle ne pouvant qu'etre strictement positif, on a : */ /* */ /* 1 1 1 */ /* --- + --- < --- */ /* N P 2 */ /* */ Bblock DEFV(Float,INIT(rapportK,FLOT__UNDEF)); DEFV(Float,INIT(rayon_du_cercle_definissant_les_cotes_du_polygone_fondamental,FLOT__UNDEF)); DEFV(Float,INIT(longueur_du_cote_OA,FLOT__UNDEF)); DEFV(Float,INIT(longueur_du_cote_OB,FLOT__UNDEF)); DEFV(Int,INIT(numero_du_cote_courant_du_polygone_fondamental,UNDEF)); DEBUT_DE_DEFINITION_D_UN_POLYGONE(polygone_fondamental); EGAL(demi_angle_au_centre_du_polygone_fondamental,DIVI(PI,nombre_de_cotes_du_polygone_fondamental)); EGAL(demi_angle_au_sommet_du_polygone_fondamental,DIVI(PI,angle_au_sommet_en_fraction_du_cercle_trigonometrique)); EGAL(rapportK ,EXP2(DIVI(SINX(demi_angle_au_centre_du_polygone_fondamental) ,COSX(demi_angle_au_sommet_du_polygone_fondamental) ) ) ); EGAL(rayon_du_cercle_definissant_les_cotes_du_polygone_fondamental,RACX(DIVI(rapportK,COMP(rapportK)))); /* Le cercle de centre A (de rayon R) est orthogonal au cercle trigonometrique (de rayon 1). */ /* Ces deux cercles se coupent en deux points dont C. Le theoreme de Pythagore donne : */ /* */ /* 2 2 2 */ /* OA = OC + CA */ /* */ /* 2 2 2 */ /* OA = 1 + R */ /* */ /* La resolution du triangle OAB donne : */ /* */ /* / \ */ /* OA.sin(AOB) */ /* AB = -------------- */ /* / \ / \ */ /* sin(AOB+OAB) */ /* */ /* or : */ /* */ /* AB = R */ /* */ /* d'ou : */ /* */ /* _______ */ /* / 2 pi */ /* \/ 1 + R .sin(----) */ /* N */ /* R = ---------------------- */ /* pi pi */ /* sin(---- - ----) */ /* 2 P */ /* */ /* d'ou finalement : */ /* */ /* ______ */ /* / K */ /* R = \/ ----- */ /* 1-K */ /* */ /* avec : */ /* */ /* / pi \2 */ /* | sin(----) | */ /* | N | */ /* K =| -----------| */ /* | pi | */ /* | cos(----) | */ /* \ P / */ /* */ EGAL(longueur_du_cote_OA ,GpytF2D(RAYON_DU_CERCLE_TRIGONOMETRIQUE,rayon_du_cercle_definissant_les_cotes_du_polygone_fondamental) ); EGAL(longueur_du_cote_OB ,MUL2(longueur_du_cote_OA ,DIVI(COSX(ADD2(demi_angle_au_centre_du_polygone_fondamental ,demi_angle_au_sommet_du_polygone_fondamental ) ) ,COSX(demi_angle_au_sommet_du_polygone_fondamental) ) ) ); DoIn(numero_du_cote_courant_du_polygone_fondamental ,PREMIER_COTE_D_UN_POLYGONE ,LSTX(PREMIER_COTE_D_UN_POLYGONE,nombre_de_cotes_du_polygone_fondamental) ,I ) Bblock INITIALISATION_POINT_2D(ACCES_SOMMET(polygone_fondamental,numero_du_cote_courant_du_polygone_fondamental,IdTb1) ,Xcartesienne_2D(longueur_du_cote_OB ,ADD2(ADD2(demi_angle_au_centre_du_polygone_fondamental ,INCLINAISON_GENERALE_DU_POLYGONE_FONDAMENTAL ) ,MUL2(SOUS(numero_du_cote_courant_du_polygone_fondamental ,PREMIER_COTE_D_UN_POLYGONE ) ,DOUB(demi_angle_au_centre_du_polygone_fondamental) ) ) ) ,Ycartesienne_2D(longueur_du_cote_OB ,ADD2(ADD2(demi_angle_au_centre_du_polygone_fondamental ,INCLINAISON_GENERALE_DU_POLYGONE_FONDAMENTAL ) ,MUL2(SOUS(numero_du_cote_courant_du_polygone_fondamental ,PREMIER_COTE_D_UN_POLYGONE ) ,DOUB(demi_angle_au_centre_du_polygone_fondamental) ) ) ) ); INITIALISATION_POINT_2D(ACCES_CENTRE(polygone_fondamental,numero_du_cote_courant_du_polygone_fondamental,IdTb1) ,Xcartesienne_2D(longueur_du_cote_OA ,ADD2(INCLINAISON_GENERALE_DU_POLYGONE_FONDAMENTAL ,MUL2(SOUS(numero_du_cote_courant_du_polygone_fondamental ,PREMIER_COTE_D_UN_POLYGONE ) ,DOUB(demi_angle_au_centre_du_polygone_fondamental) ) ) ) ,Ycartesienne_2D(longueur_du_cote_OA ,ADD2(INCLINAISON_GENERALE_DU_POLYGONE_FONDAMENTAL ,MUL2(SOUS(numero_du_cote_courant_du_polygone_fondamental ,PREMIER_COTE_D_UN_POLYGONE ) ,DOUB(demi_angle_au_centre_du_polygone_fondamental) ) ) ) ); EGAL(ACCES_RAYON_(polygone_fondamental,numero_du_cote_courant_du_polygone_fondamental,IdTb1) ,rayon_du_cercle_definissant_les_cotes_du_polygone_fondamental ); Eblock EDoI Test(IZGT(profondeur_du_disque_de_Poincare)) Bblock CALS(InversionDUnPolygone(PRED(profondeur_du_disque_de_Poincare) ,liste_des_centres_des_cercles_des_cotes_du_polygone_fondamental ,liste_des_rayons_des_cercles_des_cotes_du_polygone_fondamental ,liste_des_sommets_du_polygone_fondamental ) ); /* Inversion du polygone fondamental. */ /* */ /* Le 'PRED(profondeur_du_disque_de_Poincare)' peut paraitre inutile mais il est fait par */ /* "symetrie" avec ce qui est fait dans 'v $xci/valeurs_Hilbert2D$K REGLE_LEFT___', par */ /* exemple... */ Eblock ATes Bblock Eblock ETes FIN_DE_DEFINITION_D_UN_POLYGONE(polygone_fondamental); Eblock ATes Bblock PRINT_ERREUR("la definition du polygone fondamental est impossible"); CAL1(Prer4("((1/(N=%d))+(1/(P=%d))=%f >= %f)\n" ,nombre_de_cotes_du_polygone_fondamental ,angle_au_sommet_en_fraction_du_cercle_trigonometrique ,ADD2(INVE(nombre_de_cotes_du_polygone_fondamental),INVE(angle_au_sommet_en_fraction_du_cercle_trigonometrique)) ,FDU ) ); Eblock ETes RETU_Commande; Eblock ECommande