Commit 012fc9c4 authored by js9's avatar js9
Browse files

Added support for dangling bonds in the Molecule plot. When

using cylinder glyph for bonds, cap them if they are dangling.
Dangling bonds are a good way to show clipped molecules, and
fixes problems using the native clip algorithm (where we have
half-bonds), so we now ignore the "nodesAreCritical" flag,
assuming it's false.  This may become a user-setting later....


git-svn-id: http://visit.ilight.com/svn/visit/trunk/src@9687 18c085ea-50e0-402c-830e-de6fd14e8384
parent 618dc8d3
......@@ -153,14 +153,11 @@ ClipAttributes::Quality_FromString(const std::string &s, ClipAttributes::Quality
return false;
}
// Type map format string
const char *ClipAttributes::TypeMapFormatString = "iibbbDDDDDDbiDdb";
// ****************************************************************************
// Method: ClipAttributes::ClipAttributes
//
// Purpose:
// Constructor for the ClipAttributes class.
// Init utility for the ClipAttributes class.
//
// Note: Autogenerated by xml2atts.
//
......@@ -171,8 +168,7 @@ const char *ClipAttributes::TypeMapFormatString = "iibbbDDDDDDbiDdb";
//
// ****************************************************************************
ClipAttributes::ClipAttributes() :
AttributeSubject(ClipAttributes::TypeMapFormatString)
void ClipAttributes::Init()
{
quality = Fast;
funcType = Plane;
......@@ -204,13 +200,15 @@ ClipAttributes::ClipAttributes() :
center[2] = 0;
radius = 1;
sphereInverse = false;
ClipAttributes::SelectAll();
}
// ****************************************************************************
// Method: ClipAttributes::ClipAttributes
//
// Purpose:
// Copy constructor for the ClipAttributes class.
// Copy utility for the ClipAttributes class.
//
// Note: Autogenerated by xml2atts.
//
......@@ -221,8 +219,7 @@ ClipAttributes::ClipAttributes() :
//
// ****************************************************************************
ClipAttributes::ClipAttributes(const ClipAttributes &obj) :
AttributeSubject(ClipAttributes::TypeMapFormatString)
void ClipAttributes::Copy(const ClipAttributes &obj)
{
quality = obj.quality;
funcType = obj.funcType;
......@@ -262,7 +259,96 @@ ClipAttributes::ClipAttributes(const ClipAttributes &obj) :
radius = obj.radius;
sphereInverse = obj.sphereInverse;
SelectAll();
ClipAttributes::SelectAll();
}
// Type map format string
const char *ClipAttributes::TypeMapFormatString = CLIPATTRIBUTES_TMFS;
const AttributeGroup::private_tmfs_t ClipAttributes::TmfsStruct = {CLIPATTRIBUTES_TMFS};
// ****************************************************************************
// Method: ClipAttributes::ClipAttributes
//
// Purpose:
// Default constructor for the ClipAttributes class.
//
// Note: Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation: omitted
//
// Modifications:
//
// ****************************************************************************
ClipAttributes::ClipAttributes() :
AttributeSubject(ClipAttributes::TypeMapFormatString)
{
ClipAttributes::Init();
}
// ****************************************************************************
// Method: ClipAttributes::ClipAttributes
//
// Purpose:
// Constructor for the derived classes of ClipAttributes class.
//
// Note: Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation: omitted
//
// Modifications:
//
// ****************************************************************************
ClipAttributes::ClipAttributes(private_tmfs_t tmfs) :
AttributeSubject(tmfs.tmfs)
{
ClipAttributes::Init();
}
// ****************************************************************************
// Method: ClipAttributes::ClipAttributes
//
// Purpose:
// Copy constructor for the ClipAttributes class.
//
// Note: Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation: omitted
//
// Modifications:
//
// ****************************************************************************
ClipAttributes::ClipAttributes(const ClipAttributes &obj) :
AttributeSubject(ClipAttributes::TypeMapFormatString)
{
ClipAttributes::Copy(obj);
}
// ****************************************************************************
// Method: ClipAttributes::ClipAttributes
//
// Purpose:
// Copy constructor for derived classes of the ClipAttributes class.
//
// Note: Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation: omitted
//
// Modifications:
//
// ****************************************************************************
ClipAttributes::ClipAttributes(const ClipAttributes &obj, private_tmfs_t tmfs) :
AttributeSubject(tmfs.tmfs)
{
ClipAttributes::Copy(obj);
}
// ****************************************************************************
......@@ -304,45 +390,9 @@ ClipAttributes&
ClipAttributes::operator = (const ClipAttributes &obj)
{
if (this == &obj) return *this;
quality = obj.quality;
funcType = obj.funcType;
plane1Status = obj.plane1Status;
plane2Status = obj.plane2Status;
plane3Status = obj.plane3Status;
plane1Origin[0] = obj.plane1Origin[0];
plane1Origin[1] = obj.plane1Origin[1];
plane1Origin[2] = obj.plane1Origin[2];
plane2Origin[0] = obj.plane2Origin[0];
plane2Origin[1] = obj.plane2Origin[1];
plane2Origin[2] = obj.plane2Origin[2];
plane3Origin[0] = obj.plane3Origin[0];
plane3Origin[1] = obj.plane3Origin[1];
plane3Origin[2] = obj.plane3Origin[2];
plane1Normal[0] = obj.plane1Normal[0];
plane1Normal[1] = obj.plane1Normal[1];
plane1Normal[2] = obj.plane1Normal[2];
plane2Normal[0] = obj.plane2Normal[0];
plane2Normal[1] = obj.plane2Normal[1];
plane2Normal[2] = obj.plane2Normal[2];
plane3Normal[0] = obj.plane3Normal[0];
plane3Normal[1] = obj.plane3Normal[1];
plane3Normal[2] = obj.plane3Normal[2];
planeInverse = obj.planeInverse;
planeToolControlledClipPlane = obj.planeToolControlledClipPlane;
center[0] = obj.center[0];
center[1] = obj.center[1];
center[2] = obj.center[2];
radius = obj.radius;
sphereInverse = obj.sphereInverse;
ClipAttributes::Copy(obj);
SelectAll();
return *this;
}
......
......@@ -40,6 +40,7 @@
#define CLIPATTRIBUTES_H
#include <string>
#include <AttributeSubject.h>
#include <PlaneAttributes.h>
#include <avtVector.h>
......@@ -79,13 +80,23 @@ public:
Accurate
};
// These constructors are for objects of this class
ClipAttributes();
ClipAttributes(const ClipAttributes &obj);
protected:
// These constructors are for objects derived from this class
ClipAttributes(private_tmfs_t tmfs);
ClipAttributes(const ClipAttributes &obj, private_tmfs_t tmfs);
public:
virtual ~ClipAttributes();
virtual ClipAttributes& operator = (const ClipAttributes &obj);
virtual bool operator == (const ClipAttributes &obj) const;
virtual bool operator != (const ClipAttributes &obj) const;
private:
void Init();
void Copy(const ClipAttributes &obj);
public:
virtual const std::string TypeName() const;
virtual bool CopyAttributes(const AttributeGroup *);
......@@ -192,7 +203,8 @@ public:
ID_planeToolControlledClipPlane,
ID_center,
ID_radius,
ID_sphereInverse
ID_sphereInverse,
ID__LAST
};
private:
......@@ -215,6 +227,8 @@ private:
// Static class format string for type map.
static const char *TypeMapFormatString;
static const private_tmfs_t TmfsStruct;
};
#define CLIPATTRIBUTES_TMFS "iibbbDDDDDDbiDdb"
#endif
......@@ -387,6 +387,12 @@ avtClipFilter::ExecuteDataTree(vtkDataSet *inDS, int domain, std::string label)
// Hank Childs, Tue May 27 17:15:43 PDT 2008
// Fixed memory issue that was causing crash.
//
// Jeremy Meredith, Wed Jan 27 10:34:26 EST 2010
// Disabled special nodesAreCritical code. This was intended for
// molecular data, because half-a-bond wasn't meaningful. However,
// we now have a way to show dangling bonds (periodic cases is
// another example) correctly, so we want to clip normally now.
//
// ****************************************************************************
int
......@@ -394,7 +400,10 @@ avtClipFilter::ComputeAccurateClip(vtkDataSet *inDS, vtkDataSet **outDS,
ClipAttributes &atts, int domain, std::string label)
{
// Gather global plane clipping information.
bool nodesAreCritical = GetInput()->GetInfo().GetAttributes().NodesAreCritical();
//bool nodesAreCritical = GetInput()->GetInfo().GetAttributes().NodesAreCritical();
// TODO: For now, set nodesAreCritical to false. We can now handle
// partially-clipped bonds correctly in the molecule plot renderer.
bool nodesAreCritical = false;
int nDataSets = 0;
if (atts.GetFuncType() == ClipAttributes::Plane)
......@@ -564,6 +573,12 @@ avtClipFilter::ComputeAccurateClip(vtkDataSet *inDS, vtkDataSet **outDS,
// Hank Childs, Tue May 27 17:15:43 PDT 2008
// Fixed memory issue that was causing crash.
//
// Jeremy Meredith, Wed Jan 27 10:34:26 EST 2010
// Disabled special nodesAreCritical code. This was intended for
// molecular data, because half-a-bond wasn't meaningful. However,
// we now have a way to show dangling bonds (periodic cases is
// another example) correctly, so we want to clip normally now.
//
// ****************************************************************************
int
......@@ -588,8 +603,11 @@ avtClipFilter::ComputeFastClip(vtkDataSet *inDS, vtkDataSet **outDS,
return 1;
}
bool nodesAreCritical =
GetInput()->GetInfo().GetAttributes().NodesAreCritical();
//bool nodesAreCritical =
// GetInput()->GetInfo().GetAttributes().NodesAreCritical();
// TODO: For now, set nodesAreCritical to false. We can now handle
// partially-clipped bonds correctly in the molecule plot renderer.
bool nodesAreCritical = false;
//
// Set up and apply the clipping filters
......
......@@ -265,6 +265,10 @@ SetColor3ubv(const unsigned char *c)
// which means "unknown", and hydrogen now starts at 1. This
// also means we don't have to correct for 1-origin atomic numbers.
//
// Jeremy Meredith, Wed Jan 27 10:41:02 EST 2010
// Only draw atoms where there is a Vertex cell type. Don't assume
// all points are atoms (since we now support dangling bonds).
//
// ****************************************************************************
void
......@@ -272,6 +276,7 @@ avtOpenGLMoleculeRenderer::DrawAtomsAsSpheres(vtkPolyData *data,
const MoleculeAttributes &atts)
{
vtkPoints *points = data->GetPoints();
int numverts = data->GetNumberOfVerts();
vtkDataArray *primary = data->GetPointData()->GetScalars();
if (!primary)
......@@ -383,11 +388,17 @@ avtOpenGLMoleculeRenderer::DrawAtomsAsSpheres(vtkPolyData *data,
}
glBegin(GL_QUADS);
for (int i=0; i<data->GetNumberOfPoints(); i++)
vtkIdType *vertptr = data->GetVerts()->GetPointer();
for (int ix=0; ix<numverts; ix++, vertptr += (1+*vertptr))
{
if (*vertptr != 1)
continue;
int atom = *(vertptr+1);
int element_number = 0;
if (element)
element_number = int(elementnos[i]);
element_number = int(elementnos[atom]);
if (element_number < 0 || element_number > MAX_ELEMENT_NUMBER)
element_number = 0;
......@@ -399,7 +410,7 @@ avtOpenGLMoleculeRenderer::DrawAtomsAsSpheres(vtkPolyData *data,
else if (element && sbcr)
radius = covalent_radius[element_number] * radiusscale;
else if (radiusvar && sbv)
radius = radiusvar[i] * radiusscale;
radius = radiusvar[atom] * radiusscale;
// Determine color
if (color_by_element)
......@@ -409,7 +420,7 @@ avtOpenGLMoleculeRenderer::DrawAtomsAsSpheres(vtkPolyData *data,
}
else if (color_by_levels)
{
int level = int(scalar[i]) - (primary_is_resseq ? 1 : 0);
int level = int(scalar[atom]) - (primary_is_resseq ? 1 : 0);
if(levelsLUT != 0)
{
const unsigned char *rgb =
......@@ -428,7 +439,7 @@ avtOpenGLMoleculeRenderer::DrawAtomsAsSpheres(vtkPolyData *data,
if (varmax == varmin)
alpha = 0.5;
else
alpha = (scalar[i] - varmin) / (varmax - varmin);
alpha = (scalar[atom] - varmin) / (varmax - varmin);
int color = int((float(numcolors)-.01) * alpha);
if (color < 0)
......@@ -445,7 +456,7 @@ avtOpenGLMoleculeRenderer::DrawAtomsAsSpheres(vtkPolyData *data,
glNormal3f(radius, radius, radius);
for(int j = 0; j < 4; ++j)
{
glVertex3dv(points->GetPoint(i));
glVertex3dv(points->GetPoint(atom));
glTexCoord2fv(texCoords[j]);
}
}
......@@ -454,7 +465,7 @@ avtOpenGLMoleculeRenderer::DrawAtomsAsSpheres(vtkPolyData *data,
// Plot squares
for(int j = 0; j < 4; ++j)
{
double *pt = points->GetPoint(i);
double *pt = points->GetPoint(atom);
float vert[3];
vert[0] = pt[0] + ptOffsets[j][0] * radius;
vert[1] = pt[1] + ptOffsets[j][1] * radius;
......@@ -466,7 +477,7 @@ avtOpenGLMoleculeRenderer::DrawAtomsAsSpheres(vtkPolyData *data,
else
{
// Plot spheres
double *pt = points->GetPoint(i);
double *pt = points->GetPoint(atom);
DrawSphereAsQuads(pt[0],
pt[1],
pt[2],
......@@ -526,6 +537,11 @@ avtOpenGLMoleculeRenderer::DrawAtomsAsSpheres(vtkPolyData *data,
// which means "unknown", and hydrogen now starts at 1. This
// also means we don't have to correct for 1-origin atomic numbers.
//
// Jeremy Meredith, Wed Jan 27 10:41:02 EST 2010
// Draw a dangling, capped cylinder (or dangling line) for bonds
// where one half has no vertex cell. Also, don't draw any
// bond if neither adjacent point has a vertex cell.
//
// ****************************************************************************
void
......@@ -533,6 +549,7 @@ avtOpenGLMoleculeRenderer::DrawBonds(vtkPolyData *data,
const MoleculeAttributes &atts)
{
vtkPoints *points = data->GetPoints();
int numpoints = data->GetNumberOfPoints();
int numverts = data->GetNumberOfVerts();
vtkCellArray *lines = data->GetLines();
vtkIdType *segments = lines->GetPointer();
......@@ -646,6 +663,15 @@ avtOpenGLMoleculeRenderer::DrawBonds(vtkPolyData *data,
glBegin(GL_LINES);
}
// We only want to draw a bond-half if its adjacent atom is a "real" atom.
vector<bool> hasVertex(numpoints,false);
vtkIdType *vertptr = data->GetVerts()->GetPointer();
for (int i=0; i<data->GetNumberOfVerts(); i++, vertptr += (1+*vertptr))
{
int atom = *(vertptr+1);
hasVertex[atom] = true;
}
int *segptr = segments;
for (int i=0; i<data->GetNumberOfLines(); i++)
{
......@@ -671,10 +697,14 @@ avtOpenGLMoleculeRenderer::DrawBonds(vtkPolyData *data,
for (int half=0; half<=1; half++)
{
int atom = (half==0) ? v0 : v1;
int atom = (half==0) ? v0 : v1;
int otherAtom= (half==0) ? v1 : v0;
double *pt_a = (half==0) ? pt_0 : pt_mid;
double *pt_b = (half==0) ? pt_mid : pt_1;
if (!hasVertex[atom])
continue;
int element_number = 0;
if (element)
{
......@@ -773,6 +803,12 @@ avtOpenGLMoleculeRenderer::DrawBonds(vtkPolyData *data,
{
DrawCylinderBetweenTwoPoints(pt_a, pt_b, radius,
atts.GetBondCylinderQuality());
if (!hasVertex[otherAtom])
{
DrawCylinderCap(pt_a, pt_b, half,
radius,
atts.GetBondCylinderQuality());
}
}
else // == MoleculeAttributes::Wireframe
{
......@@ -1323,3 +1359,79 @@ avtOpenGLMoleculeRenderer::DrawCylinderBetweenTwoPoints(double *p0,
}
// ****************************************************************************
// Method: avtOpenGLMoleculeRenderer::DrawCylinderCap
//
// Purpose:
// Make the OpenGL calls to draw a cylinder cap with the given begin
// and end points, radius, and detail level. The cap is drawn at the
// second point; the first point is used for orientation.
//
// Programmer: Jeremy Meredith
// Creation: January 25, 2010
//
// Modifications:
//
// ****************************************************************************
void
avtOpenGLMoleculeRenderer::DrawCylinderCap(double *p0,
double *p1,
int half,
float r,
int detail)
{
glEnd();
glBegin(GL_TRIANGLE_FAN);
CalculateCylPts();
float vc[3] = {p1[0]-p0[0], p1[1]-p0[1], p1[2]-p0[2]};
float va[3];
float vb[3];
float vc_len = vtkMath::Normalize(vc);
if (vc_len == 0)
return;
vtkMath::Perpendiculars(vc, va,vb, 0);
float v0[4];
if (half==0)
{
glNormal3fv(vc);
glVertex3dv(p1);
}
else
{
//glNormal3f(-vc[0],-vc[1],-vc[2]);
glNormal3fv(vc);
glVertex3dv(p0);
}
int cdetail = cylinder_quality_levels[detail];
for (int b=0; b<=cdetail; b++)
{
int b0 = b;
float *u0;
u0 = &(cyl_pts[detail][b0*4]);
v0[0] = va[0]*u0[0] + vb[0]*u0[1];
v0[1] = va[1]*u0[0] + vb[1]*u0[1];
v0[2] = va[2]*u0[0] + vb[2]*u0[1];
if (half==0)
{
glVertex3f(p1[0] + r*v0[0], p1[1] + r*v0[1], p1[2] + r*v0[2]);
}
else
{
glVertex3f(p0[0] + r*v0[0], p0[1] + r*v0[1], p0[2] + r*v0[2]);
}
}
glEnd();
glBegin(GL_QUADS);
}
......@@ -65,6 +65,9 @@
// Jeremy Meredith, Tue Aug 29 11:28:15 EDT 2006
// Changed point locations to doubles.
//
// Jeremy Meredith, Tue Jan 26 17:25:38 EST 2010
// Added ability to draw a cap on a bond (used for dangling bonds).
//
// ****************************************************************************
class avtOpenGLMoleculeRenderer : public avtMoleculeRendererImplementation
......@@ -112,6 +115,7 @@ class avtOpenGLMoleculeRenderer : public avtMoleculeRendererImplementation
bool cylinders_calculated;
void CalculateCylPts();
void DrawCylinderBetweenTwoPoints(double *, double *, float r, int);
void DrawCylinderCap(double *, double *, int half, float r, int);
int numcolors;
unsigned char *colors;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment