ParaView-5.0.1: Added the source-tree to ThirdParty-dev and patched as described in the README file

Resolves bug-report http://bugs.openfoam.org/view.php?id=2098
This commit is contained in:
Henry Weller
2016-05-30 21:20:56 +01:00
parent 1cce60aa78
commit eba760a6d6
24640 changed files with 6366069 additions and 0 deletions

View File

@ -0,0 +1,36 @@
set(Module_SRCS
vtkCompassRepresentation.cxx
vtkCompassWidget.cxx
vtkGeoAdaptiveArcs.cxx
vtkGeoAlignedImageSource.cxx
vtkGeoArcs.cxx
vtkGeoAssignCoordinates.cxx
vtkGeoCamera.cxx
vtkGeoFileImageSource.cxx
vtkGeoFileTerrainSource.cxx
vtkGeoGlobeSource.cxx
vtkGeoGraticule.cxx
vtkGeoImageNode.cxx
vtkGeoInteractorStyle.cxx
vtkGeoProjection.cxx
vtkGeoProjectionSource.cxx
vtkGeoRandomGraphSource.cxx
vtkGeoSampleArcs.cxx
vtkGeoSource.cxx
vtkGeoSphereTransform.cxx
vtkGeoTerrain.cxx
vtkGeoTerrain2D.cxx
vtkGeoTerrainNode.cxx
vtkGeoTransform.cxx
vtkGeoTreeNode.cxx
vtkGeoTreeNodeCache.cxx
vtkGlobeSource.cxx
vtkGeoAlignedImageRepresentation.cxx
)
set_source_files_properties(
vtkGeoSource
ABSTRACT
)
vtk_module_library(vtkGeovisCore ${Module_SRCS})

View File

@ -0,0 +1,15 @@
vtk_add_test_cxx(${vtk-module}CxxTests tests
TestGeoAssignCoordinates.cxx
TestGeoGraticule.cxx
TestGeoProjection.cxx,NO_VALID
TestGlobeSource.cxx
)
if(NOT VTK_REPLACE_OPENGL_OVERRIDES)
vtk_add_test_cxx(${vtk-module}CxxTests tests
TestCoincidentGeoGraphRepresentation2D.cxx
TestLabeledGeoView2D.cxx
)
endif()
vtk_test_cxx_executable(${vtk-module}CxxTests tests)

View File

@ -0,0 +1,285 @@
/*=========================================================================
Program: Visualization Toolkit
Module: TestCoincidentGeoGraphRepresentation2D.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.
-------------------------------------------------------------------------*/
// .SECTION Description
#include "vtkCamera.h"
#include "vtkDataObject.h"
#include "vtkDataSetAttributes.h"
#include "vtkDoubleArray.h"
#include "vtkGeoAlignedImageSource.h"
#include "vtkGeoAlignedImageRepresentation.h"
#include "vtkGeoFileImageSource.h"
#include "vtkGeoFileTerrainSource.h"
#include "vtkGeoProjection.h"
#include "vtkGeoProjectionSource.h"
#include "vtkGeoTransform.h"
#include "vtkGeoTerrain2D.h"
#include "vtkGeoTerrainNode.h"
#include "vtkGeoView2D.h"
#include "vtkGraphLayoutView.h"
#include "vtkIdTypeArray.h"
#include "vtkJPEGReader.h"
#include "vtkMath.h"
#include "vtkMutableUndirectedGraph.h"
#include "vtkPolyData.h"
#include "vtkRegressionTestImage.h"
#include "vtkRenderedGraphRepresentation.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkSmartPointer.h"
#include "vtkStdString.h"
#include "vtkTestUtilities.h"
#include "vtkTIFFReader.h"
#include <sstream>
int TestCoincidentGeoGraphRepresentation2D(int argc, char* argv[])
{
int projNum = 44;
char* fname = vtkTestUtilities::ExpandDataFileName(
argc, argv, "Data/NE2_ps_bath_small.jpg");
vtkStdString imageFile = fname;
// Create the view
vtkSmartPointer<vtkGeoView2D> view = vtkSmartPointer<vtkGeoView2D>::New();
view->DisplayHoverTextOff();
view->GetRenderWindow()->SetMultiSamples(0); // ensure to have the same test image everywhere
// Create the terrain
vtkSmartPointer<vtkGeoTerrain2D> terrain =
vtkSmartPointer<vtkGeoTerrain2D>::New();
vtkSmartPointer<vtkGeoSource> terrainSource;
vtkGeoProjectionSource* projSource = vtkGeoProjectionSource::New();
projSource->SetProjection(projNum);
projSource->Initialize();
vtkSmartPointer<vtkGeoTransform> transform =
vtkSmartPointer<vtkGeoTransform>::New();
vtkSmartPointer<vtkGeoProjection> proj =
vtkSmartPointer<vtkGeoProjection>::New();
proj->SetName(vtkGeoProjection::GetProjectionName(projNum));
transform->SetDestinationProjection(proj);
terrainSource.TakeReference(projSource);
terrain->SetSource(terrainSource);
view->SetSurface(terrain);
// Create background image
vtkSmartPointer<vtkGeoAlignedImageRepresentation> imageRep =
vtkSmartPointer<vtkGeoAlignedImageRepresentation>::New();
vtkSmartPointer<vtkGeoSource> imageSource;
vtkGeoAlignedImageSource* alignedSource = vtkGeoAlignedImageSource::New();
vtkSmartPointer<vtkJPEGReader> reader =
vtkSmartPointer<vtkJPEGReader>::New();
reader->SetFileName(imageFile.c_str());
reader->Update();
alignedSource->SetImage(reader->GetOutput());
imageSource.TakeReference(alignedSource);
imageSource->Initialize();
imageRep->SetSource(imageSource);
view->AddRepresentation(imageRep);
// Add a graph representation
vtkSmartPointer<vtkMutableUndirectedGraph> graph =
vtkSmartPointer<vtkMutableUndirectedGraph>::New();
vtkSmartPointer<vtkDoubleArray> latArr =
vtkSmartPointer<vtkDoubleArray>::New();
vtkSmartPointer<vtkDoubleArray> lonArr =
vtkSmartPointer<vtkDoubleArray>::New();
latArr->SetNumberOfTuples(128);
lonArr->SetNumberOfTuples(128);
latArr->SetName("latitude");
lonArr->SetName("longitude");
vtkSmartPointer<vtkIdTypeArray> colorScalars =
vtkSmartPointer<vtkIdTypeArray>::New();
colorScalars->SetName("stuff");
vtkIdType v;
for (v = 0; v < 20; ++v)
{
latArr->SetValue(v, 0.0);
lonArr->SetValue(v, 0.0);
graph->AddVertex();
}
for (v = 20; v < 40; ++v)
{
latArr->SetValue(v, 42);
lonArr->SetValue(v, -73);
graph->AddVertex();
}
for (v = 40; v < 49; ++v)
{
latArr->SetValue(v, 35);
lonArr->SetValue(v, -106);
graph->AddVertex();
}
for (v = 49; v < 66; ++v)
{
latArr->SetValue(v, 39);
lonArr->SetValue(v, 116);
graph->AddVertex();
}
for (v = 66; v < 80; ++v)
{
latArr->SetValue(v, -31);
lonArr->SetValue(v, 115);
graph->AddVertex();
}
for (v = 80; v < 105; ++v)
{
latArr->SetValue(v, 48.87);
lonArr->SetValue(v, 2.29);
graph->AddVertex();
}
for (v = 105; v < 122; ++v)
{
latArr->SetValue(v, -34.44);
lonArr->SetValue(v, -59.20);
graph->AddVertex();
}
// SANTAREM
latArr->SetValue(122, -2.26);
lonArr->SetValue(122, -54.41);
graph->AddVertex();
// CAIRO
latArr->SetValue(123, 30.03);
lonArr->SetValue(123, 31.15);
graph->AddVertex();
// TEHRAN
latArr->SetValue(124, 35.40);
lonArr->SetValue(124, 51.26);
graph->AddVertex();
// MOSCOW
latArr->SetValue(125, 55.45);
lonArr->SetValue(125, 37.42);
graph->AddVertex();
// CALCUTTA
latArr->SetValue(126, 22.30);
lonArr->SetValue(126, 88.20);
graph->AddVertex();
// JAKARTA
latArr->SetValue(127, -6.08);
lonArr->SetValue(127, 106.45);
graph->AddVertex();
graph->GetVertexData()->AddArray(latArr);
graph->GetVertexData()->AddArray(lonArr);
for (v = 1; v < 20; ++v)
{
graph->AddEdge(0, v);
}
for (v = 21; v < 40; ++v)
{
graph->AddEdge(20, v);
}
for (v = 41; v < 49; ++v)
{
graph->AddEdge(40, v);
}
for (v = 50; v < 66; ++v)
{
graph->AddEdge(49, v);
}
for (v = 67; v < 80; ++v)
{
graph->AddEdge(66, v);
}
for (v = 81; v < 105; ++v)
{
graph->AddEdge(80, v);
}
for (v = 106; v < 122; ++v)
{
graph->AddEdge(105, v);
}
graph->AddEdge(122, 123);
graph->AddEdge(122, 20);
graph->AddEdge(20, 40);
graph->AddEdge(122, 105);
graph->AddEdge(123, 124);
graph->AddEdge(123, 0);
graph->AddEdge(124, 125);
graph->AddEdge(125, 80);
graph->AddEdge(124, 126);
graph->AddEdge(126, 49);
graph->AddEdge(126, 127);
graph->AddEdge(127, 66);
vtkMath::RandomSeed(123456);
for(int i = 0; i < 128; i++)
{
colorScalars->InsertNextValue(
static_cast<vtkIdType>(vtkMath::Random(0, 1024)));
}
graph->GetVertexData()->AddArray(colorScalars);
vtkSmartPointer<vtkRenderedGraphRepresentation> graphRep =
vtkSmartPointer<vtkRenderedGraphRepresentation>::New();
graphRep->SetInputData(graph);
graphRep->SetVertexColorArrayName("stuff");
graphRep->SetColorVerticesByArray(true);
graphRep->SetLayoutStrategyToAssignCoordinates("longitude", "latitude");
view->AddRepresentation(graphRep);
terrain->SetSource(terrainSource);
imageRep->SetSource(imageSource);
// Set up the viewport
view->GetRenderWindow()->SetSize(900, 600);
view->Render();
view->ResetCamera();
view->GetRenderer()->GetActiveCamera()->Zoom(2.1);
view->Render();
int retVal = vtkRegressionTestImage(view->GetRenderWindow());
if (retVal == vtkRegressionTester::DO_INTERACTOR)
{
view->GetInteractor()->Initialize();
view->GetInteractor()->Start();
}
terrainSource->ShutDown();
imageSource->ShutDown();
delete [] fname;
return !retVal;
}

View File

@ -0,0 +1,84 @@
/*=========================================================================
Program: Visualization Toolkit
Module: TestGeoAssignCoordinates.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 "vtkDataSetAttributes.h"
#include "vtkDoubleArray.h"
#include "vtkGeoAssignCoordinates.h"
#include "vtkGraphMapper.h"
#include "vtkMutableDirectedGraph.h"
#include "vtkRegressionTestImage.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkSmartPointer.h"
#define VTK_CREATE(type, name) \
vtkSmartPointer<type> name = vtkSmartPointer<type>::New()
int TestGeoAssignCoordinates(int argc, char *argv[])
{
VTK_CREATE(vtkMutableDirectedGraph, g);
VTK_CREATE(vtkDoubleArray, latitude);
latitude->SetName("latitude");
VTK_CREATE(vtkDoubleArray, longitude);
longitude->SetName("longitude");
for (vtkIdType i = -90; i <= 90; i += 10)
{
for (vtkIdType j = -180; j < 180; j += 20)
{
g->AddVertex();
latitude->InsertNextValue(i);
longitude->InsertNextValue(j);
}
}
g->GetVertexData()->AddArray(latitude);
g->GetVertexData()->AddArray(longitude);
VTK_CREATE(vtkGeoAssignCoordinates, assign);
assign->SetInputData(g);
assign->SetLatitudeArrayName("latitude");
assign->SetLongitudeArrayName("longitude");
assign->SetGlobeRadius(1.0);
assign->Update();
VTK_CREATE(vtkGraphMapper, mapper);
mapper->SetInputConnection(assign->GetOutputPort());
VTK_CREATE(vtkActor, actor);
actor->SetMapper(mapper);
VTK_CREATE(vtkRenderer, ren);
ren->AddActor(actor);
VTK_CREATE(vtkRenderWindowInteractor, iren);
VTK_CREATE(vtkRenderWindow, win);
win->AddRenderer(ren);
win->SetInteractor(iren);
ren->ResetCamera();
int retVal = vtkRegressionTestImage(win);
if (retVal == vtkRegressionTester::DO_INTERACTOR)
{
iren->Initialize();
iren->Start();
retVal = vtkRegressionTester::PASSED;
}
return !retVal;
}

View File

@ -0,0 +1,83 @@
#include "vtkGeoGraticule.h"
#include "vtkActor.h"
#include "vtkGeoProjection.h"
#include "vtkGeoTransform.h"
#include "vtkPNGWriter.h"
#include "vtkPolyDataMapper.h"
#include "vtkRegressionTestImage.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkSmartPointer.h"
#include "vtkTestUtilities.h"
#include "vtkTransformFilter.h"
#include "vtkXMLPolyDataReader.h"
#include "vtkWindowToImageFilter.h"
#define vtkCreateMacro(type, obj) \
vtkSmartPointer<type> obj = vtkSmartPointer<type>::New()
int TestGeoGraticule( int argc, char* argv[] )
{
int latLevel = 2;
int lngLevel = 2;
const char* pname = "rouss";
vtkCreateMacro( vtkGeoGraticule, ggr );
vtkCreateMacro( vtkGeoTransform, xfm );
vtkCreateMacro( vtkGeoProjection, gcs );
vtkCreateMacro( vtkGeoProjection, pcs );
vtkCreateMacro( vtkTransformFilter, xff );
vtkCreateMacro( vtkXMLPolyDataReader, pdr );
vtkCreateMacro( vtkTransformFilter, xf2 );
vtkCreateMacro( vtkPolyDataMapper, mapper );
vtkCreateMacro( vtkPolyDataMapper, mapper2 );
vtkCreateMacro( vtkActor, actor );
vtkCreateMacro( vtkActor, actor2 );
ggr->SetGeometryType( vtkGeoGraticule::POLYLINES );
ggr->SetLatitudeLevel( latLevel );
ggr->SetLongitudeLevel( lngLevel );
ggr->SetLongitudeBounds( -180, 180 );
ggr->SetLatitudeBounds( -90, 90 );
// gcs defaults to latlong.
pcs->SetName( pname );
pcs->SetCentralMeridian( 0. );
xfm->SetSourceProjection( gcs );
xfm->SetDestinationProjection( pcs );
xff->SetInputConnection( ggr->GetOutputPort() );
xff->SetTransform( xfm );
mapper->SetInputConnection( xff->GetOutputPort() );
actor->SetMapper( mapper );
char* input_file = vtkTestUtilities::ExpandDataFileName(
argc, argv, "/Data/political.vtp");
pdr->SetFileName(input_file);
xf2->SetTransform( xfm );
xf2->SetInputConnection( pdr->GetOutputPort() );
mapper2->SetInputConnection( xf2->GetOutputPort() );
actor2->SetMapper( mapper2 );
vtkCreateMacro( vtkRenderWindow, win );
win->SetMultiSamples(0);
vtkCreateMacro( vtkRenderer, ren );
vtkCreateMacro( vtkRenderWindowInteractor, iren );
win->SetInteractor( iren );
win->AddRenderer( ren );
ren->AddActor( actor );
ren->AddActor( actor2 );
win->Render();
int retVal = vtkRegressionTestImage(win);
if (retVal == vtkRegressionTester::DO_INTERACTOR)
{
iren->Initialize();
iren->Start();
}
delete [] input_file;
return !retVal;
};

View File

@ -0,0 +1,19 @@
#include "vtkGeoProjection.h"
int TestGeoProjection( int, char*[] )
{
int np = vtkGeoProjection::GetNumberOfProjections();
cout << "Supported projections:\n";
for ( int i = 0; i < np; ++ i )
{
cout << "Projection: " << vtkGeoProjection::GetProjectionName( i ) << "\n";
cout << "\t" << vtkGeoProjection::GetProjectionDescription( i ) << "\n";
}
cout << "-------\n";
vtkGeoProjection* proj = vtkGeoProjection::New();
const char* projName = "rouss";
proj->SetName( projName );
cout << projName << " is " << proj->GetDescription() << "\n";
proj->Delete();
return 0;
}

View File

@ -0,0 +1,130 @@
/*=========================================================================
Program: Visualization Toolkit
Module: TestGeoView.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 "vtkActor.h"
#include "vtkDoubleArray.h"
#include "vtkGlobeSource.h"
#include "vtkJPEGReader.h"
#include "vtkPolyDataMapper.h"
#include "vtkPointData.h"
#include "vtkRegressionTestImage.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkSmartPointer.h"
#include "vtkStdString.h"
#include "vtkTestUtilities.h"
#include "vtkTransform.h"
#include <vtksys/SystemTools.hxx>
#define VTK_CREATE(type,name) \
vtkSmartPointer<type> name = vtkSmartPointer<type>::New();
int TestGlobeSource(int argc, char* argv[])
{
char* image = vtkTestUtilities::ExpandDataFileName(
argc, argv, "Data/usa_image.jpg");
vtkStdString imageFile = image;
vtkSmartPointer<vtkJPEGReader> reader =
vtkSmartPointer<vtkJPEGReader>::New();
reader->SetFileName(imageFile.c_str());
reader->Update();
double latRange[] = {24, 50};
double longRange[] = {-126, -66};
VTK_CREATE(vtkGlobeSource, globeSource);
globeSource->SetStartLatitude(latRange[0]);
globeSource->SetEndLatitude(latRange[1]);
globeSource->SetStartLongitude(longRange[0]);
globeSource->SetEndLongitude(longRange[1]);
globeSource->Update();
VTK_CREATE(vtkActor, actor);
VTK_CREATE(vtkPolyDataMapper, mapper);
VTK_CREATE(vtkDoubleArray, textureCoords);
textureCoords->SetNumberOfComponents(2);
vtkDoubleArray* array = vtkDoubleArray::SafeDownCast(
globeSource->GetOutput(0)->GetPointData()->GetAbstractArray("LatLong"));
double range[] = { (latRange[0] - latRange[1]),
(longRange[0] - longRange[1])
};
double val[2];
double newVal[2];
// Lower values of lat / long will correspond to
// texture coordinate = 0 (for both s & t).
for(int i=0; i < array->GetNumberOfTuples(); ++i)
{
array->GetTupleValue(i, val);
// Get the texture coordinates in [0,1] range.
newVal[1] = (latRange[0] - val[0]) / range[0];
newVal[0] = (longRange[0] - val[1]) / range[1];
textureCoords->InsertNextTuple(newVal);
}
globeSource->GetOutput(0)->GetPointData()->SetTCoords(textureCoords);
mapper->SetInputConnection( globeSource->GetOutputPort() );
actor->SetMapper(mapper);
VTK_CREATE(vtkTexture, texture);
texture->SetInputConnection(reader->GetOutputPort());
actor->SetTexture(texture);
// Get the right view.
VTK_CREATE(vtkTransform, transform);
transform->RotateY(-90.0);
transform->RotateX(-90.0);
actor->SetUserMatrix(transform->GetMatrix());
VTK_CREATE(vtkRenderWindow, renWin);
VTK_CREATE(vtkRenderWindowInteractor, renWinInt);
VTK_CREATE(vtkRenderer, ren);
ren->AddActor(actor);
renWin->AddRenderer(ren);
renWinInt->SetRenderWindow(renWin);
renWin->SetSize(400,400);
renWin->Render();
renWinInt->Initialize();
renWin->Render();
int retVal = vtkRegressionTestImage( renWin );
if( retVal == vtkRegressionTester::DO_INTERACTOR)
{
renWinInt->Start();
}
delete []image;
return !retVal;
}

View File

@ -0,0 +1,130 @@
/*=========================================================================
Program: Visualization Toolkit
Module: TestLabeledGeoView2D.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.
-------------------------------------------------------------------------*/
// .SECTION Description
#include "vtkCamera.h"
#include "vtkGeoAlignedImageSource.h"
#include "vtkGeoAlignedImageRepresentation.h"
#include "vtkGeoFileImageSource.h"
#include "vtkGeoFileTerrainSource.h"
#include "vtkGeoProjectionSource.h"
#include "vtkGeoRandomGraphSource.h"
#include "vtkGeoTerrain2D.h"
#include "vtkGeoTerrainNode.h"
#include "vtkGeoView2D.h"
#include "vtkJPEGReader.h"
#include "vtkPolyData.h"
#include "vtkRegressionTestImage.h"
#include "vtkRenderedGraphRepresentation.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkSmartPointer.h"
#include "vtkStdString.h"
#include "vtkTestUtilities.h"
#include <sstream>
int TestLabeledGeoView2D(int argc, char* argv[])
{
int proj = 40;
char* fname = vtkTestUtilities::ExpandDataFileName(
argc, argv, "Data/NE2_ps_bath_small.jpg");
vtkStdString imageFile = fname;
// Create the view
vtkSmartPointer<vtkGeoView2D> view = vtkSmartPointer<vtkGeoView2D>::New();
view->DisplayHoverTextOff();
// Create the terrain
vtkSmartPointer<vtkGeoTerrain2D> terrain =
vtkSmartPointer<vtkGeoTerrain2D>::New();
vtkSmartPointer<vtkGeoSource> terrainSource;
vtkGeoProjectionSource* projSource = vtkGeoProjectionSource::New();
projSource->SetProjection(proj);
terrainSource.TakeReference(projSource);
terrainSource->Initialize();
terrain->SetSource(terrainSource);
view->SetSurface(terrain);
// Create background image
vtkSmartPointer<vtkGeoAlignedImageRepresentation> imageRep =
vtkSmartPointer<vtkGeoAlignedImageRepresentation>::New();
vtkSmartPointer<vtkGeoSource> imageSource;
vtkGeoAlignedImageSource* alignedSource = vtkGeoAlignedImageSource::New();
vtkSmartPointer<vtkJPEGReader> reader =
vtkSmartPointer<vtkJPEGReader>::New();
reader->SetFileName(imageFile.c_str());
reader->Update();
alignedSource->SetImage(reader->GetOutput());
imageSource.TakeReference(alignedSource);
imageSource->Initialize();
imageRep->SetSource(imageSource);
view->AddRepresentation(imageRep);
view->SetLabelPlacementModeToNoOverlap();
vtkSmartPointer<vtkGeoRandomGraphSource> graphSource =
vtkSmartPointer<vtkGeoRandomGraphSource>::New();
graphSource->SetNumberOfVertices(1000);
graphSource->SetNumberOfEdges(0);
vtkSmartPointer<vtkRenderedGraphRepresentation> graphRep =
vtkSmartPointer<vtkRenderedGraphRepresentation>::New();
graphRep->SetInputConnection(graphSource->GetOutputPort());
graphRep->SetVertexLabelArrayName("latitude");
graphRep->SetColorVerticesByArray(true);
graphRep->SetVertexColorArrayName("longitude");
graphRep->SetVertexLabelVisibility(true);
graphRep->SetLayoutStrategyToAssignCoordinates("longitude", "latitude");
view->AddRepresentation(graphRep);
// Set up the viewport
view->GetRenderWindow()->SetSize(600, 600);
vtkSmartPointer<vtkGeoTerrainNode> root =
vtkSmartPointer<vtkGeoTerrainNode>::New();
terrainSource->FetchRoot(root);
double bounds[6];
root->GetModel()->GetBounds(bounds);
bounds[0] = bounds[0] - (bounds[1] - bounds[0])*0.01;
bounds[1] = bounds[1] + (bounds[1] - bounds[0])*0.01;
bounds[2] = bounds[2] - (bounds[3] - bounds[2])*0.01;
bounds[3] = bounds[3] + (bounds[3] - bounds[2])*0.01;
double scalex = (bounds[1] - bounds[0])/2.0;
double scaley = (bounds[3] - bounds[2])/2.0;
double scale = (scalex > scaley) ? scalex : scaley;
view->ResetCamera();
view->GetRenderer()->GetActiveCamera()->SetParallelScale(scale);
view->GetRenderWindow()->SetMultiSamples(0);
view->Render();
int retVal = vtkRegressionTestImage(view->GetRenderWindow());
if (retVal == vtkRegressionTester::DO_INTERACTOR)
{
view->GetInteractor()->Initialize();
view->GetInteractor()->Start();
}
terrainSource->ShutDown();
imageSource->ShutDown();
delete [] fname;
return !retVal;
}

View File

@ -0,0 +1 @@
e01bf49e22f38c54cc7a1ca283b327b0

View File

@ -0,0 +1 @@
1c705f422240513ed28db9b20f843edb

View File

@ -0,0 +1 @@
5e2e3810909a17218a799bd5652986c4

View File

@ -0,0 +1 @@
981322b8b8dc7a7275bbd09d75f6176f

View File

@ -0,0 +1 @@
0087f914e60fafcad8b2a720bda407d1

View File

@ -0,0 +1 @@
a237e17712a183b6e3f3e4d839774790

View File

@ -0,0 +1,19 @@
vtk_module(vtkGeovisCore
GROUPS
Rendering
DEPENDS
vtkIOXML
vtkInteractionWidgets
vtkInteractionStyle
vtkInfovisLayout
vtkViewsCore
vtkRenderingCore
vtklibproj4
TEST_DEPENDS
vtkViewsGeovis
vtkViewsInfovis
vtkRenderingCore
vtkRendering${VTK_RENDERING_BACKEND}
vtkTestingRendering
vtkInteractionStyle
)

View File

@ -0,0 +1,809 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkCompassRepresentation.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 "vtkCompassRepresentation.h"
#include "vtkCommand.h"
#include "vtkObjectFactory.h"
#include "vtkPolyDataMapper2D.h"
#include "vtkPoints.h"
#include "vtkCellArray.h"
#include "vtkProperty2D.h"
#include "vtkRenderer.h"
#include "vtkMath.h"
#include "vtkLine.h"
#include "vtkEvent.h"
#include "vtkInteractorObserver.h"
#include "vtkWindow.h"
#include "vtkPointData.h"
#include "vtkPolyData.h"
#include "vtkTextProperty.h"
#include "vtkTextActor.h"
#include "vtkTransform.h"
#include "vtkTransformPolyDataFilter.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkRenderWindow.h"
#include <sstream>
vtkStandardNewMacro(vtkCompassRepresentation);
//----------------------------------------------------------------------
vtkCompassRepresentation::vtkCompassRepresentation()
{
// The coordinates defining the compass
this->Point1Coordinate = vtkCoordinate::New();
this->Point1Coordinate->SetCoordinateSystemToNormalizedViewport();
this->Point1Coordinate->SetValue(0.80,0.80,0.0);
this->Point2Coordinate = vtkCoordinate::New();
this->Point2Coordinate->SetCoordinateSystemToNormalizedViewport();
this->Point2Coordinate->SetValue(0.99,0.99,0.0);
// Default configuration
this->OuterRadius = 0.9;
this->InnerRadius = 0.75;
this->TiltRepresentation =
vtkSmartPointer<vtkCenteredSliderRepresentation>::New();
this->TiltRepresentation->GetPoint1Coordinate()->
SetCoordinateSystemToViewport();
this->TiltRepresentation->GetPoint2Coordinate()->
SetCoordinateSystemToViewport();
this->TiltRepresentation->SetMinimumValue(-15);
this->TiltRepresentation->SetMaximumValue(15);
this->TiltRepresentation->SetValue(0);
this->TiltRepresentation->SetTitleText("tilt");
this->DistanceRepresentation =
vtkSmartPointer<vtkCenteredSliderRepresentation>::New();
this->DistanceRepresentation->GetPoint1Coordinate()->
SetCoordinateSystemToViewport();
this->DistanceRepresentation->GetPoint2Coordinate()->
SetCoordinateSystemToViewport();
this->DistanceRepresentation->SetMinimumValue(0.8);
this->DistanceRepresentation->SetMaximumValue(1.2);
this->DistanceRepresentation->SetValue(1.0);
this->DistanceRepresentation->SetTitleText("dist");
// The points and the transformation for the points. There are a total of
// 73 points two rings of 340 degrees in increments of 10 plus three extra
// points
this->XForm = vtkTransform::New();
this->Points = vtkPoints::New();
this->Points->SetNumberOfPoints(73);
this->BuildRing();
this->RingXForm = vtkTransformPolyDataFilter::New();
this->RingXForm->SetInputData(this->Ring);
this->RingXForm->SetTransform(this->XForm);
this->RingMapper = vtkPolyDataMapper2D::New();
this->RingMapper->SetInputConnection(
this->RingXForm->GetOutputPort());
this->RingProperty = vtkProperty2D::New();
this->RingProperty->SetOpacity(0.5);
this->RingActor = vtkActor2D::New();
this->RingActor->SetMapper(this->RingMapper);
this->RingActor->SetProperty(this->RingProperty);
this->SelectedProperty = vtkProperty2D::New();
this->SelectedProperty->SetOpacity(0.8);
this->LabelProperty = vtkTextProperty::New();
this->LabelProperty->SetFontFamilyToTimes();
this->LabelProperty->SetJustificationToCentered();
//this->LabelProperty->ShadowOn();
this->LabelActor = vtkTextActor::New();
this->LabelActor->SetTextProperty(this->LabelProperty);
this->LabelActor->SetInput("N");
this->LabelActor->GetPositionCoordinate()->
SetCoordinateSystemToViewport();
this->StatusProperty = vtkTextProperty::New();
this->StatusProperty->SetFontFamilyToArial();
//this->StatusProperty->ShadowOn();
this->StatusProperty->SetJustificationToCentered();
this->StatusProperty->SetJustificationToRight();
this->StatusProperty->SetVerticalJustificationToTop();
this->StatusActor = vtkTextActor::New();
this->StatusActor->SetTextProperty(this->StatusProperty);
this->StatusActor->SetInput("0 Degrees");
this->StatusActor->GetPositionCoordinate()->
SetCoordinateSystemToViewport();
this->BuildBackdrop();
this->Heading = 0;
this->Tilt = 0;
this->Distance = 100000;
this->HighlightState = 0;
}
void vtkCompassRepresentation::BuildBackdrop()
{
vtkPolyData *backdropPolyData = vtkPolyData::New();
vtkPoints *pts = vtkPoints::New();
pts->SetNumberOfPoints(4);
pts->SetPoint(0, 0, 0, 0);
pts->SetPoint(1, 1, 0, 0);
pts->SetPoint(2, 1, 1, 0);
pts->SetPoint(3, 0, 1, 0);
backdropPolyData->SetPoints(pts);
pts->Delete();
vtkCellArray *backdrop = vtkCellArray::New();
backdrop->InsertNextCell(4);
backdrop->InsertCellPoint(0);
backdrop->InsertCellPoint(1);
backdrop->InsertCellPoint(2);
backdrop->InsertCellPoint(3);
backdropPolyData->SetPolys(backdrop);
backdrop->Delete();
vtkSmartPointer<vtkUnsignedCharArray> colors =
vtkSmartPointer<vtkUnsignedCharArray>::New();
colors->SetNumberOfComponents(4);
colors->SetNumberOfTuples(4);
unsigned char color[4];
color[0] = 0;
color[1] = 0;
color[2] = 0;
color[3] = 0;
colors->SetTupleValue(0,color);
colors->SetTupleValue(3,color);
color[3] = 80;
colors->SetTupleValue(1,color);
colors->SetTupleValue(2,color);
backdropPolyData->GetPointData()->SetScalars(colors);
this->BackdropMapper = vtkPolyDataMapper2D::New();
this->BackdropMapper->SetInputData(backdropPolyData);
this->BackdropMapper->ScalarVisibilityOn();
backdropPolyData->Delete();
this->Backdrop = vtkActor2D::New();
this->Backdrop->SetMapper(this->BackdropMapper);
this->Backdrop->GetProperty()->SetColor(0,0,0);
//this->Backdrop->GetProperty()->SetOpacity(0.2);
}
void vtkCompassRepresentation::BuildRing()
{
// crate the polydata
this->Ring = vtkPolyData::New();
this->Ring->SetPoints(this->Points);
// build the cells
vtkCellArray *ringCells = vtkCellArray::New();
for (int i = 0; i < 4; ++i)
{
ringCells->InsertNextCell(17);
for (int j = 0; j < 8; ++j)
{
ringCells->InsertCellPoint(i*9+j);
}
for (int j = 0; j < 8; ++j)
{
ringCells->InsertCellPoint(i*9+35+7-j);
}
ringCells->InsertCellPoint(i*9);
}
this->Ring->SetLines(ringCells);
ringCells->Delete();
// add some polys
vtkCellArray *markCells = vtkCellArray::New();
for (int i = 1; i < 4; ++i)
{
markCells->InsertNextCell(3);
markCells->InsertCellPoint(i+69);
markCells->InsertCellPoint(i*9+35);
markCells->InsertCellPoint(i*9+33);
}
this->Ring->SetPolys(markCells);
markCells->Delete();
// build the points
for (int i = 0; i < 35; ++i)
{
this->Points->SetPoint
(i,
this->OuterRadius * cos( vtkMath::RadiansFromDegrees( 10. * ( i + 10 ) ) ),
this->OuterRadius * sin( vtkMath::RadiansFromDegrees( 10. * ( i + 10 ) ) ),
0.0);
this->Points->SetPoint
(i+35,
this->InnerRadius * cos( vtkMath::RadiansFromDegrees( 10. * ( i + 10 ) ) ),
this->InnerRadius * sin( vtkMath::RadiansFromDegrees( 10. * ( i + 10 ) ) ),
0.0);
}
// add the WSE points
this->Points->SetPoint(70,-this->OuterRadius-0.1, 0.0, 0.0);
this->Points->SetPoint(71,0.0,-this->OuterRadius-0.1, 0.0);
this->Points->SetPoint(72,this->OuterRadius+0.1, 0.0, 0.0);
}
//----------------------------------------------------------------------
vtkCompassRepresentation::~vtkCompassRepresentation()
{
this->Backdrop->Delete();
this->BackdropMapper->Delete();
this->Point1Coordinate->Delete();
this->Point2Coordinate->Delete();
this->XForm->Delete();
this->Points->Delete();
this->Ring->Delete();
this->RingXForm->Delete();
this->RingMapper->Delete();
this->RingActor->Delete();
this->RingProperty->Delete();
this->SelectedProperty->Delete();
this->LabelProperty->Delete();
this->LabelActor->Delete();
this->StatusProperty->Delete();
this->StatusActor->Delete();
}
//----------------------------------------------------------------------
vtkCoordinate *vtkCompassRepresentation::GetPoint1Coordinate()
{
return this->Point1Coordinate;
}
//----------------------------------------------------------------------
void vtkCompassRepresentation
::StartWidgetInteraction(double eventPos[2])
{
this->ComputeInteractionState(static_cast<int>(eventPos[0]),
static_cast<int>(eventPos[1]));
}
//----------------------------------------------------------------------
void vtkCompassRepresentation::TiltWidgetInteraction(double eventPos[2])
{
this->TiltRepresentation->WidgetInteraction(eventPos);
}
//----------------------------------------------------------------------
void vtkCompassRepresentation::DistanceWidgetInteraction(double eventPos[2])
{
this->DistanceRepresentation->WidgetInteraction(eventPos);
}
//----------------------------------------------------------------------
void vtkCompassRepresentation::WidgetInteraction(double eventPos[2])
{
// adjust the value
int center[2];
double rsize;
this->GetCenterAndUnitRadius(center, rsize);
vtkRenderWindowInteractor *rwi =
this->Renderer->GetRenderWindow()->GetInteractor();
// how far did we move?
double mousePt[3];
mousePt[2] = 0;
mousePt[0] = rwi->GetLastEventPosition()[0] - center[0];
mousePt[1] = rwi->GetLastEventPosition()[1] - center[1];
vtkMath::Normalize(mousePt);
double angle1 = atan2(mousePt[1],mousePt[0]);
mousePt[0] = eventPos[0] - center[0];
mousePt[1] = eventPos[1] - center[1];
vtkMath::Normalize(mousePt);
double angle2 = atan2(mousePt[1],mousePt[0]);
angle2 = angle2 - angle1;
this->Heading = this->Heading + angle2*0.5/vtkMath::Pi();
this->BuildRepresentation();
}
//----------------------------------------------------------------------
vtkCoordinate *vtkCompassRepresentation::GetPoint2Coordinate()
{
return this->Point2Coordinate;
}
//----------------------------------------------------------------------
void vtkCompassRepresentation::PlaceWidget(double *vtkNotUsed(bds[6]))
{
// Position the handles at the end of the lines
this->BuildRepresentation();
}
//----------------------------------------------------------------------
void vtkCompassRepresentation::Highlight(int highlight)
{
if (highlight == this->HighlightState)
{
return;
}
this->HighlightState = highlight;
if ( highlight )
{
this->RingActor->SetProperty(this->SelectedProperty);
}
else
{
this->RingActor->SetProperty(this->RingProperty);
}
this->TiltRepresentation->Highlight(highlight);
this->DistanceRepresentation->Highlight(highlight);
}
//----------------------------------------------------------------------
void vtkCompassRepresentation::BuildRepresentation()
{
if ( this->GetMTime() <= this->BuildTime &&
(!this->Renderer || !this->Renderer->GetVTKWindow() ||
this->Renderer->GetVTKWindow()->GetMTime() <= this->BuildTime) )
{
return;
}
int *size = this->Renderer->GetSize();
if (0 == size[0] || 0 == size[1])
{
// Renderer has no size yet: wait until the next
// BuildRepresentation...
return;
}
this->XForm->Identity();
int center[2];
double rsize;
this->GetCenterAndUnitRadius( center, rsize );
while( this->Heading < 0 )
{
this->Heading += 1;
}
while( this->Heading > 1 )
{
this->Heading -= 1;
}
double angle = this->Heading * 2.0 * vtkMath::Pi();
this->XForm->Translate( center[0], center[1], 0.0 ) ;
this->XForm->Scale( rsize, rsize, 1.0 );
this->XForm->RotateZ( vtkMath::DegreesFromRadians( angle ) );
this->LabelActor->SetPosition
( center[0] + rsize * cos( angle + vtkMath::Pi() / 2.0 ) * this->InnerRadius,
center[1] + rsize * sin( angle + vtkMath::Pi() / 2.0 ) * this->InnerRadius );
double fsize = 1.4 * rsize * this->InnerRadius * sin( vtkMath::RadiansFromDegrees( 18. ) );
this->LabelActor->SetOrientation( vtkMath::DegreesFromRadians( angle ) );
this->LabelProperty->SetFontSize( static_cast<int>( fsize ) );
if (rsize > 40)
{
std::ostringstream out;
out.setf( ios::fixed );
out.precision(0);
out << "Distance: ";
if (this->Distance > 10000)
{
out << this->Distance/1000 << "km";
}
else
{
out << this->Distance << "m";
}
out << "\nTilt: " << this->Tilt;
out << "\nHeading: " << vtkMath::DegreesFromRadians( angle );
this->LabelProperty->SetFontSize( static_cast<int>( fsize*0.8 ) );
this->StatusProperty->SetFontSize( static_cast<int>( fsize*0.9 ) );
this->StatusActor->SetInput( out.str().c_str() );
this->StatusActor->SetPosition
( center[0] - rsize * 2.0, center[1] + rsize );
}
else
{
this->StatusActor->SetInput("");
}
// adjust the slider as well
this->TiltRepresentation->GetPoint1Coordinate()->
SetValue( center[0] - rsize * 1.5,
center[1] - rsize, 0.0 );
this->TiltRepresentation->GetPoint2Coordinate()->
SetValue( center[0] - rsize * 1.2, center[1] + rsize, 0.0 );
this->TiltRepresentation->Modified();
this->TiltRepresentation->BuildRepresentation();
// adjust the slider as well
this->DistanceRepresentation->GetPoint1Coordinate()->
SetValue( center[0] - rsize * 1.9,
center[1] - rsize, 0.0 );
this->DistanceRepresentation->GetPoint2Coordinate()->
SetValue( center[0] - rsize * 1.6, center[1] + rsize, 0.0 );
this->DistanceRepresentation->Modified();
this->DistanceRepresentation->BuildRepresentation();
int *renSize = this->Renderer->GetSize();
vtkUnsignedCharArray* colors =
vtkUnsignedCharArray::SafeDownCast
( this->BackdropMapper->GetInput()->GetPointData()->GetScalars() );
unsigned char color[4];
color[0] = 0;
color[1] = 0;
color[2] = 0;
vtkPoints *pts =
this->BackdropMapper->GetInput()->GetPoints();
pts->SetPoint( 1, renSize[0], center[1] - rsize * 1.1, 0 );
pts->SetPoint( 2, renSize[0], renSize[1], 0 );
if (this->HighlightState)
{
pts->SetPoint( 0, center[0] - rsize * 5.0, center[1] - rsize * 1.1, 0 );
pts->SetPoint( 3, center[0] - rsize * 5.0, renSize[1], 0 );
color[3] = 80;
colors->SetTupleValue(1,color);
}
else
{
pts->SetPoint( 0, center[0] - rsize * 3.0, center[1] - rsize * 1.1, 0 );
pts->SetPoint( 3, center[0] - rsize * 3.0, renSize[1], 0 );
color[3] = 0;
colors->SetTupleValue( 1, color );
}
pts->Modified();
colors->Modified();
this->BackdropMapper->GetInput()->Modified();
this->BackdropMapper->Modified();
this->BuildTime.Modified();
}
//----------------------------------------------------------------------
void vtkCompassRepresentation::GetActors(vtkPropCollection *pc)
{
pc->AddItem(this->Backdrop);
pc->AddItem(this->RingActor);
pc->AddItem(this->LabelActor);
pc->AddItem(this->StatusActor);
this->TiltRepresentation->GetActors(pc);
this->DistanceRepresentation->GetActors(pc);
}
//----------------------------------------------------------------------
void vtkCompassRepresentation::ReleaseGraphicsResources(vtkWindow *w)
{
this->Backdrop->ReleaseGraphicsResources(w);
this->RingActor->ReleaseGraphicsResources(w);
this->LabelActor->ReleaseGraphicsResources(w);
this->StatusActor->ReleaseGraphicsResources(w);
this->TiltRepresentation->ReleaseGraphicsResources(w);
this->DistanceRepresentation->ReleaseGraphicsResources(w);
}
//----------------------------------------------------------------------
int vtkCompassRepresentation
::RenderOpaqueGeometry(vtkViewport *viewport)
{
this->BuildRepresentation();
int count = 0;
count += this->Backdrop->RenderOpaqueGeometry(viewport);
if (this->HighlightState)
{
if (strlen(this->StatusActor->GetInput()))
{
count += this->StatusActor->RenderOpaqueGeometry(viewport);
}
}
count += this->RingActor->RenderOpaqueGeometry(viewport);
count += this->LabelActor->RenderOpaqueGeometry(viewport);
count += this->TiltRepresentation->RenderOpaqueGeometry(viewport);
count += this->DistanceRepresentation->RenderOpaqueGeometry(viewport);
return count;
}
//----------------------------------------------------------------------
int vtkCompassRepresentation::RenderOverlay(vtkViewport *viewport)
{
this->BuildRepresentation();
int count = 0;
count += this->Backdrop->RenderOverlay(viewport);
if (this->HighlightState)
{
if (strlen(this->StatusActor->GetInput()))
{
count += this->StatusActor->RenderOverlay(viewport);
}
}
count += this->RingActor->RenderOverlay(viewport);
count += this->LabelActor->RenderOverlay(viewport);
count += this->TiltRepresentation->RenderOverlay(viewport);
count += this->DistanceRepresentation->RenderOverlay(viewport);
return count;
}
double vtkCompassRepresentation::GetHeading()
{
return this->Heading;
}
void vtkCompassRepresentation::SetHeading(double v)
{
this->Heading = v;
if (this->Renderer)
{
this->BuildRepresentation();
}
}
double vtkCompassRepresentation::GetTilt()
{
return this->Tilt;
}
void vtkCompassRepresentation::SetTilt(double v)
{
this->Tilt = v;
if (this->Tilt > 90)
{
this->Tilt = 90;
}
if (this->Tilt < 0)
{
this->Tilt = 0;
}
}
void vtkCompassRepresentation::EndTilt()
{
this->TiltRepresentation->SetValue(0);
}
void vtkCompassRepresentation::UpdateTilt(double time)
{
double val = this->TiltRepresentation->GetValue();
this->SetTilt(this->Tilt + val*time);
}
double vtkCompassRepresentation::GetDistance()
{
return this->Distance;
}
void vtkCompassRepresentation::SetDistance(double v)
{
this->Distance = v;
if (this->Distance < 5)
{
this->Distance = 5;
}
}
void vtkCompassRepresentation::EndDistance()
{
this->DistanceRepresentation->SetValue(1.0);
}
void vtkCompassRepresentation::UpdateDistance(double time)
{
double val = this->DistanceRepresentation->GetValue();
this->SetDistance(this->Distance*(1 + (1.0/val - 1)*time));
}
void vtkCompassRepresentation::GetCenterAndUnitRadius(int center[2],
double &radius)
{
// we always fit in the bounding box, but we try to be smart :)
// We stick to the upper right and as the size increases we
// scale in a non-linear manner
int *p1 = this->Point1Coordinate->GetComputedViewportValue(this->Renderer);
int *p2 = this->Point2Coordinate->GetComputedViewportValue(this->Renderer);
radius = abs(p1[0] - p2[0]);
if (abs(p1[1] - p2[1]) < radius)
{
radius = abs(p1[1] - p2[1]);
}
radius /= 2;
// scale the rsize between 100% and 50%
double scale = 1.0 - (radius-40)/(radius+100.0)*0.5;
if (scale > 1.0)
{
scale = 1.0;
}
radius *= scale;
// stick to the upper right
center[0] = static_cast<int>(p2[0] - radius);
center[1] = static_cast<int>(p2[1] - radius);
if (this->HighlightState == 0)
{
// create a reduced size when not highlighted by applying the scale
// again, only do it when there is a significant difference
if (scale < 0.9)
{
radius = radius*scale*scale;
}
}
}
//----------------------------------------------------------------------
void vtkCompassRepresentation::PrintSelf(ostream& os, vtkIndent indent)
{
//Superclass typedef defined in vtkTypeMacro() found in vtkSetGet.h
this->Superclass::PrintSelf(os,indent);
os << indent << "Label Text: " << (this->LabelActor->GetInput() ?
this->LabelActor->GetInput() :
"(none)") << "\n";
os << indent << "Point1 Coordinate: " << this->Point1Coordinate << "\n";
this->Point1Coordinate->PrintSelf(os, indent.GetNextIndent());
os << indent << "Point2 Coordinate: " << this->Point2Coordinate << "\n";
this->Point2Coordinate->PrintSelf(os, indent.GetNextIndent());
if ( this->SelectedProperty )
{
os << indent << "SelectedProperty:\n";
this->SelectedProperty->PrintSelf(os,indent.GetNextIndent());
}
else
{
os << indent << "SelectedProperty: (none)\n";
}
if ( this->RingProperty )
{
os << indent << "RingProperty:\n";
this->RingProperty->PrintSelf(os,indent.GetNextIndent());
}
else
{
os << indent << "RingProperty: (none)\n";
}
if ( this->SelectedProperty )
{
os << indent << "SelectedProperty:\n";
this->SelectedProperty->PrintSelf(os,indent.GetNextIndent());
}
else
{
os << indent << "SelectedProperty: (none)\n";
}
if ( this->LabelProperty )
{
os << indent << "LabelProperty:\n";
this->LabelProperty->PrintSelf(os,indent.GetNextIndent());
}
else
{
os << indent << "LabelProperty: (none)\n";
}
}
//----------------------------------------------------------------------
int vtkCompassRepresentation::ComputeInteractionState(int x, int y,
int modify)
{
int *size = this->Renderer->GetSize();
if (0 == size[0] || 0 == size[1])
{
// Renderer has no size yet
this->InteractionState = vtkCompassRepresentation::Outside;
return this->InteractionState;
}
// is the pick on the ring?
int center[2];
double rsize;
this->GetCenterAndUnitRadius(center, rsize);
double radius = sqrt(static_cast<double>((x - center[0])*(x - center[0]) +
(y - center[1])*(y - center[1])));
if (radius < rsize*this->OuterRadius + 2 &&
radius > rsize*this->InnerRadius - 2)
{
this->InteractionState = vtkCompassRepresentation::Adjusting;
return this->InteractionState;
}
// on tilt?
int tiltState =
this->TiltRepresentation->ComputeInteractionState(x,y,modify);
if (tiltState != vtkCenteredSliderRepresentation::Outside)
{
switch (tiltState)
{
case vtkSliderRepresentation::LeftCap:
this->InteractionState = vtkCompassRepresentation::TiltDown;
break;
case vtkSliderRepresentation::RightCap:
this->InteractionState = vtkCompassRepresentation::TiltUp;
break;
case vtkSliderRepresentation::Slider:
this->InteractionState = vtkCompassRepresentation::TiltAdjusting;
break;
}
return this->InteractionState;
}
// on dist?
int distanceState =
this->DistanceRepresentation->ComputeInteractionState(x,y,modify);
if (distanceState != vtkCenteredSliderRepresentation::Outside)
{
switch (distanceState)
{
case vtkSliderRepresentation::LeftCap:
this->InteractionState = vtkCompassRepresentation::DistanceOut;
break;
case vtkSliderRepresentation::RightCap:
this->InteractionState = vtkCompassRepresentation::DistanceIn;
break;
case vtkSliderRepresentation::Slider:
this->InteractionState = vtkCompassRepresentation::DistanceAdjusting;
break;
}
return this->InteractionState;
}
if (radius < rsize*3.0)
{
this->InteractionState = vtkCompassRepresentation::Inside;
return this->InteractionState;
}
this->InteractionState = vtkCompassRepresentation::Outside;
return this->InteractionState;
}
//----------------------------------------------------------------------
void vtkCompassRepresentation::SetRenderer(vtkRenderer *ren)
{
this->Superclass::SetRenderer(ren);
this->TiltRepresentation->SetRenderer(ren);
this->DistanceRepresentation->SetRenderer(ren);
}

View File

@ -0,0 +1,203 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkCompassRepresentation.h
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.
-------------------------------------------------------------------------*/
// .NAME vtkCompassRepresentation - provide a compass
// .SECTION Description
// This class is used to represent and render a compass.
#ifndef vtkCompassRepresentation_h
#define vtkCompassRepresentation_h
#include "vtkGeovisCoreModule.h" // For export macro
#include "vtkContinuousValueWidgetRepresentation.h"
#include "vtkCoordinate.h" // For vtkViewportCoordinateMacro
#include "vtkCenteredSliderRepresentation.h" // to use in a SP
#include "vtkSmartPointer.h" // used for SmartPointers
class vtkActor2D;
class vtkPoints;
class vtkCellArray;
class vtkPolyData;
class vtkPolyDataMapper2D;
class vtkCoordinate;
class vtkProperty2D;
class vtkPropCollection;
class vtkWindow;
class vtkViewport;
class vtkTransform;
class vtkTransformPolyDataFilter;
class vtkTextProperty;
class vtkTextActor;
class VTKGEOVISCORE_EXPORT vtkCompassRepresentation :
public vtkContinuousValueWidgetRepresentation
{
public:
// Description:
// Instantiate the class.
static vtkCompassRepresentation *New();
// Description:
// Standard methods for the class.
vtkTypeMacro(vtkCompassRepresentation,
vtkContinuousValueWidgetRepresentation);
void PrintSelf(ostream& os, vtkIndent indent);
// Description:
// Position the first end point of the slider. Note that this point is an
// instance of vtkCoordinate, meaning that Point 1 can be specified in a
// variety of coordinate systems, and can even be relative to another
// point. To set the point, you'll want to get the Point1Coordinate and
// then invoke the necessary methods to put it into the correct coordinate
// system and set the correct initial value.
vtkCoordinate *GetPoint1Coordinate();
// Description:
// Position the second end point of the slider. Note that this point is an
// instance of vtkCoordinate, meaning that Point 1 can be specified in a
// variety of coordinate systems, and can even be relative to another
// point. To set the point, you'll want to get the Point2Coordinate and
// then invoke the necessary methods to put it into the correct coordinate
// system and set the correct initial value.
vtkCoordinate *GetPoint2Coordinate();
// Description:
// Get the slider properties. The properties of the slider when selected
// and unselected can be manipulated.
vtkGetObjectMacro(RingProperty,vtkProperty2D);
// Description:
// Get the selection property. This property is used to modify the
// appearance of selected objects (e.g., the slider).
vtkGetObjectMacro(SelectedProperty,vtkProperty2D);
// Description:
// Set/Get the properties for the label and title text.
vtkGetObjectMacro(LabelProperty,vtkTextProperty);
// Description:
// Methods to interface with the vtkSliderWidget. The PlaceWidget() method
// assumes that the parameter bounds[6] specifies the location in display
// space where the widget should be placed.
virtual void PlaceWidget(double bounds[6]);
virtual void BuildRepresentation();
virtual void StartWidgetInteraction(double eventPos[2]);
virtual void WidgetInteraction(double eventPos[2]);
virtual void TiltWidgetInteraction(double eventPos[2]);
virtual void DistanceWidgetInteraction(double eventPos[2]);
virtual int ComputeInteractionState(int X, int Y, int modify=0);
virtual void Highlight(int);
// Decsription:
// Methods supporting the rendering process.
virtual void GetActors(vtkPropCollection*);
virtual void ReleaseGraphicsResources(vtkWindow*);
virtual int RenderOverlay(vtkViewport*);
virtual int RenderOpaqueGeometry(vtkViewport*);
virtual void SetHeading(double value);
virtual double GetHeading();
virtual void SetTilt(double value);
virtual double GetTilt();
virtual void UpdateTilt(double time);
virtual void EndTilt();
virtual void SetDistance(double value);
virtual double GetDistance();
virtual void UpdateDistance(double time);
virtual void EndDistance();
virtual void SetRenderer(vtkRenderer *ren);
//BTX
// Enums are used to describe what is selected
enum _InteractionState
{
Outside=0,
Inside,
Adjusting,
TiltDown,
TiltUp,
TiltAdjusting,
DistanceOut,
DistanceIn,
DistanceAdjusting
};
//ETX
protected:
vtkCompassRepresentation();
~vtkCompassRepresentation();
// Positioning the widget
vtkCoordinate *Point1Coordinate;
vtkCoordinate *Point2Coordinate;
// radius values
double InnerRadius;
double OuterRadius;
// tilt and distance rep
//BTX
vtkSmartPointer<vtkCenteredSliderRepresentation> TiltRepresentation;
vtkSmartPointer<vtkCenteredSliderRepresentation> DistanceRepresentation;
//ETX
// Define the geometry. It is constructed in canaonical position
// along the x-axis and then rotated into position.
vtkTransform *XForm;
vtkPoints *Points;
vtkPolyData *Ring;
vtkTransformPolyDataFilter *RingXForm;
vtkPolyDataMapper2D *RingMapper;
vtkActor2D *RingActor;
vtkProperty2D *RingProperty;
vtkPolyDataMapper2D *BackdropMapper;
vtkActor2D *Backdrop;
vtkTextProperty *LabelProperty;
vtkTextActor *LabelActor;
vtkTextProperty *StatusProperty;
vtkTextActor *StatusActor;
vtkProperty2D *SelectedProperty;
// build the tube geometry
void BuildRing();
void BuildBackdrop();
// used for positioning etc
void GetCenterAndUnitRadius(int center[2], double &radius);
int HighlightState;
double Heading;
double Tilt;
double Distance;
private:
vtkCompassRepresentation(const vtkCompassRepresentation&); //Not implemented
void operator=(const vtkCompassRepresentation&); //Not implemented
};
#endif

View File

@ -0,0 +1,398 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkCompassWidget.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 "vtkCallbackCommand.h"
#include "vtkCommand.h"
#include "vtkCompassWidget.h"
#include "vtkCompassRepresentation.h"
#include "vtkEvent.h"
#include "vtkObjectFactory.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkRenderer.h"
#include "vtkWidgetCallbackMapper.h"
#include "vtkWidgetEvent.h"
#include "vtkWidgetEventTranslator.h"
#include "vtkTimerLog.h"
vtkStandardNewMacro(vtkCompassWidget);
//------------------------------------------------------------
vtkCompassWidget::vtkCompassWidget()
{
// Set the initial state
this->WidgetState = vtkCompassWidget::Start;
this->TimerDuration = 50;
// Okay, define the events
this->CallbackMapper->SetCallbackMethod
(vtkCommand::LeftButtonPressEvent,
vtkWidgetEvent::Select,
this, vtkCompassWidget::SelectAction);
this->CallbackMapper->SetCallbackMethod
(vtkCommand::MouseMoveEvent,
vtkWidgetEvent::Move,
this, vtkCompassWidget::MoveAction);
this->CallbackMapper->SetCallbackMethod
(vtkCommand::LeftButtonReleaseEvent,
vtkWidgetEvent::EndSelect,
this, vtkCompassWidget::EndSelectAction);
this->CallbackMapper->SetCallbackMethod
(vtkCommand::TimerEvent,
vtkWidgetEvent::TimedOut,
this, vtkCompassWidget::TimerAction);
}
//----------------------------------------------------------------------
void vtkCompassWidget::CreateDefaultRepresentation()
{
if ( ! this->WidgetRep )
{
this->WidgetRep = vtkCompassRepresentation::New();
}
}
//-----------------------------------------------------------------
double vtkCompassWidget::GetHeading()
{
this->CreateDefaultRepresentation();
vtkCompassRepresentation *slider =
vtkCompassRepresentation::SafeDownCast(this->WidgetRep);
return slider->GetHeading();
}
//-----------------------------------------------------------------
void vtkCompassWidget::SetHeading(double value)
{
this->CreateDefaultRepresentation();
vtkCompassRepresentation *slider =
vtkCompassRepresentation::SafeDownCast(this->WidgetRep);
slider->SetHeading(value);
}
//-----------------------------------------------------------------
double vtkCompassWidget::GetTilt()
{
this->CreateDefaultRepresentation();
vtkCompassRepresentation *slider =
vtkCompassRepresentation::SafeDownCast(this->WidgetRep);
return slider->GetTilt();
}
//-----------------------------------------------------------------
void vtkCompassWidget::SetTilt(double value)
{
this->CreateDefaultRepresentation();
vtkCompassRepresentation *slider =
vtkCompassRepresentation::SafeDownCast(this->WidgetRep);
slider->SetTilt(value);
}
//-----------------------------------------------------------------
double vtkCompassWidget::GetDistance()
{
this->CreateDefaultRepresentation();
vtkCompassRepresentation *slider =
vtkCompassRepresentation::SafeDownCast(this->WidgetRep);
return slider->GetDistance();
}
//-----------------------------------------------------------------
void vtkCompassWidget::SetDistance(double value)
{
this->CreateDefaultRepresentation();
vtkCompassRepresentation *slider =
vtkCompassRepresentation::SafeDownCast(this->WidgetRep);
slider->SetDistance(value);
}
//-------------------------------------------------------------
void vtkCompassWidget::SelectAction(vtkAbstractWidget *w)
{
vtkCompassWidget *self =
reinterpret_cast<vtkCompassWidget*>(w);
double eventPos[2];
eventPos[0] = self->Interactor->GetEventPosition()[0];
eventPos[1] = self->Interactor->GetEventPosition()[1];
// Okay, make sure that the pick is in the current renderer
if (!self->CurrentRenderer ||
!self->CurrentRenderer->IsInViewport(static_cast<int>(eventPos[0]),
static_cast<int>(eventPos[1])))
{
return;
}
// See if the widget has been selected. StartWidgetInteraction records the
// starting point of the motion.
self->CreateDefaultRepresentation();
self->WidgetRep->StartWidgetInteraction(eventPos);
int interactionState = self->WidgetRep->GetInteractionState();
if ( interactionState == vtkCompassRepresentation::TiltDown)
{
self->SetTilt(self->GetTilt() - 15);
self->InvokeEvent(vtkCommand::InteractionEvent,NULL);
self->EventCallbackCommand->SetAbortFlag(1);
return;
}
if (interactionState == vtkCompassRepresentation::TiltUp)
{
self->SetTilt(self->GetTilt() + 15);
self->InvokeEvent(vtkCommand::InteractionEvent,NULL);
self->EventCallbackCommand->SetAbortFlag(1);
return;
}
if ( interactionState == vtkCompassRepresentation::TiltAdjusting)
{
self->GrabFocus(self->EventCallbackCommand);
self->WidgetState = vtkCompassWidget::TiltAdjusting;
// Start off the timer
self->TimerId =
self->Interactor->CreateRepeatingTimer(self->TimerDuration);
self->StartTime = vtkTimerLog::GetUniversalTime();
// Highlight as necessary
self->WidgetRep->Highlight(1);
// start the interaction
self->StartInteraction();
self->InvokeEvent(vtkCommand::StartInteractionEvent,NULL);
self->EventCallbackCommand->SetAbortFlag(1);
self->Render();
return;
}
if ( interactionState == vtkCompassRepresentation::DistanceIn)
{
self->SetDistance(self->GetDistance()*0.8);
self->InvokeEvent(vtkCommand::InteractionEvent,NULL);
self->EventCallbackCommand->SetAbortFlag(1);
return;
}
if (interactionState == vtkCompassRepresentation::DistanceOut)
{
self->SetDistance(self->GetDistance()*1.2);
self->InvokeEvent(vtkCommand::InteractionEvent,NULL);
self->EventCallbackCommand->SetAbortFlag(1);
return;
}
if ( interactionState == vtkCompassRepresentation::DistanceAdjusting)
{
self->GrabFocus(self->EventCallbackCommand);
self->WidgetState = vtkCompassWidget::DistanceAdjusting;
// Start off the timer
self->TimerId =
self->Interactor->CreateRepeatingTimer(self->TimerDuration);
self->StartTime = vtkTimerLog::GetUniversalTime();
// Highlight as necessary
self->WidgetRep->Highlight(1);
// start the interaction
self->StartInteraction();
self->InvokeEvent(vtkCommand::StartInteractionEvent,NULL);
self->EventCallbackCommand->SetAbortFlag(1);
self->Render();
return;
}
if (interactionState != vtkCompassRepresentation::Adjusting)
{
return;
}
// We are definitely selected
self->GrabFocus(self->EventCallbackCommand);
self->EventCallbackCommand->SetAbortFlag(1);
if ( interactionState == vtkCompassRepresentation::Adjusting )
{
self->WidgetState = vtkCompassWidget::Adjusting;
// Highlight as necessary
self->WidgetRep->Highlight(1);
// start the interaction
self->StartInteraction();
self->InvokeEvent(vtkCommand::StartInteractionEvent,NULL);
self->EventCallbackCommand->SetAbortFlag(1);
self->Render();
return;
}
}
//---------------------------------------------------------------
void vtkCompassWidget::MoveAction(vtkAbstractWidget *w)
{
vtkCompassWidget *self =
reinterpret_cast<vtkCompassWidget*>(w);
// do we need to change highlight state?
self->CreateDefaultRepresentation();
int interactionState = self->WidgetRep->ComputeInteractionState
(self->Interactor->GetEventPosition()[0],
self->Interactor->GetEventPosition()[1]);
// if we are outside and in the start state then return
if (interactionState == vtkCompassRepresentation::Outside &&
self->WidgetState == vtkCompassWidget::Start)
{
return;
}
// if we are not outside and in the highlighting state then return
if (interactionState != vtkCompassRepresentation::Outside &&
self->WidgetState == vtkCompassWidget::Highlighting)
{
return;
}
// if we are not outside and in the Start state highlight
if ( interactionState != vtkCompassRepresentation::Outside &&
self->WidgetState == vtkCompassWidget::Start)
{
self->WidgetRep->Highlight(1);
self->WidgetState = vtkCompassWidget::Highlighting;
self->Render();
return;
}
// if we are outside but in the highlight state then stop highlighting
if ( self->WidgetState == vtkCompassWidget::Highlighting &&
interactionState == vtkCompassRepresentation::Outside)
{
self->WidgetRep->Highlight(0);
self->WidgetState = vtkCompassWidget::Start;
self->Render();
return;
}
vtkCompassRepresentation *rep =
vtkCompassRepresentation::SafeDownCast(self->WidgetRep);
// Definitely moving the slider, get the updated position
double eventPos[2];
eventPos[0] = self->Interactor->GetEventPosition()[0];
eventPos[1] = self->Interactor->GetEventPosition()[1];
if (self->WidgetState == vtkCompassWidget::TiltAdjusting)
{
rep->TiltWidgetInteraction(eventPos);
}
if (self->WidgetState == vtkCompassWidget::DistanceAdjusting)
{
rep->DistanceWidgetInteraction(eventPos);
}
if (self->WidgetState == vtkCompassWidget::Adjusting)
{
self->WidgetRep->WidgetInteraction(eventPos);
}
self->InvokeEvent(vtkCommand::InteractionEvent,NULL);
// Interact, if desired
self->EventCallbackCommand->SetAbortFlag(1);
}
//-----------------------------------------------------------------
void vtkCompassWidget::EndSelectAction(vtkAbstractWidget *w)
{
vtkCompassWidget *self =
reinterpret_cast<vtkCompassWidget*>(w);
if ( self->WidgetState != vtkCompassWidget::Adjusting &&
self->WidgetState != vtkCompassWidget::TiltAdjusting &&
self->WidgetState != vtkCompassWidget::DistanceAdjusting)
{
return;
}
if (self->WidgetState == vtkCompassWidget::TiltAdjusting)
{
// stop the timer
self->Interactor->DestroyTimer(self->TimerId);
vtkCompassRepresentation *rep =
vtkCompassRepresentation::SafeDownCast(self->WidgetRep);
rep->EndTilt();
}
if (self->WidgetState == vtkCompassWidget::DistanceAdjusting)
{
// stop the timer
self->Interactor->DestroyTimer(self->TimerId);
vtkCompassRepresentation *rep =
vtkCompassRepresentation::SafeDownCast(self->WidgetRep);
rep->EndDistance();
}
int interactionState = self->WidgetRep->ComputeInteractionState
(self->Interactor->GetEventPosition()[0],
self->Interactor->GetEventPosition()[1]);
if ( interactionState == vtkCompassRepresentation::Outside)
{
self->WidgetRep->Highlight(0);
self->WidgetState = vtkCompassWidget::Start;
}
else
{
self->WidgetState = vtkCompassWidget::Highlighting;
}
// The state returns to unselected
self->ReleaseFocus();
// Complete interaction
self->EventCallbackCommand->SetAbortFlag(1);
self->EndInteraction();
self->InvokeEvent(vtkCommand::EndInteractionEvent,NULL);
self->Render();
}
void vtkCompassWidget::TimerAction(vtkAbstractWidget *w)
{
vtkCompassWidget *self =
reinterpret_cast<vtkCompassWidget*>(w);
int timerId = *(reinterpret_cast<int*>(self->CallData));
// If this is the timer event we are waiting for...
if ( timerId == self->TimerId)
{
vtkCompassRepresentation *rep =
vtkCompassRepresentation::SafeDownCast(self->WidgetRep);
if (self->WidgetState == vtkCompassWidget::TiltAdjusting)
{
double tElapsed = vtkTimerLog::GetUniversalTime() - self->StartTime;
rep->UpdateTilt(tElapsed);
}
if (self->WidgetState == vtkCompassWidget::DistanceAdjusting)
{
double tElapsed = vtkTimerLog::GetUniversalTime() - self->StartTime;
rep->UpdateDistance(tElapsed);
}
self->StartTime = vtkTimerLog::GetUniversalTime();
self->InvokeEvent(vtkCommand::InteractionEvent,NULL);
self->EventCallbackCommand->SetAbortFlag(1); //no one else gets this timer
}
}
//-----------------------------------------------------------------
void vtkCompassWidget::PrintSelf(ostream& os, vtkIndent indent)
{
//Superclass typedef defined in vtkTypeMacro() found in vtkSetGet.h
this->Superclass::PrintSelf(os,indent);
}

View File

@ -0,0 +1,133 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkCompassWidget.h
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.
-------------------------------------------------------------------------*/
// .NAME vtkCompassWidget - set a value by manipulating something
// .SECTION Description
// The vtkCompassWidget is used to adjust a scalar value in an
// application. Note that the actual appearance of the widget depends on
// the specific representation for the widget.
//
// To use this widget, set the widget representation. (the details may
// vary depending on the particulars of the representation).
//
//
// .SECTION Event Bindings
// By default, the widget responds to the following VTK events (i.e., it
// watches the vtkRenderWindowInteractor for these events):
// <pre>
// If the slider bead is selected:
// LeftButtonPressEvent - select slider
// LeftButtonReleaseEvent - release slider
// MouseMoveEvent - move slider
// </pre>
//
// Note that the event bindings described above can be changed using this
// class's vtkWidgetEventTranslator. This class translates VTK events
// into the vtkCompassWidget's widget events:
// <pre>
// vtkWidgetEvent::Select -- some part of the widget has been selected
// vtkWidgetEvent::EndSelect -- the selection process has completed
// vtkWidgetEvent::Move -- a request for slider motion has been invoked
// </pre>
//
// In turn, when these widget events are processed, the vtkCompassWidget
// invokes the following VTK events on itself (which observers can listen for):
// <pre>
// vtkCommand::StartInteractionEvent (on vtkWidgetEvent::Select)
// vtkCommand::EndInteractionEvent (on vtkWidgetEvent::EndSelect)
// vtkCommand::InteractionEvent (on vtkWidgetEvent::Move)
// </pre>
//
#ifndef vtkCompassWidget_h
#define vtkCompassWidget_h
#include "vtkGeovisCoreModule.h" // For export macro
#include "vtkAbstractWidget.h"
class vtkCompassRepresentation;
class VTKGEOVISCORE_EXPORT vtkCompassWidget : public vtkAbstractWidget
{
public:
// Description:
// Instantiate the class.
static vtkCompassWidget *New();
// Description:
// Standard macros.
vtkTypeMacro(vtkCompassWidget,vtkAbstractWidget);
void PrintSelf(ostream& os, vtkIndent indent);
// Description:
// Specify an instance of vtkWidgetRepresentation used to represent this
// widget in the scene. Note that the representation is a subclass of vtkProp
// so it can be added to the renderer independent of the widget.
void SetRepresentation(vtkCompassRepresentation *r)
{this->Superclass::SetWidgetRepresentation
(reinterpret_cast<vtkWidgetRepresentation*>(r));}
// Description:
// Create the default widget representation if one is not set.
void CreateDefaultRepresentation();
// Description:
// Get the value for this widget.
double GetHeading();
void SetHeading(double v);
double GetTilt();
void SetTilt(double t);
double GetDistance();
void SetDistance(double t);
protected:
vtkCompassWidget();
~vtkCompassWidget() {}
// These are the events that are handled
static void SelectAction(vtkAbstractWidget*);
static void EndSelectAction(vtkAbstractWidget*);
static void MoveAction(vtkAbstractWidget*);
static void TimerAction(vtkAbstractWidget*);
//BTX - manage the state of the widget
int WidgetState;
enum _WidgetState
{
Start=0,
Highlighting,
Adjusting,
TiltAdjusting,
DistanceAdjusting
};
//ETX
int TimerId;
int TimerDuration;
double StartTime;
private:
vtkCompassWidget(const vtkCompassWidget&); //Not implemented
void operator=(const vtkCompassWidget&); //Not implemented
};
#endif

View File

@ -0,0 +1,325 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkGeoAdaptiveArcs.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 "vtkGeoAdaptiveArcs.h"
#include "vtkCamera.h"
#include "vtkCellArray.h"
#include "vtkCellData.h"
#include "vtkCoordinate.h"
#include "vtkDoubleArray.h"
#include "vtkFloatArray.h"
#include "vtkGeoMath.h"
#include "vtkGlobeSource.h"
#include "vtkMath.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkRenderWindow.h"
#include "vtkRendererCollection.h"
#include "vtkTimerLog.h"
#include <map>
vtkStandardNewMacro(vtkGeoAdaptiveArcs);
//-------------------------------------------------------------------------
vtkGeoAdaptiveArcs::vtkGeoAdaptiveArcs()
{
this->GlobeRadius = vtkGeoMath::EarthRadiusMeters();
this->Renderer = 0;
this->MaximumPixelSeparation = 10.0;
this->MinimumPixelSeparation = 1.0;
this->LastInput = 0;
this->LastInputMTime = 0;
this->InputLatitude = vtkDoubleArray::New();
this->InputLongitude = vtkDoubleArray::New();
}
//-------------------------------------------------------------------------
vtkGeoAdaptiveArcs::~vtkGeoAdaptiveArcs()
{
this->InputLatitude->Delete();
this->InputLongitude->Delete();
}
//-------------------------------------------------------------------------
int vtkGeoAdaptiveArcs::RequestData(
vtkInformation *vtkNotUsed(request),
vtkInformationVector **inputVector,
vtkInformationVector *outputVector)
{
if (!this->Renderer)
{
vtkErrorMacro("Renderer cannot be null.");
return 0;
}
// get the info objects
vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
vtkInformation *outInfo = outputVector->GetInformationObject(0);
// get the input and output
vtkPolyData *input = vtkPolyData::SafeDownCast(
inInfo->Get(vtkDataObject::DATA_OBJECT()));
vtkPolyData *output = vtkPolyData::SafeDownCast(
outInfo->Get(vtkDataObject::DATA_OBJECT()));
// if the input has changed, compute helper arrays
if (input != this->LastInput ||
input->GetMTime() > this->LastInputMTime)
{
this->InputLatitude->Initialize();
this->InputLongitude->Initialize();
vtkPoints* points = input->GetPoints();
double curPtLL[2];
double curPoint[3];
for (vtkIdType i = 0; i < input->GetNumberOfPoints(); ++i)
{
points->GetPoint(i, curPoint);
vtkGlobeSource::ComputeLatitudeLongitude(
curPoint, curPtLL[0], curPtLL[1]);
this->InputLongitude->InsertNextValue(curPtLL[0]);
this->InputLatitude->InsertNextValue(curPtLL[1]);
}
this->LastInput = input;
this->LastInputMTime = input->GetMTime();
}
// Traverse input lines, adding a circle for each line segment.
int *renSize = this->Renderer->GetSize();
// Maximum distance from center of renderer.
double maxDist = (renSize[0] > renSize[1]) ? 1.1*renSize[0]/2.0 : 1.1*renSize[1]/2.0;
vtkCellArray* lines = input->GetLines();
vtkCellArray* newLines = vtkCellArray::New();
vtkPoints* points = input->GetPoints();
float* pointsPtr = static_cast<float*>(points->GetVoidPointer(0));
vtkPoints* newPoints = vtkPoints::New();
double viewAngle = this->Renderer->GetActiveCamera()->GetViewAngle();
double cameraPos[3];
this->Renderer->GetActiveCamera()->GetPosition(cameraPos);
double cameraDir[3];
this->Renderer->GetActiveCamera()->GetDirectionOfProjection(cameraDir);
lines->InitTraversal();
for (vtkIdType i = 0; i < lines->GetNumberOfCells(); i++)
{
vtkIdType npts=0; // to remove warning
vtkIdType* pts=0; // to remove warning
lines->GetNextCell(npts, pts);
bool lastPointOffScreen = false;
bool lastPointTooClose = false;
#if defined(VTK_AGGRESSIVE_ARCS)
bool lastPointOnOtherSide = false;
#endif
double curPoint[3];
double lastPtLL[2] = {0.0, 0.0};
double curPtLL[2];
double lastVec[3] = {0.0, 0.0, 0.0};
double curVec[3];
curPoint[0] = pointsPtr[3*pts[0]+0];
curPoint[1] = pointsPtr[3*pts[0]+1];
curPoint[2] = pointsPtr[3*pts[0]+2];
curPtLL[0] = this->InputLongitude->GetValue(pts[0]);
curPtLL[1] = this->InputLatitude->GetValue(pts[0]);
double curVecSize = 0;
for (int c = 0; c < 3; ++c)
{
curVec[c] = curPoint[c] - cameraPos[c];
curVecSize += curVec[c]*curVec[c];
}
curVecSize = sqrt(curVecSize);
curVec[0] /= curVecSize;
curVec[1] /= curVecSize;
curVec[2] /= curVecSize;
for (vtkIdType p = 1; p < npts; ++p)
{
// Advance the point unless the last point was too close.
if (!lastPointTooClose)
{
for (int c = 0; c < 3; ++c)
{
// lastPoint[c] = curPoint[c];
lastVec[c] = curVec[c];
}
lastPtLL[0] = curPtLL[0];
lastPtLL[1] = curPtLL[1];
}
#if defined(VTK_AGGRESSIVE_ARCS)
// If this code is uncommented, then
// Be aggressive ... skip several points if the last
// one was offscreen or on the other side of the globe.
if (lastPointOffScreen || lastPointOnOtherSide)
{
p += 5;
if (p >= npts)
{
p = npts - 1;
}
}
#endif
curPoint[0] = pointsPtr[3*pts[p]+0];
curPoint[1] = pointsPtr[3*pts[p]+1];
curPoint[2] = pointsPtr[3*pts[p]+2];
curPtLL[0] = this->InputLongitude->GetValue(pts[p]);
curPtLL[1] = this->InputLatitude->GetValue(pts[p]);
curVecSize = 0;
for (int c = 0; c < 3; ++c)
{
curVec[c] = curPoint[c] - cameraPos[c];
curVecSize += curVec[c]*curVec[c];
}
curVecSize = sqrt(curVecSize);
curVec[0] /= curVecSize;
curVec[1] /= curVecSize;
curVec[2] /= curVecSize;
// Clear flags
#if defined(VTK_AGGRESSIVE_ARCS)
lastPointOnOtherSide = false;
#endif
lastPointOffScreen = false;
lastPointTooClose = false;
// Don't draw lines off the current screen.
double distFromCenterApprox =
vtkMath::DegreesFromRadians( acos( curVec[0] * cameraDir[0] +
curVec[1] * cameraDir[1] +
curVec[2] * cameraDir[2] ) )
/ viewAngle * renSize[1];
if (distFromCenterApprox > maxDist)
{
// If both last point and this point are offscreen, skip
// drawing the line
if (lastPointOffScreen == true)
{
continue;
}
lastPointOffScreen = true;
}
// Don't draw lines on the other side of the world.
//if (vtkMath::Dot(curPoint, cameraPos) < 0)
if (curPoint[0]*cameraPos[0]+
curPoint[1]*cameraPos[1]+
curPoint[2]*cameraPos[2] < 0)
{
#if defined(VTK_AGGRESSIVE_ARCS)
lastPointOnOtherSide = true;
#endif
continue;
}
double distApprox =
vtkMath::DegreesFromRadians( acos( lastVec[0] * curVec[0] +
lastVec[1] * curVec[1] +
lastVec[2] * curVec[2] ) )
/ viewAngle * renSize[1];
// If the points are too close, skip over it to the next point.
if (distApprox < this->MinimumPixelSeparation)
{
lastPointTooClose = true;
continue;
}
// Calculate the number of subdivisions.
vtkIdType numDivisions = static_cast<vtkIdType>(distApprox / this->MaximumPixelSeparation + 0.5) + 1;
if (numDivisions < 2)
{
numDivisions = 2;
}
// Create the new cell
newLines->InsertNextCell(numDivisions);
for (vtkIdType s = 0; s < numDivisions; ++s)
{
// Interpolate in lat-long.
double interpPtLL[2];
double frac = static_cast<double>(s) / (numDivisions - 1);
for (int c = 0; c < 2; ++c)
{
interpPtLL[c] = frac*curPtLL[c] + (1.0 - frac)*lastPtLL[c];
}
// Convert lat-long to world;
double interpPt[3];
vtkGlobeSource::ComputeGlobePoint(interpPtLL[0], interpPtLL[1], this->GlobeRadius, interpPt);
vtkIdType newPt = newPoints->InsertNextPoint(interpPt);
newLines->InsertCellPoint(newPt);
}
}
}
// Send the data to output.
output->SetLines(newLines);
output->SetPoints(newPoints);
// Clean up.
newLines->Delete();
newPoints->Delete();
return 1;
}
//-------------------------------------------------------------------------
void vtkGeoAdaptiveArcs::SetRenderer(vtkRenderer *ren)
{
// Do not reference count this, it will cause a loop.
this->Renderer = ren;
}
//-------------------------------------------------------------------------
unsigned long vtkGeoAdaptiveArcs::GetMTime()
{
unsigned long retMTime = this->Superclass::GetMTime();
if ( this->Renderer )
{
unsigned long tmpTime = this->Renderer->GetMTime();
if ( tmpTime > retMTime )
{
retMTime = tmpTime;
}
vtkCamera* cam = this->Renderer->GetActiveCamera();
if ( cam )
{
tmpTime = cam->GetMTime();
if ( tmpTime > retMTime )
retMTime = tmpTime;
}
}
return retMTime;
}
//-------------------------------------------------------------------------
void vtkGeoAdaptiveArcs::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
os << indent << "GlobeRadius: " << this->GlobeRadius << endl;
os << indent << "MinumumPixelSeparation: " << this->MinimumPixelSeparation << endl;
os << indent << "MaximumPixelSeparation: " << this->MaximumPixelSeparation << endl;
os << indent << "Renderer: " << (this->Renderer ? "" : "(null)") << endl;
if (this->Renderer)
{
this->Renderer->PrintSelf(os, indent.GetNextIndent());
}
}

View File

@ -0,0 +1,98 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkGeoAdaptiveArcs.h
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.
-------------------------------------------------------------------------*/
// .NAME vtkGeoArcs - layout graph edges on a globe as arcs.
//
// .SECTION Description
// .SECTION Thanks
#ifndef vtkGeoAdaptiveArcs_h
#define vtkGeoAdaptiveArcs_h
#include "vtkGeovisCoreModule.h" // For export macro
#include "vtkPolyDataAlgorithm.h"
class vtkDoubleArray;
class vtkPolyData;
class vtkRenderer;
class VTKGEOVISCORE_EXPORT vtkGeoAdaptiveArcs : public vtkPolyDataAlgorithm
{
public:
static vtkGeoAdaptiveArcs *New();
vtkTypeMacro(vtkGeoAdaptiveArcs,vtkPolyDataAlgorithm);
void PrintSelf(ostream& os, vtkIndent indent);
// Description:
// The base radius used to determine the earth's surface.
// Default is the earth's radius in meters.
// TODO: Change this to take in a vtkGeoTerrain to get altitude.
vtkSetMacro(GlobeRadius, double);
vtkGetMacro(GlobeRadius, double);
// Description:
// The maximum number of pixels between points on the arcs.
// If two adjacent points are farther than the threshold,
// the line segment will be subdivided such that each point
// is separated by at most the threshold.
vtkSetMacro(MaximumPixelSeparation, double);
vtkGetMacro(MaximumPixelSeparation, double);
// Description:
// The minimum number of pixels between points on the arcs.
// Points closer than the threshold will be skipped until
// a point farther than the minimum threshold is reached.
vtkSetMacro(MinimumPixelSeparation, double);
vtkGetMacro(MinimumPixelSeparation, double);
// Description:
// The renderer used to estimate the number of pixels between
// points.
virtual void SetRenderer(vtkRenderer *ren);
vtkGetObjectMacro(Renderer, vtkRenderer);
// Description:
// Return the modified time of this object.
virtual unsigned long GetMTime();
protected:
vtkGeoAdaptiveArcs();
~vtkGeoAdaptiveArcs();
// Description:
// Convert the vtkGraph into vtkPolyData.
int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *);
vtkRenderer *Renderer;
double GlobeRadius;
double MaximumPixelSeparation;
double MinimumPixelSeparation;
unsigned long LastInputMTime;
vtkPolyData* LastInput;
vtkDoubleArray* InputLatitude;
vtkDoubleArray* InputLongitude;
private:
vtkGeoAdaptiveArcs(const vtkGeoAdaptiveArcs&); // Not implemented.
void operator=(const vtkGeoAdaptiveArcs&); // Not implemented.
};
#endif

View File

@ -0,0 +1,250 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkGeoAlignedImageRepresentation.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 "vtkGeoAlignedImageRepresentation.h"
#include "vtkCollection.h"
#include "vtkGeoImageNode.h"
#include "vtkGeoSource.h"
#include "vtkGeoTreeNodeCache.h"
#include "vtkImageData.h"
#include "vtkObjectFactory.h"
#include "vtkSmartPointer.h"
#include "vtkStdString.h"
#include "vtkTexture.h"
#include "vtkTransform.h"
#include "vtkXMLImageDataReader.h"
#include "vtkXMLImageDataWriter.h"
#include <sstream>
#include <stack>
#include <utility>
static std::pair<vtkGeoImageNode*, double>
vtkGeoAlignedImageRepresentationFind(vtkGeoSource* source, vtkGeoImageNode* p, double* bounds, vtkGeoTreeNodeCache* nodeList)
{
if (!p->HasData())
{
return std::make_pair(static_cast<vtkGeoImageNode*>(0), 0.0);
}
double lb[3];
double ub[3];
p->GetTexture()->GetImageDataInput(0)->GetOrigin(lb);
p->GetTexture()->GetImageDataInput(0)->GetSpacing(ub);
double bcenter[2] = {(bounds[0] + bounds[1])/2.0, (bounds[2] + bounds[3])/2.0};
double ncenter[2] = {(lb[0] + ub[0])/2.0, (lb[1] + ub[1])/2.0};
double vec[2] = {bcenter[0] - ncenter[0], bcenter[1] - ncenter[1]};
double dist2 = vec[0]*vec[0] + vec[1]*vec[1];
if (lb[0] <= bounds[0] &&
ub[0] >= bounds[1] &&
lb[1] <= bounds[2] &&
ub[1] >= bounds[3])
{
nodeList->SendToFront(p);
std::pair<vtkGeoImageNode*, double> minDist(static_cast<vtkGeoImageNode *>(NULL), VTK_DOUBLE_MAX);
vtkGeoImageNode* child = p->GetChild(0);
vtkCollection* coll = NULL;
if (!child || !child->HasData() || p->GetStatus() == vtkGeoTreeNode::PROCESSING)
{
// TODO: This multiplier should be configurable
if ((ub[0] - lb[0]) > 2.0*(bounds[1] - bounds[0]))
{
// Populate the children
coll = source->GetRequestedNodes(p);
if (coll && coll->GetNumberOfItems() == 4)
{
if (!child)
{
p->CreateChildren();
}
for (int c = 0; c < 4; ++c)
{
vtkGeoImageNode* node = vtkGeoImageNode::SafeDownCast(coll->GetItemAsObject(c));
if (node)
{
p->GetChild(c)->SetImage(node->GetImage());
p->GetChild(c)->SetTexture(node->GetTexture());
p->GetChild(c)->SetId(node->GetId());
p->GetChild(c)->SetLevel(node->GetLevel());
nodeList->SendToFront(p->GetChild(c));
}
}
p->SetStatus(vtkGeoTreeNode::NONE);
}
if (coll)
{
coll->Delete();
}
else if(p->GetStatus() == vtkGeoTreeNode::NONE)
{
p->SetStatus(vtkGeoTreeNode::PROCESSING);
vtkGeoImageNode * temp = vtkGeoImageNode::New();
temp->DeepCopy(p);
source->RequestChildren(temp);
//source->RequestChildren(p);
}
}
}
if (p->GetChild(0))
{
for (int i = 0; i < 4; ++i)
{
std::pair<vtkGeoImageNode*, double> subsearch =
vtkGeoAlignedImageRepresentationFind(source, p->GetChild(i), bounds, nodeList);
if (subsearch.first && subsearch.second < minDist.second)
{
minDist = subsearch;
}
}
}
if (minDist.first)
{
return minDist;
}
return std::make_pair(p, dist2);
}
else
{
return std::make_pair(static_cast<vtkGeoImageNode*>(0), 0.0);
}
}
vtkStandardNewMacro(vtkGeoAlignedImageRepresentation);
vtkCxxSetObjectMacro(vtkGeoAlignedImageRepresentation, GeoSource, vtkGeoSource);
//----------------------------------------------------------------------------
vtkGeoAlignedImageRepresentation::vtkGeoAlignedImageRepresentation()
{
this->GeoSource = 0;
this->Root = vtkGeoImageNode::New();
this->Cache = vtkGeoTreeNodeCache::New();
this->SetNumberOfInputPorts(0);
}
//----------------------------------------------------------------------------
vtkGeoAlignedImageRepresentation::~vtkGeoAlignedImageRepresentation()
{
this->SetGeoSource(0);
if (this->Root)
{
this->Root->Delete();
}
if (this->Cache)
{
this->Cache->Delete();
}
}
//----------------------------------------------------------------------------
void vtkGeoAlignedImageRepresentation::SetSource(vtkGeoSource* source)
{
if (this->GeoSource != source)
{
this->SetGeoSource(source);
if (this->GeoSource)
{
this->Initialize();
}
}
}
//----------------------------------------------------------------------------
void vtkGeoAlignedImageRepresentation::Initialize()
{
if (!this->GeoSource)
{
vtkErrorMacro(<< "You must set the source before initialization.");
return;
}
this->GeoSource->FetchRoot(this->Root);
}
//----------------------------------------------------------------------------
void vtkGeoAlignedImageRepresentation::SaveDatabase(const char* path)
{
if (!this->Root)
{
this->Initialize();
}
std::stack< vtkSmartPointer<vtkGeoImageNode> > s;
s.push(this->Root);
while (!s.empty())
{
vtkSmartPointer<vtkGeoImageNode> node = s.top();
s.pop();
// Write out file.
vtkSmartPointer<vtkImageData> storedImage = vtkSmartPointer<vtkImageData>::New();
storedImage->ShallowCopy(node->GetTexture()->GetInput());
vtkSmartPointer<vtkXMLImageDataWriter> writer = vtkSmartPointer<vtkXMLImageDataWriter>::New();
char fn[512];
sprintf(fn, "%s/tile_%d_%ld.vti", path, node->GetLevel(), node->GetId());
writer->SetFileName(fn);
writer->SetInputData(storedImage);
writer->Write();
// Recurse over children.
for (int i = 0; i < 4; ++i)
{
vtkSmartPointer<vtkGeoImageNode> child =
vtkSmartPointer<vtkGeoImageNode>::New();
if (this->GeoSource->FetchChild(node, i, child))
{
// Skip nodes outside range of the world.
if (child->GetLatitudeRange()[1] > -90.0)
{
s.push(child);
}
}
}
}
}
//----------------------------------------------------------------------------
vtkGeoImageNode* vtkGeoAlignedImageRepresentation::GetBestImageForBounds(double bounds[4])
{
std::pair<vtkGeoImageNode*, double> res =
vtkGeoAlignedImageRepresentationFind(this->GeoSource, this->Root, bounds, this->Cache);
return res.first;
}
//----------------------------------------------------------------------------
void vtkGeoAlignedImageRepresentation::PrintSelf(ostream& os, vtkIndent indent)
{
this->PrintTree(os, indent, this->Root);
}
//----------------------------------------------------------------------------
void vtkGeoAlignedImageRepresentation::PrintTree(ostream& os, vtkIndent indent, vtkGeoImageNode* root)
{
os << indent << "Id: " << root->GetId() << endl;
os << indent << "LatitudeRange: " << root->GetLatitudeRange()[0] << ", " << root->GetLatitudeRange()[1] << endl;
os << indent << "LongitudeRange: " << root->GetLongitudeRange()[0] << ", " << root->GetLongitudeRange()[1] << endl;
os << indent << "Level: " << root->GetLevel() << endl;
if (root->GetChild(0))
{
for (int i = 0; i < 4; ++i)
{
this->PrintTree(os, indent.GetNextIndent(), root->GetChild(i));
}
}
}

View File

@ -0,0 +1,93 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkGeoAlignedImageRepresentation.h
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.
-------------------------------------------------------------------------*/
// .NAME vtkGeoAlignedImageRepresentation - A multi-resolution image tree
//
// .SECTION Description
// vtkGeoAlignedImageRepresentation represents a high resolution image
// over the globle. It has an associated vtkGeoSource which is responsible
// for fetching new data. This class keeps the fetched data in a quad-tree
// structure organized by latitude and longitude.
#ifndef vtkGeoAlignedImageRepresentation_h
#define vtkGeoAlignedImageRepresentation_h
#include "vtkGeovisCoreModule.h" // For export macro
#include "vtkDataRepresentation.h"
class vtkGeoImageNode;
class vtkGeoSource;
class vtkGeoTreeNodeCache;
class VTKGEOVISCORE_EXPORT vtkGeoAlignedImageRepresentation : public vtkDataRepresentation
{
public:
static vtkGeoAlignedImageRepresentation *New();
vtkTypeMacro(vtkGeoAlignedImageRepresentation,vtkDataRepresentation);
void PrintSelf(ostream& os, vtkIndent indent);
// Description:
// Retrieve the most refined image patch that covers the specified
// latitude and longitude bounds (lat-min, lat-max, long-min, long-max).
virtual vtkGeoImageNode* GetBestImageForBounds(double bounds[4]);
// Description:
// The source for this representation. This must be set first before
// calling GetBestImageForBounds.
virtual vtkGeoSource* GetSource()
{ return this->GeoSource; }
virtual void SetSource(vtkGeoSource* source);
// Description:
// Serialize the database to the specified directory.
// Each image is stored as a .vti file.
// The Origin and Spacing of the saved image contain (lat-min, long-min)
// and (lat-max, long-max), respectively.
// Files are named based on their level and id within that level.
void SaveDatabase(const char* path);
protected:
vtkGeoAlignedImageRepresentation();
~vtkGeoAlignedImageRepresentation();
// Description:
// The source for creating image nodes.
void SetGeoSource(vtkGeoSource* source);
vtkGeoSource* GeoSource;
// Description:
// The root of the image tree.
vtkGeoImageNode* Root;
// Description:
// Initialize the representation with the current source.
void Initialize();
// Description:
// Print information about the image tree.
void PrintTree(ostream& os, vtkIndent indent, vtkGeoImageNode* root);
vtkGeoTreeNodeCache* Cache;
private:
vtkGeoAlignedImageRepresentation(const vtkGeoAlignedImageRepresentation&); // Not implemented
void operator=(const vtkGeoAlignedImageRepresentation&); // Not implemented
};
#endif

View File

@ -0,0 +1,428 @@
/*=============================================================================
Program: Visualization Toolkit
Module: vtkGeoAlignedImageSource.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 "vtkGeoAlignedImageSource.h"
#include "vtkCommand.h"
#include "vtkGeoImageNode.h"
#include "vtkImageData.h"
#include "vtkImageShrink3D.h"
#include "vtkMultiBlockDataSet.h"
#include "vtkObjectFactory.h"
#include "vtkSmartPointer.h"
#include "vtkTexture.h"
#include "vtkTimerLog.h"
#include "vtkTransform.h"
#include <cassert>
vtkStandardNewMacro(vtkGeoAlignedImageSource);
vtkCxxSetObjectMacro(vtkGeoAlignedImageSource, Image, vtkImageData);
class vtkGeoAlignedImageSource::vtkProgressObserver : public vtkCommand
{
public:
static vtkProgressObserver* New()
{ return new vtkProgressObserver(); }
virtual void Execute(vtkObject *, unsigned long eventId,
void *callData)
{
if (eventId == vtkCommand::ProgressEvent)
{
double progress = *reinterpret_cast<double*>(callData);
progress = this->Offset + this->Scale * progress;
if (this->Target)
{
this->Target->InvokeEvent(vtkCommand::ProgressEvent, &progress);
}
}
}
void SetTarget(vtkObject* t)
{
this->Target = t;
}
double Offset;
double Scale;
private:
vtkProgressObserver()
{
this->Target = 0;
this->Offset = 0.0;
this->Scale = 1.0;
}
vtkObject* Target;
};
//----------------------------------------------------------------------------
vtkGeoAlignedImageSource::vtkGeoAlignedImageSource()
{
this->Image = 0;
this->LevelImages = vtkMultiBlockDataSet::New();
this->LatitudeRange[0] = -90;
this->LatitudeRange[1] = 90;
this->LongitudeRange[0] = -180;
this->LongitudeRange[1] = 180;
this->ProgressObserver = vtkProgressObserver::New();
this->ProgressObserver->SetTarget(this);
this->PowerOfTwoSize = true;
this->Overlap = 0.0;
}
//-----------------------------------------------------------------------------
vtkGeoAlignedImageSource::~vtkGeoAlignedImageSource()
{
this->SetImage(0);
this->LevelImages->Delete();
this->ProgressObserver->SetTarget(0);
this->ProgressObserver->Delete();
this->ProgressObserver = 0;
}
//-----------------------------------------------------------------------------
void vtkGeoAlignedImageSource::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
os << indent << "Image: " << (this->Image ? "" : "(null)") << endl;
if (this->Image)
{
this->Image->PrintSelf(os, indent.GetNextIndent());
}
os << indent << "LatitudeRange: " << this->LatitudeRange[0] << "," << this->LatitudeRange[1] << endl;
os << indent << "LongitudeRange: " << this->LongitudeRange[0] << "," << this->LongitudeRange[1] << endl;
os << indent << "PowerOfTwoSize: " << (this->PowerOfTwoSize ? "On" : "Off") << endl;
os << indent << "Overlap: " << this->Overlap << endl;
}
//-----------------------------------------------------------------------------
bool vtkGeoAlignedImageSource::FetchRoot(vtkGeoTreeNode* r)
{
vtkGeoImageNode* root = 0;
if (!(root = vtkGeoImageNode::SafeDownCast(r)))
{
vtkErrorMacro(<< "Node must be an image node for this source.");
return false;
}
int imageDims[3];
this->Image->GetDimensions(imageDims);
// I am ignoring the geometry of the image, and assuming the scalars
// are cell data. The normal shrink should not shift the image by half
// a pixel. I believe texture maps will preserve the image bounds.
vtkSmartPointer<vtkImageShrink3D> shrink = vtkSmartPointer<vtkImageShrink3D>::New();
shrink->SetShrinkFactors(2,2,1);
shrink->AveragingOn();
shrink->AddObserver(vtkCommand::ProgressEvent, this->ProgressObserver);
// We count the number of times vtkImageShrink3D will be executed so that we
// can report progress correctly.
int numLevels = 0;
while (imageDims[0] > 300 || imageDims[1] > 300)
{
imageDims[0] = static_cast<int>(floor(imageDims[0] /
static_cast<double>(shrink->GetShrinkFactors()[0])));
imageDims[1] = static_cast<int>(floor(imageDims[1] /
static_cast<double>(shrink->GetShrinkFactors()[1])));
numLevels++;
}
this->Image->GetDimensions(imageDims);
// Nothing says that the images cannot overlap and be larger than
// the terain pathces. Nothing says that the images have to be
// a same size for all nodes either.
// The easiest this to do to get multiple resolutions is to reduce
// the image size before traversing. This way we can avoid issues
// with the bottom up approach. Specifically, we do not need
// to combine tiles, or worry about seams from smoothing.
// This is not the best termination condition, but it will do.
// This should also work for images that do not cover the whole globe.
vtkSmartPointer<vtkImageData> image = vtkSmartPointer<vtkImageData>::New();
image->ShallowCopy(this->Image);
vtkSmartPointer<vtkImageData> fullImage = vtkSmartPointer<vtkImageData>::New();
fullImage->ShallowCopy(this->Image);
vtkSmartPointer<vtkMultiBlockDataSet> tempBlocks = vtkSmartPointer<vtkMultiBlockDataSet>::New();
tempBlocks->SetBlock(0, fullImage);
for (unsigned int curIter=0; imageDims[0] > 300 || imageDims[1] > 300; ++curIter)
{
this->ProgressObserver->Offset = curIter * 1.0/numLevels;
this->ProgressObserver->Scale = 1.0/numLevels;
// Shrink image for the next level.
shrink->SetInputData(image);
shrink->Update();
image->ShallowCopy(shrink->GetOutput());
shrink->SetInputData(0);
image->GetDimensions(imageDims);
// Store the image for the level.
vtkSmartPointer<vtkImageData> block = vtkSmartPointer<vtkImageData>::New();
block->ShallowCopy(shrink->GetOutput());
block->SetOrigin(-180, -90, 0);
block->SetSpacing(180, 90, 0);
tempBlocks->SetBlock(curIter+1, block);
}
// Reverse the coarsened images so they are in order by level.
for (unsigned int block = 0; block < tempBlocks->GetNumberOfBlocks(); ++block)
{
this->LevelImages->SetBlock(tempBlocks->GetNumberOfBlocks() - 1 - block,
tempBlocks->GetBlock(block));
}
vtkSmartPointer<vtkTexture> texture = vtkSmartPointer<vtkTexture>::New();
texture->SetInputData(this->LevelImages->GetBlock(0));
vtkSmartPointer<vtkTransform> texTrans = vtkSmartPointer<vtkTransform>::New();
// Start with (lat,lon)
texTrans->PostMultiply();
texTrans->RotateZ(90.0); // (-lon,lat)
texTrans->Scale(-1.0, 1.0, 1.0); // (lon,lat)
texTrans->Translate(-(-180.0), -(-90.0), 0.0); // to origin
texTrans->Scale(1.0/360.0, 1.0/180.0, 1.0); // to [0,1]
texture->SetTransform(texTrans);
texture->InterpolateOn();
texture->RepeatOff();
texture->EdgeClampOn();
root->SetLevel(-1);
root->SetLatitudeRange(-270, 90);
root->SetLongitudeRange(-180, 180);
root->SetTexture(texture);
return true;
}
//------------------------------------------------------------------------------
bool vtkGeoAlignedImageSource::FetchChild(vtkGeoTreeNode* p, int index, vtkGeoTreeNode* c)
{
vtkGeoImageNode* parent = 0;
if (!(parent = vtkGeoImageNode::SafeDownCast(p)))
{
vtkErrorMacro(<< "Node must be an image node for this source.");
return false;
}
vtkGeoImageNode* child = 0;
if (!(child = vtkGeoImageNode::SafeDownCast(c)))
{
vtkErrorMacro(<< "Node must be an image node for this source.");
return false;
}
int level = parent->GetLevel() + 1;
unsigned int blockLevel = level + 1;
if (blockLevel >= this->LevelImages->GetNumberOfBlocks())
{
vtkDebugMacro(<< "Reached max number of blocks (" << this->LevelImages->GetNumberOfBlocks() << ")");
return false;
}
double lonRange[2];
double latRange[2];
double center[2];
parent->GetLongitudeRange(lonRange);
parent->GetLatitudeRange(latRange);
center[0] = (lonRange[1] + lonRange[0])/2.0;
center[1] = (latRange[1] + latRange[0])/2.0;
child->SetLevel(level);
if (index / 2)
{
child->SetLatitudeRange(center[1], latRange[1]);
}
else
{
child->SetLatitudeRange(latRange[0], center[1]);
}
if (index % 2)
{
child->SetLongitudeRange(center[0], lonRange[1]);
}
else
{
child->SetLongitudeRange(lonRange[0], center[0]);
}
int id = 0;
if (level == 0)
{
// Special case: in the first level, the western hemisphere has id 0, and
// the eastern hemisphere has id 1. This is to be compatible with the old
// tile database format.
if (index == 2)
{
id = 0;
}
else if (index == 3)
{
id = 1;
}
else if (index == 0)
{
vtkSmartPointer<vtkImageData> dummyImageWest = vtkSmartPointer<vtkImageData>::New();
dummyImageWest->SetOrigin(-180.0, -270.0, 0.0);
dummyImageWest->SetSpacing(0.0, -90.0, 0.0);
child->GetTexture()->SetInputData(dummyImageWest);
child->SetLatitudeRange(-270, -90);
child->SetLongitudeRange(-180, 0);
child->SetId(2);
return true;
}
else if (index == 1)
{
vtkSmartPointer<vtkImageData> dummyImageEast = vtkSmartPointer<vtkImageData>::New();
dummyImageEast->SetOrigin(0.0, -270.0, 0.0);
dummyImageEast->SetSpacing(180.0, -90.0, 0.0);
child->GetTexture()->SetInputData(dummyImageEast);
child->SetLatitudeRange(-270, -90);
child->SetLongitudeRange(0, 180);
child->SetId(3);
return true;
}
}
else
{
id = parent->GetId() | (index << (2*level - 1));
}
child->SetId(id);
// Crop and save the image.
// Overwrite an image if it already exists.
this->CropImageForNode(child, vtkImageData::SafeDownCast(this->LevelImages->GetBlock(blockLevel)));
return true;
}
//------------------------------------------------------------------------------
void vtkGeoAlignedImageSource::CropImageForNode(vtkGeoImageNode* node, vtkImageData* image)
{
int ext[6];
int wholeExt[6];
// I am keeping this all external to the imageData object because
// I consider pixels are cells not points.
image->GetExtent(ext);
image->GetExtent(wholeExt);
double origin[2];
double spacing[2];
spacing[0] = (this->LongitudeRange[1]-this->LongitudeRange[0])/static_cast<double>(ext[1]-ext[0]+1);
spacing[1] = (this->LatitudeRange[1]-this->LatitudeRange[0])/static_cast<double>(ext[3]-ext[2]+1);
origin[0] = this->LongitudeRange[0] - ext[0]*spacing[0];
origin[1] = this->LatitudeRange[0] - ext[2]*spacing[1];
// Compute the minimum extent that covers the terrain patch.
double overlapDist[2];
overlapDist[0] = this->Overlap*(node->GetLongitudeRange()[1]-node->GetLongitudeRange()[0]);
overlapDist[1] = this->Overlap*(node->GetLatitudeRange()[1]-node->GetLatitudeRange()[0]);
ext[0] = static_cast<int>(floor((node->GetLongitudeRange()[0]-overlapDist[0]-origin[0])/spacing[0]));
ext[1] = static_cast<int>(ceil((node->GetLongitudeRange()[1]+overlapDist[0]-origin[0])/spacing[0]));
ext[2] = static_cast<int>(floor((node->GetLatitudeRange()[0]-overlapDist[1]-origin[1])/spacing[1]));
ext[3] = static_cast<int>(ceil((node->GetLatitudeRange()[1]+overlapDist[1]-origin[1])/spacing[1]));
int dims[2];
if (this->PowerOfTwoSize)
{
dims[0] = this->PowerOfTwo(ext[1]-ext[0]+1);
dims[1] = this->PowerOfTwo(ext[3]-ext[2]+1);
ext[1] = ext[0] + dims[0] - 1;
ext[3] = ext[2] + dims[1] - 1;
}
else
{
dims[0] = ext[1]-ext[0]+1;
dims[1] = ext[3]-ext[2]+1;
}
if (ext[1] > wholeExt[1])
{
ext[1] = wholeExt[1];
}
if (ext[3] > wholeExt[3])
{
ext[3] = wholeExt[3];
}
ext[0] = ext[1] - dims[0] + 1;
ext[2] = ext[3] - dims[1] + 1;
if (ext[0] < wholeExt[0])
{
ext[0] = wholeExt[0];
}
if (ext[2] < wholeExt[2])
{
ext[2] = wholeExt[2];
}
vtkSmartPointer<vtkImageData> cropped = vtkSmartPointer<vtkImageData>::New();
cropped->ShallowCopy(image);
cropped->Crop(ext);
// Now set the longitude and latitude range based on the actual image size.
double lonRange[2];
double latRange[2];
lonRange[0] = origin[0] + ext[0]*spacing[0];
lonRange[1] = origin[0] + (ext[1]+1)*spacing[0];
latRange[0] = origin[1] + ext[2]*spacing[1];
latRange[1] = origin[1] + (ext[3]+1)*spacing[1];
cropped->SetOrigin(lonRange[0], latRange[0], 0);
cropped->SetSpacing(lonRange[1], latRange[1], 0);
//assert(lonRange[1] >= lonRange[0]);
//assert(latRange[1] >= latRange[0]);
vtkSmartPointer<vtkTexture> tex = vtkSmartPointer<vtkTexture>::New();
vtkSmartPointer<vtkTransform> texTrans = vtkSmartPointer<vtkTransform>::New();
// Start with (lat,lon)
texTrans->PostMultiply();
texTrans->RotateZ(90.0); // (-lon,lat)
texTrans->Scale(-1.0, 1.0, 1.0); // (lon,lat)
texTrans->Translate(-lonRange[0], -latRange[0], 0.0); // to origin
texTrans->Scale(1.0/(lonRange[1] - lonRange[0]), 1.0/(latRange[1] - latRange[0]), 1.0); // to [0,1]
tex->SetTransform(texTrans);
tex->SetInputData(cropped);
tex->InterpolateOn();
tex->RepeatOff();
tex->EdgeClampOn();
node->SetTexture(tex);
}
//-----------------------------------------------------------------------------
int vtkGeoAlignedImageSource::PowerOfTwo(int val)
{
// Pick the next highest power of two.
int tmp;
bool nextHigherFlag = false;
tmp = 1;
while (val)
{
if ((val & 1) && val > 1)
{
nextHigherFlag = true;
}
val = val >> 1;
tmp = tmp << 1;
}
if ( ! nextHigherFlag)
{
tmp = tmp >> 1;
}
return tmp;
}

View File

@ -0,0 +1,102 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkGeoAlignedImageSource.h
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.
-------------------------------------------------------------------------*/
// .NAME vtkGeoAlignedImageSource - Splits hi-res image into tiles.
//
// .SECTION Description
// vtkGeoAlignedImageSource uses a high resolution image to generate tiles
// at multiple resolutions in a hierarchy. It should be used as a source in
// vtkGeoAlignedImageRepresentation.
// .SECTION See Also
// vtkGeoAlignedImageRepresentation vtkGeoView vtkGeoView2D
#ifndef vtkGeoAlignedImageSource_h
#define vtkGeoAlignedImageSource_h
#include "vtkGeovisCoreModule.h" // For export macro
#include "vtkGeoSource.h"
class vtkGeoImageNode;
class vtkImageData;
class vtkMultiBlockDataSet;
class VTKGEOVISCORE_EXPORT vtkGeoAlignedImageSource : public vtkGeoSource
{
public:
static vtkGeoAlignedImageSource *New();
vtkTypeMacro(vtkGeoAlignedImageSource, vtkGeoSource);
void PrintSelf(ostream& os, vtkIndent indent);
// Description:
// Fetch the root image.
virtual bool FetchRoot(vtkGeoTreeNode* node);
// Description:
// Fetch a child image.
virtual bool FetchChild(vtkGeoTreeNode* parent, int index, vtkGeoTreeNode* child);
// Description:
// The high-resolution image to be used to cover the globe.
vtkGetObjectMacro(Image, vtkImageData);
virtual void SetImage(vtkImageData* image);
// Description:
// The range of the input hi-res image.
vtkSetVector2Macro(LatitudeRange, double);
vtkGetVector2Macro(LatitudeRange, double);
vtkSetVector2Macro(LongitudeRange, double);
vtkGetVector2Macro(LongitudeRange, double);
// Description:
// The overlap of adjacent tiles.
vtkSetClampMacro(Overlap, double, 0.0, VTK_DOUBLE_MAX);
vtkGetMacro(Overlap, double);
// Description:
// Whether to force image sizes to a power of two.
vtkSetMacro(PowerOfTwoSize, bool);
vtkGetMacro(PowerOfTwoSize, bool);
vtkBooleanMacro(PowerOfTwoSize, bool);
protected:
vtkGeoAlignedImageSource();
~vtkGeoAlignedImageSource();
void CropImageForNode(vtkGeoImageNode* node, vtkImageData* image);
int PowerOfTwo(int val);
vtkImageData* Image;
vtkMultiBlockDataSet* LevelImages;
double LatitudeRange[2];
double LongitudeRange[2];
double Overlap;
bool PowerOfTwoSize;
//BTX
class vtkProgressObserver;
vtkProgressObserver* ProgressObserver;
//ETX
private:
vtkGeoAlignedImageSource(const vtkGeoAlignedImageSource&); // Not implemented.
void operator=(const vtkGeoAlignedImageSource&); // Not implemented.
};
#endif

View File

@ -0,0 +1,176 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkGeoArcs.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 "vtkGeoArcs.h"
#include "vtkCellArray.h"
#include "vtkCellData.h"
#include "vtkFloatArray.h"
#include "vtkGeoMath.h"
#include "vtkGlobeSource.h"
#include "vtkMath.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
vtkStandardNewMacro(vtkGeoArcs);
vtkGeoArcs::vtkGeoArcs()
{
this->GlobeRadius = vtkGeoMath::EarthRadiusMeters();
this->ExplodeFactor = 0.2;
this->NumberOfSubdivisions = 20;
}
int vtkGeoArcs::RequestData(
vtkInformation *vtkNotUsed(request),
vtkInformationVector **inputVector,
vtkInformationVector *outputVector)
{
// get the info objects
vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
vtkInformation *outInfo = outputVector->GetInformationObject(0);
// get the input and output
vtkPolyData *input = vtkPolyData::SafeDownCast(
inInfo->Get(vtkDataObject::DATA_OBJECT()));
vtkPolyData *output = vtkPolyData::SafeDownCast(
outInfo->Get(vtkDataObject::DATA_OBJECT()));
// Prepare to copy cell data
output->GetCellData()->CopyAllocate(input->GetCellData());
// Traverse input lines, adding a circle for each line segment.
vtkCellArray* lines = input->GetLines();
vtkCellArray* newLines = vtkCellArray::New();
vtkPoints* newPoints = vtkPoints::New();
newPoints->DeepCopy(input->GetPoints());
lines->InitTraversal();
for (vtkIdType i = 0; i < lines->GetNumberOfCells(); i++)
{
vtkIdType npts=0; // to remove warning
vtkIdType* pts=0; // to remove warning
lines->GetNextCell(npts, pts);
double lastPoint[3];
newPoints->GetPoint(pts[0], lastPoint);
for (vtkIdType p = 1; p < npts; ++p)
{
// Create the new cell
vtkIdType cellId = newLines->InsertNextCell(this->NumberOfSubdivisions);
output->GetCellData()->CopyData(input->GetCellData(), i, cellId);
double curPoint[3];
newPoints->GetPoint(pts[p], curPoint);
// Find w, a unit vector pointing from the center of the
// earth directly inbetween the two endpoints.
double w[3];
for (int c = 0; c < 3; ++c)
{
w[c] = (lastPoint[c] + curPoint[c])/2.0;
}
vtkMath::Normalize(w);
// The center of the circle used to draw the arc is a
// point along the vector w scaled by the explode factor.
double center[3];
for (int c = 0; c < 3; ++c)
{
center[c] = this->ExplodeFactor * this->GlobeRadius * w[c];
}
// The vectors u and x are unit vectors pointing from the
// center of the circle to the two endpoints of the arc,
// lastPoint and curPoint, respectively.
double u[3], x[3];
for (int c = 0; c < 3; ++c)
{
u[c] = lastPoint[c] - center[c];
x[c] = curPoint[c] - center[c];
}
double radius = vtkMath::Norm(u);
vtkMath::Normalize(u);
vtkMath::Normalize(x);
// Find the angle that the arc spans.
double theta = acos(vtkMath::Dot(u, x));
// If the vectors u, x point toward the center of the earth, take
// the larger angle between the vectors.
// We determine whether u points toward the center of the earth
// by checking whether the dot product of u and w is negative.
if (vtkMath::Dot(w, u) < 0)
{
theta = 2.0*vtkMath::Pi() - theta;
}
// We need two perpendicular vectors on the plane of the circle
// in order to draw the circle. First we calculate n, a vector
// normal to the circle, by crossing u and w. Next, we cross
// n and u in order to get a vector v in the plane of the circle
// that is perpendicular to u.
double n[3];
vtkMath::Cross(u, w, n);
vtkMath::Normalize(n);
double v[3];
vtkMath::Cross(n, u, v);
vtkMath::Normalize(v);
// Use the general equation for a circle in three dimensions
// to draw an arc from the last point to the current point.
for (int s = 0; s < this->NumberOfSubdivisions; ++s)
{
double angle = s * theta / (this->NumberOfSubdivisions - 1.0);
double circlePt[3];
for (int c = 0; c < 3; ++c)
{
circlePt[c] = center[c] + radius*cos(angle)*u[c] + radius*sin(angle)*v[c];
}
vtkIdType newPt = newPoints->InsertNextPoint(circlePt);
newLines->InsertCellPoint(newPt);
}
for (int c = 0; c < 3; ++c)
{
lastPoint[c] = curPoint[c];
}
}
}
// Send the data to output.
output->SetLines(newLines);
output->SetPoints(newPoints);
// Clean up.
newLines->Delete();
newPoints->Delete();
return 1;
}
void vtkGeoArcs::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
os << indent << "GlobeRadius: " << this->GlobeRadius << endl;
os << indent << "ExplodeFactor: " << this->ExplodeFactor << endl;
os << indent << "NumberOfSubdivisions: " << this->NumberOfSubdivisions << endl;
}

View File

@ -0,0 +1,77 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkGeoArcs.h
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.
-------------------------------------------------------------------------*/
// .NAME vtkGeoArcs - Layout graph edges on a globe as arcs.
//
// .SECTION Description
// vtkGeoArcs produces arcs for each line in the input polydata. This is useful
// for viewing lines on a sphere (e.g. the earth). The arcs may "jump" above
// the sphere's surface using ExplodeFactor.
#ifndef vtkGeoArcs_h
#define vtkGeoArcs_h
#include "vtkGeovisCoreModule.h" // For export macro
#include "vtkPolyDataAlgorithm.h"
class VTKGEOVISCORE_EXPORT vtkGeoArcs : public vtkPolyDataAlgorithm
{
public:
static vtkGeoArcs *New();
vtkTypeMacro(vtkGeoArcs,vtkPolyDataAlgorithm);
void PrintSelf(ostream& os, vtkIndent indent);
// Description:
// The base radius used to determine the earth's surface.
// Default is the earth's radius in meters.
vtkSetMacro(GlobeRadius, double);
vtkGetMacro(GlobeRadius, double);
// Description:
// Factor on which to "explode" the arcs away from the surface.
// A value of 0.0 keeps the values on the surface.
// Values larger than 0.0 push the arcs away from the surface by a distance
// proportional to the distance between the points.
// The default is 0.2.
vtkSetMacro(ExplodeFactor, double);
vtkGetMacro(ExplodeFactor, double);
// Description:
// The number of subdivisions in the arc.
// The default is 20.
vtkSetMacro(NumberOfSubdivisions, int);
vtkGetMacro(NumberOfSubdivisions, int);
protected:
vtkGeoArcs();
~vtkGeoArcs() {}
int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *);
double GlobeRadius;
double ExplodeFactor;
int NumberOfSubdivisions;
private:
vtkGeoArcs(const vtkGeoArcs&); // Not implemented.
void operator=(const vtkGeoArcs&); // Not implemented.
};
#endif

View File

@ -0,0 +1,213 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkGeoAssignCoordinates.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 "vtkGeoAssignCoordinates.h"
#include "vtkAbstractTransform.h"
#include "vtkGeoMath.h"
#include "vtkGlobeSource.h"
#include "vtkGraph.h"
#include "vtkIdTypeArray.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkMath.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkPointSet.h"
#include "vtkPoints.h"
vtkCxxSetObjectMacro(vtkGeoAssignCoordinates, Transform, vtkAbstractTransform);
vtkStandardNewMacro(vtkGeoAssignCoordinates);
vtkGeoAssignCoordinates::vtkGeoAssignCoordinates()
{
this->LongitudeArrayName = 0;
this->LatitudeArrayName = 0;
this->CoordinatesInArrays = true;
this->Transform = 0;
this->GlobeRadius = vtkGeoMath::EarthRadiusMeters();
}
vtkGeoAssignCoordinates::~vtkGeoAssignCoordinates()
{
if (this->Transform)
{
this->Transform->Delete();
}
delete[] this->LongitudeArrayName;
delete[] this->LatitudeArrayName;
}
int vtkGeoAssignCoordinates::RequestData(vtkInformation *vtkNotUsed(request),
vtkInformationVector **inputVector,
vtkInformationVector *outputVector)
{
// get the info objects
vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
vtkInformation *outInfo = outputVector->GetInformationObject(0);
// get the input and output
vtkDataObject *input = inInfo->Get(vtkDataObject::DATA_OBJECT());
vtkDataObject *output = outInfo->Get(vtkDataObject::DATA_OBJECT());
vtkGraph *graphInput = vtkGraph::SafeDownCast(input);
vtkGraph *graphOutput = vtkGraph::SafeDownCast(output);
vtkPointSet *psInput = vtkPointSet::SafeDownCast(input);
vtkPointSet *psOutput = vtkPointSet::SafeDownCast(output);
// Do a shallow copy of the input to the output
// and then create new points on the output
output->ShallowCopy(input);
vtkPoints *newPoints = vtkPoints::New();
vtkPoints *oldPoints = 0;
vtkDataSetAttributes *pd = 0;
vtkIdType numPoints = 0;
if (graphInput)
{
oldPoints = graphInput->GetPoints();
newPoints->DeepCopy(oldPoints);
graphOutput->SetPoints(newPoints);
pd = graphOutput->GetVertexData();
numPoints = graphInput->GetNumberOfVertices();
}
else
{
oldPoints = psInput->GetPoints();
newPoints->DeepCopy(oldPoints);
psOutput->SetPoints(newPoints);
pd = psOutput->GetPointData();
numPoints = psInput->GetNumberOfPoints();
}
newPoints->Delete();
// If there are no points in the input, we're done!
if (numPoints == 0)
{
return 1;
}
vtkDataArray* latitudeArray = 0;
vtkDataArray* longitudeArray = 0;
if (this->CoordinatesInArrays)
{
// I need a latitude array
if (!this->LatitudeArrayName || strlen(this->LatitudeArrayName) == 0)
{
vtkErrorMacro("No latitude array defined.");
return 0;
}
// I need a longitude array
if (!this->LongitudeArrayName || strlen(this->LongitudeArrayName) == 0)
{ // If on, uses LatitudeArrayName and LongitudeArrayName to
// move values in data arrays into the points of the data set.
// Turn off if the latitude and longitude are already in
// the points.
vtkErrorMacro("No longitude array defined.");
return 0;
}
// Okay now check for arrays
latitudeArray = pd->GetArray(this->LatitudeArrayName);
// Does the latitude array exist at all?
if (this->CoordinatesInArrays && latitudeArray == NULL)
{
vtkErrorMacro("Could not find array named " << this->LatitudeArrayName);
return 0;
}
// Longitude coordinate array
longitudeArray = pd->GetArray(this->LongitudeArrayName);
// Does the array exist at all?
if (this->CoordinatesInArrays && longitudeArray == NULL)
{
vtkErrorMacro("Could not find array named " << this->LongitudeArrayName);
return 0;
}
}
// Convert the points to global coordinates
for (int i = 0; i < numPoints; i++)
{
double theta, phi;
if (this->CoordinatesInArrays)
{
theta = longitudeArray->GetTuple1(i);
phi = latitudeArray->GetTuple1(i);
}
else
{
double a[3];
oldPoints->GetPoint(i, a);
theta = a[0];
phi = a[1];
}
// Clamp to lat/long bounds
theta = (theta > 180.0) ? 180.0 : theta;
theta = (theta < -180.0) ? -180.0 : theta;
phi = (phi > 90.0) ? 90.0 : phi;
phi = (phi < -90.0) ? -90.0 : phi;
double x[3];
if (this->Transform)
{
double in[] = {theta, phi, 0.0};
this->Transform->TransformPoint(in, x);
}
else
{
vtkGlobeSource::ComputeGlobePoint(theta, phi, this->GlobeRadius, x);
}
newPoints->SetPoint(i, x[0], x[1], x[2]);
}
return 1;
}
int vtkGeoAssignCoordinates::FillInputPortInformation(int vtkNotUsed(port), vtkInformation* info)
{
// This algorithm may accept a vtkPointSet or vtkGraph.
info->Remove(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE());
info->Append(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkPointSet");
info->Append(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkGraph");
return 1;
}
void vtkGeoAssignCoordinates::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
os << indent << "LatitudeArrayName: "
<< (this->LatitudeArrayName ? this->LatitudeArrayName : "(none)") << endl;
os << indent << "LongitudeArrayName: "
<< (this->LongitudeArrayName ? this->LongitudeArrayName : "(none)") << endl;
os << indent << "GlobeRadius: " << this->GlobeRadius << endl;
os << indent << "CoordinatesInArrays: " << (this->CoordinatesInArrays ? "on" : "off") << endl;
os << indent << "Transform: " << (this->Transform ? "" : "(none)") << endl;
if (this->Transform)
{
this->Transform->PrintSelf(os, indent.GetNextIndent());
}
}

View File

@ -0,0 +1,100 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkGeoAssignCoordinates.h
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.
-------------------------------------------------------------------------*/
// .NAME vtkGeoAssignCoordinates - Given latitude and longitude arrays,
// take the values in those arrays and convert them to x,y,z world coordinates.
//
// .SECTION Description
// Givem latitude and longitude arrays,
// take the values in those arrays and convert them to x,y,z world coordinates.
// Uses a spherical model of the earth to do the conversion.
// The position is in meters relative to the center of the earth.
//
// If a transform is given, use the transform to convert latitude and longitude
// to the world coordinate.
#ifndef vtkGeoAssignCoordinates_h
#define vtkGeoAssignCoordinates_h
#include "vtkGeovisCoreModule.h" // For export macro
#include "vtkPassInputTypeAlgorithm.h"
class vtkAbstractTransform;
class VTKGEOVISCORE_EXPORT vtkGeoAssignCoordinates : public vtkPassInputTypeAlgorithm
{
public:
static vtkGeoAssignCoordinates *New();
vtkTypeMacro(vtkGeoAssignCoordinates, vtkPassInputTypeAlgorithm);
void PrintSelf(ostream& os, vtkIndent indent);
// Description:
// Set the longitude coordinate array name.
vtkSetStringMacro(LongitudeArrayName);
vtkGetStringMacro(LongitudeArrayName);
// Description:
// Set the latitude coordinate array name.
vtkSetStringMacro(LatitudeArrayName);
vtkGetStringMacro(LatitudeArrayName);
// Description:
// The base radius to use in GLOBAL mode.
// Default is the earth's radius.
vtkSetMacro(GlobeRadius, double);
vtkGetMacro(GlobeRadius, double);
// Description:
// The transform to use to convert coordinates of the form
// (lat, long, 0) to (x, y z). If this is NULL (the default),
// use GlobeRadius to perform a spherical embedding.
virtual void SetTransform(vtkAbstractTransform* trans);
vtkGetObjectMacro(Transform, vtkAbstractTransform);
// Description:
// If on, uses LatitudeArrayName and LongitudeArrayName to
// move values in data arrays into the points of the data set.
// Turn off if the latitude and longitude are already in
// the points.
vtkSetMacro(CoordinatesInArrays, bool);
vtkGetMacro(CoordinatesInArrays, bool);
vtkBooleanMacro(CoordinatesInArrays, bool);
protected:
vtkGeoAssignCoordinates();
~vtkGeoAssignCoordinates();
int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *);
int FillInputPortInformation(int port, vtkInformation* info);
private:
char* LongitudeArrayName;
char* LatitudeArrayName;
double GlobeRadius;
bool CoordinatesInArrays;
vtkAbstractTransform* Transform;
vtkGeoAssignCoordinates(const vtkGeoAssignCoordinates&); // Not implemented.
void operator=(const vtkGeoAssignCoordinates&); // Not implemented.
};
#endif

View File

@ -0,0 +1,438 @@
/*=============================================================================
Program: Visualization Toolkit
Module: vtkGeoCamera.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 "vtkObjectFactory.h"
#include "vtkGeoCamera.h"
#include "vtkGeoMath.h"
#include "vtkGeoTerrainNode.h"
#include "vtkMath.h"
#include "vtkCamera.h"
#include "vtkTransform.h"
#include <float.h>
vtkStandardNewMacro(vtkGeoCamera);
//----------------------------------------------------------------------------
vtkGeoCamera::vtkGeoCamera()
{
this->VTKCamera = vtkSmartPointer<vtkCamera>::New();
this->Transform = vtkSmartPointer<vtkTransform>::New();
this->OriginLongitude = 0.0;
this->OriginLatitude = 0.0;
// Initial state will be looking at earth over the American continent.
//this->Longitude = -90.0;
this->Longitude = 0.0;
this->Latitude = 0.0;
this->Distance = vtkGeoMath::EarthRadiusMeters() * 5.0;
this->Heading = 0.0;
this->Tilt = 90.0;
this->LockHeading = true;
this->ComputeRectilinearOrigin();
this->UpdateAngleRanges();
this->UpdateVTKCamera();
this->Position[0] = this->Position[1] = this->Position[2] = 0.0;
this->Origin[0] = this->Origin[1] = this->Origin[2] = 0.0;
}
//-----------------------------------------------------------------------------
vtkGeoCamera::~vtkGeoCamera()
{
}
//-----------------------------------------------------------------------------
void vtkGeoCamera::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
os << indent << "Distance: " << this->Distance << endl;
os << indent << "Tilt: " << this->Tilt << endl;
os << indent << "Heading: " << this->Heading << endl;
os << indent << "Latitude: " << this->Latitude << endl;
os << indent << "Longitude: " << this->Longitude << endl;
os << indent << "LockHeading: " << (this->LockHeading ? "on" : "off");
os << indent << "Origin: {" << this->Origin[0] << ", " << this->Origin[1]
<< ", " << this->Origin[2] << "}" << endl;
os << indent << "OriginLatitude: " << this->OriginLatitude << endl;
os << indent << "OriginLongitude: " << this->OriginLongitude << endl;
os << indent << "Position: {" << this->Position[0] << ", " << this->Position[1]
<< ", " << this->Position[2] << "}" << endl;
os << indent << "VTKCamera: " << endl;
this->VTKCamera->PrintSelf(os, indent.GetNextIndent());
}
//-----------------------------------------------------------------------------
void vtkGeoCamera::SetOriginLatitude(double oLat)
{
if (this->OriginLatitude == oLat)
{
return;
}
this->OriginLatitude = oLat;
this->Modified();
this->ComputeRectilinearOrigin();
}
//-----------------------------------------------------------------------------
void vtkGeoCamera::SetOriginLongitude(double oLon)
{
if (this->OriginLongitude == oLon)
{
return;
}
this->OriginLongitude = oLon;
this->Modified();
this->ComputeRectilinearOrigin();
}
//-----------------------------------------------------------------------------
void vtkGeoCamera::ComputeRectilinearOrigin()
{
double tmp = cos(this->OriginLatitude * vtkMath::Pi() / 180.0);
this->Origin[1] = tmp * cos(this->OriginLongitude * vtkMath::Pi() / 180.0);
this->Origin[0] = -tmp * sin(this->OriginLongitude * vtkMath::Pi() / 180.0);
this->Origin[2] = sin(this->OriginLatitude * vtkMath::Pi() / 180.0);
this->Origin[0] *= vtkGeoMath::EarthRadiusMeters();
this->Origin[1] *= vtkGeoMath::EarthRadiusMeters();
this->Origin[2] *= vtkGeoMath::EarthRadiusMeters();
this->UpdateVTKCamera();
}
//-----------------------------------------------------------------------------
void vtkGeoCamera::SetLongitude(double longitude)
{
if (this->Longitude == longitude)
{
return;
}
this->Modified();
this->Longitude = longitude;
this->UpdateAngleRanges();
this->UpdateVTKCamera();
}
//-----------------------------------------------------------------------------
void vtkGeoCamera::SetLatitude(double latitude)
{
if (this->Latitude == latitude)
{
return;
}
this->Modified();
this->Latitude = latitude;
this->UpdateAngleRanges();
this->UpdateVTKCamera();
}
//-----------------------------------------------------------------------------
void vtkGeoCamera::SetDistance(double altitude)
{
if (this->Distance == altitude)
{
return;
}
this->Modified();
this->Distance = altitude;
this->UpdateVTKCamera();
}
//-----------------------------------------------------------------------------
void vtkGeoCamera::SetHeading(double heading)
{
if (this->Heading == heading)
{
return;
}
while (heading < -180)
{
heading += 360;
}
while (heading > 180)
{
heading -= 360;
}
this->Modified();
this->Heading = heading;
this->UpdateAngleRanges();
this->UpdateVTKCamera();
}
//-----------------------------------------------------------------------------
void vtkGeoCamera::SetTilt(double tilt)
{
if (this->Tilt == tilt)
{
return;
}
this->Modified();
this->Tilt = tilt;
this->UpdateVTKCamera();
}
//-----------------------------------------------------------------------------
void vtkGeoCamera::UpdateAngleRanges()
{
while (this->Heading > 180.0)
{
this->Heading -= 360.0;
}
while (this->Heading < -180.0)
{
this->Heading += 360.0;
}
while (this->Longitude > 180.0)
{
this->Longitude -= 360.0;
}
while (this->Longitude < -180.0)
{
this->Longitude += 360.0;
}
if (this->Latitude > 90.0)
{
this->Latitude = 180.0 - this->Latitude;
}
if (this->Latitude < -90.0)
{
this->Latitude = -180.0 - this->Latitude;
}
}
//-----------------------------------------------------------------------------
void vtkGeoCamera::UpdateVTKCamera()
{
this->Transform->PostMultiply();
this->Transform->Identity();
// Tilt
this->Transform->RotateX(this->Tilt);
// Heading
this->Transform->RotateY(-this->Heading);
// to surface of earth
this->Transform->Translate(0.0, vtkGeoMath::EarthRadiusMeters(), 0.0);
// Latitude
this->Transform->RotateX(this->Latitude);
// Longitude
this->Transform->RotateZ(this->Longitude);
// Consider origin.
this->Transform->Translate(-this->Origin[0],
-this->Origin[1],
-this->Origin[2]);
double* pt;
double tmp[3];
// Find focal point of the camera.
pt = this->Transform->TransformDoublePoint(0.0, 0.0, 0.0);
this->VTKCamera->SetFocalPoint(pt);
// Find position
this->VTKCamera->GetFocalPoint(tmp);
// Use arbitrary magnitude.
pt = this->Transform->TransformDoublePoint(0.0, 0.0, -this->Distance);
this->VTKCamera->SetPosition(pt);
// Save the position with out the origin shift so the evaluation works.
this->Position[0] = pt[0] + this->Origin[0];
this->Position[1] = pt[1] + this->Origin[1];
this->Position[2] = pt[2] + this->Origin[2];
if (this->LockHeading)
{
// Now find view up using heading.
pt = this->Transform->TransformDoublePoint(0.0, 1.0, 0.0);
tmp[0] = pt[0] - tmp[0];
tmp[1] = pt[1] - tmp[1];
tmp[2] = pt[2] - tmp[2];
this->VTKCamera->SetViewUp(tmp);
}
else
{
// Find heading using view up.
this->VTKCamera->OrthogonalizeViewUp();
double up[3];
this->VTKCamera->GetViewUp(up);
// Project vector to north pole and view up to the following plane:
// Normal = dir. out of center of earth from focal point, Point = origin.
// Compute the plane normal (center of earth at -origin).
double dir[3];
dir[0] = -tmp[0] - this->Origin[0];
dir[1] = -tmp[1] - this->Origin[1];
dir[2] = -tmp[2] - this->Origin[2];
vtkMath::Normalize(dir);
// Compute direction to north pole (at -origin + (0,0,earth_radius))
// from focal point.
double north[3];
north[0] = -this->Origin[0] - tmp[0];
north[1] = -this->Origin[1] - tmp[1];
north[2] = vtkGeoMath::EarthRadiusMeters() - this->Origin[2] - tmp[2];
double northDot = vtkMath::Dot(north, dir);
// Project direction to north pole to our plane.
double northProj[3];
northProj[0] = north[0] - northDot*dir[0];
northProj[1] = north[1] - northDot*dir[1];
northProj[2] = north[2] - northDot*dir[2];
vtkMath::Normalize(northProj);
// Project view up vector to the same plane.
double upDot = vtkMath::Dot(up, dir);
double upProj[3];
upProj[0] = up[0] - upDot*dir[0];
upProj[1] = up[1] - upDot*dir[1];
upProj[2] = up[2] - upDot*dir[2];
vtkMath::Normalize(upProj);
// Determine the angle between the vectors.
// Do some sin/cos trickery to get it to the full range
// [-180, 180].
double dotProd = vtkMath::Dot(northProj, upProj);
double crossProd[3];
vtkMath::Cross(northProj, upProj, crossProd);
this->Heading = vtkMath::DegreesFromRadians( asin( vtkMath::Norm( crossProd ) ) );
if (dotProd < 0)
{
this->Heading = 180.0 - this->Heading;
}
if (vtkMath::Dot(crossProd, dir) < 0)
{
this->Heading = -this->Heading;
}
}
}
//-----------------------------------------------------------------------------
void vtkGeoCamera::InitializeNodeAnalysis(int rendererSize[2])
{
this->Aspect[1] = tan( vtkMath::RadiansFromDegrees( this->VTKCamera->GetViewAngle() ) * 0.5 );
this->Aspect[0] = this->Aspect[1] * rendererSize[0]
/ static_cast<double>( rendererSize[1] );
this->VTKCamera->GetViewPlaneNormal(this->ForwardNormal);
this->ForwardNormal[0] = - this->ForwardNormal[0];
this->ForwardNormal[1] = - this->ForwardNormal[1];
this->ForwardNormal[2] = - this->ForwardNormal[2];
this->VTKCamera->GetViewUp(this->UpNormal);
vtkMath::Normalize(this->UpNormal);
vtkMath::Cross(this->ForwardNormal, this->UpNormal, this->RightNormal);
// It may not be necessary to keep the above as instance variables.
for (int ii = 0; ii < 3; ++ii)
{
this->LeftPlaneNormal[ii] = - this->ForwardNormal[ii]*this->Aspect[0]
- this->RightNormal[ii];
this->RightPlaneNormal[ii] = - this->ForwardNormal[ii]*this->Aspect[0]
+ this->RightNormal[ii];
this->DownPlaneNormal[ii] = - this->ForwardNormal[ii]*this->Aspect[1]
- this->UpNormal[ii];
this->UpPlaneNormal[ii] = - this->ForwardNormal[ii]*this->Aspect[1]
+ this->UpNormal[ii];
}
vtkMath::Normalize(this->LeftPlaneNormal);
vtkMath::Normalize(this->RightPlaneNormal);
vtkMath::Normalize(this->DownPlaneNormal);
vtkMath::Normalize(this->UpPlaneNormal);
}
//-----------------------------------------------------------------------------
// This has to be as fast as possible.
// It is called for each node every render.
// These comparisons in rectilinear coordinates are not perfect.
// I look at a viewplain containing the sphere center.
// I compate a circle with the view bounds.
// Another option is to save 4 frustum plane normals in the camera.
// This would require 5 dot products (15 multiplications).
double vtkGeoCamera::GetNodeCoverage(vtkGeoTerrainNode* node)
{
double sphereCenter[3];
double sphereRadius;
double camPosition[3];
this->GetPosition(camPosition);
// Lets take care of nodes on the opposite side of the earth.
// I think there should be a better way of figuring this out.
if (vtkMath::Dot(this->ForwardNormal,node->GetCornerNormal00())>0.0 &&
vtkMath::Dot(this->ForwardNormal,node->GetCornerNormal01())>0.0 &&
vtkMath::Dot(this->ForwardNormal,node->GetCornerNormal10())>0.0 &&
vtkMath::Dot(this->ForwardNormal,node->GetCornerNormal11())>0.0)
{ // Node is hidden by the earth.
return 0.0;
}
sphereRadius = node->GetBoundingSphereRadius();
node->GetBoundingSphereCenter(sphereCenter);
// Put the camera's position at the origin.
sphereCenter[0] = sphereCenter[0] - camPosition[0];
sphereCenter[1] = sphereCenter[1] - camPosition[1];
sphereCenter[2] = sphereCenter[2] - camPosition[2];
double left = vtkMath::Dot(this->LeftPlaneNormal,sphereCenter);
double right = vtkMath::Dot(this->RightPlaneNormal,sphereCenter);
double down = vtkMath::Dot(this->DownPlaneNormal,sphereCenter);
double up = vtkMath::Dot(this->UpPlaneNormal,sphereCenter);
double forward = vtkMath::Dot(this->ForwardNormal,sphereCenter);
if ( left > sphereRadius || right > sphereRadius ||
down > sphereRadius || up > sphereRadius ||
forward < -sphereRadius)
{
return 0.0;
}
if (forward < sphereRadius)
{ // Camera is probably in the sphere.
return 1.0;
}
left = -left;
if (left > sphereRadius) { left = sphereRadius;}
up = -up;
if (up > sphereRadius) { up = sphereRadius;}
right = -right;
if (right > sphereRadius) { right = sphereRadius;}
down = -down;
if (down > sphereRadius) { down = sphereRadius;}
double coverage = (left+right)*(up+down) / (4.0 * forward*forward*this->Aspect[0]*this->Aspect[1]);
return coverage;
}
//-----------------------------------------------------------------------------
vtkCamera* vtkGeoCamera::GetVTKCamera()
{
return this->VTKCamera;
}

View File

@ -0,0 +1,217 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkGeoCamera.h
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.
-------------------------------------------------------------------------*/
// .NAME vtkGeoCamera - Geo interface to a camera.
//
// .SECTION Description
// I wanted to hide the normal vtkCamera API
// so I did not make this a subclass. The camera is a helper object.
// You can get a pointer to the camera, but it should be treated like
// a const.
// View up of the camera is restricted so there is no roll relative
// to the earth. I am going to keep view up of the camera orthogonalized to
// avoid the singularity that exists when the camera is pointing straight down.
// In this case, view up is the same as heading.
//
// The state of the view is specified by the vector:
// (Longitude,Latitude,Distance,Heading,Tilt).
// Longitude in degrees: (-180->180)
// Relative to absolute coordinates.
// Latitude in degrees: (-90->90)
// Relative to Longitude.
// Distance in Meters
// Relative to Longitude and Latitude.
// above sea level ???? should we make this from center of earth ????
// ???? what about equatorial bulge ????
// Heading in degrees: (-180->180)
// Relative to Logitude and Latitude.
// 0 is north.
// 90 is east. ???? what is the standard ????
// 180 is south.
// -90 is west.
// Tilt in degrees: (0->90)
// Relative to Longitude, Latitude, Distance and Heading.
//
//
// Transformation:
// Post concatenate.
// All rotations use right hand rule and are around (0,0,0) (earth center).
// (0,0,0,0,0) is this rectilinear point (0, EarthRadius, 0)
// pointing (0,0,1), view up (0,1,0).
//
// Rotate Tilt around x axis,
// Rotate Heading around -y axis Center,
// Translate EarthRadius in y direction.
// Rotate Latitude around x axis by Latitude,
// Rotate Longitude around z axis (earth axis),
//
// .SECTION See Also
// vtkGeoInteractorStyle vtkCamera
#ifndef vtkGeoCamera_h
#define vtkGeoCamera_h
#include "vtkGeovisCoreModule.h" // For export macro
#include "vtkObject.h"
#include "vtkSmartPointer.h" // for SP
class vtkCamera;
class vtkGeoTerrainNode;
class vtkTransform;
class VTKGEOVISCORE_EXPORT vtkGeoCamera : public vtkObject
{
public:
static vtkGeoCamera *New();
vtkTypeMacro(vtkGeoCamera, vtkObject);
void PrintSelf(ostream& os, vtkIndent indent);
// Description:
// Get the world position without the origin shift.
vtkGetVector3Macro(Position, double);
// Description:
// Longitude is in degrees: (-180->180)
// Relative to absolute coordinates.
// Rotate Longitude around z axis (earth axis),
void SetLongitude(double longitude);
vtkGetMacro(Longitude,double);
// Description:
// Latitude is in degrees: (-90->90)
// Relative to Longitude.
// Rotate Latitude around x axis by Latitude,
void SetLatitude(double latitude);
vtkGetMacro(Latitude,double);
// Description:
// Distance is in Meters
// Relative to Longitude and Latitude.
// above sea level ???? should we make this from center of earth ????
// ???? what about equatorial bulge ????
void SetDistance(double Distance);
vtkGetMacro(Distance,double);
// Description:
// Heading is in degrees: (-180->180)
// Relative to Logitude and Latitude.
// 0 is north.
// 90 is east. ???? what is the standard ????
// 180 is south.
// -90 is west.
// Rotate Heading around -y axis Center,
void SetHeading(double heading);
vtkGetMacro(Heading,double);
// Description:
// Tilt is also know as pitch.
// Tilt is in degrees: (0->90)
// Relative to Longitude, Latitude, and Heading.
// Rotate Tilt around x axis,
void SetTilt(double tilt);
vtkGetMacro(Tilt,double);
// Description:
// This vtk camera is updated to match this geo cameras state.
// It should be treated as a const and should not be modified.
vtkCamera* GetVTKCamera();
// Description:
// We precompute some values to speed up update of the terrain.
// Unfortunately, they have to be manually/explicitly updated
// when the camera or renderer size changes.
void InitializeNodeAnalysis(int rendererSize[2]);
// Description:
// This method estimates how much of the view is covered by the sphere.
// Returns a value from 0 to 1.
double GetNodeCoverage(vtkGeoTerrainNode* node);
// Description:
// Whether to lock the heading a particular value,
// or to let the heading "roam free" when performing
// latitude and longitude changes.
vtkGetMacro(LockHeading, bool);
vtkSetMacro(LockHeading, bool);
vtkBooleanMacro(LockHeading, bool);
// Description:
// This point is shifted to 0,0,0 to avoid openGL issues.
void SetOriginLatitude(double oLat);
vtkGetMacro(OriginLatitude, double);
void SetOriginLongitude(double oLat);
vtkGetMacro(OriginLongitude, double);
// Description:
// Get the rectilinear cooridinate location of the origin.
// This is used to shift the terrain points.
vtkGetVector3Macro(Origin, double);
void SetOrigin( double ox, double oy, double oz ) {
this->Origin[0] = ox; this->Origin[1] = oy; this->Origin[2] = oz;
this->UpdateVTKCamera();
}
protected:
vtkGeoCamera();
~vtkGeoCamera();
void UpdateVTKCamera();
void UpdateAngleRanges();
//BTX
vtkSmartPointer<vtkCamera> VTKCamera;
vtkSmartPointer<vtkTransform> Transform;
//ETX
// This point is shifted to 0,0,0 to avoid openGL issues.
double OriginLatitude;
double OriginLongitude;
double Origin[3];
void ComputeRectilinearOrigin();
double Longitude;
double Latitude;
double Distance;
double Heading;
double Tilt;
bool LockHeading;
// Values precomputed to make updating terrain mode efficient.
// The vislibility of many terrain nodes is analyzed every render.
double ForwardNormal[3];
double RightNormal[3];
double UpNormal[3];
double Aspect[2];
// Frustum planes is better than other options for culling spheres.
double LeftPlaneNormal[3];
double RightPlaneNormal[3];
double DownPlaneNormal[3];
double UpPlaneNormal[3];
double Position[3];
private:
vtkGeoCamera(const vtkGeoCamera&); // Not implemented.
void operator=(const vtkGeoCamera&); // Not implemented.
};
#endif

View File

@ -0,0 +1,192 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkGeoFileImageSource.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 "vtkGeoFileImageSource.h"
#include "vtkDoubleArray.h"
#include "vtkGeoImageNode.h"
#include "vtkImageData.h"
#include "vtkImageGridSource.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkSmartPointer.h"
#include "vtkStdString.h"
#include "vtkTexture.h"
#include "vtkTransform.h"
#include "vtkXMLImageDataReader.h"
#include <fstream>
#include <sstream>
#include <utility>
vtkStandardNewMacro(vtkGeoFileImageSource);
//----------------------------------------------------------------------------
vtkGeoFileImageSource::vtkGeoFileImageSource()
{
this->Path = 0;
}
//----------------------------------------------------------------------------
vtkGeoFileImageSource::~vtkGeoFileImageSource()
{
this->SetPath(0);
}
//----------------------------------------------------------------------------
bool vtkGeoFileImageSource::FetchRoot(vtkGeoTreeNode* r)
{
vtkGeoImageNode* root = 0;
if (!(root = vtkGeoImageNode::SafeDownCast(r)))
{
vtkErrorMacro(<< "Can only fetch image nodes from this source.");
return false;
}
root->SetLatitudeRange(-270, 90);
root->SetLongitudeRange(-180, 180);
this->ReadImage(-1, 0, root);
return true;
}
//----------------------------------------------------------------------------
bool vtkGeoFileImageSource::FetchChild(vtkGeoTreeNode* p, int index, vtkGeoTreeNode* c)
{
vtkGeoImageNode* parent = 0;
if (!(parent = vtkGeoImageNode::SafeDownCast(p)))
{
vtkErrorMacro(<< "Can only fetch image nodes from this source.");
return false;
}
vtkGeoImageNode* child = 0;
if (!(child = vtkGeoImageNode::SafeDownCast(c)))
{
vtkErrorMacro(<< "Can only fetch image nodes from this source.");
return false;
}
if (parent->GetLevel() == -1)
{
// Child 0 is the dummy western hemisphere, child 1 is the dummy eastern hemisphere
// Child 2 is the western hemisphere, child 3 is the eastern hemisphere
if (index == 0)
{
vtkSmartPointer<vtkImageData> dummyImageWest = vtkSmartPointer<vtkImageData>::New();
dummyImageWest->SetOrigin(-180.0, -270.0, 0.0);
dummyImageWest->SetSpacing(0.0, -90.0, 0.0);
child->GetTexture()->SetInputData(dummyImageWest);
child->SetLatitudeRange(-270, -90);
child->SetLongitudeRange(-180, 0);
}
else if (index == 1)
{
vtkSmartPointer<vtkImageData> dummyImageEast = vtkSmartPointer<vtkImageData>::New();
dummyImageEast->SetOrigin(0.0, -270.0, 0.0);
dummyImageEast->SetSpacing(180.0, -90.0, 0.0);
child->GetTexture()->SetInputData(dummyImageEast);
child->SetLatitudeRange(-270, -90);
child->SetLongitudeRange(0, 180);
}
else if (index == 2)
{
this->ReadImage(0, 0, child);
}
else
{
this->ReadImage(0, 1, child);
}
return true;
}
int level = parent->GetLevel() + 1;
int id = parent->GetId() | (index << (2*level-1));
return this->ReadImage(level, id, child);
}
//----------------------------------------------------------------------------
bool vtkGeoFileImageSource::ReadImage(int level, int id, vtkGeoImageNode* node)
{
// Load the image
node->SetId(id);
node->SetLevel(level);
vtkSmartPointer<vtkXMLImageDataReader> reader = vtkSmartPointer<vtkXMLImageDataReader>::New();
std::stringstream ss;
ss.str("");
ss << this->Path << "/tile_" << level << "_" << id << ".vti";
// Check if the file exists
std::ifstream in;
in.open(ss.str().c_str(), std::ifstream::in);
if (in.fail())
{
// Make a dummy image
in.close();
vtkSmartPointer<vtkImageData> dummy = vtkSmartPointer<vtkImageData>::New();
dummy->SetDimensions(1, 1, 1);
vtkSmartPointer<vtkDoubleArray> scalar = vtkSmartPointer<vtkDoubleArray>::New();
scalar->InsertNextValue(0.0);
dummy->GetPointData()->SetScalars(scalar);
dummy->SetOrigin(node->GetLongitudeRange()[0], node->GetLatitudeRange()[0], 0.0);
dummy->SetSpacing(node->GetLongitudeRange()[1], node->GetLatitudeRange()[1], 0.0);
node->GetTexture()->SetInputData(dummy);
return false;
}
in.close();
// Read the file
reader->SetFileName(ss.str().c_str());
reader->Update();
vtkImageData* image = reader->GetOutput();
// Retrieve the image bounds using origin and spacing
double x1[3];
double x2[3];
image->GetOrigin(x1);
image->GetSpacing(x2);
double lonRange[2] = {x1[0], x2[0]};
double latRange[2] = {x1[1], x2[1]};
node->SetLatitudeRange(latRange);
node->SetLongitudeRange(lonRange);
// Make the texture with the correct transform
vtkSmartPointer<vtkTexture> texture = vtkSmartPointer<vtkTexture>::New();
vtkSmartPointer<vtkTransform> texTrans = vtkSmartPointer<vtkTransform>::New();
// Start with (lat,lon)
texTrans->PostMultiply();
texTrans->RotateZ(90.0); // (-lon,lat)
texTrans->Scale(-1.0, 1.0, 1.0); // (lon,lat)
texTrans->Translate(-lonRange[0], -latRange[0], 0.0); // to origin
texTrans->Scale(1.0/(lonRange[1] - lonRange[0]), 1.0/(latRange[1] - latRange[0]), 1.0); // to [0,1]
texture->SetInputConnection(reader->GetOutputPort());
texture->SetTransform(texTrans);
texture->RepeatOff();
texture->InterpolateOn();
texture->EdgeClampOn();
node->SetTexture(texture);
return true;
}
//-----------------------------------------------------------------------------
void vtkGeoFileImageSource::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
os << indent << "Path: " << (this->Path ? this->Path : "(none)") << endl;
}

View File

@ -0,0 +1,72 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkGeoFileImageSource.h
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.
-------------------------------------------------------------------------*/
// .NAME vtkGeoFileImageSource - A tiled image source on disk.
//
// .SECTION Description
// vtkGeoFileImageSource is a vtkGeoSource that fetches .vti images from
// disk in a directory with a certain naming scheme. You may use
// vtkGeoAlignedImageRepresentation's SaveDatabase method to generate
// an database of image tiles in this format.
#ifndef vtkGeoFileImageSource_h
#define vtkGeoFileImageSource_h
#include "vtkGeovisCoreModule.h" // For export macro
#include "vtkGeoSource.h"
#include "vtkSmartPointer.h" // For smart pointer ivars
class vtkGeoImageNode;
class vtkGeoTreeNode;
class VTKGEOVISCORE_EXPORT vtkGeoFileImageSource : public vtkGeoSource
{
public:
static vtkGeoFileImageSource *New();
vtkTypeMacro(vtkGeoFileImageSource,vtkGeoSource);
void PrintSelf(ostream& os, vtkIndent indent);
vtkGeoFileImageSource();
~vtkGeoFileImageSource();
// Description:
// Fetches the root image representing the whole globe.
virtual bool FetchRoot(vtkGeoTreeNode* root);
// Description:
// Fetches the child image of a parent from disk.
virtual bool FetchChild(vtkGeoTreeNode* node, int index, vtkGeoTreeNode* child);
// Description:
// The path the tiled image database.
vtkSetStringMacro(Path);
vtkGetStringMacro(Path);
protected:
bool ReadImage(int level, int id, vtkGeoImageNode* node);
private:
vtkGeoFileImageSource(const vtkGeoFileImageSource&); // Not implemented
void operator=(const vtkGeoFileImageSource&); // Not implemented
char* Path;
};
#endif

View File

@ -0,0 +1,137 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkGeoFileTerrainSource.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 "vtkGeoFileTerrainSource.h"
#include "vtkGeoTerrainNode.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkPolyData.h"
#include "vtkSmartPointer.h"
#include "vtkStdString.h"
#include "vtkXMLPolyDataReader.h"
#include <fstream>
#include <sstream>
#include <utility>
vtkStandardNewMacro(vtkGeoFileTerrainSource);
//----------------------------------------------------------------------------
vtkGeoFileTerrainSource::vtkGeoFileTerrainSource()
{
this->Path = 0;
}
//----------------------------------------------------------------------------
vtkGeoFileTerrainSource::~vtkGeoFileTerrainSource()
{
this->SetPath(0);
}
//----------------------------------------------------------------------------
bool vtkGeoFileTerrainSource::FetchRoot(vtkGeoTreeNode* r)
{
vtkGeoTerrainNode* root = 0;
if (!(root = vtkGeoTerrainNode::SafeDownCast(r)))
{
vtkErrorMacro(<< "Can only fetch terrain nodes from this source.");
return false;
}
this->ReadModel(0, 0, root);
return true;
}
//----------------------------------------------------------------------------
bool vtkGeoFileTerrainSource::FetchChild(vtkGeoTreeNode* p, int index, vtkGeoTreeNode* c)
{
vtkGeoTerrainNode* parent = 0;
if (!(parent = vtkGeoTerrainNode::SafeDownCast(p)))
{
vtkErrorMacro(<< "Can only fetch terrain nodes from this source.");
return false;
}
vtkGeoTerrainNode* child = 0;
if (!(child = vtkGeoTerrainNode::SafeDownCast(c)))
{
vtkErrorMacro(<< "Can only fetch terrain nodes from this source.");
return false;
}
int level = parent->GetLevel() + 1;
int id = parent->GetId() | (index << (2*level-2));
return this->ReadModel(level, id, child);
}
//----------------------------------------------------------------------------
bool vtkGeoFileTerrainSource::ReadModel(int level, int id, vtkGeoTerrainNode* node)
{
// Load the image
node->SetId(id);
node->SetLevel(level);
vtkSmartPointer<vtkXMLPolyDataReader> reader = vtkSmartPointer<vtkXMLPolyDataReader>::New();
std::stringstream ss;
ss.str("");
ss << this->Path << "/tile_" << level << "_" << id << ".vtp";
// Check if the file exists
std::ifstream in;
in.open(ss.str().c_str(), std::ifstream::in);
if (in.fail())
{
// Make a dummy polydata
in.close();
vtkSmartPointer<vtkPolyData> dummy = vtkSmartPointer<vtkPolyData>::New();
node->SetModel(dummy);
return false;
}
in.close();
// Read the file
reader->SetFileName(ss.str().c_str());
reader->Update();
vtkPolyData* model = reader->GetOutput();
node->SetModel(model);
double lonRange[2] = {0.0, 0.0};
double latRange[2] = {0.0, 0.0};
double xRange[2] = {0.0, 0.0};
double yRange[2] = {0.0, 0.0};
if (model->GetNumberOfPoints() > 0)
{
model->GetPointData()->GetArray("LatLong")->GetRange(latRange, 0);
model->GetPointData()->GetArray("LatLong")->GetRange(lonRange, 1);
model->GetPoints()->GetData()->GetRange(xRange, 0);
model->GetPoints()->GetData()->GetRange(yRange, 1);
}
node->SetLatitudeRange(latRange);
node->SetLongitudeRange(lonRange);
node->SetProjectionBounds(xRange[0], xRange[1], yRange[0], yRange[1]);
node->UpdateBoundingSphere();
return true;
}
//-----------------------------------------------------------------------------
void vtkGeoFileTerrainSource::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
os << indent << "Path: " << (this->Path ? this->Path : "(none)") << endl;
}

View File

@ -0,0 +1,72 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkGeoFileTerrainSource.h
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.
-------------------------------------------------------------------------*/
// .NAME vtkGeoFileTerrainSource - A source for tiled geometry on disk.
//
// .SECTION Description
// vtkGeoFileTerrainSource reads geometry tiles as .vtp files from a
// directory that follow a certain naming convention containing the level
// of the patch and the position within that level. Use vtkGeoTerrain's
// SaveDatabase method to create a database of files in this format.
#ifndef vtkGeoFileTerrainSource_h
#define vtkGeoFileTerrainSource_h
#include "vtkGeovisCoreModule.h" // For export macro
#include "vtkGeoSource.h"
#include "vtkSmartPointer.h" // For smart pointer ivars
class vtkGeoTerrainNode;
class vtkGeoTreeNode;
class VTKGEOVISCORE_EXPORT vtkGeoFileTerrainSource : public vtkGeoSource
{
public:
static vtkGeoFileTerrainSource *New();
vtkTypeMacro(vtkGeoFileTerrainSource,vtkGeoSource);
void PrintSelf(ostream& os, vtkIndent indent);
vtkGeoFileTerrainSource();
~vtkGeoFileTerrainSource();
// Description:
// Retrieve the root geometry representing the entire globe.
virtual bool FetchRoot(vtkGeoTreeNode* root);
// Description:
// Retrieve the child's geometry from disk.
virtual bool FetchChild(vtkGeoTreeNode* node, int index, vtkGeoTreeNode* child);
// Description:
// The path the tiled geometry database.
vtkSetStringMacro(Path);
vtkGetStringMacro(Path);
protected:
bool ReadModel(int level, int id, vtkGeoTerrainNode* node);
private:
vtkGeoFileTerrainSource(const vtkGeoFileTerrainSource&); // Not implemented
void operator=(const vtkGeoFileTerrainSource&); // Not implemented
char* Path;
};
#endif

View File

@ -0,0 +1,136 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkGeoGlobeSource.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 "vtkGeoGlobeSource.h"
#include "vtkGeoTerrainNode.h"
#include "vtkGlobeSource.h"
#include "vtkObjectFactory.h"
#include "vtkSmartPointer.h"
vtkStandardNewMacro(vtkGeoGlobeSource);
//----------------------------------------------------------------------------
vtkGeoGlobeSource::vtkGeoGlobeSource()
{
}
//----------------------------------------------------------------------------
vtkGeoGlobeSource::~vtkGeoGlobeSource()
{
}
//----------------------------------------------------------------------------
bool vtkGeoGlobeSource::FetchRoot(vtkGeoTreeNode* r)
{
vtkGeoTerrainNode* root = 0;
if (!(root = vtkGeoTerrainNode::SafeDownCast(r)))
{
vtkErrorMacro(<< "Can only fetch surface nodes from this source.");
}
vtkSmartPointer<vtkGlobeSource> source =
vtkSmartPointer<vtkGlobeSource>::New();
source->SetStartLatitude(-90.0);
source->SetEndLatitude(90.0);
source->SetStartLongitude(-180.0);
source->SetEndLongitude(180.0);
source->SetLatitudeResolution(20);
source->SetLongitudeResolution(20);
source->SetCurtainHeight(2000);
source->Update();
root->GetModel()->ShallowCopy(source->GetOutput());
root->SetLatitudeRange(-90, 90);
root->SetLongitudeRange(-180, 180);
root->UpdateBoundingSphere();
// Make sure bounds are up to date so we don't have threading issues
// when we hand this off to the main thread.
root->GetModel()->ComputeBounds();
return true;
}
//----------------------------------------------------------------------------
bool vtkGeoGlobeSource::FetchChild(vtkGeoTreeNode* p, int index, vtkGeoTreeNode* c)
{
vtkGeoTerrainNode* parent = 0;
if (!(parent = vtkGeoTerrainNode::SafeDownCast(p)))
{
vtkErrorMacro(<< "Can only fetch surface nodes from this source.");
}
vtkGeoTerrainNode* child = 0;
if (!(child = vtkGeoTerrainNode::SafeDownCast(c)))
{
vtkErrorMacro(<< "Can only fetch surface nodes from this source.");
}
double lonRange[2];
double latRange[2];
double center[2];
parent->GetLongitudeRange(lonRange);
parent->GetLatitudeRange(latRange);
center[0] = (lonRange[1] + lonRange[0])/2.0;
center[1] = (latRange[1] + latRange[0])/2.0;
int level = parent->GetLevel() + 1;
child->SetLevel(level);
if (index / 2)
{
child->SetLatitudeRange(center[1], latRange[1]);
}
else
{
child->SetLatitudeRange(latRange[0], center[1]);
}
if (index % 2)
{
child->SetLongitudeRange(center[0], lonRange[1]);
}
else
{
child->SetLongitudeRange(lonRange[0], center[0]);
}
int id = 0;
id = parent->GetId() | (index << (2*level - 2));
child->SetId(id);
vtkSmartPointer<vtkGlobeSource> source =
vtkSmartPointer<vtkGlobeSource>::New();
source->SetStartLatitude(child->GetLatitudeRange()[0]);
source->SetEndLatitude(child->GetLatitudeRange()[1]);
source->SetStartLongitude(child->GetLongitudeRange()[0]);
source->SetEndLongitude(child->GetLongitudeRange()[1]);
source->SetCurtainHeight(2000);
source->Update();
child->GetModel()->ShallowCopy(source->GetOutput());
child->UpdateBoundingSphere();
// Make sure bounds are up to date so we don't have threading issues
// when we hand this off to the main thread.
child->GetModel()->ComputeBounds();
return true;
}
//----------------------------------------------------------------------------
void vtkGeoGlobeSource::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
}

View File

@ -0,0 +1,58 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkGeoGlobeSource.h
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.
-------------------------------------------------------------------------*/
// .NAME vtkGeoGlobeSource - Spherical globe source.
//
// .SECTION Description
// vtkGeoGlobeSource is a 3D vtkGeoSource suitable for use in vtkGeoTerrain.
// It uses the vtkGlobeSource filter to produce terrain patches.
#ifndef vtkGeoGlobeSource_h
#define vtkGeoGlobeSource_h
#include "vtkGeovisCoreModule.h" // For export macro
#include "vtkGeoSource.h"
class vtkGeoTerrainNode;
class VTKGEOVISCORE_EXPORT vtkGeoGlobeSource : public vtkGeoSource
{
public:
static vtkGeoGlobeSource *New();
vtkTypeMacro(vtkGeoGlobeSource,vtkGeoSource);
void PrintSelf(ostream& os, vtkIndent indent);
// Description:
// Fetches a low-resolution sphere for the entire globe.
virtual bool FetchRoot(vtkGeoTreeNode* root);
// Description:
// Fetches a refined geometry patch, a section of a sphere.
virtual bool FetchChild(vtkGeoTreeNode* node, int index, vtkGeoTreeNode* child);
protected:
vtkGeoGlobeSource();
~vtkGeoGlobeSource();
private:
vtkGeoGlobeSource(const vtkGeoGlobeSource&); // Not implemented
void operator=(const vtkGeoGlobeSource&); // Not implemented
};
#endif

View File

@ -0,0 +1,304 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkGeoGraticule.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 "vtkGeoGraticule.h"
#include "vtkDoubleArray.h"
#include "vtkObjectFactory.h"
#include "vtkPolyData.h"
#include "vtkCellData.h"
#include "vtkCellType.h"
#include "vtkCellArray.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkIntArray.h"
#include "vtkPoints.h"
#include "vtkPointData.h"
#include <vector>
vtkStandardNewMacro(vtkGeoGraticule);
double vtkGeoGraticule::LatitudeLevelTics[12] =
{
90., // level 0: 90 degrees
30., // level 1: 30 degrees
10., // level 2: 10 degrees
5., // level 3: 5 degrees
1., // level 4: 1 degree
1. / 4., // level 5: 15 minutes (0.25 degrees)
1. / 12., // level 6: 5 minutes (0.08333 degrees)
1. / 60., // level 7: 1 minute (0.01667 degrees)
1. / 240., // level 8: 15 seconds (0.25 minutes)
1. / 720., // level 9: 5 seconds (0.08333 minutes)
1. / 3600., // level 10: 1 second (0.01667 minutes)
1. / 7200. // level 11: 1/2 second (0.00833 minutes)
};
double vtkGeoGraticule::LongitudeLevelTics[12] =
{
90., // level 0: 90 degrees
30., // level 1: 30 degrees
10., // level 2: 10 degrees
5., // level 3: 5 degrees
1., // level 4: 1 degree
1. / 4., // level 5: 15 minutes (0.25 degrees)
1. / 12., // level 6: 5 minutes (0.08333 degrees)
1. / 60., // level 7: 1 minute (0.01667 degrees)
1. / 240., // level 8: 15 seconds (0.25 minutes)
1. / 720., // level 9: 5 seconds (0.08333 minutes)
1. / 3600., // level 10: 1 second (0.01667 minutes)
1. / 7200. // level 11: 1/2 second (0.00833 minutes)
};
vtkGeoGraticule::vtkGeoGraticule()
{
this->SetNumberOfInputPorts( 0 );
this->LatitudeLevel = 2;
this->LongitudeLevel = 1;
this->LatitudeBounds[0] = -90.;
this->LatitudeBounds[1] = 90.;
this->LongitudeBounds[0] = 0.;
this->LongitudeBounds[1] = 180.;
this->GeometryType = vtkGeoGraticule::POLYLINES;
}
vtkGeoGraticule::~vtkGeoGraticule()
{
}
void vtkGeoGraticule::PrintSelf( ostream& os, vtkIndent indent )
{
this->Superclass::PrintSelf( os, indent );
os << indent << "GeometryType: " << this->GeometryType << "\n";
os << indent << "LatitudeLevel: " << this->LatitudeLevel << "\n";
os << indent << "LongitudeLevel: " << this->LongitudeLevel << "\n";
os << indent << "LatitudeBounds: [ " << this->LatitudeBounds[0] << ", " << this->LatitudeBounds[1] << " [\n";
os << indent << "LongitudeBounds: [ " << this->LongitudeBounds[0] << ", " << this->LongitudeBounds[1] << " [\n";
}
inline double vtkGraticuleLowerBound( double endpt, double incr )
{
return incr * floor( endpt / incr );
}
inline double vtkGraticuleUpperBound( double endpt, double incr )
{
return incr * ceil( endpt / incr );
}
int vtkGeoGraticule::RequestData( vtkInformation*, vtkInformationVector**, vtkInformationVector* outputVector )
{
if (
( this->LatitudeBounds[0] == this->LatitudeBounds[1] ) ||
( this->LongitudeBounds[0] == this->LongitudeBounds[1] ) )
{ // no work to do.
return 1;
}
vtkInformation* outInfo = outputVector->GetInformationObject( 0 );
if ( ! outInfo )
{
return 0;
}
vtkPolyData* output = vtkPolyData::SafeDownCast( outInfo->Get( vtkDataObject::DATA_OBJECT() ) );
if ( ! output )
{
return 0;
}
vtkPoints* pts = vtkPoints::New();
output->SetPoints( pts );
pts->Delete();
output->Allocate( 1000 );
// Clamp the bounds
double latbds[2];
double lngbds[2];
if ( this->LatitudeBounds[0] > this->LatitudeBounds[1] )
{
latbds[0] = this->LatitudeBounds[1];
latbds[1] = this->LatitudeBounds[0];
}
else
{
latbds[0] = this->LatitudeBounds[0];
latbds[1] = this->LatitudeBounds[1];
}
if ( this->LongitudeBounds[0] > this->LongitudeBounds[1] )
{
lngbds[0] = this->LongitudeBounds[1];
lngbds[1] = this->LongitudeBounds[0];
}
else
{
lngbds[0] = this->LongitudeBounds[0];
lngbds[1] = this->LongitudeBounds[1];
}
// Now, if the bounds don't line up on a tic, jiggle them so that they are
// on the closest mark at the current Level that is off-screen (i.e. covering
// more than the requested area).
double latTicIncrement = vtkGeoGraticule::LatitudeLevelTics[this->LatitudeLevel];
double lngTicIncrement = vtkGeoGraticule::LongitudeLevelTics[this->LongitudeLevel];
latbds[0] = vtkGraticuleLowerBound( latbds[0], latTicIncrement );
latbds[1] = vtkGraticuleUpperBound( latbds[1], latTicIncrement );
lngbds[0] = vtkGraticuleLowerBound( lngbds[0], lngTicIncrement );
lngbds[1] = vtkGraticuleUpperBound( lngbds[1], lngTicIncrement );
// Clamp to a meaningful range
if ( latbds[0] < -90. )
latbds[0] = -90.;
if ( latbds[1] > 90. )
latbds[1] = 90.;
// NB: Allow "out-of-bounds" values for longitude.
this->GenerateGraticule( output, latbds, lngbds );
return 1;
}
void vtkGeoGraticule::GenerateGraticule( vtkPolyData* output, double latbds[2], double lngbds[2] )
{
vtkPoints* pts = output->GetPoints();
vtkCellArray* edges = vtkCellArray::New();
vtkIntArray* width = vtkIntArray::New();
width->SetName( "LineLevel" );
width->SetNumberOfComponents( 1 );
vtkDoubleArray* latLong = vtkDoubleArray::New();
latLong->SetNumberOfComponents( 2 );
latLong->SetName( "LatLong" );
// Do the parallels first and record the start of each so we can do the meridians afterwards
std::vector<vtkIdType> offsets; // where each row of points starts.
double latTicIncrement = vtkGeoGraticule::LatitudeLevelTics[this->LatitudeLevel];
double lngTicIncrement = vtkGeoGraticule::LongitudeLevelTics[this->LongitudeLevel];
double pt[3] = { 0., 0., 0. };
double lat;
double lng;
vtkIdType m = 0;
vtkIdType n = -1;
vtkIdType p = 0;
for ( lat = latbds[0]; lat < latbds[1] + latTicIncrement; lat += latTicIncrement, ++ p )
{
offsets.push_back( n + 1 );
if ( this->GeometryType & vtkGeoGraticule::POLYLINES )
{
edges->InsertNextCell( 1 );
}
pt[1] = lat;
m = 0;
for ( lng = lngbds[0]; lng < lngbds[1] + lngTicIncrement; lng += lngTicIncrement, ++m )
{
pt[0] = lng;
n = pts->InsertNextPoint( pt );
latLong->InsertNextTuple2( lat, lng );
if ( this->GeometryType & vtkGeoGraticule::POLYLINES )
{
edges->InsertCellPoint( n );
}
}
if ( this->GeometryType & vtkGeoGraticule::POLYLINES )
{
edges->UpdateCellCount( m );
width->InsertNextValue( this->ComputeLineLevel( p, this->LatitudeLevel, vtkGeoGraticule::LatitudeLevelTics ) );
}
}
vtkIdType gridSize[2] = { m, p };
// Now do the meridians.
if ( this->GeometryType & vtkGeoGraticule::POLYLINES && p == static_cast<int>( offsets.size() ) )
{
int lineLevel;
int polarLatitudeLevel = this->LatitudeLevel - 2 >= 0 ? this->LatitudeLevel - 2 : 0;
int k;
p = 0;
for ( lng = lngbds[0]; lng <= lngbds[1]; lng += lngTicIncrement, ++ p )
{
n = 0;
k = 0;
lineLevel = this->ComputeLineLevel( p, this->LongitudeLevel, vtkGeoGraticule::LongitudeLevelTics );
edges->InsertNextCell( 1 );
for ( lat = latbds[0]; lat <= latbds[1]; lat += latTicIncrement, ++ n )
{
// When near the poles, include fewer meridians.
if ( fabs(lat) <= 60. || lineLevel <= polarLatitudeLevel )
{
edges->InsertCellPoint( offsets[n] );
++ k;
}
++ offsets[n];
}
edges->UpdateCellCount( k );
width->InsertNextValue( lineLevel );
}
}
output->SetLines( edges );
edges->FastDelete();
// Now create the quads to texture
if ( this->GeometryType & vtkGeoGraticule::QUADRILATERALS )
{
vtkCellArray* quads = vtkCellArray::New();
m = 0;
vtkIdType quadConn[4];
for ( p = 0; p < gridSize[1] - 1; ++ p )
{
for ( m = 0; m < gridSize[0] - 1; ++ m )
{
quadConn[0] = p * gridSize[0] + m;
quadConn[1] = p * gridSize[0] + m + 1;
quadConn[2] = ( p + 1 ) * gridSize[0] + m + 1;
quadConn[3] = ( p + 1 ) * gridSize[0] + m;
quads->InsertNextCell( 4, quadConn );
width->InsertNextValue( -1 );
}
}
output->SetPolys( quads );
quads->FastDelete();
}
output->GetCellData()->AddArray( width );
output->GetCellData()->SetActiveScalars( "LineLevel" );
width->FastDelete();
output->GetPointData()->AddArray( latLong );
//output->GetPointData()->SetActiveTCoords( "LatLong" );
latLong->FastDelete();
}
int vtkGeoGraticule::ComputeLineLevel( int ticId, int baseLevel, const double* levelIncrements )
{
for ( int curLevel = 0; curLevel < baseLevel; ++ curLevel )
{
if ( ticId % static_cast<int>( levelIncrements[curLevel] / levelIncrements[baseLevel] ) == 0 )
{
return curLevel;
}
}
return baseLevel;
}

View File

@ -0,0 +1,124 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkGeoGraticule.h
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.
-------------------------------------------------------------------------*/
// .NAME vtkGeoGraticule - Create a polygonal lat-long grid
//
// .SECTION Description
// This filter generates polydata to illustrate the distortions introduced
// by a map projection. The level parameter specifies the number of lines
// to be drawn. Poles are treated differently than other regions; hence the
// use of a Level parameter instead of a NumberOfLines parameter.
// The latitude and longitude are specified as half-open intervals with units
// of degrees. By default the latitude bounds are [-90,90[ and the longitude
// bounds are [0,180[.
#ifndef vtkGeoGraticule_h
#define vtkGeoGraticule_h
#include "vtkGeovisCoreModule.h" // For export macro
#include "vtkPolyDataAlgorithm.h"
class vtkPolyData;
class VTKGEOVISCORE_EXPORT vtkGeoGraticule : public vtkPolyDataAlgorithm
{
public:
static vtkGeoGraticule* New();
virtual void PrintSelf( ostream& os, vtkIndent indent );
vtkTypeMacro(vtkGeoGraticule,vtkPolyDataAlgorithm);
// Description:
// The latitude bounds of the graticule.
vtkSetVector2Macro(LatitudeBounds,double);
vtkGetVector2Macro(LatitudeBounds,double);
// Description:
// The longitude bounds of the graticule.
vtkSetVector2Macro(LongitudeBounds,double);
vtkGetVector2Macro(LongitudeBounds,double);
//BTX
enum LevelLimits {
LEVEL_MIN = 0,
LEVEL_MAX = 11,
NUMBER_OF_LEVELS = ( LEVEL_MAX - LEVEL_MIN + 1 )
};
//ETX
// Description:
// The frequency level of latitude lines.
vtkSetClampMacro(LatitudeLevel,int,LEVEL_MIN,LEVEL_MAX);
vtkGetMacro(LatitudeLevel,int);
// Description:
// The frequency level of longitude lines.
vtkSetClampMacro(LongitudeLevel,int,LEVEL_MIN,LEVEL_MAX);
vtkGetMacro(LongitudeLevel,int);
// Description:
// The latitude delta at a certain frequency level.
static double GetLatitudeDelta(int level)
{ return LatitudeLevelTics[level]; }
// Description:
// The longitude delta at a certain frequency level.
static double GetLongitudeDelta(int level)
{ return LongitudeLevelTics[level]; }
// Description:
// Set//get the type(s) of cells that will be
// output by the filter. By default, polylines
// are output. You may also request quadrilaterals.
// This is a bit vector of GeometryType enums.
vtkSetMacro(GeometryType,int);
vtkGetMacro(GeometryType,int);
//BTX
enum GeometryType {
POLYLINES = 0x1,
QUADRILATERALS = 0x2
};
//ETX
protected:
vtkGeoGraticule();
virtual ~vtkGeoGraticule();
int GeometryType;
double LatitudeBounds[2];
double LongitudeBounds[2];
int LatitudeLevel;
int LongitudeLevel;
// Description:
// The distance between tic marks at each level, in degrees.
static double LatitudeLevelTics[NUMBER_OF_LEVELS];
static double LongitudeLevelTics[NUMBER_OF_LEVELS];
virtual int RequestData( vtkInformation*, vtkInformationVector**, vtkInformationVector* );
void GenerateGraticule( vtkPolyData* output, double latbds[2], double lngbds[2] );
int ComputeLineLevel( int ticId, int baseLevel, const double* levelIncrements );
private:
vtkGeoGraticule( const vtkGeoGraticule& ); // Not implemented.
void operator = ( const vtkGeoGraticule& ); // Not implemented.
};
#endif // vtkGeoGraticule_h

View File

@ -0,0 +1,272 @@
/*=============================================================================
Program: Visualization Toolkit
Module: vtkGeoImageNode.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 "vtkObjectFactory.h"
#include "vtkGeoImageNode.h"
#include "vtkJPEGWriter.h"
#include "vtkTexture.h"
#include "vtkXMLImageDataReader.h"
#include "vtkXMLImageDataWriter.h"
vtkStandardNewMacro(vtkGeoImageNode);
//----------------------------------------------------------------------------
vtkGeoImageNode::vtkGeoImageNode()
{
this->Image = vtkSmartPointer<vtkImageData>::New();
this->Texture = vtkSmartPointer<vtkTexture>::New();
}
//-----------------------------------------------------------------------------
vtkGeoImageNode::~vtkGeoImageNode()
{
}
//-----------------------------------------------------------------------------
void vtkGeoImageNode::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
}
//-----------------------------------------------------------------------------
void vtkGeoImageNode::SetImage(vtkImageData* image)
{
this->Image = image;
}
//-----------------------------------------------------------------------------
vtkImageData* vtkGeoImageNode::GetImage()
{
return this->Image;
}
//-----------------------------------------------------------------------------
void vtkGeoImageNode::SetTexture(vtkTexture* texture)
{
this->Texture = texture;
}
//-----------------------------------------------------------------------------
vtkTexture* vtkGeoImageNode::GetTexture()
{
return this->Texture;
}
//-----------------------------------------------------------------------------
vtkGeoImageNode* vtkGeoImageNode::GetChild(int idx)
{
if (idx < 0 || idx > 3)
{
vtkErrorMacro("Index out of range.");
return 0;
}
return vtkGeoImageNode::SafeDownCast(this->Children[idx]);
}
//-----------------------------------------------------------------------------
vtkGeoImageNode* vtkGeoImageNode::GetParent()
{
return vtkGeoImageNode::SafeDownCast(this->Parent);
}
//-----------------------------------------------------------------------------
// We have to get a power of 2 for dimensions of the image. VTK
// resamples every time a tile is selected anr changed otherwise.
//
// We have two choises for dealing with images.
//
// 1: Treat pixels like cell data.
// This makes subsampling easy. Simply use vtkImageShrink3D.
// Tile images do not overlap.
// Difficult:
// Texture mapping is point data. TCoords have to be extended half a pixel.
// vtkImageData is point data. Have to handle meta data extenal to object.
// Interpolated texture map will have seams between tiles.
// 2: Treat pixels like point data.
// We would need a new shrink filter that uses a 3x3 kernel.
// Tiles would have to duplicate a row of xels with neighbors.
// This would make dividing image more difficult with natural pixel boundaries
// every 255 pixels (instead of 256).
void vtkGeoImageNode::CropImageForTile(
vtkImageData* image,
double* imageLonLatExt,
const char* prefix)
{
int ext[6];
int wholeExt[6];
// I am keeping this all external to the imageData object because
// I consider pixels are cells not points.
image->GetExtent(ext);
image->GetExtent(wholeExt);
double origin[2];
double spacing[2];
spacing[0] = (imageLonLatExt[1]-imageLonLatExt[0])/(ext[1]-ext[0]+1);
spacing[1] = (imageLonLatExt[3]-imageLonLatExt[2])/(ext[3]-ext[2]+1);
origin[0] = imageLonLatExt[0] - ext[0]*spacing[0];
origin[1] = imageLonLatExt[2] - ext[2]*spacing[1];
// Compute the minimum extent that covers the terrain patch.
ext[0] = static_cast<int>(floor((this->LongitudeRange[0]-origin[0])/spacing[0]));
ext[1] = static_cast<int>(ceil((this->LongitudeRange[1]-origin[0])/spacing[0]));
ext[2] = static_cast<int>(floor((this->LatitudeRange[0]-origin[1])/spacing[1]));
ext[3] = static_cast<int>(ceil((this->LatitudeRange[1]-origin[1])/spacing[1]));
int dims[2];
dims[0] = this->PowerOfTwo(ext[1]-ext[0]+1);
dims[1] = this->PowerOfTwo(ext[3]-ext[2]+1);
ext[1] = ext[0] + dims[0] - 1;
ext[3] = ext[2] + dims[1] - 1;
if (ext[1] > wholeExt[1])
{
ext[1] = wholeExt[1];
}
if (ext[3] > wholeExt[3])
{
ext[3] = wholeExt[3];
}
ext[0] = ext[1] - dims[0] + 1;
ext[2] = ext[3] - dims[1] + 1;
if (ext[0] < wholeExt[0])
{
ext[0] = wholeExt[0];
}
if (ext[2] < wholeExt[2])
{
ext[2] = wholeExt[2];
}
if (this->Image == 0)
{
this->Image = vtkSmartPointer<vtkImageData>::New();
}
this->Image->ShallowCopy(image);
this->Image->Crop(ext);
// Now set the longitude and latitude range based on the actual image size.
this->LongitudeRange[0] = origin[0] + ext[0]*spacing[0];
this->LongitudeRange[1] = origin[0] + (ext[1]+1)*spacing[0];
this->LatitudeRange[0] = origin[1] + ext[2]*spacing[1];
this->LatitudeRange[1] = origin[1] + (ext[3]+1)*spacing[1];
// Save out the image to verify we are processing properly
if (prefix)
{
vtkImageData* storedImage = vtkImageData::New();
storedImage->ShallowCopy(this->Image);
storedImage->SetOrigin(this->LongitudeRange[0], this->LatitudeRange[0], 0);
storedImage->SetSpacing(this->LongitudeRange[1], this->LatitudeRange[1], 0);
vtkXMLImageDataWriter* writer = vtkXMLImageDataWriter::New();
char fn[512];
sprintf(fn, "%s/tile_%d_%ld.vti", prefix, this->Level, this->Id);
writer->SetFileName(fn);
writer->SetInputData(storedImage);
writer->Write();
writer->Delete();
storedImage->Delete();
}
}
//-----------------------------------------------------------------------------
void vtkGeoImageNode::LoadAnImage(const char* prefix)
{
vtkXMLImageDataReader* reader = vtkXMLImageDataReader::New();
char fn[512];
sprintf(fn, "%s/tile_%d_%ld.vti", prefix, this->Level, this->Id);
reader->SetFileName(fn);
reader->Update();
vtkImageData* image = reader->GetOutput();
this->Image = image;
this->LongitudeRange[0] = this->Image->GetOrigin()[0];
this->LatitudeRange[0] = this->Image->GetOrigin()[1];
this->LongitudeRange[1] = this->Image->GetSpacing()[0];
this->LatitudeRange[1] = this->Image->GetSpacing()[1];
reader->Delete();
}
//-----------------------------------------------------------------------------
int vtkGeoImageNode::PowerOfTwo(int val)
{
// Pick the next highest power of two.
int tmp;
bool nextHigherFlag = false;
tmp = 1;
while (val)
{
if ((val & 1) && val > 1)
{
nextHigherFlag = true;
}
val = val >> 1;
tmp = tmp << 1;
}
if ( ! nextHigherFlag)
{
tmp = tmp >> 1;
}
return tmp;
}
//-----------------------------------------------------------------------------
void vtkGeoImageNode::ShallowCopy(vtkGeoTreeNode *src)
{
vtkGeoImageNode *imageNode = vtkGeoImageNode::SafeDownCast(src);
if(imageNode != NULL)
{
this->Image = imageNode->Image;
this->Texture = imageNode->Texture;
}
this->Superclass::ShallowCopy(src);
}
//-----------------------------------------------------------------------------
void vtkGeoImageNode::DeepCopy(vtkGeoTreeNode *src)
{
vtkGeoImageNode *imageNode = vtkGeoImageNode::SafeDownCast(src);
if(imageNode != NULL)
{
vtkImageData * image = vtkImageData::New();
image->DeepCopy(imageNode->Image);
this->SetImage(image);
image->Delete();
image = NULL;
this->Texture = imageNode->Texture;
}
this->Superclass::DeepCopy(src);
}
//-----------------------------------------------------------------------------
bool vtkGeoImageNode::HasData()
{
return (this->Image != 0);
}
//-----------------------------------------------------------------------------
void vtkGeoImageNode::DeleteData()
{
this->Image = 0;
this->Texture = 0;
}

View File

@ -0,0 +1,106 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkGeoImageNode.h
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.
-------------------------------------------------------------------------*/
// .NAME vtkGeoImageNode - A node in a multi-resolution image tree.
//
// .SECTION Description
// vtkGeoImageNode contains an image tile in a multi-resolution image tree,
// along with metadata about that image's extents.
//
// .SECTION See Also
// vtkGeoTreeNode vtkGeoTerrainNode
#ifndef vtkGeoImageNode_h
#define vtkGeoImageNode_h
#include "vtkGeovisCoreModule.h" // For export macro
#include "vtkGeoTreeNode.h"
#include "vtkSmartPointer.h" // for SP
#include "vtkImageData.h" // for SP
class vtkPolyData;
class vtkTexture;
class VTKGEOVISCORE_EXPORT vtkGeoImageNode : public vtkGeoTreeNode
{
public:
static vtkGeoImageNode *New();
vtkTypeMacro(vtkGeoImageNode, vtkGeoTreeNode);
void PrintSelf(ostream& os, vtkIndent indent);
// Description:
// Every subclass implements these methods returning the specific type.
// This is easier than templating.
vtkGeoImageNode* GetChild(int idx);
vtkGeoImageNode* GetParent();
// Description:
// Get the image tile.
vtkImageData* GetImage();
void SetImage(vtkImageData* image);
// Description:
// Get the image tile.
vtkTexture* GetTexture();
void SetTexture(vtkTexture* texture);
// Description:
// This crops the image as small as possible while still covering the
// patch. The Longitude Latitude range may get bigger to reflect the
// actual size of the image.
// If prefix is specified, writes the tile to that location.
void CropImageForTile(vtkImageData* image,double* imageLonLatExt,
const char* prefix = 0);
// Description:
// This loads the image from a tile database at the specified location.
void LoadAnImage(const char* prefix);
// Description:
// Shallow and Deep copy.
virtual void ShallowCopy(vtkGeoTreeNode *src);
virtual void DeepCopy(vtkGeoTreeNode *src);
// Returns whether this node has valid data associated
// with it, or if it is an "empty" node.
virtual bool HasData();
// Description:
// Deletes the data associated with the node to make this
// an "empty" node. This is performed when the node has
// been unused for a certain amount of time.
virtual void DeleteData();
protected:
vtkGeoImageNode();
~vtkGeoImageNode();
int PowerOfTwo(int val);
//BTX
vtkSmartPointer<vtkImageData> Image;
vtkSmartPointer<vtkTexture> Texture;
//ETX
private:
vtkGeoImageNode(const vtkGeoImageNode&); // Not implemented.
void operator=(const vtkGeoImageNode&); // Not implemented.
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,161 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkGeoInteractorStyle.h
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.
-------------------------------------------------------------------------*/
// .NAME vtkGeoInteractorStyle - Interaction for a globe
//
// .SECTION Description
// vtkGeoInteractorStyle contains interaction capabilities for a geographic
// view including orbit, zoom, and tilt. It also includes a compass widget
// for changing view parameters.
//
// .SECTION See Also
// vtkCompassWidget vtkInteractorStyle
#ifndef vtkGeoInteractorStyle_h
#define vtkGeoInteractorStyle_h
#include "vtkGeovisCoreModule.h" // For export macro
#include "vtkInteractorStyleTrackballCamera.h"
#include "vtkSmartPointer.h" // for SP
class vtkCamera;
class vtkCommand;
class vtkCompassWidget;
class vtkGeoCamera;
class vtkUnsignedCharArray;
class VTKGEOVISCORE_EXPORT vtkGeoInteractorStyle :
public vtkInteractorStyleTrackballCamera
{
public:
static vtkGeoInteractorStyle *New();
vtkTypeMacro(vtkGeoInteractorStyle,
vtkInteractorStyleTrackballCamera);
void PrintSelf(ostream& os, vtkIndent indent);
// Description:
// Event bindings
virtual void OnEnter();
virtual void OnLeave();
virtual void OnMouseMove();
virtual void OnLeftButtonUp();
virtual void OnMiddleButtonUp();
virtual void OnRightButtonUp();
virtual void OnLeftButtonDown();
virtual void OnMiddleButtonDown();
virtual void OnRightButtonDown();
virtual void OnChar();
virtual void RubberBandZoom();
virtual void Pan();
virtual void Dolly();
// Public for render callback.
void RedrawRectangle();
// See cxx for description of why we need this method.
void StartState(int newstate);
// Used for updating the terrain.
vtkGeoCamera* GetGeoCamera();
// Description:
// This can be used to set the camera to the standard view of the earth.
void ResetCamera();
//! Called when the sub widgets have an interaction
void WidgetInteraction(vtkObject *caller);
// Description:
// Set/Get the Interactor wrapper being controlled by this object.
// (Satisfy superclass API.)
virtual void SetInteractor(vtkRenderWindowInteractor *interactor);
int ViewportToWorld(double x, double y,
double &wx, double &wy, double &wz);
void WorldToLongLat(double wx, double wy, double wz,
double &lon, double &lat);
void ViewportToLongLat(double x, double y,
double &lon, double &lat);
int GetRayIntersection(double origin[3],
double direction[3],
double intersection[3]);
// Description:
// Override to make the renderer use this camera subclass
virtual void SetCurrentRenderer(vtkRenderer*);
// Description:
// Whether to lock the heading a particular value during pan.
vtkGetMacro(LockHeading, bool);
vtkSetMacro(LockHeading, bool);
vtkBooleanMacro(LockHeading, bool);
// Description:
// Called after camera properties are modified
void ResetCameraClippingRange();
protected:
vtkGeoInteractorStyle();
~vtkGeoInteractorStyle();
// To avoid a warning.
// We should really inherit directy from vtkInteractorStyle
virtual void Dolly(double);
void OnTimer();
// Used to get a constant speed regardless of frame rate.
double LastTime;
// Rubberband zoom has a verification stage.
int RubberBandExtent[4];
int RubberBandExtentEnabled;
int RenderCallbackTag;
void EnableRubberBandRedraw();
void DisableRubberBandRedraw();
bool InRubberBandRectangle(int x, int y);
void DrawRectangle();
void KeepCameraAboveGround(vtkCamera* camera);
void UpdateLights();
void GetPanCenter(double &px, double &py);
int StartPosition[2];
int EndPosition[2];
int DraggingRubberBandBoxState;
double MotionFactor;
vtkUnsignedCharArray *PixelArray;
int PixelDims[2];
bool LockHeading;
//BTX
vtkSmartPointer<vtkGeoCamera> GeoCamera;
// widget handling members
vtkSmartPointer<vtkCompassWidget> CompassWidget;
vtkSmartPointer<vtkCommand> EventCommand;
//ETX
private:
vtkGeoInteractorStyle(const vtkGeoInteractorStyle&); // Not implemented.
void operator=(const vtkGeoInteractorStyle&); // Not implemented.
};
#endif

View File

@ -0,0 +1,268 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkGeoProjection.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 "vtkGeoProjection.h"
#include "vtkObjectFactory.h"
#include <sstream>
#include <string>
#include <map>
#include <vector>
#include "vtk_libproj4.h"
vtkStandardNewMacro(vtkGeoProjection);
static int vtkGeoProjectionNumProj = -1;
//-----------------------------------------------------------------------------
class vtkGeoProjection::vtkInternals
{
public:
const char* GetKeyAt(int index)
{
if (static_cast<int>(this->OptionalParameters.size()) > index)
{
std::map< std::string, std::string >::iterator iter =
this->OptionalParameters.begin();
int nbIter = index;
while(nbIter > 0)
{
nbIter--;
iter++;
}
return iter->first.c_str();
}
return NULL;
}
const char* GetValueAt(int index)
{
if (static_cast<int>(this->OptionalParameters.size()) > index)
{
std::map< std::string, std::string >::iterator iter =
this->OptionalParameters.begin();
int nbIter = index;
while(nbIter > 0)
{
nbIter--;
iter++;
}
return iter->second.c_str();
}
return NULL;
}
std::map< std::string, std::string > OptionalParameters;
};
//-----------------------------------------------------------------------------
int vtkGeoProjection::GetNumberOfProjections()
{
if ( vtkGeoProjectionNumProj < 0 )
{
vtkGeoProjectionNumProj = 0;
for ( const PROJ_LIST* pj = proj_list; pj && pj->id; ++ pj )
++ vtkGeoProjectionNumProj;
}
return vtkGeoProjectionNumProj;
}
//-----------------------------------------------------------------------------
const char* vtkGeoProjection::GetProjectionName( int projection )
{
if ( projection < 0 || projection >= vtkGeoProjection::GetNumberOfProjections() )
return 0;
return proj_list[projection].id;
}
//-----------------------------------------------------------------------------
const char* vtkGeoProjection::GetProjectionDescription( int projection )
{
if ( projection < 0 || projection >= vtkGeoProjection::GetNumberOfProjections() )
return 0;
return proj_list[projection].descr[0];
}
//-----------------------------------------------------------------------------
vtkGeoProjection::vtkGeoProjection()
{
this->Name = 0;
this->SetName( "latlong" );
this->CentralMeridian = 0.;
this->Projection = 0;
this->Internals = new vtkInternals();
}
//-----------------------------------------------------------------------------
vtkGeoProjection::~vtkGeoProjection()
{
this->SetName( 0 );
if ( this->Projection )
{
proj_free( this->Projection );
}
delete this->Internals;
this->Internals = NULL;
}
//-----------------------------------------------------------------------------
void vtkGeoProjection::PrintSelf( ostream& os, vtkIndent indent )
{
this->Superclass::PrintSelf( os, indent );
os << indent << "Name: " << this->Name << "\n";
os << indent << "CentralMeridian: " << this->CentralMeridian << "\n";
os << indent << "Projection: " << this->Projection << "\n";
os << indent << "Optional parameters:\n";
for(int i=0;i<this->GetNumberOfOptionalParameters();i++)
{
os << indent << " - " << this->GetOptionalParameterKey(i) << " = "
<< this->GetOptionalParameterValue(i) << "\n";
}
}
//-----------------------------------------------------------------------------
int vtkGeoProjection::GetIndex()
{
this->UpdateProjection();
if ( ! this->Projection )
return -1;
int i = 0;
for ( const PROJ_LIST* proj = proj_list; proj && proj->id; ++ proj, ++ i )
{
if ( ! strcmp( proj->id, this->Name ) )
{
return i;
}
}
return -1;
}
//-----------------------------------------------------------------------------
const char* vtkGeoProjection::GetDescription()
{
this->UpdateProjection();
if ( ! this->Projection )
{
return 0;
}
return this->Projection->descr;
}
//-----------------------------------------------------------------------------
PROJ* vtkGeoProjection::GetProjection()
{
this->UpdateProjection();
return this->Projection;
}
//-----------------------------------------------------------------------------
int vtkGeoProjection::UpdateProjection()
{
if ( this->GetMTime() <= this->ProjectionMTime )
{
return 0;
}
if ( this->Projection )
{
proj_free( this->Projection );
this->Projection = 0;
}
if ( ! this->Name || ! strlen( this->Name ) )
{
return 1;
}
if ( ! strcmp ( this->Name, "latlong" ) )
{
// latlong is "null" projection.
return 1;
}
int argSize = 3 + this->GetNumberOfOptionalParameters();
const char** pjArgs = new const char*[argSize];
std::string projSpec( "+proj=" );
projSpec += this->Name;
std::string ellpsSpec( "+ellps=clrk66" );
std::string meridSpec;
std::ostringstream os;
os << "+lon_0=" << this->CentralMeridian;
meridSpec = os.str();
pjArgs[0] = projSpec.c_str();
pjArgs[1] = ellpsSpec.c_str();
pjArgs[2] = meridSpec.c_str();
// Add optional parameters
std::vector<std::string> stringHolder; // Keep string ref in memory
for(int i=0; i < this->GetNumberOfOptionalParameters(); i++)
{
std::ostringstream param;
param << "+" << this->GetOptionalParameterKey(i);
param << "=" << this->GetOptionalParameterValue(i);
stringHolder.push_back(param.str());
pjArgs[3+i] = stringHolder[i].c_str();
}
this->Projection = proj_init( argSize, const_cast<char**>( pjArgs ) );
delete[] pjArgs;
if ( this->Projection )
{
return 1;
}
return 0;
}
//-----------------------------------------------------------------------------
void vtkGeoProjection::SetOptionalParameter(const char* key, const char* value)
{
if(key != NULL && value != NULL)
{
this->Internals->OptionalParameters[key] = value;
}
else
{
vtkErrorMacro("Invalid Optional Parameter Key/Value pair. None can be NULL");
}
this->UpdateProjection();
}
//-----------------------------------------------------------------------------
void vtkGeoProjection::RemoveOptionalParameter(const char* key)
{
this->Internals->OptionalParameters.erase(key);
this->UpdateProjection();
}
//-----------------------------------------------------------------------------
int vtkGeoProjection::GetNumberOfOptionalParameters()
{
return static_cast<int>(this->Internals->OptionalParameters.size());
}
//-----------------------------------------------------------------------------
const char* vtkGeoProjection::GetOptionalParameterKey(int index)
{
return this->Internals->GetKeyAt(index);
}
//-----------------------------------------------------------------------------
const char* vtkGeoProjection::GetOptionalParameterValue(int index)
{
return this->Internals->GetValueAt(index);
}
//-----------------------------------------------------------------------------
void vtkGeoProjection::ClearOptionalParameters()
{
this->Internals->OptionalParameters.clear();
this->UpdateProjection();
}

View File

@ -0,0 +1,139 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkGeoProjection.h
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.
-------------------------------------------------------------------------*/
// .NAME vtkGeoProjection - Represent a projection from a sphere to a plane
//
// .SECTION Description
// This class uses the PROJ.4 library to represent geographic coordinate
// projections.
#ifndef vtkGeoProjection_h
#define vtkGeoProjection_h
#include "vtkGeovisCoreModule.h" // For export macro
#include "vtkObject.h"
struct PROJconsts;
typedef PROJconsts PROJ;
class VTKGEOVISCORE_EXPORT vtkGeoProjection : public vtkObject
{
public:
static vtkGeoProjection* New();
virtual void PrintSelf( ostream& os, vtkIndent indent );
vtkTypeMacro(vtkGeoProjection,vtkObject);
// Description:
// Returns the number of projections that this class offers.
static int GetNumberOfProjections();
// Description:
// Returns the name of one of the projections supported by this class.
// You can pass these strings to SetName(char*).
// @param projection the index of a projection, must be in [0,GetNumberOfProjections()[.
static const char* GetProjectionName( int projection );
// Description:
// Returns a description of one of the projections supported by this class.
// @param projection the index of a projection, must be in [0,GetNumberOfProjections()[.
static const char* GetProjectionDescription( int projection );
// Description:
// Set/get the short name describing the projection you wish to use.
// This defaults to "rpoly" for no reason other than I like it.
// To get a list of valid values, use the GetNumberOfProjections() and
// GetProjectionName(int) static methods.
vtkSetStringMacro(Name);
vtkGetStringMacro(Name);
// Description:
// Return the index of the current projection's type in the list of all projection types.
// On error, this will return -1. On success, it returns a number in [0,GetNumberOfProjections()[.
int GetIndex();
// Description:
// Get the description of a projection.
// This will return NULL if the projection name is invalid.
const char* GetDescription();
// Description:
// Set/get the longitude which corresponds to the central meridian of the projection.
// This defaults to 0, the Greenwich Meridian.
vtkSetMacro(CentralMeridian,double);
vtkGetMacro(CentralMeridian,double);
// Description:
// Return a pointer to the PROJ.4 data structure describing this projection.
// This may return NULL if an invalid projection name or parameter set is specified.
// If you invoke any methods on this vtkGeoProjection object, the PROJ.4 structure
// this method returns may be freed, so you should not use the PROJ.4 structure
// after changing any parameters. Also, you should not modify the PROJ.4 structure
// on your own as it will then be out of sync with the vtkGeoProjection class.
PROJ* GetProjection();
// Description:
// Add an optional parameter to the projection that will be computed or
// replace it if already present.
void SetOptionalParameter(const char* key, const char* value);
// Description:
// Remove an optional parameter to the projection that will be computed
void RemoveOptionalParameter(const char*);
// Description:
// Return the number of optional parameters
int GetNumberOfOptionalParameters();
// Description:
// Return the number of optional parameters
const char* GetOptionalParameterKey(int index);
// Description:
// Return the number of optional parameters
const char* GetOptionalParameterValue(int index);
// Description:
// Clear all optional parameters
void ClearOptionalParameters();
protected:
vtkGeoProjection();
virtual ~vtkGeoProjection();
// Description:
// Determine whether the current projection structure has any
// changes pending and apply them if necessary.
// Upon success, 0 is returned.
// When an error occurs, a nonzero value is returned.
virtual int UpdateProjection();
char* Name;
double CentralMeridian;
PROJ* Projection;
vtkTimeStamp ProjectionMTime;
private:
vtkGeoProjection( const vtkGeoProjection& ); // Not implemented.
void operator = ( const vtkGeoProjection& ); // Not implemented.
class vtkInternals;
vtkInternals* Internals;
};
#endif // vtkGeoProjection_h

View File

@ -0,0 +1,491 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkGeoProjectionSource.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 "vtkGeoProjectionSource.h"
#include "vtkActor.h"
#include "vtkBox.h"
#include "vtkCellArray.h"
#include "vtkClipPolyData.h"
#include "vtkDoubleArray.h"
#include "vtkGeoGraticule.h"
#include "vtkGeoProjection.h"
#include "vtkGeoTerrainNode.h"
#include "vtkGeoTransform.h"
#include "vtkImageData.h"
#include "vtkMath.h"
#include "vtkMutexLock.h"
#include "vtkObjectFactory.h"
#include "vtkPlane.h"
#include "vtkPlanes.h"
#include "vtkPointData.h"
#include "vtkPolyData.h"
#include "vtkPolyDataMapper.h"
#include "vtkPropCollection.h"
#include "vtkProperty.h"
#include "vtkRenderer.h"
#include "vtkSmartPointer.h"
#include "vtkTransform.h"
#include "vtkTransformFilter.h"
#include <stack>
#include <utility>
// Heap dump method used for debugging threading issues on windows.
//void heapdump( void )
// {
// _HEAPINFO hinfo;
// int heapstatus;
// hinfo._pentry = NULL;
// while( ( heapstatus = _heapwalk( &hinfo ) ) == _HEAPOK )
// {
// //printf( "%6s block at %Fp of size %4.4X\n", ( hinfo._useflag == _USEDENTRY ? "USED" : "FREE" ), hinfo._pentry, hinfo._size );
// }
//
// switch( heapstatus )
// {
// case _HEAPEMPTY:
// //printf( "OK - empty heap\n" );
// break;
// case _HEAPEND:
// //printf( "OK - end of heap\n" );
// break;
// case _HEAPBADPTR:
// printf( "ERROR - bad pointer to heap\n" );
// //throw("asdf");
// break;
// case _HEAPBADBEGIN:
// printf( "ERROR - bad start of heap\n" );
// //throw("asdf");
// break;
// case _HEAPBADNODE:
// printf( "ERROR - bad node in heap\n" );
// //throw("asdf");
// break;
// }
// }
vtkStandardNewMacro(vtkGeoProjectionSource);
vtkCxxSetObjectMacro(vtkGeoProjectionSource, Transform, vtkAbstractTransform);
//----------------------------------------------------------------------------
vtkGeoProjectionSource::vtkGeoProjectionSource()
{
this->Projection=0;
this->Transform = 0;
this->MinCellsPerNode = 20;
this->TransformLock = vtkMutexLock::New();
}
//----------------------------------------------------------------------------
vtkGeoProjectionSource::~vtkGeoProjectionSource()
{
this->TransformLock->Delete();
this->SetTransform(0);
}
void vtkGeoProjectionSource::PrintSelf( ostream& os, vtkIndent indent )
{
this->Superclass::PrintSelf( os, indent );
os << indent << "Projection: " << this->Projection << "\n";
os << indent << "Transform: " << this->Transform << "\n";
os << indent << "MinCellsPerNode: " << this->MinCellsPerNode << "\n";
}
//----------------------------------------------------------------------------
void vtkGeoProjectionSource::RefineAndComputeError(vtkGeoTerrainNode* node)
{
double* latRange = node->GetLatitudeRange();
double* lonRange = node->GetLongitudeRange();
int level = node->GetGraticuleLevel();
double latDelta = vtkGeoGraticule::GetLatitudeDelta(level);
double lonDelta = vtkGeoGraticule::GetLongitudeDelta(level);
while ((latRange[1] - latRange[0])*(lonRange[1] - lonRange[0])/(latDelta*lonDelta) < this->MinCellsPerNode)
{
++level;
latDelta = vtkGeoGraticule::GetLatitudeDelta(level);
lonDelta = vtkGeoGraticule::GetLongitudeDelta(level);
}
vtkSmartPointer<vtkGeoGraticule> grat = vtkSmartPointer<vtkGeoGraticule>::New();
vtkSmartPointer<vtkGeoGraticule> refinedGrat = vtkSmartPointer<vtkGeoGraticule>::New();
vtkSmartPointer<vtkTransformFilter> transformFilter = vtkSmartPointer<vtkTransformFilter>::New();
vtkSmartPointer<vtkGeoTransform> trans = vtkSmartPointer<vtkGeoTransform>::New();
vtkSmartPointer<vtkGeoProjection> proj = vtkSmartPointer<vtkGeoProjection>::New();
proj->SetName(vtkGeoProjection::GetProjectionName(this->Projection));
trans->SetDestinationProjection(proj);
transformFilter->SetTransform(trans);
grat->SetGeometryType(vtkGeoGraticule::QUADRILATERALS);
grat->SetLatitudeBounds(latRange);
grat->SetLongitudeBounds(lonRange);
refinedGrat->SetGeometryType(vtkGeoGraticule::QUADRILATERALS);
vtkSmartPointer<vtkPolyData> geom = vtkSmartPointer<vtkPolyData>::New();
vtkSmartPointer<vtkPolyData> refined = vtkSmartPointer<vtkPolyData>::New();
do
{
grat->SetLatitudeLevel(level);
grat->SetLongitudeLevel(level);
transformFilter->SetInputConnection(grat->GetOutputPort());
transformFilter->Update();
geom->DeepCopy(transformFilter->GetOutput());
refinedGrat->SetLatitudeLevel(level+1);
refinedGrat->SetLongitudeLevel(level+1);
double* curLatRange = geom->GetPointData()->GetArray("LatLong")->GetRange(0);
refinedGrat->SetLatitudeBounds(curLatRange);
double* curLonRange = geom->GetPointData()->GetArray("LatLong")->GetRange(1);
refinedGrat->SetLongitudeBounds(curLonRange);
transformFilter->SetInputConnection(refinedGrat->GetOutputPort());
transformFilter->Update();
refined->DeepCopy(transformFilter->GetOutput());
++level;
} while (geom->GetNumberOfCells() < this->MinCellsPerNode &&
level < vtkGeoGraticule::NUMBER_OF_LEVELS);
node->SetGraticuleLevel(level);
// Compute grid size
vtkDataArray* latLonArr = geom->GetPointData()->GetArray("LatLong");
double firstLon = latLonArr->GetComponent(0, 1);
vtkIdType gridSize[2] = {1, 0};
while (latLonArr->GetComponent(gridSize[0], 1) != firstLon)
{
gridSize[0]++;
}
gridSize[1] = geom->GetNumberOfPoints() / gridSize[0];
// Compute refined grid size
latLonArr = refined->GetPointData()->GetArray("LatLong");
firstLon = latLonArr->GetComponent(0, 1);
vtkIdType rgridSize[2] = {1, 0};
while (latLonArr->GetComponent(rgridSize[0], 1) != firstLon)
{
rgridSize[0]++;
}
rgridSize[1] = refined->GetNumberOfPoints() / rgridSize[0];
// Calculate error.
double error = 0.0;
double pt00[3];
double pt01[3];
double pt11[3];
double pt10[3];
double latFrac;
double lonFrac;
double curPt[3];
double interpPt[3];
double interpLon0;
double interpLon1;
double curError;
vtkIdType skip = (rgridSize[0]-1) / (gridSize[0]-1);
for (vtkIdType latInd = 0; latInd < rgridSize[1]-skip; ++latInd)
{
for (vtkIdType lonInd = 0; lonInd < rgridSize[0]-skip; ++lonInd)
{
vtkIdType ind00 = latInd * rgridSize[0] + lonInd;
vtkIdType ind01 = latInd * rgridSize[0] + lonInd + skip;
vtkIdType ind11 = ( latInd + skip ) * rgridSize[0] + lonInd + skip;
vtkIdType ind10 = ( latInd + skip ) * rgridSize[0] + lonInd;
refined->GetPoint(ind00, pt00);
refined->GetPoint(ind01, pt01);
refined->GetPoint(ind11, pt11);
refined->GetPoint(ind10, pt10);
for (vtkIdType rlatInd = latInd + 1; rlatInd < latInd + skip; ++rlatInd)
{
latFrac = static_cast<double>(rlatInd - latInd) / skip;
for (vtkIdType rlonInd = lonInd + 1; rlonInd < lonInd + skip; ++rlonInd)
{
lonFrac = static_cast<double>(rlonInd - lonInd) / skip;
refined->GetPoint(rlatInd * rgridSize[0] + rlonInd, curPt);
for (int c = 0; c < 3; ++c)
{
interpLon0 = (1.0 - lonFrac)*pt00[c] + lonFrac*pt01[c];
interpLon1 = (1.0 - lonFrac)*pt10[c] + lonFrac*pt11[c];
interpPt[c] = (1.0 - latFrac)*interpLon0 + latFrac*interpLon1;
}
curError = vtkMath::Distance2BetweenPoints(curPt, interpPt);
if (curError > error)
{
error = curError;
}
}
}
}
}
node->GetModel()->DeepCopy(geom);
node->SetError(sqrt(error));
}
//----------------------------------------------------------------------------
bool vtkGeoProjectionSource::FetchRoot(vtkGeoTreeNode* r)
{
this->TransformLock->Lock();
vtkGeoTerrainNode* root = 0;
if (!(root = vtkGeoTerrainNode::SafeDownCast(r)))
{
vtkErrorMacro(<< "Can only fetch surface nodes from this source.");
return false;
}
// Let's start with graticule level 2 ... why not?
root->SetGraticuleLevel(2);
vtkSmartPointer<vtkGeoGraticule> grat = vtkSmartPointer<vtkGeoGraticule>::New();
grat->SetLatitudeLevel(root->GetGraticuleLevel());
grat->SetLongitudeLevel(root->GetGraticuleLevel());
grat->SetLongitudeBounds(-180.0, 180.0);
grat->SetLatitudeBounds(-90.0, 90.0);
grat->SetGeometryType(vtkGeoGraticule::QUADRILATERALS);
vtkSmartPointer<vtkTransformFilter> transformFilter = vtkSmartPointer<vtkTransformFilter>::New();
vtkSmartPointer<vtkGeoTransform> trans = vtkSmartPointer<vtkGeoTransform>::New();
vtkSmartPointer<vtkGeoProjection> proj = vtkSmartPointer<vtkGeoProjection>::New();
proj->SetName(vtkGeoProjection::GetProjectionName(this->Projection));
trans->SetDestinationProjection(proj);
transformFilter->SetTransform(trans);
transformFilter->SetInputConnection(grat->GetOutputPort());
transformFilter->Update();
double* realBounds = transformFilter->GetOutput()->GetBounds();
// Extend the bounds just a tad to be safe
double bounds[4];
bounds[0] = realBounds[0] - (realBounds[1] - realBounds[0])*0.01;
bounds[1] = realBounds[1] + (realBounds[1] - realBounds[0])*0.01;
bounds[2] = realBounds[2] - (realBounds[3] - realBounds[2])*0.01;
bounds[3] = realBounds[3] + (realBounds[3] - realBounds[2])*0.01;
// Make the bounds square
if (bounds[1] - bounds[0] > bounds[3] - bounds[2])
{
double size = bounds[1] - bounds[0];
double center = (bounds[2] + bounds[3])/2.0;
bounds[2] = center - size/2.0;
bounds[3] = center + size/2.0;
}
else
{
double size = bounds[3] - bounds[2];
double center = (bounds[0] + bounds[1])/2.0;
bounds[0] = center - size/2.0;
bounds[1] = center + size/2.0;
}
root->GetModel()->DeepCopy(transformFilter->GetOutput());
root->SetLatitudeRange(-90.0, 90.0);
root->SetLongitudeRange(-180.0, 180.0);
root->SetProjectionBounds(bounds);
root->SetLevel(0);
this->RefineAndComputeError(root);
// Make sure bounds are up to date so we don't have threading issues
// when we hand this off to the main thread.
root->GetModel()->ComputeBounds();
this->TransformLock->Unlock();
return true;
}
//----------------------------------------------------------------------------
bool vtkGeoProjectionSource::FetchChild(vtkGeoTreeNode* p, int index, vtkGeoTreeNode* c)
{
this->TransformLock->Lock();
vtkGeoTerrainNode* parent = 0;
if (!(parent = vtkGeoTerrainNode::SafeDownCast(p)))
{
vtkErrorMacro(<< "Can only fetch surface nodes from this source.");
return false;
}
vtkGeoTerrainNode* child = 0;
if (!(child = vtkGeoTerrainNode::SafeDownCast(c)))
{
vtkErrorMacro(<< "Can only fetch surface nodes from this source.");
return false;
}
if (!parent->HasData())
{
return false;
}
// Clip the cells of the children
double bounds[4];
parent->GetProjectionBounds(bounds);
double center[3] = {
(bounds[1] + bounds[0])/2.0,
(bounds[3] + bounds[2])/2.0, 0.0};
vtkSmartPointer<vtkClipPolyData> lonClip = vtkSmartPointer<vtkClipPolyData>::New();
vtkSmartPointer<vtkPlane> lonClipPlane = vtkSmartPointer<vtkPlane>::New();
lonClipPlane->SetOrigin(center);
lonClipPlane->SetNormal(-1.0, 0.0, 0.0);
lonClip->SetClipFunction(lonClipPlane);
lonClip->GenerateClippedOutputOn();
lonClip->SetInputData(parent->GetModel());
vtkSmartPointer<vtkPlane> latClipPlane = vtkSmartPointer<vtkPlane>::New();
latClipPlane->SetOrigin(center);
latClipPlane->SetNormal(0.0, -1.0, 0.0);
vtkSmartPointer<vtkClipPolyData> latClip = vtkSmartPointer<vtkClipPolyData>::New();
latClip->SetClipFunction(latClipPlane);
latClip->GenerateClippedOutputOn();
if (index % 2)
{
latClip->SetInputConnection(lonClip->GetOutputPort(1));
bounds[0] = center[0];
}
else
{
latClip->SetInputConnection(lonClip->GetOutputPort(0));
bounds[1] = center[0];
}
latClip->Update();
if (index / 2)
{
child->GetModel()->DeepCopy(latClip->GetOutput(1));
bounds[2] = center[1];
}
else
{
child->GetModel()->DeepCopy(latClip->GetOutput(0));
bounds[3] = center[1];
}
int level = parent->GetLevel() + 1;
child->SetLevel(level);
child->SetProjectionBounds(bounds);
// Set the id
if (level <= 15)
{
int id = parent->GetId() | (index << (level*2 - 2));
child->SetId(id);
}
double* latRange = 0;
double* lonRange = 0;
if (child->GetModel()->GetNumberOfPoints() > 0)
{
latRange = child->GetModel()->GetPointData()->GetArray("LatLong")->GetRange(0);
latRange[0] = (latRange[0] < -90) ? -90 : latRange[0];
latRange[1] = (latRange[1] > 90) ? 90 : latRange[1];
child->SetLatitudeRange(latRange);
lonRange = child->GetModel()->GetPointData()->GetArray("LatLong")->GetRange(1);
lonRange[0] = (lonRange[0] < -180) ? -180 : lonRange[0];
lonRange[1] = (lonRange[1] > 180) ? 180 : lonRange[1];
child->SetLongitudeRange(lonRange);
}
else
{
child->SetLatitudeRange(0.0, 0.0);
child->SetLongitudeRange(0.0, 0.0);
this->TransformLock->Unlock();
return true;
}
// Start with at least graticule level 2.
child->SetGraticuleLevel(2);
// Refine the node using vtkGeoGraticule and compute the error of the node.
this->RefineAndComputeError(child);
// We need to do four planar clips to get the desired result.
// Using vtkBox or vtkPlanes produces a fuzzy clip that is not acceptable.
for (int i = 0; i < 4; ++i)
{
vtkSmartPointer<vtkClipPolyData> finalClip = vtkSmartPointer<vtkClipPolyData>::New();
vtkSmartPointer<vtkPlane> plane = vtkSmartPointer<vtkPlane>::New();
if (i == 0)
{
plane->SetOrigin(bounds[0], 0.0, 0.0);
plane->SetNormal(1.0, 0.0, 0.0);
}
else if (i == 1)
{
plane->SetOrigin(bounds[1], 0.0, 0.0);
plane->SetNormal(-1.0, 0.0, 0.0);
}
else if (i == 2)
{
plane->SetOrigin(0.0, bounds[2], 0.0);
plane->SetNormal(0.0, 1.0, 0.0);
}
else if (i == 3)
{
plane->SetOrigin(0.0, bounds[3], 0.0);
plane->SetNormal(0.0, -1.0, 0.0);
}
finalClip->SetClipFunction(plane);
vtkSmartPointer<vtkPolyData> pd = vtkSmartPointer<vtkPolyData>::New();
pd->DeepCopy(child->GetModel());
finalClip->SetInputData(pd);
finalClip->Update();
child->GetModel()->DeepCopy(finalClip->GetOutput());
}
// The lat/long range could have changed
if (child->GetModel()->GetNumberOfPoints() > 0)
{
latRange = child->GetModel()->GetPointData()->GetArray("LatLong")->GetRange(0);
latRange[0] = (latRange[0] < -90) ? -90 : latRange[0];
latRange[1] = (latRange[1] > 90) ? 90 : latRange[1];
child->SetLatitudeRange(latRange);
lonRange = child->GetModel()->GetPointData()->GetArray("LatLong")->GetRange(1);
lonRange[0] = (lonRange[0] < -180) ? -180 : lonRange[0];
lonRange[1] = (lonRange[1] > 180) ? 180 : lonRange[1];
child->SetLongitudeRange(lonRange);
}
else
{
child->SetLatitudeRange(0.0, 0.0);
child->SetLongitudeRange(0.0, 0.0);
}
// Make sure bounds are up to date so we don't have threading issues
// when we hand this off to the main thread.
child->GetModel()->ComputeBounds();
this->TransformLock->Unlock();
return true;
}
//----------------------------------------------------------------------------
void vtkGeoProjectionSource::SetProjection(int projection)
{
this->Projection = projection;
vtkSmartPointer<vtkGeoTransform> trans = vtkSmartPointer<vtkGeoTransform>::New();
vtkSmartPointer<vtkGeoProjection> proj = vtkSmartPointer<vtkGeoProjection>::New();
proj->SetName(vtkGeoProjection::GetProjectionName(projection));
trans->SetDestinationProjection(proj);
this->SetTransform(trans.GetPointer());
}
//----------------------------------------------------------------------------
vtkAbstractTransform* vtkGeoProjectionSource::GetTransform()
{
return this->Transform;
}

View File

@ -0,0 +1,81 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkGeoProjectionSource.h
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.
-------------------------------------------------------------------------*/
// .NAME vtkGeoProjectionSource - A 2D geographic geometry source
//
// .SECTION Description
// vtkGeoProjectionSource is a vtkGeoSource suitable for use in vtkTerrain2D.
// This source uses the libproj4 library to produce geometry patches at
// multiple resolutions. Each patch covers a specific region in projected
// space.
#ifndef vtkGeoProjectionSource_h
#define vtkGeoProjectionSource_h
#include "vtkGeovisCoreModule.h" // For export macro
#include "vtkGeoSource.h"
class vtkAbstractTransform;
class vtkGeoTerrainNode;
class vtkMutexLock;
class VTKGEOVISCORE_EXPORT vtkGeoProjectionSource : public vtkGeoSource
{
public:
static vtkGeoProjectionSource *New();
vtkTypeMacro(vtkGeoProjectionSource,vtkGeoSource);
virtual void PrintSelf( ostream& os, vtkIndent indent );
vtkGeoProjectionSource();
~vtkGeoProjectionSource();
// Description:
// Blocking methods for sources with low latency.
virtual bool FetchRoot(vtkGeoTreeNode* root);
virtual bool FetchChild(vtkGeoTreeNode* node, int index, vtkGeoTreeNode* child);
// Description:
// The projection ID defining the projection. Initial value is 0.
vtkGetMacro(Projection, int);
virtual void SetProjection(int projection);
// Description:
// The minimum number of cells per node.
vtkGetMacro(MinCellsPerNode, int);
vtkSetMacro(MinCellsPerNode, int);
// Description:
// Return the projection transformation used by this 2D terrain.
virtual vtkAbstractTransform* GetTransform();
protected:
void RefineAndComputeError(vtkGeoTerrainNode* node);
int Projection;
int MinCellsPerNode;
virtual void SetTransform(vtkAbstractTransform* transform);
vtkMutexLock* TransformLock;
vtkAbstractTransform* Transform;
private:
vtkGeoProjectionSource(const vtkGeoProjectionSource&); // Not implemented
void operator=(const vtkGeoProjectionSource&); // Not implemented
};
#endif

View File

@ -0,0 +1,83 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkGeoRandomGraphSource.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 "vtkGeoRandomGraphSource.h"
#include "vtkDataSetAttributes.h"
#include "vtkDoubleArray.h"
#include "vtkGraph.h"
#include "vtkInformation.h"
#include "vtkMath.h"
#include "vtkObjectFactory.h"
#include "vtkPoints.h"
vtkStandardNewMacro(vtkGeoRandomGraphSource);
// ----------------------------------------------------------------------
vtkGeoRandomGraphSource::vtkGeoRandomGraphSource()
{
}
// ----------------------------------------------------------------------
vtkGeoRandomGraphSource::~vtkGeoRandomGraphSource()
{
}
// ----------------------------------------------------------------------
void vtkGeoRandomGraphSource::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
}
// ----------------------------------------------------------------------
int vtkGeoRandomGraphSource::RequestData(
vtkInformation* info,
vtkInformationVector** inputVector,
vtkInformationVector* outputVector)
{
vtkRandomGraphSource::RequestData(info, inputVector, outputVector);
// Set random lat/long points into the output
vtkGraph* output = vtkGraph::GetData(outputVector);
vtkDoubleArray* latArr = vtkDoubleArray::New();
vtkDoubleArray* lonArr = vtkDoubleArray::New();
latArr->SetNumberOfTuples(output->GetNumberOfVertices());
lonArr->SetNumberOfTuples(output->GetNumberOfVertices());
latArr->SetName("latitude");
lonArr->SetName("longitude");
for (vtkIdType v = 0; v < output->GetNumberOfVertices(); ++v)
{
double lat = vtkMath::Random()*180.0 - 90.0;
double lon = vtkMath::Random()*360.0 - 180.0;
latArr->SetValue(v, lat);
lonArr->SetValue(v, lon);
}
output->GetVertexData()->AddArray(latArr);
output->GetVertexData()->AddArray(lonArr);
latArr->Delete();
lonArr->Delete();
return 1;
}

View File

@ -0,0 +1,65 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkGeoRandomGraphSource.h
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.
-------------------------------------------------------------------------*/
// .NAME vtkGeoRandomGraphSource - A geospatial graph with random edges
//
// .SECTION Description
// Generates a graph with a specified number of vertices, with the density of
// edges specified by either an exact number of edges or the probability of
// an edge. You may additionally specify whether to begin with a random
// tree (which enforces graph connectivity).
//
// The filter also adds random vertex attributes called latitude and longitude.
// The latitude is distributed uniformly from -90 to 90, while longitude is
// distributed uniformly from -180 to 180.
//
// .SECTION See Also
// vtkRandomGraphSource
#ifndef vtkGeoRandomGraphSource_h
#define vtkGeoRandomGraphSource_h
#include "vtkGeovisCoreModule.h" // For export macro
#include "vtkRandomGraphSource.h"
class vtkGraph;
class VTKGEOVISCORE_EXPORT vtkGeoRandomGraphSource : public vtkRandomGraphSource
{
public:
static vtkGeoRandomGraphSource* New();
vtkTypeMacro(vtkGeoRandomGraphSource,vtkRandomGraphSource);
void PrintSelf(ostream& os, vtkIndent indent);
protected:
vtkGeoRandomGraphSource();
~vtkGeoRandomGraphSource();
virtual int RequestData(
vtkInformation*,
vtkInformationVector**,
vtkInformationVector*);
private:
vtkGeoRandomGraphSource(const vtkGeoRandomGraphSource&); // Not implemented
void operator=(const vtkGeoRandomGraphSource&); // Not implemented
};
#endif

View File

@ -0,0 +1,187 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkGeoSampleArcs.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 "vtkGeoSampleArcs.h"
#include "vtkCamera.h"
#include "vtkCellArray.h"
#include "vtkCellData.h"
#include "vtkCoordinate.h"
#include "vtkDoubleArray.h"
#include "vtkFloatArray.h"
#include "vtkGeoMath.h"
#include "vtkGlobeSource.h"
#include "vtkMath.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkRenderWindow.h"
#include "vtkRendererCollection.h"
#include "vtkTimerLog.h"
vtkStandardNewMacro(vtkGeoSampleArcs);
vtkGeoSampleArcs::vtkGeoSampleArcs()
{
this->GlobeRadius = vtkGeoMath::EarthRadiusMeters();
this->MaximumDistanceMeters = 100000.0;
this->InputCoordinateSystem = RECTANGULAR;
this->OutputCoordinateSystem = RECTANGULAR;
}
vtkGeoSampleArcs::~vtkGeoSampleArcs()
{
}
int vtkGeoSampleArcs::RequestData(
vtkInformation *vtkNotUsed(request),
vtkInformationVector **inputVector,
vtkInformationVector *outputVector)
{
// get the info objects
vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
vtkInformation *outInfo = outputVector->GetInformationObject(0);
// get the input and output
vtkPolyData *input = vtkPolyData::SafeDownCast(
inInfo->Get(vtkDataObject::DATA_OBJECT()));
vtkPolyData *output = vtkPolyData::SafeDownCast(
outInfo->Get(vtkDataObject::DATA_OBJECT()));
// Traverse input lines, adding a circle for each line segment.
vtkCellArray* lines = input->GetLines();
vtkPoints* points = input->GetPoints();
if ( !points )
{
return 0;
}
vtkCellArray* newLines = vtkCellArray::New();
float* pointsPtr = static_cast<float*>(points->GetVoidPointer(0));
vtkPoints* newPoints = vtkPoints::New();
lines->InitTraversal();
for (vtkIdType i = 0; i < lines->GetNumberOfCells(); i++)
{
vtkIdType npts=0; // to remove warning
vtkIdType* pts=0; // to remove warning
lines->GetNextCell(npts, pts);
double lastPoint[3];
double curPoint[3];
double lastPtLL[2];
double curPtLL[2];
if (this->InputCoordinateSystem == RECTANGULAR)
{
curPoint[0] = pointsPtr[3*pts[0]+0];
curPoint[1] = pointsPtr[3*pts[0]+1];
curPoint[2] = pointsPtr[3*pts[0]+2];
vtkGlobeSource::ComputeLatitudeLongitude(
curPoint, curPtLL[0], curPtLL[1]);
}
else // SPHERICAL
{
curPtLL[0] = pointsPtr[3*pts[0]+0];
curPtLL[1] = pointsPtr[3*pts[0]+1];
vtkGlobeSource::ComputeGlobePoint(
curPtLL[0], curPtLL[1], this->GlobeRadius, curPoint);
}
for (vtkIdType p = 1; p < npts; ++p)
{
// Advance point
for (int c = 0; c < 3; ++c)
{
lastPoint[c] = curPoint[c];
}
lastPtLL[0] = curPtLL[0];
lastPtLL[1] = curPtLL[1];
if (this->InputCoordinateSystem == RECTANGULAR)
{
curPoint[0] = pointsPtr[3*pts[p]+0];
curPoint[1] = pointsPtr[3*pts[p]+1];
curPoint[2] = pointsPtr[3*pts[p]+2];
vtkGlobeSource::ComputeLatitudeLongitude(
curPoint, curPtLL[0], curPtLL[1]);
}
else // SPHERICAL
{
curPtLL[0] = pointsPtr[3*pts[p]+0];
curPtLL[1] = pointsPtr[3*pts[p]+1];
vtkGlobeSource::ComputeGlobePoint(
curPtLL[0], curPtLL[1], this->GlobeRadius, curPoint);
}
double dist = sqrt(vtkMath::Distance2BetweenPoints(lastPoint, curPoint));
// Calculate the number of subdivisions.
vtkIdType numDivisions = static_cast<vtkIdType>(dist / this->MaximumDistanceMeters + 0.5) + 1;
if (numDivisions < 2)
{
numDivisions = 2;
}
// Create the new cell
newLines->InsertNextCell(numDivisions);
for (vtkIdType s = 0; s < numDivisions; ++s)
{
// Interpolate in lat-long.
double interpPtLL[2];
double frac = static_cast<double>(s) / (numDivisions - 1);
for (int c = 0; c < 2; ++c)
{
interpPtLL[c] = frac*curPtLL[c] + (1.0 - frac)*lastPtLL[c];
}
if (this->OutputCoordinateSystem == RECTANGULAR)
{
// Convert lat-long to world;
double interpPt[3];
vtkGlobeSource::ComputeGlobePoint(interpPtLL[0], interpPtLL[1], this->GlobeRadius, interpPt);
vtkIdType newPt = newPoints->InsertNextPoint(interpPt);
newLines->InsertCellPoint(newPt);
}
else // SPHERICAL
{
vtkIdType newPt = newPoints->InsertNextPoint(interpPtLL[0], interpPtLL[1], 0.0);
newLines->InsertCellPoint(newPt);
}
}
}
}
// Send the data to output.
output->SetLines(newLines);
output->SetPoints(newPoints);
// Clean up.
newLines->Delete();
newPoints->Delete();
return 1;
}
void vtkGeoSampleArcs::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
os << indent << "GlobeRadius: " << this->GlobeRadius << endl;
os << indent << "MaximumDistanceMeters: " << this->MaximumDistanceMeters << endl;
os << indent << "InputCoordinateSystem: " << this->InputCoordinateSystem << endl;
os << indent << "OutputCoordinateSystem: " << this->OutputCoordinateSystem << endl;
}

View File

@ -0,0 +1,103 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkGeoSampleArcs.h
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.
-------------------------------------------------------------------------*/
// .NAME vtkGeoSampleArcs - Samples geospatial lines at regular intervals.
//
// .SECTION Description
// vtkGeoSampleArcs refines lines in the input polygonal data
// so that the distance between adjacent points is no more than a threshold
// distance. Points are interpolated along the surface of the globe.
// This is useful in order to keep lines such as political boundaries from
// intersecting the globe and becoming invisible.
#ifndef vtkGeoSampleArcs_h
#define vtkGeoSampleArcs_h
#include "vtkGeovisCoreModule.h" // For export macro
#include "vtkPolyDataAlgorithm.h"
class VTKGEOVISCORE_EXPORT vtkGeoSampleArcs : public vtkPolyDataAlgorithm
{
public:
static vtkGeoSampleArcs *New();
vtkTypeMacro(vtkGeoSampleArcs,vtkPolyDataAlgorithm);
void PrintSelf(ostream& os, vtkIndent indent);
// Description:
// The base radius used to determine the earth's surface.
// Default is the earth's radius in meters.
// TODO: Change this to take in a vtkGeoTerrain to get altitude.
vtkSetMacro(GlobeRadius, double);
vtkGetMacro(GlobeRadius, double);
// Description:
// The maximum distance, in meters, between adjacent points.
vtkSetMacro(MaximumDistanceMeters, double);
vtkGetMacro(MaximumDistanceMeters, double);
//BTX
enum
{
RECTANGULAR,
SPHERICAL
};
//ETX
// Description:
// The input coordinate system.
// RECTANGULAR is x,y,z meters relative the the earth center.
// SPHERICAL is longitude,latitude,altitude.
vtkSetMacro(InputCoordinateSystem, int);
vtkGetMacro(InputCoordinateSystem, int);
virtual void SetInputCoordinateSystemToRectangular()
{ this->SetInputCoordinateSystem(RECTANGULAR); }
virtual void SetInputCoordinateSystemToSpherical()
{ this->SetInputCoordinateSystem(SPHERICAL); }
// Description:
// The desired output coordinate system.
// RECTANGULAR is x,y,z meters relative the the earth center.
// SPHERICAL is longitude,latitude,altitude.
vtkSetMacro(OutputCoordinateSystem, int);
vtkGetMacro(OutputCoordinateSystem, int);
virtual void SetOutputCoordinateSystemToRectangular()
{ this->SetOutputCoordinateSystem(RECTANGULAR); }
virtual void SetOutputCoordinateSystemToSpherical()
{ this->SetOutputCoordinateSystem(SPHERICAL); }
protected:
vtkGeoSampleArcs();
~vtkGeoSampleArcs();
// Description:
// Convert the vtkGraph into vtkPolyData.
int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *);
double GlobeRadius;
double MaximumDistanceMeters;
int InputCoordinateSystem;
int OutputCoordinateSystem;
private:
vtkGeoSampleArcs(const vtkGeoSampleArcs&); // Not implemented.
void operator=(const vtkGeoSampleArcs&); // Not implemented.
};
#endif

View File

@ -0,0 +1,250 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkGeoSource.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 "vtkGeoSource.h"
#include "vtkCollection.h"
#include "vtkConditionVariable.h"
#include "vtkDataObject.h"
#include "vtkGeoImageNode.h"
#include "vtkGeoTerrainNode.h"
#include "vtkMultiThreader.h"
#include "vtkMutexLock.h"
#include "vtkObjectFactory.h"
#include "vtkSmartPointer.h"
#include "vtkTimerLog.h"
#include <map>
#include <utility>
#include <vector>
static VTK_THREAD_RETURN_TYPE vtkGeoSourceThreadStart(void* arg)
{
vtkGeoSource* self;
self = static_cast<vtkGeoSource *>(static_cast<vtkMultiThreader::ThreadInfo *>(arg)->UserData);
self->WorkerThread();
return VTK_THREAD_RETURN_VALUE;
}
class vtkGeoSource::implementation {
public:
std::map<std::pair<unsigned long, int>, vtkSmartPointer<vtkCollection> > OutputMap;
std::vector<int> ThreadIds;
};
vtkGeoSource::vtkGeoSource()
{
this->InputSet = vtkCollection::New();
this->InputSetLock = vtkMutexLock::New();
this->ProcessingSet = vtkCollection::New();
this->ProcessingSetLock = vtkMutexLock::New();
this->OutputSetLock = vtkMutexLock::New();
this->Lock = vtkMutexLock::New();
this->Condition = vtkConditionVariable::New();
this->StopThread = false;
this->Initialized = false;
this->Implementation = new implementation();
this->Threader = vtkMultiThreader::New();
}
vtkGeoSource::~vtkGeoSource()
{
this->ShutDown();
this->InputSet->Delete();
this->ProcessingSet->Delete();
this->Threader->Delete();
delete this->Implementation;
this->InputSetLock->Delete();
this->ProcessingSetLock->Delete();
this->OutputSetLock->Delete();
this->Condition->Delete();
this->Lock->Delete();
}
void vtkGeoSource::Initialize(int numThreads)
{
if(this->Initialized)
{
return;
}
int maxThreads = this->Threader->GetGlobalDefaultNumberOfThreads();
maxThreads = numThreads < maxThreads ? numThreads : maxThreads;
for(int i = 0; i < maxThreads; ++i)
{
this->Implementation->ThreadIds.push_back(
this->Threader->SpawnThread(vtkGeoSourceThreadStart, this));
}
this->Initialized = true;
}
void vtkGeoSource::ShutDown()
{
if (this->Implementation->ThreadIds.size() > 0)
{
this->Lock->Lock();
this->StopThread = true;
this->Condition->Broadcast();
this->Lock->Unlock();
std::vector<int>::iterator iter;
for(iter = this->Implementation->ThreadIds.begin();
iter != this->Implementation->ThreadIds.end();
++iter)
{
this->Threader->TerminateThread(*iter);
}
this->Implementation->ThreadIds.clear();
this->Implementation->OutputMap.clear();
}
this->Initialized = false;
}
vtkCollection* vtkGeoSource::GetRequestedNodes(vtkGeoTreeNode* node)
{
vtkCollection* c = 0;
this->OutputSetLock->Lock();
std::pair<unsigned long, int> p(node->GetId(), node->GetLevel());
if (this->Implementation->OutputMap.count(p) > 0)
{
c = this->Implementation->OutputMap[p];
if (c)
{
c->Register(0);
this->Implementation->OutputMap[p] = 0;
}
}
this->OutputSetLock->Unlock();
return c;
}
void vtkGeoSource::RequestChildren(vtkGeoTreeNode* node)
{
if(!this->Initialized)
{
vtkErrorMacro("Call Initialize() first in order to spawn worker threads.");
return;
}
this->InputSetLock->Lock();
this->InputSet->AddItem(node);
// Reference Count is 2 at this point. Decrease so that
// we can delete this copy of the node from the worker
// thread.
node->UnRegister(this);
this->Condition->Broadcast();
this->InputSetLock->Unlock();
}
void vtkGeoSource::WorkerThread()
{
bool isTerrainNode = false;
while (true)
{
this->Lock->Lock();
if (this->StopThread)
{
this->Lock->Unlock();
return;
}
this->Lock->Unlock();
this->InputSetLock->Lock();
// Try to find something to work on.
if (this->InputSet->GetNumberOfItems() > 0)
{
// Move from input set to processing set
vtkGeoTreeNode* node = vtkGeoTreeNode::SafeDownCast(this->InputSet->GetItemAsObject(0));
node->Register(this);
this->InputSet->RemoveItem(0);
this->InputSetLock->Unlock();
// Create appropriate child instances
vtkGeoTreeNode* child[4];
isTerrainNode = vtkGeoTerrainNode::SafeDownCast(node) != NULL ? true : false;
if (isTerrainNode)
{
for (int i = 0; i < 4; ++i)
{
child[i] = vtkGeoTerrainNode::New();
}
}
else
{
for (int i = 0; i < 4; ++i)
{
child[i] = vtkGeoImageNode::New();
}
}
// Fetch the children
bool success = true;
for (int i = 0; i < 4; ++i)
{
if (!this->FetchChild(node, i, child[i]))
{
success = false;
break;
}
}
// Move from processing set to output
this->OutputSetLock->Lock();
std::pair<unsigned long, int> p(node->GetId(), node->GetLevel());
this->Implementation->OutputMap[p] =
vtkSmartPointer<vtkCollection>::New();
if (success)
{
for (int i = 0; i < 4; ++i)
{
this->Implementation->OutputMap[p]->AddItem(child[i]);
}
}
this->OutputSetLock->Unlock();
node->Delete();
node = NULL;
for (int i = 0; i < 4; ++i)
{
child[i]->Delete();
}
}
else
{
this->InputSetLock->Unlock();
this->Lock->Lock();
// No Work, so lets wait till we're signaled again.
this->Condition->Wait( this->Lock );
this->Lock->Unlock();
}
}
}

View File

@ -0,0 +1,118 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkGeoSource.h
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.
-------------------------------------------------------------------------*/
// .NAME vtkGeoSource - A multi-resolution geographic data source
//
// .SECTION Description
// vtkGeoSource is an abstract superclass for all multi-resolution data sources
// shown in a geographic view like vtkGeoView or vtkGeoView2D. vtkGeoSource
// subclasses need to implement the FetchRoot() method, which fills a
// vtkGeoTreeNode with the low-res data at the root, and FetchChild(), which
// produces a refinement of a parent node. Other geovis classes such as
// vtkGeoTerrain, vtkGeoTerrain2D, and vtkGeoAlignedImageSource use a
// vtkGeoSource subclass to build their geometry or image caches which are
// stored in trees. The source itself does not maintain the tree, but
// simply provides a mechanism for generating refined tree nodes.
//
// Sources are multi-threaded. Each source may have one or more worker threads
// associated with it, which this superclass manages. It is essential that the
// FetchChild() method is thread-safe, since it may be called from multiple
// workers simultaneously.
#ifndef vtkGeoSource_h
#define vtkGeoSource_h
#include "vtkGeovisCoreModule.h" // For export macro
#include "vtkObject.h"
class vtkAbstractTransform;
class vtkCollection;
class vtkConditionVariable;
class vtkGeoTreeNode;
class vtkMultiThreader;
class vtkMutexLock;
class VTKGEOVISCORE_EXPORT vtkGeoSource : public vtkObject
{
public:
vtkTypeMacro(vtkGeoSource,vtkObject);
vtkGeoSource();
~vtkGeoSource();
// Description:
// Blocking access methods to be implemented in subclasses.
virtual bool FetchRoot(vtkGeoTreeNode* root) = 0;
virtual bool FetchChild(vtkGeoTreeNode* node, int index, vtkGeoTreeNode* child) = 0;
// Description:
// Non-blocking methods for to use from the main application.
// After calling RequestChildren() for a certain node,
// GetRequestedNodes() will after a certain period of time return a
// non-null pointer to a collection of four vtkGeoTreeNode objects,
// which are the four children of the requested node.
// The collection is reference counted, so you need to eventually
// call Delete() on the returned collection pointer (if it is non-null).
virtual void RequestChildren(vtkGeoTreeNode* node);
virtual vtkCollection* GetRequestedNodes(vtkGeoTreeNode* node);
// Description:
// Spawn worker threads.
void Initialize(int numThreads = 1);
// Description:
// Shut down the source. This terminates the thread and releases memory.
void ShutDown();
void WorkerThread();
// Description:
// Return the projection transformation used by this source.
virtual vtkAbstractTransform* GetTransform() { return NULL; }
protected:
vtkCollection* InputSet;
vtkCollection* ProcessingSet;
// Description:
// Locks the set for reading or writing
vtkMutexLock* InputSetLock;
vtkMutexLock* ProcessingSetLock;
vtkMutexLock* OutputSetLock;
vtkMutexLock* Lock;
vtkConditionVariable* Condition;
vtkMultiThreader* Threader;
bool StopThread;
bool Initialized;
//BTX
class implementation;
implementation* Implementation;
//ETX
private:
vtkGeoSource(const vtkGeoSource&); // Not implemented
void operator=(const vtkGeoSource&); // Not implemented
};
#endif // vtkGeoSource_h

View File

@ -0,0 +1,114 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkGeoSphereTransform.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 "vtkGeoSphereTransform.h"
#include "vtkDoubleArray.h"
#include "vtkGeoMath.h"
#include "vtkGlobeSource.h"
#include "vtkMath.h"
#include "vtkObjectFactory.h"
#include "vtkPoints.h"
vtkStandardNewMacro(vtkGeoSphereTransform);
vtkGeoSphereTransform::vtkGeoSphereTransform()
{
this->ToRectangular = true;
this->BaseAltitude = 0.0;
}
vtkGeoSphereTransform::~vtkGeoSphereTransform()
{
}
void vtkGeoSphereTransform::PrintSelf( ostream& os, vtkIndent indent )
{
this->Superclass::PrintSelf(os, indent);
os << indent << "ToRectangular: " << this->ToRectangular << endl;
os << indent << "BaseAltitude: " << this->BaseAltitude << endl;
}
void vtkGeoSphereTransform::Inverse()
{
this->ToRectangular = !this->ToRectangular;
this->Modified();
}
void vtkGeoSphereTransform::InternalTransformPoint( const float in[3], float out[3] )
{
double ind[3];
double oud[3];
int i;
for ( i = 0; i < 3; ++ i )
ind[i] = in[i];
this->InternalTransformPoint( ind, oud );
for ( i = 0; i < 3; ++ i )
out[i] = static_cast<float>(oud[i]);
}
void vtkGeoSphereTransform::InternalTransformPoint( const double in[3], double out[3] )
{
if ( this->ToRectangular )
{
vtkGlobeSource::ComputeGlobePoint(
in[0], in[1], vtkGeoMath::EarthRadiusMeters() + in[2] + this->BaseAltitude, out);
}
else
{
vtkGlobeSource::ComputeLatitudeLongitude(const_cast<double*>(in), out[0], out[1]);
out[2] = vtkMath::Norm(in) - vtkGeoMath::EarthRadiusMeters() - this->BaseAltitude;
}
}
void vtkGeoSphereTransform::InternalTransformDerivative( const float in[3], float out[3], float derivative[3][3] )
{
double ind[3];
double oud[3];
double drd[3][3];
int i;
for ( i = 0; i < 3; ++ i )
ind[i] = in[i];
this->InternalTransformDerivative( ind, oud, drd );
for ( i = 0; i < 3; ++ i )
{
out[i] = static_cast<float>(oud[i]);
for ( int j = 0; j < 3; ++ j )
{
derivative[i][j] = drd[i][j];
}
}
}
void vtkGeoSphereTransform::InternalTransformDerivative( const double in[3], double out[3], double derivative[3][3] )
{
// FIXME: Compute derivatives here
(void) in;
(void) out;
(void) derivative;
}
vtkAbstractTransform* vtkGeoSphereTransform::MakeTransform()
{
vtkGeoSphereTransform* geoTrans = vtkGeoSphereTransform::New();
return geoTrans;
}

View File

@ -0,0 +1,92 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkGeoSphereTransform.h
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.
-------------------------------------------------------------------------*/
// .NAME vtkGeoSphereTransform - A transformation between long-lat-alt and rect coords
// .SECTION Description
// the cartesian coordinate system is the following (if BaseAltitude is 0),
// - the origin is at the center of the earth
// - the x axis goes from the origin to (longtitude=-90,latitude=0), intersection of equator and the meridian passing just east of Galapagos Islands
// - the y axis goes from the origin to the intersection of Greenwitch meridian and equator (longitude=0,latitude=0)
// - the z axis goes from the origin to the Geographic North Pole (latitude=90)
// - therefore the frame is right-handed.
#ifndef vtkGeoSphereTransform_h
#define vtkGeoSphereTransform_h
#include "vtkGeovisCoreModule.h" // For export macro
#include "vtkAbstractTransform.h"
class vtkGeoProjection;
class VTKGEOVISCORE_EXPORT vtkGeoSphereTransform : public vtkAbstractTransform
{
public:
static vtkGeoSphereTransform* New();
virtual void PrintSelf( ostream& os, vtkIndent indent );
vtkTypeMacro(vtkGeoSphereTransform,vtkAbstractTransform);
// Description:
// Invert the transformation.
virtual void Inverse();
// Description:
// This will calculate the transformation without calling Update.
// Meant for use only within other VTK classes.
virtual void InternalTransformPoint( const float in[3], float out[3] );
virtual void InternalTransformPoint( const double in[3], double out[3] );
// Description:
// This will transform a point and, at the same time, calculate a
// 3x3 Jacobian matrix that provides the partial derivatives of the
// transformation at that point. This method does not call Update.
// Meant for use only within other VTK classes.
virtual void InternalTransformDerivative( const float in[3], float out[3], float derivative[3][3] );
virtual void InternalTransformDerivative( const double in[3], double out[3], double derivative[3][3] );
// Description:
// Make another transform of the same type.
virtual vtkAbstractTransform* MakeTransform();
// Description:
// If on, this transform converts (long,lat,alt) triples to (x,y,z) as an offset
// from the center of the earth. Alt, x, y, and z are all be in meters.
// If off, the transform works in the reverse direction.
// Initial value is on.
vtkSetMacro(ToRectangular, bool);
vtkGetMacro(ToRectangular, bool);
vtkBooleanMacro(ToRectangular, bool);
// Description:
// The base altitude to transform coordinates to. This can be useful for transforming
// lines just above the earth's surface. Default is 0.
vtkSetMacro(BaseAltitude, double);
vtkGetMacro(BaseAltitude, double);
protected:
vtkGeoSphereTransform();
virtual ~vtkGeoSphereTransform();
bool ToRectangular;
double BaseAltitude;
private:
vtkGeoSphereTransform( const vtkGeoSphereTransform& ); // Not implemented.
void operator = ( const vtkGeoSphereTransform& ); // Not implemented.
};
#endif // vtkGeoSphereTransform_h

View File

@ -0,0 +1,555 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkGeoTerrain.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 "vtkGeoTerrain.h"
#include "vtkActor.h"
#include "vtkAssembly.h"
#include "vtkBox.h"
#include "vtkCamera.h"
#include "vtkCellArray.h"
#include "vtkClipPolyData.h"
#include "vtkCollection.h"
#include "vtkDoubleArray.h"
#include "vtkExtractSelectedFrustum.h"
#include "vtkGeoAlignedImageRepresentation.h"
#include "vtkGeoCamera.h"
#include "vtkGeoImageNode.h"
#include "vtkGeoInteractorStyle.h"
#include "vtkGeoTreeNodeCache.h"
#include "vtkGeoSource.h"
#include "vtkGeoTerrainNode.h"
#include "vtkImageData.h"
#include "vtkMath.h"
#include "vtkObjectFactory.h"
#include "vtkPlane.h"
#include "vtkPlanes.h"
#include "vtkPointData.h"
#include "vtkPolyData.h"
#include "vtkPolyDataMapper.h"
#include "vtkProp3DCollection.h"
#include "vtkProperty.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkSmartPointer.h"
#include "vtkTimerLog.h"
#include "vtkTransformFilter.h"
#include "vtkXMLPolyDataWriter.h"
#include <stack>
#include <utility>
vtkStandardNewMacro(vtkGeoTerrain);
vtkCxxSetObjectMacro(vtkGeoTerrain, GeoSource, vtkGeoSource);
vtkCxxSetObjectMacro(vtkGeoTerrain, GeoCamera, vtkGeoCamera);
//----------------------------------------------------------------------------
vtkGeoTerrain::vtkGeoTerrain()
{
this->GeoSource = 0;
this->Root = vtkGeoTerrainNode::New();
this->Origin[0] = 0.0;
this->Origin[1] = 0.0;
this->Origin[2] = 0.0;
this->Extractor = vtkExtractSelectedFrustum::New();
this->GeoCamera = 0;
this->MaxLevel = 20;
this->Cache = vtkGeoTreeNodeCache::New();
}
//----------------------------------------------------------------------------
vtkGeoTerrain::~vtkGeoTerrain()
{
this->SetGeoSource(0);
this->SetGeoCamera(0);
if (this->Root)
{
this->Root->Delete();
}
if (this->Extractor)
{
this->Extractor->Delete();
}
if (this->Cache)
{
this->Cache->Delete();
}
}
//----------------------------------------------------------------------------
void vtkGeoTerrain::SetSource(vtkGeoSource* source)
{
if (this->GeoSource != source)
{
this->SetGeoSource(source);
if (this->GeoSource)
{
this->Initialize();
}
}
}
//----------------------------------------------------------------------------
void vtkGeoTerrain::Initialize()
{
if (!this->GeoSource)
{
vtkErrorMacro(<< "Must set source before initializing.");
return;
}
// Start by fetching the root.
this->GeoSource->FetchRoot(this->Root);
}
//----------------------------------------------------------------------------
void vtkGeoTerrain::InitializeNodeAnalysis(vtkRenderer* ren)
{
vtkGeoInteractorStyle* style = vtkGeoInteractorStyle::SafeDownCast(
ren->GetRenderWindow()->GetInteractor()->GetInteractorStyle());
if (!style)
{
vtkErrorMacro("vtkGeoTerrain requires vtkGeoInteractorStyle in order to get geo camera.");
return;
}
vtkGeoCamera* camera = style->GetGeoCamera();
int* rendererSize = ren->GetSize();
camera->InitializeNodeAnalysis(rendererSize);
this->SetGeoCamera(camera);
// Setup the frustum extractor for finding
// node intersections with the view frustum.
double frustumPlanes[24];
double aspect = ren->GetTiledAspectRatio();
camera->GetVTKCamera()->GetFrustumPlanes( aspect, frustumPlanes );
vtkSmartPointer<vtkPlanes> frustum = vtkSmartPointer<vtkPlanes>::New();
frustum->SetFrustumPlanes(frustumPlanes);
this->Extractor->SetFrustum(frustum);
}
//----------------------------------------------------------------------------
bool vtkGeoTerrain::NodeInViewport(vtkGeoTerrainNode* cur)
{
// Determine if node is within viewport
double bbox[6];
cur->GetModel()->GetBounds(bbox);
for (int i = 0; i < 6; ++i)
{
bbox[i] = bbox[i] - this->GeoCamera->GetOrigin()[i/2];
}
int boundsTest = this->Extractor->OverallBoundsTest(bbox);
return (boundsTest != 0);
}
//-----------------------------------------------------------------------------
// Returns 0 if there should be no change, -1 if the node resolution is too
// high, and +1 if the nodes resolution is too low.
int vtkGeoTerrain::EvaluateNode(vtkGeoTerrainNode* node)
{
double sphereViewSize;
if (!this->GeoCamera)
{
return 0;
}
// Size of the sphere in view area units (0 -> 1)
sphereViewSize = this->GeoCamera->GetNodeCoverage(node);
// Arbitrary thresholds
if (sphereViewSize > 0.2)
{
return 1;
}
if (sphereViewSize < 0.05)
{
return -1;
}
// Do not change the node.
return 0;
}
//----------------------------------------------------------------------------
void vtkGeoTerrain::AddActors(
vtkRenderer* ren,
vtkAssembly* assembly,
vtkCollection* imageReps)
{
// This method requires that the render window graphics context
// has been created.
ren->GetRenderWindow()->MakeCurrent();
if (!ren->GetRenderWindow()->IsCurrent())
{
return;
}
this->InitializeNodeAnalysis(ren);
// Disable multitexturing, using deprecated API.
bool multiTexturing = false;
int textureUnits = 0;
// Extract the image representations from the collection.
vtkGeoAlignedImageRepresentation* textureTree1 = 0;
if (imageReps->GetNumberOfItems() >= 1)
{
textureTree1 = vtkGeoAlignedImageRepresentation::SafeDownCast(
imageReps->GetItemAsObject(0));
}
vtkGeoAlignedImageRepresentation* textureTree2 = 0;
if (imageReps->GetNumberOfItems() >= 2)
{
textureTree2 = vtkGeoAlignedImageRepresentation::SafeDownCast(
imageReps->GetItemAsObject(1));
}
int visibleActors = 0;
vtkProp3DCollection* props = assembly->GetParts();
vtkDebugMacro("Number Of Props: " << props->GetNumberOfItems());
vtkSmartPointer<vtkTimerLog> timer = vtkSmartPointer<vtkTimerLog>::New();
timer->StartTimer();
// Remove actors at the beginning of the actor list until there are at most
// 100 actors.
while (props->GetNumberOfItems() > 100)
{
assembly->RemovePart(vtkActor::SafeDownCast(props->GetItemAsObject(0)));
}
// First turn off visibility of all actors
for (int p = 0; p < props->GetNumberOfItems(); ++p)
{
vtkActor* actor = vtkActor::SafeDownCast(props->GetItemAsObject(p));
actor->VisibilityOff();
}
// Use stack rather than recursion
std::stack<vtkGeoTerrainNode*> s;
s.push(this->Root);
vtkGeoTerrainNode* child = NULL;
vtkCollection* coll = NULL;
double llbounds[4];
while (!s.empty())
{
vtkGeoTerrainNode* cur = s.top();
s.pop();
if (!cur->HasData() || cur->GetModel()->GetNumberOfCells() == 0)
{
continue;
}
if (!this->NodeInViewport(cur))
{
// Totally outside, so prune node and subtree
continue;
}
// Mark this node as "visited" so it will be less likely to
// be deleted.
this->Cache->SendToFront(cur);
// Determine whether to traverse this node's children
int refine = this->EvaluateNode(cur);
child = cur->GetChild(0);
if (((!child || !child->HasData()) &&
cur->GetLevel() < this->MaxLevel &&
refine == 1) || cur->GetStatus() == vtkGeoTreeNode::PROCESSING)
{
coll = this->GeoSource->GetRequestedNodes(cur);
// Load children
if (coll != NULL && coll->GetNumberOfItems() == 4)
{
for (int c = 0; c < 4; ++c)
{
child = vtkGeoTerrainNode::SafeDownCast(coll->GetItemAsObject(c));
vtkGeoTerrainNode* oldChild = cur->GetChild(c);
if (oldChild)
{
this->Cache->RemoveNode(oldChild);
}
this->Cache->SendToFront(child);
cur->SetChild(child, c);
child->SetParent(cur);
}
cur->SetStatus(vtkGeoTreeNode::NONE);
}
else if(cur->GetStatus() == vtkGeoTreeNode::NONE)
{
cur->SetStatus(vtkGeoTreeNode::PROCESSING);
vtkGeoTerrainNode * temp = vtkGeoTerrainNode::New();
temp->DeepCopy(cur);
this->GeoSource->RequestChildren(temp);
}
if (coll)
{
coll->Delete();
}
}
if (!cur->GetChild(0) || !cur->GetChild(0)->HasData() || refine != 1)
{
// Find the best texture for this geometry
llbounds[0] = cur->GetLongitudeRange()[0];
llbounds[1] = cur->GetLongitudeRange()[1];
llbounds[2] = cur->GetLatitudeRange()[0];
llbounds[3] = cur->GetLatitudeRange()[1];
vtkGeoImageNode* textureNode1 = textureTree1->GetBestImageForBounds(llbounds);
if (!textureNode1)
{
vtkWarningMacro(<< "could not find node for bounds: "
<< llbounds[0] << ","
<< llbounds[1] << ","
<< llbounds[2] << ","
<< llbounds[3]);
}
vtkGeoImageNode* textureNode2 = 0;
if (textureTree2)
{
textureNode2 = textureTree2->GetBestImageForBounds(llbounds);
}
// See if we already have an actor for this geometry
vtkActor* existingActor = 0;
for (int p = 0; p < props->GetNumberOfItems(); ++p)
{
vtkActor* actor = vtkActor::SafeDownCast(props->GetItemAsObject(p));
bool sameTexture = false;
if (multiTexturing)
{
sameTexture = (
!textureNode1 ||
actor->GetProperty()->GetNumberOfTextures() < 1 ||
actor->GetProperty()->GetTexture(vtkProperty::VTK_TEXTURE_UNIT_0) == textureNode1->GetTexture()
) && (
!textureNode2 ||
actor->GetProperty()->GetNumberOfTextures() < 2 ||
actor->GetProperty()->GetTexture(vtkProperty::VTK_TEXTURE_UNIT_1) == textureNode2->GetTexture()
);
}
else
{
sameTexture = !textureNode1 || actor->GetTexture() == textureNode1->GetTexture();
}
if (actor && actor->GetMapper()->GetInputDataObject(0, 0) == cur->GetModel() && sameTexture)
{
existingActor = actor;
existingActor->VisibilityOn();
visibleActors++;
// Move the actor to the end of the list so it is less likely removed.
actor->Register(this);
assembly->RemovePart(actor);
assembly->AddPart(actor);
actor->Delete();
break;
}
}
if (existingActor)
{
continue;
}
// Add the data to the view
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
mapper->SetInputData(cur->GetModel());
mapper->ScalarVisibilityOff();
actor->SetMapper(mapper);
actor->SetPosition(-this->Origin[0], -this->Origin[1], -this->Origin[2] - 0.1);
visibleActors++;
if (textureNode1)
{
// Some implementations will report they support multi-texturing but have only 1
// texture unit. Seriously!!
if (multiTexturing && textureUnits > 1)
{
// Multi texturing
mapper->MapDataArrayToMultiTextureAttribute(vtkProperty::VTK_TEXTURE_UNIT_0,
"LatLong", vtkDataObject::FIELD_ASSOCIATION_POINTS);
textureNode1->GetTexture()->SetBlendingMode(vtkTexture::VTK_TEXTURE_BLENDING_MODE_REPLACE);
actor->GetProperty()->SetTexture(vtkProperty::VTK_TEXTURE_UNIT_0, textureNode1->GetTexture());
if (textureNode2)
{
mapper->MapDataArrayToMultiTextureAttribute(vtkProperty::VTK_TEXTURE_UNIT_1,
"LatLong", vtkDataObject::FIELD_ASSOCIATION_POINTS);
textureNode2->GetTexture()->SetBlendingMode(vtkTexture::VTK_TEXTURE_BLENDING_MODE_ADD);
actor->GetProperty()->SetTexture(vtkProperty::VTK_TEXTURE_UNIT_1, textureNode2->GetTexture());
}
}
else
{
if(multiTexturing)
{
textureNode1->GetTexture()->SetBlendingMode(
vtkTexture::VTK_TEXTURE_BLENDING_MODE_REPLACE);
}
// Single texturing
cur->GetModel()->GetPointData()->SetActiveTCoords("LatLong");
actor->SetTexture(textureNode1->GetTexture());
}
actor->GetProperty()->SetAmbient(1);
assembly->AddPart(actor);
}
continue;
}
// Workaround for the isse where if refinement does not happen for some reason
// then we don't see a tile as its visibility is turned off.
else
{
llbounds[0] = cur->GetLongitudeRange()[0];
llbounds[1] = cur->GetLongitudeRange()[1];
llbounds[2] = cur->GetLatitudeRange()[0];
llbounds[3] = cur->GetLatitudeRange()[1];
vtkGeoImageNode* textureNode1 = textureTree1->GetBestImageForBounds(llbounds);
vtkGeoImageNode* textureNode2 = 0;
// See if we already have an actor for this geometry
vtkActor* existingActor = 0;
for (int p = 0; p < props->GetNumberOfItems(); ++p)
{
vtkActor* actor = vtkActor::SafeDownCast(props->GetItemAsObject(p));
bool sameTexture = false;
if (multiTexturing)
{
sameTexture = (
!textureNode1 ||
actor->GetProperty()->GetNumberOfTextures() < 1 ||
actor->GetProperty()->GetTexture(vtkProperty::VTK_TEXTURE_UNIT_0) == textureNode1->GetTexture()
) && (
!textureNode2 ||
actor->GetProperty()->GetNumberOfTextures() < 2 ||
actor->GetProperty()->GetTexture(vtkProperty::VTK_TEXTURE_UNIT_1) == textureNode2->GetTexture()
);
}
else
{
sameTexture = !textureNode1 || actor->GetTexture() == textureNode1->GetTexture();
}
if (actor && actor->GetMapper()->GetInputDataObject(0, 0) == cur->GetModel() && sameTexture)
{
existingActor = actor;
existingActor->VisibilityOn();
visibleActors++;
// Move the actor to the end of the list so it is less likely removed.
actor->Register(this);
assembly->RemovePart(actor);
assembly->AddPart(actor);
actor->Delete();
break;
}
}
}
s.push(cur->GetChild(0));
s.push(cur->GetChild(1));
s.push(cur->GetChild(2));
s.push(cur->GetChild(3));
}
timer->StopTimer();
vtkDebugMacro("Visible Actors: " << visibleActors);
vtkDebugMacro("AddActors time: " << timer->GetElapsedTime());
}
//----------------------------------------------------------------------------
void vtkGeoTerrain::PrintSelf(ostream & os, vtkIndent indent)
{
this->Superclass::PrintSelf( os, indent );
os << indent << "GeoSource: " << this->GeoSource << "\n";
os << indent << "Origin: (" << this->Origin[0] << ", "
<< this->Origin[1] << ", " << this->Origin[2] << ")\n";
os << indent << "MaxLevel: " << this->MaxLevel << "\n";
this->PrintTree(os, indent, this->Root); // Root
}
//----------------------------------------------------------------------------
void vtkGeoTerrain::SaveDatabase(const char* path, int depth)
{
if (!this->Root)
{
this->Initialize();
}
std::stack< vtkSmartPointer<vtkGeoTerrainNode> > s;
s.push(this->Root);
while (!s.empty())
{
vtkSmartPointer<vtkGeoTerrainNode> node = s.top();
s.pop();
// Write out file.
vtkSmartPointer<vtkPolyData> storedData = vtkSmartPointer<vtkPolyData>::New();
storedData->ShallowCopy(node->GetModel());
vtkSmartPointer<vtkXMLPolyDataWriter> writer = vtkSmartPointer<vtkXMLPolyDataWriter>::New();
char fn[512];
sprintf(fn, "%s/tile_%d_%ld.vtp", path, node->GetLevel(), node->GetId());
writer->SetFileName(fn);
writer->SetInputData(storedData);
writer->Write();
if (node->GetLevel() == depth)
{
continue;
}
// Recurse over children.
for (int i = 0; i < 4; ++i)
{
vtkSmartPointer<vtkGeoTerrainNode> child =
vtkSmartPointer<vtkGeoTerrainNode>::New();
if (this->GeoSource->FetchChild(node, i, child))
{
s.push(child);
}
}
}
}
//----------------------------------------------------------------------------
void vtkGeoTerrain::PrintTree(ostream & os, vtkIndent indent, vtkGeoTerrainNode* parent)
{
os << indent << "Error: " << parent->GetError() << endl;
os << indent << "Level: " << parent->GetLevel() << " "
<< "Id: " << parent->GetId() << endl;
os << indent << "LatitudeRange: " << parent->GetLatitudeRange()[0]
<< "," << parent->GetLatitudeRange()[1] << endl;
os << indent << "LongitudeRange: " << parent->GetLongitudeRange()[0]
<< "," << parent->GetLongitudeRange()[1] << endl;
os << indent << "ProjectionBounds: " << parent->GetProjectionBounds()[0]
<< "," << parent->GetProjectionBounds()[1]
<< "," << parent->GetProjectionBounds()[2]
<< "," << parent->GetProjectionBounds()[3] << endl;
os << indent << "Number of cells: " << parent->GetModel()->GetNumberOfCells() << endl;
if (parent->GetChild(0) == 0)
{
return;
}
for (int i = 0; i < 4; ++i)
{
this->PrintTree(os, indent.GetNextIndent(), parent->GetChild(i));
}
}

View File

@ -0,0 +1,125 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkGeoTerrain.h
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.
-------------------------------------------------------------------------*/
// .NAME vtkGeoTerrain - A 3D terrain model for the globe.
//
// .SECTION Description
// vtkGeoTerrain contains a multi-resolution tree of geometry representing
// the globe. It uses a vtkGeoSource subclass to generate the terrain, such
// as vtkGeoGlobeSource. This source must be set before using the terrain in
// a vtkGeoView. The terrain also contains an AddActors() method which
// will update the set of actors representing the globe given the current
// camera position.
#ifndef vtkGeoTerrain_h
#define vtkGeoTerrain_h
#include "vtkGeovisCoreModule.h" // For export macro
#include "vtkObject.h"
class vtkAssembly;
class vtkCollection;
class vtkExtractSelectedFrustum;
class vtkGeoCamera;
class vtkGeoTreeNodeCache;
class vtkGeoSource;
class vtkGeoTerrainNode;
class vtkRenderer;
class VTKGEOVISCORE_EXPORT vtkGeoTerrain : public vtkObject
{
public:
static vtkGeoTerrain *New();
vtkTypeMacro(vtkGeoTerrain,vtkObject);
virtual void PrintSelf(ostream& os, vtkIndent indent);
// Description:
// The source used to obtain geometry patches.
virtual vtkGeoSource* GetSource()
{ return this->GeoSource; }
virtual void SetSource(vtkGeoSource* source);
// Description:
// Save the set of patches up to a given maximum depth.
void SaveDatabase(const char* path, int depth);
// Description:
// Update the actors in an assembly used to render the globe.
// ren is the current renderer, and imageReps holds the collection of
// vtkGeoAlignedImageRepresentations that will be blended together to
// form the image on the globe.
void AddActors(
vtkRenderer* ren,
vtkAssembly* assembly,
vtkCollection* imageReps);
// Description:
// The world-coordinate origin offset used to eliminate precision errors
// when zoomed in to a particular region of the globe.
vtkSetVector3Macro(Origin, double);
vtkGetVector3Macro(Origin, double);
// Description:
// The maximum level of the terrain tree.
vtkSetClampMacro(MaxLevel, int, 0, VTK_INT_MAX);
vtkGetMacro(MaxLevel, int);
protected:
vtkGeoTerrain();
~vtkGeoTerrain();
virtual void SetGeoSource(vtkGeoSource* source);
vtkGeoSource* GeoSource;
vtkGeoTerrainNode* Root;
vtkGeoTreeNodeCache* Cache;
// Description:
// Initialize the terrain with a new source.
void Initialize();
// Description:
// AddActors() calls this to setup parameters for evaluating nodes.
virtual void InitializeNodeAnalysis(vtkRenderer* ren);
// Description:
// AddActors() calls this to determine if a node is in the current
// viewport.
virtual bool NodeInViewport(vtkGeoTerrainNode* node);
// Description:
// AddActors() calls to to evaluate whether a node should be
// refined (1), coarsened (-1), or remain at the same level (0).
virtual int EvaluateNode(vtkGeoTerrainNode* node);
// Description:
// Print the tree of terrain nodes.
void PrintTree(ostream & os, vtkIndent indent, vtkGeoTerrainNode* node);
double Origin[3];
vtkExtractSelectedFrustum* Extractor;
virtual void SetGeoCamera(vtkGeoCamera* camera);
vtkGeoCamera* GeoCamera;
int MaxLevel;
private:
vtkGeoTerrain(const vtkGeoTerrain&); // Not implemented
void operator=(const vtkGeoTerrain&); // Not implemented
};
#endif

View File

@ -0,0 +1,112 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkGeoTerrain2D.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 "vtkGeoTerrain2D.h"
#include "vtkCamera.h"
#include "vtkGeoTerrainNode.h"
#include "vtkGeoSource.h"
#include "vtkObjectFactory.h"
#include "vtkRenderer.h"
vtkStandardNewMacro(vtkGeoTerrain2D);
//----------------------------------------------------------------------------
vtkGeoTerrain2D::vtkGeoTerrain2D()
{
this->LocationTolerance = 50.0;
this->TextureTolerance = 1.0;
this->CameraBounds[0] = 0;
this->CameraBounds[1] = 1;
this->CameraBounds[2] = 0;
this->CameraBounds[3] = 1;
this->PixelSize = 1;
}
//----------------------------------------------------------------------------
vtkGeoTerrain2D::~vtkGeoTerrain2D()
{
}
//----------------------------------------------------------------------------
void vtkGeoTerrain2D::InitializeNodeAnalysis(vtkRenderer* ren)
{
// Determine the 2D camera bounds
vtkCamera* cam = ren->GetActiveCamera();
double scale = cam->GetParallelScale();
double* pos = cam->GetPosition();
int* size = ren->GetSize();
this->PixelSize = 2.0 * scale / size[1];
this->CameraBounds[0] = pos[0] - size[0]*this->PixelSize/2.0;
this->CameraBounds[1] = pos[0] + size[0]*this->PixelSize/2.0;
this->CameraBounds[2] = pos[1] - size[1]*this->PixelSize/2.0;
this->CameraBounds[3] = pos[1] + size[1]*this->PixelSize/2.0;
}
//----------------------------------------------------------------------------
bool vtkGeoTerrain2D::NodeInViewport(vtkGeoTerrainNode* cur)
{
double bounds[4];
cur->GetProjectionBounds(bounds);
return bounds[1] > this->CameraBounds[0] && bounds[0] < this->CameraBounds[1] &&
bounds[3] > this->CameraBounds[2] && bounds[2] < this->CameraBounds[3];
}
//----------------------------------------------------------------------------
int vtkGeoTerrain2D::EvaluateNode(vtkGeoTerrainNode* cur)
{
double bounds[4];
cur->GetProjectionBounds(bounds);
// Determine the maximum allowable location error
double maxLocationError = this->LocationTolerance*this->PixelSize;
bool locationErrorOk = cur->GetError() < maxLocationError;
// Determine the maximum allowable patch size
double maxPatchSize = 300.0*this->TextureTolerance*this->PixelSize;
double patchX = bounds[1] - bounds[0];
double patchY = bounds[3] - bounds[2];
double patchSize = (patchX > patchY) ? patchX : patchY;
bool textureErrorOk = patchSize < maxPatchSize;
if (!locationErrorOk || !textureErrorOk)
{
return 1;
}
return 0;
}
//----------------------------------------------------------------------------
void vtkGeoTerrain2D::PrintSelf(ostream & os, vtkIndent indent)
{
this->Superclass::PrintSelf( os, indent );
os << indent << "LocationTolerance: " << this->LocationTolerance << "\n";
os << indent << "TextureTolerance: " << this->TextureTolerance << "\n";
}
//----------------------------------------------------------------------------
vtkAbstractTransform* vtkGeoTerrain2D::GetTransform()
{
if(this->GeoSource != NULL)
{
return this->GeoSource->GetTransform();
}
return NULL;
}

View File

@ -0,0 +1,96 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkGeoTerrain2D.h
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.
-------------------------------------------------------------------------*/
// .NAME vtkGeoTerrain2D - A 2D terrain model for the globe.
//
// .SECTION Description
// vtkGeoTerrain2D contains a multi-resolution tree of geometry representing
// the globe. It uses a vtkGeoSource subclass to generate the terrain, such
// as vtkGeoProjectionSource. This source must be set before using the
// terrain in a vtkGeoView2D. The terrain also contains an AddActors()
// method which updates the set of actors representing the globe given the
// current camera position.
#ifndef vtkGeoTerrain2D_h
#define vtkGeoTerrain2D_h
#include "vtkGeovisCoreModule.h" // For export macro
#include "vtkGeoTerrain.h"
class vtkAbstractTransform;
class vtkAssembly;
class vtkCollection;
class vtkGeoImageRepresentation;
class vtkGeoSource;
class vtkGeoTerrainNode;
class vtkRenderer;
class VTKGEOVISCORE_EXPORT vtkGeoTerrain2D : public vtkGeoTerrain
{
public:
static vtkGeoTerrain2D *New();
vtkTypeMacro(vtkGeoTerrain2D,vtkGeoTerrain);
virtual void PrintSelf(ostream& os, vtkIndent indent);
// Description:
// The maximum size of a single texel in pixels.
// Images will be refined if a texel becomes larger than the tolerance.
vtkSetMacro(TextureTolerance, double);
vtkGetMacro(TextureTolerance, double);
// Description:
// The maximum allowed deviation of geometry in pixels.
// Geometry will be refined if the deviation is larger than the tolerance.
vtkSetMacro(LocationTolerance, double);
vtkGetMacro(LocationTolerance, double);
// Description:
// Return the projection transformation used by this 2D terrain.
virtual vtkAbstractTransform* GetTransform();
protected:
vtkGeoTerrain2D();
~vtkGeoTerrain2D();
double LocationTolerance;
double TextureTolerance;
// Description:
// AddActors() calls this to setup parameters for evaluating nodes.
virtual void InitializeNodeAnalysis(vtkRenderer* ren);
// Description:
// AddActors() calls this to determine if a node is in the current
// viewport.
virtual bool NodeInViewport(vtkGeoTerrainNode* node);
// Description:
// AddActors() calls to to evaluate whether a node should be
// refined (1), coarsened (-1), or remain at the same level (0).
virtual int EvaluateNode(vtkGeoTerrainNode* node);
double CameraBounds[4];
double PixelSize;
private:
vtkGeoTerrain2D(const vtkGeoTerrain2D&); // Not implemented
void operator=(const vtkGeoTerrain2D&); // Not implemented
};
#endif

View File

@ -0,0 +1,305 @@
/*=============================================================================
Program: Visualization Toolkit
Module: vtkGeoTerrainNode.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 "vtkObjectFactory.h"
#include "vtkPolyData.h"
#include "vtkMath.h"
#include "vtkGeoMath.h"
#include "vtkGeoTerrainNode.h"
vtkStandardNewMacro(vtkGeoTerrainNode);
//----------------------------------------------------------------------------
vtkGeoTerrainNode::vtkGeoTerrainNode()
{
this->Model = vtkSmartPointer<vtkPolyData>::New();
this->BoundingSphereRadius = 0.0;
for (int idx = 0; idx < 3; ++idx)
{
this->BoundingSphereCenter[idx] = 0.0;
this->CornerNormal00[idx] = 0.0;
this->CornerNormal01[idx] = 0.0;
this->CornerNormal10[idx] = 0.0;
this->CornerNormal11[idx] = 0.0;
}
this->ProjectionBounds[0] = 0.0;
this->ProjectionBounds[1] = 0.0;
this->ProjectionBounds[2] = 0.0;
this->ProjectionBounds[3] = 0.0;
this->GraticuleLevel = 0;
this->Error = 0.0;
this->Coverage = 0.0;
}
//-----------------------------------------------------------------------------
vtkGeoTerrainNode::~vtkGeoTerrainNode()
{
}
//-----------------------------------------------------------------------------
void vtkGeoTerrainNode::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
os << indent << "BoundingSphereCenter: "
<< this->BoundingSphereCenter[0] << ", "
<< this->BoundingSphereCenter[1] << ", "
<< this->BoundingSphereCenter[2] << "\n";
os << indent << "BoundingSphereRadius: "
<< this->BoundingSphereRadius << "\n";
os << indent << "CornerNormal00: "
<< this->CornerNormal00[0] << ", "
<< this->CornerNormal00[1] << ", "
<< this->CornerNormal00[2] << "\n";
os << indent << "CornerNormal01: "
<< this->CornerNormal01[0] << ", "
<< this->CornerNormal01[1] << ", "
<< this->CornerNormal01[2] << "\n";
os << indent << "CornerNormal10: "
<< this->CornerNormal10[0] << ", "
<< this->CornerNormal10[1] << ", "
<< this->CornerNormal10[2] << "\n";
os << indent << "CornerNormal11: "
<< this->CornerNormal11[0] << ", "
<< this->CornerNormal11[1] << ", "
<< this->CornerNormal11[2] << "\n";
os << indent << "ProjectionBounds: "
<< this->ProjectionBounds[0] << ", "
<< this->ProjectionBounds[1] << ", "
<< this->ProjectionBounds[2] << ", "
<< this->ProjectionBounds[3] << "\n";
os << indent << "GraticuleLevel: " << this->GraticuleLevel << endl;
os << indent << "Error: " << this->Error << endl;
os << indent << "Coverage: " << this->Coverage << endl;
}
//-----------------------------------------------------------------------------
void vtkGeoTerrainNode::SetModel(vtkPolyData* model)
{
this->Model = model;
}
//-----------------------------------------------------------------------------
vtkPolyData* vtkGeoTerrainNode::GetModel()
{
return this->Model;
}
//-----------------------------------------------------------------------------
double vtkGeoTerrainNode::GetAltitude(double, double)
{
return 0;
}
//-----------------------------------------------------------------------------
// This might not work if Longitude range is over 180, but that is OK.
// Highest level is half the globe.
void vtkGeoTerrainNode::UpdateBoundingSphere()
{
// Compute the corners.
double* c00 = this->CornerNormal00;
double* c01 = this->CornerNormal01;
double* c10 = this->CornerNormal10;
double* c11 = this->CornerNormal11;
double longitudeLatitudeAltitude[3];
longitudeLatitudeAltitude[0] = this->LongitudeRange[0];
longitudeLatitudeAltitude[1] = this->LatitudeRange[0];
longitudeLatitudeAltitude[2]
= this->GetAltitude(this->LongitudeRange[0], this->LatitudeRange[0]);
vtkGeoMath::LongLatAltToRect(longitudeLatitudeAltitude, c00);
longitudeLatitudeAltitude[0] = this->LongitudeRange[1];
longitudeLatitudeAltitude[1] = this->LatitudeRange[0];
longitudeLatitudeAltitude[2]
= this->GetAltitude(this->LongitudeRange[1], this->LatitudeRange[0]);
vtkGeoMath::LongLatAltToRect(longitudeLatitudeAltitude, c01);
longitudeLatitudeAltitude[0] = this->LongitudeRange[0];
longitudeLatitudeAltitude[1] = this->LatitudeRange[1];
longitudeLatitudeAltitude[2]
= this->GetAltitude(this->LongitudeRange[0], this->LatitudeRange[1]);
vtkGeoMath::LongLatAltToRect(longitudeLatitudeAltitude, c10);
longitudeLatitudeAltitude[0] = this->LongitudeRange[1];
longitudeLatitudeAltitude[1] = this->LatitudeRange[1];
longitudeLatitudeAltitude[2]
= this->GetAltitude(this->LongitudeRange[1], this->LatitudeRange[1]);
vtkGeoMath::LongLatAltToRect(longitudeLatitudeAltitude, c11);
// Average the points to get a center for a bounding sphere.
this->BoundingSphereCenter[0] = 0.25 * (c00[0]+c01[0]+c10[0]+c11[0]);
this->BoundingSphereCenter[1] = 0.25 * (c00[1]+c01[1]+c10[1]+c11[1]);
this->BoundingSphereCenter[2] = 0.25 * (c00[2]+c01[2]+c10[2]+c11[2]);
double distance;
distance = vtkGeoMath::DistanceSquared(this->BoundingSphereCenter,c00);
this->BoundingSphereRadius = distance;
distance = vtkGeoMath::DistanceSquared(this->BoundingSphereCenter,c01);
if (this->BoundingSphereRadius < distance)
{
this->BoundingSphereRadius = distance;
}
distance = vtkGeoMath::DistanceSquared(this->BoundingSphereCenter,c10);
if (this->BoundingSphereRadius < distance)
{
this->BoundingSphereRadius = distance;
}
distance = vtkGeoMath::DistanceSquared(this->BoundingSphereCenter,c11);
if (this->BoundingSphereRadius < distance)
{
this->BoundingSphereRadius = distance;
}
this->BoundingSphereRadius = sqrt(this->BoundingSphereRadius);
// Change corners to normals (c00 points to normal ivar)
vtkMath::Normalize(c00);
vtkMath::Normalize(c01);
vtkMath::Normalize(c10);
vtkMath::Normalize(c11);
}
//-----------------------------------------------------------------------------
vtkGeoTerrainNode* vtkGeoTerrainNode::GetChild(int idx)
{
if (idx < 0 || idx > 3)
{
vtkErrorMacro("Index out of range.");
return 0;
}
return vtkGeoTerrainNode::SafeDownCast(this->Children[idx]);
}
//-----------------------------------------------------------------------------
vtkGeoTerrainNode* vtkGeoTerrainNode::GetParent()
{
return vtkGeoTerrainNode::SafeDownCast(this->Parent);
}
//-----------------------------------------------------------------------------
void vtkGeoTerrainNode::ShallowCopy(vtkGeoTreeNode *src)
{
vtkGeoTerrainNode *terrainNode = vtkGeoTerrainNode::SafeDownCast(src);
if(terrainNode != NULL)
{
vtkPolyData * polyData = vtkPolyData::New();
polyData->ShallowCopy(terrainNode->Model);
this->SetModel(polyData);
polyData->Delete();
polyData = NULL;
//this->Model = terrainNode->Model;
this->BoundingSphereRadius = terrainNode->BoundingSphereRadius;
this->BoundingSphereCenter[0] = terrainNode->BoundingSphereCenter[0];
this->BoundingSphereCenter[1] = terrainNode->BoundingSphereCenter[1];
this->CornerNormal00[0] = terrainNode->CornerNormal00[0];
this->CornerNormal00[1] = terrainNode->CornerNormal00[1];
this->CornerNormal00[2] = terrainNode->CornerNormal00[2];
this->CornerNormal01[0] = terrainNode->CornerNormal01[0];
this->CornerNormal01[1] = terrainNode->CornerNormal01[1];
this->CornerNormal01[2] = terrainNode->CornerNormal01[2];
this->CornerNormal10[0] = terrainNode->CornerNormal10[0];
this->CornerNormal10[1] = terrainNode->CornerNormal10[1];
this->CornerNormal10[2] = terrainNode->CornerNormal10[2];
this->CornerNormal11[0] = terrainNode->CornerNormal11[0];
this->CornerNormal11[1] = terrainNode->CornerNormal11[1];
this->CornerNormal11[2] = terrainNode->CornerNormal11[2];
this->ProjectionBounds[0] = terrainNode->ProjectionBounds[0];
this->ProjectionBounds[1] = terrainNode->ProjectionBounds[1];
this->ProjectionBounds[2] = terrainNode->ProjectionBounds[2];
this->ProjectionBounds[3] = terrainNode->ProjectionBounds[3];
this->GraticuleLevel = terrainNode->GraticuleLevel;
this->Error = terrainNode->Error;
this->Coverage = terrainNode->Coverage;
}
this->Superclass::ShallowCopy(src);
}
//-----------------------------------------------------------------------------
void vtkGeoTerrainNode::DeepCopy(vtkGeoTreeNode *src)
{
vtkGeoTerrainNode *terrainNode = vtkGeoTerrainNode::SafeDownCast(src);
if(terrainNode != NULL)
{
vtkPolyData * polyData = vtkPolyData::New();
polyData->DeepCopy(terrainNode->Model);
this->SetModel(polyData);
polyData->Delete();
polyData = NULL;
//this->Model = terrainNode->Model;
this->BoundingSphereRadius = terrainNode->BoundingSphereRadius;
this->BoundingSphereCenter[0] = terrainNode->BoundingSphereCenter[0];
this->BoundingSphereCenter[1] = terrainNode->BoundingSphereCenter[1];
this->CornerNormal00[0] = terrainNode->CornerNormal00[0];
this->CornerNormal00[1] = terrainNode->CornerNormal00[1];
this->CornerNormal00[2] = terrainNode->CornerNormal00[2];
this->CornerNormal01[0] = terrainNode->CornerNormal01[0];
this->CornerNormal01[1] = terrainNode->CornerNormal01[1];
this->CornerNormal01[2] = terrainNode->CornerNormal01[2];
this->CornerNormal10[0] = terrainNode->CornerNormal10[0];
this->CornerNormal10[1] = terrainNode->CornerNormal10[1];
this->CornerNormal10[2] = terrainNode->CornerNormal10[2];
this->CornerNormal11[0] = terrainNode->CornerNormal11[0];
this->CornerNormal11[1] = terrainNode->CornerNormal11[1];
this->CornerNormal11[2] = terrainNode->CornerNormal11[2];
this->ProjectionBounds[0] = terrainNode->ProjectionBounds[0];
this->ProjectionBounds[1] = terrainNode->ProjectionBounds[1];
this->ProjectionBounds[2] = terrainNode->ProjectionBounds[2];
this->ProjectionBounds[3] = terrainNode->ProjectionBounds[3];
this->GraticuleLevel = terrainNode->GraticuleLevel;
this->Error = terrainNode->Error;
this->Coverage = terrainNode->Coverage;
}
this->Superclass::DeepCopy(src);
}
//-----------------------------------------------------------------------------
bool vtkGeoTerrainNode::HasData()
{
return (this->Model != 0);
}
//-----------------------------------------------------------------------------
void vtkGeoTerrainNode::DeleteData()
{
this->Model = 0;
}

View File

@ -0,0 +1,139 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkGeoTerrainNode.h
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.
-------------------------------------------------------------------------*/
// .NAME vtkGeoTerrainNode -
// .SECTION Description Quadtree of poly data terrain patches.
// .SECTION See Also
#ifndef vtkGeoTerrainNode_h
#define vtkGeoTerrainNode_h
#include "vtkGeovisCoreModule.h" // For export macro
#include "vtkGeoTreeNode.h"
#include "vtkSmartPointer.h" // for SP
class vtkPolyData;
class VTKGEOVISCORE_EXPORT vtkGeoTerrainNode : public vtkGeoTreeNode
{
public:
static vtkGeoTerrainNode *New();
vtkTypeMacro(vtkGeoTerrainNode, vtkGeoTreeNode);
void PrintSelf(ostream& os, vtkIndent indent);
// Description:
// Every subclass implements these methods returning the specific type.
// This is easier than templating.
vtkGeoTerrainNode* GetChild(int idx);
vtkGeoTerrainNode* GetParent();
// Description:
// Given, a long, lat position, return altitude in meters
// relative to sea level.
double GetAltitude(double longitude, double latitude);
// Description:
// Get the terrrain model. The user has to copy the terrain
// into this object.
vtkPolyData* GetModel();
void SetModel(vtkPolyData* model);
// Description:
// Bounding sphere is precomputed for faster updates of terrain.
void UpdateBoundingSphere();
vtkGetMacro(BoundingSphereRadius, double);
vtkGetVector3Macro(BoundingSphereCenter, double);
vtkGetVector3Macro(CornerNormal00,double);
vtkGetVector3Macro(CornerNormal01,double);
vtkGetVector3Macro(CornerNormal10,double);
vtkGetVector3Macro(CornerNormal11,double);
// Description:
// For 2D projections, store the bounds of the node in projected space
// to quickly determine if a node is offscreen.
vtkGetVector4Macro(ProjectionBounds,double);
vtkSetVector4Macro(ProjectionBounds,double);
// Description:
// For 2D projections, store the granularity of the graticule in this node.
vtkGetMacro(GraticuleLevel,int);
vtkSetMacro(GraticuleLevel,int);
// Description:
// For 2D projections, store the maximum deviation of line segment centers
// from the actual projection value.
vtkGetMacro(Error,double);
vtkSetMacro(Error,double);
// Description:
// For 2D projections, store the maximum deviation of line segment centers
// from the actual projection value.
vtkGetMacro(Coverage,float);
vtkSetMacro(Coverage,float);
// Description:
// Shallow and Deep copy.
virtual void ShallowCopy(vtkGeoTreeNode *src);
virtual void DeepCopy(vtkGeoTreeNode *src);
// Description:
// Returns whether this node has valid data associated
// with it, or if it is an "empty" node.
virtual bool HasData();
// Description:
// Deletes the data associated with the node to make this
// an "empty" node. This is performed when the node has
// been unused for a certain amount of time.
virtual void DeleteData();
protected:
vtkGeoTerrainNode();
~vtkGeoTerrainNode();
//BTX
vtkSmartPointer<vtkPolyData> Model;
//ETX
double BoundingSphereRadius;
double BoundingSphereCenter[3];
// I hate having to store this, but it is the easiest
// way to determine if a node is not visible because
// it is on the other side of the earth.
double CornerNormal00[3];
double CornerNormal01[3];
double CornerNormal10[3];
double CornerNormal11[3];
double ProjectionBounds[4];
int GraticuleLevel;
double Error;
float Coverage;
private:
vtkGeoTerrainNode(const vtkGeoTerrainNode&); // Not implemented.
void operator=(const vtkGeoTerrainNode&); // Not implemented.
};
#endif

View File

@ -0,0 +1,212 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkGeoTransform.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 "vtkGeoTransform.h"
#include "vtkDoubleArray.h"
#include "vtkGeoProjection.h"
#include "vtkMath.h"
#include "vtkObjectFactory.h"
#include "vtkPoints.h"
#include "vtk_libproj4.h"
vtkStandardNewMacro(vtkGeoTransform);
vtkCxxSetObjectMacro(vtkGeoTransform, SourceProjection, vtkGeoProjection);
vtkCxxSetObjectMacro(vtkGeoTransform, DestinationProjection, vtkGeoProjection);
vtkGeoTransform::vtkGeoTransform()
{
this->SourceProjection = 0;
this->DestinationProjection = 0;
}
vtkGeoTransform::~vtkGeoTransform()
{
if ( this->SourceProjection )
{
this->SourceProjection->Delete();
}
if ( this->DestinationProjection )
{
this->DestinationProjection->Delete();
}
}
void vtkGeoTransform::PrintSelf( ostream& os, vtkIndent indent )
{
this->Superclass::PrintSelf( os, indent );
os << indent << "SourceProjection: " << this->SourceProjection << "\n";
os << indent << "DestinationProjection: " << this->DestinationProjection << "\n";
}
void vtkGeoTransform::TransformPoints( vtkPoints* srcPts, vtkPoints* dstPts )
{
if ( ! srcPts || ! dstPts )
{
return;
}
vtkDoubleArray* srcCoords = vtkDoubleArray::SafeDownCast( srcPts->GetData() );
vtkDoubleArray* dstCoords = vtkDoubleArray::SafeDownCast( dstPts->GetData() );
if ( ! srcCoords || ! dstCoords )
{ // data not in a form we can use directly anyway...
this->Superclass::TransformPoints( srcPts, dstPts );
return;
}
dstCoords->DeepCopy( srcCoords );
PROJ* src = this->SourceProjection ? this->SourceProjection->GetProjection() : 0;
PROJ* dst = this->DestinationProjection ? this->DestinationProjection->GetProjection() : 0;
if ( ! src && ! dst )
{
// we've already copied srcCoords to dstCoords and src=dst=0 implies no transform...
return;
}
if ( srcCoords->GetNumberOfComponents() < 2 )
{
vtkErrorMacro( << "Source coordinate array " << srcCoords << " only has " << srcCoords->GetNumberOfComponents()
<< " components and at least 2 are required for geographic projections." );
return;
}
this->InternalTransformPoints( dstCoords->GetPointer( 0 ), dstCoords->GetNumberOfTuples(), dstCoords->GetNumberOfComponents() );
}
void vtkGeoTransform::Inverse()
{
vtkGeoProjection* tmp = this->SourceProjection;
this->SourceProjection = this->DestinationProjection;
this->DestinationProjection = tmp;
this->Modified();
}
void vtkGeoTransform::InternalTransformPoint( const float in[3], float out[3] )
{
double ind[3];
double oud[3];
int i;
for ( i = 0; i < 3; ++ i )
ind[i] = in[i];
this->InternalTransformPoint( ind, oud );
for ( i = 0; i < 3; ++ i )
out[i] = static_cast<float>(oud[i]);
}
void vtkGeoTransform::InternalTransformPoint( const double in[3], double out[3] )
{
for ( int i = 0; i < 3; ++ i )
{
out[i] = in[i];
}
this->InternalTransformPoints( out, 1, 3 );
}
void vtkGeoTransform::InternalTransformDerivative( const float in[3], float out[3], float derivative[3][3] )
{
double ind[3];
double oud[3];
double drd[3][3];
int i;
for ( i = 0; i < 3; ++ i )
ind[i] = in[i];
this->InternalTransformDerivative( ind, oud, drd );
for ( i = 0; i < 3; ++ i )
{
out[i] = static_cast<float>(oud[i]);
for ( int j = 0; j < 3; ++ j )
{
derivative[i][j] = drd[i][j];
}
}
}
void vtkGeoTransform::InternalTransformDerivative( const double in[3], double out[3], double derivative[3][3] )
{
// FIXME: Need to use pj_factors for both source and inverted dest projection
(void) in;
(void) out;
(void) derivative;
}
vtkAbstractTransform* vtkGeoTransform::MakeTransform()
{
vtkGeoTransform* geoTrans = vtkGeoTransform::New();
return geoTrans;
}
void vtkGeoTransform::InternalTransformPoints( double* x, vtkIdType numPts, int stride )
{
PROJ* src = this->SourceProjection ? this->SourceProjection->GetProjection() : 0;
PROJ* dst = this->DestinationProjection ? this->DestinationProjection->GetProjection() : 0;
int delta = stride - 2;
PROJ_LP lp;
PROJ_XY xy;
if ( src )
{
// Convert from src system to lat/long using inverse of src transform
double* coord = x;
for ( vtkIdType i = 0; i < numPts; ++ i )
{
xy.x = coord[0]; xy.y = coord[1];
lp = proj_inv( xy, src );
coord[0] = lp.lam; coord[1] = lp.phi;
}
}
else // ! src
{
// src coords are in degrees, convert to radians
double* coord = x;
for ( vtkIdType i = 0; i < numPts; ++ i )
{
for ( int j = 0; j < 2; ++ j, ++ coord )
{
*coord = vtkMath::RadiansFromDegrees( *coord );
}
coord += delta;
}
}
if ( dst )
{
double* coord = x;
for ( vtkIdType i = 0; i < numPts; ++ i )
{
lp.lam = coord[0]; lp.phi = coord[1];
xy = proj_fwd( lp, dst );
coord[0] = xy.x; coord[1] = xy.y;
}
}
else // ! dst
{
// dst coords are in radians, convert to degrees
double* coord = x;
for ( vtkIdType i = 0; i < numPts; ++ i )
{
for ( int j = 0; j < 2; ++ j, ++ coord )
{
*coord = vtkMath::DegreesFromRadians( *coord );
}
coord += delta;
}
}
}

View File

@ -0,0 +1,90 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkGeoTransform.h
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.
-------------------------------------------------------------------------*/
// .NAME vtkGeoTransform - A transformation between two geographic coordinate systems
// .SECTION Description
// This class takes two geographic projections and transforms point
// coordinates between them.
#ifndef vtkGeoTransform_h
#define vtkGeoTransform_h
#include "vtkGeovisCoreModule.h" // For export macro
#include "vtkAbstractTransform.h"
class vtkGeoProjection;
class VTKGEOVISCORE_EXPORT vtkGeoTransform : public vtkAbstractTransform
{
public:
static vtkGeoTransform* New();
virtual void PrintSelf( ostream& os, vtkIndent indent );
vtkTypeMacro(vtkGeoTransform,vtkAbstractTransform);
// Description:
// The source geographic projection.
void SetSourceProjection(vtkGeoProjection* source);
vtkGetObjectMacro(SourceProjection,vtkGeoProjection);
// Description:
// The target geographic projection.
void SetDestinationProjection(vtkGeoProjection* dest);
vtkGetObjectMacro(DestinationProjection,vtkGeoProjection);
// Description:
// Transform many points at once.
virtual void TransformPoints( vtkPoints* src, vtkPoints* dst );
// Description:
// Invert the transformation.
virtual void Inverse();
// Description:
// This will calculate the transformation without calling Update.
// Meant for use only within other VTK classes.
virtual void InternalTransformPoint( const float in[3], float out[3] );
virtual void InternalTransformPoint( const double in[3], double out[3] );
// Description:
// This will transform a point and, at the same time, calculate a
// 3x3 Jacobian matrix that provides the partial derivatives of the
// transformation at that point. This method does not call Update.
// Meant for use only within other VTK classes.
virtual void InternalTransformDerivative( const float in[3], float out[3], float derivative[3][3] );
virtual void InternalTransformDerivative( const double in[3], double out[3], double derivative[3][3] );
// Description:
// Make another transform of the same type.
virtual vtkAbstractTransform* MakeTransform();
protected:
vtkGeoTransform();
virtual ~vtkGeoTransform();
void InternalTransformPoints( double* ptsInOut, vtkIdType numPts, int stride );
vtkGeoProjection* SourceProjection;
vtkGeoProjection* DestinationProjection;
private:
vtkGeoTransform( const vtkGeoTransform& ); // Not implemented.
void operator = ( const vtkGeoTransform& ); // Not implemented.
};
#endif // vtkGeoTransform_h

View File

@ -0,0 +1,256 @@
/*=============================================================================
Program: Visualization Toolkit
Module: vtkGeoTreeNode.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 "vtkObjectFactory.h"
#include "vtkGeoTreeNode.h"
vtkStandardNewMacro(vtkGeoTreeNode);
//----------------------------------------------------------------------------
vtkGeoTreeNode::vtkGeoTreeNode()
{
this->Level = 0;
this->Parent = 0;
this->Older = 0;
this->Newer = 0;
this->Id = 0; // make valgrind happy
this->LatitudeRange[0] = this->LatitudeRange[1] = 0.;
this->LongitudeRange[0] = this->LongitudeRange[1] = 0.;
this->Status = NONE;
}
//-----------------------------------------------------------------------------
vtkGeoTreeNode::~vtkGeoTreeNode()
{
this->SetParent(0);
}
//-----------------------------------------------------------------------------
void vtkGeoTreeNode::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
os << indent << "Level: " << this->Level << "\n";
os << indent << "Parent: " << this->Parent << "\n";
os << indent << "Older: " << this->Older << "\n";
os << indent << "Newer: " << this->Newer << "\n";
os << indent << "Id: " << this->Id << "\n";
os << indent << "LatitudeRange: [" << this->LatitudeRange[0] << "," << this->LatitudeRange[1] << "]\n";
os << indent << "LongitudeRange: [" << this->LongitudeRange[0] << "," << this->LongitudeRange[1] << "]\n";
os << indent << "Children:";
for ( int i = 0; i < 4; ++ i )
{
os << " " << this->Children[i];
}
os << "\n";
}
//-----------------------------------------------------------------------------
void vtkGeoTreeNode::SetChild(vtkGeoTreeNode* node, int idx)
{
if (idx < 0 || idx > 3)
{
vtkErrorMacro("Index out of range.");
return;
}
this->Children[idx] = node;
}
//-----------------------------------------------------------------------------
int vtkGeoTreeNode::GetWhichChildAreYou()
{
if (this->Level == 0)
{
vtkErrorMacro("Node does not have a parent.");
return 0;
}
unsigned long id = this->Id;
id = id >> (this->Level*2-1);
id = id & 3;
return id;
}
//-----------------------------------------------------------------------------
bool vtkGeoTreeNode::IsDescendantOf(vtkGeoTreeNode* elder)
{
if (elder == 0)
{
return false;
}
if (this->Level <= elder->GetLevel())
{
return false;
}
// All descendants will have the same first N bits in their Id.
int N = ((elder->GetLevel() * 2) + 1);
unsigned long mask = (1 << N) - 1;
if ((this->Id & mask) == elder->GetId())
{
return true;
}
return false;
}
//-----------------------------------------------------------------------------
int vtkGeoTreeNode::CreateChildren()
{
// Create the four children.
if (this->Children[0])
{ // This node is already has children.
return VTK_OK;
}
int childLevel = this->GetLevel()+1;
// Where the child index get coded in the node id.
unsigned long idBit0 = 0;
unsigned long idBit1 = 0;
if (childLevel <= 15)
{
idBit0 = 1 << (2*childLevel - 1);
idBit1 = 1 << (2*childLevel);
}
else
{
// if (childLevel > ((sizeof(unsigned long)*8) - 1) / 2)
// this particular message gets printed too much and clutters the console...
static bool msg_printed = false;
if (!msg_printed)
{
vtkWarningMacro("Level too high to be encoded in node id. (this warning only emitted once)");
msg_printed = true;
}
}
unsigned long id = this->GetId();
double longitudeRange[2];
double latitudeRange[2];
vtkGeoTreeNode* child;
// Child 0
this->GetLongitudeRange(longitudeRange);
this->GetLatitudeRange(latitudeRange);
double longitudeMid = 0.5 * (longitudeRange[0]+longitudeRange[1]);
double latitudeMid = 0.5 * (latitudeRange[0]+latitudeRange[1]);
// Child type is the same as parent.
child = this->NewInstance();
child->SetLevel(childLevel);
child->SetId(id);
longitudeRange[1] = longitudeMid;
child->SetLongitudeRange(longitudeRange);
latitudeRange[1] = latitudeMid;
child->SetLatitudeRange(latitudeRange);
this->SetChild(child, 0);
child->SetParent(this);
child->Delete();
// Child 1
this->GetLongitudeRange(longitudeRange);
this->GetLatitudeRange(latitudeRange);
// Child type is the same as parent.
child = this->NewInstance();
child->SetLevel(childLevel);
child->SetId(id | idBit0);
longitudeRange[0] = longitudeMid;
child->SetLongitudeRange(longitudeRange);
latitudeRange[1] = latitudeMid;
child->SetLatitudeRange(latitudeRange);
this->SetChild(child, 1);
child->SetParent(this);
child->Delete();
// Child 2
this->GetLongitudeRange(longitudeRange);
this->GetLatitudeRange(latitudeRange);
// Child type is the same as parent.
child = this->NewInstance();
child->SetLevel(childLevel);
child->SetId(id | idBit1);
longitudeRange[1] = longitudeMid;
child->SetLongitudeRange(longitudeRange);
latitudeRange[0] = latitudeMid;
child->SetLatitudeRange(latitudeRange);
this->SetChild(child, 2);
child->SetParent(this);
child->Delete();
// Child 3
this->GetLongitudeRange(longitudeRange);
this->GetLatitudeRange(latitudeRange);
// Child type is the same as parent.
child = this->NewInstance();
child->SetLevel(childLevel);
child->SetId(id | idBit1 | idBit0);
longitudeRange[0] = longitudeMid;
child->SetLongitudeRange(longitudeRange);
latitudeRange[0] = latitudeMid;
child->SetLatitudeRange(latitudeRange);
this->SetChild(child, 3);
child->SetParent(this);
child->Delete();
//cerr << "creating child with range "
// << child->GetLongitudeRange()[0] << ","
// << child->GetLongitudeRange()[1] << ","
// << child->GetLatitudeRange()[0] << ","
// << child->GetLatitudeRange()[1] << endl;
return VTK_OK;
}
vtkGeoTreeNode::NodeStatus vtkGeoTreeNode::GetStatus()
{
return this->Status;
}
void vtkGeoTreeNode::SetStatus(NodeStatus status)
{
this->Status = status;
}
void vtkGeoTreeNode::ShallowCopy(vtkGeoTreeNode *src)
{
this->Level = src->Level;
this->Id = src->Id;
this->LongitudeRange[0] = src->LongitudeRange[0];
this->LongitudeRange[1] = src->LongitudeRange[1];
this->LatitudeRange[0] = src->LatitudeRange[0];
this->LatitudeRange[1] = src->LatitudeRange[1];
this->Children[0] = src->Children[0];
this->Children[1] = src->Children[1];
this->Children[2] = src->Children[2];
this->Children[3] = src->Children[3];
this->Status = src->Status;
this->Parent = src->Parent;
}
void vtkGeoTreeNode::DeepCopy(vtkGeoTreeNode *src)
{
this->Level = src->Level;
this->Id = src->Id;
this->LongitudeRange[0] = src->LongitudeRange[0];
this->LongitudeRange[1] = src->LongitudeRange[1];
this->LatitudeRange[0] = src->LatitudeRange[0];
this->LatitudeRange[1] = src->LatitudeRange[1];
this->Children[0] = src->Children[0];
this->Children[1] = src->Children[1];
this->Children[2] = src->Children[2];
this->Children[3] = src->Children[3];
this->Status = src->Status;
this->Parent = src->Parent;
}

View File

@ -0,0 +1,176 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkGeoTreeNode.h
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.
-------------------------------------------------------------------------*/
// .NAME vtkGeoTreeNode - Stores data for a patch of the globe.
//
// .SECTION Description
// A self-referential data structure for storing geometry or imagery for
// the geospatial views. The data is organized in a quadtree. Each node
// contains a pointer to its parent and owns references to its four
// child nodes. The ID of each node is unique in its level, and encodes
// the path from the root node in its bits.
// .SECTION See Also
// vtkGeoView vtkGeoView2D vtkGeoTerrain vtkGeoAlignedImageRepresentation
#ifndef vtkGeoTreeNode_h
#define vtkGeoTreeNode_h
#include "vtkGeovisCoreModule.h" // For export macro
#include "vtkObject.h"
#include "vtkSmartPointer.h" // for SP
class vtkPolyData;
class VTKGEOVISCORE_EXPORT vtkGeoTreeNode : public vtkObject
{
public:
static vtkGeoTreeNode *New();
vtkTypeMacro(vtkGeoTreeNode, vtkObject);
void PrintSelf(ostream& os, vtkIndent indent);
// Description:
// The id uniquely specified this node.
// For this implementation I am going to store the branch path
// in the bits.
vtkSetMacro(Id,unsigned long);
vtkGetMacro(Id,unsigned long);
// Description;
// Knowing the level simplifies encoding the branch trace in the Id.
vtkSetMacro(Level, int);
vtkGetMacro(Level, int);
// Description:
// Longitude and latitude range of the terrain model.
vtkSetVector2Macro(LongitudeRange,double);
vtkGetVector2Macro(LongitudeRange,double);
vtkSetVector2Macro(LatitudeRange,double);
vtkGetVector2Macro(LatitudeRange,double);
// Description:
// Get a child of this node. If one is set, then they all should
// set. No not mix subclasses.
void SetChild(vtkGeoTreeNode* node, int idx);
// Description:
// When we merge children to a lower resolution parent, we need
// this reference. It is not referenced counted to avoid reference loops.
// A child should never exist when the parent is destructed anyway.
void SetParent(vtkGeoTreeNode* node)
{ this->Parent = node; }
// Description:
// Manage links to older and newer tree nodes.
// These are used to periodically delete unused patches.
void SetOlder(vtkGeoTreeNode* node)
{ this->Older = node; }
vtkGeoTreeNode* GetOlder()
{ return this->Older; }
void SetNewer(vtkGeoTreeNode* node)
{ this->Newer = node; }
vtkGeoTreeNode* GetNewer()
{ return this->Newer; }
// Description:
// Returns whether this node has valid data associated
// with it, or if it is an "empty" node.
virtual bool HasData()
{ return false; }
// Description:
// Deletes the data associated with the node to make this
// an "empty" node. This is performed when the node has
// been unused for a certain amount of time.
virtual void DeleteData()
{ }
// Description:
// Get this nodes child index in node's parent.
int GetWhichChildAreYou();
// Description:
// This method returns true if this node descends from the
// elder node. The decision is made from the node ids, so the nodes do
// not have to be in the same tree!
bool IsDescendantOf(vtkGeoTreeNode* elder);
// Description:
// Create children of the same type as parent.
// Id, level and Latitude-Longitude ranges are set.
// Returns VTK_ERROR if level gets too deep to create children.
int CreateChildren();
// Description:
// Get the child as a vtkGeoTreeNode.
// Subclasses also implement GetChild() which returns the child
// as the appropriate subclass type.
vtkGeoTreeNode* GetChildTreeNode(int idx)
{ return this->Children[idx]; }
// Description:
// Get the parent as a vtkGeoTreeNode.
// Subclasses also implement GetParent() which returns the parent
// as the appropriate subclass type.
vtkGeoTreeNode* GetParentTreeNode()
{ return this->Parent; }
//BTX
enum NodeStatus
{
NONE,
PROCESSING
};
NodeStatus GetStatus();
void SetStatus(NodeStatus status);
//ETX
// Description:
// Shallow and Deep copy. Deep copy performs a shallow copy
// of the Child nodes.
virtual void ShallowCopy(vtkGeoTreeNode *src);
virtual void DeepCopy(vtkGeoTreeNode *src);
protected:
vtkGeoTreeNode();
~vtkGeoTreeNode();
int Level;
unsigned long Id;
double LongitudeRange[2];
double LatitudeRange[2];
//BTX
vtkSmartPointer<vtkGeoTreeNode> Children[4];
vtkGeoTreeNode * Parent;
NodeStatus Status;
vtkGeoTreeNode* Older;
vtkGeoTreeNode* Newer;
//ETX
private:
vtkGeoTreeNode(const vtkGeoTreeNode&); // Not implemented.
void operator=(const vtkGeoTreeNode&); // Not implemented.
};
#endif

View File

@ -0,0 +1,168 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkGeoTreeNodeCache.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 "vtkGeoTreeNodeCache.h"
#include "vtkGeoTreeNode.h"
#include "vtkObjectFactory.h"
#include "vtkSmartPointer.h"
vtkStandardNewMacro(vtkGeoTreeNodeCache);
//----------------------------------------------------------------------------
vtkGeoTreeNodeCache::vtkGeoTreeNodeCache()
{
this->Oldest = 0;
this->Newest = 0;
this->Size = 0;
this->CacheMaximumLimit = 500;
this->CacheMinimumLimit = 250;
}
//----------------------------------------------------------------------------
vtkGeoTreeNodeCache::~vtkGeoTreeNodeCache()
{
// Break reference loops by explicitly setting all prev/next pointers to null.
vtkGeoTreeNode* cur;
for (cur = this->Newest; cur; cur = cur->GetOlder())
{
cur->SetOlder(0);
cur->SetNewer(0);
}
}
//----------------------------------------------------------------------------
void vtkGeoTreeNodeCache::SendToFront(vtkGeoTreeNode* node)
{
if (node == this->Newest)
{
return;
}
// Remove from the list if in the list already
this->RemoveNode(node);
// Add to the beginning of the list
if (this->Size > 0)
{
node->SetNewer(0);
node->SetOlder(this->Newest);
this->Newest->SetNewer(node);
this->Newest = node;
}
else
{
node->SetNewer(0);
node->SetOlder(0);
this->Newest = node;
this->Oldest = node;
}
this->Size++;
if (this->Size > this->CacheMaximumLimit)
{
this->TrimToCacheMinimum();
}
}
//----------------------------------------------------------------------------
void vtkGeoTreeNodeCache::TrimToCacheMinimum()
{
while (this->Size > this->CacheMinimumLimit)
{
vtkGeoTreeNode* node = this->Oldest;
node->GetNewer()->SetOlder(0);
this->Oldest = node->GetNewer();
node->SetOlder(0);
node->SetNewer(0);
// If this was the last of a set of siblings to leave the list,
// delete data from all siblings.
this->DeleteDataFromSiblings(node);
this->Size--;
}
}
//----------------------------------------------------------------------------
void vtkGeoTreeNodeCache::DeleteDataFromSiblings(vtkGeoTreeNode* node)
{
// Delete data from node or siblings if possible.
vtkGeoTreeNode* parent = node->GetParentTreeNode();
if (!parent)
{
return;
}
bool canDeleteSiblings = true;
for (int c = 0; c < 4; ++c)
{
vtkGeoTreeNode* child = parent->GetChildTreeNode(c);
if (!child || child->GetOlder() || child->GetNewer() || child == this->Newest)
{
canDeleteSiblings = false;
break;
}
}
if (canDeleteSiblings)
{
for (int c = 0; c < 4; ++c)
{
vtkGeoTreeNode* child = parent->GetChildTreeNode(c);
child->DeleteData();
}
}
}
//----------------------------------------------------------------------------
void vtkGeoTreeNodeCache::RemoveNode(vtkGeoTreeNode* node)
{
if (!node->GetNewer() && !node->GetOlder() && node != this->Newest)
{
// The node is not in the list
return;
}
if (!node->GetNewer())
{
this->Newest = node->GetOlder();
}
else
{
node->GetNewer()->SetOlder(node->GetOlder());
}
if (!node->GetOlder())
{
this->Oldest = node->GetNewer();
}
else
{
node->GetOlder()->SetNewer(node->GetNewer());
}
node->SetOlder(0);
node->SetNewer(0);
this->Size--;
}
//----------------------------------------------------------------------------
void vtkGeoTreeNodeCache::PrintSelf(ostream & os, vtkIndent indent)
{
this->Superclass::PrintSelf( os, indent );
os << indent << "CacheMinimumLimit: " << this->CacheMinimumLimit << endl;
os << indent << "CacheMaximumLimit: " << this->CacheMaximumLimit << endl;
os << indent << "Size: " << this->Size << endl;
}

View File

@ -0,0 +1,98 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkGeoTreeNodeCache.h
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.
-------------------------------------------------------------------------*/
// .NAME vtkGeoTreeNodeCache - Manages a list of vtkGeoTreeNodes.
//
// .SECTION Description
// vtkGeoTreeNodeCache keeps track of a linked list of vtkGeoTreeNodes,
// and has operations to move nodes to the front of the list and to
// delete data from the least used nodes. This is used to recover memory
// from nodes that store data that hasn't been used in a while.
#ifndef vtkGeoTreeNodeCache_h
#define vtkGeoTreeNodeCache_h
#include "vtkGeovisCoreModule.h" // For export macro
#include "vtkObject.h"
#include "vtkSmartPointer.h" // For SP ivars
class vtkGeoTreeNode;
class VTKGEOVISCORE_EXPORT vtkGeoTreeNodeCache : public vtkObject
{
public:
static vtkGeoTreeNodeCache *New();
vtkTypeMacro(vtkGeoTreeNodeCache,vtkObject);
virtual void PrintSelf(ostream& os, vtkIndent indent);
// Description:
// The size of the cache of geospatial nodes.
// When the size reaches this limit, the list of non-empty
// nodes will be shortened to CacheMinimumLimit.
vtkSetMacro(CacheMaximumLimit, int);
vtkGetMacro(CacheMaximumLimit, int);
// Description:
// The cache is reduced to this size when the maximum limit is reached.
vtkSetMacro(CacheMinimumLimit, int);
vtkGetMacro(CacheMinimumLimit, int);
// Description:
// Send a node to the front of the list.
// Perform this whenever a node is accessed, so that the most
// recently accessed nodes' data are not deleted.
void SendToFront(vtkGeoTreeNode* node);
// Description:
// Remove the node from the list.
void RemoveNode(vtkGeoTreeNode* node);
// Description:
// The current size of the list.
vtkGetMacro(Size, int);
protected:
vtkGeoTreeNodeCache();
~vtkGeoTreeNodeCache();
// Description:
// Removes data from the oldest nodes and removes them from
// the list until the list is of size CacheSize.
void TrimToCacheMinimum();
// Description:
// Checks whether a node is the last of a set of siblings
// to be removed from the list. If so, deletes data from the
// node and all siblings.
void DeleteDataFromSiblings(vtkGeoTreeNode* node);
int Size;
int CacheMinimumLimit;
int CacheMaximumLimit;
//BTX
vtkSmartPointer<vtkGeoTreeNode> Newest;
vtkSmartPointer<vtkGeoTreeNode> Oldest;
//ETX
private:
vtkGeoTreeNodeCache(const vtkGeoTreeNodeCache&); // Not implemented
void operator=(const vtkGeoTreeNodeCache&); // Not implemented
};
#endif

View File

@ -0,0 +1,389 @@
/*=========================================================================
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";
}

View File

@ -0,0 +1,155 @@
/*=========================================================================
Program: Visualization Toolkit
Module: vtkGlobeSource.h
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.
-------------------------------------------------------------------------*/
// .NAME vtkGlobeSource - Sphere patch with Lat/Long scalar array.
// .SECTION Description
// vtkGlobeSource will generate any "rectangular" patch of the globe
// given its Longitude-Latitude extent. It adds two point scalar arrays
// Longitude and Latitude to the output. These arrays can be transformed
// to generate texture coordinates for any texture map. This source is
// imperfect near the poles as implmented. It should really reduce the
// longitude resolution as the triangles become slivers.
//
// \image html vtkGlobeSourceSphericalToCartesianFigure.png
// \image latex vtkGlobeSourceSphericalToCartesianFigure.eps
#ifndef vtkGlobeSource_h
#define vtkGlobeSource_h
#include "vtkGeovisCoreModule.h" // For export macro
#include "vtkPolyDataAlgorithm.h"
class vtkCellArray;
class vtkFloatArray;
class VTKGEOVISCORE_EXPORT vtkGlobeSource : public vtkPolyDataAlgorithm
{
public:
vtkTypeMacro(vtkGlobeSource,vtkPolyDataAlgorithm);
void PrintSelf(ostream& os, vtkIndent indent);
// Description:
// This world point will be shifted to 0,0,0.
// Used to avoid picking bug caused by rendering errors with large offsets.
vtkSetVector3Macro(Origin, double);
// Description:
// Longitude Latitude clamps.
vtkSetClampMacro(StartLongitude,double,-180.0,180.0);
vtkSetClampMacro(EndLongitude,double,-180.0,180.0);
vtkSetClampMacro(StartLatitude,double,-90.0,90.0);
vtkSetClampMacro(EndLatitude,double,-90.0,90.0);
// Description:
// Set the number of points in the longitude direction (ranging from
// StartLongitude to EndLongitude).
vtkSetClampMacro(LongitudeResolution,int,3,100);
vtkGetMacro(LongitudeResolution,int);
// Description:
// Set the number of points in the latitude direction (ranging
// from StartLatitude to EndLatitude).
vtkSetClampMacro(LatitudeResolution,int,3,100);
vtkGetMacro(LatitudeResolution,int);
// Description:
// Set radius of sphere. Default is 6356750.0
vtkSetClampMacro(Radius,double,0.0,VTK_DOUBLE_MAX);
vtkGetMacro(Radius,double);
// Description:
vtkSetMacro(AutoCalculateCurtainHeight, bool);
vtkGetMacro(AutoCalculateCurtainHeight, bool);
vtkBooleanMacro(AutoCalculateCurtainHeight, bool);
// Description:
// Set/Get curtain height.
vtkSetClampMacro(CurtainHeight,double,0.0,VTK_DOUBLE_MAX);
vtkGetMacro(CurtainHeight,double);
// Description:
// Cause the sphere to be tessellated with edges along the latitude
// and longitude lines. If off, triangles are generated at non-polar
// regions, which results in edges that are not parallel to latitude and
// longitude lines. If on, quadrilaterals are generated everywhere
// except at the poles. This can be useful for generating a wireframe
// sphere with natural latitude and longitude lines.
vtkSetMacro(QuadrilateralTessellation,int);
vtkGetMacro(QuadrilateralTessellation,int);
vtkBooleanMacro(QuadrilateralTessellation,int);
// Description:
// Construct sphere with radius=0.5 and default resolution 8 in both latitude
// and longitude directions. longitude ranges from (-180,180)
// and latitude (-90,90) degrees.
static vtkGlobeSource *New();
// Description:
// Calculates the normal and point on a sphere with a specified radius
// at the spherical coordinates theta and phi.
static void ComputeGlobePoint(
double theta, double phi, double radius, double* point, double* normal = 0);
// Description:
// Calculates the spherical coordinates theta and phi based on the
// point on a sphere.
static void ComputeLatitudeLongitude(
double* x, double& theta, double& phi);
protected:
vtkGlobeSource();
~vtkGlobeSource() {}
int RequestData(
vtkInformation *,
vtkInformationVector **,
vtkInformationVector *);
void AddPoint(
double theta, double phi, double radius,
vtkPoints* newPoints, vtkFloatArray* newNormals,
vtkFloatArray* newLongitudeArray, vtkFloatArray* newLatitudeArray,
vtkDoubleArray* newLatLongArray);
double Origin[3];
double Radius;
bool AutoCalculateCurtainHeight;
double CurtainHeight;
int LongitudeResolution;
int LatitudeResolution;
double StartLongitude;
double EndLongitude;
double StartLatitude;
double EndLatitude;
int QuadrilateralTessellation;
private:
vtkGlobeSource(const vtkGlobeSource&); // Not implemented.
void operator=(const vtkGlobeSource&); // Not implemented.
};
#endif

View File

@ -0,0 +1,589 @@
%!PS-Adobe-3.0 EPSF-3.0
%%Creator: Ipelib 60032 (Ipe 6.0 preview 32)
%%CreationDate: D:20090813171853
%%LanguageLevel: 2
%%BoundingBox: 150 175 541 377
%%HiResBoundingBox: 150.155728 175.537959 540 376
%%DocumentSuppliedResources: font HTQIEW+CMR12
%%+ font FIBPZU+CMMI12
%%+ font KAYNOZ+CMSY10
%%EndComments
%%BeginProlog
%%BeginResource: procset ipe 6.0 60032
/ipe 40 dict def ipe begin
/np { newpath } def
/m { moveto } def
/l { lineto } def
/c { curveto } def
/h { closepath } def
/re { 4 2 roll moveto 1 index 0 rlineto 0 exch rlineto
neg 0 rlineto closepath } def
/d { setdash } def
/w { setlinewidth } def
/J { setlinecap } def
/j { setlinejoin } def
/cm { [ 7 1 roll ] concat } def
/q { gsave } def
/Q { grestore } def
/g { setgray } def
/G { setgray } def
/rg { setrgbcolor } def
/RG { setrgbcolor } def
/S { stroke } def
/f* { eofill } def
/f { fill } def
/ipeMakeFont {
exch findfont
dup length dict begin
{ 1 index /FID ne { def } { pop pop } ifelse } forall
/Encoding exch def
currentdict
end
definefont pop
} def
/ipeFontSize 0 def
/Tf { dup /ipeFontSize exch store selectfont } def
/Td { translate } def
/BT { gsave } def
/ET { grestore } def
/TJ { 0 0 moveto { dup type /stringtype eq
{ show } { ipeFontSize mul -0.001 mul 0 rmoveto } ifelse
} forall } def
end
%%EndResource
%%EndProlog
%%BeginSetup
ipe begin
%%BeginResource: font HTQIEW+CMR12
%!PS-AdobeFont-1.1: CMR12 1.0
%%CreationDate: 1991 Aug 20 16:38:05
% Copyright (C) 1997 American Mathematical Society. All Rights Reserved.
11 dict begin
/FontInfo 7 dict dup begin
/version (1.0) readonly def
/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def
/FullName (CMR12) readonly def
/FamilyName (Computer Modern) readonly def
/Weight (Medium) readonly def
/ItalicAngle 0 def
/isFixedPitch false def
end readonly def
/FontName /HTQIEW+CMR12 def
/PaintType 0 def
/FontType 1 def
/FontMatrix [0.001 0 0 0.001 0 0] readonly def
/Encoding 256 array
0 1 255 {1 index exch /.notdef put} for
dup 61 /equal put
dup 43 /plus put
readonly def
/FontBBox{-34 -251 988 750}readonly def
currentdict end
currentfile eexec
d9d66f633b846a97b686a97e45a3d0aa052a014267b7904eb3c0d3bd0b83d891
016ca6ca4b712adeb258faab9a130ee605e61f77fc1b738abc7c51cd46ef8171
9098d5fee67660e69a7ab91b58f29a4d79e57022f783eb0fbbb6d4f4ec35014f
d2decba99459a4c59df0c6eba150284454e707dc2100c15b76b4c19b84363758
469a6c558785b226332152109871a9883487dd7710949204ddcf837e6a8708b8
2bdbf16fbc7512faa308a093fe5cf4e9d2405b169cd5365d6eced5d768d66d6c
68618b8c482b341f8ca38e9bb9bafcfaad9c2f3fd033b62690986ed43d9c9361
3645b82392d5cae11a7cb49d7e2e82dcd485cba04c77322eb2e6a79d73dc194e
59c120a2dabb9bf72e2cf256dd6eb54eecba588101abd933b57ce8a3a0d16b28
51d7494f73096df53bdc66bbf896b587df9643317d5f610cd9088f9849126f23
dde030f7b277dd99055c8b119cae9c99158ac4e150cdfc2c66ed92ebb4cc092a
aa078ce16247a1335ad332daa950d20395a7384c33ff72eaa31a5b89766e635f
45c4c068ad7ee867398f0381b07cb94d29ff097d59ff9961d195a948e3d87c31
821e9295a56d21875b41988f7a16a1587050c3c71b4e4355bb37f255d6b237ce
96f25467f70fa19e0f85785ff49068949ccc79f2f8ae57d5f79bb9c5cf5eed5d
9857b9967d9b96cdcf73d5d65ff75afabb66734018bae264597220c89fd17379
26764a9302d078b4eb0e29178c878fd61007eea2ddb119ae88c57ecfef4b71e4
140a34951ddc3568a84cc92371a789021a103a1a347050fda6ecf7903f67d213
1d0c7c474a9053866e9c88e65e6932ba87a73686eab0019389f84d159809c498
1e7a30ed942eb211b00dbff5bcc720f4e276c3339b31b6eabbb078430e6a09bb
377d3061a20b1eb98796b8607eecbc699445eaa866c38e02df59f5edd378303a
0733b90e7835c0aaf32ba04f1566d8161ea89cd4d14ddb953f8b910bfc8a7f03
5020f55ef8fc2640adada156f6cf8f2eb6610f7ee8874a26cbe7cd154469b9f4
ed76886b3fb679ffdeb59bb6c55af7087ba48b75ee2fb374b19bcc421a963e15
fe05ecaaf9eecdf4b2715010a320102e6f8ccaa342fa11532671cccc52875960
84cc1832a068f03077baa0c4c196775201ec704b0519618eb6325c392cfdc749
16d4feea566b7f146471bd80a38772c1086962b023f9b6f5186495caa304dde8
9a81af90b29454d95f3960197b03a3c230c90fdb599f2148c652d4da3cb43695
651fd6ff092c2b139821e3a765896484539953774d852230a39ef0566729069f
1e4ad3ce2608d532f49afe71ca061ce3fb9b433fcc20350f727175025e4eae89
93edd8ea16367c252791c4798461fb8ed984eea3dddaebd66dcdfb9fa6e92168
48aa2ac824292bf50de5493cf474d61d83d4562a0554b5468d93c82188d0a0ca
93349835e4768c4cc779f697ec72a3f81c11448725996e99829afa18045b9696
19a8c734976dd45f152b6afd732a730369b76a5d12aed2c04e782aaab496fd8f
9c98efd84da41eeed255d0cd1b76320994d78f370452426a327173dcbaf1107d
ad484c91c67ff2e276d6545a4d13e1361603e791e7aee7079222c7a56736c6b8
243c52e7e218
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
cleartomark
%%EndResource
/F15 /HTQIEW+CMR12 findfont definefont pop
%%BeginResource: font FIBPZU+CMMI12
%!PS-AdobeFont-1.1: CMMI12 1.100
%%CreationDate: 1996 Jul 27 08:57:55
% Copyright (C) 1997 American Mathematical Society. All Rights Reserved.
11 dict begin
/FontInfo 7 dict dup begin
/version (1.100) readonly def
/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def
/FullName (CMMI12) readonly def
/FamilyName (Computer Modern) readonly def
/Weight (Medium) readonly def
/ItalicAngle -14.04 def
/isFixedPitch false def
end readonly def
/FontName /FIBPZU+CMMI12 def
/PaintType 0 def
/FontType 1 def
/FontMatrix [0.001 0 0 0.001 0 0] readonly def
/Encoding 256 array
0 1 255 {1 index exch /.notdef put} for
dup 99 /c put
dup 105 /i put
dup 106 /j put
dup 107 /k put
dup 110 /n put
dup 111 /o put
dup 39 /phi1 put
dup 115 /s put
dup 18 /theta put
dup 117 /u put
dup 118 /v put
readonly def
/FontBBox{-30 -250 1026 750}readonly def
currentdict end
currentfile eexec
d9d66f633b846a97b686a97e45a3d0aa0529731c99a784ccbe85b4993b2eebde
3b12d472b7cf54651ef21185116a69ab1096ed4bad2f646635e019b6417cc77b
532f85d811c70d1429a19a5307ef63eb5c5e02c89fc6c20f6d9d89e7d91fe470
b72befda23f5df76be05af4ce93137a219ed8a04a9d7d6fdf37e6b7fcde0d90b
986423e5960a5d9fbb4c956556e8df90cbfaec476fa36fd9a5c8175c9af513fe
d919c2ddd26bdc0d99398b9f4d03d6a8f05b47af95ef28a9c561dbdc98c47cf5
5250011d19e9366eb6fd153d3a100caa6212e3d5d93990737f8d326d347b7edc
4391c9df440285b8fc159d0e98d4258fc57892dcc57f7903449e07914fbe9e67
3c15c2153c061eb541f66c11e7ee77d5d77c0b11e1ac55101da976ccacab6993
eed1406fbb7ff30eac9e90b90b2af4ec7c273ca32f11a5c1426ff641b4a2fb2f
4e68635c93db835737567faf8471cbc05078dcd4e40e25a2f4e5af46c234cf59
2a1ce8f39e1ba1b2a594355637e474167ead4d97d51af0a899b44387e1fd933a
323afda6ba740534a510b4705c0a15647afbf3e53a82bf320dd96753639be49c
2f79a1988863ef977b800c9db5b42039c23eb86953713f730e03ea22ff7bb2c1
d97d33fd77b1bdcc2a60b12cf7805cfc90c5b914c0f30a673df9587f93e47cea
5932dd1930560c4f0d97547bcd805d6d854455b13a4d7382a22f562d7c55041f
0fd294bdaa1834820f894265a667e5c97d95ff152531ef97258f56374502865d
a1e7c0c5fb7c6fb7d3c43feb3431095a59fbf6f61cec6d6dee09f4eb0fd70d77
2a8b0a4984c6120293f6b947944be23259f6eb64303d627353163b6505fc8a60
00681f7a3968b6cbb49e0420a691258f5e7b07b417157803fcbe9b9fb1f80fd8
ca0bd3b53f9fd95670a878a64e913c339f38088bb76cf1458cb383805ab5359e
ba3a3537c88b7a8cab42412d8d645b9aca6d433e26192f237af00abc7bc13da3
0697fb05cc83dbca72aa53d2025675ba5e2df9e2c4a2038dcf160c2bb20b02cf
572199f77731e00587f025d73a3c33b647f7bf6664241320667428ad844c9d84
7a7747ab70245a91b895e0183954c8a93855793fe2798ee5543d775a3a54f98a
822ace46feb009049940f99d24d7050bb8b6ce2ac2990521ed35a9488016dc83
4c3f251f5a4e3ad99e4e5550830124778e065a4add58bcc72cafaed1eb8af229
119a2752aa2ad62ba6ab975e71220d5e3d23e5d9175bb3ba70303f2c006eaa33
5a906e068c3fb7cc40418179190d683917f11722a259f7809f3c7774d128b138
af76a51e2ddccc22bbfda19d9dde93f7eda19da2cef9a1a6446c0d86a6f09f1e
0563a53996afe9580c5338ec127b9d910ed59d59aaf9c9b06b8250ced51c595d
5c9c0ca1ce06feb594b08f590b1722f95f6cea4642f2409e506edbfe9aa18175
1efdc10ca164f462ca22dda16edfd6db7692a3089f75b5727d400344644d0c16
a555c50f6826750e2c929be313b1a5f23eaf1a32eca307c440566d8413d9c8e2
dd8d88efbcbe60b4a8834e49043391c768e5df27ecc9e3fd1923c32789b45410
aec18605c490a58d6ae89ed11a2258bb34cde1a6b86679411b5e93236e8b1f25
ac7ee3a0ccb8649f60957249edd95e20df0dc5bc2501ed3eba0329c8ce1ed8f9
0ab04f98850bdda7c2465106ceacd602c835e65334ddd10de0d4549f97045d45
6dd2f74184c480ee553f8d12679ffb0c149421ea5c340b791a4537ba31dc344b
32a73af45076dbbf3a1e09908054b39a83ce1449920f9a073a58ba39226c382c
f85e1de584ca3f538e63e66b4d7024b77e13b3c554678e7085865e53f74495cf
e6f84b399ed3a1a562885e3087b589cfebd8b64d26e996b2db9e6748914fcc11
e8494e53a348a3cef0d624838bc760f2d7209a14ea94c4d3f5ca0a3d748cd847
977c105f3464fccb29f5a419b4110fa1291404234f200fd82a1faf30097ffe6f
c703f882709b17fea924f1c937119f3114caa9e258ba6697bf097f96b44f575e
5c93893e3489853b86a02973b2c02070eb8dc7d4b41072a798f241e7d1afb4d3
74eea0153faa2b117b4af9457378a9e57e11cef2119b099b9205c7f313bb2507
0bdba178ed540aca63cdd24a96cf4ad464f9979cbc6c832ca868e22c6b591156
9f7b05d8474eaa4414a5ee8eee4a3d4b7c7aa93c2bc4406a877fcedf7f4ccb5d
6ac57d93901005bd719096ec280fd6f226f6065b5686599fa5f9355cf5449bbe
3e5917264d674421c92554c75de2a3f175db4decf1b973e576fcf7b168533e3b
b807cdc8657f514276c4dcd59a2267666c9d6c7a6eb88ba71453c21897a2bf9d
110ae0ba12a8ae61ec93a7131a7a0c3f83376a7aa6394f129ff88c1ff04f1b07
7b28f26a0d56a10888218e2599743602acfa879ee155ef73d2e0723769af9f47
0e3261b219b5752744eb433101d62459b2f4d6a03ac736ec056cd13c5c6a175c
f06a65f231daaa175a2d1c0cbdc941da87e278b47e2fb0d065e21963d1903f42
015889a52466981f48b427cdfbf29c6ce3a63b59819578e523e3edee69f6656d
fd9704ab6d743cb092388c4986c9d433febc675943ba152273964f1f004eba79
54c5da83db1226f0f2637d9cf6afdd6c07418cf0851a769e94f50cfab731ebd5
0c358660d94b9fecf29a4adaf7f2161b588259ef4e047353702bebe077d94758
d2a9858e0cff9b09d2342061d3e13fa6f65a52313d4c88cffd5cefdff6c3569d
967d0eb61eadf02cfa565daccc5c61bf8f31197a68314ed06c0c3e2a5151c259
b9c688af6cbb13f105cb0c9fe40737521e6d81366492cb2d4dbddd1262fd28bf
0d3d2d141884391baacf8057cb0378772fd146270016f5279ca53c740a9e0994
708e5ecff084b43e8e39d221b7a75565bd8093ce93d32a0ba6b16c6108a74975
b5a79827692b5e579696c6148f19c92d83c17db42ff16f59c603b77ba45ccf18
f97fe1101917f7fa4883f09d69d1a42337b4f506cf1be3eb6b579a3289a23bbc
171c29b47ecaa889fd869c04578604d149c471e557fa734cc5dbeb077ec68b10
2b10d27f1bf076aeb1e7b450cf5a55322f5f993ad8639d6dce3500937019de4a
66d1b221c02ea0443e16faa73ec93fd6b0c69fba07cb13ec29946f6c8a4030c8
2af43c30059981d211fb5201f9aab2503388596e99b28c97732f30534848ca3f
13c25a99075b519e95b624625f136cab80cb243d99b7678635ac351729c265a9
9b4ef6608e77041843d84468ee5e77103d74cd2dde6f8d78d566f81cdb3d437f
5324951854a8312618a4fafc01a103bfa6795c6c9110a3284a6b57d131361248
f640fedda8db865eeca8cce16821ad32270b4ca05e63f7eb81306cc5aa6d786d
21d68ec289a27e5e9c73b0e9a8156aa912c0d57b4d9cf0cb444f447eb7f6f88c
2edd6fcc17084c2fde3f132f64cec551480e7bd5b1de0eadfd27c4869704a0a1
aa437b08c202273740ee8ef47e49a3f12d0ef61174a444bfee9a836f331a3251
5aedb93e79d1ad873c4751f41aa1c3507d697ff680f0680417c89b8dc7b70360
c3ab2e406b1bc4c265fcf7c3072f1fde13a7553c671a538affa514799f51a417
1d7eb001af221d64dfab3a5e4be87b4f362428a4be522646062d6e740ecc767d
aef7e9cbf86fad1a56486d157a1236d2135560f35bf325a9415ce034264687d1
fa02409521f1dc09cd663b1c11105a948fc34bd0bc25814ef836a9e0202b1d28
bc328717ffb0145ac3f7bce5643821ddd989f2f6829ac89c3f4cefd21b7accb9
78b1909b81fac11a63ffe50e963d0c7afcee05ec6656612cff6581b9d642dd34
3a3b548c5da4276fc2b3afae46458817db0fd3e6a4c160659842a7cd8ac1aada
1b818dd17d178759a578d60e3ecf997ff3e116761860b493b943b59e1c188278
70568f5fdc60adccc1e7aa4da0f833dfcd345cc382695b926a42bc1713a8b5f9
2085e131d8d1010b2def2e0058a7aa5b8d3accf19bd00a809ee2262608063cbb
82bac765d42b006202eb4a3e9820ca990d6d365262dae1c752c162e215443746
c33272ca4b85fdb60643bd8bdc388895b38cbd1f6bf9f057a92f2245c940326c
14da93261c86a0074e82eaf5b7167da7fdd5633094152b72ce79805d098f6f36
24e062b78d7ac5f89710d12e4f4112b129d6bbbae5a72f25cd11b1b181bce560
1798d022e31d41dbf760f55cc4c7ceee01fb39ca6dd3da776664c18054764a57
379a8f1d0406d64fd4be232ce1f4c04e4a66521749ab6c7930ff1d3ad47f4a00
5e3beeae92b33baa15149b31eaefe9c26d3b8edb09399a0cab141c080468b26a
af9150aeabe48cb950086b1d1c6083b5eeba82f319684dd573f97d304805e36e
13f08e618175bbdf162da7ae2523b8671be5b52f608905e7c3edb7f3d6ac592f
f5a95e863a93bb21b784e00185dd3d2f1bd995db2f1b8667f3ef1080547a5399
d2bcb582037f40a841f2bdf2bc94da93c4e015f640bcfeecc5db70399341d337
a578dc55f4f323d28ce40924ff5e2b2424ce29ff77adaf9df8e820235706bba7
b22bf973fba3d55f58c76945bb026336dd317774c8f0e2b25dc3671318f1dfca
4fc75e409b207d1a88312b9744e532592356ee95b1f4b3ed8bd887407444926f
b31b21807ee1c08b838945f23922ebd46a70b179242cbfa1191bf082d530d7b5
ba0f501c7718a1a3401922a6593e787f303429c6785fc820bb6af272b84b1d01
4350e03ccf96778a95f703507e7e96bb911761c4c85be9918a9a0090367810b3
8b864af1e7638a4acb91f230a5bc7625e67875a8289c659a02eb86b06d9cf988
b374e6742c6331bbad207f5246f827c256ad39868492061a00b5499f46e7e33d
5e7a06c95701d2547014c257c23d211cd1fe9d40f9d24464353642c48d2d740b
4134d7094ad0908e5adc15370cd56bfc97d78920c91bc7113f0d76f58fd93a73
778dce0378c7e9ec5300496fddd6a725db863ca660c989ccc89f55012e152eec
3f66e77dcfe1c5692a596f01af15ac0c5b01a3f6eaef
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
cleartomark
%%EndResource
/F16 /FIBPZU+CMMI12 findfont definefont pop
%%BeginResource: font KAYNOZ+CMSY10
%!PS-AdobeFont-1.1: CMSY10 1.0
%%CreationDate: 1991 Aug 15 07:20:57
% Copyright (C) 1997 American Mathematical Society. All Rights Reserved.
11 dict begin
/FontInfo 7 dict dup begin
/version (1.0) readonly def
/Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def
/FullName (CMSY10) readonly def
/FamilyName (Computer Modern) readonly def
/Weight (Medium) readonly def
/ItalicAngle -14.035 def
/isFixedPitch false def
end readonly def
/FontName /KAYNOZ+CMSY10 def
/PaintType 0 def
/FontType 1 def
/FontMatrix [0.001 0 0 0.001 0 0] readonly def
/Encoding 256 array
0 1 255 {1 index exch /.notdef put} for
dup 33 /arrowright put
dup 0 /minus put
readonly def
/FontBBox{-29 -960 1116 775}readonly def
currentdict end
currentfile eexec
d9d66f633b846a97b686a97e45a3d0aa052f09f9c8ade9d907c058b87e9b6964
7d53359e51216774a4eaa1e2b58ec3176bd1184a633b951372b4198d4e8c5ef4
a213acb58aa0a658908035bf2ed8531779838a960dfe2b27ea49c37156989c85
e21b3abf72e39a89232cd9f4237fc80c9e64e8425aa3bef7ded60b122a52922a
221a37d9a807dd01161779dde7d31ff2b87f97c73d63eecdda4c49501773468a
27d1663e0b62f461f6e40a5d6676d1d12b51e641c1d4e8e2771864fc104f8cbf
5b78ec1d88228725f1c453a678f58a7e1b7bd7ca700717d288eb8da1f57c4f09
0abf1d42c5ddd0c384c7e22f8f8047be1d4c1cc8e33368fb1ac82b4e96146730
de3302b2e6b819cb6ae455b1af3187ffe8071aa57ef8a6616b9cb7941d44ec7a
71a7bb3df755178d7d2e4bb69859efa4bbc30bd6bb1531133fd4d9438ff99f09
4ecc068a324d75b5f696b8688eeb2f17e5ed34ccd6d047a4e3806d000c199d7c
515db70a8d4f6146fe068dc1e5de8bc57036431151ec603c8bcfe359bbd953ad
5f3d9983b036d9202c8fcc4fa88af960e1e49914ec809263862931db14b61eee
6d37a389b488d0b64cfb7da527aaed80494f79a073d895aa287bb47bd5246090
a76ce91680c1f37e66c3ec962b74658013610c734e3025c5d2d7009ec16a650c
e8f49b2316d5d3e736a77294ab2130fa35105f117cd86fc2b774ccc02b673605
51e29e7455202e5e99424468257e03d6cdeb79958c5bfb749ceb86fb100c4594
cdeee0c90bad06d2821bf9e33b1b9684487bd0e875d8af6957283799e9fa6654
b3e3335255313edcae8617cccc243e2cf1d679c0dfc93de5e4caeb7a95bf7e9b
becf64b0c1327fffe2a2afd5d8fe8ac7c3bacb78bf9a42a61dc05544903373f7
a39145743f80746ed965fb652c6102ca6ea518edd69c4c9e691337aa4d046057
94661c62eb63b0d70ae62f7bff92021daa44b1c34e69f98ebe838b9cc1d110f2
53
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
cleartomark
%%EndResource
/F17 /KAYNOZ+CMSY10 findfont definefont pop
%%EndSetup
0 J 1 j
q 0.4 w
192 288 m
192 224 l
S
q 192 224 m
194.333333 231 l
189.666667 231 l
h q f* Q S
Q
Q
q 0.4 w
192 288 m
256 288 l
S
q 256 288 m
249 290.333333 l
249 285.666667 l
h q f* Q S
Q
Q
q [4] 0 d
0.4 w
192 352 m
192 288 l
S
q [] 0 d
192 352 m
189.666667 345 l
194.333333 345 l
h q f* Q S
Q
Q
q 0.4 w
193.372562 289.372688 m
238.62741 334.627536 l
S
q 238.62741 334.627536 m
232.027747 331.327704 l
235.327578 328.027873 l
h q f* Q S
Q
Q
q 0.4 w
224 288 m
224 296.486928 220.628581 304.626253 214.627417 310.627417 c
S
q 214.627417 310.627417 m
217.927249 304.027754 l
221.22708 307.327585 l
h q f* Q S
Q
Q
q 1 0 0 1 264 279.538 cm 1 0 0 1 0 0 cm 0 g
0 G
1 0 0 1 0 -775.538 cm
BT
/F17 14.3462 Tf 0 786.736 Td [(\000)778(!)]TJ/F16 14.3462 Tf 3.864 -8.408 Td [(j)]TJ
0 g 0 G
ET
Q
q 1 0 0 1 184 202.328 cm 1 0 0 1 0 0 cm 0 g
0 G
1 0 0 1 0 -778.328 cm
BT
/F17 14.3462 Tf 0 786.737 Td [(\000)778(!)]TJ/F16 14.3462 Tf 4.777 -8.409 Td [(i)]TJ
0 g 0 G
ET
Q
q 1 0 0 1 176 357.132 cm 1 0 0 1 0 0 cm 0 g
0 G
1 0 0 1 0 -777.132 cm
BT
/F17 14.3462 Tf 0 778.328 Td [(\000)]TJ 11.158 8.408 Td [(\000)778(!)]TJ/F16 14.3462 Tf 4.777 -8.408 Td [(i)]TJ
0 g 0 G
ET
Q
q 1 0 0 1 244 333.556 cm 1 0 0 1 0 0 cm 0 g
0 G
1 0 0 1 0 -781.556 cm
BT
/F17 14.3462 Tf 0 786.737 Td [(\000)778(!)]TJ/F16 14.3462 Tf 3.176 -5.181 Td [(u)]TJ
0 g 0 G
ET
Q
q 1 0 0 1 152 301.77 cm 1 0 0 1 0 0 cm 0 g
0 G
1 0 0 1 0 -777.77 cm
BT
/F17 14.3462 Tf 0 786.736 Td [(\000)778(!)]TJ/F16 14.3462 Tf 3.28 -8.966 Td [(k)]TJ
0 g 0 G
ET
Q
q 0.4 w
164 288 m
164 290.209139 162.209139 292 160 292 c
157.790861 292 156 290.209139 156 288 c
156 285.790861 157.790861 284 160 284 c
162.209139 284 164 285.790861 164 288 c
h q f* Q S
Q
q 0.4 w
168.944272 288 m
168.944272 292.939785 164.939785 296.944272 160 296.944272 c
155.060215 296.944272 151.055728 292.939785 151.055728 288 c
151.055728 283.060215 155.060215 279.055728 160 279.055728 c
164.939785 279.055728 168.944272 283.060215 168.944272 288 c
h S
Q
q 1 0 0 1 228 302.037 cm 1 0 0 1 0 0 cm 0 g
0 G
1 0 0 1 0 -782.037 cm
BT
/F16 14.3462 Tf 0 782.037 Td [(\022)]TJ
0 g 0 G
ET
Q
q 0.4 w
384 288 m
448 288 l
S
q 448 288 m
441 290.333333 l
441 285.666667 l
h q f* Q S
Q
Q
q 0.4 w
384 288 m
384 352 l
S
q 384 352 m
381.666667 345 l
386.333333 345 l
h q f* Q S
Q
Q
q 0.4 w
385.178646 290.1205 m
422.821654 341.879604 l
S
q 422.821654 341.879604 m
416.8174 337.590854 l
420.591501 334.846051 l
h q f* Q S
Q
Q
q 0.4 w
416 288 m
416 297.496955 411.781664 306.503278 404.485901 312.583081 c
S
q 404.485901 312.583081 m
408.369686 306.309274 l
411.357214 309.894306 l
h q f* Q S
Q
Q
q 1 0 0 1 456 281.556 cm 1 0 0 1 0 0 cm 0 g
0 G
1 0 0 1 0 -781.556 cm
BT
/F17 14.3462 Tf 0 786.737 Td [(\000)778(!)]TJ/F16 14.3462 Tf 3.176 -5.181 Td [(u)]TJ
0 g 0 G
ET
Q
q 1 0 0 1 428 345.556 cm 1 0 0 1 0 0 cm 0 g
0 G
1 0 0 1 0 -781.556 cm
BT
/F17 14.3462 Tf 0 786.737 Td [(\000)778(!)]TJ/F16 14.3462 Tf 3.52 -5.181 Td [(v)]TJ
0 g 0 G
ET
Q
q 1 0 0 1 380 361.77 cm 1 0 0 1 0 0 cm 0 g
0 G
1 0 0 1 0 -777.77 cm
BT
/F17 14.3462 Tf 0 786.736 Td [(\000)778(!)]TJ/F16 14.3462 Tf 3.28 -8.966 Td [(k)]TJ
0 g 0 G
ET
Q
q 1 0 0 1 416 307.034 cm 1 0 0 1 0 0 cm 0 g
0 G
1 0 0 1 0 -783.034 cm
BT
/F16 14.3462 Tf 0 785.824 Td [(')]TJ
0 g 0 G
ET
Q
q 1 0 0 1 156.00002 175.537959 cm 1 0 0 1 0 0 cm 0 g
0 G
1 0 0 1 0 -775.538 cm
BT
/F17 14.3462 Tf 0 783.508 Td [(\000)778(!)]TJ/F16 14.3462 Tf 3.176 -5.18 Td [(u)]TJ/F15 14.3462 Tf 15.155 0 Td [(=)]TJ/F16 14.3462 Tf 14.911 0 Td [(cos\022)]TJ/F17 14.3462 Tf 26.352 8.408 Td [(\000)778(!)]TJ/F16 14.3462 Tf 3.864 -8.408 Td [(j)]TJ/F17 14.3462 Tf 13.395 0 Td [(\000)]TJ/F16 14.3462 Tf 14.07 0 Td [(sin\022)]TJ/F17 14.3462 Tf 26.731 8.408 Td [(\000)778(!)]TJ/F16 14.3462 Tf 4.777 -8.408 Td [(i)]TJ
0 g 0 G
ET
Q
q 1 0 0 1 352 238.981 cm 1 0 0 1 0 0 cm 0 g
0 G
1 0 0 1 0 -774.981 cm
BT
/F17 14.3462 Tf 0 782.951 Td [(\000)778(!)]TJ/F16 14.3462 Tf 3.52 -5.18 Td [(v)]TJ/F15 14.3462 Tf 14.811 0 Td [(=)]TJ/F16 14.3462 Tf 14.911 0 Td [(cos')]TJ/F17 14.3462 Tf 28.617 5.18 Td [(\000)778(!)]TJ/F16 14.3462 Tf 3.176 -5.18 Td [(u)]TJ/F15 14.3462 Tf 14.359 0 Td [(+)]TJ/F16 14.3462 Tf 14.113 0 Td [(sin')]TJ/F17 14.3462 Tf 28.996 8.966 Td [(\000)778(!)]TJ/F16 14.3462 Tf 3.28 -8.966 Td [(k)]TJ
0 g 0 G
ET
Q
showpage
%%BeginIpeXml: /FlateDecode
%GhU,<_/e6`&A@ZM)Gb8l$Y^n[E[U#!95")-]a.G"NPQ[rOJJHFHWN*`U_!W&g(&a<Hc>:;mb;CO
%`g;^%?+'4A3f=\^![9D#S?7]!MnYi_;+A^ND7t9=ka[TLr;*j8f=6)AIJsA.V9Enp2,?UQO]=.1
%\,OH]&eU8j[!9fh=]L]"7,ni\FIW+UGA*!Im*[L+=]BjanNU7oafoc&T3Oh9G(g`K?7p(.TL%/=
%2VhqRB=6X2=B4($frjTVD<e.2_aW&0cL)lS3ip-.W)bgs!**#]oV[lb:P"$NACXj+8WJ$_cn>$a
%7>!ucesU2m]3/`C34ep(Z)>+i<.'fnL\?,nQ)uQtNF>dBc']ol&Kb?]`@3(\#YF$/;'q7MnD5#n
%7LSm-UBr%O5PW^p!*iD*>&m=?B:Wc2]@H>S52*,(mXW0QWJX7F<2+0if06Dm+qK-/A,2CKaO9n'
%ZHaYQX9"NV]/$l/WmSAb\R-KG\gW\H%<'#8$6r5.Hn00WWpnmmQ_30-5MV2"Os**G+<^YE+DLP"
%;CW1G8/_^&$9\:rSrOr+.<dbk^cIid&Wsr20EX?/0N0Y10[o!d`G`^5F25!E3fMi-MI"_?9f88#
%;P72u<RCUnJKf/F.<db6LdNk'p0I3@H7HE3jkTs[;c@r,oDIZ?:.DMi/dYU\R6,Wg4ASEN)_XLd
%_qUfR#^(-J]@)6u2&M^K":eWe6Wa.#bB17=p!VB6\6srp,to[j;OTP&i'(>KK%s]anqf(`'V?:U
%Zqs'LG?41MJYjPhU<q(X8e#I1rb6hEX!<bqG*#BqBp+^#Cc3DJJI`V7M7a8+T)l3[s%`]*\Yl\@
%aUUnXqn_&o#rD(If7"m*H3<oc7/[Ro\m5')X!\bFO1D3\MPaSM5WMQbaMQM/jjILj%O[5d,G8&_
%R,aTd'NJ+JR`ImomGo]#$0^gVMV,IgS[)M9q`U>%5A.<3dn8Hd6VG)^ldNSKDp2;be[#OR+SYqp
%\1oWl9LDHr)<1N">fl^e_mX@$l$j*jSou/QE#\lGhH;2#?]hDq6i~>
%%EndIpeXml
%%Trailer
end
%%EOF

View File

@ -0,0 +1,63 @@
<ipe version="60032" creator="Ipe 6.0 preview 32">
<info created="D:20090813171535" modified="D:20090813171841" bbox="cropbox"/>
<ipestyle>
</ipestyle>
<page gridsize="4">
<layer name="alpha"/>
<view layers="alpha" active="alpha"/>
<path layer="alpha" stroke="black" pen="normal" arrow="normal">
192 288 m
192 224 l
</path>
<path stroke="black" pen="normal" arrow="normal">
192 288 m
256 288 l
</path>
<path stroke="black" dash="dashed" pen="normal" backarrow="normal">
192 352 m
192 288 l
</path>
<path stroke="black" matrix="0.707107 0.707107 -0.707107 0.707107 261.254834 -50.038672" pen="normal" arrow="normal">
192 288 m
256 288 l
</path>
<path stroke="black" pen="normal" arrow="normal">
224 288 m
32 0 0 32 192 288 214.627417 310.627417 a
</path>
<text stroke="black" pos="264 296" type="minipage" width="64" valign="top" size="Large">$\overrightarrow{j}$</text>
<text stroke="black" pos="184 216" type="minipage" width="48" valign="top" size="Large">$\overrightarrow{i}$</text>
<text stroke="black" matrix="1 0 0 1 0 -20" pos="176 392" type="minipage" width="72" valign="top" size="Large">$-\overrightarrow{i}$</text>
<text stroke="black" matrix="1 0 0 1 -12 -16" pos="256 360" type="minipage" width="64" valign="top" size="Large">$\overrightarrow{u}$</text>
<text stroke="black" matrix="1 0 0 1 88 -44" pos="64 360" type="minipage" width="48" valign="top" size="Large">$\overrightarrow{k}$</text>
<path stroke="black" fill="black" pen="normal">
4 0 0 4 160 288 e
</path>
<path stroke="black" pen="normal">
8.944272 0 0 8.944272 160 288 e
</path>
<text stroke="black" matrix="1 0 0 1 -12 -4" pos="240 316" type="minipage" width="52" valign="top" size="Large">$\theta$</text>
<path stroke="black" pen="normal" arrow="normal">
384 288 m
448 288 l
</path>
<path stroke="black" pen="normal" arrow="normal">
384 288 m
384 352 l
</path>
<path stroke="black" matrix="0.588172 0.808736 -0.808736 0.588172 392.236566 -189.82766" pen="normal" arrow="normal">
384 288 m
448 288 l
</path>
<path stroke="black" pen="normal" arrow="normal">
416 288 m
32 0 0 32 384 288 404.485901 312.583081 a
</path>
<text stroke="black" pos="456 292" type="minipage" width="44" valign="top" size="Large">$\overrightarrow{u}$</text>
<text stroke="black" matrix="1 0 0 1 -4 -4" pos="432 360" type="minipage" width="44" valign="top" size="Large">$\overrightarrow{v}$</text>
<text stroke="black" matrix="1 0 0 1 36 -20" pos="344 396" type="minipage" width="56" valign="top" size="Large">$\overrightarrow{k}$</text>
<text stroke="black" matrix="1 0 0 1 -12 -12" pos="428 328" type="minipage" width="44" valign="top" size="Large">$\varphi$</text>
<text stroke="black" matrix="-0.168324 0 0 -1.166294 177.545492 392.602527" pos="128 172" type="minipage" width="132" valign="top" size="Large">$\overrightarrow{u}=cos\theta\overrightarrow{j}-sin\theta\overrightarrow{i}$</text>
<text stroke="black" matrix="1 0 0 1 -24 60" pos="376 196" type="minipage" width="188" valign="top" size="Large">$\overrightarrow{v}=cos\varphi\overrightarrow{u}+sin\varphi\overrightarrow{k}$</text>
</page>
</ipe>

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB