Projet Emolgine 2024
Illustration de l’interprétation des fichiers SDF pour reconstruire les structures de molécules
Explication sur la mise en oeuvre :
Le chargement des molécules se fait à partir de fichier sdf de description. Ces fichiers sont constitués de la manière suivante :
Pseudo Entete
Information sur le nombre de nodes et de links
Description des nodes
…….
…….
Description des links
node node type
……..
……..
……..
M END
Informations complémentaires
……
-OEChem-07302410092D
43 46 0 1 0 0 0 0 0999 V2000
4.4487 2.0026 0.0000 S 0 0 0 0 0 0 0 0 0 0 0 0
4.2213 -0.1610 0.0000 S 0 0 0 0 0 0 0 0 0 0 0 0
.........
.........
.........
.........
9 1 1 6 0 0 0
1 13 1 0 0 0 0
10 2 1 1 0 0 0
2 16 1 0 0 0 0
3 16 1 0 0 0 0
3 25 1 0 0 0 0
4 15 1 0 0 0 0
4 40 1 0 0 0 0
5 26 2 0 0 0 0
....
M END
......
Interprétation du fichier de description pour reconstruire à l’aide des primitives de JSXGraph la représentation de la molécule.
Plusieurs problèmes sont à prendre en compte : centrer la molécule dans le graphe et représenter les différentes natures de liens entre la atomes. Plusieurs types de liens sont à prendre en compte : lien simple, lien double, lien triple, liens complexes. De plus il faut pouvoir recentrer de façon automatique la molécule dans le graphe afin d’avoir la représentation la plus lisible.
Représentation des liens :
Lien simple : se réalise simplement avec un objet de type segment.
board.create("segment",[tab_p[link[0]-1],tab_p[link[1]-1]],{strokeColor:'blue',name:'',visible:true,fixed:true,strokeWidth:1});
Lien double : le lien double a été élaboré à partir d’une combinaison entre deux segments de largeur différente tracé l’un au dessus de l’autre. Le segment tracé par dessus a la même couleur que le fond du graphe ce qui donne l’illusion d’avoir deux segments.
board.create("segment",[tab_p[link[0]-1],tab_p[link[1]-1]],{name:'',visible:true,fixed:true,strokeWidth:5});
board.create("segment",[tab_p[link[0]-1],tab_p[link[1]-1]],{strokeColor:"#E5E4E2", name:'',visible:true,fixed:true,strokeWidth:2});
Lien triple : cette réalisation se fait en plusieurs étapes, d’abord générer des points à partir d’une rotation, et ensuite on trace des parallèles sur ces points.
let t2 = board.create('transform', [Math.PI/30, tab_p[link[1]-1]], {type: 'rotate'});
let t2_ = board.create('transform', [-Math.PI/30, tab_p[link[1]-1]], {type: 'rotate'});
let pnew = board.create('point', [tab_p[link[0]-1], [t2]], {visible:false,fixed:true});
let pnew2 = board.create('point', [tab_p[link[0]-1], [t2_]], {visible:false,fixed:true});
let l1=board.create("segment",[tab_p[link[0]-1],tab_p[link[1]-1]],{name:'',visible:true,fixed:true,strokeWidth:1});
let pl1 = board.create('parallel', [tab_p[link[0]-1],tab_p[link[1]-1], pnew],{fillColor:'blue',strokeColor:'blue',straightFirst: false, straightLast: false});
let pl2 = board.create('parallel', [tab_p[link[0]-1],tab_p[link[1]-1], pnew2],{fillColor:'blue',strokeColor:'blue',straightFirst: false, straightLast: false});

Lien vers jsfiddle pour exemple
Liens complexes :deux configurations ont été réalisées pour effectuer ces représentations. La première consiste à tracer un polygone à partir de trois points. Les points supplémentaires sont obtenus par une transformation de type rotation. Pour la deuxième forme complexe qui se formalise par des segments de taille différente entre les deux points à relier, une première solution a été mise en oeuvre à partir d’une solution de type hatch qui permet de positionner sur un segment ou ligne des ticks (comme pour un axe d’un repère). Mais le problème est la taille variable de ces ticks, on n’a pas trouvé la façon de définir la taille variable. Du coup, il a fallu construire une petite fonction qui évalue les caractéristiques du segment (y=ax+b) et qui reconstruit sur ce segment les ticks à intervalle régulier.
Première forme :
let t2 = board.create('transform', [Math.PI/20, tab_p[link[0]-1]], {type: 'rotate'});
let t2_ = board.create('transform', [-Math.PI/20, tab_p[link[0]-1]], {type: 'rotate'});
let pnew = board.create('point', [tab_p[link[1]-1], [t2]], {color: 'blue',visible:false,fixed:true});
let pnew2 = board.create('point', [tab_p[link[1]-1], [t2_]], {color: 'blue',visible:false,fixed:true});
board.create("polygon",[tab_p[link[0]-1],pnew,pnew2],{ fillOpacity:1,strokeColor:'blue',fillColor:'blue',name:'',visible:true,fixed:true,strokeWidth:1});

Lien vers jsfiddle pour exemple
Deuxième forme :

Recentrage des représentations :
Lors de la lecture des coordonnées des points , on extrait le min et le max sur les deux axes X et Y. Une fois les valeurs connues on dimensionne le boudingBox du graphe pour garantir que la représentation se trouve au centre de l’image.