/*************************************************************************************************************************************/ /* */ /* C A L C U L D E T O U T E S L E S D I S T A N C E S 2 A 2 D A N S */ /* U N E N S E M B L E D E P O I N T S { X , Y , Z } : */ /* */ /* */ /* Author of '$xrv/distance.02$K' : */ /* */ /* Jean-Francois COLONNA (LACTAMME, 20000522115636). */ /* */ /*************************************************************************************************************************************/ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* 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 : */ /* */ /*************************************************************************************************************************************/ /* Le 20080311163442, fut supprime : */ /* */ /* @define PRAGMA_CL_____MODULE_NON_OPTIMISABLE */ /* */ /* qui semblait inutile... */ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* F I C H I E R S D ' I N C L U D E S : */ /* */ /*************************************************************************************************************************************/ #include INCLUDES_BASE /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* V A L E U R S I M P L I C I T E S D E S P A R A M E T R E S : */ /* */ /*************************************************************************************************************************************/ #define EDITER_LES_N_PREMIERS_VOISINS \ FAUX #define NOMBRE_DE_PREMIERS_VOISINS \ TROIS #define TRIER_LES_INDEX_DES_PREMIERS_VOISINS \ VRAI #define EDITER_LES_COORDONNEES_DES_POINTS_LORSQU_IL_Y_A_TRI_DES_PREMIERS_VOISINS \ FAUX #define METTRE_LES_POINTS_DANS_LE_BON_ORDRE_LORSQU_IL_Y_A_TRI_DES_PREMIERS_VOISINS \ FAUX /* Doit-on n'editer que les 'N' premiers voisins ('VRAI') ou bien editer quasiment tous */ /* couples {I,J} ('FAUX') suivant 'IL_FAUT(editer_tous_les_couples_IJ)' ? D'autre part, */ /* doit-on editer les couples {I,J} des premiers voisins quel que soit leur ordre ('FAUX') */ /* ou bien en respectant le critere de tri I<J ('VRAI') ? On notera au passage que cette */ /* option ('TRIER_LES_INDEX_DES_PREMIERS_VOISINS') a ete introduite le 20011014091311 */ /* afin d'optimiser 'v $xiirs/.PSPH.21.1.$U 20011014091311' et eliminer la redondance */ /* des couples... */ /* */ /* Le 20051201133356 a ete introduit la possibilite d'editer (en plus des index) les */ /* coordonnees des points lorsque 'IL_FAUT(editer_les_N_premiers_voisins)'... */ /* */ /* Le 20051203100941,la possibilite de lister les points {I,J} dans le bon ordre, lorsque */ /* 'IL_FAUT(editer_les_coordonnees_des_points_lorsqu_il_y_a_tri_des_premiers_voisins)', a */ /* a ete introduite... */ #define EDITER_TOUS_LES_COUPLES_IJ \ VRAI \ /* Doit-on editer tous les couples {I,J} ('VRAI') ou bien n'editer ceux pour lesquels */ \ /* I<J strictement ('FAUX') ? */ #define FILTRER_LES_DISTANCES \ FAUX #define BORNE_INFERIEURE_DES_DISTANCES \ FZERO #define BORNE_SUPERIEURE_DES_DISTANCES \ F_INFINI /* Doit-on filtrer dans [inf,sup] les distances ('VRAI') ou pas ('FAUX') ? Les valeurs par */ /* defaut garantissent la compatibilite anterieure. Cela fut introduit le 20161109083817 */ #define AMPLITUDE_DE_LA_TRANSLATION_DES_INDEX_DES_POINTS \ PREMIER_ELEMENT_D_UN_FICHIER \ /* Translation des index des points lors de leur edition. Ceci a ete introduit le */ \ /* 20011011112017 car, en effet, '$xrv/distance.02$K' utilise : */ \ /* */ \ /* 1-'gELEMENT_DU_FICHIER(...)', pour lequel le premier element vaut : */ \ /* */ \ /* PREMIER_ELEMENT_D_UN_FICHIER = INDEX0 = ZERO */ \ /* */ \ /* qui ne peut utiliser 'Komp(...)' et demande donc une gestion de type 'DoIn(...)' en */ \ /* precisant le premier element en tant qu'argument du 'DoIn(...)' (et valant donc 'ZERO'). */ \ /* Alors que de nombreux programmes gerant des points ('v $xrv/particule.10$K ACCES_LISTE' */ \ /* par exemple) utilisent : */ \ /* */ \ /* 2-'ACCES_LISTE(...)', pour lequel le premier element vaut : */ \ /* */ \ /* PREMIER_POINT_DES_LISTES = PREMIER_POINT = PREMIERE_ITERATION_D_UN_Komp = UN */ \ /* */ \ /* qui est donc adapte a une gestion de type 'Komp(...)' ou le premier element est defini */ \ /* implicitement (et vaut donc 'UN')... */ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* D E F I N I T I O N D E S F I C H I E R S : */ /* */ /*************************************************************************************************************************************/ #define NOMBRE_MAXIMAL_D_ELEMENTS_DANS_LE_FICHIER \ GRO1(MILLE) \ /* En prevision d'une matrice memorisant les distances 2 a 2... */ #include xrv/ARITHMET.1d.I" /* Passage a l'allocation dynamique le 20060214190521... */ #include xrv/ARITHMET.21.I" #include xrk/attractor.12.I" #include xrv/champs_5.11.I" #define X_IMPLICITE \ FZERO #define Y_IMPLICITE \ FZERO #define Z_IMPLICITE \ FZERO gGENERATION_D_UN_FICHIER(fichier_LISTE_X,liste_initiale_des_X); gGENERATION_D_UN_FICHIER(fichier_LISTE_Y,liste_initiale_des_Y); gGENERATION_D_UN_FICHIER(fichier_LISTE_Z,liste_initiale_des_Z); /* Definition en memoire des fichiers de coordonnees cartesiennes. */ #define ELEMENT_DU_FICHIER_LISTE_X(index) \ gELEMENT_DU_FICHIER(liste_initiale_des_X,index) #define ELEMENT_DU_FICHIER_LISTE_Y(index) \ gELEMENT_DU_FICHIER(liste_initiale_des_Y,index) #define ELEMENT_DU_FICHIER_LISTE_Z(index) \ gELEMENT_DU_FICHIER(liste_initiale_des_Z,index) /* Acces a un element courant des fichiers de coordonnees cartesiennes. */ #define VOISIN_IMPLICITE \ FLOT(AUTORISE) gGENERATION_D_UN_FICHIER(fichier_LISTE_VOISIN,liste_initiale_des_VOISIN); /* Definition en memoire des fichiers des "autorisations" de voisinnage (ceci fut */ /* introduit le 20051206093616). Pour chaque point 'I', on va disposer (si cela est */ /* demande via 'IL_FAUT(editer_les_N_premiers_voisins)') de la liste triee par distances */ /* croissantes des voisins {J} du point 'I'. La liste 'liste_initiale_des_VOISIN' */ /* permet de selectionner les voisins a editer dans cette liste. On notera que le */ /* point 'J' d'index 0 est le point 'I' lui-meme et donc la premiere entree du fichier */ /* 'liste_initiale_des_VOISIN' n'est pas utilisee ; on verra a ce propos le test : */ /* */ /* Test(IFNE(indexI,index_J_trie)) */ /* */ /* ci-apres qui fait que les couples de type {I,I} sont ignores lors de l'edition des */ /* premiers voisins... */ #define ELEMENT_DU_FICHIER_LISTE_VOISIN(index) \ LOGI(gELEMENT_DU_FICHIER(liste_initiale_des_VOISIN,index)) /* Acces a un element courant des fichiers des "autorisations" de voisinnage. */ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* M A C R O S U T I L E S : */ /* */ /*************************************************************************************************************************************/ #define TRANSLATION_DES_INDEX_DES_POINTS(index) \ CONX(index,PREMIER_ELEMENT_D_UN_FICHIER,amplitude_de_la_translation_des_index_des_points) \ /* Translation des index des points lors de leur edition. */ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C A L C U L D E T O U T E S L E S D I S T A N C E S 2 A 2 D A N S */ /* U N E N S E M B L E D E P O I N T S { X , Y , Z } : */ /* */ /*************************************************************************************************************************************/ BCommande(nombre_d_arguments,arguments) /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock #include xrv/ARITHMET.22.I" DEFV(Logical,INIT(editer_les_N_premiers_voisins,EDITER_LES_N_PREMIERS_VOISINS)); DEFV(Positive,INIT(nombre_de_premiers_voisins,NOMBRE_DE_PREMIERS_VOISINS)); DEFV(Logical,INIT(trier_les_index_des_premiers_voisins,TRIER_LES_INDEX_DES_PREMIERS_VOISINS)); DEFV(Logical,INIT(editer_les_coordonnees_des_points_lorsqu_il_y_a_tri_des_premiers_voisins ,EDITER_LES_COORDONNEES_DES_POINTS_LORSQU_IL_Y_A_TRI_DES_PREMIERS_VOISINS ) ); DEFV(Logical,INIT(mettre_les_points_dans_le_bon_ordre_lorsqu_il_y_a_tri_des_premiers_voisins ,METTRE_LES_POINTS_DANS_LE_BON_ORDRE_LORSQU_IL_Y_A_TRI_DES_PREMIERS_VOISINS ) ); /* Doit-on n'editer que les 'N' premiers voisins ('VRAI') ou bien editer quasiment tous */ /* couples {I,J} ('FAUX') suivant 'IL_FAUT(editer_tous_les_couples_IJ)' ? D'autre part, */ /* doit-on editer les couples {I,J} des premiers voisins quel que soit leur ordre ('FAUX') */ /* ou bien en respectant le critere de tri I<J ('VRAI') ? On notera au passage que cette */ /* option ('TRIER_LES_INDEX_DES_PREMIERS_VOISINS') a ete introduite le 20011014091311 */ /* afin d'optimiser 'v $xiirs/.PSPH.21.1.$U 20011014091311' et eliminer la redondance */ /* des couples... */ /* */ /* Le 20051201133356 a ete introduit la possibilite d'editer (en plus des index) les */ /* coordonnees des points lorsque 'IL_FAUT(editer_les_N_premiers_voisins)'... */ /* */ /* Le 20051203100941,la possibilite de lister les points {I,J} dans le bon ordre, lorsque */ /* 'IL_FAUT(editer_les_coordonnees_des_points_lorsqu_il_y_a_tri_des_premiers_voisins)', a */ /* a ete introduite... */ DEFV(Logical,INIT(editer_tous_les_couples_IJ,EDITER_TOUS_LES_COUPLES_IJ)); /* Doit-on editer tous les couples {I,J} ('VRAI') ou bien n'editer ceux pour lesquels */ /* I<J strictement ('FAUX') ? */ DEFV(Logical,INIT(filtrer_les_distances,FILTRER_LES_DISTANCES)); DEFV(Float,INIT(borne_inferieure_des_distances,BORNE_INFERIEURE_DES_DISTANCES)); DEFV(Float,INIT(borne_superieure_des_distances,BORNE_SUPERIEURE_DES_DISTANCES)); /* Doit-on filtrer dans [inf,sup] les distances ('VRAI') ou pas ('FAUX') ? Les valeurs par */ /* defaut garantissent la compatibilite anterieure. Cela fut introduit le 20161109083817 */ DEFV(Int,INIT(amplitude_de_la_translation_des_index_des_points,AMPLITUDE_DE_LA_TRANSLATION_DES_INDEX_DES_POINTS)); /* Translation des index des points lors de leur edition. Ceci a ete introduit le */ /* 20011011112017 car, en effet, '$xrv/distance.02$K' utilise : */ /* */ /* 1-'gELEMENT_DU_FICHIER(...)', pour lequel le premier element vaut : */ /* */ /* PREMIER_ELEMENT_D_UN_FICHIER=INDEX0=ZERO */ /* */ /* qui ne peut utiliser 'Komp(...)' et demande donc une gestion de type 'DoIn(...)' en */ /* precisant le premier element en tant qu'argument du 'DoIn(...)' (et valant donc 'ZERO'). */ /* Alors que de nombreux programmes gerant des points ('v $xrv/particule.10$K ACCES_LISTE' */ /* par exemple) utilisent : */ /* */ /* 2-'ACCES_LISTE(...)', pour lequel le premier element vaut : */ /* */ /* PREMIER_POINT_DES_LISTES=PREMIER_POINT=PREMIERE_ITERATION_D_UN_Komp=UN */ /* */ /* qui est donc adapte a une gestion de type 'Komp(...)' ou le premier element est defini */ /* implicitement (et vaut donc 'UN')... */ DEFV(Int,INIT(indexI,UNDEF)); DEFV(Int,INIT(indexJ,UNDEF)); /* Index des elements courants dans les fichiers pour calculer les distances {I,J}. */ DEFV(Int,INIT(compteur_des_distances,ZERO)); /* Compteur des distances destine a editer eventuellement un message d'avertissement */ /* (introduit le 20161109120606)... */ /*..............................................................................................................................*/ GET_ARGUMENTS_(nombre_d_arguments ,BLOC(PROCESS_ARGUMENT_I("nombre_elements=""ne=",nombre_d_elements ,BLOC(VIDE;) ,BLOC(Bblock PRINT_AVERTISSEMENT("'ne=' doit etre defini avant toute entree de fichiers"); Eblock ) ); PROCESS_ARGUMENTS_DE_DEFINITION_DES_FICHIERS_01; PROKESF_ARGUMENT_FICHIER("LISTE_X=" ,fichier_LISTE_X ,liste_initiale_des_X ,X_IMPLICITE ,lTRANSFORMAT_0d ,iGENERATION_D_UN_FICHIER ); PROKESF_ARGUMENT_FICHIER("LISTE_Y=" ,fichier_LISTE_Y ,liste_initiale_des_Y ,Y_IMPLICITE ,lTRANSFORMAT_0d ,iGENERATION_D_UN_FICHIER ); PROKESF_ARGUMENT_FICHIER("LISTE_Z=" ,fichier_LISTE_Z ,liste_initiale_des_Z ,Z_IMPLICITE ,lTRANSFORMAT_0d ,iGENERATION_D_UN_FICHIER ); PROKESF_ARGUMENT_FICHIER("LISTE_VOISIN=" ,fichier_LISTE_VOISIN ,liste_initiale_des_VOISIN ,VOISIN_IMPLICITE ,lTRANSFORMAT_0d ,iGENERATION_D_UN_FICHIER ); GET_ARGUMENT_L("pv=""premiers_voisins=",editer_les_N_premiers_voisins); GET_ARGUMENT_I("N=",nombre_de_premiers_voisins); GET_ARGUMENT_L("tri=",trier_les_index_des_premiers_voisins); GET_ARGUMENT_L("editer_coordonnees_si_tri=""ecst=""coordonnees=" ,editer_les_coordonnees_des_points_lorsqu_il_y_a_tri_des_premiers_voisins ); GET_ARGUMENT_L("bost=""bon_ordre_des_points_si_tri=""bon_ordre=" ,mettre_les_points_dans_le_bon_ordre_lorsqu_il_y_a_tri_des_premiers_voisins ); GET_ARGUMENT_L("tri_N2=""N_carre=""N_au_carre=""N_AU_CARRE=""N2=" ,utiliser_le_tri_d_une_liste_quelconque_VERSION_N_AU_CARRE ); GET_ARGUMENT_N("tri_NlogN=""NlN=""N_log_N=""N1=",utiliser_le_tri_d_une_liste_quelconque_VERSION_N_AU_CARRE); /* Les parametres "N_log_N=", "N_log_N",... ont ete introduits le 20111028201026... */ GET_ARGUMENT_L("IFGT_N_carre=""IFGT_N_au_carre=""IFGT_N_AU_CARRE=""IFGT_N2=" ,TRI_D_UNE_LISTE_QUELCONQUE_VERSION_N_AU_CARRE_____faire_un_IFGT ); GET_ARGUMENT_L("message_N_carre=""message_N_au_carre=""message_N_AU_CARRE=""mN2=" ,TRI_D_UNE_LISTE_QUELCONQUE_VERSION_N_AU_CARRE_____editer_le_message_de_duree_excessive ); /* Arguments introduits le 20120509095215... */ GET_ARGUMENT_L("tousIJ=""tous=""IJ=",editer_tous_les_couples_IJ); GET_ARGUMENT_L("filtrer_distances=""fd=",filtrer_les_distances); GET_ARGUMENT_F("borne_inferieure_distances=""bid=",borne_inferieure_des_distances); GET_ARGUMENT_F("borne_superieure_distances=""bsd=",borne_superieure_des_distances); /* Arguments introduits le 20161109083817... */ GET_ARGUMENT_I("translation=""t=",amplitude_de_la_translation_des_index_des_points); ) ); Test(IFGE(nombre_de_premiers_voisins,nombre_d_elements)) Bblock EGAL(nombre_de_premiers_voisins,PRED(nombre_d_elements)); /* Introduit le 20051206101606 car, en effet, cela manquait par erreur... */ PRINT_ATTENTION("le nombre de premiers voisins est trop grand par rapport au nombre de points"); CAL1(Prer1("(la valeur maximale (%d) va donc etre utilisee)\n",nombre_de_premiers_voisins)); Eblock ATes Bblock Eblock ETes Test(IL_FAUT(editer_les_N_premiers_voisins)) Bblock DEFV(Logical,INIT(au_moins_un_voisin_est_autorise,FAUX)); /* Ce test de validation de 'liste_initiale_des_VOISIN' a ete introduit le 20051206101606. */ DoIn(indexI ,SUCC(PREMIER_ELEMENT_D_UN_FICHIER) ,DERNIER_ELEMENT_D_UN_FICHIER ,I ) /* Le 'SUCC(...)' est destine a prendre en compte le fait que le premier point (d'index 0) */ /* de la liste 'liste_initiale_des_VOISIN' correspond aux couples de type {I,I} lors du */ /* calcul des distances 2 a 2 ... */ Bblock Test(EST_AUTORISE(ELEMENT_DU_FICHIER_LISTE_VOISIN(indexI))) Bblock EGAL(au_moins_un_voisin_est_autorise,VRAI); Eblock ATes Bblock Eblock ETes Eblock EDoI Test(EST_FAUX(au_moins_un_voisin_est_autorise)) Bblock PRINT_ATTENTION("aucun voisin n'est autorise (le premier element etant ignore), on les autorise donc tous"); iGENERATION_D_UN_FICHIER(liste_initiale_des_VOISIN,VOISIN_IMPLICITE); Eblock ATes Bblock Eblock ETes Eblock ATes Bblock Eblock ETes DoIn(indexI ,PREMIER_ELEMENT_D_UN_FICHIER ,DERNIER_ELEMENT_D_UN_FICHIER ,I ) Bblock DEFV(Float,INIT(coordonnee_XI,ELEMENT_DU_FICHIER_LISTE_X(indexI))); DEFV(Float,INIT(coordonnee_YI,ELEMENT_DU_FICHIER_LISTE_Y(indexI))); DEFV(Float,INIT(coordonnee_ZI,ELEMENT_DU_FICHIER_LISTE_Z(indexI))); /* Recuperation des coordonnees {X,Y,Z} courantes du point 'I' dans les fichiers. */ gGENERATION_D_UN_FICHIER_liste(liste_des_points); gGENERATION_D_UN_FICHIER_liste(liste_des_distances_du_point_I_aux_points_J); /* Liste des distances du point 'I' (fixe) aux points 'J' variables. */ iGENERATION_D_UN_FICHIER(liste_des_points,FLOT__UNDEF); iGENERATION_D_UN_FICHIER(liste_des_distances_du_point_I_aux_points_J,FLOT__UNDEF); /* Ceci est rendu obligatoire par l'allocation dynamique de la memoire (le 20060214190521). */ /* Dans la boucle 'DoIn(...)' qui suit on va rechercher les 'nombre_de_premiers_voisins' */ /* d'index 'indexJ' du point courant d'index 'indexI'. On notera que cela ne donne pas */ /* toujours le resultat "global" que l'on attend comme cela s'est vu aux environs du */ /* 20180828152255. Ainsi, lors de la generation de l'image 'v $xiirs/PSPH.B5.1.20' en */ /* choisissant '_____NPoints=3', le point d'index 4 (en tant que 'indexI' ou 'indexJ') */ /* se retrouve plus de 3 fois : */ /* */ /* */ /* indexJ=4 */ /* couple={0,4} distance=+0.792554635397115126 */ /* */ /* indexJ=4 */ /* couple={1,4} distance=+0.794813519138595659 */ /* */ /* indexJ=4 */ /* couple={2,4} distance=+0.798600008488370872 */ /* */ /* indexI=4 */ /* couple={4,0} distance=+0.792554635397115126 */ /* couple={4,1} distance=+0.794813519138595659 */ /* couple={4,13} distance=+0.796233061158463595 */ /* */ /* indexJ=4 */ /* couple={11,4} distance=+0.816106796257996314 */ /* */ /* indexJ=4 */ /* couple={13,4} distance=+0.796233061158463595 */ /* */ /* */ /* et ainsi, le point d'index 4 semble avoir 5 plus proches voisins, soit : */ /* */ /* couple ={0,4} = {4,0} 0 vrai 3-proche voisin */ /* couple ={1,4} = {4,1} 1 vrai 3-proche voisin */ /* couple ={2,4} 2 */ /* couple ={11,4} 11 */ /* couple ={4,13} = {13,4} 13 vrai 3-proche voisin */ /* */ /* et non pas 3 (=$_____NPoints) ! Et c'est cela qui fait que l'on voit certains points */ /* connectes a plus de 3 autres (dont le point 4 qui est donc connecte a 5 autres...). */ /* */ /* Que faire ? Je crois qu'il n'y a pas de solution pour le moment car, en effet, pour */ /* reprendre le cas precedent, on ne peut pas eliminer le couple {2,4} car, en effet, le */ /* point 4 est bien un 3-proche voisin du point 2, alors que le point 2 n'est pas un */ /* un 3-proche voisin du point 4... */ /* */ /* Moralite : la notion de "N-proche voisin" ne "commute" pas... */ DoIn(indexJ ,PREMIER_ELEMENT_D_UN_FICHIER ,DERNIER_ELEMENT_D_UN_FICHIER ,I ) Bblock /* Les donnees qui suivent pourraient etre evidemment apres le 'Test(...)' relatif a */ /* 'editer_tous_les_couples_IJ', mais en fait cette localisation peu optimisee a priori */ /* est en prevision d'une matrice memorisant les distances 2 a 2... */ DEFV(Float,INIT(coordonnee_XJ,ELEMENT_DU_FICHIER_LISTE_X(indexJ))); DEFV(Float,INIT(coordonnee_YJ,ELEMENT_DU_FICHIER_LISTE_Y(indexJ))); DEFV(Float,INIT(coordonnee_ZJ,ELEMENT_DU_FICHIER_LISTE_Z(indexJ))); /* Recuperation des coordonnees {X,Y,Z} courantes du point 'J' dans les fichiers. */ DEFV(Float,INIT(distance_IJ ,RdisF3D(coordonnee_XI,coordonnee_YI,coordonnee_ZI ,coordonnee_XJ,coordonnee_YJ,coordonnee_ZJ ) ) ); /* Calcul de la distance des points {I,J}. */ Test(IL_FAUT(editer_les_N_premiers_voisins)) Bblock EGAL(gELEMENT_DU_FICHIER(liste_des_points,indexJ),FLOT(indexJ)); EGAL(gELEMENT_DU_FICHIER(liste_des_distances_du_point_I_aux_points_J,indexJ),distance_IJ); Eblock ATes Bblock Test(IFOU(IL_FAUT(editer_tous_les_couples_IJ) ,IFET(IL_NE_FAUT_PAS(editer_tous_les_couples_IJ) ,IFLT(indexI,indexJ) ) ) ) Bblock Test(IFOU(IL_NE_FAUT_PAS(filtrer_les_distances) ,IFET(IL_FAUT(filtrer_les_distances) ,IFINff(distance_IJ,borne_inferieure_des_distances,borne_superieure_des_distances) ) ) ) /* Possibilite introduite le 20161109083817... */ Bblock CAL2(Prin2(" couple={%d,%d}" ,TRANSLATION_DES_INDEX_DES_POINTS(indexI) ,TRANSLATION_DES_INDEX_DES_POINTS(indexJ) ) ); /* On notera (le 20040128142430) que lorsque 'IL_FAUT(trier_les_index_des_premiers_voisins)' */ /* l'index du premier element d'un couple est inferieur a celui du second element. D'autre */ /* part, il est tout a fait logique dans ces memes circonstances de trouver en double */ /* certaines lignes ; elles correspondent alors que fait que : */ /* */ /* DISTANCE(i,j) = DISTANCE(j,i) */ /* */ /* et que faisant un tri des {i,j} et en supposant que i<j, on sort donc deux fois la */ /* ligne 'couple={i,j}' (mais pas la ligne 'couple={j,i}'). Cela ne se produira evidemment */ /* pas si 'IL_FAUT(editer_les_N_premiers_voisins)' et que l'une ou les deux de ce lignes */ /* sont alors eliminees... */ CAL2(Prin3(" pointI={%+.^^^,%+.^^^,%+.^^^}",coordonnee_XI,coordonnee_YI,coordonnee_ZI)); CAL2(Prin3(" pointJ={%+.^^^,%+.^^^,%+.^^^}",coordonnee_XJ,coordonnee_YJ,coordonnee_ZJ)); CAL2(Prin1(" distance=%+.^^^",distance_IJ)); CAL2(Prin0("\n")); /* Edition de la distance des points {I,J}. */ /* */ /* Le 20060105152121, le format "16g" est passe a "^^g" pour plus de souplesse... */ /* */ /* Le 20091123123539, le format "^^g" est passe a "^^^" pour plus de souplesse... */ INCR(compteur_des_distances,I); /* Introduit le 20161109120606... */ Eblock ATes Bblock Eblock ETes Eblock ATes Bblock Eblock ETes Eblock ETes Eblock EDoI Test(IL_FAUT(editer_les_N_premiers_voisins)) Bblock TRI_D_UNE_LISTE_QUELCONQUE(liste_des_distances_du_point_I_aux_points_J ,liste_des_points ,PREMIER_ELEMENT_D_UN_FICHIER ,NEUT(DERNIER_ELEMENT_D_UN_FICHIER) ,EST_CE_LE_TRI_AUTOMATIQUE_D_UNE_LISTE_QUELCONQUE ,utiliser_le_tri_d_une_liste_quelconque_VERSION_N_AU_CARRE ,gELEMENT_DU_FICHIER ); /* Tri des distances du point 'I' (fixe) aux points 'J' variables. */ /* */ /* Le 20020828170851 j'ai fait en sorte que l'argument '????_dernier_element' des */ /* procedures de tri pointe bien sur le dernier element de la liste et non pas sur son */ /* successeur, d'ou le remplacement des operateurs 'SUCC(...)' par des 'NEUT(...)' (voir */ /* a ce propos 'v $ximd/operator.1$FON 20020828170851'). */ /* */ /* L'argument 'EST_CE_LE_TRI_AUTOMATIQUE_D_UNE_LISTE_QUELCONQUE' a ete introduit le */ /* 20170608103553... */ DoIn(indexJ ,PREMIER_ELEMENT_D_UN_FICHIER ,LSTX(PREMIER_ELEMENT_D_UN_FICHIER,MIN2(SUCC(nombre_de_premiers_voisins),nombre_d_elements)) ,I ) /* Le 'SUCC(...)' est destine a prendre en compte le couple {I,I} pour lequel la distance */ /* est minimale (nulle...). */ Bblock DEFV(Int,INIT(index_J_trie,INTE(gELEMENT_DU_FICHIER(liste_des_points,indexJ)))); Test(EST_AUTORISE(ELEMENT_DU_FICHIER_LISTE_VOISIN(indexJ))) Bblock /* Test introduit le 20051206093616 afin de pouvoir selectionner de facon individuelle */ /* les voisins a editer. ATTENTION : c'est 'indexJ' et non point 'index_J_trie' qu'il */ /* faut utiliser ici car, en effet, on cherche a tester les couples {I,J} par distances */ /* croissantes... */ Test(IFNE(indexI,index_J_trie)) Bblock DEFV(Int,INIT(premier_index ,COND(IL_FAUT(trier_les_index_des_premiers_voisins) ,MIN2(indexI,index_J_trie) ,indexI ) ) ); DEFV(Int,INIT(second_index ,COND(IL_FAUT(trier_les_index_des_premiers_voisins) ,MAX2(indexI,index_J_trie) ,index_J_trie ) ) ); CAL2(Prin2(" couple={%d,%d}" ,TRANSLATION_DES_INDEX_DES_POINTS(premier_index) ,TRANSLATION_DES_INDEX_DES_POINTS(second_index) ) ); /* On rappelle le 20080224180559 que si 'IL_FAUT(trier_les_index_des_premiers_voisins)', */ /* il y a alors frequemment des couples qui sortent en double (par exemple {I,J} et {I,J} */ /* avec I<J, provenant donc de {I,J} et {J,I}). Cela justifie donc les '$SOR -u's faits */ /* ulterieurement apres ces sorties ('v $xiirs/.PSPH.21.1.$U ListeCouples' par exemple...). */ Test(IL_FAUT(editer_les_coordonnees_des_points_lorsqu_il_y_a_tri_des_premiers_voisins)) Bblock DEFV(Float,INIT(coordonnee_XJ,ELEMENT_DU_FICHIER_LISTE_X(index_J_trie))); DEFV(Float,INIT(coordonnee_YJ,ELEMENT_DU_FICHIER_LISTE_Y(index_J_trie))); DEFV(Float,INIT(coordonnee_ZJ,ELEMENT_DU_FICHIER_LISTE_Z(index_J_trie))); /* Recuperation des coordonnees {X,Y,Z} courantes du point 'J' dans les fichiers. */ DEFV(Float,INIT(coordonnee_X1,FLOT__UNDEF)); DEFV(Float,INIT(coordonnee_Y1,FLOT__UNDEF)); DEFV(Float,INIT(coordonnee_Z1,FLOT__UNDEF)); DEFV(Float,INIT(coordonnee_X2,FLOT__UNDEF)); DEFV(Float,INIT(coordonnee_Y2,FLOT__UNDEF)); DEFV(Float,INIT(coordonnee_Z2,FLOT__UNDEF)); /* Afin de pouvoir changer l'ordre des 2 points {I,J} (introduit le 20051203100941)... */ EGAL(coordonnee_X1,coordonnee_XI); EGAL(coordonnee_Y1,coordonnee_YI); EGAL(coordonnee_Z1,coordonnee_ZI); EGAL(coordonnee_X2,coordonnee_XJ); EGAL(coordonnee_Y2,coordonnee_YJ); EGAL(coordonnee_Z2,coordonnee_ZJ); /* Choix de l'ordre {I,J} pour les deux points. */ Test(IFET(IL_FAUT(mettre_les_points_dans_le_bon_ordre_lorsqu_il_y_a_tri_des_premiers_voisins) ,IFET(IFEQ(premier_index,index_J_trie) ,IFEQ(second_index,indexI) ) ) ) /* Ce test a ete introduit le 20051203100941... */ Bblock fSWAP(coordonnee_X1,coordonnee_X2); fSWAP(coordonnee_Y1,coordonnee_Y2); fSWAP(coordonnee_Z1,coordonnee_Z2); /* Choix de l'ordre {J,I} pour les deux points (l'utilisation de la procedure 'fSWAP(...)' */ /* fut introduite le 20051206093039...). */ Eblock ATes Bblock Eblock ETes CAL2(Prin3(" pointI={%+.^^^,%+.^^^,%+.^^^}",coordonnee_X1,coordonnee_Y1,coordonnee_Z1)); CAL2(Prin3(" pointJ={%+.^^^,%+.^^^,%+.^^^}",coordonnee_X2,coordonnee_Y2,coordonnee_Z2)); /* Le 20060105152121, le format "16g" est passe a "^^g" pour plus de souplesse... */ /* */ /* Le 20091123123539, le format "^^g" est passe a "^^^" pour plus de souplesse... */ Eblock ATes Bblock Eblock ETes CAL2(Prin1(" distance=%+.^^^" ,gELEMENT_DU_FICHIER(liste_des_distances_du_point_I_aux_points_J,index_J_trie) ) ); CAL2(Prin0("\n")); /* Edition de la distance du point 'I' (fixe) a ses N premiers voisins 'J'. */ /* */ /* Le 20060105152121, le format "16g" est passe a "^^g" pour plus de souplesse... */ /* */ /* Le 20091123123539, le format "^^g" est passe a "^^^" pour plus de souplesse... */ INCR(compteur_des_distances,I); /* Introduit le 20161109120606... */ Eblock ATes Bblock Eblock ETes Eblock ATes Bblock Eblock ETes Eblock EDoI Eblock ATes Bblock Eblock ETes lGENERATION_D_UN_FICHIER(liste_des_distances_du_point_I_aux_points_J,FLOT__UNDEF); lGENERATION_D_UN_FICHIER(liste_des_points,FLOT__UNDEF); Eblock EDoI Test(IZEQ(compteur_des_distances)) /* Test introduit le 20161109120606... */ Bblock PRINT_ATTENTION("aucune distance n'a ete editee"); Test(IL_FAUT(filtrer_les_distances)) Bblock PRINT_ATTENTION("il y a filtrage et les bornes sont certainement 'insuffisantes'"); CAL1(Prer2("(les bornes inferieure et superieure valent respectivement %f et %f)\n" ,borne_inferieure_des_distances ,borne_superieure_des_distances ) ); Eblock ATes Bblock Eblock ETes Eblock ATes Bblock Eblock ETes lGENERATION_D_UN_FICHIER(liste_initiale_des_VOISIN,VOISIN_IMPLICITE); lGENERATION_D_UN_FICHIER(liste_initiale_des_VOISIN,VOISIN_IMPLICITE); lGENERATION_D_UN_FICHIER(liste_initiale_des_Z,Z_IMPLICITE); lGENERATION_D_UN_FICHIER(liste_initiale_des_Y,Y_IMPLICITE); lGENERATION_D_UN_FICHIER(liste_initiale_des_X,X_IMPLICITE); RETU_Commande; Eblock ECommande