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.
329 lines
8.9 KiB
329 lines
8.9 KiB
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: $RCSfile: vtkConeSource.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 "vtkConeSource.h"
|
|
|
|
#include "vtkFloatArray.h"
|
|
#include "vtkMath.h"
|
|
#include "vtkInformation.h"
|
|
#include "vtkInformationVector.h"
|
|
#include "vtkObjectFactory.h"
|
|
#include "vtkStreamingDemandDrivenPipeline.h"
|
|
#include "vtkPolyData.h"
|
|
#include "vtkTransform.h"
|
|
#include "vtkCellArray.h"
|
|
|
|
#include <math.h>
|
|
|
|
vtkCxxRevisionMacro(vtkConeSource, "$Revision: 1.73 $");
|
|
vtkStandardNewMacro(vtkConeSource);
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Construct with default resolution 6, height 1.0, radius 0.5, and capping
|
|
// on.
|
|
vtkConeSource::vtkConeSource(int res)
|
|
{
|
|
res = (res < 0 ? 0 : res);
|
|
this->Resolution = res;
|
|
this->Height = 1.0;
|
|
this->Radius = 0.5;
|
|
this->Capping = 1;
|
|
|
|
this->Center[0] = 0.0;
|
|
this->Center[1] = 0.0;
|
|
this->Center[2] = 0.0;
|
|
|
|
this->Direction[0] = 1.0;
|
|
this->Direction[1] = 0.0;
|
|
this->Direction[2] = 0.0;
|
|
|
|
this->SetNumberOfInputPorts(0);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkConeSource::RequestData(
|
|
vtkInformation *vtkNotUsed(request),
|
|
vtkInformationVector **vtkNotUsed(inputVector),
|
|
vtkInformationVector *outputVector)
|
|
{
|
|
// get the info objects
|
|
vtkInformation *outInfo = outputVector->GetInformationObject(0);
|
|
|
|
double angle;
|
|
int numLines, numPolys, numPts;
|
|
double x[3], xbot;
|
|
int i;
|
|
vtkIdType pts[VTK_CELL_SIZE];
|
|
vtkPoints *newPoints;
|
|
vtkCellArray *newLines=0;
|
|
vtkCellArray *newPolys=0;
|
|
vtkPolyData *output = vtkPolyData::SafeDownCast(
|
|
outInfo->Get(vtkDataObject::DATA_OBJECT()));
|
|
// for streaming
|
|
int piece;
|
|
int numPieces;
|
|
int maxPieces;
|
|
int start, end;
|
|
int createBottom;
|
|
|
|
piece = output->GetUpdatePiece();
|
|
if (piece >= this->Resolution && !(piece == 0 && this->Resolution == 0))
|
|
{
|
|
return 1;
|
|
}
|
|
numPieces = output->GetUpdateNumberOfPieces();
|
|
maxPieces = this->Resolution != 0 ? this->Resolution : 1;
|
|
if (numPieces > maxPieces)
|
|
{
|
|
numPieces = maxPieces;
|
|
}
|
|
if (piece >= maxPieces)
|
|
{
|
|
// Super class should do this for us,
|
|
// but I put this condition in any way.
|
|
return 1;
|
|
}
|
|
start = maxPieces * piece / numPieces;
|
|
end = (maxPieces * (piece+1) / numPieces) - 1;
|
|
createBottom = (this->Capping && (start == 0));
|
|
|
|
vtkDebugMacro("ConeSource Executing");
|
|
|
|
if ( this->Resolution )
|
|
{
|
|
angle = 2.0*3.141592654/this->Resolution;
|
|
}
|
|
else
|
|
{
|
|
angle = 0.0;
|
|
}
|
|
|
|
// Set things up; allocate memory
|
|
//
|
|
switch ( this->Resolution )
|
|
{
|
|
case 0:
|
|
numPts = 2;
|
|
numLines = 1;
|
|
newLines = vtkCellArray::New();
|
|
newLines->Allocate(newLines->EstimateSize(numLines,numPts));
|
|
break;
|
|
|
|
case 1: case 2:
|
|
numPts = 2*this->Resolution + 1;
|
|
numPolys = this->Resolution;
|
|
newPolys = vtkCellArray::New();
|
|
newPolys->Allocate(newPolys->EstimateSize(numPolys,3));
|
|
break;
|
|
|
|
default:
|
|
if (createBottom)
|
|
{
|
|
// piece 0 has cap.
|
|
numPts = this->Resolution + 1;
|
|
numPolys = end - start + 2;
|
|
}
|
|
else
|
|
{
|
|
numPts = end - start + 3;
|
|
numPolys = end - start + 2;
|
|
}
|
|
newPolys = vtkCellArray::New();
|
|
newPolys->Allocate(newPolys->EstimateSize(numPolys,this->Resolution));
|
|
break;
|
|
}
|
|
newPoints = vtkPoints::New();
|
|
newPoints->SetDataTypeToFloat(); //used later during transformation
|
|
newPoints->Allocate(numPts);
|
|
|
|
// Create cone
|
|
//
|
|
x[0] = this->Height / 2.0; // zero-centered
|
|
x[1] = 0.0;
|
|
x[2] = 0.0;
|
|
pts[0] = newPoints->InsertNextPoint(x);
|
|
|
|
xbot = -this->Height / 2.0;
|
|
|
|
switch (this->Resolution)
|
|
{
|
|
case 0:
|
|
x[0] = xbot;
|
|
x[1] = 0.0;
|
|
x[2] = 0.0;
|
|
pts[1] = newPoints->InsertNextPoint(x);
|
|
newLines->InsertNextCell(2,pts);
|
|
break;
|
|
|
|
case 2: // fall through this case to use the code in case 1
|
|
x[0] = xbot;
|
|
x[1] = 0.0;
|
|
x[2] = -this->Radius;
|
|
pts[1] = newPoints->InsertNextPoint(x);
|
|
x[0] = xbot;
|
|
x[1] = 0.0;
|
|
x[2] = this->Radius;
|
|
pts[2] = newPoints->InsertNextPoint(x);
|
|
newPolys->InsertNextCell(3,pts);
|
|
|
|
case 1:
|
|
x[0] = xbot;
|
|
x[1] = -this->Radius;
|
|
x[2] = 0.0;
|
|
pts[1] = newPoints->InsertNextPoint(x);
|
|
x[0] = xbot;
|
|
x[1] = this->Radius;
|
|
x[2] = 0.0;
|
|
pts[2] = newPoints->InsertNextPoint(x);
|
|
newPolys->InsertNextCell(3,pts);
|
|
break;
|
|
|
|
default: // General case: create Resolution triangles and single cap
|
|
// create the bottom.
|
|
if ( createBottom )
|
|
{
|
|
for (i=0; i < this->Resolution; i++)
|
|
{
|
|
x[0] = xbot;
|
|
x[1] = this->Radius * cos ((double)i*angle);
|
|
x[2] = this->Radius * sin ((double)i*angle);
|
|
// Reverse the order
|
|
pts[this->Resolution - i - 1] = newPoints->InsertNextPoint(x);
|
|
}
|
|
newPolys->InsertNextCell(this->Resolution,pts);
|
|
}
|
|
|
|
pts[0] = 0;
|
|
if ( ! createBottom)
|
|
{
|
|
// we need to create the points also
|
|
x[0] = xbot;
|
|
x[1] = this->Radius * cos ((double)start*angle);
|
|
x[2] = this->Radius * sin ((double)start*angle);
|
|
pts[1] = newPoints->InsertNextPoint(x);
|
|
for (i = start; i <= end; ++i)
|
|
{
|
|
x[1] = this->Radius * cos ((double)(i+1)*angle);
|
|
x[2] = this->Radius * sin ((double)(i+1)*angle);
|
|
pts[2] = newPoints->InsertNextPoint(x);
|
|
newPolys->InsertNextCell(3,pts);
|
|
pts[1] = pts[2];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// bottom and points have already been created.
|
|
for (i=start; i <= end; i++)
|
|
{
|
|
pts[1] = i+1;
|
|
pts[2] = i+2;
|
|
if (pts[2] > this->Resolution)
|
|
{
|
|
pts[2] = 1;
|
|
}
|
|
newPolys->InsertNextCell(3,pts);
|
|
}
|
|
} // createBottom
|
|
|
|
} //switch
|
|
|
|
// A non-default origin and/or direction requires transformation
|
|
//
|
|
if ( this->Center[0] != 0.0 || this->Center[1] != 0.0 ||
|
|
this->Center[2] != 0.0 || this->Direction[0] != 1.0 ||
|
|
this->Direction[1] != 0.0 || this->Direction[2] != 0.0 )
|
|
{
|
|
vtkTransform *t = vtkTransform::New();
|
|
t->Translate(this->Center[0], this->Center[1], this->Center[2]);
|
|
double vMag = vtkMath::Norm(this->Direction);
|
|
if ( this->Direction[0] < 0.0 &&
|
|
this->Direction[1] == 0.0 &&
|
|
this->Direction[2] == 0.0 )
|
|
{
|
|
// just flip x
|
|
t->RotateWXYZ(180.0,0,1,0);
|
|
}
|
|
else
|
|
{
|
|
t->RotateWXYZ((double)180.0, (this->Direction[0]+vMag)/2.0,
|
|
this->Direction[1]/2.0, this->Direction[2]/2.0);
|
|
}
|
|
float *ipts = ((vtkFloatArray *)newPoints->GetData())->GetPointer(0);
|
|
for (i=0; i<numPts; i++, ipts+=3)
|
|
{
|
|
t->TransformPoint(ipts,ipts);
|
|
}
|
|
|
|
t->Delete();
|
|
}
|
|
|
|
// Update ourselves
|
|
//
|
|
output->SetPoints(newPoints);
|
|
newPoints->Delete();
|
|
|
|
if ( newPolys )
|
|
{
|
|
newPolys->Squeeze(); // we may have estimated size; reclaim some space
|
|
output->SetPolys(newPolys);
|
|
newPolys->Delete();
|
|
}
|
|
else
|
|
{
|
|
output->SetLines(newLines);
|
|
newLines->Delete();
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkConeSource::RequestInformation(
|
|
vtkInformation *vtkNotUsed(request),
|
|
vtkInformationVector **vtkNotUsed(inputVector),
|
|
vtkInformationVector *outputVector)
|
|
{
|
|
vtkInformation *outInfo = outputVector->GetInformationObject(0);
|
|
outInfo->Set(vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(),
|
|
-1);
|
|
return 1;
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkConeSource::SetAngle(double angle)
|
|
{
|
|
this->SetRadius (this->Height * tan ((double) angle*vtkMath::DegreesToRadians()));
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
double vtkConeSource::GetAngle()
|
|
{
|
|
return atan2 (this->Radius, this->Height) / vtkMath::DegreesToRadians();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkConeSource::PrintSelf(ostream& os, vtkIndent indent)
|
|
{
|
|
this->Superclass::PrintSelf(os,indent);
|
|
|
|
os << indent << "Resolution: " << this->Resolution << "\n";
|
|
os << indent << "Height: " << this->Height << "\n";
|
|
os << indent << "Radius: " << this->Radius << "\n";
|
|
os << indent << "Capping: " << (this->Capping ? "On\n" : "Off\n");
|
|
os << indent << "Center: (" << this->Center[0] << ", "
|
|
<< this->Center[1] << ", " << this->Center[2] << ")\n";
|
|
os << indent << "Direction: (" << this->Direction[0] << ", "
|
|
<< this->Direction[1] << ", " << this->Direction[2] << ")\n";
|
|
}
|
|
|