Cloned library of VTK-5.0.0 with extra build files for internal package management.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

363 lines
8.5 KiB

/*=========================================================================
Program: Visualization Toolkit
Module: $RCSfile: vtkBox.cxx,v $
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#include "vtkBox.h"
#include "vtkMath.h"
#include "vtkObjectFactory.h"
vtkCxxRevisionMacro(vtkBox, "$Revision: 1.5 $");
vtkStandardNewMacro(vtkBox);
// Construct the box centered at the origin and each side length 1.0.
vtkBox::vtkBox()
{
this->XMin[0] = -0.5;
this->XMin[1] = -0.5;
this->XMin[2] = -0.5;
this->XMax[0] = 0.5;
this->XMax[1] = 0.5;
this->XMax[2] = 0.5;
}
// Set the bounds in various ways
void vtkBox::SetBounds(double xMin, double xMax,
double yMin, double yMax,
double zMin, double zMax)
{
if ( this->XMin[0] != xMin || this->XMax[0] != xMax ||
this->XMin[1] != yMin || this->XMax[1] != yMax ||
this->XMin[2] != zMin || this->XMax[2] != yMax )
{
this->XMin[0] = xMin;
this->XMax[0] = xMax;
this->XMin[1] = yMin;
this->XMax[1] = yMax;
this->XMin[2] = zMin;
this->XMax[2] = zMax;
for (int i=0; i<3; i++)
{
if ( this->XMax[i] < this->XMin[i] )
{
this->XMax[i] = this->XMin[i];
}
}
this->Modified();
}
}
void vtkBox::SetBounds(double bounds[6])
{
this->SetBounds(bounds[0],bounds[1], bounds[2],bounds[3],
bounds[4],bounds[5]);
}
void vtkBox::GetBounds(double &xMin, double &xMax,
double &yMin, double &yMax,
double &zMin, double &zMax)
{
xMin = this->XMin[0];
yMin = this->XMin[1];
zMin = this->XMin[2];
xMax = this->XMax[0];
yMax = this->XMax[1];
zMax = this->XMax[2];
}
void vtkBox::GetBounds(double bounds[6])
{
for (int i=0; i<3; i++)
{
bounds[2*i] = this->XMin[i];
bounds[2*i+1] = this->XMax[i];
}
}
// Evaluate box equation. This differs from the similar vtkPlanes
// (with six planes) because of the "rounded" nature of the corners.
double vtkBox::EvaluateFunction(double x[3])
{
double diff, dist, minDistance=(-VTK_DOUBLE_MAX), t, distance=0.0;
int inside=1;
for (int i=0; i<3; i++)
{
diff = this->XMax[i] - this->XMin[i];
if ( diff != 0.0 )
{
t = (x[i]-this->XMin[i]) / (this->XMax[i]-this->XMin[i]);
if ( t < 0.0 )
{
inside = 0;
dist = this->XMin[i] - x[i];
}
else if ( t > 1.0 )
{
inside = 0;
dist = x[i] - this->XMax[i];
}
else
{//want negative distance, we are inside
if ( t <= 0.5 )
{
dist = this->XMin[i] - x[i];
}
else
{
dist = x[i] - this->XMax[i];
}
if ( dist > minDistance ) //remember, it's negative
{
minDistance = dist;
}
}//if inside
}
else
{
dist = fabs(x[i]-this->XMin[i]);
if ( x[i] != this->XMin[i] )
{
inside = 0;
}
}
if ( dist > 0.0 )
{
distance += dist*dist;
}
}//for all coordinate directions
distance = sqrt(distance);
if ( inside )
{
return minDistance;
}
else
{
return distance;
}
}
// Evaluate box gradient.
void vtkBox::EvaluateGradient(double x[3], double n[3])
{
int i, loc[3], minAxis=0;
double dist, minDist=VTK_DOUBLE_MAX, center[3];
double inDir[3], outDir[3];
// Compute the location of the point with respect to the box.
// Ultimately the point will lie in one of 27 separate regions around
// or within the box. The gradient vector is computed differently in
// each of the regions.
inDir[0] = inDir[1] = inDir[2] = 0.0;
outDir[0] = outDir[1] = outDir[2] = 0.0;
for (i=0; i<3; i++)
{
center[i] = (this->XMin[i] + this->XMax[i])/2.0;
if ( x[i] < this->XMin[i] )
{
loc[i] = 0;
outDir[i] = -1.0;
}
else if ( x[i] > this->XMax[i] )
{
loc[i] = 2;
outDir[i] = 1.0;
}
else
{
loc[i] = 1;
if ( x[i] <= center[i] )
{
dist = x[i] - this->XMin[i];
inDir[i] = -1.0;
}
else
{
dist = this->XMax[i] - x[i];
inDir[i] = 1.0;
}
if ( dist < minDist ) //remember, it's negative
{
minDist = dist;
minAxis = i;
}
}//if inside
}//for all coordinate directions
int indx = loc[0] + 3*loc[1] + 9*loc[2];
switch (indx)
{
// verts - gradient points away from center point
case 0: case 2: case 6: case 8: case 18: case 20: case 24: case 26:
for (i=0; i<3; i++)
{
n[i] = x[i] - center[i];
}
vtkMath::Normalize(n);
break;
// edges - gradient points out from axis of cube
case 1: case 3: case 5: case 7:
case 9: case 11: case 15: case 17:
case 19: case 21: case 23: case 25:
for (i=0; i<3; i++)
{
if ( outDir[i] != 0.0 )
{
n[i] = x[i] - center[i];
}
else
{
n[i] = 0.0;
}
}
vtkMath::Normalize(n);
break;
// faces - gradient points perpendicular to face
case 4: case 10: case 12: case 14: case 16: case 22:
for (i=0; i<3; i++)
{
n[i] = outDir[i];
}
break;
// interior - gradient is perpendicular to closest face
case 13:
n[0] = n[1] = n[2] = 0.0;
n[minAxis] = inDir[minAxis];
break;
}
}
#define VTK_RIGHT 0
#define VTK_LEFT 1
#define VTK_MIDDLE 2
// Bounding box intersection modified from Graphics Gems Vol I. The method
// returns a non-zero value if the bounding box is hit. Origin[3] starts
// the ray, dir[3] is the vector components of the ray in the x-y-z
// directions, coord[3] is the location of hit, and t is the parametric
// coordinate along line. (Notes: the intersection ray dir[3] is NOT
// normalized. Valid intersections will only occur between 0<=t<=1.)
char vtkBox::IntersectBox (double bounds[6], double origin[3], double dir[3],
double coord[3], double& t)
{
char inside=1;
char quadrant[3];
int i, whichPlane=0;
double maxT[3], candidatePlane[3];
// First find closest planes
//
for (i=0; i<3; i++)
{
if ( origin[i] < bounds[2*i] )
{
quadrant[i] = VTK_LEFT;
candidatePlane[i] = bounds[2*i];
inside = 0;
}
else if ( origin[i] > bounds[2*i+1] )
{
quadrant[i] = VTK_RIGHT;
candidatePlane[i] = bounds[2*i+1];
inside = 0;
}
else
{
quadrant[i] = VTK_MIDDLE;
}
}
// Check whether origin of ray is inside bbox
//
if (inside)
{
coord[0] = origin[0];
coord[1] = origin[1];
coord[2] = origin[2];
t = 0;
return 1;
}
// Calculate parametric distances to plane
//
for (i=0; i<3; i++)
{
if ( quadrant[i] != VTK_MIDDLE && dir[i] != 0.0 )
{
maxT[i] = (candidatePlane[i]-origin[i]) / dir[i];
}
else
{
maxT[i] = -1.0;
}
}
// Find the largest parametric value of intersection
//
for (i=0; i<3; i++)
{
if ( maxT[whichPlane] < maxT[i] )
{
whichPlane = i;
}
}
// Check for valid intersection along line
//
if ( maxT[whichPlane] > 1.0 || maxT[whichPlane] < 0.0 )
{
return 0;
}
else
{
t = maxT[whichPlane];
}
// Intersection point along line is okay. Check bbox.
//
for (i=0; i<3; i++)
{
if (whichPlane != i)
{
coord[i] = origin[i] + maxT[whichPlane]*dir[i];
if ( coord[i] < bounds[2*i] || coord[i] > bounds[2*i+1] )
{
return 0;
}
}
else
{
coord[i] = candidatePlane[i];
}
}
return 1;
}
#undef VTK_RIGHT
#undef VTK_LEFT
#undef VTK_MIDDLE
void vtkBox::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
os << indent << "XMin: (" << this->XMin[0] << ", "
<< this->XMin[1] << ", " << this->XMin[2] << ")\n";
os << indent << "XMax: (" << this->XMax[0] << ", "
<< this->XMax[1] << ", " << this->XMax[2] << ")\n";
}