This is BBBondShape.m in view mode; [Download] [Up]
/* BBBondShape.m
*
* This is a N3DShape the draws a simple Bond. For faster drawing we store
* the needed data.
*
* For more interface-info see the header file. More in depth information
* can be found in the source-code.
*
* Written by: Thomas Engel
* Created: 25.15.1993 (Copyleft)
* Last modified: 23.05.1994
*/
#import "BBBondShape.h"
#import "BBBasicShapeBallsSticks.h"
#import "BBMolecule.h"
#import "BBAtom.h"
#import "BBBond.h"
#import <math.h>
@implementation BBBondShape
- initFrom:aBond asPartOf:aRegionShape
{
self = [super init];
if( !self ) return self;
// OK. We really are an object...here we go with our init.
ourBond = aBond;
ourRegionShape = aRegionShape;
[self update];
return self;
}
- renderSelf:(N3DCamera *)theCamera
{
// Just do the drawing. If the colors are the same we will only render
// one cylinder. We won't check for any drawing style here.
// The translation is the same only coloring and cylindering may vary.
if( length <= 0 ) return self;
RiTranslate( fromX, fromY, fromZ );
if( angle != 0.0 ) RiRotate( angle, axisX, axisY, axisZ );
RiColor( color1 );
if( color1[0] != color2[0] ||
color1[1] != color2[1] ||
color1[2] != color2[2] )
{
RiCylinder( radius, startingZ, length/2.0, 360.0, RI_NULL );
RiColor( color2 );
RiCylinder( radius, length/2.0, length, 360.0, RI_NULL );
}
else
{
RiCylinder( radius, startingZ, length, 360.0, RI_NULL );
}
return self;
}
- renderSelfAsBox:(N3DCamera *)theCamera
{
// Just set the right color for the box !
RiColor( color1 );
return [super renderSelfAsBox:theCamera];
}
- update
{
// Here we setup every data useful for drawing at once.
// The most complex it the axis/angle calculation.
id anAtom;
float deltaX, deltaY, deltaZ;
anAtom = [ourBond fromAtom];
fromX = [anAtom xPos];
fromY = [anAtom yPos];
fromZ = [anAtom zPos];
anAtom = [ourBond toAtom];
deltaX = [anAtom xPos] - fromX;
deltaY = [anAtom yPos] - fromY;
deltaZ = [anAtom zPos] - fromZ;
// With startingZ and length we can cause our bond to be only drawn on
// a limited section. This is useful when drawing bonds that belong to a
// certain group...they can be renderd only to the half.
// The default is full length.
radius = [ourRegionShape bondRadius:self];
startingZ = 0.0;
length = sqrt( deltaX*deltaX + deltaY*deltaY + deltaZ*deltaZ );
if( length == 0.0 )
{
length = -1;
deltaX = -1;
printf( "BeakerBoy(BBBondShape): ");
printf( "BondLength is zero. Check your molecules!!!\r\n" );
}
// Now we'll reduce the deltaZ to fit delta-vector-length = 1 and then we
// will calc the angle between the bond and the z-axis (where our cylinder
// will be by default) with the scalar product. But only if the delta-vec
// is not already the z-axis.
if( deltaX == 0.0 && deltaY == 0.0 )
{
if( deltaZ > 0.0 )
angle = 0.0;
else angle = 180.0;
}
else
{
deltaX = deltaX/length;
deltaY = deltaY/length;
deltaZ = deltaZ/length;
angle = acos( deltaZ );
if( deltaX >= 0.0 && deltaY >= 0.0 )
angle *= -1.0;
angle = angle * 180.0/M_PI;
}
// If the angle is not 0.0 or 180.0 we will calc the axis now. Otherwise we
// are exactly in the z-axis an need no calced rotation-axis (it's y-axis)
// The axis is the normal vector of the plane described by the z-axis and
// bond we want to draw.
// We have a left handed RiRotate so we need -angle too.
if( angle == 0.0 ||
angle == 180.0 )
{
axisX = 0.0;
axisY = 1.0;
axisZ = 0.0;
}
else
{
axisX = deltaY;
axisY = -deltaX;
axisZ = 0;
if( deltaX < 0 || deltaY < 0 ) angle = -angle;
}
// The color depends on the mode we are in..only in stick modes we
// have differnt colors. Other we will use standard mol color
// but both above only if we don't have to use group colors!
if( [[ourRegionShape region] shapesInRegionColor] )
{
NXConvertColorToRGB( [[ourRegionShape region] color],
&color1[0], &color1[1], &color1[2] );
color2[0] = color1[0];
color2[1] = color1[1];
color2[2] = color1[2];
}
else if( [ourRegionShape respondsTo:@selector(bondColor:)] )
{
NXConvertColorToRGB( [ourRegionShape bondColor:self],
&color1[0], &color1[1], &color1[2] );
color2[0] = color1[0];
color2[1] = color1[1];
color2[2] = color1[2];
}
else
{
NXConvertColorToRGB( [[ourBond fromAtom] color],
&color1[0], &color1[1], &color1[2] );
NXConvertColorToRGB( [[ourBond toAtom] color],
&color2[0], &color2[1], &color2[2] );
}
// The ast action is to calculate the bounding box. Maybe we will
// need it later.
boundingBox[0] = - radius;
boundingBox[1] = - radius;
boundingBox[2] = 0;
boundingBox[3] = + radius;
boundingBox[4] = + radius;
boundingBox[5] = length;
return self;
}
- bond
{
return ourBond;
}
- setDrawAsBox:(BOOL)flag
{
// This shape does not want to get rendered as a box!
return self;
}
- getBoundingBox:(RtBound *)boundingBox
{
// We have to apply all the rotation stuff we did while drawing the
// bond in renderSelf:
// Right now this is too much of work.
// The current shape refuses to be rendered as a box!
return self;
}
@end
/*
* History: 23.05.94 Small changes to work with the new shape stuff.
*
* 07.05.94 Changed the naming to BB...
*
* 24.01.94 Added startingZ.
*
* 18.01.94 Removed the deltaX/deltyY bug
*
* 15.01.94 First coded entered here. RenderMan stuff taken from
* MolViewer.
*
*
* Bugs: - oh sure. Well box-rendering is quite stupid right now!
*
* - This is the place to include groupChecking or what ever. If a bond
* belongs to two atoms but only one should be shown we can adjust
* the color1/2, from/delta -> length values tu match the wanted
* drawing style. Draw just half of the bind or what you like..
*
*/These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.