mirror of
https://github.com/OpenFOAM/ThirdParty-6.git
synced 2025-12-08 06:57:43 +00:00
390 lines
12 KiB
C++
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";
|
|
}
|