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.
224 lines
6.6 KiB
224 lines
6.6 KiB
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: $RCSfile: vtkSpherePuzzleArrows.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 "vtkSpherePuzzleArrows.h"
|
|
|
|
#include "vtkCellArray.h"
|
|
#include "vtkInformation.h"
|
|
#include "vtkInformationVector.h"
|
|
#include "vtkMath.h"
|
|
#include "vtkObjectFactory.h"
|
|
#include "vtkPolyData.h"
|
|
#include "vtkSpherePuzzle.h"
|
|
|
|
#include <math.h>
|
|
|
|
vtkCxxRevisionMacro(vtkSpherePuzzleArrows, "$Revision: 1.13 $");
|
|
vtkStandardNewMacro(vtkSpherePuzzleArrows);
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Construct a new puzzle.
|
|
vtkSpherePuzzleArrows::vtkSpherePuzzleArrows()
|
|
{
|
|
int idx;
|
|
|
|
for (idx = 0; idx < 32; ++idx)
|
|
{
|
|
this->Permutation[idx] = idx;
|
|
}
|
|
|
|
this->Radius = 0.51;
|
|
|
|
this->SetNumberOfInputPorts(0);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Destruct the puzzle.
|
|
vtkSpherePuzzleArrows::~vtkSpherePuzzleArrows()
|
|
{
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkSpherePuzzleArrows::SetPermutationComponent(int comp, int val)
|
|
{
|
|
if (this->Permutation[comp] == val)
|
|
{
|
|
return;
|
|
}
|
|
|
|
this->Permutation[comp] = val;
|
|
this->Modified();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkSpherePuzzleArrows::RequestData(
|
|
vtkInformation *vtkNotUsed(request),
|
|
vtkInformationVector **vtkNotUsed(inputVector),
|
|
vtkInformationVector *outputVector)
|
|
{
|
|
// get the info object
|
|
vtkInformation *outInfo = outputVector->GetInformationObject(0);
|
|
|
|
// get the ouptut
|
|
vtkPolyData *output = vtkPolyData::SafeDownCast(
|
|
outInfo->Get(vtkDataObject::DATA_OBJECT()));
|
|
|
|
vtkPoints *pts = vtkPoints::New();
|
|
vtkCellArray *polys = vtkCellArray::New();
|
|
int idx;
|
|
|
|
for (idx = 0; idx < 32; ++idx)
|
|
{
|
|
if (this->Permutation[idx] != idx)
|
|
{
|
|
//this->AppendArrow(idx, this->Permutation[idx], pts, polys);
|
|
this->AppendArrow(this->Permutation[idx], idx, pts, polys);
|
|
}
|
|
}
|
|
output->SetPoints(pts);
|
|
output->SetPolys(polys);
|
|
pts->Delete();
|
|
polys->Delete();
|
|
|
|
return 1;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Draw an arrow for piece with id1 to piece with id2.
|
|
void vtkSpherePuzzleArrows::AppendArrow(int id1, int id2,
|
|
vtkPoints *pts, vtkCellArray *polys)
|
|
{
|
|
double phi1, phi2, dPhi;
|
|
double theta1, theta2, dTheta;
|
|
double phi=0, theta=0, phiOff, thetaOff;
|
|
double length;
|
|
double x, y, z;
|
|
int num, idx;
|
|
vtkIdType ptId1, ptId2, ptId3, ptId4, ptId5;
|
|
|
|
// Convert the start and end piece ids into sphere coordinates.
|
|
phi1 = vtkMath::Pi() * ((id1 / 8)+0.5) / 4.0;
|
|
theta1 = vtkMath::Pi() * ((id1 % 8)+0.5) / 4.0;
|
|
phi2 = vtkMath::Pi() * ((id2 / 8)+0.5) / 4.0;
|
|
theta2 = vtkMath::Pi() * ((id2 % 8)+0.5) / 4.0;
|
|
dPhi = phi2 - phi1;
|
|
dTheta = theta2 - theta1;
|
|
// Take the short way around.
|
|
while (dPhi > vtkMath::Pi())
|
|
{
|
|
dPhi -= 2*vtkMath::Pi();
|
|
}
|
|
while (dPhi < -vtkMath::Pi())
|
|
{
|
|
dPhi += 2*vtkMath::Pi();
|
|
}
|
|
while (dTheta > vtkMath::Pi())
|
|
{
|
|
dTheta -= 2*vtkMath::Pi();
|
|
}
|
|
while (dTheta < -vtkMath::Pi())
|
|
{
|
|
dTheta += 2*vtkMath::Pi();
|
|
}
|
|
theta2 = theta1 + dTheta;
|
|
phi2 = phi1 + dPhi;
|
|
|
|
// Compute the length (world coords).
|
|
length = dTheta * sin(0.5*(phi1+phi2));
|
|
length = sqrt(length*length + dPhi*dPhi);
|
|
// How many division do we need.
|
|
num = (int)(length / 0.1);
|
|
|
|
// Compute the perpendicular phi theta step.
|
|
thetaOff = dPhi;
|
|
phiOff = -dTheta;
|
|
// Normalize (sphere coords).
|
|
length = sqrt(thetaOff*thetaOff + phiOff*phiOff);
|
|
phiOff = 0.08 * phiOff / length;
|
|
thetaOff = 0.08 * thetaOff / length;
|
|
|
|
// First point.
|
|
x = cos(theta1+thetaOff)*sin(phi1+phiOff);
|
|
y = sin(theta1+thetaOff)*sin(phi1+phiOff);
|
|
z = cos(phi1+phiOff);
|
|
ptId1 = pts->InsertNextPoint(this->Radius*x, this->Radius*y, this->Radius*z);
|
|
x = cos(theta1+2*thetaOff)*sin(phi1+2*phiOff);
|
|
y = sin(theta1+2*thetaOff)*sin(phi1+2*phiOff);
|
|
z = cos(phi1+2*phiOff);
|
|
ptId2 = pts->InsertNextPoint(this->Radius*x, this->Radius*y, this->Radius*z);
|
|
for (idx = 1; idx < num; ++idx)
|
|
{
|
|
// Interpolate angles.
|
|
theta = theta1 + ((double)(idx)/(double)(num)) * dTheta;
|
|
phi = phi1 + ((double)(idx)/(double)(num)) * (phi2-phi1);
|
|
x = cos(theta+thetaOff)*sin(phi+phiOff);
|
|
y = sin(theta+thetaOff)*sin(phi+phiOff);
|
|
z = cos(phi+phiOff);
|
|
ptId3 =
|
|
pts->InsertNextPoint(this->Radius*x, this->Radius*y, this->Radius*z);
|
|
x = cos(theta+2*thetaOff)*sin(phi+2*phiOff);
|
|
y = sin(theta+2*thetaOff)*sin(phi+2*phiOff);
|
|
z = cos(phi+2*phiOff);
|
|
ptId4 =
|
|
pts->InsertNextPoint(this->Radius*x, this->Radius*y, this->Radius*z);
|
|
// Create the rectangle.
|
|
polys->InsertNextCell(4);
|
|
polys->InsertCellPoint(ptId1);
|
|
polys->InsertCellPoint(ptId2);
|
|
polys->InsertCellPoint(ptId4);
|
|
polys->InsertCellPoint(ptId3);
|
|
// Initialize the next step.
|
|
ptId1 = ptId3;
|
|
ptId2 = ptId4;
|
|
}
|
|
// Now create the arrow.
|
|
x = cos(theta)*sin(phi);
|
|
y = sin(theta)*sin(phi);
|
|
z = cos(phi);
|
|
ptId3 = pts->InsertNextPoint(this->Radius*x, this->Radius*y, this->Radius*z);
|
|
x = cos(theta+3*thetaOff)*sin(phi+3*phiOff);
|
|
y = sin(theta+3*thetaOff)*sin(phi+3*phiOff);
|
|
z = cos(phi+3*phiOff);
|
|
ptId4 = pts->InsertNextPoint(this->Radius*x, this->Radius*y, this->Radius*z);
|
|
x = cos(theta2+1.5*thetaOff)*sin(phi2+1.5*phiOff);
|
|
y = sin(theta2+1.5*thetaOff)*sin(phi2+1.5*phiOff);
|
|
z = cos(phi2+1.5*phiOff);
|
|
ptId5 = pts->InsertNextPoint(this->Radius*x, this->Radius*y, this->Radius*z);
|
|
polys->InsertNextCell(5);
|
|
polys->InsertCellPoint(ptId5);
|
|
polys->InsertCellPoint(ptId4);
|
|
polys->InsertCellPoint(ptId2);
|
|
polys->InsertCellPoint(ptId1);
|
|
polys->InsertCellPoint(ptId3);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkSpherePuzzleArrows::SetPermutation(vtkSpherePuzzle *puz)
|
|
{
|
|
this->SetPermutation(puz->GetState());
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkSpherePuzzleArrows::PrintSelf(ostream& os, vtkIndent indent)
|
|
{
|
|
int i;
|
|
this->Superclass::PrintSelf(os,indent);
|
|
|
|
os << indent << "Permutation: ";
|
|
for (i = 0; i < 32; ++i)
|
|
{
|
|
os << this->Permutation[i] << " ";
|
|
}
|
|
os << endl;
|
|
}
|
|
|