Files
ThirdParty-6/ParaView-5.0.1/VTK/Geovis/Core/vtkGlobeSource.cxx

390 lines
12 KiB
C++

/*=========================================================================
Program: Visualization Toolkit
Module: vtkGlobeSource.cxx
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.
=========================================================================*/
/*-------------------------------------------------------------------------
Copyright 2008 Sandia Corporation.
Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
the U.S. Government retains certain rights in this software.
-------------------------------------------------------------------------*/
#include "vtkGlobeSource.h"
#include "vtkCellArray.h"
#include "vtkDoubleArray.h"
#include "vtkFloatArray.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkMath.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkPoints.h"
#include "vtkPolyData.h"
#include "vtkStreamingDemandDrivenPipeline.h"
#include "vtkGeoMath.h"
#include "vtkTimerLog.h"
#include <math.h>
vtkStandardNewMacro(vtkGlobeSource);
// 0=NE, 1=SE, 2=SW, 3=NW
//----------------------------------------------------------------------------
vtkGlobeSource::vtkGlobeSource()
{
this->Origin[0] = this->Origin[1] = this->Origin[2] = 0.0;
this->Radius = vtkGeoMath::EarthRadiusMeters();
this->AutoCalculateCurtainHeight = true;
this->CurtainHeight = 1000.0;
this->LongitudeResolution = 10;
this->LatitudeResolution = 10;
this->StartLongitude = 0.0;
this->EndLongitude = 360.0;
this->StartLatitude = 0.0;
this->EndLatitude = 180.0;
this->QuadrilateralTessellation = 0;
this->SetNumberOfInputPorts(0);
}
//----------------------------------------------------------------------------
void vtkGlobeSource::ComputeGlobePoint(
double theta, double phi, double radius, double* x, double* normal)
{
// Lets keep this conversion code in a single place.
double tmp = cos( vtkMath::RadiansFromDegrees( phi ) );
double n0 = -tmp * sin( vtkMath::RadiansFromDegrees( theta ) );
double n1 = tmp * cos( vtkMath::RadiansFromDegrees( theta ) );
double n2 = sin( vtkMath::RadiansFromDegrees( phi ) );
x[0] = n0 * radius;
x[1] = n1 * radius;
x[2] = n2 * radius;
if (normal)
{
normal[0] = n0;
normal[1] = n1;
normal[2] = n2;
}
}
//----------------------------------------------------------------------------
void vtkGlobeSource::ComputeLatitudeLongitude(
double* x, double& theta, double& phi)
{
double rho = sqrt(x[0]*x[0] + x[1]*x[1] + x[2]*x[2]);
double S = sqrt(x[0]*x[0] + x[1]*x[1]);
phi = acos(x[2] / rho);
if (x[0] >= 0)
{
theta = asin(x[1] / S);
}
else
{
theta = vtkMath::Pi() - asin(x[1] / S);
}
phi = vtkMath::DegreesFromRadians( vtkMath::Pi() / 2.0 - phi );
theta = vtkMath::DegreesFromRadians( theta - vtkMath::Pi()/2.0 );
}
//----------------------------------------------------------------------------
void vtkGlobeSource::AddPoint(
double theta, double phi, double radius,
vtkPoints* newPoints, vtkFloatArray* newNormals,
vtkFloatArray* newLongitudeArray, vtkFloatArray* newLatitudeArray,
vtkDoubleArray* newLatLongArray)
{
double x[3], n[3];
vtkGlobeSource::ComputeGlobePoint(theta, phi, radius, x, n);
x[0] -= this->Origin[0];
x[1] -= this->Origin[1];
x[2] -= this->Origin[2];
newPoints->InsertNextPoint(x);
newNormals->InsertNextTuple(n);
newLongitudeArray->InsertNextValue(theta);
newLatitudeArray->InsertNextValue(phi);
newLatLongArray->InsertNextValue(phi);
newLatLongArray->InsertNextValue(theta);
}
//----------------------------------------------------------------------------
int vtkGlobeSource::RequestData(
vtkInformation *vtkNotUsed(request),
vtkInformationVector **vtkNotUsed(inputVector),
vtkInformationVector *outputVector)
{
// get the info object
vtkInformation *outInfo = outputVector->GetInformationObject(0);
// I used this to see if the background thread was really
// operating asynchronously.
//Sleep(2000);
// I am going to compute the curtain height based on the level of the
// terrain patch.
if(this->AutoCalculateCurtainHeight)
{
this->CurtainHeight = (this->EndLongitude-this->StartLongitude)
* this->Radius / 3600.0;
}
// get the ouptut
vtkPolyData *output = vtkPolyData::SafeDownCast(
outInfo->Get(vtkDataObject::DATA_OBJECT()));
int i, j;
int numPts, numPolys;
vtkPoints *newPoints;
vtkFloatArray *newLongitudeArray;
vtkFloatArray *newLatitudeArray;
vtkDoubleArray *newLatLongArray;
vtkFloatArray *newNormals;
vtkCellArray *newPolys;
double phi, theta;
vtkIdType pts[4];
// Set things up; allocate memory
//
numPts = this->LatitudeResolution * this->LongitudeResolution;
// creating triangles
numPolys = (this->LatitudeResolution-1)*(this->LongitudeResolution-1) * 2;
// Add more for curtains.
numPts += 2*(this->LatitudeResolution + this->LongitudeResolution);
newPoints = vtkPoints::New();
newPoints->Allocate(numPts);
newNormals = vtkFloatArray::New();
newNormals->SetNumberOfComponents(3);
newNormals->Allocate(3*numPts);
newNormals->SetName("Normals");
newLongitudeArray = vtkFloatArray::New();
newLongitudeArray->SetNumberOfComponents(1);
newLongitudeArray->Allocate(numPts);
newLongitudeArray->SetName("Longitude");
newLatitudeArray = vtkFloatArray::New();
newLatitudeArray->SetNumberOfComponents(1);
newLatitudeArray->Allocate(numPts);
newLatitudeArray->SetName("Latitude");
newLatLongArray = vtkDoubleArray::New();
newLatLongArray->SetNumberOfComponents(2);
newLatLongArray->Allocate(2*numPts);
newLatLongArray->SetName("LatLong");
newPolys = vtkCellArray::New();
newPolys->Allocate(newPolys->EstimateSize(numPolys, 3));
// Create sphere
//
double deltaLongitude;
double deltaLatitude;
// Check data, determine increments, and convert to radians
deltaLongitude = (this->EndLongitude - this->StartLongitude)
/ static_cast<double>(this->LongitudeResolution-1);
deltaLatitude = (this->EndLatitude - this->StartLatitude)
/ static_cast<double>(this->LatitudeResolution-1);
// Create points and point data.
for (j=0; j<this->LatitudeResolution; j++)
{
phi = this->StartLatitude + j*deltaLatitude;
for (i=0; i < this->LongitudeResolution; i++)
{
theta = this->StartLongitude + i*deltaLongitude;
this->AddPoint(theta, phi, this->Radius,
newPoints, newNormals,
newLongitudeArray, newLatitudeArray,
newLatLongArray);
}
this->UpdateProgress(
0.10 + 0.50*j/static_cast<float>(this->LatitudeResolution));
}
// Create the extra points for the curtains.
for (i=0; i < this->LongitudeResolution; i++)
{
theta = this->StartLongitude + i*deltaLongitude;
phi = this->StartLatitude;
this->AddPoint(theta, phi, this->Radius-this->CurtainHeight,
newPoints, newNormals,
newLongitudeArray, newLatitudeArray,
newLatLongArray);
}
for (i=0; i < this->LongitudeResolution; i++)
{
theta = this->StartLongitude + i*deltaLongitude;
phi = this->EndLatitude;
this->AddPoint(theta, phi, this->Radius-this->CurtainHeight,
newPoints, newNormals,
newLongitudeArray, newLatitudeArray,
newLatLongArray);
}
for (j=0; j < this->LatitudeResolution; j++)
{
theta = this->StartLongitude;
phi = this->StartLatitude + j*deltaLatitude;
this->AddPoint(theta, phi, this->Radius-this->CurtainHeight,
newPoints, newNormals,
newLongitudeArray, newLatitudeArray,
newLatLongArray);
}
for (j=0; j < this->LatitudeResolution; j++)
{
theta = this->EndLongitude;
phi = this->StartLatitude + j*deltaLatitude;
this->AddPoint(theta, phi, this->Radius-this->CurtainHeight,
newPoints, newNormals,
newLongitudeArray, newLatitudeArray,
newLatLongArray);
}
// Generate mesh connectivity
vtkIdType rowId = 0;
vtkIdType cornerId;
for (j=1; j < this->LatitudeResolution; ++j)
{
cornerId = rowId;
for (i=1; i < this->LongitudeResolution; ++i)
{
pts[0] = cornerId;
pts[2] = cornerId + this->LongitudeResolution;
pts[1] = pts[2] + 1;
newPolys->InsertNextCell(3, pts);
pts[2] = pts[1];
pts[1] = cornerId + 1;
newPolys->InsertNextCell(3, pts);
++cornerId;
}
rowId += this->LongitudeResolution;
this->UpdateProgress(
0.70 + 0.30*j/static_cast<double>(this->LatitudeResolution));
}
// Create curtain quads.
vtkIdType curtainPointId =
this->LongitudeResolution * this->LatitudeResolution;
vtkIdType edgeOffset;
edgeOffset = 0;
for (i=1; i < this->LongitudeResolution; ++i)
{
pts[0] = edgeOffset + i; // i starts at 1.
pts[1] = pts[0] - 1;
pts[2] = curtainPointId;
pts[3] = curtainPointId + 1;
newPolys->InsertNextCell(4, pts);
++curtainPointId;
}
++curtainPointId; // Skip 2 to the next edge.
edgeOffset = (this->LongitudeResolution)*(this->LatitudeResolution-1);
for (i=1; i < this->LongitudeResolution; ++i)
{
pts[0] = edgeOffset + i - 1; // i starts at 1
pts[1] = pts[0] + 1;
pts[2] = curtainPointId + 1;
pts[3] = curtainPointId;
newPolys->InsertNextCell(4, pts);
++curtainPointId;
}
++curtainPointId;
edgeOffset = 0;
for (j=1; j < this->LatitudeResolution; ++j)
{
pts[0] = edgeOffset + j*this->LongitudeResolution;
pts[1] = pts[0] - this->LongitudeResolution;
pts[2] = curtainPointId;
pts[3] = curtainPointId + 1;
newPolys->InsertNextCell(4, pts);
++curtainPointId;
}
++curtainPointId;
edgeOffset = (this->LongitudeResolution-1);
for (j=1; j < this->LatitudeResolution; ++j)
{
pts[0] = edgeOffset + (j-1)*this->LongitudeResolution;
pts[1] = pts[0] + this->LongitudeResolution;
pts[2] = curtainPointId + 1;
pts[3] = curtainPointId;
newPolys->InsertNextCell(4, pts);
++curtainPointId;
}
// Update ourselves and release memeory
//
newPoints->Squeeze();
output->SetPoints(newPoints);
newPoints->Delete();
newNormals->Squeeze();
output->GetPointData()->SetNormals(newNormals);
newNormals->Delete();
newLongitudeArray->Squeeze();
output->GetPointData()->AddArray(newLongitudeArray);
newLongitudeArray->Delete();
newLatitudeArray->Squeeze();
output->GetPointData()->AddArray(newLatitudeArray);
newLatitudeArray->Delete();
newLatLongArray->Squeeze();
output->GetPointData()->AddArray(newLatLongArray);
newLatLongArray->Delete();
newPolys->Squeeze();
output->SetPolys(newPolys);
newPolys->Delete();
return 1;
}
//----------------------------------------------------------------------------
void vtkGlobeSource::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
os << indent << "AutoCalculateCurtainHeight: " <<
(this->AutoCalculateCurtainHeight ? "ON" : "OFF") << "\n";
os << indent << "CurtainHeight: " << this->CurtainHeight << "\n";
os << indent << "Longitude Resolution: " << this->LongitudeResolution << "\n";
os << indent << "Latitude Resolution: " << this->LatitudeResolution << "\n";
os << indent << "Longitude Start: " << this->StartLongitude << "\n";
os << indent << "Latitude Start: " << this->StartLatitude << "\n";
os << indent << "Longitude End: " << this->EndLongitude << "\n";
os << indent << "Latitude End: " << this->EndLatitude << "\n";
os << indent << "Radius: " << this->Radius << "\n";
os << indent << "Origin: " << this->Origin[0] << ","
<< this->Origin[1] << ","
<< this->Origin[2] << "\n";
os << indent
<< "Quadrilateral Tessellation: "
<< this->QuadrilateralTessellation << "\n";
}