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.