/* 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 <GL/gl.h>
#include <GL/glu.h>
#include <math.h>
#include <visu_tools.h>
#include <visu_data.h>
#include <visu_object.h>
#include <visu_configFile.h>
#include <openGLFunctions/objectList.h>
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;
}
syntax highlighted by Code2HTML, v. 0.9.1