/* EXTRAITS DE LA LICENCE Copyright CEA, contributeurs : Luc BILLARD et Damien CALISTE, laboratoire L_Sim, (2001-2005) Adresse mèl : BILLARD, non joignable par mèl ; CALISTE, damien P caliste AT cea P fr. Ce logiciel est un programme informatique servant à visualiser des structures atomiques dans un rendu pseudo-3D. Ce logiciel est régi par la licence CeCILL soumise au droit français et respectant les principes de diffusion des logiciels libres. Vous pouvez utiliser, modifier et/ou redistribuer ce programme sous les conditions de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA sur le site "http://www.cecill.info". Le fait que vous puissiez accéder à cet en-tête signifie que vous avez pris connaissance de la licence CeCILL, et que vous en avez accepté les termes (cf. le fichier Documentation/licence.fr.txt fourni avec ce logiciel). */ /* LICENCE SUM UP Copyright CEA, contributors : Luc BILLARD et Damien CALISTE, laboratoire L_Sim, (2001-2005) E-mail address: BILLARD, not reachable any more ; CALISTE, damien P caliste AT cea P fr. This software is a computer program whose purpose is to visualize atomic configurations in 3D. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. You can find a copy of this licence shipped with this software at Documentation/licence.en.txt. */ #include "cylinder.h" #include #include #include #include #include #include #include #include int listCylinder; #define FLAG_RESOURCES_PAIR_RADIUS "pairCylinder_pairRadius" #define DESC_RESOURCES_PAIR_RADIUS "This value is the radius for specific pairs drawn as cylinders ; element1 elemen2 0 < real < 10" #define FLAG_RESOURCES_CYLINDER_RADIUS "pairCylinder_radius" #define DESC_RESOURCES_CYLINDER_RADIUS "This value is the default radius of the pairs drawn as cylinders ; 0 < real < 10" #define RESOURCES_CYLINDER_RADIUS_DEFAULT 0.1 float cylinderRadius; #define FLAG_RESOURCES_CYLINDER_COLOR_TYPE "cylinder_colorType" #define DESC_RESOURCES_CYLINDER_COLOR_TYPE "It chooses the colors of the cylinders according differents criterion ;" #define RESOURCES_CYLINDER_COLOR_TYPE_DEFAULT cylinder_user_color int cylinderColorType; gboolean readCylinderDefaultRadius(gchar **lines, int nbLines, int position, GString *errorMessage); gboolean readCylinderRadius(gchar **lines, int nbLines, int position, GString *errorMessage); gboolean readCylinderColorType(gchar **lines, int nbLines, int position, GString *errorMessage); gboolean exportResourcesCylinder(GString *data, int *nbLinesWritten, VisuData *dataObj); int setCylinderGeneralRadius(float val) { DBG_fprintf(stderr, "Pairs Cylinder : set the general cylinder radius to %f.\n", val); if (val < RESOURCES_CYLINDER_RADIUS_MIN) val = RESOURCES_CYLINDER_RADIUS_MIN; if (val > RESOURCES_CYLINDER_RADIUS_MAX) val = RESOURCES_CYLINDER_RADIUS_MAX; if (val == cylinderRadius) return 0; setPairsAreOutOfDate(); cylinderRadius = val; return 1; } float getCylinderGeneralRadius() { return cylinderRadius; } int setCylinderRadius(PairsData *data, float val) { float *radius; if (!data) return 0; DBG_fprintf(stderr, "Pairs Cylinder : set the cylinder radius of pair '%s-%s' to %f.\n", data->name1, data->name2, val); if (val < RESOURCES_CYLINDER_RADIUS_MIN) val = RESOURCES_CYLINDER_RADIUS_MIN; if (val > RESOURCES_CYLINDER_RADIUS_MAX) val = RESOURCES_CYLINDER_RADIUS_MAX; radius = getPairsProperty(data, "radius"); if (!radius) { radius = malloc(sizeof(float)); if (!radius) { allocationProblems(); exit(1); } setPairsProperty(data, "radius", (gpointer)radius); *radius = val; setPairsAreOutOfDate(); return 1; } else if (*radius != val) { *radius = val; setPairsAreOutOfDate(); return 1; } return 0; } float getCylinderRadius(PairsData *data) { float *radius; if (!data) return -1.; radius = getPairsProperty(data, "radius"); if (radius) return *radius; else return cylinderRadius; } int setCylinderColorType(int val) { DBG_fprintf(stderr, "Pairs Cylinder : set the cylinder color type to %d.\n", val); if (val < 0 || val >= cylinder_nb_color) { fprintf(stderr, "WARNING! A call to setCylinderColorType has been" " done with a wrong parameter (%d), val must be within 0 and %d.\n", val, cylinder_nb_color); return 0; } cylinderColorType = val; setPairsAreOutOfDate(); return 1; } int getCylinderColorType() { return cylinderColorType; } void setColorAndWidthForCylinder(VisuElement *ele1, VisuElement *ele2, PairsData *data) { float mm[4] = {0.0f, 0.0f, 0.0f, 1.0f}; float amb = 0.5, dif = 0.5, shi = 0., spe = 0. , emi = 0.; Color *color; color = (Color*)getPairsProperty(data, "color"); if (!color) return; switch (cylinderColorType) { case cylinder_user_color: mm[0] = amb * color->rgba[PAIRS_COLOR_R]; mm[1] = amb * color->rgba[PAIRS_COLOR_G]; mm[2] = amb * color->rgba[PAIRS_COLOR_B]; glMaterialfv(GL_FRONT, GL_AMBIENT, mm); mm[0] = dif * color->rgba[PAIRS_COLOR_R]; mm[1] = dif * color->rgba[PAIRS_COLOR_G]; mm[2] = dif * color->rgba[PAIRS_COLOR_B]; glMaterialfv(GL_FRONT, GL_DIFFUSE, mm); glMaterialf(GL_FRONT, GL_SHININESS, shi * 128.); mm[0] = spe; mm[1] = spe; mm[2] = spe; glMaterialfv(GL_FRONT, GL_SPECULAR, mm); mm[0] = emi * color->rgba[PAIRS_COLOR_R]; mm[1] = emi * color->rgba[PAIRS_COLOR_G]; mm[2] = emi * color->rgba[PAIRS_COLOR_B]; glMaterialfv(GL_FRONT, GL_EMISSION, mm); break; case cylinder_element_color: default: break; } setPairsAreOutOfDate(); } void drawCylinderPairs(VisuElement *ele1, VisuElement *ele2, PairsData *data, OpenGLView *view, double x1, double y1, double z1, double x2, double y2, double z2, float d2) { int mat1, mat2, nlat; double vNorm[3]; /* vecteur normal aux vecteurs (0,0,1) et (x2-x1, y2-y1, z2-z1) */ double vDest[3]; /* vecteur (x2-x1, y2-y1, z2-z1) */ double cosAlpha; /* cosinus entre (0,0,1) et Vdest */ double alpha; #define RADTODEG 57.29577951 float radius, *tmpRad; GLUquadricObj *obj; tmpRad = getPairsProperty(data, "radius"); if (tmpRad) radius = *tmpRad; else radius = cylinderRadius; nlat = OpenGLViewGet_numberOfFacettes(view, radius); vDest[0] = x2 - x1; vDest[1] = y2 - y1; vDest[2] = z2 - z1; if (vDest[0] != 0 || vDest[1] != 0) { vNorm[0] = - vDest[1]; vNorm[1] = vDest[0]; vNorm[2] = 0.; cosAlpha = sqrt((vDest[2] * vDest[2]) / d2); if (vDest[2] < 0.) cosAlpha = - cosAlpha; alpha = acos(cosAlpha) * RADTODEG; } else { vNorm[0] = 1.; vNorm[1] = 0.; vNorm[2] = 0.; if (vDest[2] < 0.) alpha = 180.; else alpha = 0.; } obj = gluNewQuadric(); glPushMatrix(); switch (cylinderColorType) { case cylinder_user_color: glTranslated(x1, y1, z1); glRotated(alpha, vNorm[0], vNorm[1], vNorm[2]); gluCylinder(obj, (GLdouble)radius, (GLdouble)radius, (GLdouble)sqrt(d2), (GLint)nlat, (GLint)1); break; case cylinder_element_color: mat1 = visuElementGet_identifierMaterial(ele1); mat2 = visuElementGet_identifierMaterial(ele2); if (mat1 <= 0 || mat2 <= 0) g_warning("Can't draw cylinders because either ele1" "or ele2 has no identifier for material.\n"); glTranslated(x1, y1, z1); glRotated(alpha, vNorm[0], vNorm[1], vNorm[2]); glCallList(mat1); gluCylinder(obj, (GLdouble)radius, (GLdouble)radius, (GLdouble)sqrt(d2) / 2., (GLint)nlat, (GLint)1); glPopMatrix(); glPushMatrix(); glTranslated(x2, y2, z2); glRotated(alpha - 180., vNorm[0], vNorm[1], vNorm[2]); glCallList(mat2); gluCylinder(obj, (GLdouble)radius, (GLdouble)radius, (GLdouble)sqrt(d2) / 2., (GLint)nlat, (GLint)1); break; default: break; } glPopMatrix(); } PairsExtension* initPairsCylinder() { char *name = _("Cylinder pairs"); char *desc = _("Pairs are rendered by cylinders." " The color and the width can by chosen."); PairsExtension *extension; VisuConfigFileEntry *resourceEntry; extension = pairsExtension_new("Cylinder pairs", name, desc, 1, (initEndOpenGlPairsFunc)0, (initEndOpenGlPairsFunc)0, setColorAndWidthForCylinder, (startEndPairsFunc)0, drawCylinderPairs); resourceEntry = visuConfigFileAdd_entry(VISU_CONFIGFILE_RESOURCE, FLAG_RESOURCES_CYLINDER_COLOR_TYPE, DESC_RESOURCES_CYLINDER_COLOR_TYPE, 1, readCylinderColorType); resourceEntry = visuConfigFileAdd_entry(VISU_CONFIGFILE_RESOURCE, FLAG_RESOURCES_CYLINDER_RADIUS, DESC_RESOURCES_CYLINDER_RADIUS, 1, readCylinderDefaultRadius); resourceEntry = visuConfigFileAdd_entry(VISU_CONFIGFILE_RESOURCE, FLAG_RESOURCES_PAIR_RADIUS, DESC_RESOURCES_PAIR_RADIUS, 1, readCylinderRadius); visuConfigFileAdd_exportFunction(VISU_CONFIGFILE_RESOURCE, exportResourcesCylinder); listCylinder = openGLObjectList_new(2); cylinderRadius = RESOURCES_CYLINDER_RADIUS_DEFAULT; cylinderColorType = cylinder_user_color; pointerToPairExtension_cylinder = extension; return extension; } /*****************************************/ /* Dealing with parameters and resources */ /*****************************************/ gboolean readCylinderDefaultRadius(gchar **lines, int nbLines, int position, GString *errorMessage) { int res; float radius; res = sscanf(lines[0], "%f", &radius); if (res != 1 || radius < RESOURCES_CYLINDER_RADIUS_MIN || radius > RESOURCES_CYLINDER_RADIUS_MAX) { if (errorMessage) g_string_append_printf(errorMessage, _("WARNING! Parse error at line %d," " 1 real value must appear after" " the %s markup.\n"), position, FLAG_RESOURCES_CYLINDER_RADIUS); setCylinderGeneralRadius(RESOURCES_CYLINDER_RADIUS_DEFAULT); return FALSE; } setCylinderGeneralRadius(radius); return TRUE; } gboolean readCylinderRadius(gchar **lines, int nbLines, int position, GString *errorMessage) { int res, errorFlag; float radius; char *cursor; VisuElement* ele1, *ele2; PairsData *data; cursor = lines[0]; ele1 = visuElementGet_fromValueLine(&cursor, -1, &errorFlag); if (!ele1 ) { if (errorMessage) visuElementPrint_errorFromValueLine(errorMessage, position, errorFlag); return FALSE; } ele2 = visuElementGet_fromValueLine(&cursor, -1, &errorFlag); if (!ele2 ) { if (errorMessage) visuElementPrint_errorFromValueLine(errorMessage, position, errorFlag); return FALSE; } data = getPairsData(ele1, ele2); if (!data) { if (errorMessage) g_string_append_printf(errorMessage, _("WARNING! unexpected internal error.\n")); g_warning("INTERNAL ERROR! Can't find the VisuData associated to" " elements '%s' and '%s'.\n", ele1->name, ele2->name); return FALSE; } res = sscanf(cursor, "%f", &radius); if (res != 1 || radius < RESOURCES_CYLINDER_RADIUS_MIN || radius > RESOURCES_CYLINDER_RADIUS_MAX) { if (errorMessage) g_string_append_printf(errorMessage, _("WARNING! Parse error at line %d," " 1 real value must appear after" " the %s markup.\n"), position, FLAG_RESOURCES_PAIR_RADIUS); setCylinderRadius(data, RESOURCES_CYLINDER_RADIUS_DEFAULT); return FALSE; } setCylinderRadius(data, radius); return TRUE; } gboolean readCylinderColorType(gchar **lines, int nbLines, int position, GString *errorMessage) { int res, val; res = sscanf(lines[0],"%d", &val); if (res != 1 || val < 0 || val >= cylinder_nb_color) { if (errorMessage) g_string_append_printf(errorMessage, _("WARNING! Parse error at line %d," " 1 integer value must appear after" " the %s markup.\n"), position, FLAG_RESOURCES_CYLINDER_COLOR_TYPE); setCylinderColorType(RESOURCES_CYLINDER_COLOR_TYPE_DEFAULT); return FALSE; } setCylinderColorType(val); return TRUE; } void exportPairsRadius(PairsData *data, gpointer userData) { struct foreachFuncExport_struct *str; float *radius; radius = (float*)getPairsProperty(data, "radius"); if (radius) { str = ( struct foreachFuncExport_struct*)userData; /* We export the resource only if the elements are part of the given VisuData. */ if (str->dataObj) { /* We test the first element. */ if (!g_hash_table_lookup(str->dataObj->fromVisuElementToInt, (gpointer)visuElementGet_fromName(data->name1))) return; /* We test the second element. */ if (!g_hash_table_lookup(str->dataObj->fromVisuElementToInt, (gpointer)visuElementGet_fromName(data->name2))) return; } g_string_append_printf(str->data, "%s:\n %s %s %f\n", FLAG_RESOURCES_PAIR_RADIUS, data->name1, data->name2, *radius); *str->nbLinesWritten += 2; } } gboolean exportResourcesCylinder(GString *data, int *nbLinesWritten, VisuData *dataObj) { struct foreachFuncExport_struct str; g_string_append_printf(data, "# %s 0 <= integer < %d\n", DESC_RESOURCES_CYLINDER_COLOR_TYPE, cylinder_nb_color); g_string_append_printf(data, "%s:\n %d\n", FLAG_RESOURCES_CYLINDER_COLOR_TYPE, cylinderColorType); g_string_append_printf(data, "# %s\n", DESC_RESOURCES_CYLINDER_RADIUS); g_string_append_printf(data, "%s:\n %f\n", FLAG_RESOURCES_CYLINDER_RADIUS, cylinderRadius); *nbLinesWritten = 6; str.data = data; str.nbLinesWritten = nbLinesWritten; str.dataObj = dataObj; g_string_append_printf(data, "# %s\n", DESC_RESOURCES_PAIR_RADIUS); foreachPairsData(exportPairsRadius, &str); g_string_append_printf(data, "\n"); *nbLinesWritten += 2; return TRUE; }